summaryrefslogtreecommitdiff
path: root/libs/libcurl/src
diff options
context:
space:
mode:
Diffstat (limited to 'libs/libcurl/src')
-rw-r--r--libs/libcurl/src/CMakeLists.txt52
-rw-r--r--libs/libcurl/src/Makefile.am24
-rw-r--r--libs/libcurl/src/Makefile.in1364
-rw-r--r--libs/libcurl/src/Makefile.inc71
-rw-r--r--libs/libcurl/src/altsvc.c138
-rw-r--r--libs/libcurl/src/altsvc.h4
-rw-r--r--libs/libcurl/src/asyn-ares.c669
-rw-r--r--libs/libcurl/src/asyn-base.c196
-rw-r--r--libs/libcurl/src/asyn-thrdd.c761
-rw-r--r--libs/libcurl/src/asyn-thread.c768
-rw-r--r--libs/libcurl/src/asyn.h321
-rw-r--r--libs/libcurl/src/cf-h1-proxy.c40
-rw-r--r--libs/libcurl/src/cf-h2-proxy.c2
-rw-r--r--libs/libcurl/src/cf-haproxy.c26
-rw-r--r--libs/libcurl/src/cf-https-connect.c56
-rw-r--r--libs/libcurl/src/cf-https-connect.h5
-rw-r--r--libs/libcurl/src/cf-socket.c65
-rw-r--r--libs/libcurl/src/cf-socket.h2
-rw-r--r--libs/libcurl/src/cfilters.c11
-rw-r--r--libs/libcurl/src/cfilters.h2
-rw-r--r--libs/libcurl/src/config-win32.h7
-rw-r--r--libs/libcurl/src/conncache.c106
-rw-r--r--libs/libcurl/src/conncache.h12
-rw-r--r--libs/libcurl/src/connect.c117
-rw-r--r--libs/libcurl/src/connect.h7
-rw-r--r--libs/libcurl/src/content_encoding.c15
-rw-r--r--libs/libcurl/src/cookie.c93
-rw-r--r--libs/libcurl/src/cshutdn.c47
-rw-r--r--libs/libcurl/src/cshutdn.h8
-rw-r--r--libs/libcurl/src/curl_addrinfo.c28
-rw-r--r--libs/libcurl/src/curl_config.h.cmake19
-rw-r--r--libs/libcurl/src/curl_config.h.in30
-rw-r--r--libs/libcurl/src/curl_get_line.c10
-rw-r--r--libs/libcurl/src/curl_get_line.h8
-rw-r--r--libs/libcurl/src/curl_krb5.h2
-rw-r--r--libs/libcurl/src/curl_ntlm_core.c2
-rw-r--r--libs/libcurl/src/curl_printf.h24
-rw-r--r--libs/libcurl/src/curl_range.c8
-rw-r--r--libs/libcurl/src/curl_rtmp.c52
-rw-r--r--libs/libcurl/src/curl_sasl.c107
-rw-r--r--libs/libcurl/src/curl_sasl.h2
-rw-r--r--libs/libcurl/src/curl_setup.h24
-rw-r--r--libs/libcurl/src/curl_sha512_256.c2
-rw-r--r--libs/libcurl/src/curl_sspi.c6
-rw-r--r--libs/libcurl/src/curl_threads.c23
-rw-r--r--libs/libcurl/src/curl_threads.h2
-rw-r--r--libs/libcurl/src/curl_trc.c26
-rw-r--r--libs/libcurl/src/curlx/base64.c (renamed from libs/libcurl/src/base64.c)58
-rw-r--r--libs/libcurl/src/curlx/base64.h (renamed from libs/libcurl/src/curl_base64.h)21
-rw-r--r--libs/libcurl/src/curlx/curlx.h (renamed from libs/libcurl/src/curlx.h)25
-rw-r--r--libs/libcurl/src/curlx/dynbuf.c (renamed from libs/libcurl/src/dynbuf.c)48
-rw-r--r--libs/libcurl/src/curlx/dynbuf.h (renamed from libs/libcurl/src/dynbuf.h)49
-rw-r--r--libs/libcurl/src/curlx/inet_pton.c (renamed from libs/libcurl/src/inet_pton.c)25
-rw-r--r--libs/libcurl/src/curlx/inet_pton.h (renamed from libs/libcurl/src/inet_pton.h)2
-rw-r--r--libs/libcurl/src/curlx/multibyte.c (renamed from libs/libcurl/src/curl_multibyte.c)48
-rw-r--r--libs/libcurl/src/curlx/multibyte.h (renamed from libs/libcurl/src/curl_multibyte.h)11
-rw-r--r--libs/libcurl/src/curlx/nonblock.c (renamed from libs/libcurl/src/nonblock.c)2
-rw-r--r--libs/libcurl/src/curlx/nonblock.h (renamed from libs/libcurl/src/nonblock.h)0
-rw-r--r--libs/libcurl/src/curlx/strparse.c (renamed from libs/libcurl/src/strparse.c)95
-rw-r--r--libs/libcurl/src/curlx/strparse.h (renamed from libs/libcurl/src/strparse.h)55
-rw-r--r--libs/libcurl/src/curlx/timediff.c (renamed from libs/libcurl/src/timediff.c)0
-rw-r--r--libs/libcurl/src/curlx/timediff.h (renamed from libs/libcurl/src/timediff.h)2
-rw-r--r--libs/libcurl/src/curlx/timeval.c (renamed from libs/libcurl/src/timeval.c)42
-rw-r--r--libs/libcurl/src/curlx/timeval.h (renamed from libs/libcurl/src/timeval.h)27
-rw-r--r--libs/libcurl/src/curlx/version_win32.c (renamed from libs/libcurl/src/version_win32.c)8
-rw-r--r--libs/libcurl/src/curlx/version_win32.h (renamed from libs/libcurl/src/version_win32.h)2
-rw-r--r--libs/libcurl/src/curlx/warnless.c (renamed from libs/libcurl/src/warnless.c)4
-rw-r--r--libs/libcurl/src/curlx/warnless.h (renamed from libs/libcurl/src/warnless.h)2
-rw-r--r--libs/libcurl/src/curlx/winapi.c135
-rw-r--r--libs/libcurl/src/curlx/winapi.h33
-rw-r--r--libs/libcurl/src/cw-out.c27
-rw-r--r--libs/libcurl/src/cw-out.h2
-rw-r--r--libs/libcurl/src/cw-pause.c2
-rw-r--r--libs/libcurl/src/cw-pause.h2
-rw-r--r--libs/libcurl/src/dict.c17
-rw-r--r--libs/libcurl/src/doh.c405
-rw-r--r--libs/libcurl/src/doh.h39
-rw-r--r--libs/libcurl/src/dynhds.c7
-rw-r--r--libs/libcurl/src/dynhds.h6
-rw-r--r--libs/libcurl/src/easy.c119
-rw-r--r--libs/libcurl/src/easygetopt.c4
-rw-r--r--libs/libcurl/src/easyoptions.c6
-rw-r--r--libs/libcurl/src/easyoptions.h2
-rw-r--r--libs/libcurl/src/escape.c51
-rw-r--r--libs/libcurl/src/escape.h4
-rw-r--r--libs/libcurl/src/fake_addrinfo.c210
-rw-r--r--libs/libcurl/src/fake_addrinfo.h54
-rw-r--r--libs/libcurl/src/file.c69
-rw-r--r--libs/libcurl/src/file.h11
-rw-r--r--libs/libcurl/src/fileinfo.c2
-rw-r--r--libs/libcurl/src/fileinfo.h2
-rw-r--r--libs/libcurl/src/fopen.c8
-rw-r--r--libs/libcurl/src/formdata.c642
-rw-r--r--libs/libcurl/src/formdata.h10
-rw-r--r--libs/libcurl/src/ftp.c902
-rw-r--r--libs/libcurl/src/ftp.h8
-rw-r--r--libs/libcurl/src/ftplistparser.c1182
-rw-r--r--libs/libcurl/src/getinfo.c18
-rw-r--r--libs/libcurl/src/gopher.c2
-rw-r--r--libs/libcurl/src/hash.c2
-rw-r--r--libs/libcurl/src/hash.h2
-rw-r--r--libs/libcurl/src/headers.c11
-rw-r--r--libs/libcurl/src/hmac.c2
-rw-r--r--libs/libcurl/src/hostasyn.c121
-rw-r--r--libs/libcurl/src/hostip.c855
-rw-r--r--libs/libcurl/src/hostip.h174
-rw-r--r--libs/libcurl/src/hostip4.c26
-rw-r--r--libs/libcurl/src/hostip6.c28
-rw-r--r--libs/libcurl/src/hostsyn.c104
-rw-r--r--libs/libcurl/src/hsts.c50
-rw-r--r--libs/libcurl/src/hsts.h2
-rw-r--r--libs/libcurl/src/http.c367
-rw-r--r--libs/libcurl/src/http.h4
-rw-r--r--libs/libcurl/src/http1.c35
-rw-r--r--libs/libcurl/src/http1.h2
-rw-r--r--libs/libcurl/src/http2.c134
-rw-r--r--libs/libcurl/src/http_aws_sigv4.c604
-rw-r--r--libs/libcurl/src/http_aws_sigv4.h10
-rw-r--r--libs/libcurl/src/http_chunks.c27
-rw-r--r--libs/libcurl/src/http_chunks.h2
-rw-r--r--libs/libcurl/src/http_digest.c4
-rw-r--r--libs/libcurl/src/http_negotiate.c10
-rw-r--r--libs/libcurl/src/http_ntlm.c14
-rw-r--r--libs/libcurl/src/http_proxy.c8
-rw-r--r--libs/libcurl/src/httpsrr.c95
-rw-r--r--libs/libcurl/src/httpsrr.h13
-rw-r--r--libs/libcurl/src/idn.c4
-rw-r--r--libs/libcurl/src/if2ip.c8
-rw-r--r--libs/libcurl/src/imap.c682
-rw-r--r--libs/libcurl/src/imap.h60
-rw-r--r--libs/libcurl/src/inet_ntop.c2
-rw-r--r--libs/libcurl/src/inet_ntop.h12
-rw-r--r--libs/libcurl/src/krb5.c50
-rw-r--r--libs/libcurl/src/ldap.c16
-rw-r--r--libs/libcurl/src/md4.c2
-rw-r--r--libs/libcurl/src/md5.c2
-rw-r--r--libs/libcurl/src/memdebug.c18
-rw-r--r--libs/libcurl/src/memdebug.h10
-rw-r--r--libs/libcurl/src/mime.c33
-rw-r--r--libs/libcurl/src/mprintf.c732
-rw-r--r--libs/libcurl/src/mqtt.c258
-rw-r--r--libs/libcurl/src/mqtt.h30
-rw-r--r--libs/libcurl/src/multi.c678
-rw-r--r--libs/libcurl/src/multi_ev.c164
-rw-r--r--libs/libcurl/src/multi_ev.h11
-rw-r--r--libs/libcurl/src/multihandle.h25
-rw-r--r--libs/libcurl/src/multiif.h13
-rw-r--r--libs/libcurl/src/netrc.c39
-rw-r--r--libs/libcurl/src/netrc.h2
-rw-r--r--libs/libcurl/src/noproxy.c8
-rw-r--r--libs/libcurl/src/openldap.c319
-rw-r--r--libs/libcurl/src/optiontable.pl4
-rw-r--r--libs/libcurl/src/parsedate.c8
-rw-r--r--libs/libcurl/src/pingpong.c52
-rw-r--r--libs/libcurl/src/pingpong.h12
-rw-r--r--libs/libcurl/src/pop3.c370
-rw-r--r--libs/libcurl/src/pop3.h63
-rw-r--r--libs/libcurl/src/progress.c84
-rw-r--r--libs/libcurl/src/progress.h7
-rw-r--r--libs/libcurl/src/psl.c2
-rw-r--r--libs/libcurl/src/psl.h2
-rw-r--r--libs/libcurl/src/rand.c13
-rw-r--r--libs/libcurl/src/rename.c8
-rw-r--r--libs/libcurl/src/request.c22
-rw-r--r--libs/libcurl/src/request.h21
-rw-r--r--libs/libcurl/src/rtsp.c248
-rw-r--r--libs/libcurl/src/rtsp.h29
-rw-r--r--libs/libcurl/src/select.c8
-rw-r--r--libs/libcurl/src/sendf.c2
-rw-r--r--libs/libcurl/src/setopt.c347
-rw-r--r--libs/libcurl/src/sha256.c2
-rw-r--r--libs/libcurl/src/share.c10
-rw-r--r--libs/libcurl/src/share.h2
-rw-r--r--libs/libcurl/src/sigpipe.h2
-rw-r--r--libs/libcurl/src/smb.c381
-rw-r--r--libs/libcurl/src/smb.h24
-rw-r--r--libs/libcurl/src/smtp.c515
-rw-r--r--libs/libcurl/src/smtp.h54
-rw-r--r--libs/libcurl/src/socketpair.c23
-rw-r--r--libs/libcurl/src/socketpair.h6
-rw-r--r--libs/libcurl/src/socks.c67
-rw-r--r--libs/libcurl/src/socks_gssapi.c17
-rw-r--r--libs/libcurl/src/socks_sspi.c6
-rw-r--r--libs/libcurl/src/speedcheck.c2
-rw-r--r--libs/libcurl/src/speedcheck.h2
-rw-r--r--libs/libcurl/src/splay.c4
-rw-r--r--libs/libcurl/src/splay.h2
-rw-r--r--libs/libcurl/src/strerror.c130
-rw-r--r--libs/libcurl/src/strerror.h3
-rw-r--r--libs/libcurl/src/system_win32.c7
-rw-r--r--libs/libcurl/src/telnet.c202
-rw-r--r--libs/libcurl/src/tftp.c114
-rw-r--r--libs/libcurl/src/transfer.c4
-rw-r--r--libs/libcurl/src/uint-bset.c238
-rw-r--r--libs/libcurl/src/uint-bset.h114
-rw-r--r--libs/libcurl/src/uint-hash.c (renamed from libs/libcurl/src/hash_offt.c)122
-rw-r--r--libs/libcurl/src/uint-hash.h (renamed from libs/libcurl/src/hash_offt.h)49
-rw-r--r--libs/libcurl/src/uint-spbset.c273
-rw-r--r--libs/libcurl/src/uint-spbset.h99
-rw-r--r--libs/libcurl/src/uint-table.c214
-rw-r--r--libs/libcurl/src/uint-table.h101
-rw-r--r--libs/libcurl/src/url.c757
-rw-r--r--libs/libcurl/src/url.h23
-rw-r--r--libs/libcurl/src/urlapi-int.h2
-rw-r--r--libs/libcurl/src/urlapi.c367
-rw-r--r--libs/libcurl/src/urldata.h155
-rw-r--r--libs/libcurl/src/vauth/cleartext.c16
-rw-r--r--libs/libcurl/src/vauth/cram.c18
-rw-r--r--libs/libcurl/src/vauth/digest.c56
-rw-r--r--libs/libcurl/src/vauth/digest_sspi.c24
-rw-r--r--libs/libcurl/src/vauth/gsasl.c14
-rw-r--r--libs/libcurl/src/vauth/krb5_gssapi.c18
-rw-r--r--libs/libcurl/src/vauth/krb5_sspi.c16
-rw-r--r--libs/libcurl/src/vauth/ntlm.c34
-rw-r--r--libs/libcurl/src/vauth/ntlm_sspi.c20
-rw-r--r--libs/libcurl/src/vauth/oauth2.c14
-rw-r--r--libs/libcurl/src/vauth/spnego_gssapi.c34
-rw-r--r--libs/libcurl/src/vauth/spnego_sspi.c28
-rw-r--r--libs/libcurl/src/vauth/vauth.c14
-rw-r--r--libs/libcurl/src/vauth/vauth.h6
-rw-r--r--libs/libcurl/src/vquic/curl_msh3.c116
-rw-r--r--libs/libcurl/src/vquic/curl_msh3.h2
-rw-r--r--libs/libcurl/src/vquic/curl_ngtcp2.c259
-rw-r--r--libs/libcurl/src/vquic/curl_ngtcp2.h7
-rw-r--r--libs/libcurl/src/vquic/curl_osslq.c137
-rw-r--r--libs/libcurl/src/vquic/curl_osslq.h4
-rw-r--r--libs/libcurl/src/vquic/curl_quiche.c142
-rw-r--r--libs/libcurl/src/vquic/curl_quiche.h2
-rw-r--r--libs/libcurl/src/vquic/vquic-tls.c44
-rw-r--r--libs/libcurl/src/vquic/vquic-tls.h12
-rw-r--r--libs/libcurl/src/vquic/vquic.c71
-rw-r--r--libs/libcurl/src/vquic/vquic.h5
-rw-r--r--libs/libcurl/src/vquic/vquic_int.h9
-rw-r--r--libs/libcurl/src/vssh/curl_path.c42
-rw-r--r--libs/libcurl/src/vssh/curl_path.h4
-rw-r--r--libs/libcurl/src/vssh/libssh.c1512
-rw-r--r--libs/libcurl/src/vssh/libssh2.c2608
-rw-r--r--libs/libcurl/src/vssh/ssh.h16
-rw-r--r--libs/libcurl/src/vssh/wolfssh.c226
-rw-r--r--libs/libcurl/src/vtls/bearssl.c20
-rw-r--r--libs/libcurl/src/vtls/bearssl.h2
-rw-r--r--libs/libcurl/src/vtls/cipher_suite.c6
-rw-r--r--libs/libcurl/src/vtls/cipher_suite.h2
-rw-r--r--libs/libcurl/src/vtls/gtls.c56
-rw-r--r--libs/libcurl/src/vtls/gtls.h4
-rw-r--r--libs/libcurl/src/vtls/hostcheck.c13
-rw-r--r--libs/libcurl/src/vtls/keylog.c22
-rw-r--r--libs/libcurl/src/vtls/keylog.h2
-rw-r--r--libs/libcurl/src/vtls/mbedtls.c46
-rw-r--r--libs/libcurl/src/vtls/mbedtls.h2
-rw-r--r--libs/libcurl/src/vtls/mbedtls_threadlock.c8
-rw-r--r--libs/libcurl/src/vtls/mbedtls_threadlock.h2
-rw-r--r--libs/libcurl/src/vtls/openssl.c917
-rw-r--r--libs/libcurl/src/vtls/openssl.h4
-rw-r--r--libs/libcurl/src/vtls/rustls.c53
-rw-r--r--libs/libcurl/src/vtls/rustls.h2
-rw-r--r--libs/libcurl/src/vtls/schannel.c57
-rw-r--r--libs/libcurl/src/vtls/schannel.h8
-rw-r--r--libs/libcurl/src/vtls/schannel_int.h14
-rw-r--r--libs/libcurl/src/vtls/schannel_verify.c41
-rw-r--r--libs/libcurl/src/vtls/sectransp.c58
-rw-r--r--libs/libcurl/src/vtls/sectransp.h2
-rw-r--r--libs/libcurl/src/vtls/vtls.c100
-rw-r--r--libs/libcurl/src/vtls/vtls.h5
-rw-r--r--libs/libcurl/src/vtls/vtls_int.h6
-rw-r--r--libs/libcurl/src/vtls/vtls_scache.c112
-rw-r--r--libs/libcurl/src/vtls/vtls_scache.h6
-rw-r--r--libs/libcurl/src/vtls/vtls_spack.c24
-rw-r--r--libs/libcurl/src/vtls/vtls_spack.h2
-rw-r--r--libs/libcurl/src/vtls/wolfssl.c90
-rw-r--r--libs/libcurl/src/vtls/wolfssl.h13
-rw-r--r--libs/libcurl/src/vtls/x509asn1.c140
-rw-r--r--libs/libcurl/src/vtls/x509asn1.h8
-rw-r--r--libs/libcurl/src/ws.c143
-rw-r--r--libs/libcurl/src/ws.h43
275 files changed, 16271 insertions, 12442 deletions
diff --git a/libs/libcurl/src/CMakeLists.txt b/libs/libcurl/src/CMakeLists.txt
index 8dd4deadfa..83af0375c7 100644
--- a/libs/libcurl/src/CMakeLists.txt
+++ b/libs/libcurl/src/CMakeLists.txt
@@ -21,8 +21,9 @@
# SPDX-License-Identifier: curl
#
###########################################################################
-set(LIB_NAME "libcurl")
-set(LIBCURL_OUTPUT_NAME "libcurl" CACHE STRING "Basename of the curl library")
+
+set(LIBCURL_OUTPUT_NAME "${LIB_NAME}" CACHE STRING "Basename of the curl library")
+
set_property(DIRECTORY APPEND PROPERTY COMPILE_DEFINITIONS "BUILDING_LIBCURL")
set_property(DIRECTORY APPEND PROPERTY COMPILE_DEFINITIONS "${CURL_DEBUG_MACROS}")
@@ -36,10 +37,10 @@ list(APPEND HHEADERS "${CMAKE_CURRENT_BINARY_DIR}/curl_config.h")
# The rest of the build
-include_directories(
- "${PROJECT_BINARY_DIR}/lib" # for "curl_config.h"
- "${PROJECT_SOURCE_DIR}/lib" # for "curl_setup.h"
+set_property(DIRECTORY APPEND PROPERTY INCLUDE_DIRECTORIES
+ "${PROJECT_BINARY_DIR}/lib" # for "curl_config.h"
)
+
if(USE_ARES)
include_directories(SYSTEM ${CARES_INCLUDE_DIRS})
endif()
@@ -51,7 +52,7 @@ if(CURL_BUILD_TESTING)
EXCLUDE_FROM_ALL
${HHEADERS} ${CSOURCES}
)
- target_compile_definitions(curlu PUBLIC "UNITTESTS" "CURL_STATICLIB")
+ target_compile_definitions(curlu PUBLIC "CURL_STATICLIB" "UNITTESTS")
target_link_libraries(curlu PRIVATE ${CURL_LIBS})
# There is plenty of parallelism when building the testdeps target.
# Override the curlu batch size with the maximum to optimize performance.
@@ -59,9 +60,9 @@ if(CURL_BUILD_TESTING)
endif()
if(ENABLE_CURLDEBUG)
- # We must compile these sources separately to avoid memdebug.h redefinitions
- # applying to them.
- set_source_files_properties("memdebug.c" "curl_multibyte.c" PROPERTIES SKIP_UNITY_BUILD_INCLUSION ON)
+ # We must compile this source separately to avoid memdebug.h redefinitions
+ # applying to it.
+ set_source_files_properties("memdebug.c" PROPERTIES SKIP_UNITY_BUILD_INCLUSION ON)
endif()
## Library definition
@@ -104,7 +105,7 @@ if(NOT DEFINED SHARE_LIB_OBJECT)
endif()
endif()
-if(SHARE_LIB_OBJECT AND NOT CMAKE_VERSION VERSION_LESS 3.12)
+if(SHARE_LIB_OBJECT AND CMAKE_VERSION VERSION_GREATER_EQUAL 3.12)
set(LIB_OBJECT "libcurl_object")
add_library(${LIB_OBJECT} OBJECT ${HHEADERS} ${CSOURCES}) # Requires CMake 3.12
if(WIN32)
@@ -122,7 +123,13 @@ if(SHARE_LIB_OBJECT AND NOT CMAKE_VERSION VERSION_LESS 3.12)
set_property(TARGET ${LIB_OBJECT} APPEND PROPERTY COMPILE_DEFINITIONS "CURL_HIDDEN_SYMBOLS")
endif()
if(CURL_HAS_LTO)
- set_target_properties(${LIB_OBJECT} PROPERTIES INTERPROCEDURAL_OPTIMIZATION TRUE)
+ if(CMAKE_CONFIGURATION_TYPES)
+ set_target_properties(${LIB_OBJECT} PROPERTIES
+ INTERPROCEDURAL_OPTIMIZATION_RELEASE TRUE
+ INTERPROCEDURAL_OPTIMIZATION_RELWITHDEBINFO TRUE)
+ else()
+ set_target_properties(${LIB_OBJECT} PROPERTIES INTERPROCEDURAL_OPTIMIZATION TRUE)
+ endif()
endif()
target_include_directories(${LIB_OBJECT} INTERFACE
@@ -154,7 +161,13 @@ if(BUILD_STATIC_LIBS)
set_property(TARGET ${LIB_STATIC} APPEND PROPERTY COMPILE_DEFINITIONS "CURL_HIDDEN_SYMBOLS")
endif()
if(CURL_HAS_LTO)
- set_target_properties(${LIB_STATIC} PROPERTIES INTERPROCEDURAL_OPTIMIZATION TRUE)
+ if(CMAKE_CONFIGURATION_TYPES)
+ set_target_properties(${LIB_OBJECT} PROPERTIES
+ INTERPROCEDURAL_OPTIMIZATION_RELEASE TRUE
+ INTERPROCEDURAL_OPTIMIZATION_RELWITHDEBINFO TRUE)
+ else()
+ set_target_properties(${LIB_OBJECT} PROPERTIES INTERPROCEDURAL_OPTIMIZATION TRUE)
+ endif()
endif()
target_include_directories(${LIB_STATIC} INTERFACE
@@ -191,7 +204,13 @@ if(BUILD_SHARED_LIBS)
set_property(TARGET ${LIB_SHARED} APPEND PROPERTY COMPILE_DEFINITIONS "CURL_HIDDEN_SYMBOLS")
endif()
if(CURL_HAS_LTO)
- set_target_properties(${LIB_SHARED} PROPERTIES INTERPROCEDURAL_OPTIMIZATION TRUE)
+ if(CMAKE_CONFIGURATION_TYPES)
+ set_target_properties(${LIB_OBJECT} PROPERTIES
+ INTERPROCEDURAL_OPTIMIZATION_RELEASE TRUE
+ INTERPROCEDURAL_OPTIMIZATION_RELWITHDEBINFO TRUE)
+ else()
+ set_target_properties(${LIB_OBJECT} PROPERTIES INTERPROCEDURAL_OPTIMIZATION TRUE)
+ endif()
endif()
target_include_directories(${LIB_SHARED} INTERFACE
@@ -267,8 +286,11 @@ if(BUILD_SHARED_LIBS)
set(CMAKE_REQUIRED_LINK_OPTIONS "-Wl,--version-script=${CMAKE_CURRENT_BINARY_DIR}/libcurl.vers")
check_c_source_compiles("int main(void) { return 0; }" HAVE_VERSIONED_SYMBOLS)
if(HAVE_VERSIONED_SYMBOLS)
- # Superseded by LINK_OPTIONS in CMake 3.13 and later.
- set_target_properties(${LIB_SHARED} PROPERTIES LINK_FLAGS "${CMAKE_REQUIRED_LINK_OPTIONS}")
+ if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.13)
+ set_target_properties(${LIB_SHARED} PROPERTIES LINK_OPTIONS "${CMAKE_REQUIRED_LINK_OPTIONS}")
+ else()
+ set_target_properties(${LIB_SHARED} PROPERTIES LINK_FLAGS "${CMAKE_REQUIRED_LINK_OPTIONS}")
+ endif()
else()
message(WARNING "Versioned symbols requested, but not supported by the toolchain.")
endif()
diff --git a/libs/libcurl/src/Makefile.am b/libs/libcurl/src/Makefile.am
index 275a467d13..29cc31dfab 100644
--- a/libs/libcurl/src/Makefile.am
+++ b/libs/libcurl/src/Makefile.am
@@ -50,11 +50,9 @@ CFLAGS += @CURL_CFLAG_EXTRAS@
#
# $(top_srcdir)/include is for libcurl's external include files
# $(top_builddir)/lib is for libcurl's generated lib/curl_config.h file
-# $(top_srcdir)/lib for libcurl's lib/curl_setup.h and other "private" files
-AM_CPPFLAGS = -I$(top_srcdir)/include \
- -I$(top_builddir)/lib \
- -I$(top_srcdir)/lib
+AM_CPPFLAGS = -I$(top_srcdir)/include \
+ -I$(top_builddir)/lib
# Prevent LIBS from being used for all link targets
LIBS = $(BLANK_AT_MAKETIME)
@@ -85,11 +83,11 @@ endif
if USE_UNITY
# Keep these separate to avoid duplicate definitions when linking libtests
# in static mode.
-curl_EXCLUDE = curl_threads.c timediff.c warnless.c
+curl_EXCLUDE = curl_threads.c curlx/timediff.c curlx/warnless.c
if CURLDEBUG
-# We must compile these sources separately to avoid memdebug.h redefinitions
-# applying to them.
-curl_EXCLUDE += memdebug.c curl_multibyte.c
+# We must compile this source separately to avoid memdebug.h redefinitions
+# applying to it.
+curl_EXCLUDE += memdebug.c
endif
# For Cygwin always compile dllmain.c as a separate unit since it
# includes windows.h, which should not be included in other units.
@@ -162,15 +160,15 @@ CS_1 =
CS_ = $(CS_0)
checksrc:
- $(CHECKSRC)(@PERL@ $(top_srcdir)/scripts/checksrc.pl -D$(srcdir) \
- -W$(srcdir)/libcurl_unity.c -W$(srcdir)/curl_config.h $(srcdir)/*.[ch] \
- $(srcdir)/vauth/*.[ch] $(srcdir)/vtls/*.[ch] $(srcdir)/vquic/*.[ch] \
- $(srcdir)/vssh/*.[ch])
+ $(CHECKSRC)(@PERL@ $(top_srcdir)/scripts/checksrc.pl -D$(srcdir) \
+ $(CSOURCES) $(HHEADERS))
+if NOT_CURL_CI
if DEBUGBUILD
# for debug builds, we scan the sources on all regular make invokes
all-local: checksrc
endif
+endif
# disable the tests that are mostly causing false positives
TIDYFLAGS := -checks=-clang-analyzer-security.insecureAPI.strcpy,-clang-analyzer-optin.performance.Padding,-clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling -quiet
@@ -185,7 +183,7 @@ tidy:
$(TIDY) $$_csources $(TIDYFLAGS) $(CURL_CLANG_TIDYFLAGS) -- $(AM_CPPFLAGS) $(CPPFLAGS) -DHAVE_CONFIG_H)
optiontable:
- perl optiontable.pl < $(top_srcdir)/include/curl/curl.h > easyoptions.c
+ @PERL@ $(srcdir)/optiontable.pl < $(top_srcdir)/include/curl/curl.h > $(srcdir)/easyoptions.c
if HAVE_WINDRES
.rc.lo:
diff --git a/libs/libcurl/src/Makefile.in b/libs/libcurl/src/Makefile.in
index f991461228..bbd7e6c17c 100644
--- a/libs/libcurl/src/Makefile.in
+++ b/libs/libcurl/src/Makefile.in
@@ -142,9 +142,9 @@ host_triplet = @host@
# Makefile.inc provides the CSOURCES and HHEADERS defines
@DOING_NATIVE_WINDOWS_TRUE@am__append_3 = dllmain.c
@DOING_CYGWIN_TRUE@@DOING_NATIVE_WINDOWS_FALSE@am__append_4 = dllmain.c
-# We must compile these sources separately to avoid memdebug.h redefinitions
-# applying to them.
-@CURLDEBUG_TRUE@@USE_UNITY_TRUE@am__append_5 = memdebug.c curl_multibyte.c
+# We must compile this source separately to avoid memdebug.h redefinitions
+# applying to it.
+@CURLDEBUG_TRUE@@USE_UNITY_TRUE@am__append_5 = memdebug.c
# For Cygwin always compile dllmain.c as a separate unit since it
# includes windows.h, which should not be included in other units.
@DOING_CYGWIN_TRUE@@USE_UNITY_TRUE@am__append_6 = dllmain.c
@@ -224,31 +224,30 @@ am__installdirs = "$(DESTDIR)$(libdir)"
LTLIBRARIES = $(lib_LTLIBRARIES) $(noinst_LTLIBRARIES)
libcurl_la_LIBADD =
am__libcurl_la_SOURCES_DIST = altsvc.c amigaos.c asyn-ares.c \
- asyn-thread.c base64.c bufq.c bufref.c cf-h1-proxy.c \
+ asyn-base.c asyn-thrdd.c bufq.c bufref.c cf-h1-proxy.c \
cf-h2-proxy.c cf-haproxy.c cf-https-connect.c cf-socket.c \
- cfilters.c conncache.c cshutdn.c connect.c content_encoding.c \
- cookie.c curl_addrinfo.c curl_des.c curl_endian.c \
+ cfilters.c conncache.c connect.c content_encoding.c cookie.c \
+ cshutdn.c curl_addrinfo.c curl_des.c curl_endian.c \
curl_fnmatch.c curl_get_line.c curl_gethostname.c \
- curl_gssapi.c curl_memrchr.c curl_multibyte.c curl_ntlm_core.c \
- curl_range.c curl_rtmp.c curl_sasl.c curl_sha512_256.c \
- curl_sspi.c curl_threads.c curl_trc.c cw-out.c cw-pause.c \
- dict.c doh.c dynbuf.c dynhds.c easy.c easygetopt.c \
- easyoptions.c escape.c file.c fileinfo.c fopen.c formdata.c \
- ftp.c ftplistparser.c getenv.c getinfo.c gopher.c hash.c \
- hash_offt.c headers.c hmac.c hostasyn.c hostip.c hostip4.c \
- hostip6.c hostsyn.c hsts.c http.c http1.c http2.c \
- http_aws_sigv4.c http_chunks.c http_digest.c http_negotiate.c \
- http_ntlm.c http_proxy.c httpsrr.c idn.c if2ip.c imap.c \
- inet_ntop.c inet_pton.c krb5.c ldap.c llist.c macos.c md4.c \
+ curl_gssapi.c curl_memrchr.c curl_ntlm_core.c curl_range.c \
+ curl_rtmp.c curl_sasl.c curl_sha512_256.c curl_sspi.c \
+ curl_threads.c curl_trc.c cw-out.c cw-pause.c dict.c doh.c \
+ dynhds.c easy.c easygetopt.c easyoptions.c escape.c \
+ fake_addrinfo.c file.c fileinfo.c fopen.c formdata.c ftp.c \
+ ftplistparser.c getenv.c getinfo.c gopher.c hash.c headers.c \
+ hmac.c hostip.c hostip4.c hostip6.c hsts.c http.c http1.c \
+ http2.c http_aws_sigv4.c http_chunks.c http_digest.c \
+ http_negotiate.c http_ntlm.c http_proxy.c httpsrr.c idn.c \
+ if2ip.c imap.c inet_ntop.c krb5.c ldap.c llist.c macos.c md4.c \
md5.c memdebug.c mime.c mprintf.c mqtt.c multi.c multi_ev.c \
- netrc.c nonblock.c noproxy.c openldap.c parsedate.c pingpong.c \
- pop3.c progress.c psl.c rand.c rename.c request.c rtsp.c \
- select.c sendf.c setopt.c sha256.c share.c slist.c smb.c \
- smtp.c socketpair.c socks.c socks_gssapi.c socks_sspi.c \
- speedcheck.c splay.c strcase.c strdup.c strequal.c strerror.c \
- strparse.c system_win32.c telnet.c tftp.c timediff.c timeval.c \
- transfer.c url.c urlapi.c version.c version_win32.c warnless.c \
- ws.c vauth/cleartext.c vauth/cram.c vauth/digest.c \
+ netrc.c noproxy.c openldap.c parsedate.c pingpong.c pop3.c \
+ progress.c psl.c rand.c rename.c request.c rtsp.c select.c \
+ sendf.c setopt.c sha256.c share.c slist.c smb.c smtp.c \
+ socketpair.c socks.c socks_gssapi.c socks_sspi.c speedcheck.c \
+ splay.c strcase.c strdup.c strequal.c strerror.c \
+ system_win32.c telnet.c tftp.c transfer.c uint-bset.c \
+ uint-hash.c uint-spbset.c uint-table.c url.c urlapi.c \
+ version.c ws.c vauth/cleartext.c vauth/cram.c vauth/digest.c \
vauth/digest_sspi.c vauth/gsasl.c vauth/krb5_gssapi.c \
vauth/krb5_sspi.c vauth/ntlm.c vauth/ntlm_sspi.c \
vauth/oauth2.c vauth/spnego_gssapi.c vauth/spnego_sspi.c \
@@ -260,100 +259,103 @@ am__libcurl_la_SOURCES_DIST = altsvc.c amigaos.c asyn-ares.c \
vtls/wolfssl.c vtls/x509asn1.c vquic/curl_msh3.c \
vquic/curl_ngtcp2.c vquic/curl_osslq.c vquic/curl_quiche.c \
vquic/vquic.c vquic/vquic-tls.c vssh/libssh.c vssh/libssh2.c \
- vssh/curl_path.c vssh/wolfssh.c dllmain.c altsvc.h amigaos.h \
- arpa_telnet.h asyn.h bufq.h bufref.h cf-h1-proxy.h \
- cf-h2-proxy.h cf-haproxy.h cf-https-connect.h cf-socket.h \
- cfilters.h conncache.h cshutdn.h connect.h content_encoding.h \
- cookie.h curl_addrinfo.h curl_base64.h curl_ctype.h curl_des.h \
- curl_endian.h curl_fnmatch.h curl_get_line.h \
- curl_gethostname.h curl_gssapi.h curl_hmac.h curl_krb5.h \
- curl_ldap.h curl_md4.h curl_md5.h curl_memory.h curl_memrchr.h \
- curl_multibyte.h curl_ntlm_core.h curl_printf.h curl_range.h \
- curl_rtmp.h curl_sasl.h curl_setup.h curl_setup_once.h \
- curl_sha256.h curl_sha512_256.h curl_sspi.h curl_threads.h \
- curl_trc.h curlx.h cw-out.h cw-pause.h dict.h doh.h dynbuf.h \
- dynhds.h easy_lock.h easyif.h easyoptions.h escape.h file.h \
- fileinfo.h fopen.h formdata.h ftp.h ftplistparser.h \
- functypes.h getinfo.h gopher.h hash.h hash_offt.h headers.h \
- hostip.h hsts.h http.h http1.h http2.h http_aws_sigv4.h \
- http_chunks.h http_digest.h http_negotiate.h http_ntlm.h \
- http_proxy.h httpsrr.h idn.h if2ip.h imap.h inet_ntop.h \
- inet_pton.h llist.h macos.h memdebug.h mime.h mqtt.h \
- multihandle.h multi_ev.h multiif.h netrc.h nonblock.h \
- noproxy.h parsedate.h pingpong.h pop3.h progress.h psl.h \
- rand.h rename.h request.h rtsp.h select.h sendf.h setopt.h \
- setup-os400.h setup-vms.h setup-win32.h share.h sigpipe.h \
- slist.h smb.h smtp.h sockaddr.h socketpair.h socks.h \
- speedcheck.h splay.h strcase.h strdup.h strerror.h strparse.h \
- system_win32.h telnet.h tftp.h timediff.h timeval.h transfer.h \
- url.h urlapi-int.h urldata.h version_win32.h warnless.h ws.h \
- vauth/digest.h vauth/vauth.h vtls/bearssl.h \
- vtls/cipher_suite.h vtls/gtls.h vtls/hostcheck.h vtls/keylog.h \
- vtls/mbedtls.h vtls/mbedtls_threadlock.h vtls/openssl.h \
- vtls/rustls.h vtls/schannel.h vtls/schannel_int.h \
- vtls/sectransp.h vtls/vtls.h vtls/vtls_int.h \
- vtls/vtls_scache.h vtls/vtls_spack.h vtls/wolfssl.h \
- vtls/x509asn1.h vquic/curl_msh3.h vquic/curl_ngtcp2.h \
- vquic/curl_osslq.h vquic/curl_quiche.h vquic/vquic.h \
- vquic/vquic_int.h vquic/vquic-tls.h vssh/curl_path.h \
- vssh/ssh.h libcurl.rc
+ vssh/curl_path.c vssh/wolfssh.c curlx/base64.c curlx/dynbuf.c \
+ curlx/inet_pton.c curlx/multibyte.c curlx/nonblock.c \
+ curlx/strparse.c curlx/timediff.c curlx/timeval.c \
+ curlx/version_win32.c curlx/warnless.c curlx/winapi.c \
+ dllmain.c altsvc.h amigaos.h arpa_telnet.h asyn.h bufq.h \
+ bufref.h cf-h1-proxy.h cf-h2-proxy.h cf-haproxy.h \
+ cf-https-connect.h cf-socket.h cfilters.h conncache.h \
+ cshutdn.h connect.h content_encoding.h cookie.h \
+ curl_addrinfo.h curl_ctype.h curl_des.h curl_endian.h \
+ curl_fnmatch.h curl_get_line.h curl_gethostname.h \
+ curl_gssapi.h curl_hmac.h curl_krb5.h curl_ldap.h curl_md4.h \
+ curl_md5.h curl_memory.h curl_memrchr.h curl_ntlm_core.h \
+ curl_printf.h curl_range.h curl_rtmp.h curl_sasl.h \
+ curl_setup.h curl_setup_once.h curl_sha256.h curl_sha512_256.h \
+ curl_sspi.h curl_threads.h curl_trc.h cw-out.h cw-pause.h \
+ dict.h doh.h dynhds.h easy_lock.h easyif.h easyoptions.h \
+ escape.h fake_addrinfo.h file.h fileinfo.h fopen.h formdata.h \
+ ftp.h ftplistparser.h functypes.h getinfo.h gopher.h hash.h \
+ headers.h hostip.h hsts.h http.h http1.h http2.h \
+ http_aws_sigv4.h http_chunks.h http_digest.h http_negotiate.h \
+ http_ntlm.h http_proxy.h httpsrr.h idn.h if2ip.h imap.h \
+ inet_ntop.h llist.h macos.h memdebug.h mime.h mqtt.h \
+ multihandle.h multi_ev.h multiif.h netrc.h noproxy.h \
+ parsedate.h pingpong.h pop3.h progress.h psl.h rand.h rename.h \
+ request.h rtsp.h select.h sendf.h setopt.h setup-os400.h \
+ setup-vms.h setup-win32.h share.h sigpipe.h slist.h smb.h \
+ smtp.h sockaddr.h socketpair.h socks.h speedcheck.h splay.h \
+ strcase.h strdup.h strerror.h system_win32.h telnet.h tftp.h \
+ transfer.h uint-bset.h uint-hash.h uint-spbset.h uint-table.h \
+ url.h urlapi-int.h urldata.h ws.h vauth/digest.h vauth/vauth.h \
+ vtls/bearssl.h vtls/cipher_suite.h vtls/gtls.h \
+ vtls/hostcheck.h vtls/keylog.h vtls/mbedtls.h \
+ vtls/mbedtls_threadlock.h vtls/openssl.h vtls/rustls.h \
+ vtls/schannel.h vtls/schannel_int.h vtls/sectransp.h \
+ vtls/vtls.h vtls/vtls_int.h vtls/vtls_scache.h \
+ vtls/vtls_spack.h vtls/wolfssl.h vtls/x509asn1.h \
+ vquic/curl_msh3.h vquic/curl_ngtcp2.h vquic/curl_osslq.h \
+ vquic/curl_quiche.h vquic/vquic.h vquic/vquic_int.h \
+ vquic/vquic-tls.h vssh/curl_path.h vssh/ssh.h curlx/base64.h \
+ curlx/curlx.h curlx/dynbuf.h curlx/inet_pton.h \
+ curlx/multibyte.h curlx/nonblock.h curlx/strparse.h \
+ curlx/timediff.h curlx/timeval.h curlx/version_win32.h \
+ curlx/warnless.h curlx/winapi.h libcurl.rc
am__objects_1 = libcurl_la-altsvc.lo libcurl_la-amigaos.lo \
- libcurl_la-asyn-ares.lo libcurl_la-asyn-thread.lo \
- libcurl_la-base64.lo libcurl_la-bufq.lo libcurl_la-bufref.lo \
- libcurl_la-cf-h1-proxy.lo libcurl_la-cf-h2-proxy.lo \
- libcurl_la-cf-haproxy.lo libcurl_la-cf-https-connect.lo \
- libcurl_la-cf-socket.lo libcurl_la-cfilters.lo \
- libcurl_la-conncache.lo libcurl_la-cshutdn.lo \
+ libcurl_la-asyn-ares.lo libcurl_la-asyn-base.lo \
+ libcurl_la-asyn-thrdd.lo libcurl_la-bufq.lo \
+ libcurl_la-bufref.lo libcurl_la-cf-h1-proxy.lo \
+ libcurl_la-cf-h2-proxy.lo libcurl_la-cf-haproxy.lo \
+ libcurl_la-cf-https-connect.lo libcurl_la-cf-socket.lo \
+ libcurl_la-cfilters.lo libcurl_la-conncache.lo \
libcurl_la-connect.lo libcurl_la-content_encoding.lo \
- libcurl_la-cookie.lo libcurl_la-curl_addrinfo.lo \
- libcurl_la-curl_des.lo libcurl_la-curl_endian.lo \
- libcurl_la-curl_fnmatch.lo libcurl_la-curl_get_line.lo \
- libcurl_la-curl_gethostname.lo libcurl_la-curl_gssapi.lo \
- libcurl_la-curl_memrchr.lo libcurl_la-curl_multibyte.lo \
+ libcurl_la-cookie.lo libcurl_la-cshutdn.lo \
+ libcurl_la-curl_addrinfo.lo libcurl_la-curl_des.lo \
+ libcurl_la-curl_endian.lo libcurl_la-curl_fnmatch.lo \
+ libcurl_la-curl_get_line.lo libcurl_la-curl_gethostname.lo \
+ libcurl_la-curl_gssapi.lo libcurl_la-curl_memrchr.lo \
libcurl_la-curl_ntlm_core.lo libcurl_la-curl_range.lo \
libcurl_la-curl_rtmp.lo libcurl_la-curl_sasl.lo \
libcurl_la-curl_sha512_256.lo libcurl_la-curl_sspi.lo \
libcurl_la-curl_threads.lo libcurl_la-curl_trc.lo \
libcurl_la-cw-out.lo libcurl_la-cw-pause.lo libcurl_la-dict.lo \
- libcurl_la-doh.lo libcurl_la-dynbuf.lo libcurl_la-dynhds.lo \
- libcurl_la-easy.lo libcurl_la-easygetopt.lo \
- libcurl_la-easyoptions.lo libcurl_la-escape.lo \
+ libcurl_la-doh.lo libcurl_la-dynhds.lo libcurl_la-easy.lo \
+ libcurl_la-easygetopt.lo libcurl_la-easyoptions.lo \
+ libcurl_la-escape.lo libcurl_la-fake_addrinfo.lo \
libcurl_la-file.lo libcurl_la-fileinfo.lo libcurl_la-fopen.lo \
libcurl_la-formdata.lo libcurl_la-ftp.lo \
libcurl_la-ftplistparser.lo libcurl_la-getenv.lo \
libcurl_la-getinfo.lo libcurl_la-gopher.lo libcurl_la-hash.lo \
- libcurl_la-hash_offt.lo libcurl_la-headers.lo \
- libcurl_la-hmac.lo libcurl_la-hostasyn.lo libcurl_la-hostip.lo \
- libcurl_la-hostip4.lo libcurl_la-hostip6.lo \
- libcurl_la-hostsyn.lo libcurl_la-hsts.lo libcurl_la-http.lo \
- libcurl_la-http1.lo libcurl_la-http2.lo \
+ libcurl_la-headers.lo libcurl_la-hmac.lo libcurl_la-hostip.lo \
+ libcurl_la-hostip4.lo libcurl_la-hostip6.lo libcurl_la-hsts.lo \
+ libcurl_la-http.lo libcurl_la-http1.lo libcurl_la-http2.lo \
libcurl_la-http_aws_sigv4.lo libcurl_la-http_chunks.lo \
libcurl_la-http_digest.lo libcurl_la-http_negotiate.lo \
libcurl_la-http_ntlm.lo libcurl_la-http_proxy.lo \
libcurl_la-httpsrr.lo libcurl_la-idn.lo libcurl_la-if2ip.lo \
- libcurl_la-imap.lo libcurl_la-inet_ntop.lo \
- libcurl_la-inet_pton.lo libcurl_la-krb5.lo libcurl_la-ldap.lo \
- libcurl_la-llist.lo libcurl_la-macos.lo libcurl_la-md4.lo \
- libcurl_la-md5.lo libcurl_la-memdebug.lo libcurl_la-mime.lo \
- libcurl_la-mprintf.lo libcurl_la-mqtt.lo libcurl_la-multi.lo \
- libcurl_la-multi_ev.lo libcurl_la-netrc.lo \
- libcurl_la-nonblock.lo libcurl_la-noproxy.lo \
- libcurl_la-openldap.lo libcurl_la-parsedate.lo \
- libcurl_la-pingpong.lo libcurl_la-pop3.lo \
- libcurl_la-progress.lo libcurl_la-psl.lo libcurl_la-rand.lo \
- libcurl_la-rename.lo libcurl_la-request.lo libcurl_la-rtsp.lo \
- libcurl_la-select.lo libcurl_la-sendf.lo libcurl_la-setopt.lo \
- libcurl_la-sha256.lo libcurl_la-share.lo libcurl_la-slist.lo \
- libcurl_la-smb.lo libcurl_la-smtp.lo libcurl_la-socketpair.lo \
- libcurl_la-socks.lo libcurl_la-socks_gssapi.lo \
- libcurl_la-socks_sspi.lo libcurl_la-speedcheck.lo \
- libcurl_la-splay.lo libcurl_la-strcase.lo libcurl_la-strdup.lo \
+ libcurl_la-imap.lo libcurl_la-inet_ntop.lo libcurl_la-krb5.lo \
+ libcurl_la-ldap.lo libcurl_la-llist.lo libcurl_la-macos.lo \
+ libcurl_la-md4.lo libcurl_la-md5.lo libcurl_la-memdebug.lo \
+ libcurl_la-mime.lo libcurl_la-mprintf.lo libcurl_la-mqtt.lo \
+ libcurl_la-multi.lo libcurl_la-multi_ev.lo libcurl_la-netrc.lo \
+ libcurl_la-noproxy.lo libcurl_la-openldap.lo \
+ libcurl_la-parsedate.lo libcurl_la-pingpong.lo \
+ libcurl_la-pop3.lo libcurl_la-progress.lo libcurl_la-psl.lo \
+ libcurl_la-rand.lo libcurl_la-rename.lo libcurl_la-request.lo \
+ libcurl_la-rtsp.lo libcurl_la-select.lo libcurl_la-sendf.lo \
+ libcurl_la-setopt.lo libcurl_la-sha256.lo libcurl_la-share.lo \
+ libcurl_la-slist.lo libcurl_la-smb.lo libcurl_la-smtp.lo \
+ libcurl_la-socketpair.lo libcurl_la-socks.lo \
+ libcurl_la-socks_gssapi.lo libcurl_la-socks_sspi.lo \
+ libcurl_la-speedcheck.lo libcurl_la-splay.lo \
+ libcurl_la-strcase.lo libcurl_la-strdup.lo \
libcurl_la-strequal.lo libcurl_la-strerror.lo \
- libcurl_la-strparse.lo libcurl_la-system_win32.lo \
- libcurl_la-telnet.lo libcurl_la-tftp.lo libcurl_la-timediff.lo \
- libcurl_la-timeval.lo libcurl_la-transfer.lo libcurl_la-url.lo \
- libcurl_la-urlapi.lo libcurl_la-version.lo \
- libcurl_la-version_win32.lo libcurl_la-warnless.lo \
+ libcurl_la-system_win32.lo libcurl_la-telnet.lo \
+ libcurl_la-tftp.lo libcurl_la-transfer.lo \
+ libcurl_la-uint-bset.lo libcurl_la-uint-hash.lo \
+ libcurl_la-uint-spbset.lo libcurl_la-uint-table.lo \
+ libcurl_la-url.lo libcurl_la-urlapi.lo libcurl_la-version.lo \
libcurl_la-ws.lo
am__dirstamp = $(am__leading_dot)dirstamp
am__objects_2 = vauth/libcurl_la-cleartext.lo vauth/libcurl_la-cram.lo \
@@ -379,28 +381,34 @@ am__objects_4 = vquic/libcurl_la-curl_msh3.lo \
vquic/libcurl_la-vquic-tls.lo
am__objects_5 = vssh/libcurl_la-libssh.lo vssh/libcurl_la-libssh2.lo \
vssh/libcurl_la-curl_path.lo vssh/libcurl_la-wolfssh.lo
-@DOING_NATIVE_WINDOWS_TRUE@am__objects_6 = libcurl_la-dllmain.lo
-@DOING_CYGWIN_TRUE@@DOING_NATIVE_WINDOWS_FALSE@am__objects_7 = libcurl_la-dllmain.lo
-am__objects_8 = $(am__objects_1) $(am__objects_2) $(am__objects_3) \
+am__objects_6 = curlx/libcurl_la-base64.lo curlx/libcurl_la-dynbuf.lo \
+ curlx/libcurl_la-inet_pton.lo curlx/libcurl_la-multibyte.lo \
+ curlx/libcurl_la-nonblock.lo curlx/libcurl_la-strparse.lo \
+ curlx/libcurl_la-timediff.lo curlx/libcurl_la-timeval.lo \
+ curlx/libcurl_la-version_win32.lo curlx/libcurl_la-warnless.lo \
+ curlx/libcurl_la-winapi.lo
+@DOING_NATIVE_WINDOWS_TRUE@am__objects_7 = libcurl_la-dllmain.lo
+@DOING_CYGWIN_TRUE@@DOING_NATIVE_WINDOWS_FALSE@am__objects_8 = libcurl_la-dllmain.lo
+am__objects_9 = $(am__objects_1) $(am__objects_2) $(am__objects_3) \
$(am__objects_4) $(am__objects_5) $(am__objects_6) \
- $(am__objects_7)
-am__objects_9 =
-am__objects_10 = $(am__objects_9) $(am__objects_9) $(am__objects_9) \
- $(am__objects_9) $(am__objects_9)
-am__objects_11 = libcurl.lo
-@HAVE_WINDRES_TRUE@@USE_CPPFLAG_CURL_STATICLIB_FALSE@am__objects_12 = $(am__objects_11)
-@CURLDEBUG_TRUE@@USE_UNITY_TRUE@am__objects_13 = \
-@CURLDEBUG_TRUE@@USE_UNITY_TRUE@ libcurl_la-memdebug.lo \
-@CURLDEBUG_TRUE@@USE_UNITY_TRUE@ libcurl_la-curl_multibyte.lo
-@DOING_CYGWIN_TRUE@@USE_UNITY_TRUE@am__objects_14 = \
+ $(am__objects_7) $(am__objects_8)
+am__objects_10 =
+am__objects_11 = $(am__objects_10) $(am__objects_10) $(am__objects_10) \
+ $(am__objects_10) $(am__objects_10) $(am__objects_10)
+am__objects_12 = libcurl.lo
+@HAVE_WINDRES_TRUE@@USE_CPPFLAG_CURL_STATICLIB_FALSE@am__objects_13 = $(am__objects_12)
+@CURLDEBUG_TRUE@@USE_UNITY_TRUE@am__objects_14 = \
+@CURLDEBUG_TRUE@@USE_UNITY_TRUE@ libcurl_la-memdebug.lo
+@DOING_CYGWIN_TRUE@@USE_UNITY_TRUE@am__objects_15 = \
@DOING_CYGWIN_TRUE@@USE_UNITY_TRUE@ libcurl_la-dllmain.lo
-@USE_UNITY_TRUE@am__objects_15 = libcurl_la-curl_threads.lo \
-@USE_UNITY_TRUE@ libcurl_la-timediff.lo libcurl_la-warnless.lo \
-@USE_UNITY_TRUE@ $(am__objects_13) $(am__objects_14)
-@USE_UNITY_FALSE@am_libcurl_la_OBJECTS = $(am__objects_8) \
-@USE_UNITY_FALSE@ $(am__objects_10) $(am__objects_12)
-@USE_UNITY_TRUE@am_libcurl_la_OBJECTS = $(am__objects_15) \
-@USE_UNITY_TRUE@ $(am__objects_12)
+@USE_UNITY_TRUE@am__objects_16 = libcurl_la-curl_threads.lo \
+@USE_UNITY_TRUE@ curlx/libcurl_la-timediff.lo \
+@USE_UNITY_TRUE@ curlx/libcurl_la-warnless.lo $(am__objects_14) \
+@USE_UNITY_TRUE@ $(am__objects_15)
+@USE_UNITY_FALSE@am_libcurl_la_OBJECTS = $(am__objects_9) \
+@USE_UNITY_FALSE@ $(am__objects_11) $(am__objects_13)
+@USE_UNITY_TRUE@am_libcurl_la_OBJECTS = $(am__objects_16) \
+@USE_UNITY_TRUE@ $(am__objects_13)
@USE_UNITY_TRUE@nodist_libcurl_la_OBJECTS = \
@USE_UNITY_TRUE@ libcurl_la-libcurl_unity.lo
libcurl_la_OBJECTS = $(am_libcurl_la_OBJECTS) \
@@ -414,31 +422,30 @@ libcurl_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
$(CFLAGS) $(libcurl_la_LDFLAGS) $(LDFLAGS) -o $@
libcurlu_la_LIBADD =
am__libcurlu_la_SOURCES_DIST = altsvc.c amigaos.c asyn-ares.c \
- asyn-thread.c base64.c bufq.c bufref.c cf-h1-proxy.c \
+ asyn-base.c asyn-thrdd.c bufq.c bufref.c cf-h1-proxy.c \
cf-h2-proxy.c cf-haproxy.c cf-https-connect.c cf-socket.c \
- cfilters.c conncache.c cshutdn.c connect.c content_encoding.c \
- cookie.c curl_addrinfo.c curl_des.c curl_endian.c \
+ cfilters.c conncache.c connect.c content_encoding.c cookie.c \
+ cshutdn.c curl_addrinfo.c curl_des.c curl_endian.c \
curl_fnmatch.c curl_get_line.c curl_gethostname.c \
- curl_gssapi.c curl_memrchr.c curl_multibyte.c curl_ntlm_core.c \
- curl_range.c curl_rtmp.c curl_sasl.c curl_sha512_256.c \
- curl_sspi.c curl_threads.c curl_trc.c cw-out.c cw-pause.c \
- dict.c doh.c dynbuf.c dynhds.c easy.c easygetopt.c \
- easyoptions.c escape.c file.c fileinfo.c fopen.c formdata.c \
- ftp.c ftplistparser.c getenv.c getinfo.c gopher.c hash.c \
- hash_offt.c headers.c hmac.c hostasyn.c hostip.c hostip4.c \
- hostip6.c hostsyn.c hsts.c http.c http1.c http2.c \
- http_aws_sigv4.c http_chunks.c http_digest.c http_negotiate.c \
- http_ntlm.c http_proxy.c httpsrr.c idn.c if2ip.c imap.c \
- inet_ntop.c inet_pton.c krb5.c ldap.c llist.c macos.c md4.c \
+ curl_gssapi.c curl_memrchr.c curl_ntlm_core.c curl_range.c \
+ curl_rtmp.c curl_sasl.c curl_sha512_256.c curl_sspi.c \
+ curl_threads.c curl_trc.c cw-out.c cw-pause.c dict.c doh.c \
+ dynhds.c easy.c easygetopt.c easyoptions.c escape.c \
+ fake_addrinfo.c file.c fileinfo.c fopen.c formdata.c ftp.c \
+ ftplistparser.c getenv.c getinfo.c gopher.c hash.c headers.c \
+ hmac.c hostip.c hostip4.c hostip6.c hsts.c http.c http1.c \
+ http2.c http_aws_sigv4.c http_chunks.c http_digest.c \
+ http_negotiate.c http_ntlm.c http_proxy.c httpsrr.c idn.c \
+ if2ip.c imap.c inet_ntop.c krb5.c ldap.c llist.c macos.c md4.c \
md5.c memdebug.c mime.c mprintf.c mqtt.c multi.c multi_ev.c \
- netrc.c nonblock.c noproxy.c openldap.c parsedate.c pingpong.c \
- pop3.c progress.c psl.c rand.c rename.c request.c rtsp.c \
- select.c sendf.c setopt.c sha256.c share.c slist.c smb.c \
- smtp.c socketpair.c socks.c socks_gssapi.c socks_sspi.c \
- speedcheck.c splay.c strcase.c strdup.c strequal.c strerror.c \
- strparse.c system_win32.c telnet.c tftp.c timediff.c timeval.c \
- transfer.c url.c urlapi.c version.c version_win32.c warnless.c \
- ws.c vauth/cleartext.c vauth/cram.c vauth/digest.c \
+ netrc.c noproxy.c openldap.c parsedate.c pingpong.c pop3.c \
+ progress.c psl.c rand.c rename.c request.c rtsp.c select.c \
+ sendf.c setopt.c sha256.c share.c slist.c smb.c smtp.c \
+ socketpair.c socks.c socks_gssapi.c socks_sspi.c speedcheck.c \
+ splay.c strcase.c strdup.c strequal.c strerror.c \
+ system_win32.c telnet.c tftp.c transfer.c uint-bset.c \
+ uint-hash.c uint-spbset.c uint-table.c url.c urlapi.c \
+ version.c ws.c vauth/cleartext.c vauth/cram.c vauth/digest.c \
vauth/digest_sspi.c vauth/gsasl.c vauth/krb5_gssapi.c \
vauth/krb5_sspi.c vauth/ntlm.c vauth/ntlm_sspi.c \
vauth/oauth2.c vauth/spnego_gssapi.c vauth/spnego_sspi.c \
@@ -450,93 +457,95 @@ am__libcurlu_la_SOURCES_DIST = altsvc.c amigaos.c asyn-ares.c \
vtls/wolfssl.c vtls/x509asn1.c vquic/curl_msh3.c \
vquic/curl_ngtcp2.c vquic/curl_osslq.c vquic/curl_quiche.c \
vquic/vquic.c vquic/vquic-tls.c vssh/libssh.c vssh/libssh2.c \
- vssh/curl_path.c vssh/wolfssh.c dllmain.c altsvc.h amigaos.h \
- arpa_telnet.h asyn.h bufq.h bufref.h cf-h1-proxy.h \
- cf-h2-proxy.h cf-haproxy.h cf-https-connect.h cf-socket.h \
- cfilters.h conncache.h cshutdn.h connect.h content_encoding.h \
- cookie.h curl_addrinfo.h curl_base64.h curl_ctype.h curl_des.h \
- curl_endian.h curl_fnmatch.h curl_get_line.h \
- curl_gethostname.h curl_gssapi.h curl_hmac.h curl_krb5.h \
- curl_ldap.h curl_md4.h curl_md5.h curl_memory.h curl_memrchr.h \
- curl_multibyte.h curl_ntlm_core.h curl_printf.h curl_range.h \
- curl_rtmp.h curl_sasl.h curl_setup.h curl_setup_once.h \
- curl_sha256.h curl_sha512_256.h curl_sspi.h curl_threads.h \
- curl_trc.h curlx.h cw-out.h cw-pause.h dict.h doh.h dynbuf.h \
- dynhds.h easy_lock.h easyif.h easyoptions.h escape.h file.h \
- fileinfo.h fopen.h formdata.h ftp.h ftplistparser.h \
- functypes.h getinfo.h gopher.h hash.h hash_offt.h headers.h \
- hostip.h hsts.h http.h http1.h http2.h http_aws_sigv4.h \
- http_chunks.h http_digest.h http_negotiate.h http_ntlm.h \
- http_proxy.h httpsrr.h idn.h if2ip.h imap.h inet_ntop.h \
- inet_pton.h llist.h macos.h memdebug.h mime.h mqtt.h \
- multihandle.h multi_ev.h multiif.h netrc.h nonblock.h \
- noproxy.h parsedate.h pingpong.h pop3.h progress.h psl.h \
- rand.h rename.h request.h rtsp.h select.h sendf.h setopt.h \
- setup-os400.h setup-vms.h setup-win32.h share.h sigpipe.h \
- slist.h smb.h smtp.h sockaddr.h socketpair.h socks.h \
- speedcheck.h splay.h strcase.h strdup.h strerror.h strparse.h \
- system_win32.h telnet.h tftp.h timediff.h timeval.h transfer.h \
- url.h urlapi-int.h urldata.h version_win32.h warnless.h ws.h \
- vauth/digest.h vauth/vauth.h vtls/bearssl.h \
- vtls/cipher_suite.h vtls/gtls.h vtls/hostcheck.h vtls/keylog.h \
- vtls/mbedtls.h vtls/mbedtls_threadlock.h vtls/openssl.h \
- vtls/rustls.h vtls/schannel.h vtls/schannel_int.h \
- vtls/sectransp.h vtls/vtls.h vtls/vtls_int.h \
- vtls/vtls_scache.h vtls/vtls_spack.h vtls/wolfssl.h \
- vtls/x509asn1.h vquic/curl_msh3.h vquic/curl_ngtcp2.h \
- vquic/curl_osslq.h vquic/curl_quiche.h vquic/vquic.h \
- vquic/vquic_int.h vquic/vquic-tls.h vssh/curl_path.h \
- vssh/ssh.h
-am__objects_16 = libcurlu_la-altsvc.lo libcurlu_la-amigaos.lo \
- libcurlu_la-asyn-ares.lo libcurlu_la-asyn-thread.lo \
- libcurlu_la-base64.lo libcurlu_la-bufq.lo \
+ vssh/curl_path.c vssh/wolfssh.c curlx/base64.c curlx/dynbuf.c \
+ curlx/inet_pton.c curlx/multibyte.c curlx/nonblock.c \
+ curlx/strparse.c curlx/timediff.c curlx/timeval.c \
+ curlx/version_win32.c curlx/warnless.c curlx/winapi.c \
+ dllmain.c altsvc.h amigaos.h arpa_telnet.h asyn.h bufq.h \
+ bufref.h cf-h1-proxy.h cf-h2-proxy.h cf-haproxy.h \
+ cf-https-connect.h cf-socket.h cfilters.h conncache.h \
+ cshutdn.h connect.h content_encoding.h cookie.h \
+ curl_addrinfo.h curl_ctype.h curl_des.h curl_endian.h \
+ curl_fnmatch.h curl_get_line.h curl_gethostname.h \
+ curl_gssapi.h curl_hmac.h curl_krb5.h curl_ldap.h curl_md4.h \
+ curl_md5.h curl_memory.h curl_memrchr.h curl_ntlm_core.h \
+ curl_printf.h curl_range.h curl_rtmp.h curl_sasl.h \
+ curl_setup.h curl_setup_once.h curl_sha256.h curl_sha512_256.h \
+ curl_sspi.h curl_threads.h curl_trc.h cw-out.h cw-pause.h \
+ dict.h doh.h dynhds.h easy_lock.h easyif.h easyoptions.h \
+ escape.h fake_addrinfo.h file.h fileinfo.h fopen.h formdata.h \
+ ftp.h ftplistparser.h functypes.h getinfo.h gopher.h hash.h \
+ headers.h hostip.h hsts.h http.h http1.h http2.h \
+ http_aws_sigv4.h http_chunks.h http_digest.h http_negotiate.h \
+ http_ntlm.h http_proxy.h httpsrr.h idn.h if2ip.h imap.h \
+ inet_ntop.h llist.h macos.h memdebug.h mime.h mqtt.h \
+ multihandle.h multi_ev.h multiif.h netrc.h noproxy.h \
+ parsedate.h pingpong.h pop3.h progress.h psl.h rand.h rename.h \
+ request.h rtsp.h select.h sendf.h setopt.h setup-os400.h \
+ setup-vms.h setup-win32.h share.h sigpipe.h slist.h smb.h \
+ smtp.h sockaddr.h socketpair.h socks.h speedcheck.h splay.h \
+ strcase.h strdup.h strerror.h system_win32.h telnet.h tftp.h \
+ transfer.h uint-bset.h uint-hash.h uint-spbset.h uint-table.h \
+ url.h urlapi-int.h urldata.h ws.h vauth/digest.h vauth/vauth.h \
+ vtls/bearssl.h vtls/cipher_suite.h vtls/gtls.h \
+ vtls/hostcheck.h vtls/keylog.h vtls/mbedtls.h \
+ vtls/mbedtls_threadlock.h vtls/openssl.h vtls/rustls.h \
+ vtls/schannel.h vtls/schannel_int.h vtls/sectransp.h \
+ vtls/vtls.h vtls/vtls_int.h vtls/vtls_scache.h \
+ vtls/vtls_spack.h vtls/wolfssl.h vtls/x509asn1.h \
+ vquic/curl_msh3.h vquic/curl_ngtcp2.h vquic/curl_osslq.h \
+ vquic/curl_quiche.h vquic/vquic.h vquic/vquic_int.h \
+ vquic/vquic-tls.h vssh/curl_path.h vssh/ssh.h curlx/base64.h \
+ curlx/curlx.h curlx/dynbuf.h curlx/inet_pton.h \
+ curlx/multibyte.h curlx/nonblock.h curlx/strparse.h \
+ curlx/timediff.h curlx/timeval.h curlx/version_win32.h \
+ curlx/warnless.h curlx/winapi.h
+am__objects_17 = libcurlu_la-altsvc.lo libcurlu_la-amigaos.lo \
+ libcurlu_la-asyn-ares.lo libcurlu_la-asyn-base.lo \
+ libcurlu_la-asyn-thrdd.lo libcurlu_la-bufq.lo \
libcurlu_la-bufref.lo libcurlu_la-cf-h1-proxy.lo \
libcurlu_la-cf-h2-proxy.lo libcurlu_la-cf-haproxy.lo \
libcurlu_la-cf-https-connect.lo libcurlu_la-cf-socket.lo \
libcurlu_la-cfilters.lo libcurlu_la-conncache.lo \
- libcurlu_la-cshutdn.lo libcurlu_la-connect.lo \
- libcurlu_la-content_encoding.lo libcurlu_la-cookie.lo \
+ libcurlu_la-connect.lo libcurlu_la-content_encoding.lo \
+ libcurlu_la-cookie.lo libcurlu_la-cshutdn.lo \
libcurlu_la-curl_addrinfo.lo libcurlu_la-curl_des.lo \
libcurlu_la-curl_endian.lo libcurlu_la-curl_fnmatch.lo \
libcurlu_la-curl_get_line.lo libcurlu_la-curl_gethostname.lo \
libcurlu_la-curl_gssapi.lo libcurlu_la-curl_memrchr.lo \
- libcurlu_la-curl_multibyte.lo libcurlu_la-curl_ntlm_core.lo \
- libcurlu_la-curl_range.lo libcurlu_la-curl_rtmp.lo \
- libcurlu_la-curl_sasl.lo libcurlu_la-curl_sha512_256.lo \
- libcurlu_la-curl_sspi.lo libcurlu_la-curl_threads.lo \
- libcurlu_la-curl_trc.lo libcurlu_la-cw-out.lo \
- libcurlu_la-cw-pause.lo libcurlu_la-dict.lo libcurlu_la-doh.lo \
- libcurlu_la-dynbuf.lo libcurlu_la-dynhds.lo \
+ libcurlu_la-curl_ntlm_core.lo libcurlu_la-curl_range.lo \
+ libcurlu_la-curl_rtmp.lo libcurlu_la-curl_sasl.lo \
+ libcurlu_la-curl_sha512_256.lo libcurlu_la-curl_sspi.lo \
+ libcurlu_la-curl_threads.lo libcurlu_la-curl_trc.lo \
+ libcurlu_la-cw-out.lo libcurlu_la-cw-pause.lo \
+ libcurlu_la-dict.lo libcurlu_la-doh.lo libcurlu_la-dynhds.lo \
libcurlu_la-easy.lo libcurlu_la-easygetopt.lo \
libcurlu_la-easyoptions.lo libcurlu_la-escape.lo \
- libcurlu_la-file.lo libcurlu_la-fileinfo.lo \
- libcurlu_la-fopen.lo libcurlu_la-formdata.lo \
- libcurlu_la-ftp.lo libcurlu_la-ftplistparser.lo \
- libcurlu_la-getenv.lo libcurlu_la-getinfo.lo \
- libcurlu_la-gopher.lo libcurlu_la-hash.lo \
- libcurlu_la-hash_offt.lo libcurlu_la-headers.lo \
- libcurlu_la-hmac.lo libcurlu_la-hostasyn.lo \
+ libcurlu_la-fake_addrinfo.lo libcurlu_la-file.lo \
+ libcurlu_la-fileinfo.lo libcurlu_la-fopen.lo \
+ libcurlu_la-formdata.lo libcurlu_la-ftp.lo \
+ libcurlu_la-ftplistparser.lo libcurlu_la-getenv.lo \
+ libcurlu_la-getinfo.lo libcurlu_la-gopher.lo \
+ libcurlu_la-hash.lo libcurlu_la-headers.lo libcurlu_la-hmac.lo \
libcurlu_la-hostip.lo libcurlu_la-hostip4.lo \
- libcurlu_la-hostip6.lo libcurlu_la-hostsyn.lo \
- libcurlu_la-hsts.lo libcurlu_la-http.lo libcurlu_la-http1.lo \
- libcurlu_la-http2.lo libcurlu_la-http_aws_sigv4.lo \
- libcurlu_la-http_chunks.lo libcurlu_la-http_digest.lo \
- libcurlu_la-http_negotiate.lo libcurlu_la-http_ntlm.lo \
- libcurlu_la-http_proxy.lo libcurlu_la-httpsrr.lo \
- libcurlu_la-idn.lo libcurlu_la-if2ip.lo libcurlu_la-imap.lo \
- libcurlu_la-inet_ntop.lo libcurlu_la-inet_pton.lo \
+ libcurlu_la-hostip6.lo libcurlu_la-hsts.lo libcurlu_la-http.lo \
+ libcurlu_la-http1.lo libcurlu_la-http2.lo \
+ libcurlu_la-http_aws_sigv4.lo libcurlu_la-http_chunks.lo \
+ libcurlu_la-http_digest.lo libcurlu_la-http_negotiate.lo \
+ libcurlu_la-http_ntlm.lo libcurlu_la-http_proxy.lo \
+ libcurlu_la-httpsrr.lo libcurlu_la-idn.lo libcurlu_la-if2ip.lo \
+ libcurlu_la-imap.lo libcurlu_la-inet_ntop.lo \
libcurlu_la-krb5.lo libcurlu_la-ldap.lo libcurlu_la-llist.lo \
libcurlu_la-macos.lo libcurlu_la-md4.lo libcurlu_la-md5.lo \
libcurlu_la-memdebug.lo libcurlu_la-mime.lo \
libcurlu_la-mprintf.lo libcurlu_la-mqtt.lo \
libcurlu_la-multi.lo libcurlu_la-multi_ev.lo \
- libcurlu_la-netrc.lo libcurlu_la-nonblock.lo \
- libcurlu_la-noproxy.lo libcurlu_la-openldap.lo \
- libcurlu_la-parsedate.lo libcurlu_la-pingpong.lo \
- libcurlu_la-pop3.lo libcurlu_la-progress.lo libcurlu_la-psl.lo \
- libcurlu_la-rand.lo libcurlu_la-rename.lo \
- libcurlu_la-request.lo libcurlu_la-rtsp.lo \
- libcurlu_la-select.lo libcurlu_la-sendf.lo \
+ libcurlu_la-netrc.lo libcurlu_la-noproxy.lo \
+ libcurlu_la-openldap.lo libcurlu_la-parsedate.lo \
+ libcurlu_la-pingpong.lo libcurlu_la-pop3.lo \
+ libcurlu_la-progress.lo libcurlu_la-psl.lo libcurlu_la-rand.lo \
+ libcurlu_la-rename.lo libcurlu_la-request.lo \
+ libcurlu_la-rtsp.lo libcurlu_la-select.lo libcurlu_la-sendf.lo \
libcurlu_la-setopt.lo libcurlu_la-sha256.lo \
libcurlu_la-share.lo libcurlu_la-slist.lo libcurlu_la-smb.lo \
libcurlu_la-smtp.lo libcurlu_la-socketpair.lo \
@@ -544,14 +553,13 @@ am__objects_16 = libcurlu_la-altsvc.lo libcurlu_la-amigaos.lo \
libcurlu_la-socks_sspi.lo libcurlu_la-speedcheck.lo \
libcurlu_la-splay.lo libcurlu_la-strcase.lo \
libcurlu_la-strdup.lo libcurlu_la-strequal.lo \
- libcurlu_la-strerror.lo libcurlu_la-strparse.lo \
- libcurlu_la-system_win32.lo libcurlu_la-telnet.lo \
- libcurlu_la-tftp.lo libcurlu_la-timediff.lo \
- libcurlu_la-timeval.lo libcurlu_la-transfer.lo \
- libcurlu_la-url.lo libcurlu_la-urlapi.lo \
- libcurlu_la-version.lo libcurlu_la-version_win32.lo \
- libcurlu_la-warnless.lo libcurlu_la-ws.lo
-am__objects_17 = vauth/libcurlu_la-cleartext.lo \
+ libcurlu_la-strerror.lo libcurlu_la-system_win32.lo \
+ libcurlu_la-telnet.lo libcurlu_la-tftp.lo \
+ libcurlu_la-transfer.lo libcurlu_la-uint-bset.lo \
+ libcurlu_la-uint-hash.lo libcurlu_la-uint-spbset.lo \
+ libcurlu_la-uint-table.lo libcurlu_la-url.lo \
+ libcurlu_la-urlapi.lo libcurlu_la-version.lo libcurlu_la-ws.lo
+am__objects_18 = vauth/libcurlu_la-cleartext.lo \
vauth/libcurlu_la-cram.lo vauth/libcurlu_la-digest.lo \
vauth/libcurlu_la-digest_sspi.lo vauth/libcurlu_la-gsasl.lo \
vauth/libcurlu_la-krb5_gssapi.lo \
@@ -559,7 +567,7 @@ am__objects_17 = vauth/libcurlu_la-cleartext.lo \
vauth/libcurlu_la-ntlm_sspi.lo vauth/libcurlu_la-oauth2.lo \
vauth/libcurlu_la-spnego_gssapi.lo \
vauth/libcurlu_la-spnego_sspi.lo vauth/libcurlu_la-vauth.lo
-am__objects_18 = vtls/libcurlu_la-bearssl.lo \
+am__objects_19 = vtls/libcurlu_la-bearssl.lo \
vtls/libcurlu_la-cipher_suite.lo vtls/libcurlu_la-gtls.lo \
vtls/libcurlu_la-hostcheck.lo vtls/libcurlu_la-keylog.lo \
vtls/libcurlu_la-mbedtls.lo \
@@ -570,31 +578,37 @@ am__objects_18 = vtls/libcurlu_la-bearssl.lo \
vtls/libcurlu_la-sectransp.lo vtls/libcurlu_la-vtls.lo \
vtls/libcurlu_la-vtls_scache.lo vtls/libcurlu_la-vtls_spack.lo \
vtls/libcurlu_la-wolfssl.lo vtls/libcurlu_la-x509asn1.lo
-am__objects_19 = vquic/libcurlu_la-curl_msh3.lo \
+am__objects_20 = vquic/libcurlu_la-curl_msh3.lo \
vquic/libcurlu_la-curl_ngtcp2.lo \
vquic/libcurlu_la-curl_osslq.lo \
vquic/libcurlu_la-curl_quiche.lo vquic/libcurlu_la-vquic.lo \
vquic/libcurlu_la-vquic-tls.lo
-am__objects_20 = vssh/libcurlu_la-libssh.lo \
+am__objects_21 = vssh/libcurlu_la-libssh.lo \
vssh/libcurlu_la-libssh2.lo vssh/libcurlu_la-curl_path.lo \
vssh/libcurlu_la-wolfssh.lo
-@DOING_NATIVE_WINDOWS_TRUE@am__objects_21 = libcurlu_la-dllmain.lo
-@DOING_CYGWIN_TRUE@@DOING_NATIVE_WINDOWS_FALSE@am__objects_22 = libcurlu_la-dllmain.lo
-am__objects_23 = $(am__objects_16) $(am__objects_17) $(am__objects_18) \
- $(am__objects_19) $(am__objects_20) $(am__objects_21) \
- $(am__objects_22)
-@CURLDEBUG_TRUE@@USE_UNITY_TRUE@am__objects_24 = \
-@CURLDEBUG_TRUE@@USE_UNITY_TRUE@ libcurlu_la-memdebug.lo \
-@CURLDEBUG_TRUE@@USE_UNITY_TRUE@ libcurlu_la-curl_multibyte.lo
-@DOING_CYGWIN_TRUE@@USE_UNITY_TRUE@am__objects_25 = \
+am__objects_22 = curlx/libcurlu_la-base64.lo \
+ curlx/libcurlu_la-dynbuf.lo curlx/libcurlu_la-inet_pton.lo \
+ curlx/libcurlu_la-multibyte.lo curlx/libcurlu_la-nonblock.lo \
+ curlx/libcurlu_la-strparse.lo curlx/libcurlu_la-timediff.lo \
+ curlx/libcurlu_la-timeval.lo \
+ curlx/libcurlu_la-version_win32.lo \
+ curlx/libcurlu_la-warnless.lo curlx/libcurlu_la-winapi.lo
+@DOING_NATIVE_WINDOWS_TRUE@am__objects_23 = libcurlu_la-dllmain.lo
+@DOING_CYGWIN_TRUE@@DOING_NATIVE_WINDOWS_FALSE@am__objects_24 = libcurlu_la-dllmain.lo
+am__objects_25 = $(am__objects_17) $(am__objects_18) $(am__objects_19) \
+ $(am__objects_20) $(am__objects_21) $(am__objects_22) \
+ $(am__objects_23) $(am__objects_24)
+@CURLDEBUG_TRUE@@USE_UNITY_TRUE@am__objects_26 = \
+@CURLDEBUG_TRUE@@USE_UNITY_TRUE@ libcurlu_la-memdebug.lo
+@DOING_CYGWIN_TRUE@@USE_UNITY_TRUE@am__objects_27 = \
@DOING_CYGWIN_TRUE@@USE_UNITY_TRUE@ libcurlu_la-dllmain.lo
-@USE_UNITY_TRUE@am__objects_26 = libcurlu_la-curl_threads.lo \
-@USE_UNITY_TRUE@ libcurlu_la-timediff.lo \
-@USE_UNITY_TRUE@ libcurlu_la-warnless.lo $(am__objects_24) \
-@USE_UNITY_TRUE@ $(am__objects_25)
-@USE_UNITY_FALSE@am_libcurlu_la_OBJECTS = $(am__objects_23) \
-@USE_UNITY_FALSE@ $(am__objects_10)
-@USE_UNITY_TRUE@am_libcurlu_la_OBJECTS = $(am__objects_26)
+@USE_UNITY_TRUE@am__objects_28 = libcurlu_la-curl_threads.lo \
+@USE_UNITY_TRUE@ curlx/libcurlu_la-timediff.lo \
+@USE_UNITY_TRUE@ curlx/libcurlu_la-warnless.lo \
+@USE_UNITY_TRUE@ $(am__objects_26) $(am__objects_27)
+@USE_UNITY_FALSE@am_libcurlu_la_OBJECTS = $(am__objects_25) \
+@USE_UNITY_FALSE@ $(am__objects_11)
+@USE_UNITY_TRUE@am_libcurlu_la_OBJECTS = $(am__objects_28)
@USE_UNITY_TRUE@nodist_libcurlu_la_OBJECTS = \
@USE_UNITY_TRUE@ libcurlu_la-libcurl_unity.lo
libcurlu_la_OBJECTS = $(am_libcurlu_la_OBJECTS) \
@@ -621,8 +635,8 @@ am__maybe_remake_depfiles = depfiles
am__depfiles_remade = ./$(DEPDIR)/libcurl_la-altsvc.Plo \
./$(DEPDIR)/libcurl_la-amigaos.Plo \
./$(DEPDIR)/libcurl_la-asyn-ares.Plo \
- ./$(DEPDIR)/libcurl_la-asyn-thread.Plo \
- ./$(DEPDIR)/libcurl_la-base64.Plo \
+ ./$(DEPDIR)/libcurl_la-asyn-base.Plo \
+ ./$(DEPDIR)/libcurl_la-asyn-thrdd.Plo \
./$(DEPDIR)/libcurl_la-bufq.Plo \
./$(DEPDIR)/libcurl_la-bufref.Plo \
./$(DEPDIR)/libcurl_la-cf-h1-proxy.Plo \
@@ -644,7 +658,6 @@ am__depfiles_remade = ./$(DEPDIR)/libcurl_la-altsvc.Plo \
./$(DEPDIR)/libcurl_la-curl_gethostname.Plo \
./$(DEPDIR)/libcurl_la-curl_gssapi.Plo \
./$(DEPDIR)/libcurl_la-curl_memrchr.Plo \
- ./$(DEPDIR)/libcurl_la-curl_multibyte.Plo \
./$(DEPDIR)/libcurl_la-curl_ntlm_core.Plo \
./$(DEPDIR)/libcurl_la-curl_range.Plo \
./$(DEPDIR)/libcurl_la-curl_rtmp.Plo \
@@ -658,12 +671,12 @@ am__depfiles_remade = ./$(DEPDIR)/libcurl_la-altsvc.Plo \
./$(DEPDIR)/libcurl_la-dict.Plo \
./$(DEPDIR)/libcurl_la-dllmain.Plo \
./$(DEPDIR)/libcurl_la-doh.Plo \
- ./$(DEPDIR)/libcurl_la-dynbuf.Plo \
./$(DEPDIR)/libcurl_la-dynhds.Plo \
./$(DEPDIR)/libcurl_la-easy.Plo \
./$(DEPDIR)/libcurl_la-easygetopt.Plo \
./$(DEPDIR)/libcurl_la-easyoptions.Plo \
./$(DEPDIR)/libcurl_la-escape.Plo \
+ ./$(DEPDIR)/libcurl_la-fake_addrinfo.Plo \
./$(DEPDIR)/libcurl_la-file.Plo \
./$(DEPDIR)/libcurl_la-fileinfo.Plo \
./$(DEPDIR)/libcurl_la-fopen.Plo \
@@ -674,14 +687,11 @@ am__depfiles_remade = ./$(DEPDIR)/libcurl_la-altsvc.Plo \
./$(DEPDIR)/libcurl_la-getinfo.Plo \
./$(DEPDIR)/libcurl_la-gopher.Plo \
./$(DEPDIR)/libcurl_la-hash.Plo \
- ./$(DEPDIR)/libcurl_la-hash_offt.Plo \
./$(DEPDIR)/libcurl_la-headers.Plo \
./$(DEPDIR)/libcurl_la-hmac.Plo \
- ./$(DEPDIR)/libcurl_la-hostasyn.Plo \
./$(DEPDIR)/libcurl_la-hostip.Plo \
./$(DEPDIR)/libcurl_la-hostip4.Plo \
./$(DEPDIR)/libcurl_la-hostip6.Plo \
- ./$(DEPDIR)/libcurl_la-hostsyn.Plo \
./$(DEPDIR)/libcurl_la-hsts.Plo \
./$(DEPDIR)/libcurl_la-http.Plo \
./$(DEPDIR)/libcurl_la-http1.Plo \
@@ -697,7 +707,6 @@ am__depfiles_remade = ./$(DEPDIR)/libcurl_la-altsvc.Plo \
./$(DEPDIR)/libcurl_la-if2ip.Plo \
./$(DEPDIR)/libcurl_la-imap.Plo \
./$(DEPDIR)/libcurl_la-inet_ntop.Plo \
- ./$(DEPDIR)/libcurl_la-inet_pton.Plo \
./$(DEPDIR)/libcurl_la-krb5.Plo \
./$(DEPDIR)/libcurl_la-ldap.Plo \
./$(DEPDIR)/libcurl_la-libcurl_unity.Plo \
@@ -711,7 +720,6 @@ am__depfiles_remade = ./$(DEPDIR)/libcurl_la-altsvc.Plo \
./$(DEPDIR)/libcurl_la-multi.Plo \
./$(DEPDIR)/libcurl_la-multi_ev.Plo \
./$(DEPDIR)/libcurl_la-netrc.Plo \
- ./$(DEPDIR)/libcurl_la-nonblock.Plo \
./$(DEPDIR)/libcurl_la-noproxy.Plo \
./$(DEPDIR)/libcurl_la-openldap.Plo \
./$(DEPDIR)/libcurl_la-parsedate.Plo \
@@ -739,24 +747,23 @@ am__depfiles_remade = ./$(DEPDIR)/libcurl_la-altsvc.Plo \
./$(DEPDIR)/libcurl_la-strdup.Plo \
./$(DEPDIR)/libcurl_la-strequal.Plo \
./$(DEPDIR)/libcurl_la-strerror.Plo \
- ./$(DEPDIR)/libcurl_la-strparse.Plo \
./$(DEPDIR)/libcurl_la-system_win32.Plo \
./$(DEPDIR)/libcurl_la-telnet.Plo \
./$(DEPDIR)/libcurl_la-tftp.Plo \
- ./$(DEPDIR)/libcurl_la-timediff.Plo \
- ./$(DEPDIR)/libcurl_la-timeval.Plo \
./$(DEPDIR)/libcurl_la-transfer.Plo \
+ ./$(DEPDIR)/libcurl_la-uint-bset.Plo \
+ ./$(DEPDIR)/libcurl_la-uint-hash.Plo \
+ ./$(DEPDIR)/libcurl_la-uint-spbset.Plo \
+ ./$(DEPDIR)/libcurl_la-uint-table.Plo \
./$(DEPDIR)/libcurl_la-url.Plo \
./$(DEPDIR)/libcurl_la-urlapi.Plo \
./$(DEPDIR)/libcurl_la-version.Plo \
- ./$(DEPDIR)/libcurl_la-version_win32.Plo \
- ./$(DEPDIR)/libcurl_la-warnless.Plo \
./$(DEPDIR)/libcurl_la-ws.Plo \
./$(DEPDIR)/libcurlu_la-altsvc.Plo \
./$(DEPDIR)/libcurlu_la-amigaos.Plo \
./$(DEPDIR)/libcurlu_la-asyn-ares.Plo \
- ./$(DEPDIR)/libcurlu_la-asyn-thread.Plo \
- ./$(DEPDIR)/libcurlu_la-base64.Plo \
+ ./$(DEPDIR)/libcurlu_la-asyn-base.Plo \
+ ./$(DEPDIR)/libcurlu_la-asyn-thrdd.Plo \
./$(DEPDIR)/libcurlu_la-bufq.Plo \
./$(DEPDIR)/libcurlu_la-bufref.Plo \
./$(DEPDIR)/libcurlu_la-cf-h1-proxy.Plo \
@@ -778,7 +785,6 @@ am__depfiles_remade = ./$(DEPDIR)/libcurl_la-altsvc.Plo \
./$(DEPDIR)/libcurlu_la-curl_gethostname.Plo \
./$(DEPDIR)/libcurlu_la-curl_gssapi.Plo \
./$(DEPDIR)/libcurlu_la-curl_memrchr.Plo \
- ./$(DEPDIR)/libcurlu_la-curl_multibyte.Plo \
./$(DEPDIR)/libcurlu_la-curl_ntlm_core.Plo \
./$(DEPDIR)/libcurlu_la-curl_range.Plo \
./$(DEPDIR)/libcurlu_la-curl_rtmp.Plo \
@@ -792,12 +798,12 @@ am__depfiles_remade = ./$(DEPDIR)/libcurl_la-altsvc.Plo \
./$(DEPDIR)/libcurlu_la-dict.Plo \
./$(DEPDIR)/libcurlu_la-dllmain.Plo \
./$(DEPDIR)/libcurlu_la-doh.Plo \
- ./$(DEPDIR)/libcurlu_la-dynbuf.Plo \
./$(DEPDIR)/libcurlu_la-dynhds.Plo \
./$(DEPDIR)/libcurlu_la-easy.Plo \
./$(DEPDIR)/libcurlu_la-easygetopt.Plo \
./$(DEPDIR)/libcurlu_la-easyoptions.Plo \
./$(DEPDIR)/libcurlu_la-escape.Plo \
+ ./$(DEPDIR)/libcurlu_la-fake_addrinfo.Plo \
./$(DEPDIR)/libcurlu_la-file.Plo \
./$(DEPDIR)/libcurlu_la-fileinfo.Plo \
./$(DEPDIR)/libcurlu_la-fopen.Plo \
@@ -808,14 +814,11 @@ am__depfiles_remade = ./$(DEPDIR)/libcurl_la-altsvc.Plo \
./$(DEPDIR)/libcurlu_la-getinfo.Plo \
./$(DEPDIR)/libcurlu_la-gopher.Plo \
./$(DEPDIR)/libcurlu_la-hash.Plo \
- ./$(DEPDIR)/libcurlu_la-hash_offt.Plo \
./$(DEPDIR)/libcurlu_la-headers.Plo \
./$(DEPDIR)/libcurlu_la-hmac.Plo \
- ./$(DEPDIR)/libcurlu_la-hostasyn.Plo \
./$(DEPDIR)/libcurlu_la-hostip.Plo \
./$(DEPDIR)/libcurlu_la-hostip4.Plo \
./$(DEPDIR)/libcurlu_la-hostip6.Plo \
- ./$(DEPDIR)/libcurlu_la-hostsyn.Plo \
./$(DEPDIR)/libcurlu_la-hsts.Plo \
./$(DEPDIR)/libcurlu_la-http.Plo \
./$(DEPDIR)/libcurlu_la-http1.Plo \
@@ -831,7 +834,6 @@ am__depfiles_remade = ./$(DEPDIR)/libcurl_la-altsvc.Plo \
./$(DEPDIR)/libcurlu_la-if2ip.Plo \
./$(DEPDIR)/libcurlu_la-imap.Plo \
./$(DEPDIR)/libcurlu_la-inet_ntop.Plo \
- ./$(DEPDIR)/libcurlu_la-inet_pton.Plo \
./$(DEPDIR)/libcurlu_la-krb5.Plo \
./$(DEPDIR)/libcurlu_la-ldap.Plo \
./$(DEPDIR)/libcurlu_la-libcurl_unity.Plo \
@@ -846,7 +848,6 @@ am__depfiles_remade = ./$(DEPDIR)/libcurl_la-altsvc.Plo \
./$(DEPDIR)/libcurlu_la-multi.Plo \
./$(DEPDIR)/libcurlu_la-multi_ev.Plo \
./$(DEPDIR)/libcurlu_la-netrc.Plo \
- ./$(DEPDIR)/libcurlu_la-nonblock.Plo \
./$(DEPDIR)/libcurlu_la-noproxy.Plo \
./$(DEPDIR)/libcurlu_la-openldap.Plo \
./$(DEPDIR)/libcurlu_la-parsedate.Plo \
@@ -876,19 +877,40 @@ am__depfiles_remade = ./$(DEPDIR)/libcurl_la-altsvc.Plo \
./$(DEPDIR)/libcurlu_la-strdup.Plo \
./$(DEPDIR)/libcurlu_la-strequal.Plo \
./$(DEPDIR)/libcurlu_la-strerror.Plo \
- ./$(DEPDIR)/libcurlu_la-strparse.Plo \
./$(DEPDIR)/libcurlu_la-system_win32.Plo \
./$(DEPDIR)/libcurlu_la-telnet.Plo \
./$(DEPDIR)/libcurlu_la-tftp.Plo \
- ./$(DEPDIR)/libcurlu_la-timediff.Plo \
- ./$(DEPDIR)/libcurlu_la-timeval.Plo \
./$(DEPDIR)/libcurlu_la-transfer.Plo \
+ ./$(DEPDIR)/libcurlu_la-uint-bset.Plo \
+ ./$(DEPDIR)/libcurlu_la-uint-hash.Plo \
+ ./$(DEPDIR)/libcurlu_la-uint-spbset.Plo \
+ ./$(DEPDIR)/libcurlu_la-uint-table.Plo \
./$(DEPDIR)/libcurlu_la-url.Plo \
./$(DEPDIR)/libcurlu_la-urlapi.Plo \
./$(DEPDIR)/libcurlu_la-version.Plo \
- ./$(DEPDIR)/libcurlu_la-version_win32.Plo \
- ./$(DEPDIR)/libcurlu_la-warnless.Plo \
./$(DEPDIR)/libcurlu_la-ws.Plo \
+ curlx/$(DEPDIR)/libcurl_la-base64.Plo \
+ curlx/$(DEPDIR)/libcurl_la-dynbuf.Plo \
+ curlx/$(DEPDIR)/libcurl_la-inet_pton.Plo \
+ curlx/$(DEPDIR)/libcurl_la-multibyte.Plo \
+ curlx/$(DEPDIR)/libcurl_la-nonblock.Plo \
+ curlx/$(DEPDIR)/libcurl_la-strparse.Plo \
+ curlx/$(DEPDIR)/libcurl_la-timediff.Plo \
+ curlx/$(DEPDIR)/libcurl_la-timeval.Plo \
+ curlx/$(DEPDIR)/libcurl_la-version_win32.Plo \
+ curlx/$(DEPDIR)/libcurl_la-warnless.Plo \
+ curlx/$(DEPDIR)/libcurl_la-winapi.Plo \
+ curlx/$(DEPDIR)/libcurlu_la-base64.Plo \
+ curlx/$(DEPDIR)/libcurlu_la-dynbuf.Plo \
+ curlx/$(DEPDIR)/libcurlu_la-inet_pton.Plo \
+ curlx/$(DEPDIR)/libcurlu_la-multibyte.Plo \
+ curlx/$(DEPDIR)/libcurlu_la-nonblock.Plo \
+ curlx/$(DEPDIR)/libcurlu_la-strparse.Plo \
+ curlx/$(DEPDIR)/libcurlu_la-timediff.Plo \
+ curlx/$(DEPDIR)/libcurlu_la-timeval.Plo \
+ curlx/$(DEPDIR)/libcurlu_la-version_win32.Plo \
+ curlx/$(DEPDIR)/libcurlu_la-warnless.Plo \
+ curlx/$(DEPDIR)/libcurlu_la-winapi.Plo \
vauth/$(DEPDIR)/libcurl_la-cleartext.Plo \
vauth/$(DEPDIR)/libcurl_la-cram.Plo \
vauth/$(DEPDIR)/libcurl_la-digest.Plo \
@@ -1230,10 +1252,8 @@ lib_LTLIBRARIES = libcurl.la
#
# $(top_srcdir)/include is for libcurl's external include files
# $(top_builddir)/lib is for libcurl's generated lib/curl_config.h file
-# $(top_srcdir)/lib for libcurl's lib/curl_setup.h and other "private" files
AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_builddir)/lib \
- -I$(top_srcdir)/lib -DBUILDING_LIBCURL $(am__append_1) \
- $(am__append_2)
+ -DBUILDING_LIBCURL $(am__append_1) $(am__append_2)
# Keep in sync with CURL_LIBCURL_VERSIONED_SYMBOLS_SONAME in configure.ac
VERSIONCHANGE = 12
@@ -1244,6 +1264,33 @@ VERSIONDEL = 8
VERSIONINFO = -version-info $(VERSIONCHANGE):$(VERSIONADD):$(VERSIONDEL)
AM_LDFLAGS =
AM_CFLAGS =
+LIB_CURLX_CFILES = \
+ curlx/base64.c \
+ curlx/dynbuf.c \
+ curlx/inet_pton.c \
+ curlx/multibyte.c \
+ curlx/nonblock.c \
+ curlx/strparse.c \
+ curlx/timediff.c \
+ curlx/timeval.c \
+ curlx/version_win32.c \
+ curlx/warnless.c \
+ curlx/winapi.c
+
+LIB_CURLX_HFILES = \
+ curlx/base64.h \
+ curlx/curlx.h \
+ curlx/dynbuf.h \
+ curlx/inet_pton.h \
+ curlx/multibyte.h \
+ curlx/nonblock.h \
+ curlx/strparse.h \
+ curlx/timediff.h \
+ curlx/timeval.h \
+ curlx/version_win32.h \
+ curlx/warnless.h \
+ curlx/winapi.h
+
LIB_VAUTH_CFILES = \
vauth/cleartext.c \
vauth/cram.c \
@@ -1333,8 +1380,8 @@ LIB_CFILES = \
altsvc.c \
amigaos.c \
asyn-ares.c \
- asyn-thread.c \
- base64.c \
+ asyn-base.c \
+ asyn-thrdd.c \
bufq.c \
bufref.c \
cf-h1-proxy.c \
@@ -1344,10 +1391,10 @@ LIB_CFILES = \
cf-socket.c \
cfilters.c \
conncache.c \
- cshutdn.c \
connect.c \
content_encoding.c \
cookie.c \
+ cshutdn.c \
curl_addrinfo.c \
curl_des.c \
curl_endian.c \
@@ -1356,7 +1403,6 @@ LIB_CFILES = \
curl_gethostname.c \
curl_gssapi.c \
curl_memrchr.c \
- curl_multibyte.c \
curl_ntlm_core.c \
curl_range.c \
curl_rtmp.c \
@@ -1369,12 +1415,12 @@ LIB_CFILES = \
cw-pause.c \
dict.c \
doh.c \
- dynbuf.c \
dynhds.c \
easy.c \
easygetopt.c \
easyoptions.c \
escape.c \
+ fake_addrinfo.c \
file.c \
fileinfo.c \
fopen.c \
@@ -1385,14 +1431,11 @@ LIB_CFILES = \
getinfo.c \
gopher.c \
hash.c \
- hash_offt.c \
headers.c \
hmac.c \
- hostasyn.c \
hostip.c \
hostip4.c \
hostip6.c \
- hostsyn.c \
hsts.c \
http.c \
http1.c \
@@ -1408,7 +1451,6 @@ LIB_CFILES = \
if2ip.c \
imap.c \
inet_ntop.c \
- inet_pton.c \
krb5.c \
ldap.c \
llist.c \
@@ -1422,7 +1464,6 @@ LIB_CFILES = \
multi.c \
multi_ev.c \
netrc.c \
- nonblock.c \
noproxy.c \
openldap.c \
parsedate.c \
@@ -1452,18 +1493,17 @@ LIB_CFILES = \
strdup.c \
strequal.c \
strerror.c \
- strparse.c \
system_win32.c \
telnet.c \
tftp.c \
- timediff.c \
- timeval.c \
transfer.c \
+ uint-bset.c \
+ uint-hash.c \
+ uint-spbset.c \
+ uint-table.c \
url.c \
urlapi.c \
version.c \
- version_win32.c \
- warnless.c \
ws.c
LIB_HFILES = \
@@ -1485,7 +1525,6 @@ LIB_HFILES = \
content_encoding.h \
cookie.h \
curl_addrinfo.h \
- curl_base64.h \
curl_ctype.h \
curl_des.h \
curl_endian.h \
@@ -1500,7 +1539,6 @@ LIB_HFILES = \
curl_md5.h \
curl_memory.h \
curl_memrchr.h \
- curl_multibyte.h \
curl_ntlm_core.h \
curl_printf.h \
curl_range.h \
@@ -1513,17 +1551,16 @@ LIB_HFILES = \
curl_sspi.h \
curl_threads.h \
curl_trc.h \
- curlx.h \
cw-out.h \
cw-pause.h \
dict.h \
doh.h \
- dynbuf.h \
dynhds.h \
easy_lock.h \
easyif.h \
easyoptions.h \
escape.h \
+ fake_addrinfo.h \
file.h \
fileinfo.h \
fopen.h \
@@ -1534,7 +1571,6 @@ LIB_HFILES = \
getinfo.h \
gopher.h \
hash.h \
- hash_offt.h \
headers.h \
hostip.h \
hsts.h \
@@ -1552,7 +1588,6 @@ LIB_HFILES = \
if2ip.h \
imap.h \
inet_ntop.h \
- inet_pton.h \
llist.h \
macos.h \
memdebug.h \
@@ -1562,7 +1597,6 @@ LIB_HFILES = \
multi_ev.h \
multiif.h \
netrc.h \
- nonblock.h \
noproxy.h \
parsedate.h \
pingpong.h \
@@ -1592,32 +1626,32 @@ LIB_HFILES = \
strcase.h \
strdup.h \
strerror.h \
- strparse.h \
system_win32.h \
telnet.h \
tftp.h \
- timediff.h \
- timeval.h \
transfer.h \
+ uint-bset.h \
+ uint-hash.h \
+ uint-spbset.h \
+ uint-table.h \
url.h \
urlapi-int.h \
urldata.h \
- version_win32.h \
- warnless.h \
ws.h
LIB_RCFILES = libcurl.rc
CSOURCES = $(LIB_CFILES) $(LIB_VAUTH_CFILES) $(LIB_VTLS_CFILES) \
- $(LIB_VQUIC_CFILES) $(LIB_VSSH_CFILES) $(am__append_3) \
- $(am__append_4)
+ $(LIB_VQUIC_CFILES) $(LIB_VSSH_CFILES) $(LIB_CURLX_CFILES) \
+ $(am__append_3) $(am__append_4)
HHEADERS = $(LIB_HFILES) $(LIB_VAUTH_HFILES) $(LIB_VTLS_HFILES) \
- $(LIB_VQUIC_HFILES) $(LIB_VSSH_HFILES)
+ $(LIB_VQUIC_HFILES) $(LIB_VSSH_HFILES) $(LIB_CURLX_HFILES)
# Keep these separate to avoid duplicate definitions when linking libtests
# in static mode.
-@USE_UNITY_TRUE@curl_EXCLUDE = curl_threads.c timediff.c warnless.c \
-@USE_UNITY_TRUE@ $(am__append_5) $(am__append_6)
+@USE_UNITY_TRUE@curl_EXCLUDE = curl_threads.c curlx/timediff.c \
+@USE_UNITY_TRUE@ curlx/warnless.c $(am__append_5) \
+@USE_UNITY_TRUE@ $(am__append_6)
@USE_UNITY_TRUE@nodist_libcurl_la_SOURCES = libcurl_unity.c
@USE_UNITY_FALSE@libcurl_la_SOURCES = $(CSOURCES) $(HHEADERS) \
@USE_UNITY_FALSE@ $(am__append_13)
@@ -1847,6 +1881,34 @@ vssh/libcurl_la-curl_path.lo: vssh/$(am__dirstamp) \
vssh/$(DEPDIR)/$(am__dirstamp)
vssh/libcurl_la-wolfssh.lo: vssh/$(am__dirstamp) \
vssh/$(DEPDIR)/$(am__dirstamp)
+curlx/$(am__dirstamp):
+ @$(MKDIR_P) curlx
+ @: > curlx/$(am__dirstamp)
+curlx/$(DEPDIR)/$(am__dirstamp):
+ @$(MKDIR_P) curlx/$(DEPDIR)
+ @: > curlx/$(DEPDIR)/$(am__dirstamp)
+curlx/libcurl_la-base64.lo: curlx/$(am__dirstamp) \
+ curlx/$(DEPDIR)/$(am__dirstamp)
+curlx/libcurl_la-dynbuf.lo: curlx/$(am__dirstamp) \
+ curlx/$(DEPDIR)/$(am__dirstamp)
+curlx/libcurl_la-inet_pton.lo: curlx/$(am__dirstamp) \
+ curlx/$(DEPDIR)/$(am__dirstamp)
+curlx/libcurl_la-multibyte.lo: curlx/$(am__dirstamp) \
+ curlx/$(DEPDIR)/$(am__dirstamp)
+curlx/libcurl_la-nonblock.lo: curlx/$(am__dirstamp) \
+ curlx/$(DEPDIR)/$(am__dirstamp)
+curlx/libcurl_la-strparse.lo: curlx/$(am__dirstamp) \
+ curlx/$(DEPDIR)/$(am__dirstamp)
+curlx/libcurl_la-timediff.lo: curlx/$(am__dirstamp) \
+ curlx/$(DEPDIR)/$(am__dirstamp)
+curlx/libcurl_la-timeval.lo: curlx/$(am__dirstamp) \
+ curlx/$(DEPDIR)/$(am__dirstamp)
+curlx/libcurl_la-version_win32.lo: curlx/$(am__dirstamp) \
+ curlx/$(DEPDIR)/$(am__dirstamp)
+curlx/libcurl_la-warnless.lo: curlx/$(am__dirstamp) \
+ curlx/$(DEPDIR)/$(am__dirstamp)
+curlx/libcurl_la-winapi.lo: curlx/$(am__dirstamp) \
+ curlx/$(DEPDIR)/$(am__dirstamp)
libcurl.la: $(libcurl_la_OBJECTS) $(libcurl_la_DEPENDENCIES) $(EXTRA_libcurl_la_DEPENDENCIES)
$(AM_V_CCLD)$(libcurl_la_LINK) -rpath $(libdir) $(libcurl_la_OBJECTS) $(libcurl_la_LIBADD) $(LIBS)
@@ -1930,12 +1992,36 @@ vssh/libcurlu_la-curl_path.lo: vssh/$(am__dirstamp) \
vssh/$(DEPDIR)/$(am__dirstamp)
vssh/libcurlu_la-wolfssh.lo: vssh/$(am__dirstamp) \
vssh/$(DEPDIR)/$(am__dirstamp)
+curlx/libcurlu_la-base64.lo: curlx/$(am__dirstamp) \
+ curlx/$(DEPDIR)/$(am__dirstamp)
+curlx/libcurlu_la-dynbuf.lo: curlx/$(am__dirstamp) \
+ curlx/$(DEPDIR)/$(am__dirstamp)
+curlx/libcurlu_la-inet_pton.lo: curlx/$(am__dirstamp) \
+ curlx/$(DEPDIR)/$(am__dirstamp)
+curlx/libcurlu_la-multibyte.lo: curlx/$(am__dirstamp) \
+ curlx/$(DEPDIR)/$(am__dirstamp)
+curlx/libcurlu_la-nonblock.lo: curlx/$(am__dirstamp) \
+ curlx/$(DEPDIR)/$(am__dirstamp)
+curlx/libcurlu_la-strparse.lo: curlx/$(am__dirstamp) \
+ curlx/$(DEPDIR)/$(am__dirstamp)
+curlx/libcurlu_la-timediff.lo: curlx/$(am__dirstamp) \
+ curlx/$(DEPDIR)/$(am__dirstamp)
+curlx/libcurlu_la-timeval.lo: curlx/$(am__dirstamp) \
+ curlx/$(DEPDIR)/$(am__dirstamp)
+curlx/libcurlu_la-version_win32.lo: curlx/$(am__dirstamp) \
+ curlx/$(DEPDIR)/$(am__dirstamp)
+curlx/libcurlu_la-warnless.lo: curlx/$(am__dirstamp) \
+ curlx/$(DEPDIR)/$(am__dirstamp)
+curlx/libcurlu_la-winapi.lo: curlx/$(am__dirstamp) \
+ curlx/$(DEPDIR)/$(am__dirstamp)
libcurlu.la: $(libcurlu_la_OBJECTS) $(libcurlu_la_DEPENDENCIES) $(EXTRA_libcurlu_la_DEPENDENCIES)
$(AM_V_CCLD)$(libcurlu_la_LINK) $(am_libcurlu_la_rpath) $(libcurlu_la_OBJECTS) $(libcurlu_la_LIBADD) $(LIBS)
mostlyclean-compile:
-rm -f *.$(OBJEXT)
+ -rm -f curlx/*.$(OBJEXT)
+ -rm -f curlx/*.lo
-rm -f vauth/*.$(OBJEXT)
-rm -f vauth/*.lo
-rm -f vquic/*.$(OBJEXT)
@@ -1951,8 +2037,8 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-altsvc.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-amigaos.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-asyn-ares.Plo@am__quote@ # am--include-marker
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-asyn-thread.Plo@am__quote@ # am--include-marker
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-base64.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-asyn-base.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-asyn-thrdd.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-bufq.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-bufref.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-cf-h1-proxy.Plo@am__quote@ # am--include-marker
@@ -1974,7 +2060,6 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-curl_gethostname.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-curl_gssapi.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-curl_memrchr.Plo@am__quote@ # am--include-marker
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-curl_multibyte.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-curl_ntlm_core.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-curl_range.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-curl_rtmp.Plo@am__quote@ # am--include-marker
@@ -1988,12 +2073,12 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-dict.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-dllmain.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-doh.Plo@am__quote@ # am--include-marker
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-dynbuf.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-dynhds.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-easy.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-easygetopt.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-easyoptions.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-escape.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-fake_addrinfo.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-file.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-fileinfo.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-fopen.Plo@am__quote@ # am--include-marker
@@ -2004,14 +2089,11 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-getinfo.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-gopher.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-hash.Plo@am__quote@ # am--include-marker
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-hash_offt.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-headers.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-hmac.Plo@am__quote@ # am--include-marker
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-hostasyn.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-hostip.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-hostip4.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-hostip6.Plo@am__quote@ # am--include-marker
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-hostsyn.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-hsts.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-http.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-http1.Plo@am__quote@ # am--include-marker
@@ -2027,7 +2109,6 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-if2ip.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-imap.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-inet_ntop.Plo@am__quote@ # am--include-marker
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-inet_pton.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-krb5.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-ldap.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-libcurl_unity.Plo@am__quote@ # am--include-marker
@@ -2042,7 +2123,6 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-multi.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-multi_ev.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-netrc.Plo@am__quote@ # am--include-marker
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-nonblock.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-noproxy.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-openldap.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-parsedate.Plo@am__quote@ # am--include-marker
@@ -2072,24 +2152,23 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-strdup.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-strequal.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-strerror.Plo@am__quote@ # am--include-marker
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-strparse.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-system_win32.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-telnet.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-tftp.Plo@am__quote@ # am--include-marker
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-timediff.Plo@am__quote@ # am--include-marker
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-timeval.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-transfer.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-uint-bset.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-uint-hash.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-uint-spbset.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-uint-table.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-url.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-urlapi.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-version.Plo@am__quote@ # am--include-marker
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-version_win32.Plo@am__quote@ # am--include-marker
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-warnless.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurl_la-ws.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-altsvc.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-amigaos.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-asyn-ares.Plo@am__quote@ # am--include-marker
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-asyn-thread.Plo@am__quote@ # am--include-marker
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-base64.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-asyn-base.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-asyn-thrdd.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-bufq.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-bufref.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-cf-h1-proxy.Plo@am__quote@ # am--include-marker
@@ -2111,7 +2190,6 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-curl_gethostname.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-curl_gssapi.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-curl_memrchr.Plo@am__quote@ # am--include-marker
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-curl_multibyte.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-curl_ntlm_core.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-curl_range.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-curl_rtmp.Plo@am__quote@ # am--include-marker
@@ -2125,12 +2203,12 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-dict.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-dllmain.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-doh.Plo@am__quote@ # am--include-marker
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-dynbuf.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-dynhds.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-easy.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-easygetopt.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-easyoptions.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-escape.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-fake_addrinfo.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-file.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-fileinfo.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-fopen.Plo@am__quote@ # am--include-marker
@@ -2141,14 +2219,11 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-getinfo.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-gopher.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-hash.Plo@am__quote@ # am--include-marker
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-hash_offt.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-headers.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-hmac.Plo@am__quote@ # am--include-marker
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-hostasyn.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-hostip.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-hostip4.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-hostip6.Plo@am__quote@ # am--include-marker
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-hostsyn.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-hsts.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-http.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-http1.Plo@am__quote@ # am--include-marker
@@ -2164,7 +2239,6 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-if2ip.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-imap.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-inet_ntop.Plo@am__quote@ # am--include-marker
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-inet_pton.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-krb5.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-ldap.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-libcurl_unity.Plo@am__quote@ # am--include-marker
@@ -2179,7 +2253,6 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-multi.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-multi_ev.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-netrc.Plo@am__quote@ # am--include-marker
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-nonblock.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-noproxy.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-openldap.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-parsedate.Plo@am__quote@ # am--include-marker
@@ -2209,19 +2282,40 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-strdup.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-strequal.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-strerror.Plo@am__quote@ # am--include-marker
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-strparse.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-system_win32.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-telnet.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-tftp.Plo@am__quote@ # am--include-marker
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-timediff.Plo@am__quote@ # am--include-marker
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-timeval.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-transfer.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-uint-bset.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-uint-hash.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-uint-spbset.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-uint-table.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-url.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-urlapi.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-version.Plo@am__quote@ # am--include-marker
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-version_win32.Plo@am__quote@ # am--include-marker
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-warnless.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcurlu_la-ws.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@curlx/$(DEPDIR)/libcurl_la-base64.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@curlx/$(DEPDIR)/libcurl_la-dynbuf.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@curlx/$(DEPDIR)/libcurl_la-inet_pton.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@curlx/$(DEPDIR)/libcurl_la-multibyte.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@curlx/$(DEPDIR)/libcurl_la-nonblock.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@curlx/$(DEPDIR)/libcurl_la-strparse.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@curlx/$(DEPDIR)/libcurl_la-timediff.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@curlx/$(DEPDIR)/libcurl_la-timeval.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@curlx/$(DEPDIR)/libcurl_la-version_win32.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@curlx/$(DEPDIR)/libcurl_la-warnless.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@curlx/$(DEPDIR)/libcurl_la-winapi.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@curlx/$(DEPDIR)/libcurlu_la-base64.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@curlx/$(DEPDIR)/libcurlu_la-dynbuf.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@curlx/$(DEPDIR)/libcurlu_la-inet_pton.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@curlx/$(DEPDIR)/libcurlu_la-multibyte.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@curlx/$(DEPDIR)/libcurlu_la-nonblock.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@curlx/$(DEPDIR)/libcurlu_la-strparse.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@curlx/$(DEPDIR)/libcurlu_la-timediff.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@curlx/$(DEPDIR)/libcurlu_la-timeval.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@curlx/$(DEPDIR)/libcurlu_la-version_win32.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@curlx/$(DEPDIR)/libcurlu_la-warnless.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@curlx/$(DEPDIR)/libcurlu_la-winapi.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@vauth/$(DEPDIR)/libcurl_la-cleartext.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@vauth/$(DEPDIR)/libcurl_la-cram.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@vauth/$(DEPDIR)/libcurl_la-digest.Plo@am__quote@ # am--include-marker
@@ -2354,19 +2448,19 @@ libcurl_la-asyn-ares.lo: asyn-ares.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-asyn-ares.lo `test -f 'asyn-ares.c' || echo '$(srcdir)/'`asyn-ares.c
-libcurl_la-asyn-thread.lo: asyn-thread.c
-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-asyn-thread.lo -MD -MP -MF $(DEPDIR)/libcurl_la-asyn-thread.Tpo -c -o libcurl_la-asyn-thread.lo `test -f 'asyn-thread.c' || echo '$(srcdir)/'`asyn-thread.c
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-asyn-thread.Tpo $(DEPDIR)/libcurl_la-asyn-thread.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='asyn-thread.c' object='libcurl_la-asyn-thread.lo' libtool=yes @AMDEPBACKSLASH@
+libcurl_la-asyn-base.lo: asyn-base.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-asyn-base.lo -MD -MP -MF $(DEPDIR)/libcurl_la-asyn-base.Tpo -c -o libcurl_la-asyn-base.lo `test -f 'asyn-base.c' || echo '$(srcdir)/'`asyn-base.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-asyn-base.Tpo $(DEPDIR)/libcurl_la-asyn-base.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='asyn-base.c' object='libcurl_la-asyn-base.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-asyn-thread.lo `test -f 'asyn-thread.c' || echo '$(srcdir)/'`asyn-thread.c
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-asyn-base.lo `test -f 'asyn-base.c' || echo '$(srcdir)/'`asyn-base.c
-libcurl_la-base64.lo: base64.c
-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-base64.lo -MD -MP -MF $(DEPDIR)/libcurl_la-base64.Tpo -c -o libcurl_la-base64.lo `test -f 'base64.c' || echo '$(srcdir)/'`base64.c
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-base64.Tpo $(DEPDIR)/libcurl_la-base64.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='base64.c' object='libcurl_la-base64.lo' libtool=yes @AMDEPBACKSLASH@
+libcurl_la-asyn-thrdd.lo: asyn-thrdd.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-asyn-thrdd.lo -MD -MP -MF $(DEPDIR)/libcurl_la-asyn-thrdd.Tpo -c -o libcurl_la-asyn-thrdd.lo `test -f 'asyn-thrdd.c' || echo '$(srcdir)/'`asyn-thrdd.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-asyn-thrdd.Tpo $(DEPDIR)/libcurl_la-asyn-thrdd.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='asyn-thrdd.c' object='libcurl_la-asyn-thrdd.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-base64.lo `test -f 'base64.c' || echo '$(srcdir)/'`base64.c
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-asyn-thrdd.lo `test -f 'asyn-thrdd.c' || echo '$(srcdir)/'`asyn-thrdd.c
libcurl_la-bufq.lo: bufq.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-bufq.lo -MD -MP -MF $(DEPDIR)/libcurl_la-bufq.Tpo -c -o libcurl_la-bufq.lo `test -f 'bufq.c' || echo '$(srcdir)/'`bufq.c
@@ -2431,13 +2525,6 @@ libcurl_la-conncache.lo: conncache.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-conncache.lo `test -f 'conncache.c' || echo '$(srcdir)/'`conncache.c
-libcurl_la-cshutdn.lo: cshutdn.c
-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-cshutdn.lo -MD -MP -MF $(DEPDIR)/libcurl_la-cshutdn.Tpo -c -o libcurl_la-cshutdn.lo `test -f 'cshutdn.c' || echo '$(srcdir)/'`cshutdn.c
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-cshutdn.Tpo $(DEPDIR)/libcurl_la-cshutdn.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cshutdn.c' object='libcurl_la-cshutdn.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-cshutdn.lo `test -f 'cshutdn.c' || echo '$(srcdir)/'`cshutdn.c
-
libcurl_la-connect.lo: connect.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-connect.lo -MD -MP -MF $(DEPDIR)/libcurl_la-connect.Tpo -c -o libcurl_la-connect.lo `test -f 'connect.c' || echo '$(srcdir)/'`connect.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-connect.Tpo $(DEPDIR)/libcurl_la-connect.Plo
@@ -2459,6 +2546,13 @@ libcurl_la-cookie.lo: cookie.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-cookie.lo `test -f 'cookie.c' || echo '$(srcdir)/'`cookie.c
+libcurl_la-cshutdn.lo: cshutdn.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-cshutdn.lo -MD -MP -MF $(DEPDIR)/libcurl_la-cshutdn.Tpo -c -o libcurl_la-cshutdn.lo `test -f 'cshutdn.c' || echo '$(srcdir)/'`cshutdn.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-cshutdn.Tpo $(DEPDIR)/libcurl_la-cshutdn.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cshutdn.c' object='libcurl_la-cshutdn.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-cshutdn.lo `test -f 'cshutdn.c' || echo '$(srcdir)/'`cshutdn.c
+
libcurl_la-curl_addrinfo.lo: curl_addrinfo.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-curl_addrinfo.lo -MD -MP -MF $(DEPDIR)/libcurl_la-curl_addrinfo.Tpo -c -o libcurl_la-curl_addrinfo.lo `test -f 'curl_addrinfo.c' || echo '$(srcdir)/'`curl_addrinfo.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-curl_addrinfo.Tpo $(DEPDIR)/libcurl_la-curl_addrinfo.Plo
@@ -2515,13 +2609,6 @@ libcurl_la-curl_memrchr.lo: curl_memrchr.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-curl_memrchr.lo `test -f 'curl_memrchr.c' || echo '$(srcdir)/'`curl_memrchr.c
-libcurl_la-curl_multibyte.lo: curl_multibyte.c
-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-curl_multibyte.lo -MD -MP -MF $(DEPDIR)/libcurl_la-curl_multibyte.Tpo -c -o libcurl_la-curl_multibyte.lo `test -f 'curl_multibyte.c' || echo '$(srcdir)/'`curl_multibyte.c
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-curl_multibyte.Tpo $(DEPDIR)/libcurl_la-curl_multibyte.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='curl_multibyte.c' object='libcurl_la-curl_multibyte.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-curl_multibyte.lo `test -f 'curl_multibyte.c' || echo '$(srcdir)/'`curl_multibyte.c
-
libcurl_la-curl_ntlm_core.lo: curl_ntlm_core.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-curl_ntlm_core.lo -MD -MP -MF $(DEPDIR)/libcurl_la-curl_ntlm_core.Tpo -c -o libcurl_la-curl_ntlm_core.lo `test -f 'curl_ntlm_core.c' || echo '$(srcdir)/'`curl_ntlm_core.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-curl_ntlm_core.Tpo $(DEPDIR)/libcurl_la-curl_ntlm_core.Plo
@@ -2606,13 +2693,6 @@ libcurl_la-doh.lo: doh.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-doh.lo `test -f 'doh.c' || echo '$(srcdir)/'`doh.c
-libcurl_la-dynbuf.lo: dynbuf.c
-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-dynbuf.lo -MD -MP -MF $(DEPDIR)/libcurl_la-dynbuf.Tpo -c -o libcurl_la-dynbuf.lo `test -f 'dynbuf.c' || echo '$(srcdir)/'`dynbuf.c
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-dynbuf.Tpo $(DEPDIR)/libcurl_la-dynbuf.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='dynbuf.c' object='libcurl_la-dynbuf.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-dynbuf.lo `test -f 'dynbuf.c' || echo '$(srcdir)/'`dynbuf.c
-
libcurl_la-dynhds.lo: dynhds.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-dynhds.lo -MD -MP -MF $(DEPDIR)/libcurl_la-dynhds.Tpo -c -o libcurl_la-dynhds.lo `test -f 'dynhds.c' || echo '$(srcdir)/'`dynhds.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-dynhds.Tpo $(DEPDIR)/libcurl_la-dynhds.Plo
@@ -2648,6 +2728,13 @@ libcurl_la-escape.lo: escape.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-escape.lo `test -f 'escape.c' || echo '$(srcdir)/'`escape.c
+libcurl_la-fake_addrinfo.lo: fake_addrinfo.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-fake_addrinfo.lo -MD -MP -MF $(DEPDIR)/libcurl_la-fake_addrinfo.Tpo -c -o libcurl_la-fake_addrinfo.lo `test -f 'fake_addrinfo.c' || echo '$(srcdir)/'`fake_addrinfo.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-fake_addrinfo.Tpo $(DEPDIR)/libcurl_la-fake_addrinfo.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='fake_addrinfo.c' object='libcurl_la-fake_addrinfo.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-fake_addrinfo.lo `test -f 'fake_addrinfo.c' || echo '$(srcdir)/'`fake_addrinfo.c
+
libcurl_la-file.lo: file.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-file.lo -MD -MP -MF $(DEPDIR)/libcurl_la-file.Tpo -c -o libcurl_la-file.lo `test -f 'file.c' || echo '$(srcdir)/'`file.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-file.Tpo $(DEPDIR)/libcurl_la-file.Plo
@@ -2718,13 +2805,6 @@ libcurl_la-hash.lo: hash.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-hash.lo `test -f 'hash.c' || echo '$(srcdir)/'`hash.c
-libcurl_la-hash_offt.lo: hash_offt.c
-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-hash_offt.lo -MD -MP -MF $(DEPDIR)/libcurl_la-hash_offt.Tpo -c -o libcurl_la-hash_offt.lo `test -f 'hash_offt.c' || echo '$(srcdir)/'`hash_offt.c
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-hash_offt.Tpo $(DEPDIR)/libcurl_la-hash_offt.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='hash_offt.c' object='libcurl_la-hash_offt.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-hash_offt.lo `test -f 'hash_offt.c' || echo '$(srcdir)/'`hash_offt.c
-
libcurl_la-headers.lo: headers.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-headers.lo -MD -MP -MF $(DEPDIR)/libcurl_la-headers.Tpo -c -o libcurl_la-headers.lo `test -f 'headers.c' || echo '$(srcdir)/'`headers.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-headers.Tpo $(DEPDIR)/libcurl_la-headers.Plo
@@ -2739,13 +2819,6 @@ libcurl_la-hmac.lo: hmac.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-hmac.lo `test -f 'hmac.c' || echo '$(srcdir)/'`hmac.c
-libcurl_la-hostasyn.lo: hostasyn.c
-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-hostasyn.lo -MD -MP -MF $(DEPDIR)/libcurl_la-hostasyn.Tpo -c -o libcurl_la-hostasyn.lo `test -f 'hostasyn.c' || echo '$(srcdir)/'`hostasyn.c
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-hostasyn.Tpo $(DEPDIR)/libcurl_la-hostasyn.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='hostasyn.c' object='libcurl_la-hostasyn.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-hostasyn.lo `test -f 'hostasyn.c' || echo '$(srcdir)/'`hostasyn.c
-
libcurl_la-hostip.lo: hostip.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-hostip.lo -MD -MP -MF $(DEPDIR)/libcurl_la-hostip.Tpo -c -o libcurl_la-hostip.lo `test -f 'hostip.c' || echo '$(srcdir)/'`hostip.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-hostip.Tpo $(DEPDIR)/libcurl_la-hostip.Plo
@@ -2767,13 +2840,6 @@ libcurl_la-hostip6.lo: hostip6.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-hostip6.lo `test -f 'hostip6.c' || echo '$(srcdir)/'`hostip6.c
-libcurl_la-hostsyn.lo: hostsyn.c
-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-hostsyn.lo -MD -MP -MF $(DEPDIR)/libcurl_la-hostsyn.Tpo -c -o libcurl_la-hostsyn.lo `test -f 'hostsyn.c' || echo '$(srcdir)/'`hostsyn.c
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-hostsyn.Tpo $(DEPDIR)/libcurl_la-hostsyn.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='hostsyn.c' object='libcurl_la-hostsyn.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-hostsyn.lo `test -f 'hostsyn.c' || echo '$(srcdir)/'`hostsyn.c
-
libcurl_la-hsts.lo: hsts.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-hsts.lo -MD -MP -MF $(DEPDIR)/libcurl_la-hsts.Tpo -c -o libcurl_la-hsts.lo `test -f 'hsts.c' || echo '$(srcdir)/'`hsts.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-hsts.Tpo $(DEPDIR)/libcurl_la-hsts.Plo
@@ -2879,13 +2945,6 @@ libcurl_la-inet_ntop.lo: inet_ntop.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-inet_ntop.lo `test -f 'inet_ntop.c' || echo '$(srcdir)/'`inet_ntop.c
-libcurl_la-inet_pton.lo: inet_pton.c
-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-inet_pton.lo -MD -MP -MF $(DEPDIR)/libcurl_la-inet_pton.Tpo -c -o libcurl_la-inet_pton.lo `test -f 'inet_pton.c' || echo '$(srcdir)/'`inet_pton.c
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-inet_pton.Tpo $(DEPDIR)/libcurl_la-inet_pton.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='inet_pton.c' object='libcurl_la-inet_pton.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-inet_pton.lo `test -f 'inet_pton.c' || echo '$(srcdir)/'`inet_pton.c
-
libcurl_la-krb5.lo: krb5.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-krb5.lo -MD -MP -MF $(DEPDIR)/libcurl_la-krb5.Tpo -c -o libcurl_la-krb5.lo `test -f 'krb5.c' || echo '$(srcdir)/'`krb5.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-krb5.Tpo $(DEPDIR)/libcurl_la-krb5.Plo
@@ -2977,13 +3036,6 @@ libcurl_la-netrc.lo: netrc.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-netrc.lo `test -f 'netrc.c' || echo '$(srcdir)/'`netrc.c
-libcurl_la-nonblock.lo: nonblock.c
-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-nonblock.lo -MD -MP -MF $(DEPDIR)/libcurl_la-nonblock.Tpo -c -o libcurl_la-nonblock.lo `test -f 'nonblock.c' || echo '$(srcdir)/'`nonblock.c
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-nonblock.Tpo $(DEPDIR)/libcurl_la-nonblock.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nonblock.c' object='libcurl_la-nonblock.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-nonblock.lo `test -f 'nonblock.c' || echo '$(srcdir)/'`nonblock.c
-
libcurl_la-noproxy.lo: noproxy.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-noproxy.lo -MD -MP -MF $(DEPDIR)/libcurl_la-noproxy.Tpo -c -o libcurl_la-noproxy.lo `test -f 'noproxy.c' || echo '$(srcdir)/'`noproxy.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-noproxy.Tpo $(DEPDIR)/libcurl_la-noproxy.Plo
@@ -3187,13 +3239,6 @@ libcurl_la-strerror.lo: strerror.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-strerror.lo `test -f 'strerror.c' || echo '$(srcdir)/'`strerror.c
-libcurl_la-strparse.lo: strparse.c
-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-strparse.lo -MD -MP -MF $(DEPDIR)/libcurl_la-strparse.Tpo -c -o libcurl_la-strparse.lo `test -f 'strparse.c' || echo '$(srcdir)/'`strparse.c
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-strparse.Tpo $(DEPDIR)/libcurl_la-strparse.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='strparse.c' object='libcurl_la-strparse.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-strparse.lo `test -f 'strparse.c' || echo '$(srcdir)/'`strparse.c
-
libcurl_la-system_win32.lo: system_win32.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-system_win32.lo -MD -MP -MF $(DEPDIR)/libcurl_la-system_win32.Tpo -c -o libcurl_la-system_win32.lo `test -f 'system_win32.c' || echo '$(srcdir)/'`system_win32.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-system_win32.Tpo $(DEPDIR)/libcurl_la-system_win32.Plo
@@ -3215,20 +3260,6 @@ libcurl_la-tftp.lo: tftp.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-tftp.lo `test -f 'tftp.c' || echo '$(srcdir)/'`tftp.c
-libcurl_la-timediff.lo: timediff.c
-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-timediff.lo -MD -MP -MF $(DEPDIR)/libcurl_la-timediff.Tpo -c -o libcurl_la-timediff.lo `test -f 'timediff.c' || echo '$(srcdir)/'`timediff.c
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-timediff.Tpo $(DEPDIR)/libcurl_la-timediff.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='timediff.c' object='libcurl_la-timediff.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-timediff.lo `test -f 'timediff.c' || echo '$(srcdir)/'`timediff.c
-
-libcurl_la-timeval.lo: timeval.c
-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-timeval.lo -MD -MP -MF $(DEPDIR)/libcurl_la-timeval.Tpo -c -o libcurl_la-timeval.lo `test -f 'timeval.c' || echo '$(srcdir)/'`timeval.c
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-timeval.Tpo $(DEPDIR)/libcurl_la-timeval.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='timeval.c' object='libcurl_la-timeval.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-timeval.lo `test -f 'timeval.c' || echo '$(srcdir)/'`timeval.c
-
libcurl_la-transfer.lo: transfer.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-transfer.lo -MD -MP -MF $(DEPDIR)/libcurl_la-transfer.Tpo -c -o libcurl_la-transfer.lo `test -f 'transfer.c' || echo '$(srcdir)/'`transfer.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-transfer.Tpo $(DEPDIR)/libcurl_la-transfer.Plo
@@ -3236,6 +3267,34 @@ libcurl_la-transfer.lo: transfer.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-transfer.lo `test -f 'transfer.c' || echo '$(srcdir)/'`transfer.c
+libcurl_la-uint-bset.lo: uint-bset.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-uint-bset.lo -MD -MP -MF $(DEPDIR)/libcurl_la-uint-bset.Tpo -c -o libcurl_la-uint-bset.lo `test -f 'uint-bset.c' || echo '$(srcdir)/'`uint-bset.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-uint-bset.Tpo $(DEPDIR)/libcurl_la-uint-bset.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='uint-bset.c' object='libcurl_la-uint-bset.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-uint-bset.lo `test -f 'uint-bset.c' || echo '$(srcdir)/'`uint-bset.c
+
+libcurl_la-uint-hash.lo: uint-hash.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-uint-hash.lo -MD -MP -MF $(DEPDIR)/libcurl_la-uint-hash.Tpo -c -o libcurl_la-uint-hash.lo `test -f 'uint-hash.c' || echo '$(srcdir)/'`uint-hash.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-uint-hash.Tpo $(DEPDIR)/libcurl_la-uint-hash.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='uint-hash.c' object='libcurl_la-uint-hash.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-uint-hash.lo `test -f 'uint-hash.c' || echo '$(srcdir)/'`uint-hash.c
+
+libcurl_la-uint-spbset.lo: uint-spbset.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-uint-spbset.lo -MD -MP -MF $(DEPDIR)/libcurl_la-uint-spbset.Tpo -c -o libcurl_la-uint-spbset.lo `test -f 'uint-spbset.c' || echo '$(srcdir)/'`uint-spbset.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-uint-spbset.Tpo $(DEPDIR)/libcurl_la-uint-spbset.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='uint-spbset.c' object='libcurl_la-uint-spbset.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-uint-spbset.lo `test -f 'uint-spbset.c' || echo '$(srcdir)/'`uint-spbset.c
+
+libcurl_la-uint-table.lo: uint-table.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-uint-table.lo -MD -MP -MF $(DEPDIR)/libcurl_la-uint-table.Tpo -c -o libcurl_la-uint-table.lo `test -f 'uint-table.c' || echo '$(srcdir)/'`uint-table.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-uint-table.Tpo $(DEPDIR)/libcurl_la-uint-table.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='uint-table.c' object='libcurl_la-uint-table.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-uint-table.lo `test -f 'uint-table.c' || echo '$(srcdir)/'`uint-table.c
+
libcurl_la-url.lo: url.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-url.lo -MD -MP -MF $(DEPDIR)/libcurl_la-url.Tpo -c -o libcurl_la-url.lo `test -f 'url.c' || echo '$(srcdir)/'`url.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-url.Tpo $(DEPDIR)/libcurl_la-url.Plo
@@ -3257,20 +3316,6 @@ libcurl_la-version.lo: version.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-version.lo `test -f 'version.c' || echo '$(srcdir)/'`version.c
-libcurl_la-version_win32.lo: version_win32.c
-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-version_win32.lo -MD -MP -MF $(DEPDIR)/libcurl_la-version_win32.Tpo -c -o libcurl_la-version_win32.lo `test -f 'version_win32.c' || echo '$(srcdir)/'`version_win32.c
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-version_win32.Tpo $(DEPDIR)/libcurl_la-version_win32.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='version_win32.c' object='libcurl_la-version_win32.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-version_win32.lo `test -f 'version_win32.c' || echo '$(srcdir)/'`version_win32.c
-
-libcurl_la-warnless.lo: warnless.c
-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-warnless.lo -MD -MP -MF $(DEPDIR)/libcurl_la-warnless.Tpo -c -o libcurl_la-warnless.lo `test -f 'warnless.c' || echo '$(srcdir)/'`warnless.c
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-warnless.Tpo $(DEPDIR)/libcurl_la-warnless.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='warnless.c' object='libcurl_la-warnless.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o libcurl_la-warnless.lo `test -f 'warnless.c' || echo '$(srcdir)/'`warnless.c
-
libcurl_la-ws.lo: ws.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-ws.lo -MD -MP -MF $(DEPDIR)/libcurl_la-ws.Tpo -c -o libcurl_la-ws.lo `test -f 'ws.c' || echo '$(srcdir)/'`ws.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-ws.Tpo $(DEPDIR)/libcurl_la-ws.Plo
@@ -3558,6 +3603,83 @@ vssh/libcurl_la-wolfssh.lo: vssh/wolfssh.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o vssh/libcurl_la-wolfssh.lo `test -f 'vssh/wolfssh.c' || echo '$(srcdir)/'`vssh/wolfssh.c
+curlx/libcurl_la-base64.lo: curlx/base64.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT curlx/libcurl_la-base64.lo -MD -MP -MF curlx/$(DEPDIR)/libcurl_la-base64.Tpo -c -o curlx/libcurl_la-base64.lo `test -f 'curlx/base64.c' || echo '$(srcdir)/'`curlx/base64.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) curlx/$(DEPDIR)/libcurl_la-base64.Tpo curlx/$(DEPDIR)/libcurl_la-base64.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='curlx/base64.c' object='curlx/libcurl_la-base64.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o curlx/libcurl_la-base64.lo `test -f 'curlx/base64.c' || echo '$(srcdir)/'`curlx/base64.c
+
+curlx/libcurl_la-dynbuf.lo: curlx/dynbuf.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT curlx/libcurl_la-dynbuf.lo -MD -MP -MF curlx/$(DEPDIR)/libcurl_la-dynbuf.Tpo -c -o curlx/libcurl_la-dynbuf.lo `test -f 'curlx/dynbuf.c' || echo '$(srcdir)/'`curlx/dynbuf.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) curlx/$(DEPDIR)/libcurl_la-dynbuf.Tpo curlx/$(DEPDIR)/libcurl_la-dynbuf.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='curlx/dynbuf.c' object='curlx/libcurl_la-dynbuf.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o curlx/libcurl_la-dynbuf.lo `test -f 'curlx/dynbuf.c' || echo '$(srcdir)/'`curlx/dynbuf.c
+
+curlx/libcurl_la-inet_pton.lo: curlx/inet_pton.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT curlx/libcurl_la-inet_pton.lo -MD -MP -MF curlx/$(DEPDIR)/libcurl_la-inet_pton.Tpo -c -o curlx/libcurl_la-inet_pton.lo `test -f 'curlx/inet_pton.c' || echo '$(srcdir)/'`curlx/inet_pton.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) curlx/$(DEPDIR)/libcurl_la-inet_pton.Tpo curlx/$(DEPDIR)/libcurl_la-inet_pton.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='curlx/inet_pton.c' object='curlx/libcurl_la-inet_pton.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o curlx/libcurl_la-inet_pton.lo `test -f 'curlx/inet_pton.c' || echo '$(srcdir)/'`curlx/inet_pton.c
+
+curlx/libcurl_la-multibyte.lo: curlx/multibyte.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT curlx/libcurl_la-multibyte.lo -MD -MP -MF curlx/$(DEPDIR)/libcurl_la-multibyte.Tpo -c -o curlx/libcurl_la-multibyte.lo `test -f 'curlx/multibyte.c' || echo '$(srcdir)/'`curlx/multibyte.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) curlx/$(DEPDIR)/libcurl_la-multibyte.Tpo curlx/$(DEPDIR)/libcurl_la-multibyte.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='curlx/multibyte.c' object='curlx/libcurl_la-multibyte.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o curlx/libcurl_la-multibyte.lo `test -f 'curlx/multibyte.c' || echo '$(srcdir)/'`curlx/multibyte.c
+
+curlx/libcurl_la-nonblock.lo: curlx/nonblock.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT curlx/libcurl_la-nonblock.lo -MD -MP -MF curlx/$(DEPDIR)/libcurl_la-nonblock.Tpo -c -o curlx/libcurl_la-nonblock.lo `test -f 'curlx/nonblock.c' || echo '$(srcdir)/'`curlx/nonblock.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) curlx/$(DEPDIR)/libcurl_la-nonblock.Tpo curlx/$(DEPDIR)/libcurl_la-nonblock.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='curlx/nonblock.c' object='curlx/libcurl_la-nonblock.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o curlx/libcurl_la-nonblock.lo `test -f 'curlx/nonblock.c' || echo '$(srcdir)/'`curlx/nonblock.c
+
+curlx/libcurl_la-strparse.lo: curlx/strparse.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT curlx/libcurl_la-strparse.lo -MD -MP -MF curlx/$(DEPDIR)/libcurl_la-strparse.Tpo -c -o curlx/libcurl_la-strparse.lo `test -f 'curlx/strparse.c' || echo '$(srcdir)/'`curlx/strparse.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) curlx/$(DEPDIR)/libcurl_la-strparse.Tpo curlx/$(DEPDIR)/libcurl_la-strparse.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='curlx/strparse.c' object='curlx/libcurl_la-strparse.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o curlx/libcurl_la-strparse.lo `test -f 'curlx/strparse.c' || echo '$(srcdir)/'`curlx/strparse.c
+
+curlx/libcurl_la-timediff.lo: curlx/timediff.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT curlx/libcurl_la-timediff.lo -MD -MP -MF curlx/$(DEPDIR)/libcurl_la-timediff.Tpo -c -o curlx/libcurl_la-timediff.lo `test -f 'curlx/timediff.c' || echo '$(srcdir)/'`curlx/timediff.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) curlx/$(DEPDIR)/libcurl_la-timediff.Tpo curlx/$(DEPDIR)/libcurl_la-timediff.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='curlx/timediff.c' object='curlx/libcurl_la-timediff.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o curlx/libcurl_la-timediff.lo `test -f 'curlx/timediff.c' || echo '$(srcdir)/'`curlx/timediff.c
+
+curlx/libcurl_la-timeval.lo: curlx/timeval.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT curlx/libcurl_la-timeval.lo -MD -MP -MF curlx/$(DEPDIR)/libcurl_la-timeval.Tpo -c -o curlx/libcurl_la-timeval.lo `test -f 'curlx/timeval.c' || echo '$(srcdir)/'`curlx/timeval.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) curlx/$(DEPDIR)/libcurl_la-timeval.Tpo curlx/$(DEPDIR)/libcurl_la-timeval.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='curlx/timeval.c' object='curlx/libcurl_la-timeval.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o curlx/libcurl_la-timeval.lo `test -f 'curlx/timeval.c' || echo '$(srcdir)/'`curlx/timeval.c
+
+curlx/libcurl_la-version_win32.lo: curlx/version_win32.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT curlx/libcurl_la-version_win32.lo -MD -MP -MF curlx/$(DEPDIR)/libcurl_la-version_win32.Tpo -c -o curlx/libcurl_la-version_win32.lo `test -f 'curlx/version_win32.c' || echo '$(srcdir)/'`curlx/version_win32.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) curlx/$(DEPDIR)/libcurl_la-version_win32.Tpo curlx/$(DEPDIR)/libcurl_la-version_win32.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='curlx/version_win32.c' object='curlx/libcurl_la-version_win32.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o curlx/libcurl_la-version_win32.lo `test -f 'curlx/version_win32.c' || echo '$(srcdir)/'`curlx/version_win32.c
+
+curlx/libcurl_la-warnless.lo: curlx/warnless.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT curlx/libcurl_la-warnless.lo -MD -MP -MF curlx/$(DEPDIR)/libcurl_la-warnless.Tpo -c -o curlx/libcurl_la-warnless.lo `test -f 'curlx/warnless.c' || echo '$(srcdir)/'`curlx/warnless.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) curlx/$(DEPDIR)/libcurl_la-warnless.Tpo curlx/$(DEPDIR)/libcurl_la-warnless.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='curlx/warnless.c' object='curlx/libcurl_la-warnless.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o curlx/libcurl_la-warnless.lo `test -f 'curlx/warnless.c' || echo '$(srcdir)/'`curlx/warnless.c
+
+curlx/libcurl_la-winapi.lo: curlx/winapi.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT curlx/libcurl_la-winapi.lo -MD -MP -MF curlx/$(DEPDIR)/libcurl_la-winapi.Tpo -c -o curlx/libcurl_la-winapi.lo `test -f 'curlx/winapi.c' || echo '$(srcdir)/'`curlx/winapi.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) curlx/$(DEPDIR)/libcurl_la-winapi.Tpo curlx/$(DEPDIR)/libcurl_la-winapi.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='curlx/winapi.c' object='curlx/libcurl_la-winapi.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -c -o curlx/libcurl_la-winapi.lo `test -f 'curlx/winapi.c' || echo '$(srcdir)/'`curlx/winapi.c
+
libcurl_la-dllmain.lo: dllmain.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurl_la_CPPFLAGS) $(CPPFLAGS) $(libcurl_la_CFLAGS) $(CFLAGS) -MT libcurl_la-dllmain.lo -MD -MP -MF $(DEPDIR)/libcurl_la-dllmain.Tpo -c -o libcurl_la-dllmain.lo `test -f 'dllmain.c' || echo '$(srcdir)/'`dllmain.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurl_la-dllmain.Tpo $(DEPDIR)/libcurl_la-dllmain.Plo
@@ -3593,19 +3715,19 @@ libcurlu_la-asyn-ares.lo: asyn-ares.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-asyn-ares.lo `test -f 'asyn-ares.c' || echo '$(srcdir)/'`asyn-ares.c
-libcurlu_la-asyn-thread.lo: asyn-thread.c
-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-asyn-thread.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-asyn-thread.Tpo -c -o libcurlu_la-asyn-thread.lo `test -f 'asyn-thread.c' || echo '$(srcdir)/'`asyn-thread.c
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-asyn-thread.Tpo $(DEPDIR)/libcurlu_la-asyn-thread.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='asyn-thread.c' object='libcurlu_la-asyn-thread.lo' libtool=yes @AMDEPBACKSLASH@
+libcurlu_la-asyn-base.lo: asyn-base.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-asyn-base.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-asyn-base.Tpo -c -o libcurlu_la-asyn-base.lo `test -f 'asyn-base.c' || echo '$(srcdir)/'`asyn-base.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-asyn-base.Tpo $(DEPDIR)/libcurlu_la-asyn-base.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='asyn-base.c' object='libcurlu_la-asyn-base.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-asyn-thread.lo `test -f 'asyn-thread.c' || echo '$(srcdir)/'`asyn-thread.c
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-asyn-base.lo `test -f 'asyn-base.c' || echo '$(srcdir)/'`asyn-base.c
-libcurlu_la-base64.lo: base64.c
-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-base64.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-base64.Tpo -c -o libcurlu_la-base64.lo `test -f 'base64.c' || echo '$(srcdir)/'`base64.c
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-base64.Tpo $(DEPDIR)/libcurlu_la-base64.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='base64.c' object='libcurlu_la-base64.lo' libtool=yes @AMDEPBACKSLASH@
+libcurlu_la-asyn-thrdd.lo: asyn-thrdd.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-asyn-thrdd.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-asyn-thrdd.Tpo -c -o libcurlu_la-asyn-thrdd.lo `test -f 'asyn-thrdd.c' || echo '$(srcdir)/'`asyn-thrdd.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-asyn-thrdd.Tpo $(DEPDIR)/libcurlu_la-asyn-thrdd.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='asyn-thrdd.c' object='libcurlu_la-asyn-thrdd.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-base64.lo `test -f 'base64.c' || echo '$(srcdir)/'`base64.c
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-asyn-thrdd.lo `test -f 'asyn-thrdd.c' || echo '$(srcdir)/'`asyn-thrdd.c
libcurlu_la-bufq.lo: bufq.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-bufq.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-bufq.Tpo -c -o libcurlu_la-bufq.lo `test -f 'bufq.c' || echo '$(srcdir)/'`bufq.c
@@ -3670,13 +3792,6 @@ libcurlu_la-conncache.lo: conncache.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-conncache.lo `test -f 'conncache.c' || echo '$(srcdir)/'`conncache.c
-libcurlu_la-cshutdn.lo: cshutdn.c
-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-cshutdn.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-cshutdn.Tpo -c -o libcurlu_la-cshutdn.lo `test -f 'cshutdn.c' || echo '$(srcdir)/'`cshutdn.c
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-cshutdn.Tpo $(DEPDIR)/libcurlu_la-cshutdn.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cshutdn.c' object='libcurlu_la-cshutdn.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-cshutdn.lo `test -f 'cshutdn.c' || echo '$(srcdir)/'`cshutdn.c
-
libcurlu_la-connect.lo: connect.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-connect.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-connect.Tpo -c -o libcurlu_la-connect.lo `test -f 'connect.c' || echo '$(srcdir)/'`connect.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-connect.Tpo $(DEPDIR)/libcurlu_la-connect.Plo
@@ -3698,6 +3813,13 @@ libcurlu_la-cookie.lo: cookie.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-cookie.lo `test -f 'cookie.c' || echo '$(srcdir)/'`cookie.c
+libcurlu_la-cshutdn.lo: cshutdn.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-cshutdn.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-cshutdn.Tpo -c -o libcurlu_la-cshutdn.lo `test -f 'cshutdn.c' || echo '$(srcdir)/'`cshutdn.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-cshutdn.Tpo $(DEPDIR)/libcurlu_la-cshutdn.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cshutdn.c' object='libcurlu_la-cshutdn.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-cshutdn.lo `test -f 'cshutdn.c' || echo '$(srcdir)/'`cshutdn.c
+
libcurlu_la-curl_addrinfo.lo: curl_addrinfo.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-curl_addrinfo.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-curl_addrinfo.Tpo -c -o libcurlu_la-curl_addrinfo.lo `test -f 'curl_addrinfo.c' || echo '$(srcdir)/'`curl_addrinfo.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-curl_addrinfo.Tpo $(DEPDIR)/libcurlu_la-curl_addrinfo.Plo
@@ -3754,13 +3876,6 @@ libcurlu_la-curl_memrchr.lo: curl_memrchr.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-curl_memrchr.lo `test -f 'curl_memrchr.c' || echo '$(srcdir)/'`curl_memrchr.c
-libcurlu_la-curl_multibyte.lo: curl_multibyte.c
-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-curl_multibyte.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-curl_multibyte.Tpo -c -o libcurlu_la-curl_multibyte.lo `test -f 'curl_multibyte.c' || echo '$(srcdir)/'`curl_multibyte.c
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-curl_multibyte.Tpo $(DEPDIR)/libcurlu_la-curl_multibyte.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='curl_multibyte.c' object='libcurlu_la-curl_multibyte.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-curl_multibyte.lo `test -f 'curl_multibyte.c' || echo '$(srcdir)/'`curl_multibyte.c
-
libcurlu_la-curl_ntlm_core.lo: curl_ntlm_core.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-curl_ntlm_core.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-curl_ntlm_core.Tpo -c -o libcurlu_la-curl_ntlm_core.lo `test -f 'curl_ntlm_core.c' || echo '$(srcdir)/'`curl_ntlm_core.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-curl_ntlm_core.Tpo $(DEPDIR)/libcurlu_la-curl_ntlm_core.Plo
@@ -3845,13 +3960,6 @@ libcurlu_la-doh.lo: doh.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-doh.lo `test -f 'doh.c' || echo '$(srcdir)/'`doh.c
-libcurlu_la-dynbuf.lo: dynbuf.c
-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-dynbuf.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-dynbuf.Tpo -c -o libcurlu_la-dynbuf.lo `test -f 'dynbuf.c' || echo '$(srcdir)/'`dynbuf.c
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-dynbuf.Tpo $(DEPDIR)/libcurlu_la-dynbuf.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='dynbuf.c' object='libcurlu_la-dynbuf.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-dynbuf.lo `test -f 'dynbuf.c' || echo '$(srcdir)/'`dynbuf.c
-
libcurlu_la-dynhds.lo: dynhds.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-dynhds.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-dynhds.Tpo -c -o libcurlu_la-dynhds.lo `test -f 'dynhds.c' || echo '$(srcdir)/'`dynhds.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-dynhds.Tpo $(DEPDIR)/libcurlu_la-dynhds.Plo
@@ -3887,6 +3995,13 @@ libcurlu_la-escape.lo: escape.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-escape.lo `test -f 'escape.c' || echo '$(srcdir)/'`escape.c
+libcurlu_la-fake_addrinfo.lo: fake_addrinfo.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-fake_addrinfo.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-fake_addrinfo.Tpo -c -o libcurlu_la-fake_addrinfo.lo `test -f 'fake_addrinfo.c' || echo '$(srcdir)/'`fake_addrinfo.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-fake_addrinfo.Tpo $(DEPDIR)/libcurlu_la-fake_addrinfo.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='fake_addrinfo.c' object='libcurlu_la-fake_addrinfo.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-fake_addrinfo.lo `test -f 'fake_addrinfo.c' || echo '$(srcdir)/'`fake_addrinfo.c
+
libcurlu_la-file.lo: file.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-file.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-file.Tpo -c -o libcurlu_la-file.lo `test -f 'file.c' || echo '$(srcdir)/'`file.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-file.Tpo $(DEPDIR)/libcurlu_la-file.Plo
@@ -3957,13 +4072,6 @@ libcurlu_la-hash.lo: hash.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-hash.lo `test -f 'hash.c' || echo '$(srcdir)/'`hash.c
-libcurlu_la-hash_offt.lo: hash_offt.c
-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-hash_offt.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-hash_offt.Tpo -c -o libcurlu_la-hash_offt.lo `test -f 'hash_offt.c' || echo '$(srcdir)/'`hash_offt.c
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-hash_offt.Tpo $(DEPDIR)/libcurlu_la-hash_offt.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='hash_offt.c' object='libcurlu_la-hash_offt.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-hash_offt.lo `test -f 'hash_offt.c' || echo '$(srcdir)/'`hash_offt.c
-
libcurlu_la-headers.lo: headers.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-headers.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-headers.Tpo -c -o libcurlu_la-headers.lo `test -f 'headers.c' || echo '$(srcdir)/'`headers.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-headers.Tpo $(DEPDIR)/libcurlu_la-headers.Plo
@@ -3978,13 +4086,6 @@ libcurlu_la-hmac.lo: hmac.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-hmac.lo `test -f 'hmac.c' || echo '$(srcdir)/'`hmac.c
-libcurlu_la-hostasyn.lo: hostasyn.c
-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-hostasyn.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-hostasyn.Tpo -c -o libcurlu_la-hostasyn.lo `test -f 'hostasyn.c' || echo '$(srcdir)/'`hostasyn.c
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-hostasyn.Tpo $(DEPDIR)/libcurlu_la-hostasyn.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='hostasyn.c' object='libcurlu_la-hostasyn.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-hostasyn.lo `test -f 'hostasyn.c' || echo '$(srcdir)/'`hostasyn.c
-
libcurlu_la-hostip.lo: hostip.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-hostip.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-hostip.Tpo -c -o libcurlu_la-hostip.lo `test -f 'hostip.c' || echo '$(srcdir)/'`hostip.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-hostip.Tpo $(DEPDIR)/libcurlu_la-hostip.Plo
@@ -4006,13 +4107,6 @@ libcurlu_la-hostip6.lo: hostip6.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-hostip6.lo `test -f 'hostip6.c' || echo '$(srcdir)/'`hostip6.c
-libcurlu_la-hostsyn.lo: hostsyn.c
-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-hostsyn.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-hostsyn.Tpo -c -o libcurlu_la-hostsyn.lo `test -f 'hostsyn.c' || echo '$(srcdir)/'`hostsyn.c
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-hostsyn.Tpo $(DEPDIR)/libcurlu_la-hostsyn.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='hostsyn.c' object='libcurlu_la-hostsyn.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-hostsyn.lo `test -f 'hostsyn.c' || echo '$(srcdir)/'`hostsyn.c
-
libcurlu_la-hsts.lo: hsts.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-hsts.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-hsts.Tpo -c -o libcurlu_la-hsts.lo `test -f 'hsts.c' || echo '$(srcdir)/'`hsts.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-hsts.Tpo $(DEPDIR)/libcurlu_la-hsts.Plo
@@ -4118,13 +4212,6 @@ libcurlu_la-inet_ntop.lo: inet_ntop.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-inet_ntop.lo `test -f 'inet_ntop.c' || echo '$(srcdir)/'`inet_ntop.c
-libcurlu_la-inet_pton.lo: inet_pton.c
-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-inet_pton.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-inet_pton.Tpo -c -o libcurlu_la-inet_pton.lo `test -f 'inet_pton.c' || echo '$(srcdir)/'`inet_pton.c
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-inet_pton.Tpo $(DEPDIR)/libcurlu_la-inet_pton.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='inet_pton.c' object='libcurlu_la-inet_pton.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-inet_pton.lo `test -f 'inet_pton.c' || echo '$(srcdir)/'`inet_pton.c
-
libcurlu_la-krb5.lo: krb5.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-krb5.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-krb5.Tpo -c -o libcurlu_la-krb5.lo `test -f 'krb5.c' || echo '$(srcdir)/'`krb5.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-krb5.Tpo $(DEPDIR)/libcurlu_la-krb5.Plo
@@ -4216,13 +4303,6 @@ libcurlu_la-netrc.lo: netrc.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-netrc.lo `test -f 'netrc.c' || echo '$(srcdir)/'`netrc.c
-libcurlu_la-nonblock.lo: nonblock.c
-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-nonblock.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-nonblock.Tpo -c -o libcurlu_la-nonblock.lo `test -f 'nonblock.c' || echo '$(srcdir)/'`nonblock.c
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-nonblock.Tpo $(DEPDIR)/libcurlu_la-nonblock.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nonblock.c' object='libcurlu_la-nonblock.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-nonblock.lo `test -f 'nonblock.c' || echo '$(srcdir)/'`nonblock.c
-
libcurlu_la-noproxy.lo: noproxy.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-noproxy.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-noproxy.Tpo -c -o libcurlu_la-noproxy.lo `test -f 'noproxy.c' || echo '$(srcdir)/'`noproxy.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-noproxy.Tpo $(DEPDIR)/libcurlu_la-noproxy.Plo
@@ -4426,13 +4506,6 @@ libcurlu_la-strerror.lo: strerror.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-strerror.lo `test -f 'strerror.c' || echo '$(srcdir)/'`strerror.c
-libcurlu_la-strparse.lo: strparse.c
-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-strparse.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-strparse.Tpo -c -o libcurlu_la-strparse.lo `test -f 'strparse.c' || echo '$(srcdir)/'`strparse.c
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-strparse.Tpo $(DEPDIR)/libcurlu_la-strparse.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='strparse.c' object='libcurlu_la-strparse.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-strparse.lo `test -f 'strparse.c' || echo '$(srcdir)/'`strparse.c
-
libcurlu_la-system_win32.lo: system_win32.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-system_win32.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-system_win32.Tpo -c -o libcurlu_la-system_win32.lo `test -f 'system_win32.c' || echo '$(srcdir)/'`system_win32.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-system_win32.Tpo $(DEPDIR)/libcurlu_la-system_win32.Plo
@@ -4454,20 +4527,6 @@ libcurlu_la-tftp.lo: tftp.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-tftp.lo `test -f 'tftp.c' || echo '$(srcdir)/'`tftp.c
-libcurlu_la-timediff.lo: timediff.c
-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-timediff.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-timediff.Tpo -c -o libcurlu_la-timediff.lo `test -f 'timediff.c' || echo '$(srcdir)/'`timediff.c
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-timediff.Tpo $(DEPDIR)/libcurlu_la-timediff.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='timediff.c' object='libcurlu_la-timediff.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-timediff.lo `test -f 'timediff.c' || echo '$(srcdir)/'`timediff.c
-
-libcurlu_la-timeval.lo: timeval.c
-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-timeval.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-timeval.Tpo -c -o libcurlu_la-timeval.lo `test -f 'timeval.c' || echo '$(srcdir)/'`timeval.c
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-timeval.Tpo $(DEPDIR)/libcurlu_la-timeval.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='timeval.c' object='libcurlu_la-timeval.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-timeval.lo `test -f 'timeval.c' || echo '$(srcdir)/'`timeval.c
-
libcurlu_la-transfer.lo: transfer.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-transfer.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-transfer.Tpo -c -o libcurlu_la-transfer.lo `test -f 'transfer.c' || echo '$(srcdir)/'`transfer.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-transfer.Tpo $(DEPDIR)/libcurlu_la-transfer.Plo
@@ -4475,6 +4534,34 @@ libcurlu_la-transfer.lo: transfer.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-transfer.lo `test -f 'transfer.c' || echo '$(srcdir)/'`transfer.c
+libcurlu_la-uint-bset.lo: uint-bset.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-uint-bset.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-uint-bset.Tpo -c -o libcurlu_la-uint-bset.lo `test -f 'uint-bset.c' || echo '$(srcdir)/'`uint-bset.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-uint-bset.Tpo $(DEPDIR)/libcurlu_la-uint-bset.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='uint-bset.c' object='libcurlu_la-uint-bset.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-uint-bset.lo `test -f 'uint-bset.c' || echo '$(srcdir)/'`uint-bset.c
+
+libcurlu_la-uint-hash.lo: uint-hash.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-uint-hash.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-uint-hash.Tpo -c -o libcurlu_la-uint-hash.lo `test -f 'uint-hash.c' || echo '$(srcdir)/'`uint-hash.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-uint-hash.Tpo $(DEPDIR)/libcurlu_la-uint-hash.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='uint-hash.c' object='libcurlu_la-uint-hash.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-uint-hash.lo `test -f 'uint-hash.c' || echo '$(srcdir)/'`uint-hash.c
+
+libcurlu_la-uint-spbset.lo: uint-spbset.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-uint-spbset.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-uint-spbset.Tpo -c -o libcurlu_la-uint-spbset.lo `test -f 'uint-spbset.c' || echo '$(srcdir)/'`uint-spbset.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-uint-spbset.Tpo $(DEPDIR)/libcurlu_la-uint-spbset.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='uint-spbset.c' object='libcurlu_la-uint-spbset.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-uint-spbset.lo `test -f 'uint-spbset.c' || echo '$(srcdir)/'`uint-spbset.c
+
+libcurlu_la-uint-table.lo: uint-table.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-uint-table.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-uint-table.Tpo -c -o libcurlu_la-uint-table.lo `test -f 'uint-table.c' || echo '$(srcdir)/'`uint-table.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-uint-table.Tpo $(DEPDIR)/libcurlu_la-uint-table.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='uint-table.c' object='libcurlu_la-uint-table.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-uint-table.lo `test -f 'uint-table.c' || echo '$(srcdir)/'`uint-table.c
+
libcurlu_la-url.lo: url.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-url.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-url.Tpo -c -o libcurlu_la-url.lo `test -f 'url.c' || echo '$(srcdir)/'`url.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-url.Tpo $(DEPDIR)/libcurlu_la-url.Plo
@@ -4496,20 +4583,6 @@ libcurlu_la-version.lo: version.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-version.lo `test -f 'version.c' || echo '$(srcdir)/'`version.c
-libcurlu_la-version_win32.lo: version_win32.c
-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-version_win32.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-version_win32.Tpo -c -o libcurlu_la-version_win32.lo `test -f 'version_win32.c' || echo '$(srcdir)/'`version_win32.c
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-version_win32.Tpo $(DEPDIR)/libcurlu_la-version_win32.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='version_win32.c' object='libcurlu_la-version_win32.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-version_win32.lo `test -f 'version_win32.c' || echo '$(srcdir)/'`version_win32.c
-
-libcurlu_la-warnless.lo: warnless.c
-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-warnless.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-warnless.Tpo -c -o libcurlu_la-warnless.lo `test -f 'warnless.c' || echo '$(srcdir)/'`warnless.c
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-warnless.Tpo $(DEPDIR)/libcurlu_la-warnless.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='warnless.c' object='libcurlu_la-warnless.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o libcurlu_la-warnless.lo `test -f 'warnless.c' || echo '$(srcdir)/'`warnless.c
-
libcurlu_la-ws.lo: ws.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-ws.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-ws.Tpo -c -o libcurlu_la-ws.lo `test -f 'ws.c' || echo '$(srcdir)/'`ws.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-ws.Tpo $(DEPDIR)/libcurlu_la-ws.Plo
@@ -4797,6 +4870,83 @@ vssh/libcurlu_la-wolfssh.lo: vssh/wolfssh.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o vssh/libcurlu_la-wolfssh.lo `test -f 'vssh/wolfssh.c' || echo '$(srcdir)/'`vssh/wolfssh.c
+curlx/libcurlu_la-base64.lo: curlx/base64.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT curlx/libcurlu_la-base64.lo -MD -MP -MF curlx/$(DEPDIR)/libcurlu_la-base64.Tpo -c -o curlx/libcurlu_la-base64.lo `test -f 'curlx/base64.c' || echo '$(srcdir)/'`curlx/base64.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) curlx/$(DEPDIR)/libcurlu_la-base64.Tpo curlx/$(DEPDIR)/libcurlu_la-base64.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='curlx/base64.c' object='curlx/libcurlu_la-base64.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o curlx/libcurlu_la-base64.lo `test -f 'curlx/base64.c' || echo '$(srcdir)/'`curlx/base64.c
+
+curlx/libcurlu_la-dynbuf.lo: curlx/dynbuf.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT curlx/libcurlu_la-dynbuf.lo -MD -MP -MF curlx/$(DEPDIR)/libcurlu_la-dynbuf.Tpo -c -o curlx/libcurlu_la-dynbuf.lo `test -f 'curlx/dynbuf.c' || echo '$(srcdir)/'`curlx/dynbuf.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) curlx/$(DEPDIR)/libcurlu_la-dynbuf.Tpo curlx/$(DEPDIR)/libcurlu_la-dynbuf.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='curlx/dynbuf.c' object='curlx/libcurlu_la-dynbuf.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o curlx/libcurlu_la-dynbuf.lo `test -f 'curlx/dynbuf.c' || echo '$(srcdir)/'`curlx/dynbuf.c
+
+curlx/libcurlu_la-inet_pton.lo: curlx/inet_pton.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT curlx/libcurlu_la-inet_pton.lo -MD -MP -MF curlx/$(DEPDIR)/libcurlu_la-inet_pton.Tpo -c -o curlx/libcurlu_la-inet_pton.lo `test -f 'curlx/inet_pton.c' || echo '$(srcdir)/'`curlx/inet_pton.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) curlx/$(DEPDIR)/libcurlu_la-inet_pton.Tpo curlx/$(DEPDIR)/libcurlu_la-inet_pton.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='curlx/inet_pton.c' object='curlx/libcurlu_la-inet_pton.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o curlx/libcurlu_la-inet_pton.lo `test -f 'curlx/inet_pton.c' || echo '$(srcdir)/'`curlx/inet_pton.c
+
+curlx/libcurlu_la-multibyte.lo: curlx/multibyte.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT curlx/libcurlu_la-multibyte.lo -MD -MP -MF curlx/$(DEPDIR)/libcurlu_la-multibyte.Tpo -c -o curlx/libcurlu_la-multibyte.lo `test -f 'curlx/multibyte.c' || echo '$(srcdir)/'`curlx/multibyte.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) curlx/$(DEPDIR)/libcurlu_la-multibyte.Tpo curlx/$(DEPDIR)/libcurlu_la-multibyte.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='curlx/multibyte.c' object='curlx/libcurlu_la-multibyte.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o curlx/libcurlu_la-multibyte.lo `test -f 'curlx/multibyte.c' || echo '$(srcdir)/'`curlx/multibyte.c
+
+curlx/libcurlu_la-nonblock.lo: curlx/nonblock.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT curlx/libcurlu_la-nonblock.lo -MD -MP -MF curlx/$(DEPDIR)/libcurlu_la-nonblock.Tpo -c -o curlx/libcurlu_la-nonblock.lo `test -f 'curlx/nonblock.c' || echo '$(srcdir)/'`curlx/nonblock.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) curlx/$(DEPDIR)/libcurlu_la-nonblock.Tpo curlx/$(DEPDIR)/libcurlu_la-nonblock.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='curlx/nonblock.c' object='curlx/libcurlu_la-nonblock.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o curlx/libcurlu_la-nonblock.lo `test -f 'curlx/nonblock.c' || echo '$(srcdir)/'`curlx/nonblock.c
+
+curlx/libcurlu_la-strparse.lo: curlx/strparse.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT curlx/libcurlu_la-strparse.lo -MD -MP -MF curlx/$(DEPDIR)/libcurlu_la-strparse.Tpo -c -o curlx/libcurlu_la-strparse.lo `test -f 'curlx/strparse.c' || echo '$(srcdir)/'`curlx/strparse.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) curlx/$(DEPDIR)/libcurlu_la-strparse.Tpo curlx/$(DEPDIR)/libcurlu_la-strparse.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='curlx/strparse.c' object='curlx/libcurlu_la-strparse.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o curlx/libcurlu_la-strparse.lo `test -f 'curlx/strparse.c' || echo '$(srcdir)/'`curlx/strparse.c
+
+curlx/libcurlu_la-timediff.lo: curlx/timediff.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT curlx/libcurlu_la-timediff.lo -MD -MP -MF curlx/$(DEPDIR)/libcurlu_la-timediff.Tpo -c -o curlx/libcurlu_la-timediff.lo `test -f 'curlx/timediff.c' || echo '$(srcdir)/'`curlx/timediff.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) curlx/$(DEPDIR)/libcurlu_la-timediff.Tpo curlx/$(DEPDIR)/libcurlu_la-timediff.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='curlx/timediff.c' object='curlx/libcurlu_la-timediff.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o curlx/libcurlu_la-timediff.lo `test -f 'curlx/timediff.c' || echo '$(srcdir)/'`curlx/timediff.c
+
+curlx/libcurlu_la-timeval.lo: curlx/timeval.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT curlx/libcurlu_la-timeval.lo -MD -MP -MF curlx/$(DEPDIR)/libcurlu_la-timeval.Tpo -c -o curlx/libcurlu_la-timeval.lo `test -f 'curlx/timeval.c' || echo '$(srcdir)/'`curlx/timeval.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) curlx/$(DEPDIR)/libcurlu_la-timeval.Tpo curlx/$(DEPDIR)/libcurlu_la-timeval.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='curlx/timeval.c' object='curlx/libcurlu_la-timeval.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o curlx/libcurlu_la-timeval.lo `test -f 'curlx/timeval.c' || echo '$(srcdir)/'`curlx/timeval.c
+
+curlx/libcurlu_la-version_win32.lo: curlx/version_win32.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT curlx/libcurlu_la-version_win32.lo -MD -MP -MF curlx/$(DEPDIR)/libcurlu_la-version_win32.Tpo -c -o curlx/libcurlu_la-version_win32.lo `test -f 'curlx/version_win32.c' || echo '$(srcdir)/'`curlx/version_win32.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) curlx/$(DEPDIR)/libcurlu_la-version_win32.Tpo curlx/$(DEPDIR)/libcurlu_la-version_win32.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='curlx/version_win32.c' object='curlx/libcurlu_la-version_win32.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o curlx/libcurlu_la-version_win32.lo `test -f 'curlx/version_win32.c' || echo '$(srcdir)/'`curlx/version_win32.c
+
+curlx/libcurlu_la-warnless.lo: curlx/warnless.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT curlx/libcurlu_la-warnless.lo -MD -MP -MF curlx/$(DEPDIR)/libcurlu_la-warnless.Tpo -c -o curlx/libcurlu_la-warnless.lo `test -f 'curlx/warnless.c' || echo '$(srcdir)/'`curlx/warnless.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) curlx/$(DEPDIR)/libcurlu_la-warnless.Tpo curlx/$(DEPDIR)/libcurlu_la-warnless.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='curlx/warnless.c' object='curlx/libcurlu_la-warnless.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o curlx/libcurlu_la-warnless.lo `test -f 'curlx/warnless.c' || echo '$(srcdir)/'`curlx/warnless.c
+
+curlx/libcurlu_la-winapi.lo: curlx/winapi.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT curlx/libcurlu_la-winapi.lo -MD -MP -MF curlx/$(DEPDIR)/libcurlu_la-winapi.Tpo -c -o curlx/libcurlu_la-winapi.lo `test -f 'curlx/winapi.c' || echo '$(srcdir)/'`curlx/winapi.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) curlx/$(DEPDIR)/libcurlu_la-winapi.Tpo curlx/$(DEPDIR)/libcurlu_la-winapi.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='curlx/winapi.c' object='curlx/libcurlu_la-winapi.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -c -o curlx/libcurlu_la-winapi.lo `test -f 'curlx/winapi.c' || echo '$(srcdir)/'`curlx/winapi.c
+
libcurlu_la-dllmain.lo: dllmain.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcurlu_la_CPPFLAGS) $(CPPFLAGS) $(libcurlu_la_CFLAGS) $(CFLAGS) -MT libcurlu_la-dllmain.lo -MD -MP -MF $(DEPDIR)/libcurlu_la-dllmain.Tpo -c -o libcurlu_la-dllmain.lo `test -f 'dllmain.c' || echo '$(srcdir)/'`dllmain.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcurlu_la-dllmain.Tpo $(DEPDIR)/libcurlu_la-dllmain.Plo
@@ -4816,6 +4966,7 @@ mostlyclean-libtool:
clean-libtool:
-rm -rf .libs _libs
+ -rm -rf curlx/.libs curlx/_libs
-rm -rf vauth/.libs vauth/_libs
-rm -rf vquic/.libs vquic/_libs
-rm -rf vssh/.libs vssh/_libs
@@ -4908,6 +5059,7 @@ distdir-am: $(DISTFILES)
check-am: all-am
check: check-am
@DEBUGBUILD_FALSE@all-local:
+@NOT_CURL_CI_FALSE@all-local:
all-am: Makefile $(LTLIBRARIES) curl_config.h all-local
installdirs:
for dir in "$(DESTDIR)$(libdir)"; do \
@@ -4940,6 +5092,8 @@ clean-generic:
distclean-generic:
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+ -rm -f curlx/$(DEPDIR)/$(am__dirstamp)
+ -rm -f curlx/$(am__dirstamp)
-rm -f vauth/$(DEPDIR)/$(am__dirstamp)
-rm -f vauth/$(am__dirstamp)
-rm -f vquic/$(DEPDIR)/$(am__dirstamp)
@@ -4961,8 +5115,8 @@ distclean: distclean-am
-rm -f ./$(DEPDIR)/libcurl_la-altsvc.Plo
-rm -f ./$(DEPDIR)/libcurl_la-amigaos.Plo
-rm -f ./$(DEPDIR)/libcurl_la-asyn-ares.Plo
- -rm -f ./$(DEPDIR)/libcurl_la-asyn-thread.Plo
- -rm -f ./$(DEPDIR)/libcurl_la-base64.Plo
+ -rm -f ./$(DEPDIR)/libcurl_la-asyn-base.Plo
+ -rm -f ./$(DEPDIR)/libcurl_la-asyn-thrdd.Plo
-rm -f ./$(DEPDIR)/libcurl_la-bufq.Plo
-rm -f ./$(DEPDIR)/libcurl_la-bufref.Plo
-rm -f ./$(DEPDIR)/libcurl_la-cf-h1-proxy.Plo
@@ -4984,7 +5138,6 @@ distclean: distclean-am
-rm -f ./$(DEPDIR)/libcurl_la-curl_gethostname.Plo
-rm -f ./$(DEPDIR)/libcurl_la-curl_gssapi.Plo
-rm -f ./$(DEPDIR)/libcurl_la-curl_memrchr.Plo
- -rm -f ./$(DEPDIR)/libcurl_la-curl_multibyte.Plo
-rm -f ./$(DEPDIR)/libcurl_la-curl_ntlm_core.Plo
-rm -f ./$(DEPDIR)/libcurl_la-curl_range.Plo
-rm -f ./$(DEPDIR)/libcurl_la-curl_rtmp.Plo
@@ -4998,12 +5151,12 @@ distclean: distclean-am
-rm -f ./$(DEPDIR)/libcurl_la-dict.Plo
-rm -f ./$(DEPDIR)/libcurl_la-dllmain.Plo
-rm -f ./$(DEPDIR)/libcurl_la-doh.Plo
- -rm -f ./$(DEPDIR)/libcurl_la-dynbuf.Plo
-rm -f ./$(DEPDIR)/libcurl_la-dynhds.Plo
-rm -f ./$(DEPDIR)/libcurl_la-easy.Plo
-rm -f ./$(DEPDIR)/libcurl_la-easygetopt.Plo
-rm -f ./$(DEPDIR)/libcurl_la-easyoptions.Plo
-rm -f ./$(DEPDIR)/libcurl_la-escape.Plo
+ -rm -f ./$(DEPDIR)/libcurl_la-fake_addrinfo.Plo
-rm -f ./$(DEPDIR)/libcurl_la-file.Plo
-rm -f ./$(DEPDIR)/libcurl_la-fileinfo.Plo
-rm -f ./$(DEPDIR)/libcurl_la-fopen.Plo
@@ -5014,14 +5167,11 @@ distclean: distclean-am
-rm -f ./$(DEPDIR)/libcurl_la-getinfo.Plo
-rm -f ./$(DEPDIR)/libcurl_la-gopher.Plo
-rm -f ./$(DEPDIR)/libcurl_la-hash.Plo
- -rm -f ./$(DEPDIR)/libcurl_la-hash_offt.Plo
-rm -f ./$(DEPDIR)/libcurl_la-headers.Plo
-rm -f ./$(DEPDIR)/libcurl_la-hmac.Plo
- -rm -f ./$(DEPDIR)/libcurl_la-hostasyn.Plo
-rm -f ./$(DEPDIR)/libcurl_la-hostip.Plo
-rm -f ./$(DEPDIR)/libcurl_la-hostip4.Plo
-rm -f ./$(DEPDIR)/libcurl_la-hostip6.Plo
- -rm -f ./$(DEPDIR)/libcurl_la-hostsyn.Plo
-rm -f ./$(DEPDIR)/libcurl_la-hsts.Plo
-rm -f ./$(DEPDIR)/libcurl_la-http.Plo
-rm -f ./$(DEPDIR)/libcurl_la-http1.Plo
@@ -5037,7 +5187,6 @@ distclean: distclean-am
-rm -f ./$(DEPDIR)/libcurl_la-if2ip.Plo
-rm -f ./$(DEPDIR)/libcurl_la-imap.Plo
-rm -f ./$(DEPDIR)/libcurl_la-inet_ntop.Plo
- -rm -f ./$(DEPDIR)/libcurl_la-inet_pton.Plo
-rm -f ./$(DEPDIR)/libcurl_la-krb5.Plo
-rm -f ./$(DEPDIR)/libcurl_la-ldap.Plo
-rm -f ./$(DEPDIR)/libcurl_la-libcurl_unity.Plo
@@ -5052,7 +5201,6 @@ distclean: distclean-am
-rm -f ./$(DEPDIR)/libcurl_la-multi.Plo
-rm -f ./$(DEPDIR)/libcurl_la-multi_ev.Plo
-rm -f ./$(DEPDIR)/libcurl_la-netrc.Plo
- -rm -f ./$(DEPDIR)/libcurl_la-nonblock.Plo
-rm -f ./$(DEPDIR)/libcurl_la-noproxy.Plo
-rm -f ./$(DEPDIR)/libcurl_la-openldap.Plo
-rm -f ./$(DEPDIR)/libcurl_la-parsedate.Plo
@@ -5082,24 +5230,23 @@ distclean: distclean-am
-rm -f ./$(DEPDIR)/libcurl_la-strdup.Plo
-rm -f ./$(DEPDIR)/libcurl_la-strequal.Plo
-rm -f ./$(DEPDIR)/libcurl_la-strerror.Plo
- -rm -f ./$(DEPDIR)/libcurl_la-strparse.Plo
-rm -f ./$(DEPDIR)/libcurl_la-system_win32.Plo
-rm -f ./$(DEPDIR)/libcurl_la-telnet.Plo
-rm -f ./$(DEPDIR)/libcurl_la-tftp.Plo
- -rm -f ./$(DEPDIR)/libcurl_la-timediff.Plo
- -rm -f ./$(DEPDIR)/libcurl_la-timeval.Plo
-rm -f ./$(DEPDIR)/libcurl_la-transfer.Plo
+ -rm -f ./$(DEPDIR)/libcurl_la-uint-bset.Plo
+ -rm -f ./$(DEPDIR)/libcurl_la-uint-hash.Plo
+ -rm -f ./$(DEPDIR)/libcurl_la-uint-spbset.Plo
+ -rm -f ./$(DEPDIR)/libcurl_la-uint-table.Plo
-rm -f ./$(DEPDIR)/libcurl_la-url.Plo
-rm -f ./$(DEPDIR)/libcurl_la-urlapi.Plo
-rm -f ./$(DEPDIR)/libcurl_la-version.Plo
- -rm -f ./$(DEPDIR)/libcurl_la-version_win32.Plo
- -rm -f ./$(DEPDIR)/libcurl_la-warnless.Plo
-rm -f ./$(DEPDIR)/libcurl_la-ws.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-altsvc.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-amigaos.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-asyn-ares.Plo
- -rm -f ./$(DEPDIR)/libcurlu_la-asyn-thread.Plo
- -rm -f ./$(DEPDIR)/libcurlu_la-base64.Plo
+ -rm -f ./$(DEPDIR)/libcurlu_la-asyn-base.Plo
+ -rm -f ./$(DEPDIR)/libcurlu_la-asyn-thrdd.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-bufq.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-bufref.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-cf-h1-proxy.Plo
@@ -5121,7 +5268,6 @@ distclean: distclean-am
-rm -f ./$(DEPDIR)/libcurlu_la-curl_gethostname.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-curl_gssapi.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-curl_memrchr.Plo
- -rm -f ./$(DEPDIR)/libcurlu_la-curl_multibyte.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-curl_ntlm_core.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-curl_range.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-curl_rtmp.Plo
@@ -5135,12 +5281,12 @@ distclean: distclean-am
-rm -f ./$(DEPDIR)/libcurlu_la-dict.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-dllmain.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-doh.Plo
- -rm -f ./$(DEPDIR)/libcurlu_la-dynbuf.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-dynhds.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-easy.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-easygetopt.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-easyoptions.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-escape.Plo
+ -rm -f ./$(DEPDIR)/libcurlu_la-fake_addrinfo.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-file.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-fileinfo.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-fopen.Plo
@@ -5151,14 +5297,11 @@ distclean: distclean-am
-rm -f ./$(DEPDIR)/libcurlu_la-getinfo.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-gopher.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-hash.Plo
- -rm -f ./$(DEPDIR)/libcurlu_la-hash_offt.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-headers.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-hmac.Plo
- -rm -f ./$(DEPDIR)/libcurlu_la-hostasyn.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-hostip.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-hostip4.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-hostip6.Plo
- -rm -f ./$(DEPDIR)/libcurlu_la-hostsyn.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-hsts.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-http.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-http1.Plo
@@ -5174,7 +5317,6 @@ distclean: distclean-am
-rm -f ./$(DEPDIR)/libcurlu_la-if2ip.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-imap.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-inet_ntop.Plo
- -rm -f ./$(DEPDIR)/libcurlu_la-inet_pton.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-krb5.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-ldap.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-libcurl_unity.Plo
@@ -5189,7 +5331,6 @@ distclean: distclean-am
-rm -f ./$(DEPDIR)/libcurlu_la-multi.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-multi_ev.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-netrc.Plo
- -rm -f ./$(DEPDIR)/libcurlu_la-nonblock.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-noproxy.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-openldap.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-parsedate.Plo
@@ -5219,19 +5360,40 @@ distclean: distclean-am
-rm -f ./$(DEPDIR)/libcurlu_la-strdup.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-strequal.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-strerror.Plo
- -rm -f ./$(DEPDIR)/libcurlu_la-strparse.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-system_win32.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-telnet.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-tftp.Plo
- -rm -f ./$(DEPDIR)/libcurlu_la-timediff.Plo
- -rm -f ./$(DEPDIR)/libcurlu_la-timeval.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-transfer.Plo
+ -rm -f ./$(DEPDIR)/libcurlu_la-uint-bset.Plo
+ -rm -f ./$(DEPDIR)/libcurlu_la-uint-hash.Plo
+ -rm -f ./$(DEPDIR)/libcurlu_la-uint-spbset.Plo
+ -rm -f ./$(DEPDIR)/libcurlu_la-uint-table.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-url.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-urlapi.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-version.Plo
- -rm -f ./$(DEPDIR)/libcurlu_la-version_win32.Plo
- -rm -f ./$(DEPDIR)/libcurlu_la-warnless.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-ws.Plo
+ -rm -f curlx/$(DEPDIR)/libcurl_la-base64.Plo
+ -rm -f curlx/$(DEPDIR)/libcurl_la-dynbuf.Plo
+ -rm -f curlx/$(DEPDIR)/libcurl_la-inet_pton.Plo
+ -rm -f curlx/$(DEPDIR)/libcurl_la-multibyte.Plo
+ -rm -f curlx/$(DEPDIR)/libcurl_la-nonblock.Plo
+ -rm -f curlx/$(DEPDIR)/libcurl_la-strparse.Plo
+ -rm -f curlx/$(DEPDIR)/libcurl_la-timediff.Plo
+ -rm -f curlx/$(DEPDIR)/libcurl_la-timeval.Plo
+ -rm -f curlx/$(DEPDIR)/libcurl_la-version_win32.Plo
+ -rm -f curlx/$(DEPDIR)/libcurl_la-warnless.Plo
+ -rm -f curlx/$(DEPDIR)/libcurl_la-winapi.Plo
+ -rm -f curlx/$(DEPDIR)/libcurlu_la-base64.Plo
+ -rm -f curlx/$(DEPDIR)/libcurlu_la-dynbuf.Plo
+ -rm -f curlx/$(DEPDIR)/libcurlu_la-inet_pton.Plo
+ -rm -f curlx/$(DEPDIR)/libcurlu_la-multibyte.Plo
+ -rm -f curlx/$(DEPDIR)/libcurlu_la-nonblock.Plo
+ -rm -f curlx/$(DEPDIR)/libcurlu_la-strparse.Plo
+ -rm -f curlx/$(DEPDIR)/libcurlu_la-timediff.Plo
+ -rm -f curlx/$(DEPDIR)/libcurlu_la-timeval.Plo
+ -rm -f curlx/$(DEPDIR)/libcurlu_la-version_win32.Plo
+ -rm -f curlx/$(DEPDIR)/libcurlu_la-warnless.Plo
+ -rm -f curlx/$(DEPDIR)/libcurlu_la-winapi.Plo
-rm -f vauth/$(DEPDIR)/libcurl_la-cleartext.Plo
-rm -f vauth/$(DEPDIR)/libcurl_la-cram.Plo
-rm -f vauth/$(DEPDIR)/libcurl_la-digest.Plo
@@ -5360,8 +5522,8 @@ maintainer-clean: maintainer-clean-am
-rm -f ./$(DEPDIR)/libcurl_la-altsvc.Plo
-rm -f ./$(DEPDIR)/libcurl_la-amigaos.Plo
-rm -f ./$(DEPDIR)/libcurl_la-asyn-ares.Plo
- -rm -f ./$(DEPDIR)/libcurl_la-asyn-thread.Plo
- -rm -f ./$(DEPDIR)/libcurl_la-base64.Plo
+ -rm -f ./$(DEPDIR)/libcurl_la-asyn-base.Plo
+ -rm -f ./$(DEPDIR)/libcurl_la-asyn-thrdd.Plo
-rm -f ./$(DEPDIR)/libcurl_la-bufq.Plo
-rm -f ./$(DEPDIR)/libcurl_la-bufref.Plo
-rm -f ./$(DEPDIR)/libcurl_la-cf-h1-proxy.Plo
@@ -5383,7 +5545,6 @@ maintainer-clean: maintainer-clean-am
-rm -f ./$(DEPDIR)/libcurl_la-curl_gethostname.Plo
-rm -f ./$(DEPDIR)/libcurl_la-curl_gssapi.Plo
-rm -f ./$(DEPDIR)/libcurl_la-curl_memrchr.Plo
- -rm -f ./$(DEPDIR)/libcurl_la-curl_multibyte.Plo
-rm -f ./$(DEPDIR)/libcurl_la-curl_ntlm_core.Plo
-rm -f ./$(DEPDIR)/libcurl_la-curl_range.Plo
-rm -f ./$(DEPDIR)/libcurl_la-curl_rtmp.Plo
@@ -5397,12 +5558,12 @@ maintainer-clean: maintainer-clean-am
-rm -f ./$(DEPDIR)/libcurl_la-dict.Plo
-rm -f ./$(DEPDIR)/libcurl_la-dllmain.Plo
-rm -f ./$(DEPDIR)/libcurl_la-doh.Plo
- -rm -f ./$(DEPDIR)/libcurl_la-dynbuf.Plo
-rm -f ./$(DEPDIR)/libcurl_la-dynhds.Plo
-rm -f ./$(DEPDIR)/libcurl_la-easy.Plo
-rm -f ./$(DEPDIR)/libcurl_la-easygetopt.Plo
-rm -f ./$(DEPDIR)/libcurl_la-easyoptions.Plo
-rm -f ./$(DEPDIR)/libcurl_la-escape.Plo
+ -rm -f ./$(DEPDIR)/libcurl_la-fake_addrinfo.Plo
-rm -f ./$(DEPDIR)/libcurl_la-file.Plo
-rm -f ./$(DEPDIR)/libcurl_la-fileinfo.Plo
-rm -f ./$(DEPDIR)/libcurl_la-fopen.Plo
@@ -5413,14 +5574,11 @@ maintainer-clean: maintainer-clean-am
-rm -f ./$(DEPDIR)/libcurl_la-getinfo.Plo
-rm -f ./$(DEPDIR)/libcurl_la-gopher.Plo
-rm -f ./$(DEPDIR)/libcurl_la-hash.Plo
- -rm -f ./$(DEPDIR)/libcurl_la-hash_offt.Plo
-rm -f ./$(DEPDIR)/libcurl_la-headers.Plo
-rm -f ./$(DEPDIR)/libcurl_la-hmac.Plo
- -rm -f ./$(DEPDIR)/libcurl_la-hostasyn.Plo
-rm -f ./$(DEPDIR)/libcurl_la-hostip.Plo
-rm -f ./$(DEPDIR)/libcurl_la-hostip4.Plo
-rm -f ./$(DEPDIR)/libcurl_la-hostip6.Plo
- -rm -f ./$(DEPDIR)/libcurl_la-hostsyn.Plo
-rm -f ./$(DEPDIR)/libcurl_la-hsts.Plo
-rm -f ./$(DEPDIR)/libcurl_la-http.Plo
-rm -f ./$(DEPDIR)/libcurl_la-http1.Plo
@@ -5436,7 +5594,6 @@ maintainer-clean: maintainer-clean-am
-rm -f ./$(DEPDIR)/libcurl_la-if2ip.Plo
-rm -f ./$(DEPDIR)/libcurl_la-imap.Plo
-rm -f ./$(DEPDIR)/libcurl_la-inet_ntop.Plo
- -rm -f ./$(DEPDIR)/libcurl_la-inet_pton.Plo
-rm -f ./$(DEPDIR)/libcurl_la-krb5.Plo
-rm -f ./$(DEPDIR)/libcurl_la-ldap.Plo
-rm -f ./$(DEPDIR)/libcurl_la-libcurl_unity.Plo
@@ -5451,7 +5608,6 @@ maintainer-clean: maintainer-clean-am
-rm -f ./$(DEPDIR)/libcurl_la-multi.Plo
-rm -f ./$(DEPDIR)/libcurl_la-multi_ev.Plo
-rm -f ./$(DEPDIR)/libcurl_la-netrc.Plo
- -rm -f ./$(DEPDIR)/libcurl_la-nonblock.Plo
-rm -f ./$(DEPDIR)/libcurl_la-noproxy.Plo
-rm -f ./$(DEPDIR)/libcurl_la-openldap.Plo
-rm -f ./$(DEPDIR)/libcurl_la-parsedate.Plo
@@ -5481,24 +5637,23 @@ maintainer-clean: maintainer-clean-am
-rm -f ./$(DEPDIR)/libcurl_la-strdup.Plo
-rm -f ./$(DEPDIR)/libcurl_la-strequal.Plo
-rm -f ./$(DEPDIR)/libcurl_la-strerror.Plo
- -rm -f ./$(DEPDIR)/libcurl_la-strparse.Plo
-rm -f ./$(DEPDIR)/libcurl_la-system_win32.Plo
-rm -f ./$(DEPDIR)/libcurl_la-telnet.Plo
-rm -f ./$(DEPDIR)/libcurl_la-tftp.Plo
- -rm -f ./$(DEPDIR)/libcurl_la-timediff.Plo
- -rm -f ./$(DEPDIR)/libcurl_la-timeval.Plo
-rm -f ./$(DEPDIR)/libcurl_la-transfer.Plo
+ -rm -f ./$(DEPDIR)/libcurl_la-uint-bset.Plo
+ -rm -f ./$(DEPDIR)/libcurl_la-uint-hash.Plo
+ -rm -f ./$(DEPDIR)/libcurl_la-uint-spbset.Plo
+ -rm -f ./$(DEPDIR)/libcurl_la-uint-table.Plo
-rm -f ./$(DEPDIR)/libcurl_la-url.Plo
-rm -f ./$(DEPDIR)/libcurl_la-urlapi.Plo
-rm -f ./$(DEPDIR)/libcurl_la-version.Plo
- -rm -f ./$(DEPDIR)/libcurl_la-version_win32.Plo
- -rm -f ./$(DEPDIR)/libcurl_la-warnless.Plo
-rm -f ./$(DEPDIR)/libcurl_la-ws.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-altsvc.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-amigaos.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-asyn-ares.Plo
- -rm -f ./$(DEPDIR)/libcurlu_la-asyn-thread.Plo
- -rm -f ./$(DEPDIR)/libcurlu_la-base64.Plo
+ -rm -f ./$(DEPDIR)/libcurlu_la-asyn-base.Plo
+ -rm -f ./$(DEPDIR)/libcurlu_la-asyn-thrdd.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-bufq.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-bufref.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-cf-h1-proxy.Plo
@@ -5520,7 +5675,6 @@ maintainer-clean: maintainer-clean-am
-rm -f ./$(DEPDIR)/libcurlu_la-curl_gethostname.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-curl_gssapi.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-curl_memrchr.Plo
- -rm -f ./$(DEPDIR)/libcurlu_la-curl_multibyte.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-curl_ntlm_core.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-curl_range.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-curl_rtmp.Plo
@@ -5534,12 +5688,12 @@ maintainer-clean: maintainer-clean-am
-rm -f ./$(DEPDIR)/libcurlu_la-dict.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-dllmain.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-doh.Plo
- -rm -f ./$(DEPDIR)/libcurlu_la-dynbuf.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-dynhds.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-easy.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-easygetopt.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-easyoptions.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-escape.Plo
+ -rm -f ./$(DEPDIR)/libcurlu_la-fake_addrinfo.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-file.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-fileinfo.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-fopen.Plo
@@ -5550,14 +5704,11 @@ maintainer-clean: maintainer-clean-am
-rm -f ./$(DEPDIR)/libcurlu_la-getinfo.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-gopher.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-hash.Plo
- -rm -f ./$(DEPDIR)/libcurlu_la-hash_offt.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-headers.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-hmac.Plo
- -rm -f ./$(DEPDIR)/libcurlu_la-hostasyn.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-hostip.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-hostip4.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-hostip6.Plo
- -rm -f ./$(DEPDIR)/libcurlu_la-hostsyn.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-hsts.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-http.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-http1.Plo
@@ -5573,7 +5724,6 @@ maintainer-clean: maintainer-clean-am
-rm -f ./$(DEPDIR)/libcurlu_la-if2ip.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-imap.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-inet_ntop.Plo
- -rm -f ./$(DEPDIR)/libcurlu_la-inet_pton.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-krb5.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-ldap.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-libcurl_unity.Plo
@@ -5588,7 +5738,6 @@ maintainer-clean: maintainer-clean-am
-rm -f ./$(DEPDIR)/libcurlu_la-multi.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-multi_ev.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-netrc.Plo
- -rm -f ./$(DEPDIR)/libcurlu_la-nonblock.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-noproxy.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-openldap.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-parsedate.Plo
@@ -5618,19 +5767,40 @@ maintainer-clean: maintainer-clean-am
-rm -f ./$(DEPDIR)/libcurlu_la-strdup.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-strequal.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-strerror.Plo
- -rm -f ./$(DEPDIR)/libcurlu_la-strparse.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-system_win32.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-telnet.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-tftp.Plo
- -rm -f ./$(DEPDIR)/libcurlu_la-timediff.Plo
- -rm -f ./$(DEPDIR)/libcurlu_la-timeval.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-transfer.Plo
+ -rm -f ./$(DEPDIR)/libcurlu_la-uint-bset.Plo
+ -rm -f ./$(DEPDIR)/libcurlu_la-uint-hash.Plo
+ -rm -f ./$(DEPDIR)/libcurlu_la-uint-spbset.Plo
+ -rm -f ./$(DEPDIR)/libcurlu_la-uint-table.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-url.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-urlapi.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-version.Plo
- -rm -f ./$(DEPDIR)/libcurlu_la-version_win32.Plo
- -rm -f ./$(DEPDIR)/libcurlu_la-warnless.Plo
-rm -f ./$(DEPDIR)/libcurlu_la-ws.Plo
+ -rm -f curlx/$(DEPDIR)/libcurl_la-base64.Plo
+ -rm -f curlx/$(DEPDIR)/libcurl_la-dynbuf.Plo
+ -rm -f curlx/$(DEPDIR)/libcurl_la-inet_pton.Plo
+ -rm -f curlx/$(DEPDIR)/libcurl_la-multibyte.Plo
+ -rm -f curlx/$(DEPDIR)/libcurl_la-nonblock.Plo
+ -rm -f curlx/$(DEPDIR)/libcurl_la-strparse.Plo
+ -rm -f curlx/$(DEPDIR)/libcurl_la-timediff.Plo
+ -rm -f curlx/$(DEPDIR)/libcurl_la-timeval.Plo
+ -rm -f curlx/$(DEPDIR)/libcurl_la-version_win32.Plo
+ -rm -f curlx/$(DEPDIR)/libcurl_la-warnless.Plo
+ -rm -f curlx/$(DEPDIR)/libcurl_la-winapi.Plo
+ -rm -f curlx/$(DEPDIR)/libcurlu_la-base64.Plo
+ -rm -f curlx/$(DEPDIR)/libcurlu_la-dynbuf.Plo
+ -rm -f curlx/$(DEPDIR)/libcurlu_la-inet_pton.Plo
+ -rm -f curlx/$(DEPDIR)/libcurlu_la-multibyte.Plo
+ -rm -f curlx/$(DEPDIR)/libcurlu_la-nonblock.Plo
+ -rm -f curlx/$(DEPDIR)/libcurlu_la-strparse.Plo
+ -rm -f curlx/$(DEPDIR)/libcurlu_la-timediff.Plo
+ -rm -f curlx/$(DEPDIR)/libcurlu_la-timeval.Plo
+ -rm -f curlx/$(DEPDIR)/libcurlu_la-version_win32.Plo
+ -rm -f curlx/$(DEPDIR)/libcurlu_la-warnless.Plo
+ -rm -f curlx/$(DEPDIR)/libcurlu_la-winapi.Plo
-rm -f vauth/$(DEPDIR)/libcurl_la-cleartext.Plo
-rm -f vauth/$(DEPDIR)/libcurl_la-cram.Plo
-rm -f vauth/$(DEPDIR)/libcurl_la-digest.Plo
@@ -5766,20 +5936,18 @@ uninstall-am: uninstall-libLTLIBRARIES
@HAVE_WINDRES_TRUE@@USE_CPPFLAG_CURL_STATICLIB_FALSE@$(LIB_RCFILES): $(top_srcdir)/include/curl/curlver.h
checksrc:
- $(CHECKSRC)(@PERL@ $(top_srcdir)/scripts/checksrc.pl -D$(srcdir) \
- -W$(srcdir)/libcurl_unity.c -W$(srcdir)/curl_config.h $(srcdir)/*.[ch] \
- $(srcdir)/vauth/*.[ch] $(srcdir)/vtls/*.[ch] $(srcdir)/vquic/*.[ch] \
- $(srcdir)/vssh/*.[ch])
+ $(CHECKSRC)(@PERL@ $(top_srcdir)/scripts/checksrc.pl -D$(srcdir) \
+ $(CSOURCES) $(HHEADERS))
# for debug builds, we scan the sources on all regular make invokes
-@DEBUGBUILD_TRUE@all-local: checksrc
+@DEBUGBUILD_TRUE@@NOT_CURL_CI_TRUE@all-local: checksrc
tidy:
(_csources=`echo ' $(CSOURCES)' | sed -E -e 's/ +$$//' -e 's/ +/ /g' -e 's| | $(srcdir)/|g'`; \
$(TIDY) $$_csources $(TIDYFLAGS) $(CURL_CLANG_TIDYFLAGS) -- $(AM_CPPFLAGS) $(CPPFLAGS) -DHAVE_CONFIG_H)
optiontable:
- perl optiontable.pl < $(top_srcdir)/include/curl/curl.h > easyoptions.c
+ @PERL@ $(srcdir)/optiontable.pl < $(top_srcdir)/include/curl/curl.h > $(srcdir)/easyoptions.c
@HAVE_WINDRES_TRUE@.rc.lo:
@HAVE_WINDRES_TRUE@ $(LIBTOOL) --tag=RC --mode=compile $(RC) -I$(top_srcdir)/include $(RCFLAGS) -i $< -o $@
diff --git a/libs/libcurl/src/Makefile.inc b/libs/libcurl/src/Makefile.inc
index d1a54a1d3c..1b8684a8ba 100644
--- a/libs/libcurl/src/Makefile.inc
+++ b/libs/libcurl/src/Makefile.inc
@@ -22,6 +22,33 @@
#
###########################################################################
+LIB_CURLX_CFILES = \
+ curlx/base64.c \
+ curlx/dynbuf.c \
+ curlx/inet_pton.c \
+ curlx/multibyte.c \
+ curlx/nonblock.c \
+ curlx/strparse.c \
+ curlx/timediff.c \
+ curlx/timeval.c \
+ curlx/version_win32.c \
+ curlx/warnless.c \
+ curlx/winapi.c
+
+LIB_CURLX_HFILES = \
+ curlx/base64.h \
+ curlx/curlx.h \
+ curlx/dynbuf.h \
+ curlx/inet_pton.h \
+ curlx/multibyte.h \
+ curlx/nonblock.h \
+ curlx/strparse.h \
+ curlx/timediff.h \
+ curlx/timeval.h \
+ curlx/version_win32.h \
+ curlx/warnless.h \
+ curlx/winapi.h
+
LIB_VAUTH_CFILES = \
vauth/cleartext.c \
vauth/cram.c \
@@ -111,8 +138,8 @@ LIB_CFILES = \
altsvc.c \
amigaos.c \
asyn-ares.c \
- asyn-thread.c \
- base64.c \
+ asyn-base.c \
+ asyn-thrdd.c \
bufq.c \
bufref.c \
cf-h1-proxy.c \
@@ -122,10 +149,10 @@ LIB_CFILES = \
cf-socket.c \
cfilters.c \
conncache.c \
- cshutdn.c \
connect.c \
content_encoding.c \
cookie.c \
+ cshutdn.c \
curl_addrinfo.c \
curl_des.c \
curl_endian.c \
@@ -134,7 +161,6 @@ LIB_CFILES = \
curl_gethostname.c \
curl_gssapi.c \
curl_memrchr.c \
- curl_multibyte.c \
curl_ntlm_core.c \
curl_range.c \
curl_rtmp.c \
@@ -147,12 +173,12 @@ LIB_CFILES = \
cw-pause.c \
dict.c \
doh.c \
- dynbuf.c \
dynhds.c \
easy.c \
easygetopt.c \
easyoptions.c \
escape.c \
+ fake_addrinfo.c \
file.c \
fileinfo.c \
fopen.c \
@@ -163,14 +189,11 @@ LIB_CFILES = \
getinfo.c \
gopher.c \
hash.c \
- hash_offt.c \
headers.c \
hmac.c \
- hostasyn.c \
hostip.c \
hostip4.c \
hostip6.c \
- hostsyn.c \
hsts.c \
http.c \
http1.c \
@@ -186,7 +209,6 @@ LIB_CFILES = \
if2ip.c \
imap.c \
inet_ntop.c \
- inet_pton.c \
krb5.c \
ldap.c \
llist.c \
@@ -200,7 +222,6 @@ LIB_CFILES = \
multi.c \
multi_ev.c \
netrc.c \
- nonblock.c \
noproxy.c \
openldap.c \
parsedate.c \
@@ -230,18 +251,17 @@ LIB_CFILES = \
strdup.c \
strequal.c \
strerror.c \
- strparse.c \
system_win32.c \
telnet.c \
tftp.c \
- timediff.c \
- timeval.c \
transfer.c \
+ uint-bset.c \
+ uint-hash.c \
+ uint-spbset.c \
+ uint-table.c \
url.c \
urlapi.c \
version.c \
- version_win32.c \
- warnless.c \
ws.c
LIB_HFILES = \
@@ -263,7 +283,6 @@ LIB_HFILES = \
content_encoding.h \
cookie.h \
curl_addrinfo.h \
- curl_base64.h \
curl_ctype.h \
curl_des.h \
curl_endian.h \
@@ -278,7 +297,6 @@ LIB_HFILES = \
curl_md5.h \
curl_memory.h \
curl_memrchr.h \
- curl_multibyte.h \
curl_ntlm_core.h \
curl_printf.h \
curl_range.h \
@@ -291,17 +309,16 @@ LIB_HFILES = \
curl_sspi.h \
curl_threads.h \
curl_trc.h \
- curlx.h \
cw-out.h \
cw-pause.h \
dict.h \
doh.h \
- dynbuf.h \
dynhds.h \
easy_lock.h \
easyif.h \
easyoptions.h \
escape.h \
+ fake_addrinfo.h \
file.h \
fileinfo.h \
fopen.h \
@@ -312,7 +329,6 @@ LIB_HFILES = \
getinfo.h \
gopher.h \
hash.h \
- hash_offt.h \
headers.h \
hostip.h \
hsts.h \
@@ -330,7 +346,6 @@ LIB_HFILES = \
if2ip.h \
imap.h \
inet_ntop.h \
- inet_pton.h \
llist.h \
macos.h \
memdebug.h \
@@ -340,7 +355,6 @@ LIB_HFILES = \
multi_ev.h \
multiif.h \
netrc.h \
- nonblock.h \
noproxy.h \
parsedate.h \
pingpong.h \
@@ -370,23 +384,22 @@ LIB_HFILES = \
strcase.h \
strdup.h \
strerror.h \
- strparse.h \
system_win32.h \
telnet.h \
tftp.h \
- timediff.h \
- timeval.h \
transfer.h \
+ uint-bset.h \
+ uint-hash.h \
+ uint-spbset.h \
+ uint-table.h \
url.h \
urlapi-int.h \
urldata.h \
- version_win32.h \
- warnless.h \
ws.h
LIB_RCFILES = libcurl.rc
CSOURCES = $(LIB_CFILES) $(LIB_VAUTH_CFILES) $(LIB_VTLS_CFILES) \
- $(LIB_VQUIC_CFILES) $(LIB_VSSH_CFILES)
+ $(LIB_VQUIC_CFILES) $(LIB_VSSH_CFILES) $(LIB_CURLX_CFILES)
HHEADERS = $(LIB_HFILES) $(LIB_VAUTH_HFILES) $(LIB_VTLS_HFILES) \
- $(LIB_VQUIC_HFILES) $(LIB_VSSH_HFILES)
+ $(LIB_VQUIC_HFILES) $(LIB_VSSH_HFILES) $(LIB_CURLX_HFILES)
diff --git a/libs/libcurl/src/altsvc.c b/libs/libcurl/src/altsvc.c
index 89f2a100f9..fd568742bb 100644
--- a/libs/libcurl/src/altsvc.c
+++ b/libs/libcurl/src/altsvc.c
@@ -35,12 +35,12 @@
#include "strcase.h"
#include "parsedate.h"
#include "sendf.h"
-#include "warnless.h"
+#include "curlx/warnless.h"
#include "fopen.h"
#include "rename.h"
#include "strdup.h"
-#include "inet_pton.h"
-#include "strparse.h"
+#include "curlx/inet_pton.h"
+#include "curlx/strparse.h"
#include "connect.h"
/* The last 3 #include files should be in this order */
@@ -139,13 +139,13 @@ static struct altsvc *altsvc_create(struct Curl_str *srchost,
size_t dstport)
{
enum alpnid dstalpnid =
- Curl_alpn2alpnid(Curl_str(dstalpn), Curl_strlen(dstalpn));
+ Curl_alpn2alpnid(curlx_str(dstalpn), curlx_strlen(dstalpn));
enum alpnid srcalpnid =
- Curl_alpn2alpnid(Curl_str(srcalpn), Curl_strlen(srcalpn));
+ Curl_alpn2alpnid(curlx_str(srcalpn), curlx_strlen(srcalpn));
if(!srcalpnid || !dstalpnid)
return NULL;
- return altsvc_createid(Curl_str(srchost), Curl_strlen(srchost),
- Curl_str(dsthost), Curl_strlen(dsthost),
+ return altsvc_createid(curlx_str(srchost), curlx_strlen(srchost),
+ curlx_str(dsthost), curlx_strlen(dsthost),
srcalpnid, dstalpnid,
srcport, dstport);
}
@@ -166,24 +166,24 @@ static CURLcode altsvc_add(struct altsvcinfo *asi, const char *line)
curl_off_t persist;
curl_off_t prio;
- if(Curl_str_word(&line, &srcalpn, MAX_ALTSVC_ALPNLEN) ||
- Curl_str_singlespace(&line) ||
- Curl_str_word(&line, &srchost, MAX_ALTSVC_HOSTLEN) ||
- Curl_str_singlespace(&line) ||
- Curl_str_number(&line, &srcport, 65535) ||
- Curl_str_singlespace(&line) ||
- Curl_str_word(&line, &dstalpn, MAX_ALTSVC_ALPNLEN) ||
- Curl_str_singlespace(&line) ||
- Curl_str_word(&line, &dsthost, MAX_ALTSVC_HOSTLEN) ||
- Curl_str_singlespace(&line) ||
- Curl_str_number(&line, &dstport, 65535) ||
- Curl_str_singlespace(&line) ||
- Curl_str_quotedword(&line, &date, MAX_ALTSVC_DATELEN) ||
- Curl_str_singlespace(&line) ||
- Curl_str_number(&line, &persist, 1) ||
- Curl_str_singlespace(&line) ||
- Curl_str_number(&line, &prio, 0) ||
- Curl_str_newline(&line))
+ if(curlx_str_word(&line, &srcalpn, MAX_ALTSVC_ALPNLEN) ||
+ curlx_str_singlespace(&line) ||
+ curlx_str_word(&line, &srchost, MAX_ALTSVC_HOSTLEN) ||
+ curlx_str_singlespace(&line) ||
+ curlx_str_number(&line, &srcport, 65535) ||
+ curlx_str_singlespace(&line) ||
+ curlx_str_word(&line, &dstalpn, MAX_ALTSVC_ALPNLEN) ||
+ curlx_str_singlespace(&line) ||
+ curlx_str_word(&line, &dsthost, MAX_ALTSVC_HOSTLEN) ||
+ curlx_str_singlespace(&line) ||
+ curlx_str_number(&line, &dstport, 65535) ||
+ curlx_str_singlespace(&line) ||
+ curlx_str_quotedword(&line, &date, MAX_ALTSVC_DATELEN) ||
+ curlx_str_singlespace(&line) ||
+ curlx_str_number(&line, &persist, 1) ||
+ curlx_str_singlespace(&line) ||
+ curlx_str_number(&line, &prio, 0) ||
+ curlx_str_newline(&line))
;
else {
struct altsvc *as;
@@ -191,9 +191,9 @@ static CURLcode altsvc_add(struct altsvcinfo *asi, const char *line)
time_t expires;
/* The date parser works on a null terminated string. The maximum length
- is upheld by Curl_str_quotedword(). */
- memcpy(dbuf, Curl_str(&date), Curl_strlen(&date));
- dbuf[Curl_strlen(&date)] = 0;
+ is upheld by curlx_str_quotedword(). */
+ memcpy(dbuf, curlx_str(&date), curlx_strlen(&date));
+ dbuf[curlx_strlen(&date)] = 0;
expires = Curl_getdate_capped(dbuf);
as = altsvc_create(&srchost, &dsthost, &srcalpn, &dstalpn,
(size_t)srcport, (size_t)dstport);
@@ -231,14 +231,14 @@ static CURLcode altsvc_load(struct altsvcinfo *asi, const char *file)
fp = fopen(file, FOPEN_READTEXT);
if(fp) {
struct dynbuf buf;
- Curl_dyn_init(&buf, MAX_ALTSVC_LINE);
+ curlx_dyn_init(&buf, MAX_ALTSVC_LINE);
while(Curl_get_line(&buf, fp)) {
- const char *lineptr = Curl_dyn_ptr(&buf);
- Curl_str_passblanks(&lineptr);
- if(Curl_str_single(&lineptr, '#'))
+ const char *lineptr = curlx_dyn_ptr(&buf);
+ curlx_str_passblanks(&lineptr);
+ if(curlx_str_single(&lineptr, '#'))
altsvc_add(asi, lineptr);
}
- Curl_dyn_free(&buf); /* free the line buffer */
+ curlx_dyn_free(&buf); /* free the line buffer */
fclose(fp);
}
return result;
@@ -447,7 +447,7 @@ static time_t altsvc_debugtime(void *unused)
(void)unused;
if(timestr) {
curl_off_t val;
- Curl_str_number(&timestr, &val, TIME_T_MAX);
+ curlx_str_number(&timestr, &val, TIME_T_MAX);
return (time_t)val;
}
return time(NULL);
@@ -487,11 +487,11 @@ CURLcode Curl_altsvc_parse(struct Curl_easy *data,
DEBUGASSERT(asi);
/* initial check for "clear" */
- if(!Curl_str_until(&p, &alpn, MAX_ALTSVC_LINE, ';') &&
- !Curl_str_single(&p, ';')) {
- Curl_str_trimblanks(&alpn);
+ if(!curlx_str_until(&p, &alpn, MAX_ALTSVC_LINE, ';') &&
+ !curlx_str_single(&p, ';')) {
+ curlx_str_trimblanks(&alpn);
/* "clear" is a magic keyword */
- if(Curl_str_casecompare(&alpn, "clear")) {
+ if(curlx_str_casecompare(&alpn, "clear")) {
/* Flush cached alternatives for this source origin */
altsvc_flush(asi, srcalpnid, srchost, srcport);
return CURLE_OK;
@@ -500,10 +500,10 @@ CURLcode Curl_altsvc_parse(struct Curl_easy *data,
p = value;
- if(Curl_str_until(&p, &alpn, MAX_ALTSVC_LINE, '='))
+ if(curlx_str_until(&p, &alpn, MAX_ALTSVC_LINE, '='))
return CURLE_OK; /* strange line */
- Curl_str_trimblanks(&alpn);
+ curlx_str_trimblanks(&alpn);
/* Handle the optional 'ma' and 'persist' flags once first, as they need to
be known for each alternative service. Unknown flags are skipped. */
@@ -517,69 +517,69 @@ CURLcode Curl_altsvc_parse(struct Curl_easy *data,
curl_off_t num;
bool quoted;
/* allow some extra whitespaces around name and value */
- if(Curl_str_until(&sp, &name, 20, '=') ||
- Curl_str_single(&sp, '=') ||
- Curl_str_until(&sp, &val, 80, ';'))
+ if(curlx_str_until(&sp, &name, 20, '=') ||
+ curlx_str_single(&sp, '=') ||
+ curlx_str_until(&sp, &val, 80, ';'))
break;
- Curl_str_trimblanks(&name);
- Curl_str_trimblanks(&val);
+ curlx_str_trimblanks(&name);
+ curlx_str_trimblanks(&val);
/* the value might be quoted */
- vp = Curl_str(&val);
+ vp = curlx_str(&val);
quoted = (*vp == '\"');
if(quoted)
vp++;
- if(!Curl_str_number(&vp, &num, TIME_T_MAX)) {
- if(Curl_str_casecompare(&name, "ma"))
+ if(!curlx_str_number(&vp, &num, TIME_T_MAX)) {
+ if(curlx_str_casecompare(&name, "ma"))
maxage = (time_t)num;
- else if(Curl_str_casecompare(&name, "persist") && (num == 1))
+ else if(curlx_str_casecompare(&name, "persist") && (num == 1))
persist = TRUE;
}
- if(quoted && Curl_str_single(&sp, '\"'))
+ if(quoted && curlx_str_single(&sp, '\"'))
break;
- if(Curl_str_single(&sp, ';'))
+ if(curlx_str_single(&sp, ';'))
break;
}
}
do {
- if(!Curl_str_single(&p, '=')) {
+ if(!curlx_str_single(&p, '=')) {
/* [protocol]="[host][:port], [protocol]="[host][:port]" */
enum alpnid dstalpnid =
- Curl_alpn2alpnid(Curl_str(&alpn), Curl_strlen(&alpn));
- if(!Curl_str_single(&p, '\"')) {
+ Curl_alpn2alpnid(curlx_str(&alpn), curlx_strlen(&alpn));
+ if(!curlx_str_single(&p, '\"')) {
struct Curl_str dsthost;
curl_off_t port = 0;
- if(Curl_str_single(&p, ':')) {
+ if(curlx_str_single(&p, ':')) {
/* hostname starts here */
- if(Curl_str_single(&p, '[')) {
- if(Curl_str_until(&p, &dsthost, MAX_ALTSVC_HOSTLEN, ':')) {
+ if(curlx_str_single(&p, '[')) {
+ if(curlx_str_until(&p, &dsthost, MAX_ALTSVC_HOSTLEN, ':')) {
infof(data, "Bad alt-svc hostname, ignoring.");
break;
}
}
else {
/* IPv6 host name */
- if(Curl_str_until(&p, &dsthost, MAX_IPADR_LEN, ']') ||
- Curl_str_single(&p, ']')) {
+ if(curlx_str_until(&p, &dsthost, MAX_IPADR_LEN, ']') ||
+ curlx_str_single(&p, ']')) {
infof(data, "Bad alt-svc IPv6 hostname, ignoring.");
break;
}
}
- if(Curl_str_single(&p, ':'))
+ if(curlx_str_single(&p, ':'))
break;
}
else
/* no destination name, use source host */
- Curl_str_assign(&dsthost, srchost, strlen(srchost));
+ curlx_str_assign(&dsthost, srchost, strlen(srchost));
- if(Curl_str_number(&p, &port, 0xffff)) {
+ if(curlx_str_number(&p, &port, 0xffff)) {
infof(data, "Unknown alt-svc port number, ignoring.");
break;
}
dstport = (unsigned short)port;
- if(Curl_str_single(&p, '\"'))
+ if(curlx_str_single(&p, '\"'))
break;
if(dstalpnid) {
@@ -589,8 +589,8 @@ CURLcode Curl_altsvc_parse(struct Curl_easy *data,
altsvc_flush(asi, srcalpnid, srchost, srcport);
as = altsvc_createid(srchost, strlen(srchost),
- Curl_str(&dsthost),
- Curl_strlen(&dsthost),
+ curlx_str(&dsthost),
+ curlx_strlen(&dsthost),
srcalpnid, dstalpnid,
srcport, dstport);
if(as) {
@@ -604,7 +604,7 @@ CURLcode Curl_altsvc_parse(struct Curl_easy *data,
as->persist = persist;
Curl_llist_append(&asi->list, as, &as->node);
infof(data, "Added alt-svc: %.*s:%d over %s",
- (int)Curl_strlen(&dsthost), Curl_str(&dsthost),
+ (int)curlx_strlen(&dsthost), curlx_str(&dsthost),
dstport, Curl_alpnid2str(dstalpnid));
}
}
@@ -614,13 +614,13 @@ CURLcode Curl_altsvc_parse(struct Curl_easy *data,
/* after the double quote there can be a comma if there is another
string or a semicolon if no more */
- if(Curl_str_single(&p, ','))
+ if(curlx_str_single(&p, ','))
break;
/* comma means another alternative is present */
- if(Curl_str_until(&p, &alpn, MAX_ALTSVC_LINE, '='))
+ if(curlx_str_until(&p, &alpn, MAX_ALTSVC_LINE, '='))
break;
- Curl_str_trimblanks(&alpn);
+ curlx_str_trimblanks(&alpn);
}
else
break;
diff --git a/libs/libcurl/src/altsvc.h b/libs/libcurl/src/altsvc.h
index 917f6d38a2..8b2293a813 100644
--- a/libs/libcurl/src/altsvc.h
+++ b/libs/libcurl/src/altsvc.h
@@ -39,9 +39,9 @@ struct altsvc {
struct althost src;
struct althost dst;
time_t expires;
- bool persist;
- unsigned int prio;
struct Curl_llist_node node;
+ unsigned int prio;
+ BIT(persist);
};
struct altsvcinfo {
diff --git a/libs/libcurl/src/asyn-ares.c b/libs/libcurl/src/asyn-ares.c
index 389a6cc1ad..e97810c1b9 100644
--- a/libs/libcurl/src/asyn-ares.c
+++ b/libs/libcurl/src/asyn-ares.c
@@ -24,7 +24,7 @@
#include "curl_setup.h"
-#ifdef USE_ARES
+#ifdef CURLRES_ARES
/***********************************************************************
* Only for ares-enabled builds
@@ -54,11 +54,11 @@
#include "share.h"
#include "url.h"
#include "multiif.h"
-#include "inet_pton.h"
+#include "curlx/inet_pton.h"
#include "connect.h"
#include "select.h"
#include "progress.h"
-#include "timediff.h"
+#include "curlx/timediff.h"
#include "httpsrr.h"
#include "strdup.h"
@@ -66,109 +66,6 @@
#include <ares_version.h> /* really old c-ares did not include this by
itself */
-#ifdef USE_HTTPSRR
-/* 1.28.0 and later have ares_query_dnsrec */
-#if ARES_VERSION < 0x011c00
-#error "requires c-ares 1.28.0 or newer for HTTPSRR"
-#endif
-#define HTTPSRR_WORKS
-#else
-#if ARES_VERSION < 0x010600
-#error "requires c-ares 1.6.0 or newer"
-#endif
-#endif
-
-/*
- * Curl_ares_getsock() is called when the outside world (using
- * curl_multi_fdset()) wants to get our fd_set setup and we are talking with
- * ares. The caller must make sure that this function is only called when we
- * have a working ares channel.
- *
- * Returns: sockets-in-use-bitmap
- */
-
-int Curl_ares_getsock(struct Curl_easy *data,
- ares_channel channel,
- curl_socket_t *socks)
-{
- struct timeval maxtime = { CURL_TIMEOUT_RESOLVE, 0 };
- struct timeval timebuf;
- int max = ares_getsock(channel,
- (ares_socket_t *)socks, MAX_SOCKSPEREASYHANDLE);
- struct timeval *timeout = ares_timeout(channel, &maxtime, &timebuf);
- timediff_t milli = curlx_tvtoms(timeout);
- Curl_expire(data, milli, EXPIRE_ASYNC_NAME);
- return max;
-}
-
-/*
- * Curl_ares_perform()
- *
- * 1) Ask ares what sockets it currently plays with, then
- * 2) wait for the timeout period to check for action on ares' sockets.
- * 3) tell ares to act on all the sockets marked as "with action"
- *
- * return number of sockets it worked on, or -1 on error
- */
-
-int Curl_ares_perform(ares_channel channel,
- timediff_t timeout_ms)
-{
- int nfds;
- int bitmask;
- ares_socket_t socks[ARES_GETSOCK_MAXNUM];
- struct pollfd pfd[ARES_GETSOCK_MAXNUM];
- int i;
- int num = 0;
-
- if(!channel)
- return 0;
-
- bitmask = ares_getsock(channel, socks, ARES_GETSOCK_MAXNUM);
-
- for(i = 0; i < ARES_GETSOCK_MAXNUM; i++) {
- pfd[i].events = 0;
- pfd[i].revents = 0;
- if(ARES_GETSOCK_READABLE(bitmask, i)) {
- pfd[i].fd = socks[i];
- pfd[i].events |= POLLRDNORM|POLLIN;
- }
- if(ARES_GETSOCK_WRITABLE(bitmask, i)) {
- pfd[i].fd = socks[i];
- pfd[i].events |= POLLWRNORM|POLLOUT;
- }
- if(pfd[i].events)
- num++;
- else
- break;
- }
-
- if(num) {
- nfds = Curl_poll(pfd, (unsigned int)num, timeout_ms);
- if(nfds < 0)
- return -1;
- }
- else
- nfds = 0;
-
- if(!nfds)
- /* Call ares_process() unconditionally here, even if we simply timed out
- above, as otherwise the ares name resolve will not timeout! */
- ares_process_fd(channel, ARES_SOCKET_BAD, ARES_SOCKET_BAD);
- else {
- /* move through the descriptors and ask for processing on them */
- for(i = 0; i < num; i++)
- ares_process_fd(channel,
- (pfd[i].revents & (POLLRDNORM|POLLIN)) ?
- pfd[i].fd : ARES_SOCKET_BAD,
- (pfd[i].revents & (POLLWRNORM|POLLOUT)) ?
- pfd[i].fd : ARES_SOCKET_BAD);
- }
- return nfds;
-}
-
-#ifdef CURLRES_ARES
-
#if ARES_VERSION >= 0x010601
/* IPv6 supported since 1.6.1 */
#define HAVE_CARES_IPV6 1
@@ -189,6 +86,13 @@ int Curl_ares_perform(ares_channel channel,
#define HAVE_CARES_GETADDRINFO 1
#endif
+#ifdef USE_HTTPSRR
+#if ARES_VERSION < 0x011c00
+#error "requires c-ares 1.28.0 or newer for HTTPSRR"
+#endif
+#define HTTPSRR_WORKS
+#endif
+
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h"
@@ -209,12 +113,15 @@ int Curl_ares_perform(ares_channel channel,
static int ares_ver = 0;
+static CURLcode async_ares_set_dns_servers(struct Curl_easy *data,
+ bool reset_on_null);
+
/*
- * Curl_resolver_global_init() - the generic low-level asynchronous name
+ * Curl_async_global_init() - the generic low-level asynchronous name
* resolve API. Called from curl_global_init() to initialize global resolver
* environment. Initializes ares library.
*/
-int Curl_resolver_global_init(void)
+int Curl_async_global_init(void)
{
#ifdef CARES_HAVE_ARES_LIBRARY_INIT
if(ares_library_init(ARES_LIB_INIT_ALL)) {
@@ -226,12 +133,12 @@ int Curl_resolver_global_init(void)
}
/*
- * Curl_resolver_global_cleanup()
+ * Curl_async_global_cleanup()
*
* Called from curl_global_cleanup() to destroy global resolver environment.
* Deinitializes ares library.
*/
-void Curl_resolver_global_cleanup(void)
+void Curl_async_global_cleanup(void)
{
#ifdef CARES_HAVE_ARES_LIBRARY_CLEANUP
ares_library_cleanup();
@@ -249,21 +156,18 @@ static void sock_state_cb(void *data, ares_socket_t socket_fd,
}
}
-/*
- * Curl_resolver_init()
- *
- * Called from curl_easy_init() -> Curl_open() to initialize resolver
- * URL-state specific environment ('resolver' member of the UrlState
- * structure). Fills the passed pointer by the initialized ares_channel.
- */
-CURLcode Curl_resolver_init(struct Curl_easy *easy, void **resolver)
+static CURLcode async_ares_init(struct Curl_easy *data)
{
+ struct async_ares_ctx *ares = &data->state.async.ares;
int status;
struct ares_options options;
int optmask = ARES_OPT_SOCK_STATE_CB;
+ CURLcode rc = CURLE_OK;
+
options.sock_state_cb = sock_state_cb;
- options.sock_state_cb_data = easy;
+ options.sock_state_cb_data = data;
+ DEBUGASSERT(!ares->channel);
/*
if c ares < 1.20.0: curl set timeout to CARES_TIMEOUT_PER_ATTEMPT (2s)
@@ -279,169 +183,193 @@ CURLcode Curl_resolver_init(struct Curl_easy *easy, void **resolver)
optmask |= ARES_OPT_TIMEOUTMS;
}
- status = ares_init_options((ares_channel*)resolver, &options, optmask);
+ status = ares_init_options(&ares->channel, &options, optmask);
if(status != ARES_SUCCESS) {
- if(status == ARES_ENOMEM)
- return CURLE_OUT_OF_MEMORY;
- else
- return CURLE_FAILED_INIT;
+ ares->channel = NULL;
+ rc = (status == ARES_ENOMEM) ?
+ CURLE_OUT_OF_MEMORY : CURLE_FAILED_INIT;
+ goto out;
}
- return CURLE_OK;
- /* make sure that all other returns from this function should destroy the
- ares channel before returning error! */
+
+ rc = async_ares_set_dns_servers(data, FALSE);
+ if(rc && rc != CURLE_NOT_BUILT_IN)
+ goto out;
+
+ rc = Curl_async_ares_set_dns_interface(data);
+ if(rc && rc != CURLE_NOT_BUILT_IN)
+ goto out;
+
+ rc = Curl_async_ares_set_dns_local_ip4(data);
+ if(rc && rc != CURLE_NOT_BUILT_IN)
+ goto out;
+
+ rc = Curl_async_ares_set_dns_local_ip6(data);
+ if(rc && rc != CURLE_NOT_BUILT_IN)
+ goto out;
+
+ rc = CURLE_OK;
+
+out:
+ if(rc && ares->channel) {
+ ares_destroy(ares->channel);
+ ares->channel = NULL;
+ }
+ return rc;
}
-/*
- * Curl_resolver_cleanup()
- *
- * Called from curl_easy_cleanup() -> Curl_close() to cleanup resolver
- * URL-state specific environment ('resolver' member of the UrlState
- * structure). Destroys the ares channel.
- */
-void Curl_resolver_cleanup(void *resolver)
+static CURLcode async_ares_init_lazy(struct Curl_easy *data)
{
- ares_destroy((ares_channel)resolver);
+ struct async_ares_ctx *ares = &data->state.async.ares;
+ if(!ares->channel)
+ return async_ares_init(data);
+ return CURLE_OK;
}
-/*
- * Curl_resolver_duphandle()
- *
- * Called from curl_easy_duphandle() to duplicate resolver URL-state specific
- * environment ('resolver' member of the UrlState structure). Duplicates the
- * 'from' ares channel and passes the resulting channel to the 'to' pointer.
- */
-CURLcode Curl_resolver_duphandle(struct Curl_easy *easy, void **to, void *from)
+CURLcode Curl_async_get_impl(struct Curl_easy *data, void **impl)
{
- (void)from;
- /*
- * it would be better to call ares_dup instead, but right now
- * it is not possible to set 'sock_state_cb_data' outside of
- * ares_init_options
- */
- return Curl_resolver_init(easy, to);
+ struct async_ares_ctx *ares = &data->state.async.ares;
+ CURLcode result = CURLE_OK;
+ if(!ares->channel) {
+ result = async_ares_init(data);
+ }
+ *impl = ares->channel;
+ return result;
}
-static void destroy_async_data(struct Curl_async *async);
+static void async_ares_cleanup(struct Curl_easy *data);
-/*
- * Cancel all possibly still on-going resolves for this connection.
- */
-void Curl_resolver_cancel(struct Curl_easy *data)
+void Curl_async_ares_shutdown(struct Curl_easy *data)
{
- DEBUGASSERT(data);
- if(data->state.async.resolver)
- ares_cancel((ares_channel)data->state.async.resolver);
- destroy_async_data(&data->state.async);
+ struct async_ares_ctx *ares = &data->state.async.ares;
+ if(ares->channel)
+ ares_cancel(ares->channel);
+ async_ares_cleanup(data);
}
-/*
- * We are equivalent to Curl_resolver_cancel() for the c-ares resolver. We
- * never block.
- */
-void Curl_resolver_kill(struct Curl_easy *data)
+void Curl_async_ares_destroy(struct Curl_easy *data)
{
- /* We do not need to check the resolver state because we can be called safely
- at any time and we always do the same thing. */
- Curl_resolver_cancel(data);
+ struct async_ares_ctx *ares = &data->state.async.ares;
+ Curl_async_ares_shutdown(data);
+ if(ares->channel) {
+ ares_destroy(ares->channel);
+ ares->channel = NULL;
+ }
}
/*
- * destroy_async_data() cleans up async resolver data.
+ * async_ares_cleanup() cleans up async resolver data.
*/
-static void destroy_async_data(struct Curl_async *async)
+static void async_ares_cleanup(struct Curl_easy *data)
{
- struct thread_data *res = &async->thdata;
- if(res->temp_ai) {
- Curl_freeaddrinfo(res->temp_ai);
- res->temp_ai = NULL;
+ struct async_ares_ctx *ares = &data->state.async.ares;
+ if(ares->temp_ai) {
+ Curl_freeaddrinfo(ares->temp_ai);
+ ares->temp_ai = NULL;
}
- Curl_safefree(res->hostname);
+#ifdef USE_HTTPSRR
+ Curl_httpsrr_cleanup(&ares->hinfo);
+#endif
}
/*
- * Curl_resolver_getsock() is called when someone from the outside world
+ * Curl_async_getsock() is called when someone from the outside world
* (using curl_multi_fdset()) wants to get our fd_set setup.
*/
-int Curl_resolver_getsock(struct Curl_easy *data, curl_socket_t *socks)
+int Curl_async_getsock(struct Curl_easy *data, curl_socket_t *socks)
{
- return Curl_ares_getsock(data, (ares_channel)data->state.async.resolver,
- socks);
+ struct async_ares_ctx *ares = &data->state.async.ares;
+ DEBUGASSERT(ares->channel);
+ return Curl_ares_getsock(data, ares->channel, socks);
}
/*
- * Curl_resolver_is_resolved() is called repeatedly to check if a previous
+ * Curl_async_is_resolved() is called repeatedly to check if a previous
* name resolve request has completed. It should also make sure to time-out if
* the operation seems to take too long.
*
* Returns normal CURLcode errors.
*/
-CURLcode Curl_resolver_is_resolved(struct Curl_easy *data,
- struct Curl_dns_entry **dns)
+CURLcode Curl_async_is_resolved(struct Curl_easy *data,
+ struct Curl_dns_entry **dns)
{
- struct thread_data *res = &data->state.async.thdata;
+ struct async_ares_ctx *ares = &data->state.async.ares;
CURLcode result = CURLE_OK;
DEBUGASSERT(dns);
*dns = NULL;
- if(Curl_ares_perform((ares_channel)data->state.async.resolver, 0) < 0)
+ if(data->state.async.done) {
+ *dns = data->state.async.dns;
+ return CURLE_OK;
+ }
+
+ if(Curl_ares_perform(ares->channel, 0) < 0)
return CURLE_UNRECOVERABLE_POLL;
#ifndef HAVE_CARES_GETADDRINFO
/* Now that we have checked for any last minute results above, see if there
are any responses still pending when the EXPIRE_HAPPY_EYEBALLS_DNS timer
expires. */
- if(res->num_pending
+ if(ares->num_pending
/* This is only set to non-zero if the timer was started. */
- && (res->happy_eyeballs_dns_time.tv_sec
- || res->happy_eyeballs_dns_time.tv_usec)
- && (Curl_timediff(Curl_now(), res->happy_eyeballs_dns_time)
+ && (ares->happy_eyeballs_dns_time.tv_sec
+ || ares->happy_eyeballs_dns_time.tv_usec)
+ && (curlx_timediff(curlx_now(), ares->happy_eyeballs_dns_time)
>= HAPPY_EYEBALLS_DNS_TIMEOUT)) {
/* Remember that the EXPIRE_HAPPY_EYEBALLS_DNS timer is no longer
running. */
- memset(
- &res->happy_eyeballs_dns_time, 0, sizeof(res->happy_eyeballs_dns_time));
+ memset(&ares->happy_eyeballs_dns_time, 0,
+ sizeof(ares->happy_eyeballs_dns_time));
/* Cancel the raw c-ares request, which will fire query_completed_cb() with
ARES_ECANCELLED synchronously for all pending responses. This will
leave us with res->num_pending == 0, which is perfect for the next
block. */
- ares_cancel((ares_channel)data->state.async.resolver);
- DEBUGASSERT(res->num_pending == 0);
+ ares_cancel(ares->channel);
+ DEBUGASSERT(ares->num_pending == 0);
}
#endif
- if(!res->num_pending) {
- (void)Curl_addrinfo_callback(data, res->last_status, res->temp_ai);
- /* temp_ai ownership is moved to the connection, so we need not free-up
- them */
- res->temp_ai = NULL;
-
- result = res->result;
- if(!data->state.async.dns)
- result = Curl_resolver_error(data);
- if(!result) {
- *dns = data->state.async.dns;
+ if(!ares->num_pending) {
+ /* all c-ares operations done, what is the result to report? */
+ Curl_resolv_unlink(data, &data->state.async.dns);
+ data->state.async.done = TRUE;
+ result = ares->result;
+ if(ares->last_status == CURL_ASYNC_SUCCESS && !result) {
+ data->state.async.dns =
+ Curl_dnscache_mk_entry(data, ares->temp_ai,
+ data->state.async.hostname, 0,
+ data->state.async.port, FALSE);
+ ares->temp_ai = NULL; /* temp_ai now owned by entry */
#ifdef HTTPSRR_WORKS
- {
- struct Curl_https_rrinfo *lhrr = Curl_httpsrr_dup_move(&res->hinfo);
- if(!lhrr)
- result = CURLE_OUT_OF_MEMORY;
- else
- (*dns)->hinfo = lhrr;
- }
+ if(data->state.async.dns) {
+ struct Curl_https_rrinfo *lhrr = Curl_httpsrr_dup_move(&ares->hinfo);
+ if(!lhrr)
+ result = CURLE_OUT_OF_MEMORY;
+ else
+ data->state.async.dns->hinfo = lhrr;
+ }
#endif
+ if(!result && data->state.async.dns)
+ result = Curl_dnscache_add(data, data->state.async.dns);
}
-
- destroy_async_data(&data->state.async);
+ /* if we have not found anything, report the proper
+ * CURLE_COULDNT_RESOLVE_* code */
+ if(!result && !data->state.async.dns)
+ result = Curl_resolver_error(data);
+ if(result)
+ Curl_resolv_unlink(data, &data->state.async.dns);
+ *dns = data->state.async.dns;
+ CURL_TRC_DNS(data, "is_resolved() result=%d, dns=%sfound",
+ result, *dns ? "" : "not ");
+ async_ares_cleanup(data);
}
-
return result;
}
/*
- * Curl_resolver_wait_resolv()
+ * Curl_async_await()
*
* Waits for a resolve to finish. This function should be avoided since using
* this risk getting the multi interface to "hang".
@@ -451,12 +379,13 @@ CURLcode Curl_resolver_is_resolved(struct Curl_easy *data,
* Returns CURLE_COULDNT_RESOLVE_HOST if the host was not resolved,
* CURLE_OPERATION_TIMEDOUT if a time-out occurred, or other errors.
*/
-CURLcode Curl_resolver_wait_resolv(struct Curl_easy *data,
- struct Curl_dns_entry **entry)
+CURLcode Curl_async_await(struct Curl_easy *data,
+ struct Curl_dns_entry **entry)
{
+ struct async_ares_ctx *ares = &data->state.async.ares;
CURLcode result = CURLE_OK;
timediff_t timeout;
- struct curltime now = Curl_now();
+ struct curltime now = curlx_now();
DEBUGASSERT(entry);
*entry = NULL; /* clear on entry */
@@ -485,7 +414,7 @@ CURLcode Curl_resolver_wait_resolv(struct Curl_easy *data,
store.tv_sec = itimeout/1000;
store.tv_usec = (itimeout%1000)*1000;
- tvp = ares_timeout((ares_channel)data->state.async.resolver, &store, &tv);
+ tvp = ares_timeout(ares->channel, &store, &tv);
/* use the timeout period ares returned to us above if less than one
second is left, otherwise just use 1000ms to make sure the progress
@@ -495,19 +424,18 @@ CURLcode Curl_resolver_wait_resolv(struct Curl_easy *data,
else
timeout_ms = 1000;
- if(Curl_ares_perform((ares_channel)data->state.async.resolver,
- timeout_ms) < 0)
+ if(Curl_ares_perform(ares->channel, timeout_ms) < 0)
return CURLE_UNRECOVERABLE_POLL;
- result = Curl_resolver_is_resolved(data, entry);
+ result = Curl_async_is_resolved(data, entry);
if(result || data->state.async.done)
break;
if(Curl_pgrsUpdate(data))
result = CURLE_ABORTED_BY_CALLBACK;
else {
- struct curltime now2 = Curl_now();
- timediff_t timediff = Curl_timediff(now2, now); /* spent time */
+ struct curltime now2 = curlx_now();
+ timediff_t timediff = curlx_timediff(now2, now); /* spent time */
if(timediff <= 0)
timeout -= 1; /* always deduct at least 1 */
else if(timediff > timeout)
@@ -519,68 +447,62 @@ CURLcode Curl_resolver_wait_resolv(struct Curl_easy *data,
if(timeout < 0)
result = CURLE_OPERATION_TIMEDOUT;
}
- if(result)
- /* failure, so we cancel the ares operation */
- ares_cancel((ares_channel)data->state.async.resolver);
/* Operation complete, if the lookup was successful we now have the entry
in the cache. */
+ data->state.async.done = TRUE;
if(entry)
*entry = data->state.async.dns;
if(result)
- /* close the connection, since we cannot return failure here without
- cleaning up this connection properly. */
- connclose(data->conn, "c-ares resolve failed");
-
+ ares_cancel(ares->channel);
return result;
}
#ifndef HAVE_CARES_GETADDRINFO
/* Connects results to the list */
-static void compound_results(struct thread_data *res,
- struct Curl_addrinfo *ai)
+static void async_addr_concat(struct Curl_addrinfo **pbase,
+ struct Curl_addrinfo *ai)
{
if(!ai)
return;
+ /* When adding `ai` to an existing address list, we prefer ipv6
+ * to be in front. */
#ifdef USE_IPV6 /* CURLRES_IPV6 */
- if(res->temp_ai && res->temp_ai->ai_family == PF_INET6) {
- /* We have results already, put the new IPv6 entries at the head of the
- list. */
- struct Curl_addrinfo *temp_ai_tail = res->temp_ai;
-
- while(temp_ai_tail->ai_next)
- temp_ai_tail = temp_ai_tail->ai_next;
-
- temp_ai_tail->ai_next = ai;
+ if(*pbase && (*pbase)->ai_family == PF_INET6) {
+ /* ipv6 already in front, append `ai` */
+ struct Curl_addrinfo *tail = *pbase;
+ while(tail->ai_next)
+ tail = tail->ai_next;
+ tail->ai_next = ai;
}
else
#endif /* CURLRES_IPV6 */
{
- /* Add the new results to the list of old results. */
- struct Curl_addrinfo *ai_tail = ai;
- while(ai_tail->ai_next)
- ai_tail = ai_tail->ai_next;
-
- ai_tail->ai_next = res->temp_ai;
- res->temp_ai = ai;
+ /* prepend to the (possibly) existing list. */
+ struct Curl_addrinfo *tail = ai;
+ while(tail->ai_next)
+ tail = tail->ai_next;
+ tail->ai_next = *pbase;
+ *pbase = ai;
}
}
/*
* ares_query_completed_cb() is the callback that ares will call when
- * the host query initiated by ares_gethostbyname() from Curl_getaddrinfo(),
- * when using ares, is completed either successfully or with failure.
+ * the host query initiated by ares_gethostbyname() from
+ * Curl_async_getaddrinfo(), when using ares, is completed either
+ * successfully or with failure.
*/
-static void query_completed_cb(void *arg, /* (struct connectdata *) */
- int status,
- int timeouts,
- struct hostent *hostent)
+static void async_ares_hostbyname_cb(void *user_data,
+ int status,
+ int timeouts,
+ struct hostent *hostent)
{
- struct Curl_easy *data = (struct Curl_easy *)arg;
- struct thread_data *res = &data->state.async.thdata;
+ struct Curl_easy *data = (struct Curl_easy *)user_data;
+ struct async_ares_ctx *ares = &data->state.async.ares;
(void)timeouts; /* ignored */
@@ -589,24 +511,27 @@ static void query_completed_cb(void *arg, /* (struct connectdata *) */
be valid so only defer it when we know the 'status' says its fine! */
return;
- res->num_pending--;
-
if(CURL_ASYNC_SUCCESS == status) {
- struct Curl_addrinfo *ai = Curl_he2ai(hostent, data->state.async.port);
- if(ai) {
- compound_results(res, ai);
- }
+ ares->last_status = status; /* one success overrules any error */
+ async_addr_concat(&ares->temp_ai,
+ Curl_he2ai(hostent, data->state.async.port));
+ }
+ else if(ares->last_status != ARES_SUCCESS) {
+ /* no success so far, remember error */
+ ares->last_status = status;
}
- /* A successful result overwrites any previous error */
- if(res->last_status != ARES_SUCCESS)
- res->last_status = status;
+ ares->num_pending--;
+
+ CURL_TRC_DNS(data, "ares: hostbyname done, status=%d, pending=%d, "
+ "addr=%sfound",
+ status, ares->num_pending, ares->temp_ai ? "" : "not ");
/* If there are responses still pending, we presume they must be the
complementary IPv4 or IPv6 lookups that we started in parallel in
- Curl_resolver_getaddrinfo() (for Happy Eyeballs). If we have got a
+ Curl_async_getaddrinfo() (for Happy Eyeballs). If we have got a
"definitive" response from one of a set of parallel queries, we need to
think about how long we are willing to wait for more responses. */
- if(res->num_pending
+ if(ares->num_pending
/* Only these c-ares status values count as "definitive" for these
purposes. For example, ARES_ENODATA is what we expect when there is
no IPv6 entry for a domain name, and that is not a reason to get more
@@ -617,7 +542,7 @@ static void query_completed_cb(void *arg, /* (struct connectdata *) */
&& (status == ARES_SUCCESS || status == ARES_ENOTFOUND)) {
/* Right now, there can only be up to two parallel queries, so do not
bother handling any other cases. */
- DEBUGASSERT(res->num_pending == 1);
+ DEBUGASSERT(ares->num_pending == 1);
/* it is possible that one of these parallel queries could succeed
quickly, but the other could always fail or timeout (when we are
@@ -656,19 +581,21 @@ static void query_completed_cb(void *arg, /* (struct connectdata *) */
timeout to prevent it. After all, we do not even know where in the
c-ares retry cycle each request is.
*/
- res->happy_eyeballs_dns_time = Curl_now();
+ ares->happy_eyeballs_dns_time = curlx_now();
Curl_expire(data, HAPPY_EYEBALLS_DNS_TIMEOUT,
EXPIRE_HAPPY_EYEBALLS_DNS);
}
}
+
#else
/* c-ares 1.16.0 or later */
/*
- * ares2addr() converts an address list provided by c-ares to an internal
- * libcurl compatible list
+ * async_ares_node2addr() converts an address list provided by c-ares
+ * to an internal libcurl compatible list.
*/
-static struct Curl_addrinfo *ares2addr(struct ares_addrinfo_node *node)
+static struct Curl_addrinfo *
+async_ares_node2addr(struct ares_addrinfo_node *node)
{
/* traverse the ares_addrinfo_node list */
struct ares_addrinfo_node *ai;
@@ -738,48 +665,78 @@ static struct Curl_addrinfo *ares2addr(struct ares_addrinfo_node *node)
return cafirst;
}
-static void addrinfo_cb(void *arg, int status, int timeouts,
- struct ares_addrinfo *result)
+static void async_ares_addrinfo_cb(void *user_data, int status, int timeouts,
+ struct ares_addrinfo *result)
{
- struct Curl_easy *data = (struct Curl_easy *)arg;
- struct thread_data *res = &data->state.async.thdata;
+ struct Curl_easy *data = (struct Curl_easy *)user_data;
+ struct async_ares_ctx *ares = &data->state.async.ares;
(void)timeouts;
+ CURL_TRC_DNS(data, "asyn-ares: addrinfo callback, status=%d", status);
if(ARES_SUCCESS == status) {
- res->temp_ai = ares2addr(result->nodes);
- res->last_status = CURL_ASYNC_SUCCESS;
+ ares->temp_ai = async_ares_node2addr(result->nodes);
+ ares->last_status = CURL_ASYNC_SUCCESS;
ares_freeaddrinfo(result);
}
- res->num_pending--;
+ ares->num_pending--;
+ CURL_TRC_DNS(data, "ares: addrinfo done, status=%d, pending=%d, "
+ "addr=%sfound",
+ status, ares->num_pending, ares->temp_ai ? "" : "not ");
}
#endif
+#ifdef USE_HTTPSRR
+static void async_ares_rr_done(void *user_data, ares_status_t status,
+ size_t timeouts,
+ const ares_dns_record_t *dnsrec)
+{
+ struct Curl_easy *data = user_data;
+ struct async_ares_ctx *ares = &data->state.async.ares;
+
+ (void)timeouts;
+ --ares->num_pending;
+ CURL_TRC_DNS(data, "ares: httpsrr done, status=%d, pending=%d, "
+ "dnsres=%sfound",
+ status, ares->num_pending,
+ (dnsrec &&
+ ares_dns_record_rr_cnt(dnsrec, ARES_SECTION_ANSWER)) ?
+ "" : "not ");
+ if((ARES_SUCCESS != status) || !dnsrec)
+ return;
+ ares->result = Curl_httpsrr_from_ares(data, dnsrec, &ares->hinfo);
+}
+#endif /* USE_HTTPSRR */
+
/*
- * Curl_resolver_getaddrinfo() - when using ares
+ * Curl_async_getaddrinfo() - when using ares
*
* Returns name information about the given hostname and port number. If
* successful, the 'hostent' is returned and the fourth argument will point to
* memory we need to free after use. That memory *MUST* be freed with
* Curl_freeaddrinfo(), nothing else.
*/
-struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data,
- const char *hostname,
- int port,
- int *waitp)
+struct Curl_addrinfo *Curl_async_getaddrinfo(struct Curl_easy *data,
+ const char *hostname,
+ int port,
+ int ip_version,
+ int *waitp)
{
- struct thread_data *res = &data->state.async.thdata;
+ struct async_ares_ctx *ares = &data->state.async.ares;
*waitp = 0; /* default to synchronous response */
- res->hostname = strdup(hostname);
- if(!res->hostname)
+ if(async_ares_init_lazy(data))
return NULL;
- data->state.async.port = port;
data->state.async.done = FALSE; /* not done */
data->state.async.dns = NULL; /* clear */
+ data->state.async.port = port;
+ data->state.async.ip_version = ip_version;
+ data->state.async.hostname = strdup(hostname);
+ if(!data->state.async.hostname)
+ return NULL;
/* initial status - failed */
- res->last_status = ARES_ENOTFOUND;
+ ares->last_status = ARES_ENOTFOUND;
#ifdef HAVE_CARES_GETADDRINFO
{
@@ -788,15 +745,18 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data,
int pf = PF_INET;
memset(&hints, 0, sizeof(hints));
#ifdef CURLRES_IPV6
- if((data->conn->ip_version != CURL_IPRESOLVE_V4) &&
+ if((ip_version != CURL_IPRESOLVE_V4) &&
Curl_ipv6works(data)) {
/* The stack seems to be IPv6-enabled */
- if(data->conn->ip_version == CURL_IPRESOLVE_V6)
+ if(ip_version == CURL_IPRESOLVE_V6)
pf = PF_INET6;
else
pf = PF_UNSPEC;
}
#endif /* CURLRES_IPV6 */
+ CURL_TRC_DNS(data, "asyn-ares: fire off getaddrinfo for %s",
+ (pf == PF_UNSPEC) ? "A+AAAA" :
+ ((pf == PF_INET) ? "A" : "AAAA"));
hints.ai_family = pf;
hints.ai_socktype = (data->conn->transport == TRNSPRT_TCP) ?
SOCK_STREAM : SOCK_DGRAM;
@@ -805,44 +765,43 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data,
*/
hints.ai_flags = ARES_AI_NUMERICSERV;
msnprintf(service, sizeof(service), "%d", port);
- res->num_pending = 1;
- ares_getaddrinfo((ares_channel)data->state.async.resolver, hostname,
- service, &hints, addrinfo_cb, data);
+ ares->num_pending = 1;
+ ares_getaddrinfo(ares->channel, data->state.async.hostname,
+ service, &hints, async_ares_addrinfo_cb, data);
}
#else
#ifdef HAVE_CARES_IPV6
- if((data->conn->ip_version != CURL_IPRESOLVE_V4) && Curl_ipv6works(data)) {
+ if((ip_version != CURL_IPRESOLVE_V4) && Curl_ipv6works(data)) {
/* The stack seems to be IPv6-enabled */
- res->num_pending = 2;
-
/* areschannel is already setup in the Curl_open() function */
- ares_gethostbyname((ares_channel)data->state.async.resolver, hostname,
- PF_INET, query_completed_cb, data);
- ares_gethostbyname((ares_channel)data->state.async.resolver, hostname,
- PF_INET6, query_completed_cb, data);
+ CURL_TRC_DNS(data, "asyn-ares: fire off query for A");
+ ares_gethostbyname(ares->channel, hostname, PF_INET,
+ async_ares_hostbyname_cb, data);
+ CURL_TRC_DNS(data, "asyn-ares: fire off query for AAAA");
+ ares->num_pending = 2;
+ ares_gethostbyname(ares->channel, data->state.async.hostname, PF_INET6,
+ async_ares_hostbyname_cb, data);
}
else
#endif
{
- res->num_pending = 1;
-
/* areschannel is already setup in the Curl_open() function */
- ares_gethostbyname((ares_channel)data->state.async.resolver,
- hostname, PF_INET,
- query_completed_cb, data);
+ CURL_TRC_DNS(data, "asyn-ares: fire off query for A");
+ ares->num_pending = 1;
+ ares_gethostbyname(ares->channel, data->state.async.hostname, PF_INET,
+ async_ares_hostbyname_cb, data);
}
#endif
#ifdef USE_HTTPSRR
{
CURL_TRC_DNS(data, "asyn-ares: fire off query for HTTPSRR");
- res->num_pending++; /* one more */
- memset(&res->hinfo, 0, sizeof(struct Curl_https_rrinfo));
- res->hinfo.port = -1;
- ares_query_dnsrec((ares_channel)data->state.async.resolver,
- hostname, ARES_CLASS_IN,
- ARES_REC_TYPE_HTTPS,
- Curl_dnsrec_done_cb, data, NULL);
+ memset(&ares->hinfo, 0, sizeof(ares->hinfo));
+ ares->hinfo.port = -1;
+ ares->num_pending++; /* one more */
+ ares_query_dnsrec(ares->channel, data->state.async.hostname,
+ ARES_CLASS_IN, ARES_REC_TYPE_HTTPS,
+ async_ares_rr_done, data, NULL);
}
#endif
*waitp = 1; /* expect asynchronous response */
@@ -850,39 +809,39 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data,
return NULL; /* no struct yet */
}
-CURLcode Curl_set_dns_servers(struct Curl_easy *data,
- char *servers)
+/* Set what DNS server are is to use. This is called in 2 situations:
+ * 1. when the application does 'CURLOPT_DNS_SERVERS' and passing NULL
+ * means any previous set value should be unset. Which means
+ * we need to destroy and create the are channel anew, if there is one.
+ * 2. When we lazy init the ares channel and NULL means that there
+ * are no preferences and we do not reset any existing channel. */
+static CURLcode async_ares_set_dns_servers(struct Curl_easy *data,
+ bool reset_on_null)
{
+ struct async_ares_ctx *ares = &data->state.async.ares;
CURLcode result = CURLE_NOT_BUILT_IN;
- int ares_result;
+ const char *servers = data->set.str[STRING_DNS_SERVERS];
+ int ares_result = ARES_SUCCESS;
+
+#if defined(CURLDEBUG) && defined(HAVE_CARES_SERVERS_CSV)
+ if(getenv("CURL_DNS_SERVER"))
+ servers = getenv("CURL_DNS_SERVER");
+#endif
- /* If server is NULL, this purges all DNS servers from c-ares. Reset it to
- * default.
- */
if(!servers) {
- Curl_resolver_cleanup(data->state.async.resolver);
- result = Curl_resolver_init(data, &data->state.async.resolver);
- if(!result) {
- /* this now needs to restore the other options set to c-ares */
- if(data->set.str[STRING_DNS_INTERFACE])
- (void)Curl_set_dns_interface(data,
- data->set.str[STRING_DNS_INTERFACE]);
- if(data->set.str[STRING_DNS_LOCAL_IP4])
- (void)Curl_set_dns_local_ip4(data,
- data->set.str[STRING_DNS_LOCAL_IP4]);
- if(data->set.str[STRING_DNS_LOCAL_IP6])
- (void)Curl_set_dns_local_ip6(data,
- data->set.str[STRING_DNS_LOCAL_IP6]);
+ if(reset_on_null) {
+ Curl_async_destroy(data);
}
- return result;
+ return CURLE_OK;
}
#ifdef HAVE_CARES_SERVERS_CSV
+ /* if channel is not there, this is just a parameter check */
+ if(ares->channel)
#ifdef HAVE_CARES_PORTS_CSV
- ares_result = ares_set_servers_ports_csv(data->state.async.resolver,
- servers);
+ ares_result = ares_set_servers_ports_csv(ares->channel, servers);
#else
- ares_result = ares_set_servers_csv(data->state.async.resolver, servers);
+ ares_result = ares_set_servers_csv(ares->channel, servers);
#endif
switch(ares_result) {
case ARES_SUCCESS:
@@ -906,14 +865,23 @@ CURLcode Curl_set_dns_servers(struct Curl_easy *data,
return result;
}
-CURLcode Curl_set_dns_interface(struct Curl_easy *data,
- const char *interf)
+CURLcode Curl_async_ares_set_dns_servers(struct Curl_easy *data)
+{
+ return async_ares_set_dns_servers(data, TRUE);
+}
+
+CURLcode Curl_async_ares_set_dns_interface(struct Curl_easy *data)
{
#ifdef HAVE_CARES_LOCAL_DEV
+ struct async_ares_ctx *ares = &data->state.async.ares;
+ const char *interf = data->set.str[STRING_DNS_INTERFACE];
+
if(!interf)
interf = "";
- ares_set_local_dev((ares_channel)data->state.async.resolver, interf);
+ /* if channel is not there, this is just a parameter check */
+ if(ares->channel)
+ ares_set_local_dev(ares->channel, interf);
return CURLE_OK;
#else /* c-ares version too old! */
@@ -923,11 +891,12 @@ CURLcode Curl_set_dns_interface(struct Curl_easy *data,
#endif
}
-CURLcode Curl_set_dns_local_ip4(struct Curl_easy *data,
- const char *local_ip4)
+CURLcode Curl_async_ares_set_dns_local_ip4(struct Curl_easy *data)
{
#ifdef HAVE_CARES_SET_LOCAL
+ struct async_ares_ctx *ares = &data->state.async.ares;
struct in_addr a4;
+ const char *local_ip4 = data->set.str[STRING_DNS_LOCAL_IP4];
if((!local_ip4) || (local_ip4[0] == 0)) {
a4.s_addr = 0; /* disabled: do not bind to a specific address */
@@ -939,8 +908,9 @@ CURLcode Curl_set_dns_local_ip4(struct Curl_easy *data,
}
}
- ares_set_local_ip4((ares_channel)data->state.async.resolver,
- ntohl(a4.s_addr));
+ /* if channel is not there yet, this is just a parameter check */
+ if(ares->channel)
+ ares_set_local_ip4(ares->channel, ntohl(a4.s_addr));
return CURLE_OK;
#else /* c-ares version too old! */
@@ -950,11 +920,12 @@ CURLcode Curl_set_dns_local_ip4(struct Curl_easy *data,
#endif
}
-CURLcode Curl_set_dns_local_ip6(struct Curl_easy *data,
- const char *local_ip6)
+CURLcode Curl_async_ares_set_dns_local_ip6(struct Curl_easy *data)
{
#if defined(HAVE_CARES_SET_LOCAL) && defined(USE_IPV6)
+ struct async_ares_ctx *ares = &data->state.async.ares;
unsigned char a6[INET6_ADDRSTRLEN];
+ const char *local_ip6 = data->set.str[STRING_DNS_LOCAL_IP6];
if((!local_ip6) || (local_ip6[0] == 0)) {
/* disabled: do not bind to a specific address */
@@ -967,15 +938,15 @@ CURLcode Curl_set_dns_local_ip6(struct Curl_easy *data,
}
}
- ares_set_local_ip6((ares_channel)data->state.async.resolver, a6);
+ /* if channel is not there, this is just a parameter check */
+ if(ares->channel)
+ ares_set_local_ip6(ares->channel, a6);
return CURLE_OK;
#else /* c-ares version too old! */
(void)data;
- (void)local_ip6;
return CURLE_NOT_BUILT_IN;
#endif
}
-#endif /* CURLRES_ARES */
-#endif /* USE_ARES */
+#endif /* CURLRES_ARES */
diff --git a/libs/libcurl/src/asyn-base.c b/libs/libcurl/src/asyn-base.c
new file mode 100644
index 0000000000..4d2996d237
--- /dev/null
+++ b/libs/libcurl/src/asyn-base.c
@@ -0,0 +1,196 @@
+/***************************************************************************
+ * _ _ ____ _
+ * 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"
+
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+#ifdef __VMS
+#include <in.h>
+#include <inet.h>
+#endif
+
+#ifdef USE_ARES
+#include <ares.h>
+#include <ares_version.h> /* really old c-ares did not include this by
+ itself */
+#endif
+
+#include "urldata.h"
+#include "asyn.h"
+#include "sendf.h"
+#include "hostip.h"
+#include "hash.h"
+#include "multiif.h"
+#include "select.h"
+#include "share.h"
+#include "url.h"
+#include "curl_memory.h"
+/* The last #include file should be: */
+#include "memdebug.h"
+
+/***********************************************************************
+ * Only for builds using asynchronous name resolves
+ **********************************************************************/
+#ifdef CURLRES_ASYNCH
+
+
+#ifdef USE_ARES
+
+#if ARES_VERSION < 0x010600
+#error "requires c-ares 1.6.0 or newer"
+#endif
+
+/*
+ * Curl_ares_getsock() is called when the outside world (using
+ * curl_multi_fdset()) wants to get our fd_set setup and we are talking with
+ * ares. The caller must make sure that this function is only called when we
+ * have a working ares channel.
+ *
+ * Returns: sockets-in-use-bitmap
+ */
+
+int Curl_ares_getsock(struct Curl_easy *data,
+ ares_channel channel,
+ curl_socket_t *socks)
+{
+ struct timeval maxtime = { CURL_TIMEOUT_RESOLVE, 0 };
+ struct timeval timebuf;
+ int max = ares_getsock(channel,
+ (ares_socket_t *)socks, MAX_SOCKSPEREASYHANDLE);
+ struct timeval *timeout = ares_timeout(channel, &maxtime, &timebuf);
+ timediff_t milli = curlx_tvtoms(timeout);
+ Curl_expire(data, milli, EXPIRE_ASYNC_NAME);
+ return max;
+}
+
+/*
+ * Curl_ares_perform()
+ *
+ * 1) Ask ares what sockets it currently plays with, then
+ * 2) wait for the timeout period to check for action on ares' sockets.
+ * 3) tell ares to act on all the sockets marked as "with action"
+ *
+ * return number of sockets it worked on, or -1 on error
+ */
+int Curl_ares_perform(ares_channel channel,
+ timediff_t timeout_ms)
+{
+ int nfds;
+ int bitmask;
+ ares_socket_t socks[ARES_GETSOCK_MAXNUM];
+ struct pollfd pfd[ARES_GETSOCK_MAXNUM];
+ int i;
+ int num = 0;
+
+ if(!channel)
+ return 0;
+
+ bitmask = ares_getsock(channel, socks, ARES_GETSOCK_MAXNUM);
+
+ for(i = 0; i < ARES_GETSOCK_MAXNUM; i++) {
+ pfd[i].events = 0;
+ pfd[i].revents = 0;
+ if(ARES_GETSOCK_READABLE(bitmask, i)) {
+ pfd[i].fd = socks[i];
+ pfd[i].events |= POLLRDNORM|POLLIN;
+ }
+ if(ARES_GETSOCK_WRITABLE(bitmask, i)) {
+ pfd[i].fd = socks[i];
+ pfd[i].events |= POLLWRNORM|POLLOUT;
+ }
+ if(pfd[i].events)
+ num++;
+ else
+ break;
+ }
+
+ if(num) {
+ nfds = Curl_poll(pfd, (unsigned int)num, timeout_ms);
+ if(nfds < 0)
+ return -1;
+ }
+ else
+ nfds = 0;
+
+ if(!nfds)
+ /* Call ares_process() unconditionally here, even if we simply timed out
+ above, as otherwise the ares name resolve will not timeout! */
+ ares_process_fd(channel, ARES_SOCKET_BAD, ARES_SOCKET_BAD);
+ else {
+ /* move through the descriptors and ask for processing on them */
+ for(i = 0; i < num; i++)
+ ares_process_fd(channel,
+ (pfd[i].revents & (POLLRDNORM|POLLIN)) ?
+ pfd[i].fd : ARES_SOCKET_BAD,
+ (pfd[i].revents & (POLLWRNORM|POLLOUT)) ?
+ pfd[i].fd : ARES_SOCKET_BAD);
+ }
+ return nfds;
+}
+
+#endif
+
+#endif /* CURLRES_ASYNCH */
+
+#ifdef USE_CURL_ASYNC
+
+#include "doh.h"
+
+void Curl_async_shutdown(struct Curl_easy *data)
+{
+#ifdef CURLRES_ARES
+ Curl_async_ares_shutdown(data);
+#endif
+#ifdef CURLRES_THREADED
+ Curl_async_thrdd_shutdown(data);
+#endif
+#ifndef CURL_DISABLE_DOH
+ Curl_doh_cleanup(data);
+#endif
+ Curl_safefree(data->state.async.hostname);
+}
+
+void Curl_async_destroy(struct Curl_easy *data)
+{
+#ifdef CURLRES_ARES
+ Curl_async_ares_destroy(data);
+#endif
+#ifdef CURLRES_THREADED
+ Curl_async_thrdd_destroy(data);
+#endif
+#ifndef CURL_DISABLE_DOH
+ Curl_doh_cleanup(data);
+#endif
+ Curl_safefree(data->state.async.hostname);
+}
+
+#endif /* USE_CURL_ASYNC */
diff --git a/libs/libcurl/src/asyn-thrdd.c b/libs/libcurl/src/asyn-thrdd.c
new file mode 100644
index 0000000000..f0495a7d2e
--- /dev/null
+++ b/libs/libcurl/src/asyn-thrdd.c
@@ -0,0 +1,761 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+#include "socketpair.h"
+
+/***********************************************************************
+ * Only for threaded name resolves builds
+ **********************************************************************/
+#ifdef CURLRES_THREADED
+
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+#ifdef __VMS
+#include <in.h>
+#include <inet.h>
+#endif
+
+#if defined(USE_THREADS_POSIX) && defined(HAVE_PTHREAD_H)
+# include <pthread.h>
+#endif
+
+#ifdef HAVE_GETADDRINFO
+# define RESOLVER_ENOMEM EAI_MEMORY /* = WSA_NOT_ENOUGH_MEMORY on Windows */
+#else
+# define RESOLVER_ENOMEM SOCKENOMEM
+#endif
+
+#include "urldata.h"
+#include "sendf.h"
+#include "hostip.h"
+#include "hash.h"
+#include "share.h"
+#include "url.h"
+#include "multiif.h"
+#include "inet_ntop.h"
+#include "curl_threads.h"
+#include "strdup.h"
+
+#ifdef USE_ARES
+#include <ares.h>
+#ifdef USE_HTTPSRR
+#define USE_HTTPSRR_ARES /* the combo */
+#endif
+#endif
+
+/* The last 3 #include files should be in this order */
+#include "curl_printf.h"
+#include "curl_memory.h"
+#include "memdebug.h"
+
+
+/*
+ * Curl_async_global_init()
+ * Called from curl_global_init() to initialize global resolver environment.
+ * Does nothing here.
+ */
+int Curl_async_global_init(void)
+{
+#if defined(USE_ARES) && defined(CARES_HAVE_ARES_LIBRARY_INIT)
+ if(ares_library_init(ARES_LIB_INIT_ALL)) {
+ return CURLE_FAILED_INIT;
+ }
+#endif
+ return CURLE_OK;
+}
+
+/*
+ * Curl_async_global_cleanup()
+ * Called from curl_global_cleanup() to destroy global resolver environment.
+ * Does nothing here.
+ */
+void Curl_async_global_cleanup(void)
+{
+#if defined(USE_ARES) && defined(CARES_HAVE_ARES_LIBRARY_INIT)
+ ares_library_cleanup();
+#endif
+}
+
+static void async_thrdd_destroy(struct Curl_easy *);
+
+CURLcode Curl_async_get_impl(struct Curl_easy *data, void **impl)
+{
+ (void)data;
+ *impl = NULL;
+ return CURLE_OK;
+}
+
+/* Destroy context of threaded resolver */
+static void addr_ctx_destroy(struct async_thrdd_addr_ctx *addr_ctx)
+{
+ if(addr_ctx) {
+ DEBUGASSERT(!addr_ctx->ref_count);
+ Curl_mutex_destroy(&addr_ctx->mutx);
+ free(addr_ctx->hostname);
+ if(addr_ctx->res)
+ Curl_freeaddrinfo(addr_ctx->res);
+#ifndef CURL_DISABLE_SOCKETPAIR
+ /*
+ * close one end of the socket pair (may be done in resolver thread);
+ * the other end (for reading) is always closed in the parent thread.
+ */
+#ifndef USE_EVENTFD
+ if(addr_ctx->sock_pair[1] != CURL_SOCKET_BAD) {
+ wakeup_close(addr_ctx->sock_pair[1]);
+ }
+#endif
+#endif
+ free(addr_ctx);
+ }
+}
+
+/* Initialize context for threaded resolver */
+static struct async_thrdd_addr_ctx *
+addr_ctx_create(const char *hostname, int port,
+ const struct addrinfo *hints)
+{
+ struct async_thrdd_addr_ctx *addr_ctx = calloc(1, sizeof(*addr_ctx));
+ if(!addr_ctx)
+ return NULL;
+
+ addr_ctx->thread_hnd = curl_thread_t_null;
+ addr_ctx->port = port;
+#ifndef CURL_DISABLE_SOCKETPAIR
+ addr_ctx->sock_pair[0] = CURL_SOCKET_BAD;
+ addr_ctx->sock_pair[1] = CURL_SOCKET_BAD;
+#endif
+ addr_ctx->ref_count = 0;
+
+#ifdef HAVE_GETADDRINFO
+ DEBUGASSERT(hints);
+ addr_ctx->hints = *hints;
+#else
+ (void) hints;
+#endif
+
+ Curl_mutex_init(&addr_ctx->mutx);
+
+#ifndef CURL_DISABLE_SOCKETPAIR
+ /* create socket pair or pipe */
+ if(wakeup_create(addr_ctx->sock_pair, FALSE) < 0) {
+ addr_ctx->sock_pair[0] = CURL_SOCKET_BAD;
+ addr_ctx->sock_pair[1] = CURL_SOCKET_BAD;
+ goto err_exit;
+ }
+#endif
+ addr_ctx->sock_error = CURL_ASYNC_SUCCESS;
+
+ /* Copying hostname string because original can be destroyed by parent
+ * thread during gethostbyname execution.
+ */
+ addr_ctx->hostname = strdup(hostname);
+ if(!addr_ctx->hostname)
+ goto err_exit;
+
+ addr_ctx->ref_count = 1;
+ return addr_ctx;
+
+err_exit:
+#ifndef CURL_DISABLE_SOCKETPAIR
+ if(addr_ctx->sock_pair[0] != CURL_SOCKET_BAD) {
+ wakeup_close(addr_ctx->sock_pair[0]);
+ addr_ctx->sock_pair[0] = CURL_SOCKET_BAD;
+ }
+#endif
+ addr_ctx_destroy(addr_ctx);
+ return NULL;
+}
+
+#ifdef HAVE_GETADDRINFO
+
+/*
+ * getaddrinfo_thread() resolves a name and then exits.
+ *
+ * For builds without ARES, but with USE_IPV6, create a resolver thread
+ * and wait on it.
+ */
+static
+#if defined(CURL_WINDOWS_UWP) || defined(UNDER_CE)
+DWORD
+#else
+unsigned int
+#endif
+CURL_STDCALL getaddrinfo_thread(void *arg)
+{
+ struct async_thrdd_addr_ctx *addr_ctx = arg;
+ char service[12];
+ int rc;
+ bool all_gone;
+
+ msnprintf(service, sizeof(service), "%d", addr_ctx->port);
+
+ rc = Curl_getaddrinfo_ex(addr_ctx->hostname, service,
+ &addr_ctx->hints, &addr_ctx->res);
+
+ if(rc) {
+ addr_ctx->sock_error = SOCKERRNO ? SOCKERRNO : rc;
+ if(addr_ctx->sock_error == 0)
+ addr_ctx->sock_error = RESOLVER_ENOMEM;
+ }
+ else {
+ Curl_addrinfo_set_port(addr_ctx->res, addr_ctx->port);
+ }
+
+ Curl_mutex_acquire(&addr_ctx->mutx);
+ if(addr_ctx->ref_count > 1) {
+ /* Someone still waiting on our results. */
+#ifndef CURL_DISABLE_SOCKETPAIR
+ if(addr_ctx->sock_pair[1] != CURL_SOCKET_BAD) {
+#ifdef USE_EVENTFD
+ const uint64_t buf[1] = { 1 };
+#else
+ const char buf[1] = { 1 };
+#endif
+ /* DNS has been resolved, signal client task */
+ if(wakeup_write(addr_ctx->sock_pair[1], buf, sizeof(buf)) < 0) {
+ /* update sock_erro to errno */
+ addr_ctx->sock_error = SOCKERRNO;
+ }
+ }
+#endif
+ }
+ /* thread gives up its reference to the shared data now. */
+ --addr_ctx->ref_count;
+ all_gone = !addr_ctx->ref_count;
+ Curl_mutex_release(&addr_ctx->mutx);
+ if(all_gone)
+ addr_ctx_destroy(addr_ctx);
+
+ return 0;
+}
+
+#else /* HAVE_GETADDRINFO */
+
+/*
+ * gethostbyname_thread() resolves a name and then exits.
+ */
+static
+#if defined(CURL_WINDOWS_UWP) || defined(UNDER_CE)
+DWORD
+#else
+unsigned int
+#endif
+CURL_STDCALL gethostbyname_thread(void *arg)
+{
+ struct async_thrdd_addr_ctx *addr_ctx = arg;
+ bool all_gone;
+
+ addr_ctx->res = Curl_ipv4_resolve_r(addr_ctx->hostname, addr_ctx->port);
+
+ if(!addr_ctx->res) {
+ addr_ctx->sock_error = SOCKERRNO;
+ if(addr_ctx->sock_error == 0)
+ addr_ctx->sock_error = RESOLVER_ENOMEM;
+ }
+
+ Curl_mutex_acquire(&addr_ctx->mutx);
+ /* thread gives up its reference to the shared data now. */
+ --addr_ctx->ref_count;
+ all_gone = !addr_ctx->ref_count;;
+ Curl_mutex_release(&addr_ctx->mutx);
+ if(all_gone)
+ addr_ctx_destroy(addr_ctx);
+
+ return 0;
+}
+
+#endif /* HAVE_GETADDRINFO */
+
+/*
+ * async_thrdd_destroy() cleans up async resolver data and thread handle.
+ */
+static void async_thrdd_destroy(struct Curl_easy *data)
+{
+ struct async_thrdd_ctx *thrdd = &data->state.async.thrdd;
+ struct async_thrdd_addr_ctx *addr = thrdd->addr;
+#ifdef USE_HTTPSRR_ARES
+ if(thrdd->rr.channel) {
+ ares_destroy(thrdd->rr.channel);
+ thrdd->rr.channel = NULL;
+ }
+ Curl_httpsrr_cleanup(&thrdd->rr.hinfo);
+#endif
+
+ if(addr) {
+#ifndef CURL_DISABLE_SOCKETPAIR
+ curl_socket_t sock_rd = addr->sock_pair[0];
+#endif
+ bool done;
+
+ /* Release our reference to the data shared with the thread. */
+ Curl_mutex_acquire(&addr->mutx);
+ --addr->ref_count;
+ CURL_TRC_DNS(data, "resolve, destroy async data, shared ref=%d",
+ addr->ref_count);
+ done = !addr->ref_count;
+ /* we give up our reference to `addr`, so NULL our pointer.
+ * coverity analyses this as being a potential unsynched write,
+ * assuming two calls to this function could be invoked concurrently.
+ * Which they never are, as the transfer's side runs single-threaded. */
+ thrdd->addr = NULL;
+ if(!done) {
+ /* thread is still running. Detach the thread while mutexed, it will
+ * trigger the cleanup when it releases its reference. */
+ Curl_thread_destroy(&addr->thread_hnd);
+ }
+ Curl_mutex_release(&addr->mutx);
+
+ if(done) {
+ /* thread has released its reference, join it and
+ * release the memory we shared with it. */
+ if(addr->thread_hnd != curl_thread_t_null)
+ Curl_thread_join(&addr->thread_hnd);
+ addr_ctx_destroy(addr);
+ }
+#ifndef CURL_DISABLE_SOCKETPAIR
+ /*
+ * ensure CURLMOPT_SOCKETFUNCTION fires CURL_POLL_REMOVE
+ * before the FD is invalidated to avoid EBADF on EPOLL_CTL_DEL
+ */
+ Curl_multi_will_close(data, sock_rd);
+ wakeup_close(sock_rd);
+#endif
+ }
+}
+
+#ifdef USE_HTTPSRR_ARES
+
+static void async_thrdd_rr_done(void *user_data, ares_status_t status,
+ size_t timeouts,
+ const ares_dns_record_t *dnsrec)
+{
+ struct Curl_easy *data = user_data;
+ struct async_thrdd_ctx *thrdd = &data->state.async.thrdd;
+
+ (void)timeouts;
+ thrdd->rr.done = TRUE;
+ if((ARES_SUCCESS != status) || !dnsrec)
+ return;
+ thrdd->rr.result = Curl_httpsrr_from_ares(data, dnsrec, &thrdd->rr.hinfo);
+}
+
+static CURLcode async_rr_start(struct Curl_easy *data)
+{
+ struct async_thrdd_ctx *thrdd = &data->state.async.thrdd;
+ int status;
+
+ DEBUGASSERT(!thrdd->rr.channel);
+ status = ares_init_options(&thrdd->rr.channel, NULL, 0);
+ if(status != ARES_SUCCESS) {
+ thrdd->rr.channel = NULL;
+ return CURLE_FAILED_INIT;
+ }
+
+ memset(&thrdd->rr.hinfo, 0, sizeof(thrdd->rr.hinfo));
+ thrdd->rr.hinfo.port = -1;
+ ares_query_dnsrec(thrdd->rr.channel,
+ data->conn->host.name, ARES_CLASS_IN,
+ ARES_REC_TYPE_HTTPS,
+ async_thrdd_rr_done, data, NULL);
+ return CURLE_OK;
+}
+#endif
+
+/*
+ * async_thrdd_init() starts a new thread that performs the actual
+ * resolve. This function returns before the resolve is done.
+ *
+ * Returns FALSE in case of failure, otherwise TRUE.
+ */
+static bool async_thrdd_init(struct Curl_easy *data,
+ const char *hostname, int port, int ip_version,
+ const struct addrinfo *hints)
+{
+ struct async_thrdd_ctx *thrdd = &data->state.async.thrdd;
+ struct async_thrdd_addr_ctx *addr_ctx;
+
+ /* !checksrc! disable ERRNOVAR 1 */
+ int err = ENOMEM;
+
+ if(thrdd->addr
+#ifdef USE_HTTPSRR_ARES
+ || thrdd->rr.channel
+#endif
+ ) {
+ CURL_TRC_DNS(data, "starting new resolve, with previous not cleaned up");
+ async_thrdd_destroy(data);
+ DEBUGASSERT(!thrdd->addr);
+#ifdef USE_HTTPSRR_ARES
+ DEBUGASSERT(!thrdd->rr.channel);
+#endif
+ }
+
+ data->state.async.dns = NULL;
+ data->state.async.done = FALSE;
+ data->state.async.port = port;
+ data->state.async.ip_version = ip_version;
+ data->state.async.hostname = strdup(hostname);
+ if(!data->state.async.hostname)
+ goto err_exit;
+
+ addr_ctx = addr_ctx_create(hostname, port, hints);
+ if(!addr_ctx)
+ goto err_exit;
+ thrdd->addr = addr_ctx;
+
+ Curl_mutex_acquire(&addr_ctx->mutx);
+ DEBUGASSERT(addr_ctx->ref_count == 1);
+ /* passing addr_ctx to the thread adds a reference */
+ addr_ctx->start = curlx_now();
+ ++addr_ctx->ref_count;
+#ifdef HAVE_GETADDRINFO
+ addr_ctx->thread_hnd = Curl_thread_create(getaddrinfo_thread, addr_ctx);
+#else
+ addr_ctx->thread_hnd = Curl_thread_create(gethostbyname_thread, addr_ctx);
+#endif
+ if(addr_ctx->thread_hnd == curl_thread_t_null) {
+ /* The thread never started, remove its reference that never happened. */
+ --addr_ctx->ref_count;
+ err = errno;
+ Curl_mutex_release(&addr_ctx->mutx);
+ goto err_exit;
+ }
+ Curl_mutex_release(&addr_ctx->mutx);
+
+#ifdef USE_HTTPSRR_ARES
+ if(async_rr_start(data))
+ infof(data, "Failed HTTPS RR operation");
+#endif
+ CURL_TRC_DNS(data, "resolve thread started for of %s:%d", hostname, port);
+ return TRUE;
+
+err_exit:
+ CURL_TRC_DNS(data, "resolve thread failed init: %d", err);
+ async_thrdd_destroy(data);
+ CURL_SETERRNO(err);
+ return FALSE;
+}
+
+/*
+ * 'entry' may be NULL and then no data is returned
+ */
+static CURLcode asyn_thrdd_await(struct Curl_easy *data,
+ struct async_thrdd_addr_ctx *addr_ctx,
+ struct Curl_dns_entry **entry)
+{
+ CURLcode result = CURLE_OK;
+
+ DEBUGASSERT(addr_ctx->thread_hnd != curl_thread_t_null);
+
+ CURL_TRC_DNS(data, "resolve, wait for thread to finish");
+ /* wait for the thread to resolve the name */
+ if(Curl_thread_join(&addr_ctx->thread_hnd)) {
+ if(entry)
+ result = Curl_async_is_resolved(data, entry);
+ }
+ else
+ DEBUGASSERT(0);
+
+ data->state.async.done = TRUE;
+ if(entry)
+ *entry = data->state.async.dns;
+
+ async_thrdd_destroy(data);
+ return result;
+}
+
+
+/*
+ * Until we gain a way to signal the resolver threads to stop early, we must
+ * simply wait for them and ignore their results.
+ */
+void Curl_async_thrdd_shutdown(struct Curl_easy *data)
+{
+ struct async_thrdd_ctx *thrdd = &data->state.async.thrdd;
+
+ /* If we are still resolving, we must wait for the threads to fully clean up,
+ unfortunately. Otherwise, we can simply cancel to clean up any resolver
+ data. */
+ if(thrdd->addr && (thrdd->addr->thread_hnd != curl_thread_t_null) &&
+ !data->set.quick_exit)
+ (void)asyn_thrdd_await(data, thrdd->addr, NULL);
+ else
+ async_thrdd_destroy(data);
+}
+
+void Curl_async_thrdd_destroy(struct Curl_easy *data)
+{
+ Curl_async_thrdd_shutdown(data);
+}
+
+/*
+ * Curl_async_await()
+ *
+ * Waits for a resolve to finish. This function should be avoided since using
+ * this risk getting the multi interface to "hang".
+ *
+ * If 'entry' is non-NULL, make it point to the resolved dns entry
+ *
+ * Returns CURLE_COULDNT_RESOLVE_HOST if the host was not resolved,
+ * CURLE_OPERATION_TIMEDOUT if a time-out occurred, or other errors.
+ *
+ * This is the version for resolves-in-a-thread.
+ */
+CURLcode Curl_async_await(struct Curl_easy *data,
+ struct Curl_dns_entry **entry)
+{
+ struct async_thrdd_ctx *thrdd = &data->state.async.thrdd;
+ if(thrdd->addr)
+ return asyn_thrdd_await(data, thrdd->addr, entry);
+ return CURLE_FAILED_INIT;
+}
+
+/*
+ * Curl_async_is_resolved() is called repeatedly to check if a previous
+ * name resolve request has completed. It should also make sure to time-out if
+ * the operation seems to take too long.
+ */
+CURLcode Curl_async_is_resolved(struct Curl_easy *data,
+ struct Curl_dns_entry **dns)
+{
+ struct async_thrdd_ctx *thrdd = &data->state.async.thrdd;
+ bool done = FALSE;
+
+ DEBUGASSERT(dns);
+ *dns = NULL;
+
+ if(data->state.async.done) {
+ *dns = data->state.async.dns;
+ CURL_TRC_DNS(data, "threaded: is_resolved(), already done, dns=%sfound",
+ *dns ? "" : "not ");
+ return CURLE_OK;
+ }
+
+#ifdef USE_HTTPSRR_ARES
+ /* best effort, ignore errors */
+ if(thrdd->rr.channel)
+ (void)Curl_ares_perform(thrdd->rr.channel, 0);
+#endif
+
+ DEBUGASSERT(thrdd->addr);
+ if(!thrdd->addr)
+ return CURLE_FAILED_INIT;
+
+ Curl_mutex_acquire(&thrdd->addr->mutx);
+ done = (thrdd->addr->ref_count == 1);
+ Curl_mutex_release(&thrdd->addr->mutx);
+
+ if(done) {
+ CURLcode result = CURLE_OK;
+
+ data->state.async.done = TRUE;
+ Curl_resolv_unlink(data, &data->state.async.dns);
+
+ if(thrdd->addr->res) {
+ data->state.async.dns =
+ Curl_dnscache_mk_entry(data, thrdd->addr->res,
+ data->state.async.hostname, 0,
+ data->state.async.port, FALSE);
+ thrdd->addr->res = NULL;
+ if(!data->state.async.dns)
+ result = CURLE_OUT_OF_MEMORY;
+
+#ifdef USE_HTTPSRR_ARES
+ if(thrdd->rr.channel) {
+ result = thrdd->rr.result;
+ if(!result) {
+ struct Curl_https_rrinfo *lhrr;
+ lhrr = Curl_httpsrr_dup_move(&thrdd->rr.hinfo);
+ if(!lhrr) {
+ async_thrdd_destroy(data);
+ return CURLE_OUT_OF_MEMORY;
+ }
+ data->state.async.dns->hinfo = lhrr;
+ }
+ }
+#endif
+ if(!result && data->state.async.dns)
+ result = Curl_dnscache_add(data, data->state.async.dns);
+ }
+
+ if(!result && !data->state.async.dns)
+ result = Curl_resolver_error(data);
+ if(result)
+ Curl_resolv_unlink(data, &data->state.async.dns);
+ *dns = data->state.async.dns;
+ CURL_TRC_DNS(data, "is_resolved() result=%d, dns=%sfound",
+ result, *dns ? "" : "not ");
+ async_thrdd_destroy(data);
+ return result;
+ }
+ else {
+ /* poll for name lookup done with exponential backoff up to 250ms */
+ /* should be fine even if this converts to 32-bit */
+ timediff_t elapsed = curlx_timediff(curlx_now(),
+ data->progress.t_startsingle);
+ if(elapsed < 0)
+ elapsed = 0;
+
+ if(thrdd->addr->poll_interval == 0)
+ /* Start at 1ms poll interval */
+ thrdd->addr->poll_interval = 1;
+ else if(elapsed >= thrdd->addr->interval_end)
+ /* Back-off exponentially if last interval expired */
+ thrdd->addr->poll_interval *= 2;
+
+ if(thrdd->addr->poll_interval > 250)
+ thrdd->addr->poll_interval = 250;
+
+ thrdd->addr->interval_end = elapsed + thrdd->addr->poll_interval;
+ Curl_expire(data, thrdd->addr->poll_interval, EXPIRE_ASYNC_NAME);
+ return CURLE_OK;
+ }
+}
+
+int Curl_async_getsock(struct Curl_easy *data, curl_socket_t *socks)
+{
+ struct async_thrdd_ctx *thrdd = &data->state.async.thrdd;
+ int ret_val = 0;
+#if !defined(CURL_DISABLE_SOCKETPAIR) || defined(USE_HTTPSRR_ARES)
+ int socketi = 0;
+#else
+ (void)socks;
+#endif
+
+#ifdef USE_HTTPSRR_ARES
+ if(thrdd->rr.channel) {
+ ret_val = Curl_ares_getsock(data, thrdd->rr.channel, socks);
+ for(socketi = 0; socketi < (MAX_SOCKSPEREASYHANDLE - 1); socketi++)
+ if(!ARES_GETSOCK_READABLE(ret_val, socketi) &&
+ !ARES_GETSOCK_WRITABLE(ret_val, socketi))
+ break;
+ }
+#endif
+ if(!thrdd->addr)
+ return ret_val;
+
+#ifndef CURL_DISABLE_SOCKETPAIR
+ if(thrdd->addr) {
+ /* return read fd to client for polling the DNS resolution status */
+ socks[socketi] = thrdd->addr->sock_pair[0];
+ ret_val |= GETSOCK_READSOCK(socketi);
+ }
+ else
+#endif
+ {
+ timediff_t milli;
+ timediff_t ms = curlx_timediff(curlx_now(), thrdd->addr->start);
+ if(ms < 3)
+ milli = 0;
+ else if(ms <= 50)
+ milli = ms/3;
+ else if(ms <= 250)
+ milli = 50;
+ else
+ milli = 200;
+ Curl_expire(data, milli, EXPIRE_ASYNC_NAME);
+ }
+
+ return ret_val;
+}
+
+#ifndef HAVE_GETADDRINFO
+/*
+ * Curl_async_getaddrinfo() - for platforms without getaddrinfo
+ */
+struct Curl_addrinfo *Curl_async_getaddrinfo(struct Curl_easy *data,
+ const char *hostname,
+ int port,
+ int ip_version,
+ int *waitp)
+{
+ (void)ip_version;
+ *waitp = 0; /* default to synchronous response */
+
+ /* fire up a new resolver thread! */
+ if(async_thrdd_init(data, hostname, port, ip_version, NULL)) {
+ *waitp = 1; /* expect asynchronous response */
+ return NULL;
+ }
+
+ failf(data, "getaddrinfo() thread failed");
+
+ return NULL;
+}
+
+#else /* !HAVE_GETADDRINFO */
+
+/*
+ * Curl_async_getaddrinfo() - for getaddrinfo
+ */
+struct Curl_addrinfo *Curl_async_getaddrinfo(struct Curl_easy *data,
+ const char *hostname,
+ int port,
+ int ip_version,
+ int *waitp)
+{
+ struct addrinfo hints;
+ int pf = PF_INET;
+ *waitp = 0; /* default to synchronous response */
+
+ CURL_TRC_DNS(data, "init threaded resolve of %s:%d", hostname, port);
+#ifdef CURLRES_IPV6
+ if((ip_version != CURL_IPRESOLVE_V4) && Curl_ipv6works(data)) {
+ /* The stack seems to be IPv6-enabled */
+ if(ip_version == CURL_IPRESOLVE_V6)
+ pf = PF_INET6;
+ else
+ pf = PF_UNSPEC;
+ }
+#else
+ (void)ip_version;
+#endif /* CURLRES_IPV6 */
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = pf;
+ hints.ai_socktype = (data->conn->transport == TRNSPRT_TCP) ?
+ SOCK_STREAM : SOCK_DGRAM;
+
+ /* fire up a new resolver thread! */
+ if(async_thrdd_init(data, hostname, port, ip_version, &hints)) {
+ *waitp = 1; /* expect asynchronous response */
+ return NULL;
+ }
+
+ failf(data, "getaddrinfo() thread failed to start");
+ return NULL;
+
+}
+
+#endif /* !HAVE_GETADDRINFO */
+
+#endif /* CURLRES_THREADED */
diff --git a/libs/libcurl/src/asyn-thread.c b/libs/libcurl/src/asyn-thread.c
deleted file mode 100644
index c7db2e1b60..0000000000
--- a/libs/libcurl/src/asyn-thread.c
+++ /dev/null
@@ -1,768 +0,0 @@
-/***************************************************************************
- * _ _ ____ _
- * Project ___| | | | _ \| |
- * / __| | | | |_) | |
- * | (__| |_| | _ <| |___
- * \___|\___/|_| \_\_____|
- *
- * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
- *
- * This software is licensed as described in the file COPYING, which
- * you should have received as part of this distribution. The terms
- * are also available at https://curl.se/docs/copyright.html.
- *
- * You may opt to use, copy, modify, merge, publish, distribute and/or sell
- * copies of the Software, and permit persons to whom the Software is
- * furnished to do so, under the terms of the COPYING file.
- *
- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
- * KIND, either express or implied.
- *
- * SPDX-License-Identifier: curl
- *
- ***************************************************************************/
-
-#include "curl_setup.h"
-#include "socketpair.h"
-
-/***********************************************************************
- * Only for threaded name resolves builds
- **********************************************************************/
-#ifdef CURLRES_THREADED
-
-#ifdef HAVE_NETINET_IN_H
-#include <netinet/in.h>
-#endif
-#ifdef HAVE_NETDB_H
-#include <netdb.h>
-#endif
-#ifdef HAVE_ARPA_INET_H
-#include <arpa/inet.h>
-#endif
-#ifdef __VMS
-#include <in.h>
-#include <inet.h>
-#endif
-
-#if defined(USE_THREADS_POSIX) && defined(HAVE_PTHREAD_H)
-# include <pthread.h>
-#endif
-
-#ifdef HAVE_GETADDRINFO
-# define RESOLVER_ENOMEM EAI_MEMORY /* = WSA_NOT_ENOUGH_MEMORY on Windows */
-#else
-# define RESOLVER_ENOMEM SOCKENOMEM
-#endif
-
-#include "urldata.h"
-#include "sendf.h"
-#include "hostip.h"
-#include "hash.h"
-#include "share.h"
-#include "url.h"
-#include "multiif.h"
-#include "inet_ntop.h"
-#include "curl_threads.h"
-#include "connect.h"
-#include "strdup.h"
-
-#ifdef USE_ARES
-#include <ares.h>
-#ifdef USE_HTTPSRR
-#define USE_HTTPSRR_ARES /* the combo */
-#endif
-#endif
-
-/* The last 3 #include files should be in this order */
-#include "curl_printf.h"
-#include "curl_memory.h"
-#include "memdebug.h"
-
-
-/*
- * Curl_resolver_global_init()
- * Called from curl_global_init() to initialize global resolver environment.
- * Does nothing here.
- */
-int Curl_resolver_global_init(void)
-{
- return CURLE_OK;
-}
-
-/*
- * Curl_resolver_global_cleanup()
- * Called from curl_global_cleanup() to destroy global resolver environment.
- * Does nothing here.
- */
-void Curl_resolver_global_cleanup(void)
-{
-}
-
-/*
- * Curl_resolver_init()
- * Called from curl_easy_init() -> Curl_open() to initialize resolver
- * URL-state specific environment ('resolver' member of the UrlState
- * structure).
- */
-CURLcode Curl_resolver_init(struct Curl_easy *easy, void **resolver)
-{
- (void)easy;
- (void)resolver;
- return CURLE_OK;
-}
-
-/*
- * Curl_resolver_cleanup()
- * Called from curl_easy_cleanup() -> Curl_close() to cleanup resolver
- * URL-state specific environment ('resolver' member of the UrlState
- * structure).
- */
-void Curl_resolver_cleanup(void *resolver)
-{
- (void)resolver;
-}
-
-/*
- * Curl_resolver_duphandle()
- * Called from curl_easy_duphandle() to duplicate resolver URL state-specific
- * environment ('resolver' member of the UrlState structure).
- */
-CURLcode Curl_resolver_duphandle(struct Curl_easy *easy, void **to, void *from)
-{
- (void)from;
- return Curl_resolver_init(easy, to);
-}
-
-static void destroy_async_data(struct Curl_easy *);
-
-/*
- * Cancel all possibly still on-going resolves for this connection.
- */
-void Curl_resolver_cancel(struct Curl_easy *data)
-{
- destroy_async_data(data);
-}
-
-/* This function is used to init a threaded resolve */
-static bool init_resolve_thread(struct Curl_easy *data,
- const char *hostname, int port,
- const struct addrinfo *hints);
-
-
-static struct thread_sync_data *conn_thread_sync_data(struct Curl_easy *data)
-{
- return &(data->state.async.thdata.tsd);
-}
-
-/* Destroy resolver thread synchronization data */
-static
-void destroy_thread_sync_data(struct thread_sync_data *tsd)
-{
- Curl_mutex_destroy(&tsd->mutx);
-
- free(tsd->hostname);
-
- if(tsd->res)
- Curl_freeaddrinfo(tsd->res);
-
-#ifndef CURL_DISABLE_SOCKETPAIR
- /*
- * close one end of the socket pair (may be done in resolver thread);
- * the other end (for reading) is always closed in the parent thread.
- */
-#ifndef HAVE_EVENTFD
- if(tsd->sock_pair[1] != CURL_SOCKET_BAD) {
- wakeup_close(tsd->sock_pair[1]);
- }
-#endif
-#endif
- memset(tsd, 0, sizeof(*tsd));
-}
-
-/* Initialize resolver thread synchronization data */
-static
-int init_thread_sync_data(struct thread_data *td,
- const char *hostname,
- int port,
- const struct addrinfo *hints)
-{
- struct thread_sync_data *tsd = &td->tsd;
-
- memset(tsd, 0, sizeof(*tsd));
-
- td->init = TRUE;
- tsd->port = port;
- /* Treat the request as done until the thread actually starts so any early
- * cleanup gets done properly.
- */
- tsd->done = TRUE;
-#ifdef HAVE_GETADDRINFO
- DEBUGASSERT(hints);
- tsd->hints = *hints;
-#else
- (void) hints;
-#endif
-
- Curl_mutex_init(&tsd->mutx);
-
-#ifndef CURL_DISABLE_SOCKETPAIR
- /* create socket pair or pipe */
- if(wakeup_create(tsd->sock_pair, FALSE) < 0) {
- tsd->sock_pair[0] = CURL_SOCKET_BAD;
- tsd->sock_pair[1] = CURL_SOCKET_BAD;
- goto err_exit;
- }
-#endif
- tsd->sock_error = CURL_ASYNC_SUCCESS;
-
- /* Copying hostname string because original can be destroyed by parent
- * thread during gethostbyname execution.
- */
- tsd->hostname = strdup(hostname);
- if(!tsd->hostname)
- goto err_exit;
-
- return 1;
-
-err_exit:
-#ifndef CURL_DISABLE_SOCKETPAIR
- if(tsd->sock_pair[0] != CURL_SOCKET_BAD) {
- wakeup_close(tsd->sock_pair[0]);
- tsd->sock_pair[0] = CURL_SOCKET_BAD;
- }
-#endif
- destroy_thread_sync_data(tsd);
- return 0;
-}
-
-static CURLcode getaddrinfo_complete(struct Curl_easy *data)
-{
- struct thread_sync_data *tsd = conn_thread_sync_data(data);
- CURLcode result;
-
- result = Curl_addrinfo_callback(data, tsd->sock_error, tsd->res);
- /* The tsd->res structure has been copied to async.dns and perhaps the DNS
- cache. Set our copy to NULL so destroy_thread_sync_data does not free it.
- */
- tsd->res = NULL;
-
- return result;
-}
-
-
-#ifdef HAVE_GETADDRINFO
-
-/*
- * getaddrinfo_thread() resolves a name and then exits.
- *
- * For builds without ARES, but with USE_IPV6, create a resolver thread
- * and wait on it.
- */
-static
-#if defined(CURL_WINDOWS_UWP) || defined(UNDER_CE)
-DWORD
-#else
-unsigned int
-#endif
-CURL_STDCALL getaddrinfo_thread(void *arg)
-{
- struct thread_data *td = arg;
- struct thread_sync_data *tsd = &td->tsd;
- char service[12];
- int rc;
-
- msnprintf(service, sizeof(service), "%d", tsd->port);
-
- rc = Curl_getaddrinfo_ex(tsd->hostname, service, &tsd->hints, &tsd->res);
-
- if(rc) {
- tsd->sock_error = SOCKERRNO ? SOCKERRNO : rc;
- if(tsd->sock_error == 0)
- tsd->sock_error = RESOLVER_ENOMEM;
- }
- else {
- Curl_addrinfo_set_port(tsd->res, tsd->port);
- }
-
- Curl_mutex_acquire(&tsd->mutx);
- if(tsd->done) {
- /* too late, gotta clean up the mess */
- Curl_mutex_release(&tsd->mutx);
- destroy_thread_sync_data(tsd);
- }
- else {
-#ifndef CURL_DISABLE_SOCKETPAIR
- if(tsd->sock_pair[1] != CURL_SOCKET_BAD) {
-#ifdef HAVE_EVENTFD
- const uint64_t buf[1] = { 1 };
-#else
- const char buf[1] = { 1 };
-#endif
- /* DNS has been resolved, signal client task */
- if(wakeup_write(tsd->sock_pair[1], buf, sizeof(buf)) < 0) {
- /* update sock_erro to errno */
- tsd->sock_error = SOCKERRNO;
- }
- }
-#endif
- tsd->done = TRUE;
- Curl_mutex_release(&tsd->mutx);
- }
-
- return 0;
-}
-
-#else /* HAVE_GETADDRINFO */
-
-/*
- * gethostbyname_thread() resolves a name and then exits.
- */
-static
-#if defined(CURL_WINDOWS_UWP) || defined(UNDER_CE)
-DWORD
-#else
-unsigned int
-#endif
-CURL_STDCALL gethostbyname_thread(void *arg)
-{
- struct thread_data *td = arg;
- struct thread_sync_data *tsd = &td->tsd;
-
- tsd->res = Curl_ipv4_resolve_r(tsd->hostname, tsd->port);
-
- if(!tsd->res) {
- tsd->sock_error = SOCKERRNO;
- if(tsd->sock_error == 0)
- tsd->sock_error = RESOLVER_ENOMEM;
- }
-
- Curl_mutex_acquire(&tsd->mutx);
- if(tsd->done) {
- /* too late, gotta clean up the mess */
- Curl_mutex_release(&tsd->mutx);
- destroy_thread_sync_data(tsd);
- }
- else {
- tsd->done = TRUE;
- Curl_mutex_release(&tsd->mutx);
- }
-
- return 0;
-}
-
-#endif /* HAVE_GETADDRINFO */
-
-/*
- * destroy_async_data() cleans up async resolver data and thread handle.
- */
-static void destroy_async_data(struct Curl_easy *data)
-{
- struct Curl_async *async = &data->state.async;
- struct thread_data *td = &async->thdata;
- if(td->init) {
- bool done;
-#ifndef CURL_DISABLE_SOCKETPAIR
- curl_socket_t sock_rd = td->tsd.sock_pair[0];
-#endif
-
-#ifdef USE_HTTPSRR_ARES
- if(td->channel) {
- ares_destroy(td->channel);
- td->channel = NULL;
- }
-#endif
- /*
- * if the thread is still blocking in the resolve syscall, detach it and
- * let the thread do the cleanup...
- */
- Curl_mutex_acquire(&td->tsd.mutx);
- done = td->tsd.done;
- td->tsd.done = TRUE;
- Curl_mutex_release(&td->tsd.mutx);
-
- if(!done) {
- Curl_thread_destroy(td->thread_hnd);
- }
- else {
- if(td->thread_hnd != curl_thread_t_null)
- Curl_thread_join(&td->thread_hnd);
-
- destroy_thread_sync_data(&td->tsd);
- }
-#ifndef CURL_DISABLE_SOCKETPAIR
- /*
- * ensure CURLMOPT_SOCKETFUNCTION fires CURL_POLL_REMOVE
- * before the FD is invalidated to avoid EBADF on EPOLL_CTL_DEL
- */
- Curl_multi_will_close(data, sock_rd);
- wakeup_close(sock_rd);
-#endif
-
- td->init = FALSE;
- }
-
-}
-
-#ifdef USE_HTTPSRR_ARES
-static CURLcode resolve_httpsrr(struct Curl_easy *data,
- struct Curl_async *async)
-{
- int status = ares_init_options(&async->thdata.channel, NULL, 0);
- if(status != ARES_SUCCESS)
- return CURLE_FAILED_INIT;
-
- memset(&async->thdata.hinfo, 0, sizeof(struct Curl_https_rrinfo));
- async->thdata.hinfo.port = -1;
- ares_query_dnsrec(async->thdata.channel,
- data->conn->host.name, ARES_CLASS_IN,
- ARES_REC_TYPE_HTTPS,
- Curl_dnsrec_done_cb, data, NULL);
-
- return CURLE_OK;
-}
-#endif
-
-/*
- * init_resolve_thread() starts a new thread that performs the actual
- * resolve. This function returns before the resolve is done.
- *
- * Returns FALSE in case of failure, otherwise TRUE.
- */
-static bool init_resolve_thread(struct Curl_easy *data,
- const char *hostname, int port,
- const struct addrinfo *hints)
-{
- struct thread_data *td = &data->state.async.thdata;
- /* !checksrc! disable ERRNOVAR 1 */
- int err = ENOMEM;
- struct Curl_async *async = &data->state.async;
-
- async->port = port;
- async->done = FALSE;
- async->dns = NULL;
- td->thread_hnd = curl_thread_t_null;
- td->start = Curl_now();
-
- if(!init_thread_sync_data(td, hostname, port, hints)) {
- goto errno_exit;
- }
-
- /* The thread will set this TRUE when complete. */
- td->tsd.done = FALSE;
-
-#ifdef HAVE_GETADDRINFO
- td->thread_hnd = Curl_thread_create(getaddrinfo_thread, td);
-#else
- td->thread_hnd = Curl_thread_create(gethostbyname_thread, td);
-#endif
-
- if(td->thread_hnd == curl_thread_t_null) {
- /* The thread never started, so mark it as done here for proper cleanup. */
- td->tsd.done = TRUE;
- err = errno;
- goto err_exit;
- }
-#ifdef USE_HTTPSRR_ARES
- if(resolve_httpsrr(data, async))
- infof(data, "Failed HTTPS RR operation");
-#endif
- return TRUE;
-
-err_exit:
- destroy_async_data(data);
-
-errno_exit:
- CURL_SETERRNO(err);
- return FALSE;
-}
-
-/*
- * 'entry' may be NULL and then no data is returned
- */
-static CURLcode thread_wait_resolv(struct Curl_easy *data,
- struct Curl_dns_entry **entry,
- bool report)
-{
- struct thread_data *td;
- CURLcode result = CURLE_OK;
-
- DEBUGASSERT(data);
- td = &data->state.async.thdata;
- DEBUGASSERT(td);
- DEBUGASSERT(td->thread_hnd != curl_thread_t_null);
-
- /* wait for the thread to resolve the name */
- if(Curl_thread_join(&td->thread_hnd)) {
- if(entry)
- result = getaddrinfo_complete(data);
- }
- else
- DEBUGASSERT(0);
-
- data->state.async.done = TRUE;
-
- if(entry)
- *entry = data->state.async.dns;
-
- if(!data->state.async.dns && report)
- /* a name was not resolved, report error */
- result = Curl_resolver_error(data);
-
- destroy_async_data(data);
-
- if(!data->state.async.dns && report)
- connclose(data->conn, "asynch resolve failed");
-
- return result;
-}
-
-
-/*
- * Until we gain a way to signal the resolver threads to stop early, we must
- * simply wait for them and ignore their results.
- */
-void Curl_resolver_kill(struct Curl_easy *data)
-{
- struct thread_data *td = &data->state.async.thdata;
-
- /* If we are still resolving, we must wait for the threads to fully clean up,
- unfortunately. Otherwise, we can simply cancel to clean up any resolver
- data. */
- if((td->thread_hnd != curl_thread_t_null) && !data->set.quick_exit)
- (void)thread_wait_resolv(data, NULL, FALSE);
- else
- Curl_resolver_cancel(data);
-}
-
-/*
- * Curl_resolver_wait_resolv()
- *
- * Waits for a resolve to finish. This function should be avoided since using
- * this risk getting the multi interface to "hang".
- *
- * If 'entry' is non-NULL, make it point to the resolved dns entry
- *
- * Returns CURLE_COULDNT_RESOLVE_HOST if the host was not resolved,
- * CURLE_OPERATION_TIMEDOUT if a time-out occurred, or other errors.
- *
- * This is the version for resolves-in-a-thread.
- */
-CURLcode Curl_resolver_wait_resolv(struct Curl_easy *data,
- struct Curl_dns_entry **entry)
-{
- return thread_wait_resolv(data, entry, TRUE);
-}
-
-/*
- * Curl_resolver_is_resolved() is called repeatedly to check if a previous
- * name resolve request has completed. It should also make sure to time-out if
- * the operation seems to take too long.
- */
-CURLcode Curl_resolver_is_resolved(struct Curl_easy *data,
- struct Curl_dns_entry **entry)
-{
- struct thread_data *td = &data->state.async.thdata;
- bool done = FALSE;
-
- DEBUGASSERT(entry);
- *entry = NULL;
-
-#ifdef USE_HTTPSRR_ARES
- (void)Curl_ares_perform(td->channel, 0); /* ignore errors */
-#endif
-
- Curl_mutex_acquire(&td->tsd.mutx);
- done = td->tsd.done;
- Curl_mutex_release(&td->tsd.mutx);
-
- if(done) {
- CURLcode result = td->result;
- getaddrinfo_complete(data);
-
- if(!result && !data->state.async.dns)
- result = Curl_resolver_error(data);
-
- if(result) {
- destroy_async_data(data);
- return result;
- }
-#ifdef USE_HTTPSRR_ARES
- {
- struct Curl_https_rrinfo *lhrr = Curl_httpsrr_dup_move(&td->hinfo);
- if(!lhrr) {
- destroy_async_data(data);
- return CURLE_OUT_OF_MEMORY;
- }
- data->state.async.dns->hinfo = lhrr;
- }
-#endif
- destroy_async_data(data);
- *entry = data->state.async.dns;
- }
- else {
- /* poll for name lookup done with exponential backoff up to 250ms */
- /* should be fine even if this converts to 32-bit */
- timediff_t elapsed = Curl_timediff(Curl_now(),
- data->progress.t_startsingle);
- if(elapsed < 0)
- elapsed = 0;
-
- if(td->poll_interval == 0)
- /* Start at 1ms poll interval */
- td->poll_interval = 1;
- else if(elapsed >= td->interval_end)
- /* Back-off exponentially if last interval expired */
- td->poll_interval *= 2;
-
- if(td->poll_interval > 250)
- td->poll_interval = 250;
-
- td->interval_end = elapsed + td->poll_interval;
- Curl_expire(data, td->poll_interval, EXPIRE_ASYNC_NAME);
- }
-
- return CURLE_OK;
-}
-
-int Curl_resolver_getsock(struct Curl_easy *data, curl_socket_t *socks)
-{
- int ret_val = 0;
- struct thread_data *td = &data->state.async.thdata;
-#if !defined(CURL_DISABLE_SOCKETPAIR) || defined(USE_HTTPSRR_ARES)
- int socketi = 0;
-#else
- (void)socks;
-#endif
-
-#ifdef USE_HTTPSRR_ARES
- if(td->init && td->channel) {
- ret_val = Curl_ares_getsock(data, td->channel, socks);
- for(socketi = 0; socketi < (MAX_SOCKSPEREASYHANDLE - 1); socketi++)
- if(!ARES_GETSOCK_READABLE(ret_val, socketi) &&
- !ARES_GETSOCK_WRITABLE(ret_val, socketi))
- break;
- }
-#endif
-#ifndef CURL_DISABLE_SOCKETPAIR
- if(td->init) {
- /* return read fd to client for polling the DNS resolution status */
- socks[socketi] = td->tsd.sock_pair[0];
- ret_val |= GETSOCK_READSOCK(socketi);
- }
- else
-#endif
- {
- timediff_t milli;
- timediff_t ms = Curl_timediff(Curl_now(), td->start);
- if(ms < 3)
- milli = 0;
- else if(ms <= 50)
- milli = ms/3;
- else if(ms <= 250)
- milli = 50;
- else
- milli = 200;
- Curl_expire(data, milli, EXPIRE_ASYNC_NAME);
- }
-
- return ret_val;
-}
-
-#ifndef HAVE_GETADDRINFO
-/*
- * Curl_getaddrinfo() - for platforms without getaddrinfo
- */
-struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data,
- const char *hostname,
- int port,
- int *waitp)
-{
- *waitp = 0; /* default to synchronous response */
-
- /* fire up a new resolver thread! */
- if(init_resolve_thread(data, hostname, port, NULL)) {
- *waitp = 1; /* expect asynchronous response */
- return NULL;
- }
-
- failf(data, "getaddrinfo() thread failed");
-
- return NULL;
-}
-
-#else /* !HAVE_GETADDRINFO */
-
-/*
- * Curl_resolver_getaddrinfo() - for getaddrinfo
- */
-struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data,
- const char *hostname,
- int port,
- int *waitp)
-{
- struct addrinfo hints;
- int pf = PF_INET;
- *waitp = 0; /* default to synchronous response */
-
-#ifdef CURLRES_IPV6
- if((data->conn->ip_version != CURL_IPRESOLVE_V4) && Curl_ipv6works(data)) {
- /* The stack seems to be IPv6-enabled */
- if(data->conn->ip_version == CURL_IPRESOLVE_V6)
- pf = PF_INET6;
- else
- pf = PF_UNSPEC;
- }
-#endif /* CURLRES_IPV6 */
-
- memset(&hints, 0, sizeof(hints));
- hints.ai_family = pf;
- hints.ai_socktype = (data->conn->transport == TRNSPRT_TCP) ?
- SOCK_STREAM : SOCK_DGRAM;
-
- /* fire up a new resolver thread! */
- if(init_resolve_thread(data, hostname, port, &hints)) {
- *waitp = 1; /* expect asynchronous response */
- return NULL;
- }
-
- failf(data, "getaddrinfo() thread failed to start");
- return NULL;
-
-}
-
-#endif /* !HAVE_GETADDRINFO */
-
-CURLcode Curl_set_dns_servers(struct Curl_easy *data,
- char *servers)
-{
- (void)data;
- (void)servers;
- return CURLE_NOT_BUILT_IN;
-
-}
-
-CURLcode Curl_set_dns_interface(struct Curl_easy *data,
- const char *interf)
-{
- (void)data;
- (void)interf;
- return CURLE_NOT_BUILT_IN;
-}
-
-CURLcode Curl_set_dns_local_ip4(struct Curl_easy *data,
- const char *local_ip4)
-{
- (void)data;
- (void)local_ip4;
- return CURLE_NOT_BUILT_IN;
-}
-
-CURLcode Curl_set_dns_local_ip6(struct Curl_easy *data,
- const char *local_ip6)
-{
- (void)data;
- (void)local_ip6;
- return CURLE_NOT_BUILT_IN;
-}
-
-#endif /* CURLRES_THREADED */
diff --git a/libs/libcurl/src/asyn.h b/libs/libcurl/src/asyn.h
index 50cd7e858b..16626d8a8f 100644
--- a/libs/libcurl/src/asyn.h
+++ b/libs/libcurl/src/asyn.h
@@ -25,81 +25,23 @@
***************************************************************************/
#include "curl_setup.h"
-#include "curl_addrinfo.h"
-#include "httpsrr.h"
-struct addrinfo;
-struct hostent;
struct Curl_easy;
-struct connectdata;
struct Curl_dns_entry;
-#ifdef CURLRES_THREADED
-#include "curl_threads.h"
-
-/* Data for synchronization between resolver thread and its parent */
-struct thread_sync_data {
- char *hostname; /* hostname to resolve, Curl_async.hostname
- duplicate */
- curl_mutex_t mutx;
-#ifndef CURL_DISABLE_SOCKETPAIR
- curl_socket_t sock_pair[2]; /* eventfd/pipes/socket pair */
-#endif
- struct Curl_addrinfo *res;
-#ifdef HAVE_GETADDRINFO
- struct addrinfo hints;
-#endif
- int port;
- int sock_error;
- bool done;
-};
-
-struct thread_data {
- curl_thread_t thread_hnd;
- unsigned int poll_interval;
- timediff_t interval_end;
- struct curltime start;
- struct thread_sync_data tsd;
- CURLcode result; /* CURLE_OK or error handling response */
-#if defined(USE_HTTPSRR) && defined(USE_ARES)
- struct Curl_https_rrinfo hinfo;
- ares_channel channel;
- int num_pending; /* number of outstanding c-ares requests */
-#endif
- bool init;
-};
-
-#elif defined(CURLRES_ARES) /* CURLRES_THREADED */
-
-struct thread_data {
- int num_pending; /* number of outstanding c-ares requests */
- struct Curl_addrinfo *temp_ai; /* intermediary result while fetching c-ares
- parts */
- int last_status;
- CURLcode result; /* CURLE_OK or error handling response */
-#ifndef HAVE_CARES_GETADDRINFO
- struct curltime happy_eyeballs_dns_time; /* when this timer started, or 0 */
-#endif
-#ifdef USE_HTTPSRR
- struct Curl_https_rrinfo hinfo;
-#endif
- char *hostname;
-};
+#ifdef CURLRES_ASYNCH
-#endif /* CURLRES_ARES */
+#include "curl_addrinfo.h"
+#include "httpsrr.h"
-#ifdef USE_ARES
-#include <ares.h>
+struct addrinfo;
+struct hostent;
+struct connectdata;
-/* for HTTPS RR purposes as well */
-int Curl_ares_getsock(struct Curl_easy *data,
- ares_channel channel,
- curl_socket_t *socks);
-int Curl_ares_perform(ares_channel channel,
- timediff_t timeout_ms);
+#if defined(CURLRES_ARES) && defined(CURLRES_THREADED)
+#error cannot have both CURLRES_ARES and CURLRES_THREADED defined
#endif
-
/*
* This header defines all functions in the internal asynch resolver interface.
* All asynch resolvers need to provide these functions.
@@ -108,74 +50,27 @@ int Curl_ares_perform(ares_channel channel,
*/
/*
- * Curl_resolver_global_init()
+ * Curl_async_global_init()
*
* Called from curl_global_init() to initialize global resolver environment.
* Returning anything else than CURLE_OK fails curl_global_init().
*/
-int Curl_resolver_global_init(void);
+int Curl_async_global_init(void);
/*
- * Curl_resolver_global_cleanup()
+ * Curl_async_global_cleanup()
* Called from curl_global_cleanup() to destroy global resolver environment.
*/
-void Curl_resolver_global_cleanup(void);
-
-/*
- * Curl_resolver_init()
- * Called from curl_easy_init() -> Curl_open() to initialize resolver
- * URL-state specific environment ('resolver' member of the UrlState
- * structure). Should fill the passed pointer by the initialized handler.
- * Returning anything else than CURLE_OK fails curl_easy_init() with the
- * correspondent code.
- */
-CURLcode Curl_resolver_init(struct Curl_easy *easy, void **resolver);
-
-/*
- * Curl_resolver_cleanup()
- * Called from curl_easy_cleanup() -> Curl_close() to cleanup resolver
- * URL-state specific environment ('resolver' member of the UrlState
- * structure). Should destroy the handler and free all resources connected to
- * it.
- */
-void Curl_resolver_cleanup(void *resolver);
+void Curl_async_global_cleanup(void);
/*
- * Curl_resolver_duphandle()
- * Called from curl_easy_duphandle() to duplicate resolver URL-state specific
- * environment ('resolver' member of the UrlState structure). Should
- * duplicate the 'from' handle and pass the resulting handle to the 'to'
- * pointer. Returning anything else than CURLE_OK causes failed
- * curl_easy_duphandle() call.
+ * Curl_async_get_impl()
+ * Get the resolver implementation instance (c-ares channel) or NULL
+ * for passing to application callback.
*/
-CURLcode Curl_resolver_duphandle(struct Curl_easy *easy, void **to,
- void *from);
+CURLcode Curl_async_get_impl(struct Curl_easy *easy, void **impl);
-/*
- * Curl_resolver_cancel().
- *
- * It is called from inside other functions to cancel currently performing
- * resolver request. Should also free any temporary resources allocated to
- * perform a request. This never waits for resolver threads to complete.
- *
- * It is safe to call this when conn is in any state.
- */
-void Curl_resolver_cancel(struct Curl_easy *data);
-
-/*
- * Curl_resolver_kill().
- *
- * This acts like Curl_resolver_cancel() except it will block until any threads
- * associated with the resolver are complete. This never blocks for resolvers
- * that do not use threads. This is intended to be the "last chance" function
- * that cleans up an in-progress resolver completely (before its owner is about
- * to die).
- *
- * It is safe to call this when conn is in any state.
- */
-void Curl_resolver_kill(struct Curl_easy *data);
-
-/* Curl_resolver_getsock()
+/* Curl_async_getsock()
*
* This function is called from the Curl_multi_getsock() function. 'sock' is a
* pointer to an array to hold the file descriptors, with 'numsock' being the
@@ -183,10 +78,10 @@ void Curl_resolver_kill(struct Curl_easy *data);
* return bitmask indicating what file descriptors (referring to array indexes
* in the 'sock' array) to wait for, read/write.
*/
-int Curl_resolver_getsock(struct Curl_easy *data, curl_socket_t *sock);
+int Curl_async_getsock(struct Curl_easy *data, curl_socket_t *sock);
/*
- * Curl_resolver_is_resolved()
+ * Curl_async_is_resolved()
*
* Called repeatedly to check if a previous name resolve request has
* completed. It should also make sure to time-out if the operation seems to
@@ -194,25 +89,25 @@ int Curl_resolver_getsock(struct Curl_easy *data, curl_socket_t *sock);
*
* Returns normal CURLcode errors.
*/
-CURLcode Curl_resolver_is_resolved(struct Curl_easy *data,
- struct Curl_dns_entry **dns);
+CURLcode Curl_async_is_resolved(struct Curl_easy *data,
+ struct Curl_dns_entry **dns);
/*
- * Curl_resolver_wait_resolv()
+ * Curl_async_await()
*
* Waits for a resolve to finish. This function should be avoided since using
* this risk getting the multi interface to "hang".
*
- * If 'entry' is non-NULL, make it point to the resolved dns entry
+ * On return 'entry' is assigned the resolved dns (CURLE_OK or NULL otherwise.
*
* Returns CURLE_COULDNT_RESOLVE_HOST if the host was not resolved,
* CURLE_OPERATION_TIMEDOUT if a time-out occurred, or other errors.
*/
-CURLcode Curl_resolver_wait_resolv(struct Curl_easy *data,
- struct Curl_dns_entry **dnsentry);
+CURLcode Curl_async_await(struct Curl_easy *data,
+ struct Curl_dns_entry **dnsentry);
/*
- * Curl_resolver_getaddrinfo() - when using this resolver
+ * Curl_async_getaddrinfo() - when using this resolver
*
* Returns name information about the given hostname and port number. If
* successful, the 'hostent' is returned and the fourth argument will point to
@@ -222,29 +117,157 @@ CURLcode Curl_resolver_wait_resolv(struct Curl_easy *data,
* Each resolver backend must of course make sure to return data in the
* correct format to comply with this.
*/
-struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data,
- const char *hostname,
- int port,
- int *waitp);
+struct Curl_addrinfo *Curl_async_getaddrinfo(struct Curl_easy *data,
+ const char *hostname,
+ int port,
+ int ip_version,
+ int *waitp);
+
+#ifdef USE_ARES
+/* common functions for c-ares and threaded resolver with HTTPSRR */
+#include <ares.h>
+
+int Curl_ares_getsock(struct Curl_easy *data,
+ ares_channel channel,
+ curl_socket_t *socks);
+int Curl_ares_perform(ares_channel channel,
+ timediff_t timeout_ms);
+#endif
+
+#ifdef CURLRES_ARES
+/* async resolving implementation using c-ares alone */
+struct async_ares_ctx {
+ ares_channel channel;
+ int num_pending; /* number of outstanding c-ares requests */
+ struct Curl_addrinfo *temp_ai; /* intermediary result while fetching c-ares
+ parts */
+ int last_status;
+ CURLcode result; /* CURLE_OK or error handling response */
+#ifndef HAVE_CARES_GETADDRINFO
+ struct curltime happy_eyeballs_dns_time; /* when this timer started, or 0 */
+#endif
+#ifdef USE_HTTPSRR
+ struct Curl_https_rrinfo hinfo;
+#endif
+};
+
+void Curl_async_ares_shutdown(struct Curl_easy *data);
+void Curl_async_ares_destroy(struct Curl_easy *data);
+
+/* Set the DNS server to use by ares, from `data` settings. */
+CURLcode Curl_async_ares_set_dns_servers(struct Curl_easy *data);
+
+/* Set the DNS interfacer to use by ares, from `data` settings. */
+CURLcode Curl_async_ares_set_dns_interface(struct Curl_easy *data);
+
+/* Set the local ipv4 address to use by ares, from `data` settings. */
+CURLcode Curl_async_ares_set_dns_local_ip4(struct Curl_easy *data);
+
+/* Set the local ipv6 address to use by ares, from `data` settings. */
+CURLcode Curl_async_ares_set_dns_local_ip6(struct Curl_easy *data);
+
+#endif /* CURLRES_ARES */
+
+#ifdef CURLRES_THREADED
+/* async resolving implementation using POSIX threads */
+#include "curl_threads.h"
+
+/* Context for threaded address resolver */
+struct async_thrdd_addr_ctx {
+ curl_thread_t thread_hnd;
+ char *hostname; /* hostname to resolve, Curl_async.hostname
+ duplicate */
+ curl_mutex_t mutx;
+#ifndef CURL_DISABLE_SOCKETPAIR
+ curl_socket_t sock_pair[2]; /* eventfd/pipes/socket pair */
+#endif
+ struct Curl_addrinfo *res;
+#ifdef HAVE_GETADDRINFO
+ struct addrinfo hints;
+#endif
+ struct curltime start;
+ timediff_t interval_end;
+ unsigned int poll_interval;
+ int port;
+ int sock_error;
+ int ref_count;
+};
+
+/* Context for threaded resolver */
+struct async_thrdd_ctx {
+ /* `addr` is a pointer since this memory is shared with a started
+ * thread. Since threads cannot be killed, we use reference counting
+ * so that we can "release" our pointer to this memory while the
+ * thread is still running. */
+ struct async_thrdd_addr_ctx *addr;
+#if defined(USE_HTTPSRR) && defined(USE_ARES)
+ struct {
+ ares_channel channel;
+ struct Curl_https_rrinfo hinfo;
+ CURLcode result;
+ BIT(done);
+ } rr;
+#endif
+};
+
+void Curl_async_thrdd_shutdown(struct Curl_easy *data);
+void Curl_async_thrdd_destroy(struct Curl_easy *data);
+
+#endif /* CURLRES_THREADED */
+
+#ifndef CURL_DISABLE_DOH
+struct doh_probes;
+#endif
+
+#else /* CURLRES_ASYNCH */
-#ifndef CURLRES_ASYNCH
/* convert these functions if an asynch resolver is not used */
-#define Curl_resolver_cancel(x) Curl_nop_stmt
-#define Curl_resolver_kill(x) Curl_nop_stmt
-#define Curl_resolver_is_resolved(x,y) CURLE_COULDNT_RESOLVE_HOST
-#define Curl_resolver_wait_resolv(x,y) CURLE_COULDNT_RESOLVE_HOST
-#define Curl_resolver_duphandle(x,y,z) CURLE_OK
-#define Curl_resolver_init(x,y) CURLE_OK
-#define Curl_resolver_global_init() CURLE_OK
-#define Curl_resolver_global_cleanup() Curl_nop_stmt
-#define Curl_resolver_cleanup(x) Curl_nop_stmt
+#define Curl_async_get_impl(x,y) (*(y) = NULL, CURLE_OK)
+#define Curl_async_is_resolved(x,y) CURLE_COULDNT_RESOLVE_HOST
+#define Curl_async_await(x,y) CURLE_COULDNT_RESOLVE_HOST
+#define Curl_async_global_init() CURLE_OK
+#define Curl_async_global_cleanup() Curl_nop_stmt
+
+#endif /* !CURLRES_ASYNCH */
+
+#if defined(CURLRES_ASYNCH) || !defined(CURL_DISABLE_DOH)
+#define USE_CURL_ASYNC
#endif
-#ifdef CURLRES_ASYNCH
-#define Curl_resolver_asynch() 1
-#else
-#define Curl_resolver_asynch() 0
+#ifdef USE_CURL_ASYNC
+struct Curl_async {
+#ifdef CURLRES_ARES /* */
+ struct async_ares_ctx ares;
+#elif defined(CURLRES_THREADED)
+ struct async_thrdd_ctx thrdd;
#endif
+#ifndef CURL_DISABLE_DOH
+ struct doh_probes *doh; /* DoH specific data for this request */
+#endif
+ struct Curl_dns_entry *dns; /* result of resolving on success */
+ char *hostname; /* copy of the params resolv started with */
+ int port;
+ int ip_version;
+ BIT(done);
+};
+
+/*
+ * Curl_async_shutdown().
+ *
+ * This shuts down all ongoing operations.
+ */
+void Curl_async_shutdown(struct Curl_easy *data);
+
+/*
+ * Curl_async_destroy().
+ *
+ * This frees the resources of any async resolve.
+ */
+void Curl_async_destroy(struct Curl_easy *data);
+#else /* !USE_CURL_ASYNC */
+#define Curl_async_shutdown(x) Curl_nop_stmt
+#define Curl_async_destroy(x) Curl_nop_stmt
+#endif /* USE_CURL_ASYNC */
/********** end of generic resolver interface functions *****************/
diff --git a/libs/libcurl/src/cf-h1-proxy.c b/libs/libcurl/src/cf-h1-proxy.c
index 0e9db654fa..9a24245c6f 100644
--- a/libs/libcurl/src/cf-h1-proxy.c
+++ b/libs/libcurl/src/cf-h1-proxy.c
@@ -28,7 +28,7 @@
#include <curl/curl.h>
#include "urldata.h"
-#include "dynbuf.h"
+#include "curlx/dynbuf.h"
#include "sendf.h"
#include "http.h"
#include "http1.h"
@@ -40,11 +40,11 @@
#include "cf-h1-proxy.h"
#include "connect.h"
#include "curl_trc.h"
-#include "curlx.h"
+#include "strcase.h"
#include "vtls/vtls.h"
#include "transfer.h"
#include "multiif.h"
-#include "strparse.h"
+#include "curlx/strparse.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
@@ -97,8 +97,8 @@ static CURLcode tunnel_reinit(struct Curl_cfilter *cf,
(void)data;
(void)cf;
DEBUGASSERT(ts);
- Curl_dyn_reset(&ts->rcvbuf);
- Curl_dyn_reset(&ts->request_data);
+ curlx_dyn_reset(&ts->rcvbuf);
+ curlx_dyn_reset(&ts->request_data);
ts->tunnel_state = H1_TUNNEL_INIT;
ts->keepon = KEEPON_CONNECT;
ts->cl = 0;
@@ -123,8 +123,8 @@ static CURLcode tunnel_init(struct Curl_cfilter *cf,
infof(data, "allocate connect buffer");
- Curl_dyn_init(&ts->rcvbuf, DYN_PROXY_CONNECT_HEADERS);
- Curl_dyn_init(&ts->request_data, DYN_HTTP_REQUEST);
+ curlx_dyn_init(&ts->rcvbuf, DYN_PROXY_CONNECT_HEADERS);
+ curlx_dyn_init(&ts->request_data, DYN_HTTP_REQUEST);
Curl_httpchunk_init(data, &ts->ch, TRUE);
*pts = ts;
@@ -150,7 +150,7 @@ static void h1_tunnel_go_state(struct Curl_cfilter *cf,
CURL_TRC_CF(data, cf, "new tunnel state 'connect'");
ts->tunnel_state = H1_TUNNEL_CONNECT;
ts->keepon = KEEPON_CONNECT;
- Curl_dyn_reset(&ts->rcvbuf);
+ curlx_dyn_reset(&ts->rcvbuf);
break;
case H1_TUNNEL_RECEIVE:
@@ -173,8 +173,8 @@ static void h1_tunnel_go_state(struct Curl_cfilter *cf,
if(new_state == H1_TUNNEL_FAILED)
CURL_TRC_CF(data, cf, "new tunnel state 'failed'");
ts->tunnel_state = new_state;
- Curl_dyn_reset(&ts->rcvbuf);
- Curl_dyn_reset(&ts->request_data);
+ curlx_dyn_reset(&ts->rcvbuf);
+ curlx_dyn_reset(&ts->request_data);
/* restore the protocol pointer */
data->info.httpcode = 0; /* clear it as it might've been used for the
proxy */
@@ -193,8 +193,8 @@ static void tunnel_free(struct Curl_cfilter *cf,
struct h1_tunnel_state *ts = cf->ctx;
if(ts) {
h1_tunnel_go_state(cf, ts, H1_TUNNEL_FAILED, data);
- Curl_dyn_free(&ts->rcvbuf);
- Curl_dyn_free(&ts->request_data);
+ curlx_dyn_free(&ts->rcvbuf);
+ curlx_dyn_free(&ts->request_data);
Curl_httpchunk_free(data, &ts->ch);
free(ts);
cf->ctx = NULL;
@@ -226,7 +226,7 @@ static CURLcode start_CONNECT(struct Curl_cfilter *cf,
infof(data, "Establish HTTP proxy tunnel to %s", req->authority);
- Curl_dyn_reset(&ts->request_data);
+ curlx_dyn_reset(&ts->request_data);
ts->nsent = 0;
ts->headerlines = 0;
http_minor = (cf->conn->http_proxy.proxytype == CURLPROXY_HTTP_1_0) ? 0 : 1;
@@ -248,8 +248,8 @@ static CURLcode send_CONNECT(struct Curl_cfilter *cf,
struct h1_tunnel_state *ts,
bool *done)
{
- char *buf = Curl_dyn_ptr(&ts->request_data);
- size_t request_len = Curl_dyn_len(&ts->request_data);
+ char *buf = curlx_dyn_ptr(&ts->request_data);
+ size_t request_len = curlx_dyn_len(&ts->request_data);
size_t blen = request_len;
CURLcode result = CURLE_OK;
ssize_t nwritten;
@@ -316,7 +316,7 @@ static CURLcode on_resp_header(struct Curl_cfilter *cf,
}
else {
const char *p = header + strlen("Content-Length:");
- if(Curl_str_numblanks(&p, &ts->cl)) {
+ if(curlx_str_numblanks(&p, &ts->cl)) {
failf(data, "Unsupported Content-Length value");
return CURLE_WEIRD_SERVER_REPLY;
}
@@ -444,7 +444,7 @@ static CURLcode recv_CONNECT_resp(struct Curl_cfilter *cf,
continue;
}
- if(Curl_dyn_addn(&ts->rcvbuf, &byte, 1)) {
+ if(curlx_dyn_addn(&ts->rcvbuf, &byte, 1)) {
failf(data, "CONNECT response too large");
return CURLE_RECV_ERROR;
}
@@ -454,8 +454,8 @@ static CURLcode recv_CONNECT_resp(struct Curl_cfilter *cf,
continue;
ts->headerlines++;
- linep = Curl_dyn_ptr(&ts->rcvbuf);
- line_len = Curl_dyn_len(&ts->rcvbuf); /* amount of bytes in this line */
+ linep = curlx_dyn_ptr(&ts->rcvbuf);
+ line_len = curlx_dyn_len(&ts->rcvbuf); /* amount of bytes in this line */
/* output debug if that is requested */
Curl_debug(data, CURLINFO_HEADER_IN, linep, line_len);
@@ -512,7 +512,7 @@ static CURLcode recv_CONNECT_resp(struct Curl_cfilter *cf,
if(result)
return result;
- Curl_dyn_reset(&ts->rcvbuf);
+ curlx_dyn_reset(&ts->rcvbuf);
} /* while there is buffer left and loop is requested */
if(error)
diff --git a/libs/libcurl/src/cf-h2-proxy.c b/libs/libcurl/src/cf-h2-proxy.c
index 1175399696..fe257c6457 100644
--- a/libs/libcurl/src/cf-h2-proxy.c
+++ b/libs/libcurl/src/cf-h2-proxy.c
@@ -32,7 +32,7 @@
#include "connect.h"
#include "curl_trc.h"
#include "bufq.h"
-#include "dynbuf.h"
+#include "curlx/dynbuf.h"
#include "dynhds.h"
#include "http1.h"
#include "http2.h"
diff --git a/libs/libcurl/src/cf-haproxy.c b/libs/libcurl/src/cf-haproxy.c
index a0dadce173..05855a828e 100644
--- a/libs/libcurl/src/cf-haproxy.c
+++ b/libs/libcurl/src/cf-haproxy.c
@@ -54,13 +54,13 @@ static void cf_haproxy_ctx_reset(struct cf_haproxy_ctx *ctx)
{
DEBUGASSERT(ctx);
ctx->state = HAPROXY_INIT;
- Curl_dyn_reset(&ctx->data_out);
+ curlx_dyn_reset(&ctx->data_out);
}
static void cf_haproxy_ctx_free(struct cf_haproxy_ctx *ctx)
{
if(ctx) {
- Curl_dyn_free(&ctx->data_out);
+ curlx_dyn_free(&ctx->data_out);
free(ctx);
}
}
@@ -79,7 +79,7 @@ static CURLcode cf_haproxy_date_out_set(struct Curl_cfilter*cf,
#ifdef USE_UNIX_SOCKETS
if(cf->conn->unix_domain_socket)
/* the buffer is large enough to hold this! */
- result = Curl_dyn_addn(&ctx->data_out, STRCONST("PROXY UNKNOWN\r\n"));
+ result = curlx_dyn_addn(&ctx->data_out, STRCONST("PROXY UNKNOWN\r\n"));
else {
#endif /* USE_UNIX_SOCKETS */
result = Curl_conn_cf_get_ip_info(cf->next, data, &is_ipv6, &ipquad);
@@ -92,10 +92,10 @@ static CURLcode cf_haproxy_date_out_set(struct Curl_cfilter*cf,
else
client_ip = ipquad.local_ip;
- result = Curl_dyn_addf(&ctx->data_out, "PROXY %s %s %s %i %i\r\n",
- is_ipv6 ? "TCP6" : "TCP4",
- client_ip, ipquad.remote_ip,
- ipquad.local_port, ipquad.remote_port);
+ result = curlx_dyn_addf(&ctx->data_out, "PROXY %s %s %s %i %i\r\n",
+ is_ipv6 ? "TCP6" : "TCP4",
+ client_ip, ipquad.remote_ip,
+ ipquad.local_port, ipquad.remote_port);
#ifdef USE_UNIX_SOCKETS
}
@@ -129,11 +129,11 @@ static CURLcode cf_haproxy_connect(struct Curl_cfilter *cf,
ctx->state = HAPROXY_SEND;
FALLTHROUGH();
case HAPROXY_SEND:
- len = Curl_dyn_len(&ctx->data_out);
+ len = curlx_dyn_len(&ctx->data_out);
if(len > 0) {
ssize_t nwritten;
nwritten = Curl_conn_cf_send(cf->next, data,
- Curl_dyn_ptr(&ctx->data_out), len, FALSE,
+ curlx_dyn_ptr(&ctx->data_out), len, FALSE,
&result);
if(nwritten < 0) {
if(result != CURLE_AGAIN)
@@ -141,8 +141,8 @@ static CURLcode cf_haproxy_connect(struct Curl_cfilter *cf,
result = CURLE_OK;
nwritten = 0;
}
- Curl_dyn_tail(&ctx->data_out, len - (size_t)nwritten);
- if(Curl_dyn_len(&ctx->data_out) > 0) {
+ curlx_dyn_tail(&ctx->data_out, len - (size_t)nwritten);
+ if(curlx_dyn_len(&ctx->data_out) > 0) {
result = CURLE_OK;
goto out;
}
@@ -150,7 +150,7 @@ static CURLcode cf_haproxy_connect(struct Curl_cfilter *cf,
ctx->state = HAPROXY_DONE;
FALLTHROUGH();
default:
- Curl_dyn_free(&ctx->data_out);
+ curlx_dyn_free(&ctx->data_out);
break;
}
@@ -222,7 +222,7 @@ static CURLcode cf_haproxy_create(struct Curl_cfilter **pcf,
goto out;
}
ctx->state = HAPROXY_INIT;
- Curl_dyn_init(&ctx->data_out, DYN_HAXPROXY);
+ curlx_dyn_init(&ctx->data_out, DYN_HAXPROXY);
result = Curl_cf_create(&cf, &Curl_cft_haproxy, ctx);
if(result)
diff --git a/libs/libcurl/src/cf-https-connect.c b/libs/libcurl/src/cf-https-connect.c
index 1cc4a03e49..c66bcba2b2 100644
--- a/libs/libcurl/src/cf-https-connect.c
+++ b/libs/libcurl/src/cf-https-connect.c
@@ -113,7 +113,6 @@ static CURLcode cf_hc_baller_cntrl(struct cf_hc_baller *b,
struct cf_hc_ctx {
cf_hc_state state;
- const struct Curl_dns_entry *remotehost;
struct curltime started; /* when connect started */
CURLcode result; /* overall result */
struct cf_hc_baller ballers[2];
@@ -147,11 +146,10 @@ static void cf_hc_baller_init(struct cf_hc_baller *b,
struct Curl_easy *data,
int transport)
{
- struct cf_hc_ctx *ctx = cf->ctx;
struct Curl_cfilter *save = cf->next;
cf->next = NULL;
- b->started = Curl_now();
+ b->started = curlx_now();
switch(b->alpn_id) {
case ALPN_h3:
transport = TRNSPRT_QUIC;
@@ -161,8 +159,8 @@ static void cf_hc_baller_init(struct cf_hc_baller *b,
}
if(!b->result)
- b->result = Curl_cf_setup_insert_after(cf, data, ctx->remotehost,
- transport, CURL_CF_SSL_ENABLE);
+ b->result = Curl_cf_setup_insert_after(cf, data, transport,
+ CURL_CF_SSL_ENABLE);
b->cf = cf->next;
cf->next = save;
}
@@ -213,11 +211,12 @@ static CURLcode baller_connected(struct Curl_cfilter *cf,
reply_ms = cf_hc_baller_reply_ms(winner, data);
if(reply_ms >= 0)
CURL_TRC_CF(data, cf, "connect+handshake %s: %dms, 1st data: %dms",
- winner->name, (int)Curl_timediff(Curl_now(), winner->started),
- reply_ms);
+ winner->name, (int)curlx_timediff(curlx_now(),
+ winner->started), reply_ms);
else
CURL_TRC_CF(data, cf, "deferred handshake %s: %dms",
- winner->name, (int)Curl_timediff(Curl_now(), winner->started));
+ winner->name, (int)curlx_timediff(curlx_now(),
+ winner->started));
cf->next = winner->cf;
winner->cf = NULL;
@@ -267,7 +266,7 @@ static bool time_to_start_next(struct Curl_cfilter *cf,
ctx->ballers[idx].name);
return TRUE;
}
- elapsed_ms = Curl_timediff(now, ctx->started);
+ elapsed_ms = curlx_timediff(now, ctx->started);
if(elapsed_ms >= ctx->hard_eyeballs_timeout_ms) {
CURL_TRC_CF(data, cf, "hard timeout of %dms reached, starting %s",
ctx->hard_eyeballs_timeout_ms, ctx->ballers[idx].name);
@@ -304,7 +303,7 @@ static CURLcode cf_hc_connect(struct Curl_cfilter *cf,
}
*done = FALSE;
- now = Curl_now();
+ now = curlx_now();
switch(ctx->state) {
case CF_HC_INIT:
DEBUGASSERT(!cf->next);
@@ -469,7 +468,7 @@ static struct curltime cf_get_max_baller_time(struct Curl_cfilter *cf,
struct Curl_cfilter *cfb = ctx->ballers[i].cf;
memset(&t, 0, sizeof(t));
if(cfb && !cfb->cft->query(cfb, data, query, NULL, &t)) {
- if((t.tv_sec || t.tv_usec) && Curl_timediff_us(t, tmax) > 0)
+ if((t.tv_sec || t.tv_usec) && curlx_timediff_us(t, tmax) > 0)
tmax = t;
}
}
@@ -575,7 +574,6 @@ struct Curl_cftype Curl_cft_http_connect = {
static CURLcode cf_hc_create(struct Curl_cfilter **pcf,
struct Curl_easy *data,
- const struct Curl_dns_entry *remotehost,
enum alpnid *alpnids, size_t alpn_count)
{
struct Curl_cfilter *cf = NULL;
@@ -597,7 +595,6 @@ static CURLcode cf_hc_create(struct Curl_cfilter **pcf,
result = CURLE_OUT_OF_MEMORY;
goto out;
}
- ctx->remotehost = remotehost;
for(i = 0; i < alpn_count; ++i)
cf_hc_baller_assign(&ctx->ballers[i], alpnids[i]);
for(; i < CURL_ARRAYSIZE(ctx->ballers); ++i)
@@ -619,14 +616,13 @@ out:
static CURLcode cf_http_connect_add(struct Curl_easy *data,
struct connectdata *conn,
int sockindex,
- const struct Curl_dns_entry *remotehost,
enum alpnid *alpn_ids, size_t alpn_count)
{
struct Curl_cfilter *cf;
CURLcode result = CURLE_OK;
DEBUGASSERT(data);
- result = cf_hc_create(&cf, data, remotehost, alpn_ids, alpn_count);
+ result = cf_hc_create(&cf, data, alpn_ids, alpn_count);
if(result)
goto out;
Curl_conn_cf_add(data, conn, sockindex, cf);
@@ -647,8 +643,7 @@ static bool cf_https_alpns_contain(enum alpnid id,
CURLcode Curl_cf_https_setup(struct Curl_easy *data,
struct connectdata *conn,
- int sockindex,
- const struct Curl_dns_entry *remotehost)
+ int sockindex)
{
enum alpnid alpn_ids[2];
size_t alpn_count = 0;
@@ -656,7 +651,6 @@ CURLcode Curl_cf_https_setup(struct Curl_easy *data,
struct Curl_cfilter cf_fake, *cf = NULL;
(void)sockindex;
- (void)remotehost;
/* we want to log for the filter before we create it, fake it. */
memset(&cf_fake, 0, sizeof(cf_fake));
cf_fake.cft = &Curl_cft_http_connect;
@@ -664,22 +658,23 @@ CURLcode Curl_cf_https_setup(struct Curl_easy *data,
if(conn->bits.tls_enable_alpn) {
#ifdef USE_HTTPSRR
- /* Is there a HTTPSRR and if so, do its ALPNs it apply here?
+ /* Is there a HTTPSRR use its ALPNs here.
* We are here after having selected a connection to a host+port and
* can no longer change that. Any HTTPSRR advice for other hosts and ports
* we need to ignore. */
- if(conn->dns_entry && conn->dns_entry->hinfo &&
- !conn->dns_entry->hinfo->no_def_alpn && /* ALPNs are defaults */
- (!conn->dns_entry->hinfo->target || /* for same host */
- !conn->dns_entry->hinfo->target[0] ||
- (conn->dns_entry->hinfo->target[0] == '.' &&
- !conn->dns_entry->hinfo->target[0])) &&
- (conn->dns_entry->hinfo->port < 0 || /* for same port */
- conn->dns_entry->hinfo->port == conn->remote_port)) {
+ struct Curl_dns_entry *dns = data->state.dns[sockindex];
+ struct Curl_https_rrinfo *rr = dns ? dns->hinfo : NULL;
+ if(rr && !rr->no_def_alpn && /* ALPNs are defaults */
+ (!rr->target || /* for same host */
+ !rr->target[0] ||
+ (rr->target[0] == '.' &&
+ !rr->target[1])) &&
+ (rr->port < 0 || /* for same port */
+ rr->port == conn->remote_port)) {
size_t i;
- for(i = 0; i < CURL_ARRAYSIZE(conn->dns_entry->hinfo->alpns) &&
+ for(i = 0; i < CURL_ARRAYSIZE(rr->alpns) &&
alpn_count < CURL_ARRAYSIZE(alpn_ids); ++i) {
- enum alpnid alpn = conn->dns_entry->hinfo->alpns[i];
+ enum alpnid alpn = rr->alpns[i];
if(cf_https_alpns_contain(alpn, alpn_ids, alpn_count))
continue;
switch(alpn) {
@@ -738,8 +733,7 @@ CURLcode Curl_cf_https_setup(struct Curl_easy *data,
/* If we identified ALPNs to use, install our filter. Otherwise,
* install nothing, so our call will use a default connect setup. */
if(alpn_count) {
- result = cf_http_connect_add(data, conn, sockindex, remotehost,
- alpn_ids, alpn_count);
+ result = cf_http_connect_add(data, conn, sockindex, alpn_ids, alpn_count);
}
out:
diff --git a/libs/libcurl/src/cf-https-connect.h b/libs/libcurl/src/cf-https-connect.h
index 047550e383..8d956c04bf 100644
--- a/libs/libcurl/src/cf-https-connect.h
+++ b/libs/libcurl/src/cf-https-connect.h
@@ -38,20 +38,17 @@ extern struct Curl_cftype Curl_cft_http_connect;
CURLcode Curl_cf_http_connect_add(struct Curl_easy *data,
struct connectdata *conn,
int sockindex,
- const struct Curl_dns_entry *remotehost,
bool try_h3, bool try_h21);
CURLcode
Curl_cf_http_connect_insert_after(struct Curl_cfilter *cf_at,
struct Curl_easy *data,
- const struct Curl_dns_entry *remotehost,
bool try_h3, bool try_h21);
CURLcode Curl_cf_https_setup(struct Curl_easy *data,
struct connectdata *conn,
- int sockindex,
- const struct Curl_dns_entry *remotehost);
+ int sockindex);
#endif /* !defined(CURL_DISABLE_HTTP) */
diff --git a/libs/libcurl/src/cf-socket.c b/libs/libcurl/src/cf-socket.c
index b40bd05801..9e85ee211a 100644
--- a/libs/libcurl/src/cf-socket.c
+++ b/libs/libcurl/src/cf-socket.c
@@ -74,17 +74,17 @@
#include "multiif.h"
#include "sockaddr.h" /* required for Curl_sockaddr_storage */
#include "inet_ntop.h"
-#include "inet_pton.h"
+#include "curlx/inet_pton.h"
#include "progress.h"
-#include "warnless.h"
+#include "curlx/warnless.h"
#include "conncache.h"
#include "multihandle.h"
#include "rand.h"
#include "share.h"
#include "strdup.h"
#include "system_win32.h"
-#include "version_win32.h"
-#include "strparse.h"
+#include "curlx/version_win32.h"
+#include "curlx/strparse.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
@@ -674,21 +674,14 @@ static CURLcode bindlocal(struct Curl_easy *data, struct connectdata *conn,
* of the connection. The resolve functions should really be changed
* to take a type parameter instead.
*/
- unsigned char ipver = conn->ip_version;
- int rc;
-
- if(af == AF_INET)
- conn->ip_version = CURL_IPRESOLVE_V4;
+ int ip_version = (af == AF_INET) ?
+ CURL_IPRESOLVE_V4 : CURL_IPRESOLVE_WHATEVER;
#ifdef USE_IPV6
- else if(af == AF_INET6)
- conn->ip_version = CURL_IPRESOLVE_V6;
+ if(af == AF_INET6)
+ ip_version = CURL_IPRESOLVE_V6;
#endif
- rc = Curl_resolv(data, host, 80, FALSE, &h);
- if(rc == CURLRESOLV_PENDING)
- (void)Curl_resolver_wait_resolv(data, &h);
- conn->ip_version = ipver;
-
+ (void)Curl_resolv_blocking(data, host, 80, ip_version, &h);
if(h) {
int h_af = h->addr->ai_family;
/* convert the resolved address, sizeof myhost >= INET_ADDRSTRLEN */
@@ -731,7 +724,7 @@ static CURLcode bindlocal(struct Curl_easy *data, struct connectdata *conn,
IDs and the former returns none at all. So the scope ID, if
present, is known to be numeric */
curl_off_t scope_id;
- if(Curl_str_number((const char **)CURL_UNCONST(&scope_ptr),
+ if(curlx_str_number((const char **)CURL_UNCONST(&scope_ptr),
&scope_id, UINT_MAX))
return CURLE_UNSUPPORTED_PROTOCOL;
si6->sin6_scope_id = (unsigned int)scope_id;
@@ -966,25 +959,25 @@ static CURLcode cf_socket_ctx_init(struct cf_socket_ctx *ctx,
const char *p = getenv("CURL_DBG_SOCK_WBLOCK");
if(p) {
curl_off_t l;
- if(!Curl_str_number(&p, &l, 100))
+ if(!curlx_str_number(&p, &l, 100))
ctx->wblock_percent = (int)l;
}
p = getenv("CURL_DBG_SOCK_WPARTIAL");
if(p) {
curl_off_t l;
- if(!Curl_str_number(&p, &l, 100))
+ if(!curlx_str_number(&p, &l, 100))
ctx->wpartial_percent = (int)l;
}
p = getenv("CURL_DBG_SOCK_RBLOCK");
if(p) {
curl_off_t l;
- if(!Curl_str_number(&p, &l, 100))
+ if(!curlx_str_number(&p, &l, 100))
ctx->rblock_percent = (int)l;
}
p = getenv("CURL_DBG_SOCK_RMAX");
if(p) {
curl_off_t l;
- if(!Curl_str_number(&p, &l, CURL_OFF_T_MAX))
+ if(!curlx_str_number(&p, &l, CURL_OFF_T_MAX))
ctx->recv_max = (size_t)l;
}
}
@@ -1112,7 +1105,7 @@ static CURLcode cf_socket_open(struct Curl_cfilter *cf,
(void)data;
DEBUGASSERT(ctx->sock == CURL_SOCKET_BAD);
- ctx->started_at = Curl_now();
+ ctx->started_at = curlx_now();
#ifdef SOCK_NONBLOCK
/* Do not tuck SOCK_NONBLOCK into socktype when opensocket callback is set
* because we would not know how socketype is about to be used in the
@@ -1228,7 +1221,7 @@ out:
}
else if(isconnected) {
set_local_ip(cf, data);
- ctx->connected_at = Curl_now();
+ ctx->connected_at = curlx_now();
cf->connected = TRUE;
}
CURL_TRC_CF(data, cf, "cf_socket_open() -> %d, fd=%" FMT_SOCKET_T,
@@ -1347,7 +1340,7 @@ static CURLcode cf_tcp_connect(struct Curl_cfilter *cf,
else if(rc == CURL_CSELECT_OUT || cf->conn->bits.tcp_fastopen) {
if(verifyconnect(ctx->sock, &ctx->error)) {
/* we are connected with TCP, awesome! */
- ctx->connected_at = Curl_now();
+ ctx->connected_at = curlx_now();
set_local_ip(cf, data);
*done = TRUE;
cf->connected = TRUE;
@@ -1448,9 +1441,9 @@ static void win_update_sndbuf_size(struct cf_socket_ctx *ctx)
{
ULONG ideal;
DWORD ideallen;
- struct curltime n = Curl_now();
+ struct curltime n = curlx_now();
- if(Curl_timediff(n, ctx->last_sndbuf_query_at) > 1000) {
+ if(curlx_timediff(n, ctx->last_sndbuf_query_at) > 1000) {
if(!WSAIoctl(ctx->sock, SIO_IDEAL_SEND_BACKLOG_QUERY, 0, 0,
&ideal, sizeof(ideal), &ideallen, 0, 0) &&
ideal != ctx->sndbuf_size &&
@@ -1611,7 +1604,7 @@ static ssize_t cf_socket_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
CURL_TRC_CF(data, cf, "recv(len=%zu) -> %d, err=%d", len, (int)nread,
*err);
if(nread > 0 && !ctx->got_first_byte) {
- ctx->first_byte_at = Curl_now();
+ ctx->first_byte_at = curlx_now();
ctx->got_first_byte = TRUE;
}
return nread;
@@ -1722,7 +1715,7 @@ static CURLcode cf_socket_query(struct Curl_cfilter *cf,
return CURLE_OK;
case CF_QUERY_CONNECT_REPLY_MS:
if(ctx->got_first_byte) {
- timediff_t ms = Curl_timediff(ctx->first_byte_at, ctx->started_at);
+ timediff_t ms = curlx_timediff(ctx->first_byte_at, ctx->started_at);
*pres1 = (ms < INT_MAX) ? (int)ms : INT_MAX;
}
else
@@ -2039,7 +2032,7 @@ static timediff_t cf_tcp_accept_timeleft(struct Curl_cfilter *cf,
timeout_ms = data->set.accepttimeout;
#endif
- now = Curl_now();
+ now = curlx_now();
/* check if the generic timeout possibly is set shorter */
other = Curl_timeleft(data, &now, FALSE);
if(other && (other < timeout_ms))
@@ -2048,7 +2041,7 @@ static timediff_t cf_tcp_accept_timeleft(struct Curl_cfilter *cf,
timeout_ms = other;
else {
/* subtract elapsed time */
- timeout_ms -= Curl_timediff(now, ctx->started_at);
+ timeout_ms -= curlx_timediff(now, ctx->started_at);
if(!timeout_ms)
/* avoid returning 0 as that means no timeout! */
timeout_ms = -1;
@@ -2144,7 +2137,12 @@ static CURLcode cf_tcp_accept_connect(struct Curl_cfilter *cf,
if(0 == getsockname(ctx->sock, (struct sockaddr *) &add, &size)) {
size = sizeof(add);
+#ifdef HAVE_ACCEPT4
+ s_accepted = accept4(ctx->sock, (struct sockaddr *) &add, &size,
+ SOCK_NONBLOCK | SOCK_CLOEXEC);
+#else
s_accepted = accept(ctx->sock, (struct sockaddr *) &add, &size);
+#endif
}
if(CURL_SOCKET_BAD == s_accepted) {
@@ -2153,7 +2151,9 @@ static CURLcode cf_tcp_accept_connect(struct Curl_cfilter *cf,
}
infof(data, "Connection accepted from server");
+#ifndef HAVE_ACCEPT4
(void)curlx_nonblock(s_accepted, TRUE); /* enable non-blocking */
+#endif
/* Replace any filter on SECONDARY with one listening on this socket */
ctx->listening = FALSE;
ctx->accepted = TRUE;
@@ -2164,7 +2164,7 @@ static CURLcode cf_tcp_accept_connect(struct Curl_cfilter *cf,
cf_tcp_set_accepted_remote_ip(cf, data);
set_local_ip(cf, data);
ctx->active = TRUE;
- ctx->connected_at = Curl_now();
+ ctx->connected_at = curlx_now();
cf->connected = TRUE;
CURL_TRC_CF(data, cf, "accepted_set(sock=%" FMT_SOCKET_T
", remote=%s port=%d)",
@@ -2182,6 +2182,7 @@ static CURLcode cf_tcp_accept_connect(struct Curl_cfilter *cf,
if(error)
return CURLE_ABORTED_BY_CALLBACK;
}
+ *done = TRUE;
return CURLE_OK;
}
@@ -2230,7 +2231,7 @@ CURLcode Curl_conn_tcp_listen_set(struct Curl_easy *data,
goto out;
Curl_conn_cf_add(data, conn, sockindex, cf);
- ctx->started_at = Curl_now();
+ ctx->started_at = curlx_now();
conn->sock[sockindex] = ctx->sock;
set_local_ip(cf, data);
CURL_TRC_CF(data, cf, "set filter for listen socket fd=%" FMT_SOCKET_T
diff --git a/libs/libcurl/src/cf-socket.h b/libs/libcurl/src/cf-socket.h
index 44cae12879..520e764c1c 100644
--- a/libs/libcurl/src/cf-socket.h
+++ b/libs/libcurl/src/cf-socket.h
@@ -25,7 +25,7 @@
***************************************************************************/
#include "curl_setup.h"
-#include "nonblock.h" /* for curlx_nonblock(), formerly Curl_nonblock() */
+#include "curlx/nonblock.h" /* for curlx_nonblock() */
#include "sockaddr.h"
struct Curl_addrinfo;
diff --git a/libs/libcurl/src/cfilters.c b/libs/libcurl/src/cfilters.c
index c2036f7092..5dd3271f20 100644
--- a/libs/libcurl/src/cfilters.c
+++ b/libs/libcurl/src/cfilters.c
@@ -34,8 +34,8 @@
#include "multiif.h"
#include "progress.h"
#include "select.h"
-#include "warnless.h"
-#include "strparse.h"
+#include "curlx/warnless.h"
+#include "curlx/strparse.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
@@ -198,7 +198,7 @@ CURLcode Curl_conn_shutdown(struct Curl_easy *data, int sockindex, bool *done)
}
*done = FALSE;
- now = Curl_now();
+ now = curlx_now();
if(!Curl_shutdown_started(data, sockindex)) {
CURL_TRC_M(data, "shutdown start on%s connection",
sockindex ? " secondary" : "");
@@ -415,7 +415,6 @@ CURLcode Curl_conn_connect(struct Curl_easy *data,
DEBUGASSERT(data->conn);
cf = data->conn->cfilter[sockindex];
- DEBUGASSERT(cf);
if(!cf) {
*done = FALSE;
return CURLE_FAILED_INIT;
@@ -443,7 +442,7 @@ CURLcode Curl_conn_connect(struct Curl_easy *data,
* socket and ip related information. */
cf_cntrl_update_info(data, data->conn);
conn_report_connect_stats(data, data->conn);
- data->conn->keepalive = Curl_now();
+ data->conn->keepalive = curlx_now();
Curl_verboseconnect(data, data->conn, sockindex);
goto out;
}
@@ -942,7 +941,7 @@ CURLcode Curl_conn_send(struct Curl_easy *data, int sockindex,
const char *p = getenv("CURL_SMALLSENDS");
if(p) {
curl_off_t altsize;
- if(!Curl_str_number(&p, &altsize, write_len))
+ if(!curlx_str_number(&p, &altsize, write_len))
write_len = (size_t)altsize;
}
}
diff --git a/libs/libcurl/src/cfilters.h b/libs/libcurl/src/cfilters.h
index 7155695418..e93bca96a8 100644
--- a/libs/libcurl/src/cfilters.h
+++ b/libs/libcurl/src/cfilters.h
@@ -24,7 +24,7 @@
*
***************************************************************************/
-#include "timediff.h"
+#include "curlx/timediff.h"
struct Curl_cfilter;
struct Curl_easy;
diff --git a/libs/libcurl/src/config-win32.h b/libs/libcurl/src/config-win32.h
index 9ec03e3294..3544a29557 100644
--- a/libs/libcurl/src/config-win32.h
+++ b/libs/libcurl/src/config-win32.h
@@ -159,10 +159,6 @@
/* Define if you have the select function. */
#define HAVE_SELECT 1
-/* Define if libSSH2 is in use */
-#define USE_LIBSSH2 1
-#define HAVE_LIBSSH2_H 1
-
#ifndef UNDER_CE
/* Define if you have the setlocale function. */
#define HAVE_SETLOCALE 1
@@ -457,9 +453,6 @@ Vista
#define USE_WIN32_LDAP 1
#endif
-/* if SSL is enabled */
-#define USE_OPENSSL 1
-
/* Define to use the Windows crypto library. */
#ifndef CURL_WINDOWS_UWP
#define USE_WIN32_CRYPTO
diff --git a/libs/libcurl/src/conncache.c b/libs/libcurl/src/conncache.c
index 5cc9fc88d2..1de4a86b7d 100644
--- a/libs/libcurl/src/conncache.c
+++ b/libs/libcurl/src/conncache.c
@@ -43,7 +43,8 @@
#include "connect.h"
#include "select.h"
#include "strcase.h"
-#include "strparse.h"
+#include "curlx/strparse.h"
+#include "uint-table.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
@@ -132,20 +133,19 @@ static void cpool_bundle_free_entry(void *freethis)
cpool_bundle_destroy((struct cpool_bundle *)freethis);
}
-int Curl_cpool_init(struct cpool *cpool,
- struct Curl_easy *idata,
- struct Curl_share *share,
- size_t size)
+void Curl_cpool_init(struct cpool *cpool,
+ struct Curl_easy *idata,
+ struct Curl_share *share,
+ size_t size)
{
Curl_hash_init(&cpool->dest2bundle, size, Curl_hash_str,
- Curl_str_key_compare, cpool_bundle_free_entry);
+ curlx_str_key_compare, cpool_bundle_free_entry);
DEBUGASSERT(idata);
cpool->idata = idata;
cpool->share = share;
cpool->initialised = TRUE;
- return 0; /* good */
}
/* Return the "first" connection in the pool or NULL. */
@@ -294,14 +294,14 @@ cpool_bundle_get_oldest_idle(struct cpool_bundle *bundle)
struct connectdata *oldest_idle = NULL;
struct connectdata *conn;
- now = Curl_now();
+ now = curlx_now();
curr = Curl_llist_head(&bundle->conns);
while(curr) {
conn = Curl_node_elem(curr);
if(!CONN_INUSE(conn)) {
/* Set higher score for the age passed since the connection was used */
- score = Curl_timediff(now, conn->lastused);
+ score = curlx_timediff(now, conn->lastused);
if(score > highscore) {
highscore = score;
@@ -324,7 +324,7 @@ static struct connectdata *cpool_get_oldest_idle(struct cpool *cpool)
timediff_t highscore =- 1;
timediff_t score;
- now = Curl_now();
+ now = curlx_now();
Curl_hash_start_iterate(&cpool->dest2bundle, &iter);
for(he = Curl_hash_next_element(&iter); he;
@@ -338,7 +338,7 @@ static struct connectdata *cpool_get_oldest_idle(struct cpool *cpool)
if(CONN_INUSE(conn) || conn->bits.close || conn->connect_only)
continue;
/* Set higher score for the age passed since the connection was used */
- score = Curl_timediff(now, conn->lastused);
+ score = curlx_timediff(now, conn->lastused);
if(score > highscore) {
highscore = score;
oldest_idle = conn;
@@ -376,24 +376,33 @@ int Curl_cpool_check_limits(struct Curl_easy *data,
bundle = cpool_find_bundle(cpool, conn);
live = bundle ? Curl_llist_count(&bundle->conns) : 0;
- shutdowns = Curl_cshutdn_dest_count(data, conn->destination);
- while(!shutdowns && bundle && live >= dest_limit) {
- struct connectdata *oldest_idle = NULL;
- /* The bundle is full. Extract the oldest connection that may
- * be removed now, if there is one. */
- oldest_idle = cpool_bundle_get_oldest_idle(bundle);
- if(!oldest_idle)
+ shutdowns = Curl_cshutdn_dest_count(data, conn->destination);
+ while((live + shutdowns) >= dest_limit) {
+ if(shutdowns) {
+ /* close one connection in shutdown right away, if we can */
+ if(!Curl_cshutdn_close_oldest(data, conn->destination))
+ break;
+ }
+ else if(!bundle)
break;
- /* disconnect the old conn and continue */
- CURL_TRC_M(data, "Discarding connection #%"
- FMT_OFF_T " from %zu to reach destination "
- "limit of %zu", oldest_idle->connection_id,
- Curl_llist_count(&bundle->conns), dest_limit);
- Curl_conn_terminate(cpool->idata, oldest_idle, FALSE);
-
- /* in case the bundle was destroyed in disconnect, look it up again */
- bundle = cpool_find_bundle(cpool, conn);
- live = bundle ? Curl_llist_count(&bundle->conns) : 0;
+ else {
+ struct connectdata *oldest_idle = NULL;
+ /* The bundle is full. Extract the oldest connection that may
+ * be removed now, if there is one. */
+ oldest_idle = cpool_bundle_get_oldest_idle(bundle);
+ if(!oldest_idle)
+ break;
+ /* disconnect the old conn and continue */
+ CURL_TRC_M(data, "Discarding connection #%"
+ FMT_OFF_T " from %zu to reach destination "
+ "limit of %zu", oldest_idle->connection_id,
+ Curl_llist_count(&bundle->conns), dest_limit);
+ Curl_conn_terminate(cpool->idata, oldest_idle, FALSE);
+
+ /* in case the bundle was destroyed in disconnect, look it up again */
+ bundle = cpool_find_bundle(cpool, conn);
+ live = bundle ? Curl_llist_count(&bundle->conns) : 0;
+ }
shutdowns = Curl_cshutdn_dest_count(cpool->idata, conn->destination);
}
if((live + shutdowns) >= dest_limit) {
@@ -405,15 +414,22 @@ int Curl_cpool_check_limits(struct Curl_easy *data,
if(total_limit) {
shutdowns = Curl_cshutdn_count(cpool->idata);
while((cpool->num_conn + shutdowns) >= total_limit) {
- struct connectdata *oldest_idle = cpool_get_oldest_idle(cpool);
- if(!oldest_idle)
- break;
- /* disconnect the old conn and continue */
- CURL_TRC_M(data, "Discarding connection #%"
- FMT_OFF_T " from %zu to reach total "
- "limit of %zu",
- oldest_idle->connection_id, cpool->num_conn, total_limit);
- Curl_conn_terminate(cpool->idata, oldest_idle, FALSE);
+ if(shutdowns) {
+ /* close one connection in shutdown right away, if we can */
+ if(!Curl_cshutdn_close_oldest(data, NULL))
+ break;
+ }
+ else {
+ struct connectdata *oldest_idle = cpool_get_oldest_idle(cpool);
+ if(!oldest_idle)
+ break;
+ /* disconnect the old conn and continue */
+ CURL_TRC_M(data, "Discarding connection #%"
+ FMT_OFF_T " from %zu to reach total "
+ "limit of %zu",
+ oldest_idle->connection_id, cpool->num_conn, total_limit);
+ Curl_conn_terminate(cpool->idata, oldest_idle, FALSE);
+ }
shutdowns = Curl_cshutdn_count(cpool->idata);
}
if((cpool->num_conn + shutdowns) >= total_limit) {
@@ -518,12 +534,12 @@ bool Curl_cpool_conn_now_idle(struct Curl_easy *data,
struct connectdata *conn)
{
unsigned int maxconnects = !data->multi->maxconnects ?
- data->multi->num_easy * 4 : data->multi->maxconnects;
+ (Curl_multi_xfers_running(data->multi) * 4) : data->multi->maxconnects;
struct connectdata *oldest_idle = NULL;
struct cpool *cpool = cpool_get_instance(data);
bool kept = TRUE;
- conn->lastused = Curl_now(); /* it was used up until now */
+ conn->lastused = curlx_now(); /* it was used up until now */
if(cpool && maxconnects) {
/* may be called form a callback already under lock */
bool do_lock = !CPOOL_IS_LOCKED(cpool);
@@ -604,8 +620,8 @@ static void cpool_discard_conn(struct cpool *cpool,
*/
if(CONN_INUSE(conn) && !aborted) {
CURL_TRC_M(data, "[CPOOL] not discarding #%" FMT_OFF_T
- " still in use by %zu transfers", conn->connection_id,
- CONN_INUSE(conn));
+ " still in use by %u transfers", conn->connection_id,
+ CONN_ATTACHED(conn));
return;
}
@@ -649,7 +665,7 @@ void Curl_conn_terminate(struct Curl_easy *data,
* are other users of it */
if(CONN_INUSE(conn) && !aborted) {
DEBUGASSERT(0); /* does this ever happen? */
- DEBUGF(infof(data, "Curl_disconnect when inuse: %zu", CONN_INUSE(conn)));
+ DEBUGF(infof(data, "Curl_disconnect when inuse: %u", CONN_ATTACHED(conn)));
return;
}
@@ -718,9 +734,9 @@ void Curl_cpool_prune_dead(struct Curl_easy *data)
if(!cpool)
return;
- rctx.now = Curl_now();
+ rctx.now = curlx_now();
CPOOL_LOCK(cpool, data);
- elapsed = Curl_timediff(rctx.now, cpool->last_cleanup);
+ elapsed = curlx_timediff(rctx.now, cpool->last_cleanup);
if(elapsed >= 1000L) {
while(cpool_foreach(data, cpool, &rctx, cpool_reap_dead_cb))
@@ -742,7 +758,7 @@ static int conn_upkeep(struct Curl_easy *data,
CURLcode Curl_cpool_upkeep(void *data)
{
struct cpool *cpool = cpool_get_instance(data);
- struct curltime now = Curl_now();
+ struct curltime now = curlx_now();
if(!cpool)
return CURLE_OK;
diff --git a/libs/libcurl/src/conncache.h b/libs/libcurl/src/conncache.h
index e900e786fa..b97252fa4e 100644
--- a/libs/libcurl/src/conncache.h
+++ b/libs/libcurl/src/conncache.h
@@ -26,7 +26,7 @@
***************************************************************************/
#include <curl/curl.h>
-#include "timeval.h"
+#include "curlx/timeval.h"
struct connectdata;
struct Curl_easy;
@@ -62,12 +62,12 @@ struct cpool {
};
/* Init the pool, pass multi only if pool is owned by it.
- * returns 1 on error, 0 is fine.
+ * Cannot fail.
*/
-int Curl_cpool_init(struct cpool *cpool,
- struct Curl_easy *idata,
- struct Curl_share *share,
- size_t size);
+void Curl_cpool_init(struct cpool *cpool,
+ struct Curl_easy *idata,
+ struct Curl_share *share,
+ size_t size);
/* Destroy all connections and free all members */
void Curl_cpool_destroy(struct cpool *connc);
diff --git a/libs/libcurl/src/connect.c b/libs/libcurl/src/connect.c
index c909d6b544..cbc31a2bc3 100644
--- a/libs/libcurl/src/connect.c
+++ b/libs/libcurl/src/connect.c
@@ -67,14 +67,14 @@
#include "multiif.h"
#include "sockaddr.h" /* required for Curl_sockaddr_storage */
#include "inet_ntop.h"
-#include "inet_pton.h"
+#include "curlx/inet_pton.h"
#include "vtls/vtls.h" /* for vtsl cfilters */
#include "progress.h"
-#include "warnless.h"
+#include "curlx/warnless.h"
#include "conncache.h"
#include "multihandle.h"
#include "share.h"
-#include "version_win32.h"
+#include "curlx/version_win32.h"
#include "vquic/vquic.h" /* for quic cfilters */
#include "http_proxy.h"
#include "socks.h"
@@ -112,7 +112,7 @@ enum alpnid Curl_alpn2alpnid(const char *name, size_t len)
* infinite time left). If the value is negative, the timeout time has already
* elapsed.
* @param data the transfer to check on
- * @param nowp timestamp to use for calculation, NULL to use Curl_now()
+ * @param nowp timestamp to use for calculation, NULL to use curlx_now()
* @param duringconnect TRUE iff connect timeout is also taken into account.
* @unittest: 1303
*/
@@ -133,13 +133,13 @@ timediff_t Curl_timeleft(struct Curl_easy *data,
return 0; /* no timeout in place or checked, return "no limit" */
if(!nowp) {
- now = Curl_now();
+ now = curlx_now();
nowp = &now;
}
if(data->set.timeout > 0) {
timeleft_ms = data->set.timeout -
- Curl_timediff(*nowp, data->progress.t_startop);
+ curlx_timediff(*nowp, data->progress.t_startop);
if(!timeleft_ms)
timeleft_ms = -1; /* 0 is "no limit", fake 1 ms expiry */
if(!duringconnect)
@@ -150,7 +150,7 @@ timediff_t Curl_timeleft(struct Curl_easy *data,
timediff_t ctimeout_ms = (data->set.connecttimeout > 0) ?
data->set.connecttimeout : DEFAULT_CONNECT_TIMEOUT;
ctimeleft_ms = ctimeout_ms -
- Curl_timediff(*nowp, data->progress.t_startsingle);
+ curlx_timediff(*nowp, data->progress.t_startsingle);
if(!ctimeleft_ms)
ctimeleft_ms = -1; /* 0 is "no limit", fake 1 ms expiry */
if(!timeleft_ms)
@@ -167,15 +167,16 @@ void Curl_shutdown_start(struct Curl_easy *data, int sockindex,
DEBUGASSERT(data->conn);
if(!nowp) {
- now = Curl_now();
+ now = curlx_now();
nowp = &now;
}
data->conn->shutdown.start[sockindex] = *nowp;
- data->conn->shutdown.timeout_ms = (timeout_ms >= 0) ?
+ data->conn->shutdown.timeout_ms = (timeout_ms > 0) ?
(unsigned int)timeout_ms :
((data->set.shutdowntimeout > 0) ?
data->set.shutdowntimeout : DEFAULT_SHUTDOWN_TIMEOUT_MS);
- if(data->conn->shutdown.timeout_ms)
+ /* Set a timer, unless we operate on the admin handle */
+ if(data->mid && data->conn->shutdown.timeout_ms)
Curl_expire_ex(data, nowp, data->conn->shutdown.timeout_ms,
EXPIRE_SHUTDOWN);
}
@@ -190,11 +191,11 @@ timediff_t Curl_shutdown_timeleft(struct connectdata *conn, int sockindex,
return 0; /* not started or no limits */
if(!nowp) {
- now = Curl_now();
+ now = curlx_now();
nowp = &now;
}
left_ms = conn->shutdown.timeout_ms -
- Curl_timediff(*nowp, conn->shutdown.start[sockindex]);
+ curlx_timediff(*nowp, conn->shutdown.start[sockindex]);
return left_ms ? left_ms : -1;
}
@@ -209,7 +210,7 @@ timediff_t Curl_conn_shutdown_timeleft(struct connectdata *conn,
if(!conn->shutdown.start[i].tv_sec)
continue;
if(!nowp) {
- now = Curl_now();
+ now = curlx_now();
nowp = &now;
}
ms = Curl_shutdown_timeleft(conn, i, nowp);
@@ -254,7 +255,7 @@ addr_next_match(const struct Curl_addrinfo *addr, int family)
}
/* retrieves ip address and port from a sockaddr structure.
- note it calls curlx_inet_ntop which sets errno on fail, not SOCKERRNO. */
+ note it calls Curl_inet_ntop which sets errno on fail, not SOCKERRNO. */
bool Curl_addr2string(struct sockaddr *sa, curl_socklen_t salen,
char *addr, int *port)
{
@@ -271,8 +272,7 @@ bool Curl_addr2string(struct sockaddr *sa, curl_socklen_t salen,
switch(sa->sa_family) {
case AF_INET:
si = (struct sockaddr_in *)(void *) sa;
- if(curlx_inet_ntop(sa->sa_family, &si->sin_addr,
- addr, MAX_IPADR_LEN)) {
+ if(Curl_inet_ntop(sa->sa_family, &si->sin_addr, addr, MAX_IPADR_LEN)) {
unsigned short us_port = ntohs(si->sin_port);
*port = us_port;
return TRUE;
@@ -281,8 +281,7 @@ bool Curl_addr2string(struct sockaddr *sa, curl_socklen_t salen,
#ifdef USE_IPV6
case AF_INET6:
si6 = (struct sockaddr_in6 *)(void *) sa;
- if(curlx_inet_ntop(sa->sa_family, &si6->sin6_addr,
- addr, MAX_IPADR_LEN)) {
+ if(Curl_inet_ntop(sa->sa_family, &si6->sin6_addr, addr, MAX_IPADR_LEN)) {
unsigned short us_port = ntohs(si6->sin6_port);
*port = us_port;
return TRUE;
@@ -409,7 +408,6 @@ typedef enum {
struct cf_he_ctx {
int transport;
cf_ip_connect_create *cf_create;
- const struct Curl_dns_entry *remotehost;
cf_connect_state state;
struct eyeballer *baller[2];
struct eyeballer *winner;
@@ -546,7 +544,7 @@ static CURLcode baller_start(struct Curl_cfilter *cf,
baller->has_started = TRUE;
while(baller->addr) {
- baller->started = Curl_now();
+ baller->started = curlx_now();
baller->timeoutms = addr_next_match(baller->addr, baller->ai_family) ?
USETIME(timeoutms) : timeoutms;
baller_initiate(cf, data, baller);
@@ -605,7 +603,7 @@ static CURLcode baller_connect(struct Curl_cfilter *cf,
baller->connected = TRUE;
baller->is_done = TRUE;
}
- else if(Curl_timediff(*now, baller->started) >= baller->timeoutms) {
+ else if(curlx_timediff(*now, baller->started) >= baller->timeoutms) {
infof(data, "%s connect timeout after %" FMT_TIMEDIFF_T
"ms, move on!", baller->name, baller->timeoutms);
#ifdef SOCKETIMEDOUT
@@ -643,7 +641,7 @@ static CURLcode is_connected(struct Curl_cfilter *cf,
* cot ballers in a QUIC appropriate way. */
evaluate:
*connected = FALSE; /* a negative world view is best */
- now = Curl_now();
+ now = curlx_now();
ongoing = not_started = 0;
for(i = 0; i < CURL_ARRAYSIZE(ctx->baller); i++) {
struct eyeballer *baller = ctx->baller[i];
@@ -698,7 +696,7 @@ evaluate:
* start new ballers or return ok. */
if((ongoing || not_started) && Curl_timeleft(data, &now, TRUE) < 0) {
failf(data, "Connection timeout after %" FMT_OFF_T " ms",
- Curl_timediff(now, data->progress.t_startsingle));
+ curlx_timediff(now, data->progress.t_startsingle));
return CURLE_OPERATION_TIMEDOUT;
}
@@ -714,7 +712,7 @@ evaluate:
/* We start its primary baller has failed to connect or if
* its start delay_ms have expired */
if((baller->primary && baller->primary->is_done) ||
- Curl_timediff(now, ctx->started) >= baller->delay_ms) {
+ curlx_timediff(now, ctx->started) >= baller->delay_ms) {
baller_start(cf, data, baller, Curl_timeleft(data, &now, TRUE));
if(baller->is_done) {
CURL_TRC_CF(data, cf, "%s done", baller->name);
@@ -767,7 +765,7 @@ evaluate:
failf(data, "Failed to connect to %s port %u after "
"%" FMT_TIMEDIFF_T " ms: %s",
hostname, conn->primary.remote_port,
- Curl_timediff(now, data->progress.t_startsingle),
+ curlx_timediff(now, data->progress.t_startsingle),
curl_easy_strerror(result));
#ifdef SOCKETIMEDOUT
@@ -783,8 +781,7 @@ evaluate:
* There might be more than one IP address to try out.
*/
static CURLcode start_connect(struct Curl_cfilter *cf,
- struct Curl_easy *data,
- const struct Curl_dns_entry *remotehost)
+ struct Curl_easy *data)
{
struct cf_he_ctx *ctx = cf->ctx;
struct connectdata *conn = cf->conn;
@@ -792,6 +789,10 @@ static CURLcode start_connect(struct Curl_cfilter *cf,
int ai_family0 = 0, ai_family1 = 0;
timediff_t timeout_ms = Curl_timeleft(data, NULL, TRUE);
const struct Curl_addrinfo *addr0 = NULL, *addr1 = NULL;
+ struct Curl_dns_entry *dns = data->state.dns[cf->sockindex];
+
+ if(!dns)
+ return CURLE_FAILED_INIT;
if(timeout_ms < 0) {
/* a precaution, no need to continue if time already is up */
@@ -799,9 +800,9 @@ static CURLcode start_connect(struct Curl_cfilter *cf,
return CURLE_OPERATION_TIMEDOUT;
}
- ctx->started = Curl_now();
+ ctx->started = curlx_now();
- /* remotehost->addr is the list of addresses from the resolver, each
+ /* dns->addr is the list of addresses from the resolver, each
* with an address family. The list has at least one entry, possibly
* many more.
* We try at most 2 at a time, until we either get a connection or
@@ -813,27 +814,27 @@ static CURLcode start_connect(struct Curl_cfilter *cf,
if(conn->ip_version == CURL_IPRESOLVE_V6) {
#ifdef USE_IPV6
ai_family0 = AF_INET6;
- addr0 = addr_first_match(remotehost->addr, ai_family0);
+ addr0 = addr_first_match(dns->addr, ai_family0);
#endif
}
else if(conn->ip_version == CURL_IPRESOLVE_V4) {
ai_family0 = AF_INET;
- addr0 = addr_first_match(remotehost->addr, ai_family0);
+ addr0 = addr_first_match(dns->addr, ai_family0);
}
else {
/* no user preference, we try ipv6 always first when available */
#ifdef USE_IPV6
ai_family0 = AF_INET6;
- addr0 = addr_first_match(remotehost->addr, ai_family0);
+ addr0 = addr_first_match(dns->addr, ai_family0);
#endif
/* next candidate is ipv4 */
ai_family1 = AF_INET;
- addr1 = addr_first_match(remotehost->addr, ai_family1);
+ addr1 = addr_first_match(dns->addr, ai_family1);
/* no ip address families, probably AF_UNIX or something, use the
* address family given to us */
- if(!addr1 && !addr0 && remotehost->addr) {
- ai_family0 = remotehost->addr->ai_family;
- addr0 = addr_first_match(remotehost->addr, ai_family0);
+ if(!addr1 && !addr0 && dns->addr) {
+ ai_family0 = dns->addr->ai_family;
+ addr0 = addr_first_match(dns->addr, ai_family0);
}
}
@@ -967,7 +968,7 @@ static CURLcode cf_he_connect(struct Curl_cfilter *cf,
case SCFST_INIT:
DEBUGASSERT(CURL_SOCKET_BAD == Curl_conn_cf_get_socket(cf, data));
DEBUGASSERT(!cf->connected);
- result = start_connect(cf, data, ctx->remotehost);
+ result = start_connect(cf, data);
if(result)
return result;
ctx->state = SCFST_WAITING;
@@ -1059,7 +1060,7 @@ static struct curltime get_max_baller_time(struct Curl_cfilter *cf,
memset(&t, 0, sizeof(t));
if(baller && baller->cf &&
!baller->cf->cft->query(baller->cf, data, query, NULL, &t)) {
- if((t.tv_sec || t.tv_usec) && Curl_timediff_us(t, tmax) > 0)
+ if((t.tv_sec || t.tv_usec) && curlx_timediff_us(t, tmax) > 0)
tmax = t;
}
}
@@ -1159,7 +1160,6 @@ cf_happy_eyeballs_create(struct Curl_cfilter **pcf,
struct Curl_easy *data,
struct connectdata *conn,
cf_ip_connect_create *cf_create,
- const struct Curl_dns_entry *remotehost,
int transport)
{
struct cf_he_ctx *ctx = NULL;
@@ -1175,14 +1175,13 @@ cf_happy_eyeballs_create(struct Curl_cfilter **pcf,
}
ctx->transport = transport;
ctx->cf_create = cf_create;
- ctx->remotehost = remotehost;
result = Curl_cf_create(pcf, &Curl_cft_happy_eyeballs, ctx);
out:
if(result) {
Curl_safefree(*pcf);
- Curl_safefree(ctx);
+ free(ctx);
}
return result;
}
@@ -1221,7 +1220,6 @@ static cf_ip_connect_create *get_cf_create(int transport)
static CURLcode cf_he_insert_after(struct Curl_cfilter *cf_at,
struct Curl_easy *data,
- const struct Curl_dns_entry *remotehost,
int transport)
{
cf_ip_connect_create *cf_create;
@@ -1236,8 +1234,7 @@ static CURLcode cf_he_insert_after(struct Curl_cfilter *cf_at,
return CURLE_UNSUPPORTED_PROTOCOL;
}
result = cf_happy_eyeballs_create(&cf, data, cf_at->conn,
- cf_create, remotehost,
- transport);
+ cf_create, transport);
if(result)
return result;
@@ -1257,7 +1254,6 @@ typedef enum {
struct cf_setup_ctx {
cf_setup_state state;
- const struct Curl_dns_entry *remotehost;
int ssl_mode;
int transport;
};
@@ -1268,6 +1264,7 @@ static CURLcode cf_setup_connect(struct Curl_cfilter *cf,
{
struct cf_setup_ctx *ctx = cf->ctx;
CURLcode result = CURLE_OK;
+ struct Curl_dns_entry *dns = data->state.dns[cf->sockindex];
if(cf->connected) {
*done = TRUE;
@@ -1276,6 +1273,9 @@ static CURLcode cf_setup_connect(struct Curl_cfilter *cf,
/* connect current sub-chain */
connect_sub_chain:
+ if(!dns)
+ return CURLE_FAILED_INIT;
+
if(cf->next && !cf->next->connected) {
result = Curl_conn_cf_connect(cf->next, data, done);
if(result || !*done)
@@ -1283,7 +1283,7 @@ connect_sub_chain:
}
if(ctx->state < CF_SETUP_CNNCT_EYEBALLS) {
- result = cf_he_insert_after(cf, data, ctx->remotehost, ctx->transport);
+ result = cf_he_insert_after(cf, data, ctx->transport);
if(result)
return result;
ctx->state = CF_SETUP_CNNCT_EYEBALLS;
@@ -1411,7 +1411,6 @@ struct Curl_cftype Curl_cft_setup = {
static CURLcode cf_setup_create(struct Curl_cfilter **pcf,
struct Curl_easy *data,
- const struct Curl_dns_entry *remotehost,
int transport,
int ssl_mode)
{
@@ -1426,7 +1425,6 @@ static CURLcode cf_setup_create(struct Curl_cfilter **pcf,
goto out;
}
ctx->state = CF_SETUP_INIT;
- ctx->remotehost = remotehost;
ctx->ssl_mode = ssl_mode;
ctx->transport = transport;
@@ -1437,14 +1435,15 @@ static CURLcode cf_setup_create(struct Curl_cfilter **pcf,
out:
*pcf = result ? NULL : cf;
- free(ctx);
+ if(ctx) {
+ free(ctx);
+ }
return result;
}
static CURLcode cf_setup_add(struct Curl_easy *data,
struct connectdata *conn,
int sockindex,
- const struct Curl_dns_entry *remotehost,
int transport,
int ssl_mode)
{
@@ -1452,7 +1451,7 @@ static CURLcode cf_setup_add(struct Curl_easy *data,
CURLcode result = CURLE_OK;
DEBUGASSERT(data);
- result = cf_setup_create(&cf, data, remotehost, transport, ssl_mode);
+ result = cf_setup_create(&cf, data, transport, ssl_mode);
if(result)
goto out;
Curl_conn_cf_add(data, conn, sockindex, cf);
@@ -1477,7 +1476,6 @@ void Curl_debug_set_transport_provider(int transport,
CURLcode Curl_cf_setup_insert_after(struct Curl_cfilter *cf_at,
struct Curl_easy *data,
- const struct Curl_dns_entry *remotehost,
int transport,
int ssl_mode)
{
@@ -1485,7 +1483,7 @@ CURLcode Curl_cf_setup_insert_after(struct Curl_cfilter *cf_at,
CURLcode result;
DEBUGASSERT(data);
- result = cf_setup_create(&cf, data, remotehost, transport, ssl_mode);
+ result = cf_setup_create(&cf, data, transport, ssl_mode);
if(result)
goto out;
Curl_conn_cf_insert_after(cf_at, cf);
@@ -1496,19 +1494,23 @@ out:
CURLcode Curl_conn_setup(struct Curl_easy *data,
struct connectdata *conn,
int sockindex,
- const struct Curl_dns_entry *remotehost,
+ struct Curl_dns_entry *dns,
int ssl_mode)
{
CURLcode result = CURLE_OK;
DEBUGASSERT(data);
DEBUGASSERT(conn->handler);
+ DEBUGASSERT(dns);
+
+ Curl_resolv_unlink(data, &data->state.dns[sockindex]);
+ data->state.dns[sockindex] = dns;
#if !defined(CURL_DISABLE_HTTP)
if(!conn->cfilter[sockindex] &&
conn->handler->protocol == CURLPROTO_HTTPS) {
DEBUGASSERT(ssl_mode != CURL_CF_SSL_DISABLE);
- result = Curl_cf_https_setup(data, conn, sockindex, remotehost);
+ result = Curl_cf_https_setup(data, conn, sockindex);
if(result)
goto out;
}
@@ -1516,13 +1518,14 @@ CURLcode Curl_conn_setup(struct Curl_easy *data,
/* Still no cfilter set, apply default. */
if(!conn->cfilter[sockindex]) {
- result = cf_setup_add(data, conn, sockindex, remotehost,
- conn->transport, ssl_mode);
+ result = cf_setup_add(data, conn, sockindex, conn->transport, ssl_mode);
if(result)
goto out;
}
DEBUGASSERT(conn->cfilter[sockindex]);
out:
+ if(result)
+ Curl_resolv_unlink(data, &data->state.dns[sockindex]);
return result;
}
diff --git a/libs/libcurl/src/connect.h b/libs/libcurl/src/connect.h
index 3077178d8c..d44fb6b4f6 100644
--- a/libs/libcurl/src/connect.h
+++ b/libs/libcurl/src/connect.h
@@ -25,9 +25,9 @@
***************************************************************************/
#include "curl_setup.h"
-#include "nonblock.h" /* for curlx_nonblock(), formerly Curl_nonblock() */
+#include "curlx/nonblock.h" /* for curlx_nonblock() */
#include "sockaddr.h"
-#include "timeval.h"
+#include "curlx/timeval.h"
struct Curl_dns_entry;
struct ip_quadruple;
@@ -126,7 +126,6 @@ typedef CURLcode cf_ip_connect_create(struct Curl_cfilter **pcf,
CURLcode Curl_cf_setup_insert_after(struct Curl_cfilter *cf_at,
struct Curl_easy *data,
- const struct Curl_dns_entry *remotehost,
int transport,
int ssl_mode);
@@ -138,7 +137,7 @@ CURLcode Curl_cf_setup_insert_after(struct Curl_cfilter *cf_at,
CURLcode Curl_conn_setup(struct Curl_easy *data,
struct connectdata *conn,
int sockindex,
- const struct Curl_dns_entry *remotehost,
+ struct Curl_dns_entry *dns,
int ssl_mode);
extern struct Curl_cftype Curl_cft_happy_eyeballs;
diff --git a/libs/libcurl/src/content_encoding.c b/libs/libcurl/src/content_encoding.c
index b185890df9..f553f3c0fb 100644
--- a/libs/libcurl/src/content_encoding.c
+++ b/libs/libcurl/src/content_encoding.c
@@ -737,6 +737,7 @@ CURLcode Curl_build_unencoding_stack(struct Curl_easy *data,
Curl_cwriter_phase phase = is_transfer ?
CURL_CW_TRANSFER_DECODE : CURL_CW_CONTENT_DECODE;
CURLcode result;
+ bool has_chunked = FALSE;
do {
const char *name;
@@ -765,9 +766,21 @@ CURLcode Curl_build_unencoding_stack(struct Curl_easy *data,
* Exception is "chunked" transfer-encoding which always must happen */
if((is_transfer && !data->set.http_transfer_encoding && !is_chunked) ||
(!is_transfer && data->set.http_ce_skip)) {
+ bool is_identity = strncasecompare(name, "identity", 8);
/* not requested, ignore */
CURL_TRC_WRITE(data, "decoder not requested, ignored: %.*s",
(int)namelen, name);
+ if(is_transfer && !data->set.http_te_skip) {
+ if(has_chunked)
+ failf(data, "A Transfer-Encoding (%.*s) was listed after chunked",
+ (int)namelen, name);
+ else if(is_identity)
+ continue;
+ else
+ failf(data, "Unsolicited Transfer-Encoding (%.*s) found",
+ (int)namelen, name);
+ return CURLE_BAD_CONTENT_ENCODING;
+ }
return CURLE_OK;
}
@@ -818,6 +831,8 @@ CURLcode Curl_build_unencoding_stack(struct Curl_easy *data,
Curl_cwriter_free(data, writer);
return result;
}
+ if(is_chunked)
+ has_chunked = TRUE;
}
} while(*enclist);
diff --git a/libs/libcurl/src/cookie.c b/libs/libcurl/src/cookie.c
index 455d3962b1..0b80ad8f0c 100644
--- a/libs/libcurl/src/cookie.c
+++ b/libs/libcurl/src/cookie.c
@@ -87,7 +87,7 @@ Example set of cookies:
#include "fopen.h"
#include "strdup.h"
#include "llist.h"
-#include "strparse.h"
+#include "curlx/strparse.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
@@ -497,25 +497,25 @@ parse_cookie_header(struct Curl_easy *data,
struct Curl_str val;
/* we have a <name>=<value> pair or a stand-alone word here */
- if(!Curl_str_cspn(&ptr, &name, ";\t\r\n=")) {
+ if(!curlx_str_cspn(&ptr, &name, ";\t\r\n=")) {
bool done = FALSE;
bool sep = FALSE;
- Curl_str_trimblanks(&name);
+ curlx_str_trimblanks(&name);
- if(!Curl_str_single(&ptr, '=')) {
+ if(!curlx_str_single(&ptr, '=')) {
sep = TRUE; /* a '=' was used */
- if(!Curl_str_cspn(&ptr, &val, ";\r\n")) {
- Curl_str_trimblanks(&val);
+ if(!curlx_str_cspn(&ptr, &val, ";\r\n")) {
+ curlx_str_trimblanks(&val);
/* Reject cookies with a TAB inside the value */
- if(memchr(Curl_str(&val), '\t', Curl_strlen(&val))) {
+ if(memchr(curlx_str(&val), '\t', curlx_strlen(&val))) {
infof(data, "cookie contains TAB, dropping");
return CERR_TAB;
}
}
}
else {
- Curl_str_init(&val);
+ curlx_str_init(&val);
}
/*
@@ -523,11 +523,11 @@ parse_cookie_header(struct Curl_easy *data,
* combination of name + contents. Chrome and Firefox support 4095 or
* 4096 bytes combo
*/
- if(Curl_strlen(&name) >= (MAX_NAME-1) ||
- Curl_strlen(&val) >= (MAX_NAME-1) ||
- ((Curl_strlen(&name) + Curl_strlen(&val)) > MAX_NAME)) {
+ if(curlx_strlen(&name) >= (MAX_NAME-1) ||
+ curlx_strlen(&val) >= (MAX_NAME-1) ||
+ ((curlx_strlen(&name) + curlx_strlen(&val)) > MAX_NAME)) {
infof(data, "oversized cookie dropped, name/val %zu + %zu bytes",
- Curl_strlen(&name), Curl_strlen(&val));
+ curlx_strlen(&name), curlx_strlen(&val));
return CERR_TOO_BIG;
}
@@ -537,9 +537,9 @@ parse_cookie_header(struct Curl_easy *data,
* "the rest". Prefixes must start with '__' and end with a '-', so
* only test for names where that can possibly be true.
*/
- if(!strncmp("__Secure-", Curl_str(&name), 9))
+ if(!strncmp("__Secure-", curlx_str(&name), 9))
co->prefix_secure = TRUE;
- else if(!strncmp("__Host-", Curl_str(&name), 7))
+ else if(!strncmp("__Host-", curlx_str(&name), 7))
co->prefix_host = TRUE;
/*
@@ -554,8 +554,8 @@ parse_cookie_header(struct Curl_easy *data,
/* Bad name/value pair. */
return CERR_NO_SEP;
- strstore(&co->name, Curl_str(&name), Curl_strlen(&name));
- strstore(&co->value, Curl_str(&val), Curl_strlen(&val));
+ strstore(&co->name, curlx_str(&name), curlx_strlen(&name));
+ strstore(&co->value, curlx_str(&val), curlx_strlen(&val));
done = TRUE;
if(!co->name || !co->value)
return CERR_NO_NAME_VALUE;
@@ -565,7 +565,7 @@ parse_cookie_header(struct Curl_easy *data,
return CERR_INVALID_OCTET;
}
}
- else if(!Curl_strlen(&val)) {
+ else if(!curlx_strlen(&val)) {
/*
* this was a "<name>=" with no content, and we must allow
* 'secure' and 'httponly' specified this weirdly
@@ -576,7 +576,7 @@ parse_cookie_header(struct Curl_easy *data,
* using a secure protocol, or when the cookie is being set by
* reading from file
*/
- if(Curl_str_casecompare(&name, "secure")) {
+ if(curlx_str_casecompare(&name, "secure")) {
if(secure || !ci->running) {
co->secure = TRUE;
}
@@ -584,7 +584,7 @@ parse_cookie_header(struct Curl_easy *data,
return CERR_BAD_SECURE;
}
}
- else if(Curl_str_casecompare(&name, "httponly"))
+ else if(curlx_str_casecompare(&name, "httponly"))
co->httponly = TRUE;
else if(sep)
/* there was a '=' so we are not done parsing this field */
@@ -592,8 +592,8 @@ parse_cookie_header(struct Curl_easy *data,
}
if(done)
;
- else if(Curl_str_casecompare(&name, "path")) {
- strstore(&co->path, Curl_str(&val), Curl_strlen(&val));
+ else if(curlx_str_casecompare(&name, "path")) {
+ strstore(&co->path, curlx_str(&val), curlx_strlen(&val));
if(!co->path)
return CERR_OUT_OF_MEMORY;
free(co->spath); /* if this is set again */
@@ -601,16 +601,16 @@ parse_cookie_header(struct Curl_easy *data,
if(!co->spath)
return CERR_OUT_OF_MEMORY;
}
- else if(Curl_str_casecompare(&name, "domain") && Curl_strlen(&val)) {
+ else if(curlx_str_casecompare(&name, "domain") && curlx_strlen(&val)) {
bool is_ip;
- const char *v = Curl_str(&val);
+ const char *v = curlx_str(&val);
/*
* Now, we make sure that our host is within the given domain, or
* the given domain is not valid and thus cannot be set.
*/
if('.' == *v)
- Curl_str_nudge(&val, 1);
+ curlx_str_nudge(&val, 1);
#ifndef USE_LIBPSL
/*
@@ -618,18 +618,19 @@ parse_cookie_header(struct Curl_easy *data,
* TLD or otherwise "protected" suffix. To reduce risk, we require a
* dot OR the exact hostname being "localhost".
*/
- if(bad_domain(Curl_str(&val), Curl_strlen(&val)))
+ if(bad_domain(curlx_str(&val), curlx_strlen(&val)))
domain = ":";
#endif
- is_ip = Curl_host_is_ipnum(domain ? domain : Curl_str(&val));
+ is_ip = Curl_host_is_ipnum(domain ? domain : curlx_str(&val));
if(!domain
- || (is_ip && !strncmp(Curl_str(&val), domain, Curl_strlen(&val)) &&
- (Curl_strlen(&val) == strlen(domain)))
- || (!is_ip && cookie_tailmatch(Curl_str(&val),
- Curl_strlen(&val), domain))) {
- strstore(&co->domain, Curl_str(&val), Curl_strlen(&val));
+ || (is_ip && !strncmp(curlx_str(&val), domain,
+ curlx_strlen(&val)) &&
+ (curlx_strlen(&val) == strlen(domain)))
+ || (!is_ip && cookie_tailmatch(curlx_str(&val),
+ curlx_strlen(&val), domain))) {
+ strstore(&co->domain, curlx_str(&val), curlx_strlen(&val));
if(!co->domain)
return CERR_OUT_OF_MEMORY;
@@ -643,14 +644,14 @@ parse_cookie_header(struct Curl_easy *data,
* not a domain to which the current host belongs. Mark as bad.
*/
infof(data, "skipped cookie with bad tailmatch domain: %s",
- Curl_str(&val));
+ curlx_str(&val));
return CERR_NO_TAILMATCH;
}
}
- else if(Curl_str_casecompare(&name, "version")) {
+ else if(curlx_str_casecompare(&name, "version")) {
/* just ignore */
}
- else if(Curl_str_casecompare(&name, "max-age") && Curl_strlen(&val)) {
+ else if(curlx_str_casecompare(&name, "max-age") && curlx_strlen(&val)) {
/*
* Defined in RFC2109:
*
@@ -661,10 +662,10 @@ parse_cookie_header(struct Curl_easy *data,
* cookie should be discarded immediately.
*/
int rc;
- const char *maxage = Curl_str(&val);
+ const char *maxage = curlx_str(&val);
if(*maxage == '\"')
maxage++;
- rc = Curl_str_number(&maxage, &co->expires, CURL_OFF_T_MAX);
+ rc = curlx_str_number(&maxage, &co->expires, CURL_OFF_T_MAX);
switch(rc) {
case STRE_OVERFLOW:
@@ -688,8 +689,8 @@ parse_cookie_header(struct Curl_easy *data,
}
cap_expires(now, co);
}
- else if(Curl_str_casecompare(&name, "expires") && Curl_strlen(&val)) {
- if(!co->expires && (Curl_strlen(&val) < MAX_DATE_LENGTH)) {
+ else if(curlx_str_casecompare(&name, "expires") && curlx_strlen(&val)) {
+ if(!co->expires && (curlx_strlen(&val) < MAX_DATE_LENGTH)) {
/*
* Let max-age have priority.
*
@@ -697,8 +698,8 @@ parse_cookie_header(struct Curl_easy *data,
* will be treated as a session cookie
*/
char dbuf[MAX_DATE_LENGTH + 1];
- memcpy(dbuf, Curl_str(&val), Curl_strlen(&val));
- dbuf[Curl_strlen(&val)] = 0;
+ memcpy(dbuf, curlx_str(&val), curlx_strlen(&val));
+ dbuf[curlx_strlen(&val)] = 0;
co->expires = Curl_getdate_capped(dbuf);
/*
@@ -719,7 +720,7 @@ parse_cookie_header(struct Curl_easy *data,
*/
}
- if(Curl_str_single(&ptr, ';'))
+ if(curlx_str_single(&ptr, ';'))
break;
} while(1);
@@ -849,7 +850,7 @@ parse_netscape(struct Cookie *co,
}
break;
case 4:
- if(Curl_str_number(&ptr, &co->expires, CURL_OFF_T_MAX))
+ if(curlx_str_number(&ptr, &co->expires, CURL_OFF_T_MAX))
return CERR_RANGE;
break;
case 5:
@@ -1209,20 +1210,20 @@ struct CookieInfo *Curl_cookie_init(struct Curl_easy *data,
ci->running = FALSE; /* this is not running, this is init */
if(fp) {
struct dynbuf buf;
- Curl_dyn_init(&buf, MAX_COOKIE_LINE);
+ curlx_dyn_init(&buf, MAX_COOKIE_LINE);
while(Curl_get_line(&buf, fp)) {
- const char *lineptr = Curl_dyn_ptr(&buf);
+ const char *lineptr = curlx_dyn_ptr(&buf);
bool headerline = FALSE;
if(checkprefix("Set-Cookie:", lineptr)) {
/* This is a cookie line, get it! */
lineptr += 11;
headerline = TRUE;
- Curl_str_passblanks(&lineptr);
+ curlx_str_passblanks(&lineptr);
}
Curl_cookie_add(data, ci, headerline, TRUE, lineptr, NULL, NULL, TRUE);
}
- Curl_dyn_free(&buf); /* free the line buffer */
+ curlx_dyn_free(&buf); /* free the line buffer */
/*
* Remove expired cookies from the hash. We must make sure to run this
diff --git a/libs/libcurl/src/cshutdn.c b/libs/libcurl/src/cshutdn.c
index fb6e34410b..f6e52267ad 100644
--- a/libs/libcurl/src/cshutdn.c
+++ b/libs/libcurl/src/cshutdn.c
@@ -41,7 +41,7 @@
#include "connect.h"
#include "select.h"
#include "strcase.h"
-#include "strparse.h"
+#include "curlx/strparse.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
@@ -53,8 +53,6 @@ static void cshutdn_run_conn_handler(struct Curl_easy *data,
struct connectdata *conn)
{
if(!conn->bits.shutdown_handler) {
- if(conn->dns_entry)
- Curl_resolv_unlink(data, &conn->dns_entry);
/* Cleanup NTLM connection-related data */
Curl_http_auth_cleanup_ntlm(conn);
@@ -81,9 +79,6 @@ static void cshutdn_run_conn_handler(struct Curl_easy *data,
conn->handler->disconnect(data, conn, conn->bits.aborted);
}
- /* possible left-overs from the async name resolvers */
- Curl_resolver_cancel(data);
-
conn->bits.shutdown_handler = TRUE;
}
}
@@ -166,7 +161,9 @@ void Curl_cshutdn_terminate(struct Curl_easy *data,
* not done so already. */
cshutdn_run_once(admin, conn, &done);
}
- CURL_TRC_M(admin, "[SHUTDOWN] closing connection");
+ CURL_TRC_M(admin, "[SHUTDOWN] %sclosing connection #%" FMT_OFF_T,
+ conn->bits.shutdown_filters ? "" : "force ",
+ conn->connection_id);
Curl_conn_close(admin, SECONDARYSOCKET);
Curl_conn_close(admin, FIRSTSOCKET);
Curl_detach_connection(admin);
@@ -181,13 +178,21 @@ void Curl_cshutdn_terminate(struct Curl_easy *data,
}
}
-static void cshutdn_destroy_oldest(struct cshutdn *cshutdn,
- struct Curl_easy *data)
+static bool cshutdn_destroy_oldest(struct cshutdn *cshutdn,
+ struct Curl_easy *data,
+ const char *destination)
{
struct Curl_llist_node *e;
struct connectdata *conn;
e = Curl_llist_head(&cshutdn->list);
+ while(e) {
+ conn = Curl_node_elem(e);
+ if(!destination || !strcmp(destination, conn->destination))
+ break;
+ e = Curl_node_next(e);
+ }
+
if(e) {
SIGPIPE_VARIABLE(pipe_st);
conn = Curl_node_elem(e);
@@ -196,7 +201,19 @@ static void cshutdn_destroy_oldest(struct cshutdn *cshutdn,
sigpipe_apply(data, &pipe_st);
Curl_cshutdn_terminate(data, conn, FALSE);
sigpipe_restore(&pipe_st);
+ return TRUE;
}
+ return FALSE;
+}
+
+bool Curl_cshutdn_close_oldest(struct Curl_easy *data,
+ const char *destination)
+{
+ if(data && data->multi) {
+ struct cshutdn *csd = &data->multi->cshutdn;
+ return cshutdn_destroy_oldest(csd, data, destination);
+ }
+ return FALSE;
}
#define NUM_POLLS_ON_STACK 10
@@ -251,7 +268,7 @@ static void cshutdn_perform(struct cshutdn *cshutdn,
/* idata has one timer list, but maybe more than one connection.
* Set EXPIRE_SHUTDOWN to the smallest time left for all. */
if(!nowp) {
- now = Curl_now();
+ now = curlx_now();
nowp = &now;
}
ms = Curl_conn_shutdown_timeleft(conn, nowp);
@@ -270,7 +287,7 @@ static void cshutdn_terminate_all(struct cshutdn *cshutdn,
struct Curl_easy *data,
int timeout_ms)
{
- struct curltime started = Curl_now();
+ struct curltime started = curlx_now();
struct Curl_llist_node *e;
SIGPIPE_VARIABLE(pipe_st);
@@ -293,7 +310,7 @@ static void cshutdn_terminate_all(struct cshutdn *cshutdn,
}
/* wait for activity, timeout or "nothing" */
- timespent = Curl_timediff(Curl_now(), started);
+ timespent = curlx_timediff(curlx_now(), started);
if(timespent >= (timediff_t)timeout_ms) {
CURL_TRC_M(data, "[SHUTDOWN] shutdown finished, %s",
(timeout_ms > 0) ? "timeout" : "best effort done");
@@ -317,8 +334,6 @@ static void cshutdn_terminate_all(struct cshutdn *cshutdn,
}
DEBUGASSERT(!Curl_llist_count(&cshutdn->list));
- Curl_hostcache_clean(data, data->dns.hostcache);
-
sigpipe_restore(&pipe_st);
}
@@ -345,7 +360,7 @@ void Curl_cshutdn_destroy(struct cshutdn *cshutdn,
const char *p = getenv("CURL_GRACEFUL_SHUTDOWN");
if(p) {
curl_off_t l;
- if(!Curl_str_number(&p, &l, INT_MAX))
+ if(!curlx_str_number(&p, &l, INT_MAX))
timeout_ms = (int)l;
}
}
@@ -416,7 +431,7 @@ void Curl_cshutdn_add(struct cshutdn *cshutdn,
(conns_in_pool + Curl_llist_count(&cshutdn->list)))) {
CURL_TRC_M(data, "[SHUTDOWN] discarding oldest shutdown connection "
"due to connection limit of %zu", max_total);
- cshutdn_destroy_oldest(cshutdn, data);
+ cshutdn_destroy_oldest(cshutdn, data, NULL);
}
if(cshutdn->multi->socket_cb) {
diff --git a/libs/libcurl/src/cshutdn.h b/libs/libcurl/src/cshutdn.h
index 070fb53b67..690d8eefda 100644
--- a/libs/libcurl/src/cshutdn.h
+++ b/libs/libcurl/src/cshutdn.h
@@ -26,7 +26,7 @@
***************************************************************************/
#include <curl/curl.h>
-#include "timeval.h"
+#include "curlx/timeval.h"
struct connectdata;
struct Curl_easy;
@@ -75,6 +75,12 @@ size_t Curl_cshutdn_count(struct Curl_easy *data);
size_t Curl_cshutdn_dest_count(struct Curl_easy *data,
const char *destination);
+/* Close the oldest connection in shutdown to destination or,
+ * when destination is NULL for any destination.
+ * Return TRUE if a connection has been closed. */
+bool Curl_cshutdn_close_oldest(struct Curl_easy *data,
+ const char *destination);
+
/* Add a connection to have it shut down. Will terminate the oldest
* connection when total connection limit of multi is being reached. */
void Curl_cshutdn_add(struct cshutdn *cshutdn,
diff --git a/libs/libcurl/src/curl_addrinfo.c b/libs/libcurl/src/curl_addrinfo.c
index 7f60477ed6..98b02d3050 100644
--- a/libs/libcurl/src/curl_addrinfo.c
+++ b/libs/libcurl/src/curl_addrinfo.c
@@ -50,8 +50,9 @@
#include <stddef.h>
#include "curl_addrinfo.h"
-#include "inet_pton.h"
-#include "warnless.h"
+#include "fake_addrinfo.h"
+#include "curlx/inet_pton.h"
+#include "curlx/warnless.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h"
@@ -508,6 +509,14 @@ curl_dbg_freeaddrinfo(struct addrinfo *freethis,
source, line, (void *)freethis);
#ifdef USE_LWIPSOCK
lwip_freeaddrinfo(freethis);
+#elif defined(USE_FAKE_GETADDRINFO)
+ {
+ const char *env = getenv("CURL_DNS_SERVER");
+ if(env)
+ r_freeaddrinfo(freethis);
+ else
+ freeaddrinfo(freethis);
+ }
#else
freeaddrinfo(freethis);
#endif
@@ -526,13 +535,20 @@ curl_dbg_freeaddrinfo(struct addrinfo *freethis,
int
curl_dbg_getaddrinfo(const char *hostname,
- const char *service,
- const struct addrinfo *hints,
- struct addrinfo **result,
- int line, const char *source)
+ const char *service,
+ const struct addrinfo *hints,
+ struct addrinfo **result,
+ int line, const char *source)
{
#ifdef USE_LWIPSOCK
int res = lwip_getaddrinfo(hostname, service, hints, result);
+#elif defined(USE_FAKE_GETADDRINFO)
+ int res;
+ const char *env = getenv("CURL_DNS_SERVER");
+ if(env)
+ res = r_getaddrinfo(hostname, service, hints, result);
+ else
+ res = getaddrinfo(hostname, service, hints, result);
#else
int res = getaddrinfo(hostname, service, hints, result);
#endif
diff --git a/libs/libcurl/src/curl_config.h.cmake b/libs/libcurl/src/curl_config.h.cmake
index 6f7b9a736b..57af226987 100644
--- a/libs/libcurl/src/curl_config.h.cmake
+++ b/libs/libcurl/src/curl_config.h.cmake
@@ -197,6 +197,9 @@
/* Define to 1 if you have _Atomic support. */
#cmakedefine HAVE_ATOMIC 1
+/* Define to 1 if you have the `accept4' function. */
+#cmakedefine HAVE_ACCEPT4 1
+
/* Define to 1 if you have the `fnmatch' function. */
#cmakedefine HAVE_FNMATCH 1
@@ -427,6 +430,9 @@
/* Define to 1 if you have the `pipe' function. */
#cmakedefine HAVE_PIPE 1
+/* Define to 1 if you have the `pipe2' function. */
+#cmakedefine HAVE_PIPE2 1
+
/* Define to 1 if you have the `eventfd' function. */
#cmakedefine HAVE_EVENTFD 1
@@ -697,14 +703,20 @@ ${SIZEOF_TIME_T_CODE}
/* if wolfSSL is enabled */
#cmakedefine USE_WOLFSSL 1
+/* if wolfSSL has the wolfSSL_get_peer_certificate function. */
+#cmakedefine HAVE_WOLFSSL_GET_PEER_CERTIFICATE 1
+
+/* if wolfSSL has the wolfSSL_UseALPN function. */
+#cmakedefine HAVE_WOLFSSL_USEALPN 1
+
/* if wolfSSL has the wolfSSL_DES_ecb_encrypt function. */
#cmakedefine HAVE_WOLFSSL_DES_ECB_ENCRYPT 1
/* if wolfSSL has the wolfSSL_BIO_new function. */
-#cmakedefine HAVE_WOLFSSL_BIO 1
+#cmakedefine HAVE_WOLFSSL_BIO_NEW 1
/* if wolfSSL has the wolfSSL_BIO_set_shutdown function. */
-#cmakedefine HAVE_WOLFSSL_FULL_BIO 1
+#cmakedefine HAVE_WOLFSSL_BIO_SET_SHUTDOWN 1
/* if libssh is in use */
#cmakedefine USE_LIBSSH 1
@@ -758,6 +770,9 @@ ${SIZEOF_TIME_T_CODE}
/* to enable openssl + nghttp3 */
#cmakedefine USE_OPENSSL_QUIC 1
+/* to enable openssl + ngtcp2 + nghttp3 */
+#cmakedefine OPENSSL_QUIC_API2 1
+
/* Define to 1 if you have the quiche_conn_set_qlog_fd function. */
#cmakedefine HAVE_QUICHE_CONN_SET_QLOG_FD 1
diff --git a/libs/libcurl/src/curl_config.h.in b/libs/libcurl/src/curl_config.h.in
index 7f3dea8c08..e540b6d005 100644
--- a/libs/libcurl/src/curl_config.h.in
+++ b/libs/libcurl/src/curl_config.h.in
@@ -1,5 +1,7 @@
/* lib/curl_config.h.in. Generated from configure.ac by autoheader. */
+/* !checksrc! disable COPYRIGHT all */
+
/* Location of default ca bundle */
#undef CURL_CA_BUNDLE
@@ -162,6 +164,9 @@
/* Define to the type of arg 2 for gethostname. */
#undef GETHOSTNAME_TYPE_ARG2
+/* Define to 1 if you have the `accept4' function. */
+#undef HAVE_ACCEPT4
+
/* Define to 1 if symbol `ADDRESS_FAMILY' exists */
#undef HAVE_ADDRESS_FAMILY
@@ -496,6 +501,9 @@
/* Define to 1 if you have the `pipe' function. */
#undef HAVE_PIPE
+/* Define to 1 if you have the `pipe2' function. */
+#undef HAVE_PIPE2
+
/* Define to 1 if you have the `poll' function. */
#undef HAVE_POLL
@@ -583,6 +591,9 @@
/* Define to 1 if you have the `SSL_set1_ech_config_list' function. */
#undef HAVE_SSL_SET1_ECH_CONFIG_LIST
+/* Define to 1 if you have the `SSL_set_quic_tls_cbs' function. */
+#undef HAVE_SSL_SET_QUIC_TLS_CBS
+
/* Define to 1 if you have the `SSL_set_quic_use_legacy_codepoint' function.
*/
#undef HAVE_SSL_SET_QUIC_USE_LEGACY_CODEPOINT
@@ -710,21 +721,25 @@
/* Define to 1 if you have the <wolfssh/ssh.h> header file. */
#undef HAVE_WOLFSSH_SSH_H
-/* if you have wolfSSL_BIO_new */
-#undef HAVE_WOLFSSL_BIO
+/* Define to 1 if you have the `wolfSSL_BIO_new' function. */
+#undef HAVE_WOLFSSL_BIO_NEW
+
+/* Define to 1 if you have the `wolfSSL_BIO_set_shutdown' function. */
+#undef HAVE_WOLFSSL_BIO_SET_SHUTDOWN
/* Define to 1 if you have the `wolfSSL_CTX_GenerateEchConfig' function. */
#undef HAVE_WOLFSSL_CTX_GENERATEECHCONFIG
-/* if you have wolfSSL_DES_ecb_encrypt */
+/* Define to 1 if you have the `wolfSSL_DES_ecb_encrypt' function. */
#undef HAVE_WOLFSSL_DES_ECB_ENCRYPT
-/* if you have wolfSSL_BIO_set_shutdown */
-#undef HAVE_WOLFSSL_FULL_BIO
-
/* Define to 1 if you have the `wolfSSL_get_peer_certificate' function. */
#undef HAVE_WOLFSSL_GET_PEER_CERTIFICATE
+/* Define to 1 if you have the `wolfSSL_set_quic_use_legacy_codepoint'
+ function. */
+#undef HAVE_WOLFSSL_SET_QUIC_USE_LEGACY_CODEPOINT
+
/* Define to 1 if you have the `wolfSSL_UseALPN' function. */
#undef HAVE_WOLFSSL_USEALPN
@@ -752,6 +767,9 @@
/* Define to 1 if _THREAD_SAFE preprocessor symbol must be defined. */
#undef NEED_THREAD_SAFE
+/* openssl with new QUIC API */
+#undef OPENSSL_QUIC_API2
+
/* Name of package */
#undef PACKAGE
diff --git a/libs/libcurl/src/curl_get_line.c b/libs/libcurl/src/curl_get_line.c
index e88d0cc34d..04f0650d0e 100644
--- a/libs/libcurl/src/curl_get_line.c
+++ b/libs/libcurl/src/curl_get_line.c
@@ -28,9 +28,7 @@
!defined(CURL_DISABLE_HSTS) || !defined(CURL_DISABLE_NETRC)
#include "curl_get_line.h"
-#ifdef BUILDING_LIBCURL
#include "curl_memory.h"
-#endif
/* The last #include file should be: */
#include "memdebug.h"
@@ -42,7 +40,7 @@ int Curl_get_line(struct dynbuf *buf, FILE *input)
{
CURLcode result;
char buffer[128];
- Curl_dyn_reset(buf);
+ curlx_dyn_reset(buf);
while(1) {
char *b = fgets(buffer, sizeof(buffer), input);
@@ -52,7 +50,7 @@ int Curl_get_line(struct dynbuf *buf, FILE *input)
if(!rlen)
break;
- result = Curl_dyn_addn(buf, b, rlen);
+ result = curlx_dyn_addn(buf, b, rlen);
if(result)
/* too long line or out of memory */
return 0; /* error */
@@ -63,13 +61,15 @@ int Curl_get_line(struct dynbuf *buf, FILE *input)
else if(feof(input)) {
/* append a newline */
- result = Curl_dyn_addn(buf, "\n", 1);
+ result = curlx_dyn_addn(buf, "\n", 1);
if(result)
/* too long line or out of memory */
return 0; /* error */
return 1; /* all good */
}
}
+ else if(curlx_dyn_len(buf))
+ return 1; /* all good */
else
break;
}
diff --git a/libs/libcurl/src/curl_get_line.h b/libs/libcurl/src/curl_get_line.h
index 9debce926d..64b8081557 100644
--- a/libs/libcurl/src/curl_get_line.h
+++ b/libs/libcurl/src/curl_get_line.h
@@ -24,13 +24,7 @@
*
***************************************************************************/
-#include "dynbuf.h"
-
-#ifndef BUILDING_LIBCURL
-/* this renames functions so that the tool code can use the same code
- without getting symbol collisions */
-#define Curl_get_line(a,b) curlx_get_line(a,b)
-#endif
+#include "curlx/dynbuf.h"
/* Curl_get_line() returns complete lines that end with a newline. */
int Curl_get_line(struct dynbuf *buf, FILE *input);
diff --git a/libs/libcurl/src/curl_krb5.h b/libs/libcurl/src/curl_krb5.h
index b9742fd14f..f9bf63b1ce 100644
--- a/libs/libcurl/src/curl_krb5.h
+++ b/libs/libcurl/src/curl_krb5.h
@@ -39,7 +39,7 @@ struct Curl_sec_client_mech {
#define AUTH_CONTINUE 1
#define AUTH_ERROR 2
-#ifdef HAVE_GSSAPI
+#if defined(HAVE_GSSAPI) && !defined(CURL_DISABLE_FTP)
void Curl_sec_conn_init(struct connectdata *);
void Curl_sec_conn_destroy(struct connectdata *);
int Curl_sec_read_msg(struct Curl_easy *data, struct connectdata *conn, char *,
diff --git a/libs/libcurl/src/curl_ntlm_core.c b/libs/libcurl/src/curl_ntlm_core.c
index b574a1b612..01e91c24fc 100644
--- a/libs/libcurl/src/curl_ntlm_core.c
+++ b/libs/libcurl/src/curl_ntlm_core.c
@@ -126,7 +126,7 @@
#include "curl_ntlm_core.h"
#include "curl_md5.h"
#include "curl_hmac.h"
-#include "warnless.h"
+#include "curlx/warnless.h"
#include "curl_endian.h"
#include "curl_des.h"
#include "curl_md4.h"
diff --git a/libs/libcurl/src/curl_printf.h b/libs/libcurl/src/curl_printf.h
index 349735d000..f92bf7e4d0 100644
--- a/libs/libcurl/src/curl_printf.h
+++ b/libs/libcurl/src/curl_printf.h
@@ -24,21 +24,25 @@
*
***************************************************************************/
-/*
- * This header should be included by ALL code in libcurl that uses any
- * *rintf() functions.
- */
-
-#ifndef CURL_TEMP_PRINTF
-#error "CURL_TEMP_PRINTF must be set before including curl/mprintf.h"
-#endif
-
#include <curl/mprintf.h>
#define MERR_OK 0
#define MERR_MEM 1
#define MERR_TOO_LARGE 2
+/* Lower-case digits. */
+extern const unsigned char Curl_ldigits[];
+
+/* Upper-case digits. */
+extern const unsigned char Curl_udigits[];
+
+#ifdef BUILDING_LIBCURL
+
+/*
+ * This header should be included by ALL code in libcurl that uses any
+ * *rintf() functions.
+ */
+
# undef printf
# undef fprintf
# undef msnprintf
@@ -55,4 +59,6 @@
# define mvsnprintf curl_mvsnprintf
# define aprintf curl_maprintf
# define vaprintf curl_mvaprintf
+
+#endif /* BUILDING_LIBCURL */
#endif /* HEADER_CURL_PRINTF_H */
diff --git a/libs/libcurl/src/curl_range.c b/libs/libcurl/src/curl_range.c
index 795ff097df..2703d5c904 100644
--- a/libs/libcurl/src/curl_range.c
+++ b/libs/libcurl/src/curl_range.c
@@ -26,7 +26,7 @@
#include <curl/curl.h>
#include "curl_range.h"
#include "sendf.h"
-#include "strparse.h"
+#include "curlx/strparse.h"
/* Only include this function if one or more of FTP, FILE are enabled. */
#if !defined(CURL_DISABLE_FTP) || !defined(CURL_DISABLE_FILE)
@@ -41,14 +41,14 @@ CURLcode Curl_range(struct Curl_easy *data)
curl_off_t from, to;
bool first_num = TRUE;
const char *p = data->state.range;
- if(Curl_str_number(&p, &from, CURL_OFF_T_MAX))
+ if(curlx_str_number(&p, &from, CURL_OFF_T_MAX))
first_num = FALSE;
- if(Curl_str_single(&p, '-'))
+ if(curlx_str_single(&p, '-'))
/* no leading dash or after the first number is an error */
return CURLE_RANGE_ERROR;
- if(Curl_str_number(&p, &to, CURL_OFF_T_MAX)) {
+ if(curlx_str_number(&p, &to, CURL_OFF_T_MAX)) {
/* no second number */
/* X - */
data->state.resume_from = from;
diff --git a/libs/libcurl/src/curl_rtmp.c b/libs/libcurl/src/curl_rtmp.c
index e3a075dc5e..6eb41040c2 100644
--- a/libs/libcurl/src/curl_rtmp.c
+++ b/libs/libcurl/src/curl_rtmp.c
@@ -29,10 +29,11 @@
#include "curl_rtmp.h"
#include "urldata.h"
-#include "nonblock.h" /* for curlx_nonblock */
+#include "url.h"
+#include "curlx/nonblock.h" /* for curlx_nonblock */
#include "progress.h" /* for Curl_pgrsSetUploadSize */
#include "transfer.h"
-#include "warnless.h"
+#include "curlx/warnless.h"
#include <curl/curl.h>
#include <librtmp/rtmp.h>
@@ -52,6 +53,10 @@
#define DEF_BUFTIME (2*60*60*1000) /* 2 hours */
+/* meta key for storing RTMP* at connection */
+#define CURL_META_RTMP_CONN "meta:proto:rtmp:conn"
+
+
static CURLcode rtmp_setup_connection(struct Curl_easy *data,
struct connectdata *conn);
static CURLcode rtmp_do(struct Curl_easy *data, bool *done);
@@ -217,11 +222,21 @@ const struct Curl_handler Curl_handler_rtmpts = {
PROTOPT_NONE /* flags */
};
+static void rtmp_conn_dtor(void *key, size_t klen, void *entry)
+{
+ RTMP *r = entry;
+ (void)key;
+ (void)klen;
+ RTMP_Close(r);
+ RTMP_Free(r);
+}
+
static CURLcode rtmp_setup_connection(struct Curl_easy *data,
struct connectdata *conn)
{
RTMP *r = RTMP_Alloc();
- if(!r)
+ if(!r ||
+ Curl_conn_meta_set(conn, CURL_META_RTMP_CONN, r, rtmp_conn_dtor))
return CURLE_OUT_OF_MEMORY;
RTMP_Init(r);
@@ -230,16 +245,18 @@ static CURLcode rtmp_setup_connection(struct Curl_easy *data,
RTMP_Free(r);
return CURLE_URL_MALFORMAT;
}
- conn->proto.rtmp = r;
return CURLE_OK;
}
static CURLcode rtmp_connect(struct Curl_easy *data, bool *done)
{
struct connectdata *conn = data->conn;
- RTMP *r = conn->proto.rtmp;
+ RTMP *r = Curl_conn_meta_get(conn, CURL_META_RTMP_CONN);
SET_RCVTIMEO(tv, 10);
+ if(!r)
+ return CURLE_FAILED_INIT;
+
r->m_sb.sb_socket = (int)conn->sock[FIRSTSOCKET];
/* We have to know if it is a write before we send the
@@ -272,9 +289,9 @@ static CURLcode rtmp_connect(struct Curl_easy *data, bool *done)
static CURLcode rtmp_do(struct Curl_easy *data, bool *done)
{
struct connectdata *conn = data->conn;
- RTMP *r = conn->proto.rtmp;
+ RTMP *r = Curl_conn_meta_get(conn, CURL_META_RTMP_CONN);
- if(!RTMP_ConnectStream(r, 0))
+ if(!r || !RTMP_ConnectStream(r, 0))
return CURLE_FAILED_INIT;
if(data->state.upload) {
@@ -301,14 +318,11 @@ static CURLcode rtmp_disconnect(struct Curl_easy *data,
struct connectdata *conn,
bool dead_connection)
{
- RTMP *r = conn->proto.rtmp;
+ RTMP *r = Curl_conn_meta_get(conn, CURL_META_RTMP_CONN);
(void)data;
(void)dead_connection;
- if(r) {
- conn->proto.rtmp = NULL;
- RTMP_Close(r);
- RTMP_Free(r);
- }
+ if(r)
+ Curl_conn_meta_remove(conn, CURL_META_RTMP_CONN);
return CURLE_OK;
}
@@ -316,10 +330,14 @@ static ssize_t rtmp_recv(struct Curl_easy *data, int sockindex, char *buf,
size_t len, CURLcode *err)
{
struct connectdata *conn = data->conn;
- RTMP *r = conn->proto.rtmp;
+ RTMP *r = Curl_conn_meta_get(conn, CURL_META_RTMP_CONN);
ssize_t nread;
(void)sockindex; /* unused */
+ if(!r) {
+ *err = CURLE_FAILED_INIT;
+ return -1;
+ }
nread = RTMP_Read(r, buf, curlx_uztosi(len));
if(nread < 0) {
@@ -338,11 +356,15 @@ static ssize_t rtmp_send(struct Curl_easy *data, int sockindex,
const void *buf, size_t len, bool eos, CURLcode *err)
{
struct connectdata *conn = data->conn;
- RTMP *r = conn->proto.rtmp;
+ RTMP *r = Curl_conn_meta_get(conn, CURL_META_RTMP_CONN);
ssize_t num;
(void)sockindex; /* unused */
(void)eos; /* unused */
+ if(!r) {
+ *err = CURLE_FAILED_INIT;
+ return -1;
+ }
num = RTMP_Write(r, (const char *)buf, curlx_uztosi(len));
if(num < 0)
diff --git a/libs/libcurl/src/curl_sasl.c b/libs/libcurl/src/curl_sasl.c
index 09a2b85719..d919fe4b0e 100644
--- a/libs/libcurl/src/curl_sasl.c
+++ b/libs/libcurl/src/curl_sasl.c
@@ -42,14 +42,14 @@
#include <curl/curl.h>
#include "urldata.h"
-#include "curl_base64.h"
+#include "curlx/base64.h"
#include "curl_md5.h"
#include "vauth/vauth.h"
#include "cfilters.h"
#include "vtls/vtls.h"
#include "curl_hmac.h"
#include "curl_sasl.h"
-#include "warnless.h"
+#include "curlx/warnless.h"
#include "sendf.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
@@ -283,7 +283,7 @@ static CURLcode get_server_message(struct SASL *sasl, struct Curl_easy *data,
if(!*serverdata || *serverdata == '=')
Curl_bufref_set(out, NULL, 0, NULL);
else {
- result = Curl_base64_decode(serverdata, &msg, &msglen);
+ result = curlx_base64_decode(serverdata, &msg, &msglen);
if(!result)
Curl_bufref_set(out, msg, msglen, curl_free);
}
@@ -306,8 +306,8 @@ static CURLcode build_message(struct SASL *sasl, struct bufref *msg)
char *base64;
size_t base64len;
- result = Curl_base64_encode((const char *) Curl_bufref_ptr(msg),
- Curl_bufref_len(msg), &base64, &base64len);
+ result = curlx_base64_encode((const char *) Curl_bufref_ptr(msg),
+ Curl_bufref_len(msg), &base64, &base64len);
if(!result)
Curl_bufref_set(msg, base64, base64len, curl_free);
}
@@ -756,4 +756,101 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct Curl_easy *data,
return result;
}
+
+#ifndef CURL_DISABLE_VERBOSE_STRINGS
+static void sasl_unchosen(struct Curl_easy *data, unsigned short mech,
+ unsigned short enabledmechs,
+ bool built_in, bool platform,
+ const char *param_missing)
+{
+ const char *mname = NULL;
+ size_t i;
+
+ if(!(enabledmechs & mech))
+ return;
+
+ for(i = 0; mechtable[i].name; ++i) {
+ if(mechtable[i].bit == mech) {
+ mname = mechtable[i].name;
+ break;
+ }
+ }
+ if(!mname) /* should not happen */
+ return;
+ if(!built_in)
+ infof(data, "SASL: %s not builtin", mname);
+ else if(!platform)
+ infof(data, "SASL: %s not supported by the platform/libraries", mname);
+ else {
+ if(param_missing)
+ infof(data, "SASL: %s is missing %s", mname, param_missing);
+ if(!data->state.aptr.user)
+ infof(data, "SASL: %s is missing username", mname);
+ }
+}
+#endif /* CURL_DISABLE_VERBOSE_STRINGS */
+
+CURLcode Curl_sasl_is_blocked(struct SASL *sasl, struct Curl_easy *data)
+{
+#ifndef CURL_DISABLE_VERBOSE_STRINGS
+#ifdef USE_KERBEROS5
+#define CURL_SASL_KERBEROS5 TRUE
+#else
+#define CURL_SASL_KERBEROS5 FALSE
+#endif
+#ifdef USE_GSASL
+#define CURL_SASL_GASL TRUE
+#else
+#define CURL_SASL_GASL FALSE
+#endif
+#ifdef CURL_DISABLE_DIGEST_AUTH
+#define CURL_SASL_DIGEST TRUE
+#else
+#define CURL_SASL_DIGEST FALSE
+#endif
+#ifndef USE_NTLM
+#define CURL_SASL_NTLM TRUE
+#else
+#define CURL_SASL_NTLM FALSE
+#endif
+ /* Failing SASL authentication is a pain. Give a helping hand if
+ * we were unable to select an AUTH mechanism.
+ * `sasl->authmechs` are mechanisms offered by the peer
+ * `sasl->prefmech` are mechanisms preferred by us */
+ unsigned short enabledmechs = sasl->authmechs & sasl->prefmech;
+
+ if(!sasl->authmechs)
+ infof(data, "SASL: no auth mechanism was offered or recognized");
+ else if(!enabledmechs)
+ infof(data, "SASL: no overlap between offered and configured "
+ "auth mechanisms");
+ else {
+ infof(data, "SASL: no auth mechanism offered could be selected");
+ if((enabledmechs & SASL_MECH_EXTERNAL) && data->conn->passwd[0])
+ infof(data, "SASL: auth EXTERNAL not chosen with password");
+ sasl_unchosen(data, SASL_MECH_GSSAPI, enabledmechs,
+ CURL_SASL_KERBEROS5, Curl_auth_is_gssapi_supported(), NULL);
+ sasl_unchosen(data, SASL_MECH_SCRAM_SHA_256, enabledmechs,
+ CURL_SASL_GASL, FALSE, NULL);
+ sasl_unchosen(data, SASL_MECH_SCRAM_SHA_1, enabledmechs,
+ CURL_SASL_GASL, FALSE, NULL);
+ sasl_unchosen(data, SASL_MECH_DIGEST_MD5, enabledmechs,
+ CURL_SASL_DIGEST, Curl_auth_is_digest_supported(), NULL);
+ sasl_unchosen(data, SASL_MECH_CRAM_MD5, enabledmechs,
+ CURL_SASL_DIGEST, TRUE, NULL);
+ sasl_unchosen(data, SASL_MECH_NTLM, enabledmechs,
+ CURL_SASL_NTLM, Curl_auth_is_ntlm_supported(), NULL);
+ sasl_unchosen(data, SASL_MECH_OAUTHBEARER, enabledmechs, TRUE, TRUE,
+ data->set.str[STRING_BEARER] ?
+ NULL : "CURLOPT_XOAUTH2_BEARER");
+ sasl_unchosen(data, SASL_MECH_XOAUTH2, enabledmechs, TRUE, TRUE,
+ data->set.str[STRING_BEARER] ?
+ NULL : "CURLOPT_XOAUTH2_BEARER");
+ }
+#endif /* CURL_DISABLE_VERBOSE_STRINGS */
+ (void)sasl;
+ (void)data;
+ return CURLE_LOGIN_DENIED;
+}
+
#endif /* protocols are enabled that use SASL */
diff --git a/libs/libcurl/src/curl_sasl.h b/libs/libcurl/src/curl_sasl.h
index 0c07f9f642..a11cc555c8 100644
--- a/libs/libcurl/src/curl_sasl.h
+++ b/libs/libcurl/src/curl_sasl.h
@@ -162,4 +162,6 @@ CURLcode Curl_sasl_start(struct SASL *sasl, struct Curl_easy *data,
CURLcode Curl_sasl_continue(struct SASL *sasl, struct Curl_easy *data,
int code, saslprogress *progress);
+CURLcode Curl_sasl_is_blocked(struct SASL *sasl, struct Curl_easy *data);
+
#endif /* HEADER_CURL_SASL_H */
diff --git a/libs/libcurl/src/curl_setup.h b/libs/libcurl/src/curl_setup.h
index 63a8b329e5..a69b222044 100644
--- a/libs/libcurl/src/curl_setup.h
+++ b/libs/libcurl/src/curl_setup.h
@@ -28,9 +28,6 @@
#define CURL_NO_OLDIES
#endif
-/* Tell "curl/curl.h" not to include "curl/mprintf.h" */
-#define CURL_SKIP_INCLUDE_MPRINTF
-
/* Set default _WIN32_WINNT */
#ifdef __MINGW32__
#include <_mingw.h>
@@ -108,6 +105,16 @@
# ifndef NOGDI
# define NOGDI
# endif
+/* Detect Windows App environment which has a restricted access
+ * to the Win32 APIs. */
+# if (defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0602)) || \
+ defined(WINAPI_FAMILY)
+# include <winapifamily.h>
+# if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) && \
+ !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
+# define CURL_WINDOWS_UWP
+# endif
+# endif
#endif
/* Avoid bogus format check warnings with mingw32ce gcc 4.4.0 in
@@ -445,6 +452,11 @@
# define __NO_NET_API
#endif
+/* Whether to use eventfd() */
+#if defined(HAVE_EVENTFD) && defined(HAVE_SYS_EVENTFD_H)
+#define USE_EVENTFD
+#endif
+
#include <stdio.h>
#include <assert.h>
@@ -458,12 +470,6 @@
#include <curl/stdcheaders.h>
#endif
-#ifdef _WIN32
-#define curlx_getpid() GetCurrentProcessId()
-#else
-#define curlx_getpid() getpid()
-#endif
-
/*
* Large file (>2Gb) support using Win32 functions.
*/
diff --git a/libs/libcurl/src/curl_sha512_256.c b/libs/libcurl/src/curl_sha512_256.c
index d43b2e420c..f68c9d7f4c 100644
--- a/libs/libcurl/src/curl_sha512_256.c
+++ b/libs/libcurl/src/curl_sha512_256.c
@@ -27,7 +27,7 @@
#if !defined(CURL_DISABLE_DIGEST_AUTH) && !defined(CURL_DISABLE_SHA512_256)
#include "curl_sha512_256.h"
-#include "warnless.h"
+#include "curlx/warnless.h"
/* The recommended order of the TLS backends:
* * OpenSSL
diff --git a/libs/libcurl/src/curl_sspi.c b/libs/libcurl/src/curl_sspi.c
index cdec76c263..ddfa8e8525 100644
--- a/libs/libcurl/src/curl_sspi.c
+++ b/libs/libcurl/src/curl_sspi.c
@@ -28,10 +28,10 @@
#include <curl/curl.h>
#include "curl_sspi.h"
-#include "curl_multibyte.h"
+#include "curlx/multibyte.h"
#include "system_win32.h"
-#include "version_win32.h"
-#include "warnless.h"
+#include "curlx/version_win32.h"
+#include "curlx/warnless.h"
/* The last #include files should be: */
#include "curl_memory.h"
diff --git a/libs/libcurl/src/curl_threads.c b/libs/libcurl/src/curl_threads.c
index caee0a6df9..c4831471d6 100644
--- a/libs/libcurl/src/curl_threads.c
+++ b/libs/libcurl/src/curl_threads.c
@@ -35,9 +35,7 @@
#endif
#include "curl_threads.h"
-#ifdef BUILDING_LIBCURL
#include "curl_memory.h"
-#endif
/* The last #include file should be: */
#include "memdebug.h"
@@ -82,11 +80,12 @@ err:
return curl_thread_t_null;
}
-void Curl_thread_destroy(curl_thread_t hnd)
+void Curl_thread_destroy(curl_thread_t *hnd)
{
- if(hnd != curl_thread_t_null) {
- pthread_detach(*hnd);
- free(hnd);
+ if(*hnd != curl_thread_t_null) {
+ pthread_detach(**hnd);
+ free(*hnd);
+ *hnd = curl_thread_t_null;
}
}
@@ -138,10 +137,12 @@ curl_thread_t Curl_thread_create(
return t;
}
-void Curl_thread_destroy(curl_thread_t hnd)
+void Curl_thread_destroy(curl_thread_t *hnd)
{
- if(hnd != curl_thread_t_null)
- CloseHandle(hnd);
+ if(*hnd != curl_thread_t_null) {
+ CloseHandle(*hnd);
+ *hnd = curl_thread_t_null;
+ }
}
int Curl_thread_join(curl_thread_t *hnd)
@@ -153,9 +154,7 @@ int Curl_thread_join(curl_thread_t *hnd)
int ret = (WaitForSingleObjectEx(*hnd, INFINITE, FALSE) == WAIT_OBJECT_0);
#endif
- Curl_thread_destroy(*hnd);
-
- *hnd = curl_thread_t_null;
+ Curl_thread_destroy(hnd);
return ret;
}
diff --git a/libs/libcurl/src/curl_threads.h b/libs/libcurl/src/curl_threads.h
index b8e4b316fa..8b1821d011 100644
--- a/libs/libcurl/src/curl_threads.h
+++ b/libs/libcurl/src/curl_threads.h
@@ -61,7 +61,7 @@ curl_thread_t Curl_thread_create(
(CURL_STDCALL *func) (void *),
void *arg);
-void Curl_thread_destroy(curl_thread_t hnd);
+void Curl_thread_destroy(curl_thread_t *hnd);
int Curl_thread_join(curl_thread_t *hnd);
diff --git a/libs/libcurl/src/curl_trc.c b/libs/libcurl/src/curl_trc.c
index 4ac583b140..546d3c547e 100644
--- a/libs/libcurl/src/curl_trc.c
+++ b/libs/libcurl/src/curl_trc.c
@@ -43,7 +43,7 @@
#include "cf-haproxy.h"
#include "cf-https-connect.h"
#include "socks.h"
-#include "strparse.h"
+#include "curlx/strparse.h"
#include "vtls/vtls.h"
#include "vquic/vquic.h"
@@ -497,13 +497,13 @@ static void trc_apply_level_by_name(struct Curl_str *token, int lvl)
size_t i;
for(i = 0; i < CURL_ARRAYSIZE(trc_cfts); ++i) {
- if(Curl_str_casecompare(token, trc_cfts[i].cft->name)) {
+ if(curlx_str_casecompare(token, trc_cfts[i].cft->name)) {
trc_cfts[i].cft->log_level = lvl;
break;
}
}
for(i = 0; i < CURL_ARRAYSIZE(trc_feats); ++i) {
- if(Curl_str_casecompare(token, trc_feats[i].feat->name)) {
+ if(curlx_str_casecompare(token, trc_feats[i].feat->name)) {
trc_feats[i].feat->log_level = lvl;
break;
}
@@ -527,33 +527,33 @@ static void trc_apply_level_by_category(int category, int lvl)
static CURLcode trc_opt(const char *config)
{
struct Curl_str out;
- while(!Curl_str_until(&config, &out, 32, ',')) {
+ while(!curlx_str_until(&config, &out, 32, ',')) {
int lvl = CURL_LOG_LVL_INFO;
- const char *token = Curl_str(&out);
+ const char *token = curlx_str(&out);
if(*token == '-') {
lvl = CURL_LOG_LVL_NONE;
- Curl_str_nudge(&out, 1);
+ curlx_str_nudge(&out, 1);
}
else if(*token == '+')
- Curl_str_nudge(&out, 1);
+ curlx_str_nudge(&out, 1);
- if(Curl_str_casecompare(&out, "all"))
+ if(curlx_str_casecompare(&out, "all"))
trc_apply_level_by_category(TRC_CT_NONE, lvl);
- else if(Curl_str_casecompare(&out, "protocol"))
+ else if(curlx_str_casecompare(&out, "protocol"))
trc_apply_level_by_category(TRC_CT_PROTOCOL, lvl);
- else if(Curl_str_casecompare(&out, "network"))
+ else if(curlx_str_casecompare(&out, "network"))
trc_apply_level_by_category(TRC_CT_NETWORK, lvl);
- else if(Curl_str_casecompare(&out, "proxy"))
+ else if(curlx_str_casecompare(&out, "proxy"))
trc_apply_level_by_category(TRC_CT_PROXY, lvl);
- else if(Curl_str_casecompare(&out, "doh")) {
+ else if(curlx_str_casecompare(&out, "doh")) {
struct Curl_str dns = { "dns", 3 };
trc_apply_level_by_name(&dns, lvl);
}
else
trc_apply_level_by_name(&out, lvl);
- if(Curl_str_single(&config, ','))
+ if(curlx_str_single(&config, ','))
break;
}
return CURLE_OK;
diff --git a/libs/libcurl/src/base64.c b/libs/libcurl/src/curlx/base64.c
index 24a8fc1f0f..5396eba41a 100644
--- a/libs/libcurl/src/base64.c
+++ b/libs/libcurl/src/curlx/base64.c
@@ -24,7 +24,7 @@
/* Base64 encoding/decoding */
-#include "curl_setup.h"
+#include "../curl_setup.h"
#if !defined(CURL_DISABLE_HTTP_AUTH) || defined(USE_SSH) || \
!defined(CURL_DISABLE_LDAP) || \
@@ -33,20 +33,19 @@
!defined(CURL_DISABLE_IMAP) || \
!defined(CURL_DISABLE_DIGEST_AUTH) || \
!defined(CURL_DISABLE_DOH) || defined(USE_SSL) || !defined(BUILDING_LIBCURL)
-#include "curl/curl.h"
+#include <curl/curl.h>
#include "warnless.h"
-#include "curl_base64.h"
+#include "base64.h"
/* The last 2 #include files should be in this order */
#ifdef BUILDING_LIBCURL
-#include "curl_memory.h"
+#include "../curl_memory.h"
#endif
-#include "memdebug.h"
+#include "../memdebug.h"
/* ---- Base64 Encoding/Decoding Table --- */
-/* Padding character string starts at offset 64. */
-static const char base64encdec[]=
- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
+const char Curl_base64encdec[]=
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
/* The Base 64 encoding with a URL and filename safe alphabet, RFC 4648
section 5 */
@@ -60,7 +59,7 @@ static const unsigned char decodetable[] =
29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
48, 49, 50, 51 };
/*
- * Curl_base64_decode()
+ * curlx_base64_decode()
*
* Given a base64 NUL-terminated string at src, decode it and return a
* pointer in *outptr to a newly allocated memory area holding decoded
@@ -73,8 +72,8 @@ static const unsigned char decodetable[] =
*
* @unittest: 1302
*/
-CURLcode Curl_base64_decode(const char *src,
- unsigned char **outptr, size_t *outlen)
+CURLcode curlx_base64_decode(const char *src,
+ unsigned char **outptr, size_t *outlen)
{
size_t srclen = 0;
size_t padding = 0;
@@ -119,14 +118,6 @@ CURLcode Curl_base64_decode(const char *src,
memset(lookup, 0xff, sizeof(lookup));
memcpy(&lookup['+'], decodetable, sizeof(decodetable));
- /* replaces
- {
- unsigned char c;
- const unsigned char *p = (const unsigned char *)base64encdec;
- for(c = 0; *p; c++, p++)
- lookup[*p] = c;
- }
- */
/* Decode the complete quantums first */
for(i = 0; i < fullQuantums; i++) {
@@ -186,13 +177,13 @@ bad:
}
static CURLcode base64_encode(const char *table64,
+ unsigned char padbyte,
const char *inputbuff, size_t insize,
char **outptr, size_t *outlen)
{
char *output;
char *base64data;
const unsigned char *in = (const unsigned char *)inputbuff;
- const char *padstr = &table64[64]; /* Point to padding string. */
*outptr = NULL;
*outlen = 0;
@@ -222,17 +213,17 @@ static CURLcode base64_encode(const char *table64,
*output++ = table64[ in[0] >> 2 ];
if(insize == 1) {
*output++ = table64[ ((in[0] & 0x03) << 4) ];
- if(*padstr) {
- *output++ = *padstr;
- *output++ = *padstr;
+ if(padbyte) {
+ *output++ = padbyte;
+ *output++ = padbyte;
}
}
else {
/* insize == 2 */
*output++ = table64[ ((in[0] & 0x03) << 4) | ((in[1] & 0xF0) >> 4) ];
*output++ = table64[ ((in[1] & 0x0F) << 2) ];
- if(*padstr)
- *output++ = *padstr;
+ if(padbyte)
+ *output++ = padbyte;
}
}
@@ -249,7 +240,7 @@ static CURLcode base64_encode(const char *table64,
}
/*
- * Curl_base64_encode()
+ * curlx_base64_encode()
*
* Given a pointer to an input buffer and an input size, encode it and
* return a pointer in *outptr to a newly allocated memory area holding
@@ -263,14 +254,15 @@ static CURLcode base64_encode(const char *table64,
*
* @unittest: 1302
*/
-CURLcode Curl_base64_encode(const char *inputbuff, size_t insize,
- char **outptr, size_t *outlen)
+CURLcode curlx_base64_encode(const char *inputbuff, size_t insize,
+ char **outptr, size_t *outlen)
{
- return base64_encode(base64encdec, inputbuff, insize, outptr, outlen);
+ return base64_encode(Curl_base64encdec, '=',
+ inputbuff, insize, outptr, outlen);
}
/*
- * Curl_base64url_encode()
+ * curlx_base64url_encode()
*
* Given a pointer to an input buffer and an input size, encode it and
* return a pointer in *outptr to a newly allocated memory area holding
@@ -284,10 +276,10 @@ CURLcode Curl_base64_encode(const char *inputbuff, size_t insize,
*
* @unittest: 1302
*/
-CURLcode Curl_base64url_encode(const char *inputbuff, size_t insize,
- char **outptr, size_t *outlen)
+CURLcode curlx_base64url_encode(const char *inputbuff, size_t insize,
+ char **outptr, size_t *outlen)
{
- return base64_encode(base64url, inputbuff, insize, outptr, outlen);
+ return base64_encode(base64url, 0, inputbuff, insize, outptr, outlen);
}
#endif /* no users so disabled */
diff --git a/libs/libcurl/src/curl_base64.h b/libs/libcurl/src/curlx/base64.h
index 6f9d341ae4..ab458cfe6f 100644
--- a/libs/libcurl/src/curl_base64.h
+++ b/libs/libcurl/src/curlx/base64.h
@@ -24,18 +24,13 @@
*
***************************************************************************/
-#ifndef BUILDING_LIBCURL
-/* this renames functions so that the tool code can use the same code
- without getting symbol collisions */
-#define Curl_base64_encode(a,b,c,d) curlx_base64_encode(a,b,c,d)
-#define Curl_base64url_encode(a,b,c,d) curlx_base64url_encode(a,b,c,d)
-#define Curl_base64_decode(a,b,c) curlx_base64_decode(a,b,c)
-#endif
+CURLcode curlx_base64_encode(const char *inputbuff, size_t insize,
+ char **outptr, size_t *outlen);
+CURLcode curlx_base64url_encode(const char *inputbuff, size_t insize,
+ char **outptr, size_t *outlen);
+CURLcode curlx_base64_decode(const char *src,
+ unsigned char **outptr, size_t *outlen);
+
+extern const char Curl_base64encdec[];
-CURLcode Curl_base64_encode(const char *inputbuff, size_t insize,
- char **outptr, size_t *outlen);
-CURLcode Curl_base64url_encode(const char *inputbuff, size_t insize,
- char **outptr, size_t *outlen);
-CURLcode Curl_base64_decode(const char *src,
- unsigned char **outptr, size_t *outlen);
#endif /* HEADER_CURL_BASE64_H */
diff --git a/libs/libcurl/src/curlx.h b/libs/libcurl/src/curlx/curlx.h
index b1d79ed7aa..bb1ad81b28 100644
--- a/libs/libcurl/src/curlx.h
+++ b/libs/libcurl/src/curlx/curlx.h
@@ -31,12 +31,6 @@
* be.
*/
-/* map standard printf functions to curl implementations */
-#include "curl_printf.h"
-
-#include "strcase.h"
-/* "strcase.h" provides the strcasecompare protos */
-
#include "nonblock.h"
/* "nonblock.h" provides curlx_nonblock() */
@@ -48,8 +42,8 @@
curlx_uztosi()
*/
-#include "curl_multibyte.h"
-/* "curl_multibyte.h" provides these functions and macros:
+#include "multibyte.h"
+/* "multibyte.h" provides these functions and macros:
curlx_convert_UTF8_to_wchar()
curlx_convert_wchar_to_UTF8()
@@ -59,11 +53,22 @@
*/
#include "version_win32.h"
-/* "version_win32.h" provides curlx_verify_windows_version() */
+/* provides curlx_verify_windows_version() */
#include "strparse.h"
/* The curlx_str_* parsing functions */
-#define curlx_safefree(x) Curl_safefree(x)
+#include "dynbuf.h"
+/* The curlx_dyn_* functions */
+
+#include "base64.h"
+#include "timeval.h"
+#include "timediff.h"
+
+#include "winapi.h"
+/* for curlx_winapi_strerror */
+
+#include "inet_pton.h"
+/* for curlx_inet_pton */
#endif /* HEADER_CURL_CURLX_H */
diff --git a/libs/libcurl/src/dynbuf.c b/libs/libcurl/src/curlx/dynbuf.c
index f756363fea..fd25cc9f77 100644
--- a/libs/libcurl/src/dynbuf.c
+++ b/libs/libcurl/src/curlx/dynbuf.c
@@ -22,13 +22,13 @@
*
***************************************************************************/
-#include "curl_setup.h"
+#include "../curl_setup.h"
#include "dynbuf.h"
-#include "curl_printf.h"
+#include "../curl_printf.h"
#ifdef BUILDING_LIBCURL
-#include "curl_memory.h"
+#include "../curl_memory.h"
#endif
-#include "memdebug.h"
+#include "../memdebug.h"
#define MIN_FIRST_ALLOC 32
@@ -39,7 +39,7 @@
/*
* Init a dynbuf struct.
*/
-void Curl_dyn_init(struct dynbuf *s, size_t toobig)
+void curlx_dyn_init(struct dynbuf *s, size_t toobig)
{
DEBUGASSERT(s);
DEBUGASSERT(toobig);
@@ -57,7 +57,7 @@ void Curl_dyn_init(struct dynbuf *s, size_t toobig)
* free the buffer and re-init the necessary fields. It does not touch the
* 'init' field and thus this buffer can be reused to add data to again.
*/
-void Curl_dyn_free(struct dynbuf *s)
+void curlx_dyn_free(struct dynbuf *s)
{
DEBUGASSERT(s);
DEBUGASSERT(s->init == DYNINIT);
@@ -84,7 +84,7 @@ static CURLcode dyn_nappend(struct dynbuf *s,
DEBUGASSERT(!len || mem);
if(fit > s->toobig) {
- Curl_dyn_free(s);
+ curlx_dyn_free(s);
return CURLE_TOO_LARGE;
}
else if(!a) {
@@ -110,7 +110,7 @@ static CURLcode dyn_nappend(struct dynbuf *s,
include that as well when it uses this code */
void *p = realloc(s->bufr, a);
if(!p) {
- Curl_dyn_free(s);
+ curlx_dyn_free(s);
return CURLE_OUT_OF_MEMORY;
}
s->bufr = p;
@@ -128,7 +128,7 @@ static CURLcode dyn_nappend(struct dynbuf *s,
* Clears the string, keeps the allocation. This can also be called on a
* buffer that already was freed.
*/
-void Curl_dyn_reset(struct dynbuf *s)
+void curlx_dyn_reset(struct dynbuf *s)
{
DEBUGASSERT(s);
DEBUGASSERT(s->init == DYNINIT);
@@ -142,7 +142,7 @@ void Curl_dyn_reset(struct dynbuf *s)
* Specify the size of the tail to keep (number of bytes from the end of the
* buffer). The rest will be dropped.
*/
-CURLcode Curl_dyn_tail(struct dynbuf *s, size_t trail)
+CURLcode curlx_dyn_tail(struct dynbuf *s, size_t trail)
{
DEBUGASSERT(s);
DEBUGASSERT(s->init == DYNINIT);
@@ -152,7 +152,7 @@ CURLcode Curl_dyn_tail(struct dynbuf *s, size_t trail)
else if(trail == s->leng)
return CURLE_OK;
else if(!trail) {
- Curl_dyn_reset(s);
+ curlx_dyn_reset(s);
}
else {
memmove(&s->bufr[0], &s->bufr[s->leng - trail], trail);
@@ -166,7 +166,7 @@ CURLcode Curl_dyn_tail(struct dynbuf *s, size_t trail)
/*
* Appends a buffer with length.
*/
-CURLcode Curl_dyn_addn(struct dynbuf *s, const void *mem, size_t len)
+CURLcode curlx_dyn_addn(struct dynbuf *s, const void *mem, size_t len)
{
DEBUGASSERT(s);
DEBUGASSERT(s->init == DYNINIT);
@@ -177,7 +177,7 @@ CURLcode Curl_dyn_addn(struct dynbuf *s, const void *mem, size_t len)
/*
* Append a null-terminated string at the end.
*/
-CURLcode Curl_dyn_add(struct dynbuf *s, const char *str)
+CURLcode curlx_dyn_add(struct dynbuf *s, const char *str)
{
size_t n;
DEBUGASSERT(str);
@@ -191,7 +191,7 @@ CURLcode Curl_dyn_add(struct dynbuf *s, const char *str)
/*
* Append a string vprintf()-style
*/
-CURLcode Curl_dyn_vaddf(struct dynbuf *s, const char *fmt, va_list ap)
+CURLcode curlx_dyn_vaddf(struct dynbuf *s, const char *fmt, va_list ap)
{
#ifdef BUILDING_LIBCURL
int rc;
@@ -199,7 +199,7 @@ CURLcode Curl_dyn_vaddf(struct dynbuf *s, const char *fmt, va_list ap)
DEBUGASSERT(s->init == DYNINIT);
DEBUGASSERT(!s->leng || s->bufr);
DEBUGASSERT(fmt);
- rc = Curl_dyn_vprintf(s, fmt, ap);
+ rc = curlx_dyn_vprintf(s, fmt, ap);
if(!rc)
return CURLE_OK;
@@ -208,7 +208,7 @@ CURLcode Curl_dyn_vaddf(struct dynbuf *s, const char *fmt, va_list ap)
return CURLE_OUT_OF_MEMORY;
#else
char *str;
- str = vaprintf(fmt, ap); /* this allocs a new string to append */
+ str = curl_mvaprintf(fmt, ap); /* this allocs a new string to append */
if(str) {
CURLcode result = dyn_nappend(s, (const unsigned char *)str, strlen(str));
@@ -216,7 +216,7 @@ CURLcode Curl_dyn_vaddf(struct dynbuf *s, const char *fmt, va_list ap)
return result;
}
/* If we failed, we cleanup the whole buffer and return error */
- Curl_dyn_free(s);
+ curlx_dyn_free(s);
return CURLE_OUT_OF_MEMORY;
#endif
}
@@ -224,7 +224,7 @@ CURLcode Curl_dyn_vaddf(struct dynbuf *s, const char *fmt, va_list ap)
/*
* Append a string printf()-style
*/
-CURLcode Curl_dyn_addf(struct dynbuf *s, const char *fmt, ...)
+CURLcode curlx_dyn_addf(struct dynbuf *s, const char *fmt, ...)
{
CURLcode result;
va_list ap;
@@ -232,7 +232,7 @@ CURLcode Curl_dyn_addf(struct dynbuf *s, const char *fmt, ...)
DEBUGASSERT(s->init == DYNINIT);
DEBUGASSERT(!s->leng || s->bufr);
va_start(ap, fmt);
- result = Curl_dyn_vaddf(s, fmt, ap);
+ result = curlx_dyn_vaddf(s, fmt, ap);
va_end(ap);
return result;
}
@@ -240,7 +240,7 @@ CURLcode Curl_dyn_addf(struct dynbuf *s, const char *fmt, ...)
/*
* Returns a pointer to the buffer.
*/
-char *Curl_dyn_ptr(const struct dynbuf *s)
+char *curlx_dyn_ptr(const struct dynbuf *s)
{
DEBUGASSERT(s);
DEBUGASSERT(s->init == DYNINIT);
@@ -248,7 +248,7 @@ char *Curl_dyn_ptr(const struct dynbuf *s)
return s->bufr;
}
-char *Curl_dyn_take(struct dynbuf *s, size_t *plen)
+char *curlx_dyn_take(struct dynbuf *s, size_t *plen)
{
char *ptr = s->bufr;
DEBUGASSERT(s);
@@ -263,7 +263,7 @@ char *Curl_dyn_take(struct dynbuf *s, size_t *plen)
/*
* Returns an unsigned pointer to the buffer.
*/
-unsigned char *Curl_dyn_uptr(const struct dynbuf *s)
+unsigned char *curlx_dyn_uptr(const struct dynbuf *s)
{
DEBUGASSERT(s);
DEBUGASSERT(s->init == DYNINIT);
@@ -274,7 +274,7 @@ unsigned char *Curl_dyn_uptr(const struct dynbuf *s)
/*
* Returns the length of the buffer.
*/
-size_t Curl_dyn_len(const struct dynbuf *s)
+size_t curlx_dyn_len(const struct dynbuf *s)
{
DEBUGASSERT(s);
DEBUGASSERT(s->init == DYNINIT);
@@ -285,7 +285,7 @@ size_t Curl_dyn_len(const struct dynbuf *s)
/*
* Set a new (smaller) length.
*/
-CURLcode Curl_dyn_setlen(struct dynbuf *s, size_t set)
+CURLcode curlx_dyn_setlen(struct dynbuf *s, size_t set)
{
DEBUGASSERT(s);
DEBUGASSERT(s->init == DYNINIT);
diff --git a/libs/libcurl/src/dynbuf.h b/libs/libcurl/src/curlx/dynbuf.h
index 663bf90141..bd19caa343 100644
--- a/libs/libcurl/src/dynbuf.h
+++ b/libs/libcurl/src/curlx/dynbuf.h
@@ -26,25 +26,6 @@
#include <curl/curl.h>
-#ifndef BUILDING_LIBCURL
-/* this renames the functions so that the tool code can use the same code
- without getting symbol collisions */
-#define Curl_dyn_init(a,b) curlx_dyn_init(a,b)
-#define Curl_dyn_add(a,b) curlx_dyn_add(a,b)
-#define Curl_dyn_addn(a,b,c) curlx_dyn_addn(a,b,c)
-#define Curl_dyn_addf curlx_dyn_addf
-#define Curl_dyn_vaddf curlx_dyn_vaddf
-#define Curl_dyn_free(a) curlx_dyn_free(a)
-#define Curl_dyn_ptr(a) curlx_dyn_ptr(a)
-#define Curl_dyn_uptr(a) curlx_dyn_uptr(a)
-#define Curl_dyn_len(a) curlx_dyn_len(a)
-#define Curl_dyn_reset(a) curlx_dyn_reset(a)
-#define Curl_dyn_take(a,b) curlx_dyn_take(a,b)
-#define Curl_dyn_tail(a,b) curlx_dyn_tail(a,b)
-#define Curl_dyn_setlen(a,b) curlx_dyn_setlen(a,b)
-#define curlx_dynbuf dynbuf /* for the struct name */
-#endif
-
struct dynbuf {
char *bufr; /* point to a null-terminated allocated buffer */
size_t leng; /* number of bytes *EXCLUDING* the null-terminator */
@@ -55,30 +36,30 @@ struct dynbuf {
#endif
};
-void Curl_dyn_init(struct dynbuf *s, size_t toobig);
-void Curl_dyn_free(struct dynbuf *s);
-CURLcode Curl_dyn_addn(struct dynbuf *s, const void *mem, size_t len)
+void curlx_dyn_init(struct dynbuf *s, size_t toobig);
+void curlx_dyn_free(struct dynbuf *s);
+CURLcode curlx_dyn_addn(struct dynbuf *s, const void *mem, size_t len)
WARN_UNUSED_RESULT;
-CURLcode Curl_dyn_add(struct dynbuf *s, const char *str)
+CURLcode curlx_dyn_add(struct dynbuf *s, const char *str)
WARN_UNUSED_RESULT;
-CURLcode Curl_dyn_addf(struct dynbuf *s, const char *fmt, ...)
+CURLcode curlx_dyn_addf(struct dynbuf *s, const char *fmt, ...)
WARN_UNUSED_RESULT CURL_PRINTF(2, 3);
-CURLcode Curl_dyn_vaddf(struct dynbuf *s, const char *fmt, va_list ap)
+CURLcode curlx_dyn_vaddf(struct dynbuf *s, const char *fmt, va_list ap)
WARN_UNUSED_RESULT CURL_PRINTF(2, 0);
-void Curl_dyn_reset(struct dynbuf *s);
-CURLcode Curl_dyn_tail(struct dynbuf *s, size_t trail);
-CURLcode Curl_dyn_setlen(struct dynbuf *s, size_t set);
-char *Curl_dyn_ptr(const struct dynbuf *s);
-unsigned char *Curl_dyn_uptr(const struct dynbuf *s);
-size_t Curl_dyn_len(const struct dynbuf *s);
+void curlx_dyn_reset(struct dynbuf *s);
+CURLcode curlx_dyn_tail(struct dynbuf *s, size_t trail);
+CURLcode curlx_dyn_setlen(struct dynbuf *s, size_t set);
+char *curlx_dyn_ptr(const struct dynbuf *s);
+unsigned char *curlx_dyn_uptr(const struct dynbuf *s);
+size_t curlx_dyn_len(const struct dynbuf *s);
/* returns 0 on success, -1 on error */
/* The implementation of this function exists in mprintf.c */
-int Curl_dyn_vprintf(struct dynbuf *dyn, const char *format, va_list ap_save);
+int curlx_dyn_vprintf(struct dynbuf *dyn, const char *format, va_list ap_save);
/* Take the buffer out of the dynbuf. Caller has ownership and
* dynbuf resets to initial state. */
-char *Curl_dyn_take(struct dynbuf *s, size_t *plen);
+char *curlx_dyn_take(struct dynbuf *s, size_t *plen);
/* Dynamic buffer max sizes */
#define MAX_DYNBUF_SIZE (SIZE_T_MAX/2)
@@ -99,4 +80,6 @@ char *Curl_dyn_take(struct dynbuf *s, size_t *plen);
#define DYN_MQTT_RECV (64*1024)
#define DYN_MQTT_SEND 0xFFFFFFF
#define DYN_CRLFILE_SIZE (400*1024*1024) /* 400mb */
+#define DYN_CERTFILE_SIZE (100*1024) /* 100KiB */
+#define DYN_KEYFILE_SIZE (100*1024) /* 100KiB */
#endif
diff --git a/libs/libcurl/src/inet_pton.c b/libs/libcurl/src/curlx/inet_pton.c
index 9db20c559c..0e32e129da 100644
--- a/libs/libcurl/src/inet_pton.c
+++ b/libs/libcurl/src/curlx/inet_pton.c
@@ -18,7 +18,9 @@
* SPDX-License-Identifier: ISC
*/
-#include "curl_setup.h"
+#include "../curl_setup.h"
+#include "../curl_ctype.h"
+#include "strparse.h"
#ifndef HAVE_INET_PTON
@@ -99,7 +101,6 @@ curlx_inet_pton(int af, const char *src, void *dst)
static int
inet_pton4(const char *src, unsigned char *dst)
{
- static const char digits[] = "0123456789";
int saw_digit, octets, ch;
unsigned char tmp[INADDRSZ], *tp;
@@ -108,12 +109,8 @@ inet_pton4(const char *src, unsigned char *dst)
tp = tmp;
*tp = 0;
while((ch = *src++) != '\0') {
- const char *pch;
-
- pch = strchr(digits, ch);
- if(pch) {
- unsigned int val = (unsigned int)(*tp * 10) +
- (unsigned int)(pch - digits);
+ if(ISDIGIT(ch)) {
+ unsigned int val = (*tp * 10) + (ch - '0');
if(saw_digit && *tp == 0)
return 0;
@@ -157,8 +154,6 @@ inet_pton4(const char *src, unsigned char *dst)
static int
inet_pton6(const char *src, unsigned char *dst)
{
- static const char xdigits_l[] = "0123456789abcdef",
- xdigits_u[] = "0123456789ABCDEF";
unsigned char tmp[IN6ADDRSZ], *tp, *endp, *colonp;
const char *curtok;
int ch, saw_xdigit;
@@ -175,15 +170,9 @@ inet_pton6(const char *src, unsigned char *dst)
saw_xdigit = 0;
val = 0;
while((ch = *src++) != '\0') {
- const char *xdigits;
- const char *pch;
-
- pch = strchr((xdigits = xdigits_l), ch);
- if(!pch)
- pch = strchr((xdigits = xdigits_u), ch);
- if(pch) {
+ if(ISXDIGIT(ch)) {
val <<= 4;
- val |= (pch - xdigits);
+ val |= Curl_hexval(ch);
if(++saw_xdigit > 4)
return 0;
continue;
diff --git a/libs/libcurl/src/inet_pton.h b/libs/libcurl/src/curlx/inet_pton.h
index a33c50ee3f..4e9c87922e 100644
--- a/libs/libcurl/src/inet_pton.h
+++ b/libs/libcurl/src/curlx/inet_pton.h
@@ -24,7 +24,7 @@
*
***************************************************************************/
-#include "curl_setup.h"
+#include "../curl_setup.h"
int curlx_inet_pton(int, const char *, void *);
diff --git a/libs/libcurl/src/curl_multibyte.c b/libs/libcurl/src/curlx/multibyte.c
index 2e96362b8c..3337397a56 100644
--- a/libs/libcurl/src/curl_multibyte.c
+++ b/libs/libcurl/src/curlx/multibyte.c
@@ -23,18 +23,18 @@
***************************************************************************/
/*
- * This file is 'mem-include-scan' clean, which means memdebug.h and
- * curl_memory.h are purposely not included in this file. See test 1132.
- *
- * The functions in this file are curlx functions which are not tracked by the
- * curl memory tracker memdebug.
+ * This file is 'mem-include-scan' clean, which means its memory allocations
+ * are not tracked by the curl memory tracker memdebug, so they must not use
+ * `CURLDEBUG` macro replacements in memdebug.h for free, malloc, etc. To avoid
+ * these macro replacements, wrap the names in parentheses to call the original
+ * versions: `ptr = (malloc)(123)`, `(free)(ptr)`, etc.
*/
-#include "curl_setup.h"
+#include "../curl_setup.h"
#ifdef _WIN32
-#include "curl_multibyte.h"
+#include "multibyte.h"
/*
* MultiByte conversions using Windows kernel32 library.
@@ -48,11 +48,11 @@ wchar_t *curlx_convert_UTF8_to_wchar(const char *str_utf8)
int str_w_len = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS,
str_utf8, -1, NULL, 0);
if(str_w_len > 0) {
- str_w = malloc(str_w_len * sizeof(wchar_t));
+ str_w = (malloc)(str_w_len * sizeof(wchar_t));
if(str_w) {
if(MultiByteToWideChar(CP_UTF8, 0, str_utf8, -1, str_w,
str_w_len) == 0) {
- free(str_w);
+ (free)(str_w);
return NULL;
}
}
@@ -70,11 +70,11 @@ char *curlx_convert_wchar_to_UTF8(const wchar_t *str_w)
int bytes = WideCharToMultiByte(CP_UTF8, 0, str_w, -1,
NULL, 0, NULL, NULL);
if(bytes > 0) {
- str_utf8 = malloc(bytes);
+ str_utf8 = (malloc)(bytes);
if(str_utf8) {
if(WideCharToMultiByte(CP_UTF8, 0, str_w, -1, str_utf8, bytes,
NULL, NULL) == 0) {
- free(str_utf8);
+ (free)(str_utf8);
return NULL;
}
}
@@ -136,7 +136,7 @@ static bool fix_excessive_path(const TCHAR *in, TCHAR **out)
if(needed == (size_t)-1 || needed >= max_path_len)
goto cleanup;
++needed; /* for NUL */
- ibuf = malloc(needed * sizeof(wchar_t));
+ ibuf = (malloc)(needed * sizeof(wchar_t));
if(!ibuf)
goto cleanup;
count = mbstowcs(ibuf, in, needed);
@@ -156,7 +156,7 @@ static bool fix_excessive_path(const TCHAR *in, TCHAR **out)
/* skip paths that are not excessive and do not need modification */
if(needed <= MAX_PATH)
goto cleanup;
- fbuf = malloc(needed * sizeof(wchar_t));
+ fbuf = (malloc)(needed * sizeof(wchar_t));
if(!fbuf)
goto cleanup;
count = (size_t)GetFullPathNameW(in_w, (DWORD)needed, fbuf, NULL);
@@ -189,7 +189,7 @@ static bool fix_excessive_path(const TCHAR *in, TCHAR **out)
if(needed > max_path_len)
goto cleanup;
- temp = malloc(needed * sizeof(wchar_t));
+ temp = (malloc)(needed * sizeof(wchar_t));
if(!temp)
goto cleanup;
@@ -202,7 +202,7 @@ static bool fix_excessive_path(const TCHAR *in, TCHAR **out)
if(needed > max_path_len)
goto cleanup;
- temp = malloc(needed * sizeof(wchar_t));
+ temp = (malloc)(needed * sizeof(wchar_t));
if(!temp)
goto cleanup;
@@ -210,7 +210,7 @@ static bool fix_excessive_path(const TCHAR *in, TCHAR **out)
wcscpy(temp + 4, fbuf);
}
- free(fbuf);
+ (free)(fbuf);
fbuf = temp;
}
@@ -220,7 +220,7 @@ static bool fix_excessive_path(const TCHAR *in, TCHAR **out)
if(needed == (size_t)-1 || needed >= max_path_len)
goto cleanup;
++needed; /* for NUL */
- obuf = malloc(needed);
+ obuf = (malloc)(needed);
if(!obuf)
goto cleanup;
count = wcstombs(obuf, fbuf, needed);
@@ -234,10 +234,10 @@ static bool fix_excessive_path(const TCHAR *in, TCHAR **out)
#endif
cleanup:
- free(fbuf);
+ (free)(fbuf);
#ifndef _UNICODE
- free(ibuf);
- free(obuf);
+ (free)(ibuf);
+ (free)(obuf);
#endif
return *out ? true : false;
}
@@ -276,10 +276,10 @@ int curlx_win32_open(const char *filename, int oflag, ...)
target = fixed;
else
target = filename;
- result = (_open)(target, oflag, pmode);
+ result = _open(target, oflag, pmode);
#endif
- free(fixed);
+ (free)(fixed);
return result;
}
@@ -312,7 +312,7 @@ FILE *curlx_win32_fopen(const char *filename, const char *mode)
result = (fopen)(target, mode);
#endif
- free(fixed);
+ (free)(fixed);
return result;
}
@@ -351,7 +351,7 @@ int curlx_win32_stat(const char *path, struct_stat *buffer)
#endif
#endif
- free(fixed);
+ (free)(fixed);
return result;
}
diff --git a/libs/libcurl/src/curl_multibyte.h b/libs/libcurl/src/curlx/multibyte.h
index 7c56631a07..3f8c04bb70 100644
--- a/libs/libcurl/src/curl_multibyte.h
+++ b/libs/libcurl/src/curlx/multibyte.h
@@ -23,7 +23,7 @@
* SPDX-License-Identifier: curl
*
***************************************************************************/
-#include "curl_setup.h"
+#include "../curl_setup.h"
#ifdef _WIN32
@@ -81,12 +81,7 @@ typedef union {
#endif /* UNICODE && _WIN32 */
-#define curlx_unicodefree(ptr) \
- do { \
- if(ptr) { \
- (free)(CURL_UNCONST(ptr)); \
- (ptr) = NULL; \
- } \
- } while(0)
+/* the purpose of this macro is to free() without being traced by memdebug */
+#define curlx_unicodefree(ptr) (free)(CURL_UNCONST(ptr))
#endif /* HEADER_CURL_MULTIBYTE_H */
diff --git a/libs/libcurl/src/nonblock.c b/libs/libcurl/src/curlx/nonblock.c
index f33ae8eee7..4f8153f140 100644
--- a/libs/libcurl/src/nonblock.c
+++ b/libs/libcurl/src/curlx/nonblock.c
@@ -22,7 +22,7 @@
*
***************************************************************************/
-#include "curl_setup.h"
+#include "../curl_setup.h"
#ifdef HAVE_SYS_IOCTL_H
#include <sys/ioctl.h>
diff --git a/libs/libcurl/src/nonblock.h b/libs/libcurl/src/curlx/nonblock.h
index 9834ccff01..9834ccff01 100644
--- a/libs/libcurl/src/nonblock.h
+++ b/libs/libcurl/src/curlx/nonblock.h
diff --git a/libs/libcurl/src/strparse.c b/libs/libcurl/src/curlx/strparse.c
index 2c1ec20517..b92959ec2c 100644
--- a/libs/libcurl/src/strparse.c
+++ b/libs/libcurl/src/curlx/strparse.c
@@ -23,15 +23,15 @@
***************************************************************************/
#include "strparse.h"
-#include "strcase.h"
+#include "../strcase.h"
-void Curl_str_init(struct Curl_str *out)
+void curlx_str_init(struct Curl_str *out)
{
out->str = NULL;
out->len = 0;
}
-void Curl_str_assign(struct Curl_str *out, const char *str, size_t len)
+void curlx_str_assign(struct Curl_str *out, const char *str, size_t len)
{
out->str = str;
out->len = len;
@@ -39,14 +39,14 @@ void Curl_str_assign(struct Curl_str *out, const char *str, size_t len)
/* Get a word until the first DELIM or end of string. At least one byte long.
return non-zero on error */
-int Curl_str_until(const char **linep, struct Curl_str *out,
+int curlx_str_until(const char **linep, struct Curl_str *out,
const size_t max, char delim)
{
const char *s = *linep;
size_t len = 0;
DEBUGASSERT(linep && *linep && out && max && delim);
- Curl_str_init(out);
+ curlx_str_init(out);
while(*s && (*s != delim)) {
s++;
if(++len > max) {
@@ -63,22 +63,22 @@ int Curl_str_until(const char **linep, struct Curl_str *out,
/* Get a word until the first space or end of string. At least one byte long.
return non-zero on error */
-int Curl_str_word(const char **linep, struct Curl_str *out,
+int curlx_str_word(const char **linep, struct Curl_str *out,
const size_t max)
{
- return Curl_str_until(linep, out, max, ' ');
+ return curlx_str_until(linep, out, max, ' ');
}
/* Get a word until a newline byte or end of string. At least one byte long.
return non-zero on error */
-int Curl_str_untilnl(const char **linep, struct Curl_str *out,
+int curlx_str_untilnl(const char **linep, struct Curl_str *out,
const size_t max)
{
const char *s = *linep;
size_t len = 0;
DEBUGASSERT(linep && *linep && out && max);
- Curl_str_init(out);
+ curlx_str_init(out);
while(*s && !ISNEWLINE(*s)) {
s++;
if(++len > max)
@@ -95,14 +95,14 @@ int Curl_str_untilnl(const char **linep, struct Curl_str *out,
/* Get a "quoted" word. No escaping possible.
return non-zero on error */
-int Curl_str_quotedword(const char **linep, struct Curl_str *out,
+int curlx_str_quotedword(const char **linep, struct Curl_str *out,
const size_t max)
{
const char *s = *linep;
size_t len = 0;
DEBUGASSERT(linep && *linep && out && max);
- Curl_str_init(out);
+ curlx_str_init(out);
if(*s != '\"')
return STRE_BEGQUOTE;
s++;
@@ -121,7 +121,7 @@ int Curl_str_quotedword(const char **linep, struct Curl_str *out,
/* Advance over a single character.
return non-zero on error */
-int Curl_str_single(const char **linep, char byte)
+int curlx_str_single(const char **linep, char byte)
{
DEBUGASSERT(linep && *linep);
if(**linep != byte)
@@ -132,32 +132,30 @@ int Curl_str_single(const char **linep, char byte)
/* Advance over a single space.
return non-zero on error */
-int Curl_str_singlespace(const char **linep)
+int curlx_str_singlespace(const char **linep)
{
- return Curl_str_single(linep, ' ');
+ return curlx_str_single(linep, ' ');
}
/* given an ASCII character and max ascii, return TRUE if valid */
#define valid_digit(x,m) \
- (((x) >= '0') && ((x) <= m) && hexasciitable[(x)-'0'])
+ (((x) >= '0') && ((x) <= m) && Curl_hexasciitable[(x)-'0'])
+
+/* We use 16 for the zero index (and the necessary bitwise AND in the loop)
+ to be able to have a non-zero value there to make valid_digit() able to
+ use the info */
+const unsigned char Curl_hexasciitable[] = {
+ 16, 1, 2, 3, 4, 5, 6, 7, 8, 9, /* 0x30: 0 - 9 */
+ 0, 0, 0, 0, 0, 0, 0,
+ 10, 11, 12, 13, 14, 15, /* 0x41: A - F */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 10, 11, 12, 13, 14, 15 /* 0x61: a - f */
+};
/* no support for 0x prefix nor leading spaces */
static int str_num_base(const char **linep, curl_off_t *nump, curl_off_t max,
int base) /* 8, 10 or 16, nothing else */
{
- /* We use 16 for the zero index (and the necessary bitwise AND in the loop)
- to be able to have a non-zero value there to make valid_digit() able to
- use the info */
- static const unsigned char hexasciitable[] = {
- 16, 1, 2, 3, 4, 5, 6, 7, 8, 9, /* 0x30: 0 - 9 */
- 0, 0, 0, 0, 0, 0, 0,
- 10, 11, 12, 13, 14, 15, /* 0x41: A - F */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0,
- 10, 11, 12, 13, 14, 15 /* 0x61: a - f */
- };
-
curl_off_t num = 0;
const char *p;
int m = (base == 10) ? '9' : /* the largest digit possible */
@@ -172,7 +170,7 @@ static int str_num_base(const char **linep, curl_off_t *nump, curl_off_t max,
if(max < base) {
/* special-case low max scenario because check needs to be different */
do {
- int n = hexasciitable[*p++ - '0'] & 0x0f;
+ int n = Curl_hexval(*p++);
num = num * base + n;
if(num > max)
return STRE_OVERFLOW;
@@ -180,7 +178,7 @@ static int str_num_base(const char **linep, curl_off_t *nump, curl_off_t max,
}
else {
do {
- int n = hexasciitable[*p++ - '0'] & 0x0f;
+ int n = Curl_hexval(*p++);
if(num > ((max - n) / base))
return STRE_OVERFLOW;
num = num * base + n;
@@ -193,21 +191,21 @@ static int str_num_base(const char **linep, curl_off_t *nump, curl_off_t max,
/* Get an unsigned decimal number with no leading space or minus. Leading
zeroes are accepted. return non-zero on error */
-int Curl_str_number(const char **linep, curl_off_t *nump, curl_off_t max)
+int curlx_str_number(const char **linep, curl_off_t *nump, curl_off_t max)
{
return str_num_base(linep, nump, max, 10);
}
/* Get an unsigned hexadecimal number with no leading space or minus and no
"0x" support. Leading zeroes are accepted. return non-zero on error */
-int Curl_str_hex(const char **linep, curl_off_t *nump, curl_off_t max)
+int curlx_str_hex(const char **linep, curl_off_t *nump, curl_off_t max)
{
return str_num_base(linep, nump, max, 16);
}
/* Get an unsigned octal number with no leading space or minus and no "0"
prefix support. Leading zeroes are accepted. return non-zero on error */
-int Curl_str_octal(const char **linep, curl_off_t *nump, curl_off_t max)
+int curlx_str_octal(const char **linep, curl_off_t *nump, curl_off_t max)
{
return str_num_base(linep, nump, max, 8);
}
@@ -216,15 +214,15 @@ int Curl_str_octal(const char **linep, curl_off_t *nump, curl_off_t max)
* Parse a positive number up to 63-bit number written in ASCII. Skip leading
* blanks. No support for prefixes.
*/
-int Curl_str_numblanks(const char **str, curl_off_t *num)
+int curlx_str_numblanks(const char **str, curl_off_t *num)
{
- Curl_str_passblanks(str);
- return Curl_str_number(str, num, CURL_OFF_T_MAX);
+ curlx_str_passblanks(str);
+ return curlx_str_number(str, num, CURL_OFF_T_MAX);
}
/* CR or LF
return non-zero on error */
-int Curl_str_newline(const char **linep)
+int curlx_str_newline(const char **linep)
{
DEBUGASSERT(linep && *linep);
if(ISNEWLINE(**linep)) {
@@ -234,16 +232,18 @@ int Curl_str_newline(const char **linep)
return STRE_NEWLINE;
}
-/* case insensitive compare that the parsed string matches the
- given string. Returns non-zero on match. */
-int Curl_str_casecompare(struct Curl_str *str, const char *check)
+#ifndef WITHOUT_LIBCURL
+/* case insensitive compare that the parsed string matches the given string.
+ Returns non-zero on match. */
+int curlx_str_casecompare(struct Curl_str *str, const char *check)
{
size_t clen = check ? strlen(check) : 0;
return ((str->len == clen) && strncasecompare(str->str, check, clen));
}
+#endif
/* case sensitive string compare. Returns non-zero on match. */
-int Curl_str_cmp(struct Curl_str *str, const char *check)
+int curlx_str_cmp(struct Curl_str *str, const char *check)
{
if(check) {
size_t clen = strlen(check);
@@ -254,7 +254,7 @@ int Curl_str_cmp(struct Curl_str *str, const char *check)
/* Trim off 'num' number of bytes from the beginning (left side) of the
string. If 'num' is larger than the string, return error. */
-int Curl_str_nudge(struct Curl_str *str, size_t num)
+int curlx_str_nudge(struct Curl_str *str, size_t num)
{
if(num <= str->len) {
str->str += num;
@@ -266,7 +266,8 @@ int Curl_str_nudge(struct Curl_str *str, size_t num)
/* Get the following character sequence that consists only of bytes not
present in the 'reject' string. Like strcspn(). */
-int Curl_str_cspn(const char **linep, struct Curl_str *out, const char *reject)
+int curlx_str_cspn(const char **linep, struct Curl_str *out,
+ const char *reject)
{
const char *s = *linep;
size_t len;
@@ -279,15 +280,15 @@ int Curl_str_cspn(const char **linep, struct Curl_str *out, const char *reject)
*linep = &s[len];
return STRE_OK;
}
- Curl_str_init(out);
+ curlx_str_init(out);
return STRE_SHORT;
}
/* remove ISBLANK()s from both ends of the string */
-void Curl_str_trimblanks(struct Curl_str *out)
+void curlx_str_trimblanks(struct Curl_str *out)
{
while(out->len && ISBLANK(*out->str))
- Curl_str_nudge(out, 1);
+ curlx_str_nudge(out, 1);
/* trim trailing spaces and tabs */
while(out->len && ISBLANK(out->str[out->len - 1]))
@@ -295,7 +296,7 @@ void Curl_str_trimblanks(struct Curl_str *out)
}
/* increase the pointer until it has moved over all blanks */
-void Curl_str_passblanks(const char **linep)
+void curlx_str_passblanks(const char **linep)
{
while(ISBLANK(**linep))
(*linep)++; /* move over it */
diff --git a/libs/libcurl/src/strparse.h b/libs/libcurl/src/curlx/strparse.h
index 01c696c277..585e058872 100644
--- a/libs/libcurl/src/strparse.h
+++ b/libs/libcurl/src/curlx/strparse.h
@@ -23,7 +23,7 @@
* SPDX-License-Identifier: curl
*
***************************************************************************/
-#include "curl_setup.h"
+#include "../curl_setup.h"
#define STRE_OK 0
#define STRE_BIG 1
@@ -42,70 +42,71 @@ struct Curl_str {
size_t len;
};
-void Curl_str_init(struct Curl_str *out);
-void Curl_str_assign(struct Curl_str *out, const char *str, size_t len);
+void curlx_str_init(struct Curl_str *out);
+void curlx_str_assign(struct Curl_str *out, const char *str, size_t len);
-#define Curl_str(x) ((x)->str)
-#define Curl_strlen(x) ((x)->len)
+#define curlx_str(x) ((x)->str)
+#define curlx_strlen(x) ((x)->len)
/* Get a word until the first space
return non-zero on error */
-int Curl_str_word(const char **linep, struct Curl_str *out, const size_t max);
+int curlx_str_word(const char **linep, struct Curl_str *out, const size_t max);
/* Get a word until the first DELIM or end of string
return non-zero on error */
-int Curl_str_until(const char **linep, struct Curl_str *out, const size_t max,
+int curlx_str_until(const char **linep, struct Curl_str *out, const size_t max,
char delim);
/* Get a word until a newline byte or end of string. At least one byte long.
return non-zero on error */
-int Curl_str_untilnl(const char **linep, struct Curl_str *out,
+int curlx_str_untilnl(const char **linep, struct Curl_str *out,
const size_t max);
/* Get a "quoted" word. No escaping possible.
return non-zero on error */
-int Curl_str_quotedword(const char **linep, struct Curl_str *out,
+int curlx_str_quotedword(const char **linep, struct Curl_str *out,
const size_t max);
/* Advance over a single character.
return non-zero on error */
-int Curl_str_single(const char **linep, char byte);
+int curlx_str_single(const char **linep, char byte);
/* Advance over a single space.
return non-zero on error */
-int Curl_str_singlespace(const char **linep);
+int curlx_str_singlespace(const char **linep);
/* Get an unsigned decimal number. Return non-zero on error */
-int Curl_str_number(const char **linep, curl_off_t *nump, curl_off_t max);
+int curlx_str_number(const char **linep, curl_off_t *nump, curl_off_t max);
/* As above with CURL_OFF_T_MAX but also pass leading blanks */
-int Curl_str_numblanks(const char **str, curl_off_t *num);
+int curlx_str_numblanks(const char **str, curl_off_t *num);
/* Get an unsigned hexadecimal number. Return non-zero on error */
-int Curl_str_hex(const char **linep, curl_off_t *nump, curl_off_t max);
+int curlx_str_hex(const char **linep, curl_off_t *nump, curl_off_t max);
/* Get an unsigned octal number. Return non-zero on error */
-int Curl_str_octal(const char **linep, curl_off_t *nump, curl_off_t max);
+int curlx_str_octal(const char **linep, curl_off_t *nump, curl_off_t max);
/* Check for CR or LF
return non-zero on error */
-int Curl_str_newline(const char **linep);
+int curlx_str_newline(const char **linep);
/* case insensitive compare that the parsed string matches the
given string. */
-int Curl_str_casecompare(struct Curl_str *str, const char *check);
-int Curl_str_cmp(struct Curl_str *str, const char *check);
+int curlx_str_casecompare(struct Curl_str *str, const char *check);
+int curlx_str_cmp(struct Curl_str *str, const char *check);
-int Curl_str_nudge(struct Curl_str *str, size_t num);
+int curlx_str_nudge(struct Curl_str *str, size_t num);
-int Curl_str_cspn(const char **linep, struct Curl_str *out, const char *cspn);
-void Curl_str_trimblanks(struct Curl_str *out);
-void Curl_str_passblanks(const char **linep);
+int curlx_str_cspn(const char **linep, struct Curl_str *out, const char *cspn);
+void curlx_str_trimblanks(struct Curl_str *out);
+void curlx_str_passblanks(const char **linep);
-#define curlx_str_number(x,y,z) Curl_str_number(x,y,z)
-#define curlx_str_octal(x,y,z) Curl_str_octal(x,y,z)
-#define curlx_str_single(x,y) Curl_str_single(x,y)
-#define curlx_str_passblanks(x) Curl_str_passblanks(x)
-#define curlx_str_numblanks(x,y) Curl_str_numblanks(x,y)
+/* given a hexadecimal letter, return the binary value. '0' returns 0, 'a'
+ returns 10. THIS ONLY WORKS ON VALID HEXADECIMAL LETTER INPUT. Verify
+ before calling this!
+*/
+extern const unsigned char Curl_hexasciitable[];
+#define Curl_hexval(x) (unsigned char)(Curl_hexasciitable[(x) - '0'] & 0x0f)
#endif /* HEADER_CURL_STRPARSE_H */
diff --git a/libs/libcurl/src/timediff.c b/libs/libcurl/src/curlx/timediff.c
index 641a15c404..641a15c404 100644
--- a/libs/libcurl/src/timediff.c
+++ b/libs/libcurl/src/curlx/timediff.c
diff --git a/libs/libcurl/src/timediff.h b/libs/libcurl/src/curlx/timediff.h
index d24e01803c..9a8f695982 100644
--- a/libs/libcurl/src/timediff.h
+++ b/libs/libcurl/src/curlx/timediff.h
@@ -24,7 +24,7 @@
*
***************************************************************************/
-#include "curl_setup.h"
+#include "../curl_setup.h"
/* Use a larger type even for 32-bit time_t systems so that we can keep
microsecond accuracy in it */
diff --git a/libs/libcurl/src/timeval.c b/libs/libcurl/src/curlx/timeval.c
index 582bf09344..e6739b50b3 100644
--- a/libs/libcurl/src/timeval.c
+++ b/libs/libcurl/src/curlx/timeval.c
@@ -27,45 +27,35 @@
#ifdef _WIN32
#include <curl/curl.h>
-#ifdef BUILDING_LIBCURL
-#include "system_win32.h"
-#else
#include "version_win32.h"
+#include "../system_win32.h"
-static LARGE_INTEGER s_freq;
-static bool s_isVistaOrGreater;
+LARGE_INTEGER Curl_freq;
+bool Curl_isVistaOrGreater;
-/* For tool or tests, we must initialize before calling Curl_now() */
+/* For tool or tests, we must initialize before calling curlx_now().
+ Providing this function here is wrong. */
void curlx_now_init(void)
{
if(curlx_verify_windows_version(6, 0, 0, PLATFORM_WINNT,
VERSION_GREATER_THAN_EQUAL))
- s_isVistaOrGreater = true;
+ Curl_isVistaOrGreater = true;
else
- s_isVistaOrGreater = false;
+ Curl_isVistaOrGreater = false;
- QueryPerformanceFrequency(&s_freq);
+ QueryPerformanceFrequency(&Curl_freq);
}
-#endif
/* In case of bug fix this function has a counterpart in tool_util.c */
-struct curltime Curl_now(void)
+struct curltime curlx_now(void)
{
struct curltime now;
bool isVistaOrGreater;
-#ifdef BUILDING_LIBCURL
isVistaOrGreater = Curl_isVistaOrGreater;
-#else
- isVistaOrGreater = s_isVistaOrGreater;
-#endif
if(isVistaOrGreater) { /* QPC timer might have issues pre-Vista */
LARGE_INTEGER count;
LARGE_INTEGER freq;
-#ifdef BUILDING_LIBCURL
freq = Curl_freq;
-#else
- freq = s_freq;
-#endif
DEBUGASSERT(freq.QuadPart);
QueryPerformanceCounter(&count);
now.tv_sec = (time_t)(count.QuadPart / freq.QuadPart);
@@ -92,7 +82,7 @@ struct curltime Curl_now(void)
#elif defined(HAVE_CLOCK_GETTIME_MONOTONIC) || \
defined(HAVE_CLOCK_GETTIME_MONOTONIC_RAW)
-struct curltime Curl_now(void)
+struct curltime curlx_now(void)
{
/*
** clock_gettime() is granted to be increased monotonically when the
@@ -166,7 +156,7 @@ struct curltime Curl_now(void)
#include <stdint.h>
#include <mach/mach_time.h>
-struct curltime Curl_now(void)
+struct curltime curlx_now(void)
{
/*
** Monotonic timer on macOS is provided by mach_absolute_time(), which
@@ -194,7 +184,7 @@ struct curltime Curl_now(void)
#elif defined(HAVE_GETTIMEOFDAY)
-struct curltime Curl_now(void)
+struct curltime curlx_now(void)
{
/*
** gettimeofday() is not granted to be increased monotonically, due to
@@ -211,7 +201,7 @@ struct curltime Curl_now(void)
#else
-struct curltime Curl_now(void)
+struct curltime curlx_now(void)
{
/*
** time() returns the value of time in seconds since the Epoch.
@@ -230,7 +220,7 @@ struct curltime Curl_now(void)
*
* @unittest: 1323
*/
-timediff_t Curl_timediff(struct curltime newer, struct curltime older)
+timediff_t curlx_timediff(struct curltime newer, struct curltime older)
{
timediff_t diff = (timediff_t)newer.tv_sec-older.tv_sec;
if(diff >= (TIMEDIFF_T_MAX/1000))
@@ -244,7 +234,7 @@ timediff_t Curl_timediff(struct curltime newer, struct curltime older)
* Returns: time difference in number of milliseconds, rounded up.
* For too large diffs it returns max value.
*/
-timediff_t Curl_timediff_ceil(struct curltime newer, struct curltime older)
+timediff_t curlx_timediff_ceil(struct curltime newer, struct curltime older)
{
timediff_t diff = (timediff_t)newer.tv_sec-older.tv_sec;
if(diff >= (TIMEDIFF_T_MAX/1000))
@@ -258,7 +248,7 @@ timediff_t Curl_timediff_ceil(struct curltime newer, struct curltime older)
* Returns: time difference in number of microseconds. For too large diffs it
* returns max value.
*/
-timediff_t Curl_timediff_us(struct curltime newer, struct curltime older)
+timediff_t curlx_timediff_us(struct curltime newer, struct curltime older)
{
timediff_t diff = (timediff_t)newer.tv_sec-older.tv_sec;
if(diff >= (TIMEDIFF_T_MAX/1000000))
diff --git a/libs/libcurl/src/timeval.h b/libs/libcurl/src/curlx/timeval.h
index b610f51935..8e34a07967 100644
--- a/libs/libcurl/src/timeval.h
+++ b/libs/libcurl/src/curlx/timeval.h
@@ -24,28 +24,21 @@
*
***************************************************************************/
-#include "curl_setup.h"
+#include "../curl_setup.h"
#include "timediff.h"
-#ifndef BUILDING_LIBCURL
-/* this renames the functions so that the tool code can use the same code
- without getting symbol collisions */
-#define Curl_now curlx_now
-#define Curl_timediff(a,b) curlx_timediff(a,b)
-#define Curl_timediff_ceil(a,b) curlx_timediff_ceil(a,b)
-#define Curl_timediff_us(a,b) curlx_timediff_us(a,b)
-
-/* For tool or tests, we must initialize before calling Curl_now() */
-void curlx_now_init(void);
-#endif
-
struct curltime {
time_t tv_sec; /* seconds */
int tv_usec; /* microseconds */
};
-struct curltime Curl_now(void);
+#ifdef _WIN32
+/* For tool or tests, we must initialize before calling curlx_now() */
+void curlx_now_init(void);
+#endif
+
+struct curltime curlx_now(void);
/*
* Make sure that the first argument (newer) is the more recent time and older
@@ -53,7 +46,7 @@ struct curltime Curl_now(void);
*
* Returns: the time difference in number of milliseconds.
*/
-timediff_t Curl_timediff(struct curltime newer, struct curltime older);
+timediff_t curlx_timediff(struct curltime newer, struct curltime older);
/*
* Make sure that the first argument (newer) is the more recent time and older
@@ -61,7 +54,7 @@ timediff_t Curl_timediff(struct curltime newer, struct curltime older);
*
* Returns: the time difference in number of milliseconds, rounded up.
*/
-timediff_t Curl_timediff_ceil(struct curltime newer, struct curltime older);
+timediff_t curlx_timediff_ceil(struct curltime newer, struct curltime older);
/*
* Make sure that the first argument (newer) is the more recent time and older
@@ -69,6 +62,6 @@ timediff_t Curl_timediff_ceil(struct curltime newer, struct curltime older);
*
* Returns: the time difference in number of microseconds.
*/
-timediff_t Curl_timediff_us(struct curltime newer, struct curltime older);
+timediff_t curlx_timediff_us(struct curltime newer, struct curltime older);
#endif /* HEADER_CURL_TIMEVAL_H */
diff --git a/libs/libcurl/src/version_win32.c b/libs/libcurl/src/curlx/version_win32.c
index 40eb5dff33..54c02bdfe0 100644
--- a/libs/libcurl/src/version_win32.c
+++ b/libs/libcurl/src/curlx/version_win32.c
@@ -22,7 +22,7 @@
*
***************************************************************************/
-#include "curl_setup.h"
+#include "../curl_setup.h"
#ifdef _WIN32
@@ -31,10 +31,8 @@
#include "warnless.h"
/* The last 2 #include files should be in this order */
-#ifdef BUILDING_LIBCURL
-#include "curl_memory.h"
-#endif
-#include "memdebug.h"
+#include "../curl_memory.h"
+#include "../memdebug.h"
/* This Unicode version struct works for VerifyVersionInfoW (OSVERSIONINFOEXW)
and RtlVerifyVersionInfo (RTLOSVERSIONINFOEXW) */
diff --git a/libs/libcurl/src/version_win32.h b/libs/libcurl/src/curlx/version_win32.h
index 10ebe37783..0a9aa9b2e0 100644
--- a/libs/libcurl/src/version_win32.h
+++ b/libs/libcurl/src/curlx/version_win32.h
@@ -24,7 +24,7 @@
*
***************************************************************************/
-#include "curl_setup.h"
+#include "../curl_setup.h"
#ifdef _WIN32
diff --git a/libs/libcurl/src/warnless.c b/libs/libcurl/src/curlx/warnless.c
index 32cca52de7..de43a2c17b 100644
--- a/libs/libcurl/src/warnless.c
+++ b/libs/libcurl/src/curlx/warnless.c
@@ -22,7 +22,7 @@
*
***************************************************************************/
-#include "curl_setup.h"
+#include "warnless.h"
#if defined(__INTEL_COMPILER) && defined(__unix__)
@@ -35,8 +35,6 @@
#endif /* __INTEL_COMPILER && __unix__ */
-#include "warnless.h"
-
#ifdef _WIN32
#undef read
#undef write
diff --git a/libs/libcurl/src/warnless.h b/libs/libcurl/src/curlx/warnless.h
index 630d6ccb1b..e995a3c9d3 100644
--- a/libs/libcurl/src/warnless.h
+++ b/libs/libcurl/src/curlx/warnless.h
@@ -24,7 +24,7 @@
*
***************************************************************************/
-#include "curl_setup.h"
+#include "../curl_setup.h"
#ifdef USE_WINSOCK
#include <curl/curl.h> /* for curl_socket_t */
diff --git a/libs/libcurl/src/curlx/winapi.c b/libs/libcurl/src/curlx/winapi.c
new file mode 100644
index 0000000000..60eddc23f2
--- /dev/null
+++ b/libs/libcurl/src/curlx/winapi.c
@@ -0,0 +1,135 @@
+/***************************************************************************
+ * _ _ ____ _
+ * 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"
+
+/*
+ * curlx_winapi_strerror:
+ * Variant of Curl_strerror if the error code is definitely Windows API.
+ */
+#ifdef _WIN32
+#include "winapi.h"
+
+#ifdef BUILDING_LIBCURL
+#include <curl/mprintf.h>
+#define SNPRINTF curl_msnprintf
+#else
+/* when built for the test servers */
+
+/* adjust for old MSVC */
+#if defined(_MSC_VER) && (_MSC_VER < 1900)
+# define SNPRINTF _snprintf
+#else
+#define SNPRINTF snprintf
+#endif
+
+#endif /* !BUILDING_LIBCURL */
+
+#ifdef _WIN32
+/* This is a helper function for Curl_strerror that converts Windows API error
+ * codes (GetLastError) to error messages.
+ * Returns NULL if no error message was found for error code.
+ */
+const char *curlx_get_winapi_error(int err, char *buf, size_t buflen)
+{
+ char *p;
+ wchar_t wbuf[256];
+
+ if(!buflen)
+ return NULL;
+
+ *buf = '\0';
+ *wbuf = L'\0';
+
+ /* We return the local codepage version of the error string because if it is
+ output to the user's terminal it will likely be with functions which
+ expect the local codepage (eg fprintf, failf, infof).
+ FormatMessageW -> wcstombs is used for Windows CE compatibility. */
+ if(FormatMessageW((FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS), NULL, (DWORD)err,
+ LANG_NEUTRAL, wbuf, CURL_ARRAYSIZE(wbuf), NULL)) {
+ size_t written = wcstombs(buf, wbuf, buflen - 1);
+ if(written != (size_t)-1)
+ buf[written] = '\0';
+ else
+ *buf = '\0';
+ }
+
+ /* Truncate multiple lines */
+ p = strchr(buf, '\n');
+ if(p) {
+ if(p > buf && *(p-1) == '\r')
+ *(p-1) = '\0';
+ else
+ *p = '\0';
+ }
+
+ return *buf ? buf : NULL;
+}
+#endif /* _WIN32 */
+
+const char *curlx_winapi_strerror(DWORD err, char *buf, size_t buflen)
+{
+#ifdef _WIN32
+ DWORD old_win_err = GetLastError();
+#endif
+ int old_errno = errno;
+
+ if(!buflen)
+ return NULL;
+
+ *buf = '\0';
+
+#ifndef CURL_DISABLE_VERBOSE_STRINGS
+ if(!curlx_get_winapi_error((int)err, buf, buflen)) {
+#if defined(__GNUC__) && __GNUC__ >= 7
+#pragma GCC diagnostic push
+#pragma GCC diagnostic warning "-Wformat-truncation=1"
+#endif
+ /* some GCC compilers cause false positive warnings if we allow this
+ warning */
+ SNPRINTF(buf, buflen, "Unknown error %lu (0x%08lX)", err, err);
+#if defined(__GNUC__) && __GNUC__ >= 7
+#pragma GCC diagnostic pop
+#endif
+
+ }
+#else
+ {
+ const char *txt = (err == ERROR_SUCCESS) ? "No error" : "Error";
+ if(strlen(txt) < buflen)
+ strcpy(buf, txt);
+ }
+#endif
+
+ if(errno != old_errno)
+ CURL_SETERRNO(old_errno);
+
+#ifdef _WIN32
+ if(old_win_err != GetLastError())
+ SetLastError(old_win_err);
+#endif
+
+ return buf;
+}
+#endif /* _WIN32 */
diff --git a/libs/libcurl/src/curlx/winapi.h b/libs/libcurl/src/curlx/winapi.h
new file mode 100644
index 0000000000..65425b9a0f
--- /dev/null
+++ b/libs/libcurl/src/curlx/winapi.h
@@ -0,0 +1,33 @@
+#ifndef HEADER_CURLX_WINAPI_H
+#define HEADER_CURLX_WINAPI_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+
+#ifdef _WIN32
+#define WINAPI_ERROR_LEN 100
+const char *curlx_get_winapi_error(int err, char *buf, size_t buflen);
+const char *curlx_winapi_strerror(DWORD err, char *buf, size_t buflen);
+#endif
+
+#endif /* HEADER_CURLX_WINAPI_H */
diff --git a/libs/libcurl/src/cw-out.c b/libs/libcurl/src/cw-out.c
index 213a0c20a6..6f897ec376 100644
--- a/libs/libcurl/src/cw-out.c
+++ b/libs/libcurl/src/cw-out.c
@@ -87,7 +87,7 @@ static struct cw_out_buf *cw_out_buf_create(cw_out_type otype)
struct cw_out_buf *cwbuf = calloc(1, sizeof(*cwbuf));
if(cwbuf) {
cwbuf->type = otype;
- Curl_dyn_init(&cwbuf->b, DYN_PAUSE_BUFFER);
+ curlx_dyn_init(&cwbuf->b, DYN_PAUSE_BUFFER);
}
return cwbuf;
}
@@ -95,7 +95,7 @@ static struct cw_out_buf *cw_out_buf_create(cw_out_type otype)
static void cw_out_buf_free(struct cw_out_buf *cwbuf)
{
if(cwbuf) {
- Curl_dyn_free(&cwbuf->b);
+ curlx_dyn_free(&cwbuf->b);
free(cwbuf);
}
}
@@ -114,7 +114,7 @@ static void cw_out_close(struct Curl_easy *data, struct Curl_cwriter *writer);
static CURLcode cw_out_init(struct Curl_easy *data,
struct Curl_cwriter *writer);
-struct Curl_cwtype Curl_cwt_out = {
+const struct Curl_cwtype Curl_cwt_out = {
"cw-out",
NULL,
cw_out_init,
@@ -146,7 +146,7 @@ static size_t cw_out_bufs_len(struct cw_out_ctx *ctx)
struct cw_out_buf *cwbuf = ctx->buf;
size_t len = 0;
while(cwbuf) {
- len += Curl_dyn_len(&cwbuf->b);
+ len += curlx_dyn_len(&cwbuf->b);
cwbuf = cwbuf->next;
}
return len;
@@ -263,23 +263,24 @@ static CURLcode cw_out_buf_flush(struct cw_out_ctx *ctx,
{
CURLcode result = CURLE_OK;
- if(Curl_dyn_len(&cwbuf->b)) {
+ if(curlx_dyn_len(&cwbuf->b)) {
size_t consumed;
result = cw_out_ptr_flush(ctx, data, cwbuf->type, flush_all,
- Curl_dyn_ptr(&cwbuf->b),
- Curl_dyn_len(&cwbuf->b),
+ curlx_dyn_ptr(&cwbuf->b),
+ curlx_dyn_len(&cwbuf->b),
&consumed);
if(result)
return result;
if(consumed) {
- if(consumed == Curl_dyn_len(&cwbuf->b)) {
- Curl_dyn_free(&cwbuf->b);
+ if(consumed == curlx_dyn_len(&cwbuf->b)) {
+ curlx_dyn_free(&cwbuf->b);
}
else {
- DEBUGASSERT(consumed < Curl_dyn_len(&cwbuf->b));
- result = Curl_dyn_tail(&cwbuf->b, Curl_dyn_len(&cwbuf->b) - consumed);
+ DEBUGASSERT(consumed < curlx_dyn_len(&cwbuf->b));
+ result = curlx_dyn_tail(&cwbuf->b,
+ curlx_dyn_len(&cwbuf->b) - consumed);
if(result)
return result;
}
@@ -319,7 +320,7 @@ static CURLcode cw_out_flush_chain(struct cw_out_ctx *ctx,
result = cw_out_buf_flush(ctx, data, cwbuf, flush_all);
if(result)
return result;
- if(!Curl_dyn_len(&cwbuf->b)) {
+ if(!curlx_dyn_len(&cwbuf->b)) {
cw_out_buf_free(cwbuf);
*pcwbuf = NULL;
}
@@ -349,7 +350,7 @@ static CURLcode cw_out_append(struct cw_out_ctx *ctx,
ctx->buf = cwbuf;
}
DEBUGASSERT(ctx->buf && (ctx->buf->type == otype));
- return Curl_dyn_addn(&ctx->buf->b, buf, blen);
+ return curlx_dyn_addn(&ctx->buf->b, buf, blen);
}
static CURLcode cw_out_do_write(struct cw_out_ctx *ctx,
diff --git a/libs/libcurl/src/cw-out.h b/libs/libcurl/src/cw-out.h
index e5afe097a0..ecab9e50b5 100644
--- a/libs/libcurl/src/cw-out.h
+++ b/libs/libcurl/src/cw-out.h
@@ -33,7 +33,7 @@
* the client callbacks. Intended to be the last installed in the
* client writer stack of a transfer.
*/
-extern struct Curl_cwtype Curl_cwt_out;
+extern const struct Curl_cwtype Curl_cwt_out;
/**
* Return TRUE iff 'cw-out' client write has paused data.
diff --git a/libs/libcurl/src/cw-pause.c b/libs/libcurl/src/cw-pause.c
index 7bb6b3b0fd..8df2a32059 100644
--- a/libs/libcurl/src/cw-pause.c
+++ b/libs/libcurl/src/cw-pause.c
@@ -87,7 +87,7 @@ static void cw_pause_close(struct Curl_easy *data,
static CURLcode cw_pause_init(struct Curl_easy *data,
struct Curl_cwriter *writer);
-struct Curl_cwtype Curl_cwt_pause = {
+const struct Curl_cwtype Curl_cwt_pause = {
"cw-pause",
NULL,
cw_pause_init,
diff --git a/libs/libcurl/src/cw-pause.h b/libs/libcurl/src/cw-pause.h
index c514b1029f..4bcf656a41 100644
--- a/libs/libcurl/src/cw-pause.h
+++ b/libs/libcurl/src/cw-pause.h
@@ -32,7 +32,7 @@
* The client writer type "cw-pause" that buffers writes for
* paused transfer writes.
*/
-extern struct Curl_cwtype Curl_cwt_pause;
+extern const struct Curl_cwtype Curl_cwt_pause;
CURLcode Curl_cw_pause_flush(struct Curl_easy *data);
diff --git a/libs/libcurl/src/dict.c b/libs/libcurl/src/dict.c
index dc849df1a8..851514708a 100644
--- a/libs/libcurl/src/dict.c
+++ b/libs/libcurl/src/dict.c
@@ -65,6 +65,15 @@
/* The last #include file should be: */
#include "memdebug.h"
+
+#define DICT_MATCH "/MATCH:"
+#define DICT_MATCH2 "/M:"
+#define DICT_MATCH3 "/FIND:"
+#define DICT_DEFINE "/DEFINE:"
+#define DICT_DEFINE2 "/D:"
+#define DICT_DEFINE3 "/LOOKUP:"
+
+
/*
* Forward declarations.
*/
@@ -106,7 +115,7 @@ static char *unescape_word(const char *input)
struct dynbuf out;
const char *ptr;
CURLcode result = CURLE_OK;
- Curl_dyn_init(&out, DYN_DICT_WORD);
+ curlx_dyn_init(&out, DYN_DICT_WORD);
/* According to RFC2229 section 2.2, these letters need to be escaped with
\[letter] */
@@ -114,13 +123,13 @@ static char *unescape_word(const char *input)
char ch = *ptr;
if((ch <= 32) || (ch == 127) ||
(ch == '\'') || (ch == '\"') || (ch == '\\'))
- result = Curl_dyn_addn(&out, "\\", 1);
+ result = curlx_dyn_addn(&out, "\\", 1);
if(!result)
- result = Curl_dyn_addn(&out, ptr, 1);
+ result = curlx_dyn_addn(&out, ptr, 1);
if(result)
return NULL;
}
- return Curl_dyn_ptr(&out);
+ return curlx_dyn_ptr(&out);
}
/* sendf() sends formatted data to the server */
diff --git a/libs/libcurl/src/doh.c b/libs/libcurl/src/doh.c
index 9dd8283a1d..693d96bc0f 100644
--- a/libs/libcurl/src/doh.c
+++ b/libs/libcurl/src/doh.c
@@ -34,15 +34,17 @@
#include "multiif.h"
#include "url.h"
#include "share.h"
-#include "curl_base64.h"
+#include "curlx/base64.h"
#include "connect.h"
#include "strdup.h"
-#include "dynbuf.h"
+#include "curlx/dynbuf.h"
+#include "escape.h"
+#include "urlapi-int.h"
+
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h"
#include "memdebug.h"
-#include "escape.h"
#define DNS_CLASS_IN 0x01
@@ -113,7 +115,7 @@ UNITTEST DOHcode doh_req_encode(const char *host,
if(host[hostlen-1]!='.')
expected_len++;
- if(expected_len > (256 + 16)) /* RFCs 1034, 1035 */
+ if(expected_len > DOH_MAX_DNSREQ_SIZE)
return DOH_DNS_NAME_TOO_LONG;
if(len < expected_len)
@@ -173,12 +175,15 @@ UNITTEST DOHcode doh_req_encode(const char *host,
}
static size_t
-doh_write_cb(char *contents, size_t size, size_t nmemb, void *userp)
+doh_probe_write_cb(char *contents, size_t size, size_t nmemb, void *userp)
{
size_t realsize = size * nmemb;
- struct dynbuf *mem = (struct dynbuf *)userp;
+ struct Curl_easy *data = userp;
+ struct doh_request *doh_req = Curl_meta_get(data, CURL_EZM_DOH_PROBE);
+ if(!doh_req)
+ return CURL_WRITEFUNC_ERROR;
- if(Curl_dyn_addn(mem, contents, realsize))
+ if(curlx_dyn_addn(&doh_req->resp_body, contents, realsize))
return 0;
return realsize;
@@ -208,22 +213,45 @@ static void doh_print_buf(struct Curl_easy *data,
}
#endif
-/* called from multi.c when this DoH transfer is complete */
-static int doh_done(struct Curl_easy *doh, CURLcode result)
+/* called from multi when a sub transfer, e.g. doh probe, is done.
+ * This looks up the the probe response at its meta CURL_EZM_DOH_PROBE
+ * and copies the response body over to the struct at the master's
+ * meta at CURL_EZM_DOH_MASTER. */
+static void doh_probe_done(struct Curl_easy *data,
+ struct Curl_easy *doh, CURLcode result)
{
- struct Curl_easy *data; /* the transfer that asked for the DoH probe */
+ struct doh_probes *dohp = data->state.async.doh;
+ DEBUGASSERT(dohp);
+ if(dohp) {
+ struct doh_request *doh_req = Curl_meta_get(doh, CURL_EZM_DOH_PROBE);
+ int i;
+
+ for(i = 0; i < DOH_SLOT_COUNT; ++i) {
+ if(dohp->probe_resp[i].probe_mid == doh->mid)
+ break;
+ }
+ if(i >= DOH_SLOT_COUNT) {
+ failf(data, "unknown sub request done");
+ return;
+ }
- data = Curl_multi_get_handle(doh->multi, doh->set.dohfor_mid);
- if(!data) {
- DEBUGF(infof(doh, "doh_done: xfer for mid=%" FMT_OFF_T
- " not found", doh->set.dohfor_mid));
- DEBUGASSERT(0);
- }
- else {
- struct doh_probes *dohp = data->req.doh;
- /* one of the DoH request done for the 'data' transfer is now complete! */
dohp->pending--;
infof(doh, "a DoH request is completed, %u to go", dohp->pending);
+ dohp->probe_resp[i].result = result;
+ /* We expect either the meta data still to exist or the sub request
+ * to have already failed. */
+ DEBUGASSERT(doh_req || result);
+ if(doh_req) {
+ if(!result) {
+ dohp->probe_resp[i].dnstype = doh_req->dnstype;
+ result = curlx_dyn_addn(&dohp->probe_resp[i].body,
+ curlx_dyn_ptr(&doh_req->resp_body),
+ curlx_dyn_len(&doh_req->resp_body));
+ curlx_dyn_free(&doh_req->resp_body);
+ }
+ Curl_meta_remove(doh, CURL_EZM_DOH_PROBE);
+ }
+
if(result)
infof(doh, "DoH request %s", curl_easy_strerror(result));
@@ -232,7 +260,18 @@ static int doh_done(struct Curl_easy *doh, CURLcode result)
Curl_expire(data, 0, EXPIRE_RUN_NOW);
}
}
- return 0;
+}
+
+static void doh_probe_dtor(void *key, size_t klen, void *e)
+{
+ (void)key;
+ (void)klen;
+ if(e) {
+ struct doh_request *doh_req = e;
+ curl_slist_free_all(doh_req->req_hds);
+ curlx_dyn_free(&doh_req->resp_body);
+ free(e);
+ }
}
#define ERROR_CHECK_SETOPT(x,y) \
@@ -244,30 +283,48 @@ static int doh_done(struct Curl_easy *doh, CURLcode result)
goto error; \
} while(0)
-static CURLcode doh_run_probe(struct Curl_easy *data,
- struct doh_probe *p, DNStype dnstype,
+static CURLcode doh_probe_run(struct Curl_easy *data,
+ DNStype dnstype,
const char *host,
const char *url, CURLM *multi,
- struct curl_slist *headers)
+ unsigned int *pmid)
{
struct Curl_easy *doh = NULL;
CURLcode result = CURLE_OK;
timediff_t timeout_ms;
- DOHcode d = doh_req_encode(host, dnstype, p->req_body, sizeof(p->req_body),
- &p->req_body_len);
+ struct doh_request *doh_req;
+ DOHcode d;
+
+ *pmid = UINT_MAX;
+
+ doh_req = calloc(1, sizeof(*doh_req));
+ if(!doh_req)
+ return CURLE_OUT_OF_MEMORY;
+ doh_req->dnstype = dnstype;
+ curlx_dyn_init(&doh_req->resp_body, DYN_DOH_RESPONSE);
+
+ d = doh_req_encode(host, dnstype, doh_req->req_body,
+ sizeof(doh_req->req_body),
+ &doh_req->req_body_len);
if(d) {
failf(data, "Failed to encode DoH packet [%d]", d);
- return CURLE_OUT_OF_MEMORY;
+ result = CURLE_OUT_OF_MEMORY;
+ goto error;
}
- p->dnstype = dnstype;
- Curl_dyn_init(&p->resp_body, DYN_DOH_RESPONSE);
-
timeout_ms = Curl_timeleft(data, NULL, TRUE);
if(timeout_ms <= 0) {
result = CURLE_OPERATION_TIMEDOUT;
goto error;
}
+
+ doh_req->req_hds =
+ curl_slist_append(NULL, "Content-Type: application/dns-message");
+ if(!doh_req->req_hds) {
+ result = CURLE_OUT_OF_MEMORY;
+ goto error;
+ }
+
/* Curl_open() is the internal version of curl_easy_init() */
result = Curl_open(&doh);
if(result)
@@ -275,27 +332,26 @@ static CURLcode doh_run_probe(struct Curl_easy *data,
/* pass in the struct pointer via a local variable to please coverity and
the gcc typecheck helpers */
- doh->state.internal = TRUE;
#ifndef CURL_DISABLE_VERBOSE_STRINGS
doh->state.feat = &Curl_trc_feat_dns;
#endif
ERROR_CHECK_SETOPT(CURLOPT_URL, url);
ERROR_CHECK_SETOPT(CURLOPT_DEFAULT_PROTOCOL, "https");
- ERROR_CHECK_SETOPT(CURLOPT_WRITEFUNCTION, doh_write_cb);
- ERROR_CHECK_SETOPT(CURLOPT_WRITEDATA, &p->resp_body);
- ERROR_CHECK_SETOPT(CURLOPT_POSTFIELDS, p->req_body);
- ERROR_CHECK_SETOPT(CURLOPT_POSTFIELDSIZE, (long)p->req_body_len);
- ERROR_CHECK_SETOPT(CURLOPT_HTTPHEADER, headers);
+ ERROR_CHECK_SETOPT(CURLOPT_WRITEFUNCTION, doh_probe_write_cb);
+ ERROR_CHECK_SETOPT(CURLOPT_WRITEDATA, doh);
+ ERROR_CHECK_SETOPT(CURLOPT_POSTFIELDS, doh_req->req_body);
+ ERROR_CHECK_SETOPT(CURLOPT_POSTFIELDSIZE, (long)doh_req->req_body_len);
+ ERROR_CHECK_SETOPT(CURLOPT_HTTPHEADER, doh_req->req_hds);
#ifdef USE_HTTP2
ERROR_CHECK_SETOPT(CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2TLS);
ERROR_CHECK_SETOPT(CURLOPT_PIPEWAIT, 1L);
#endif
#ifndef DEBUGBUILD
/* enforce HTTPS if not debug */
- ERROR_CHECK_SETOPT(CURLOPT_PROTOCOLS, CURLPROTO_HTTPS);
+ ERROR_CHECK_SETOPT(CURLOPT_PROTOCOLS, (long)CURLPROTO_HTTPS);
#else
/* in debug mode, also allow http */
- ERROR_CHECK_SETOPT(CURLOPT_PROTOCOLS, CURLPROTO_HTTP|CURLPROTO_HTTPS);
+ ERROR_CHECK_SETOPT(CURLOPT_PROTOCOLS, (long)CURLPROTO_HTTP|CURLPROTO_HTTPS);
#endif
ERROR_CHECK_SETOPT(CURLOPT_TIMEOUT_MS, (long)timeout_ms);
ERROR_CHECK_SETOPT(CURLOPT_SHARE, (CURLSH *)data->share);
@@ -354,26 +410,16 @@ static CURLcode doh_run_probe(struct Curl_easy *data,
data->set.str[STRING_SSL_EC_CURVES]);
}
- {
- long mask =
- (data->set.ssl.enable_beast ?
- CURLSSLOPT_ALLOW_BEAST : 0) |
- (data->set.ssl.no_revoke ?
- CURLSSLOPT_NO_REVOKE : 0) |
- (data->set.ssl.no_partialchain ?
- CURLSSLOPT_NO_PARTIALCHAIN : 0) |
- (data->set.ssl.revoke_best_effort ?
- CURLSSLOPT_REVOKE_BEST_EFFORT : 0) |
- (data->set.ssl.native_ca_store ?
- CURLSSLOPT_NATIVE_CA : 0) |
- (data->set.ssl.auto_client_cert ?
- CURLSSLOPT_AUTO_CLIENT_CERT : 0);
-
- (void)curl_easy_setopt(doh, CURLOPT_SSL_OPTIONS, mask);
- }
+ (void)curl_easy_setopt(doh, CURLOPT_SSL_OPTIONS,
+ (long)data->set.ssl.primary.ssl_options);
+
+ doh->state.internal = TRUE;
+ doh->master_mid = data->mid; /* master transfer of this one */
- doh->set.fmultidone = doh_done;
- doh->set.dohfor_mid = data->mid; /* for which transfer this is done */
+ result = Curl_meta_set(doh, CURL_EZM_DOH_PROBE, doh_req, doh_probe_dtor);
+ doh_req = NULL; /* call took ownership */
+ if(result)
+ goto error;
/* DoH handles must not inherit private_data. The handles may be passed to
the user via callbacks and the user will be able to identify them as
@@ -384,12 +430,13 @@ static CURLcode doh_run_probe(struct Curl_easy *data,
if(curl_multi_add_handle(multi, doh))
goto error;
- p->easy_mid = doh->mid;
+ *pmid = doh->mid;
return CURLE_OK;
error:
Curl_close(&doh);
- p->easy_mid = -1;
+ if(doh_req)
+ doh_probe_dtor(NULL, 0, doh_req);
return result;
}
@@ -401,51 +448,59 @@ error:
struct Curl_addrinfo *Curl_doh(struct Curl_easy *data,
const char *hostname,
int port,
+ int ip_version,
int *waitp)
{
CURLcode result = CURLE_OK;
- struct doh_probes *dohp;
+ struct doh_probes *dohp = NULL;
struct connectdata *conn = data->conn;
size_t i;
- *waitp = FALSE;
- (void)hostname;
- (void)port;
- DEBUGASSERT(!data->req.doh);
DEBUGASSERT(conn);
+ DEBUGASSERT(!data->state.async.doh);
+ if(data->state.async.doh)
+ Curl_doh_cleanup(data);
+
+ data->state.async.done = FALSE;
+ data->state.async.port = port;
+ data->state.async.ip_version = ip_version;
+ data->state.async.hostname = strdup(hostname);
+ if(!data->state.async.hostname)
+ return NULL;
/* start clean, consider allocating this struct on demand */
- dohp = data->req.doh = calloc(1, sizeof(struct doh_probes));
+ data->state.async.doh = dohp = calloc(1, sizeof(struct doh_probes));
if(!dohp)
return NULL;
for(i = 0; i < DOH_SLOT_COUNT; ++i) {
- dohp->probe[i].easy_mid = -1;
+ dohp->probe_resp[i].probe_mid = UINT_MAX;
+ curlx_dyn_init(&dohp->probe_resp[i].body, DYN_DOH_RESPONSE);
}
conn->bits.doh = TRUE;
- dohp->host = hostname;
- dohp->port = port;
- dohp->req_hds =
- curl_slist_append(NULL,
- "Content-Type: application/dns-message");
- if(!dohp->req_hds)
- goto error;
+ dohp->host = data->state.async.hostname;
+ dohp->port = data->state.async.port;
+ /* We are making sub easy handles and want to be called back when
+ * one is done. */
+ data->sub_xfer_done = doh_probe_done;
/* create IPv4 DoH request */
- result = doh_run_probe(data, &dohp->probe[DOH_SLOT_IPV4],
- DNS_TYPE_A, hostname, data->set.str[STRING_DOH],
- data->multi, dohp->req_hds);
+ result = doh_probe_run(data, DNS_TYPE_A,
+ hostname, data->set.str[STRING_DOH],
+ data->multi,
+ &dohp->probe_resp[DOH_SLOT_IPV4].probe_mid);
if(result)
goto error;
dohp->pending++;
#ifdef USE_IPV6
- if((conn->ip_version != CURL_IPRESOLVE_V4) && Curl_ipv6works(data)) {
+ if((ip_version != CURL_IPRESOLVE_V4) && Curl_ipv6works(data)) {
/* create IPv6 DoH request */
- result = doh_run_probe(data, &dohp->probe[DOH_SLOT_IPV6],
- DNS_TYPE_AAAA, hostname, data->set.str[STRING_DOH],
- data->multi, dohp->req_hds);
+ result = doh_probe_run(data, DNS_TYPE_AAAA,
+ hostname, data->set.str[STRING_DOH],
+ data->multi,
+ &dohp->probe_resp[DOH_SLOT_IPV6].probe_mid);
if(result)
goto error;
dohp->pending++;
@@ -461,10 +516,10 @@ struct Curl_addrinfo *Curl_doh(struct Curl_easy *data,
if(!qname)
goto error;
}
- result = doh_run_probe(data, &dohp->probe[DOH_SLOT_HTTPS_RR],
- DNS_TYPE_HTTPS,
+ result = doh_probe_run(data, DNS_TYPE_HTTPS,
qname ? qname : hostname, data->set.str[STRING_DOH],
- data->multi, dohp->req_hds);
+ data->multi,
+ &dohp->probe_resp[DOH_SLOT_HTTPS_RR].probe_mid);
free(qname);
if(result)
goto error;
@@ -595,14 +650,14 @@ static DOHcode doh_store_cname(const unsigned char *doh, size_t dohlen,
index++;
if(length) {
- if(Curl_dyn_len(c)) {
- if(Curl_dyn_addn(c, STRCONST(".")))
+ if(curlx_dyn_len(c)) {
+ if(curlx_dyn_addn(c, STRCONST(".")))
return DOH_OUT_OF_MEM;
}
if((index + length) > dohlen)
return DOH_DNS_BAD_LABEL;
- if(Curl_dyn_addn(c, &doh[index], length))
+ if(curlx_dyn_addn(c, &doh[index], length))
return DOH_OUT_OF_MEM;
index += length;
}
@@ -666,7 +721,7 @@ UNITTEST void de_init(struct dohentry *de)
memset(de, 0, sizeof(*de));
de->ttl = INT_MAX;
for(i = 0; i < DOH_MAX_CNAME; i++)
- Curl_dyn_init(&de->cname[i], DYN_DOH_CNAME);
+ curlx_dyn_init(&de->cname[i], DYN_DOH_CNAME);
}
@@ -853,7 +908,7 @@ static void doh_show(struct Curl_easy *data,
}
#endif
for(i = 0; i < d->numcname; i++) {
- infof(data, "CNAME: %s", Curl_dyn_ptr(&d->cname[i]));
+ infof(data, "CNAME: %s", curlx_dyn_ptr(&d->cname[i]));
}
}
#else
@@ -990,7 +1045,7 @@ UNITTEST void de_cleanup(struct dohentry *d)
{
int i = 0;
for(i = 0; i < d->numcname; i++) {
- Curl_dyn_free(&d->cname[i]);
+ curlx_dyn_free(&d->cname[i]);
}
#ifdef USE_HTTPSRR
for(i = 0; i < d->numhttps_rrs; i++)
@@ -1014,10 +1069,10 @@ UNITTEST void de_cleanup(struct dohentry *d)
* just after the end of the DNS name encoding on output. (And
* that is why it is an "unsigned char **" :-)
*/
-static CURLcode doh_decode_rdata_name(unsigned char **buf, size_t *remaining,
- char **dnsname)
+static CURLcode doh_decode_rdata_name(const unsigned char **buf,
+ size_t *remaining, char **dnsname)
{
- unsigned char *cp = NULL;
+ const unsigned char *cp = NULL;
size_t rem = 0;
unsigned char clen = 0; /* chunk len */
struct dynbuf thename;
@@ -1025,75 +1080,55 @@ static CURLcode doh_decode_rdata_name(unsigned char **buf, size_t *remaining,
DEBUGASSERT(buf && remaining && dnsname);
if(!buf || !remaining || !dnsname || !*remaining)
return CURLE_OUT_OF_MEMORY;
- Curl_dyn_init(&thename, CURL_MAXLEN_host_name);
+ curlx_dyn_init(&thename, CURL_MAXLEN_host_name);
rem = *remaining;
cp = *buf;
clen = *cp++;
if(clen == 0) {
/* special case - return "." as name */
- if(Curl_dyn_addn(&thename, ".", 1))
+ if(curlx_dyn_addn(&thename, ".", 1))
return CURLE_OUT_OF_MEMORY;
}
while(clen) {
if(clen >= rem) {
- Curl_dyn_free(&thename);
+ curlx_dyn_free(&thename);
return CURLE_OUT_OF_MEMORY;
}
- if(Curl_dyn_addn(&thename, cp, clen) ||
- Curl_dyn_addn(&thename, ".", 1))
+ if(curlx_dyn_addn(&thename, cp, clen) ||
+ curlx_dyn_addn(&thename, ".", 1))
return CURLE_TOO_LARGE;
cp += clen;
rem -= (clen + 1);
if(rem <= 0) {
- Curl_dyn_free(&thename);
+ curlx_dyn_free(&thename);
return CURLE_OUT_OF_MEMORY;
}
clen = *cp++;
}
*buf = cp;
*remaining = rem - 1;
- *dnsname = Curl_dyn_ptr(&thename);
+ *dnsname = curlx_dyn_ptr(&thename);
return CURLE_OK;
}
-#ifdef DEBUGBUILD
-static CURLcode doh_test_alpn_escapes(void)
-{
- /* we will use an example from draft-ietf-dnsop-svcb, figure 10 */
- static unsigned char example[] = {
- 0x08, /* length 8 */
- 0x66, 0x5c, 0x6f, 0x6f, 0x2c, 0x62, 0x61, 0x72, /* value "f\\oo,bar" */
- 0x02, /* length 2 */
- 0x68, 0x32 /* value "h2" */
- };
- size_t example_len = sizeof(example);
- unsigned char aval[MAX_HTTPSRR_ALPNS] = { 0 };
- static const char expected[2] = { ALPN_h2, ALPN_none };
-
- if(Curl_httpsrr_decode_alpn(example, example_len, aval) != CURLE_OK)
- return CURLE_BAD_CONTENT_ENCODING;
- if(memcmp(aval, expected, sizeof(expected)))
- return CURLE_BAD_CONTENT_ENCODING;
- return CURLE_OK;
-}
-#endif
+UNITTEST CURLcode doh_resp_decode_httpsrr(struct Curl_easy *data,
+ const unsigned char *cp, size_t len,
+ struct Curl_https_rrinfo **hrr);
-static CURLcode doh_resp_decode_httpsrr(struct Curl_easy *data,
- unsigned char *cp, size_t len,
- struct Curl_https_rrinfo **hrr)
+/* @unittest 1658 */
+UNITTEST CURLcode doh_resp_decode_httpsrr(struct Curl_easy *data,
+ const unsigned char *cp, size_t len,
+ struct Curl_https_rrinfo **hrr)
{
uint16_t pcode = 0, plen = 0;
uint32_t expected_min_pcode = 0;
struct Curl_https_rrinfo *lhrr = NULL;
char *dnsname = NULL;
CURLcode result = CURLE_OUT_OF_MEMORY;
+ size_t olen;
-#ifdef DEBUGBUILD
- /* a few tests of escaping, should not be here but ok for now */
- if(doh_test_alpn_escapes() != CURLE_OK)
- return CURLE_OUT_OF_MEMORY;
-#endif
+ *hrr = NULL;
if(len <= 2)
return CURLE_BAD_FUNCTION_ARGUMENT;
lhrr = calloc(1, sizeof(struct Curl_https_rrinfo));
@@ -1105,6 +1140,11 @@ static CURLcode doh_resp_decode_httpsrr(struct Curl_easy *data,
if(doh_decode_rdata_name(&cp, &len, &dnsname) != CURLE_OK)
goto err;
lhrr->target = dnsname;
+ if(Curl_junkscan(dnsname, &olen, FALSE)) {
+ /* unacceptable hostname content */
+ result = CURLE_WEIRD_SERVER_REPLY;
+ goto err;
+ }
lhrr->port = -1; /* until set */
while(len >= 4) {
pcode = doh_get16bit(cp, 0);
@@ -1131,9 +1171,12 @@ err:
return result;
}
-# ifdef DEBUGBUILD
-static void doh_print_httpsrr(struct Curl_easy *data,
- struct Curl_https_rrinfo *hrr)
+#ifdef DEBUGBUILD
+UNITTEST void doh_print_httpsrr(struct Curl_easy *data,
+ struct Curl_https_rrinfo *hrr);
+
+UNITTEST void doh_print_httpsrr(struct Curl_easy *data,
+ struct Curl_https_rrinfo *hrr)
{
DEBUGASSERT(hrr);
infof(data, "HTTPS RR: priority %d, target: %s",
@@ -1174,13 +1217,13 @@ CURLcode Curl_doh_is_resolved(struct Curl_easy *data,
struct Curl_dns_entry **dnsp)
{
CURLcode result;
- struct doh_probes *dohp = data->req.doh;
+ struct doh_probes *dohp = data->state.async.doh;
*dnsp = NULL; /* defaults to no response */
if(!dohp)
return CURLE_OUT_OF_MEMORY;
- if(dohp->probe[DOH_SLOT_IPV4].easy_mid < 0 &&
- dohp->probe[DOH_SLOT_IPV6].easy_mid < 0) {
+ if(dohp->probe_resp[DOH_SLOT_IPV4].probe_mid == UINT_MAX &&
+ dohp->probe_resp[DOH_SLOT_IPV6].probe_mid == UINT_MAX) {
failf(data, "Could not DoH-resolve: %s", dohp->host);
return CONN_IS_PROXIED(data->conn) ? CURLE_COULDNT_RESOLVE_PROXY :
CURLE_COULDNT_RESOLVE_HOST;
@@ -1190,19 +1233,21 @@ CURLcode Curl_doh_is_resolved(struct Curl_easy *data,
struct dohentry de;
int slot;
+ /* Clear any result the might still be there */
+ Curl_resolv_unlink(data, &data->state.async.dns);
+
memset(rc, 0, sizeof(rc));
/* remove DoH handles from multi handle and close them */
Curl_doh_close(data);
/* parse the responses, create the struct and return it! */
de_init(&de);
for(slot = 0; slot < DOH_SLOT_COUNT; slot++) {
- struct doh_probe *p = &dohp->probe[slot];
+ struct doh_response *p = &dohp->probe_resp[slot];
if(!p->dnstype)
continue;
- rc[slot] = doh_resp_decode(Curl_dyn_uptr(&p->resp_body),
- Curl_dyn_len(&p->resp_body),
+ rc[slot] = doh_resp_decode(curlx_dyn_uptr(&p->body),
+ curlx_dyn_len(&p->body),
p->dnstype, &de);
- Curl_dyn_free(&p->resp_body);
#ifndef CURL_DISABLE_VERBOSE_STRINGS
if(rc[slot]) {
infof(data, "DoH: %s type %s for %s", doh_strerror(rc[slot]),
@@ -1229,45 +1274,35 @@ CURLcode Curl_doh_is_resolved(struct Curl_easy *data,
return result;
}
- if(data->share)
- Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);
-
- /* we got a response, store it in the cache */
- dns = Curl_cache_addr(data, ai, dohp->host, 0, dohp->port, FALSE);
-
- if(data->share)
- Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
-
- if(!dns) {
- /* returned failure, bail out nicely */
- Curl_freeaddrinfo(ai);
- }
- else {
- data->state.async.dns = dns;
- *dnsp = dns;
- result = CURLE_OK; /* address resolution OK */
- }
- } /* address processing done */
-
- /* Now process any build-specific attributes retrieved from DNS */
+ /* we got a response, create a dns entry. */
+ dns = Curl_dnscache_mk_entry(data, ai, dohp->host, 0, dohp->port, FALSE);
+ if(dns) {
+ /* Now add and HTTPSRR information if we have */
#ifdef USE_HTTPSRR
- if(de.numhttps_rrs > 0 && result == CURLE_OK && *dnsp) {
- struct Curl_https_rrinfo *hrr = NULL;
- result = doh_resp_decode_httpsrr(data, de.https_rrs->val,
- de.https_rrs->len, &hrr);
- if(result) {
- infof(data, "Failed to decode HTTPS RR");
- return result;
- }
- infof(data, "Some HTTPS RR to process");
+ if(de.numhttps_rrs > 0 && result == CURLE_OK) {
+ struct Curl_https_rrinfo *hrr = NULL;
+ result = doh_resp_decode_httpsrr(data, de.https_rrs->val,
+ de.https_rrs->len, &hrr);
+ if(result) {
+ infof(data, "Failed to decode HTTPS RR");
+ return result;
+ }
+ infof(data, "Some HTTPS RR to process");
# ifdef DEBUGBUILD
- doh_print_httpsrr(data, hrr);
+ doh_print_httpsrr(data, hrr);
# endif
- (*dnsp)->hinfo = hrr;
- }
+ dns->hinfo = hrr;
+ }
#endif
+ /* and add the entry to the cache */
+ data->state.async.dns = dns;
+ result = Curl_dnscache_add(data, dns);
+ *dnsp = data->state.async.dns;
+ }
+ } /* address processing done */
/* All done */
+ data->state.async.done = TRUE;
de_cleanup(&de);
Curl_doh_cleanup(data);
return result;
@@ -1280,41 +1315,43 @@ CURLcode Curl_doh_is_resolved(struct Curl_easy *data,
void Curl_doh_close(struct Curl_easy *data)
{
- struct doh_probes *doh = data->req.doh;
+ struct doh_probes *doh = data->state.async.doh;
if(doh && data->multi) {
struct Curl_easy *probe_data;
- curl_off_t mid;
+ unsigned int mid;
size_t slot;
for(slot = 0; slot < DOH_SLOT_COUNT; slot++) {
- mid = doh->probe[slot].easy_mid;
- if(mid < 0)
+ mid = doh->probe_resp[slot].probe_mid;
+ if(mid == UINT_MAX)
continue;
- doh->probe[slot].easy_mid = -1;
+ doh->probe_resp[slot].probe_mid = UINT_MAX;
/* should have been called before data is removed from multi handle */
DEBUGASSERT(data->multi);
- probe_data = data->multi ? Curl_multi_get_handle(data->multi, mid) :
+ probe_data = data->multi ? Curl_multi_get_easy(data->multi, mid) :
NULL;
if(!probe_data) {
- DEBUGF(infof(data, "Curl_doh_close: xfer for mid=%"
- FMT_OFF_T " not found!",
- doh->probe[slot].easy_mid));
+ DEBUGF(infof(data, "Curl_doh_close: xfer for mid=%u not found!",
+ doh->probe_resp[slot].probe_mid));
continue;
}
/* data->multi might already be reset at this time */
curl_multi_remove_handle(data->multi, probe_data);
Curl_close(&probe_data);
}
+ data->sub_xfer_done = NULL;
}
}
void Curl_doh_cleanup(struct Curl_easy *data)
{
- struct doh_probes *doh = data->req.doh;
- if(doh) {
+ struct doh_probes *dohp = data->state.async.doh;
+ if(dohp) {
+ int i;
Curl_doh_close(data);
- curl_slist_free_all(doh->req_hds);
- data->req.doh->req_hds = NULL;
- Curl_safefree(data->req.doh);
+ for(i = 0; i < DOH_SLOT_COUNT; ++i) {
+ curlx_dyn_free(&dohp->probe_resp[i].body);
+ }
+ Curl_safefree(data->state.async.doh);
}
}
diff --git a/libs/libcurl/src/doh.h b/libs/libcurl/src/doh.h
index 4f0e2501b2..65312c113d 100644
--- a/libs/libcurl/src/doh.h
+++ b/libs/libcurl/src/doh.h
@@ -59,15 +59,6 @@ typedef enum {
DNS_TYPE_HTTPS = 65
} DNStype;
-/* one of these for each DoH request */
-struct doh_probe {
- curl_off_t easy_mid; /* multi id of easy handle doing the lookup */
- DNStype dnstype;
- unsigned char req_body[512];
- size_t req_body_len;
- struct dynbuf resp_body;
-};
-
enum doh_slot_num {
/* Explicit values for first two symbols so as to match hard-coded
* constants in existing code
@@ -89,9 +80,32 @@ enum doh_slot_num {
DOH_SLOT_COUNT
};
-struct doh_probes {
+#define CURL_EZM_DOH_PROBE "ezm:doh-p"
+
+/* the largest one we can make, based on RFCs 1034, 1035 */
+#define DOH_MAX_DNSREQ_SIZE (256 + 16)
+
+/* each DoH probe request has this
+ * as easy meta for CURL_EZM_DOH_PROBE */
+struct doh_request {
+ unsigned char req_body[DOH_MAX_DNSREQ_SIZE];
struct curl_slist *req_hds;
- struct doh_probe probe[DOH_SLOT_COUNT];
+ struct dynbuf resp_body;
+ size_t req_body_len;
+ DNStype dnstype;
+};
+
+struct doh_response {
+ unsigned int probe_mid;
+ struct dynbuf body;
+ DNStype dnstype;
+ CURLcode result;
+};
+
+/* each transfer firing off DoH requests has this
+ * as easy meta for CURL_EZM_DOH_MASTER */
+struct doh_probes {
+ struct doh_response probe_resp[DOH_SLOT_COUNT];
unsigned int pending; /* still outstanding probes */
int port;
const char *host;
@@ -105,6 +119,7 @@ struct doh_probes {
struct Curl_addrinfo *Curl_doh(struct Curl_easy *data,
const char *hostname,
int port,
+ int ip_version,
int *waitp);
CURLcode Curl_doh_is_resolved(struct Curl_easy *data,
@@ -168,7 +183,7 @@ UNITTEST void de_cleanup(struct dohentry *d);
#endif
#else /* if DoH is disabled */
-#define Curl_doh(a,b,c,d) NULL
+#define Curl_doh(a,b,c,d,e) NULL
#define Curl_doh_is_resolved(x,y) CURLE_COULDNT_RESOLVE_HOST
#endif
diff --git a/libs/libcurl/src/dynhds.c b/libs/libcurl/src/dynhds.c
index 289bde68fc..6c39356761 100644
--- a/libs/libcurl/src/dynhds.c
+++ b/libs/libcurl/src/dynhds.c
@@ -359,9 +359,10 @@ CURLcode Curl_dynhds_h1_dprint(struct dynhds *dynhds, struct dynbuf *dbuf)
return result;
for(i = 0; i < dynhds->hds_len; ++i) {
- result = Curl_dyn_addf(dbuf, "%.*s: %.*s\r\n",
- (int)dynhds->hds[i]->namelen, dynhds->hds[i]->name,
- (int)dynhds->hds[i]->valuelen, dynhds->hds[i]->value);
+ result = curlx_dyn_addf(dbuf, "%.*s: %.*s\r\n",
+ (int)dynhds->hds[i]->namelen, dynhds->hds[i]->name,
+ (int)dynhds->hds[i]->valuelen,
+ dynhds->hds[i]->value);
if(result)
break;
}
diff --git a/libs/libcurl/src/dynhds.h b/libs/libcurl/src/dynhds.h
index f2af6668d6..aab4bfc375 100644
--- a/libs/libcurl/src/dynhds.h
+++ b/libs/libcurl/src/dynhds.h
@@ -26,7 +26,7 @@
#include "curl_setup.h"
#include <curl/curl.h>
-#include "dynbuf.h"
+#include "curlx/dynbuf.h"
struct dynbuf;
@@ -156,14 +156,14 @@ CURLcode Curl_dynhds_cadd(struct dynhds *dynhds,
/**
* Add a single header from an HTTP/1.1 formatted line at the end. Line
- * may contain a delimiting \r\n or just \n. Any characters after
+ * may contain a delimiting CRLF or just LF. Any characters after
* that will be ignored.
*/
CURLcode Curl_dynhds_h1_cadd_line(struct dynhds *dynhds, const char *line);
/**
* Add a single header from an HTTP/1.1 formatted line at the end. Line
- * may contain a delimiting \r\n or just \n. Any characters after
+ * may contain a delimiting CRLF or just LF. Any characters after
* that will be ignored.
*/
CURLcode Curl_dynhds_h1_add_line(struct dynhds *dynhds,
diff --git a/libs/libcurl/src/easy.c b/libs/libcurl/src/easy.c
index 62c3d1556d..ff55df8e20 100644
--- a/libs/libcurl/src/easy.c
+++ b/libs/libcurl/src/easy.c
@@ -49,6 +49,7 @@
#include "transfer.h"
#include "vtls/vtls.h"
#include "vtls/vtls_scache.h"
+#include "vquic/vquic.h"
#include "url.h"
#include "getinfo.h"
#include "hostip.h"
@@ -65,14 +66,14 @@
#include "mime.h"
#include "amigaos.h"
#include "macos.h"
-#include "warnless.h"
+#include "curlx/warnless.h"
#include "sigpipe.h"
#include "vssh/ssh.h"
#include "setopt.h"
#include "http_digest.h"
#include "system_win32.h"
#include "http2.h"
-#include "dynbuf.h"
+#include "curlx/dynbuf.h"
#include "altsvc.h"
#include "hsts.h"
@@ -170,6 +171,11 @@ static CURLcode global_init(long flags, bool memoryfuncs)
goto fail;
}
+ if(!Curl_vquic_init()) {
+ DEBUGF(fprintf(stderr, "Error: Curl_vquic_init failed\n"));
+ goto fail;
+ }
+
if(Curl_win32_init(flags)) {
DEBUGF(fprintf(stderr, "Error: win32_init failed\n"));
goto fail;
@@ -185,7 +191,7 @@ static CURLcode global_init(long flags, bool memoryfuncs)
goto fail;
}
- if(Curl_resolver_global_init()) {
+ if(Curl_async_global_init()) {
DEBUGF(fprintf(stderr, "Error: resolver_global_init failed\n"));
goto fail;
}
@@ -288,7 +294,7 @@ void curl_global_cleanup(void)
}
Curl_ssl_cleanup();
- Curl_resolver_global_cleanup();
+ Curl_async_global_cleanup();
#ifdef _WIN32
Curl_win32_cleanup(easy_init_flags);
@@ -584,7 +590,7 @@ static CURLcode wait_or_timeout(struct Curl_multi *multi, struct events *ev)
const unsigned int numfds = populate_fds(fds, ev);
/* get the time stamp to use to figure out how long poll takes */
- before = Curl_now();
+ before = curlx_now();
if(numfds) {
/* wait for activity or timeout */
@@ -619,21 +625,15 @@ static CURLcode wait_or_timeout(struct Curl_multi *multi, struct events *ev)
}
else {
/* here pollrc is > 0 */
- struct Curl_llist_node *e = Curl_llist_head(&multi->process);
- struct Curl_easy *data;
- unsigned int i;
- DEBUGASSERT(e);
- data = Curl_node_elem(e);
- DEBUGASSERT(data);
-
/* loop over the monitored sockets to see which ones had activity */
+ unsigned int i;
for(i = 0; i < numfds; i++) {
if(fds[i].revents) {
/* socket activity, tell libcurl */
int act = poll2cselect(fds[i].revents); /* convert */
/* sending infof "randomly" to the first easy handle */
- infof(data, "call curl_multi_socket_action(socket "
+ infof(multi->admin, "call curl_multi_socket_action(socket "
"%" FMT_SOCKET_T ")", (curl_socket_t)fds[i].fd);
mcode = curl_multi_socket_action(multi, fds[i].fd, act,
&ev->running_handles);
@@ -645,7 +645,7 @@ static CURLcode wait_or_timeout(struct Curl_multi *multi, struct events *ev)
/* If nothing updated the timeout, we decrease it by the spent time.
* If it was updated, it has the new timeout time stored already.
*/
- timediff_t timediff = Curl_timediff(Curl_now(), before);
+ timediff_t timediff = curlx_timediff(curlx_now(), before);
if(timediff > 0) {
#if DEBUG_EV_POLL
fprintf(stderr, "poll timeout %ldms not updated, decrease by "
@@ -788,7 +788,7 @@ static CURLcode easy_perform(struct Curl_easy *data, bool events)
else {
/* this multi handle will only ever have a single easy handle attached to
it, so make it use minimal hash sizes */
- multi = Curl_multi_handle(1, 3, 7, 3);
+ multi = Curl_multi_handle(16, 1, 3, 7, 3);
if(!multi)
return CURLE_OUT_OF_MEMORY;
}
@@ -938,6 +938,15 @@ static CURLcode dupset(struct Curl_easy *dst, struct Curl_easy *src)
return result;
}
+static void dupeasy_meta_freeentry(void *p)
+{
+ (void)p;
+ /* Will always be FALSE. Cannot use a 0 assert here since compilers
+ * are not in agreement if they then want a NORETURN attribute or
+ * not. *sigh* */
+ DEBUGASSERT(p == NULL);
+}
+
/*
* curl_easy_duphandle() is an external interface to allow duplication of a
* given input easy handle. The returned handle will be a new working handle
@@ -957,14 +966,17 @@ CURL *curl_easy_duphandle(CURL *d)
*/
outcurl->set.buffer_size = data->set.buffer_size;
- Curl_dyn_init(&outcurl->state.headerb, CURL_MAX_HTTP_HEADER);
+ Curl_hash_init(&outcurl->meta_hash, 23,
+ Curl_hash_str, curlx_str_key_compare, dupeasy_meta_freeentry);
+ curlx_dyn_init(&outcurl->state.headerb, CURL_MAX_HTTP_HEADER);
Curl_netrc_init(&outcurl->state.netrc);
/* the connection pool is setup on demand */
outcurl->state.lastconnect_id = -1;
outcurl->state.recent_conn_id = -1;
outcurl->id = -1;
- outcurl->mid = -1;
+ outcurl->mid = UINT_MAX;
+ outcurl->master_mid = UINT_MAX;
#ifndef CURL_DISABLE_HTTP
Curl_llist_init(&outcurl->state.httphdrs, NULL);
@@ -975,7 +987,7 @@ CURL *curl_easy_duphandle(CURL *d)
if(dupset(outcurl, data))
goto fail;
- outcurl->progress.flags = data->progress.flags;
+ outcurl->progress.hide = data->progress.hide;
outcurl->progress.callback = data->progress.callback;
#ifndef CURL_DISABLE_COOKIES
@@ -1038,36 +1050,6 @@ CURL *curl_easy_duphandle(CURL *d)
}
#endif
-#ifdef CURLRES_ASYNCH
- /* Clone the resolver handle, if present, for the new handle */
- if(Curl_resolver_duphandle(outcurl,
- &outcurl->state.async.resolver,
- data->state.async.resolver))
- goto fail;
-#endif
-
-#ifdef USE_ARES
- {
- CURLcode rc;
-
- rc = Curl_set_dns_servers(outcurl, data->set.str[STRING_DNS_SERVERS]);
- if(rc && rc != CURLE_NOT_BUILT_IN)
- goto fail;
-
- rc = Curl_set_dns_interface(outcurl, data->set.str[STRING_DNS_INTERFACE]);
- if(rc && rc != CURLE_NOT_BUILT_IN)
- goto fail;
-
- rc = Curl_set_dns_local_ip4(outcurl, data->set.str[STRING_DNS_LOCAL_IP4]);
- if(rc && rc != CURLE_NOT_BUILT_IN)
- goto fail;
-
- rc = Curl_set_dns_local_ip6(outcurl, data->set.str[STRING_DNS_LOCAL_IP6]);
- if(rc && rc != CURLE_NOT_BUILT_IN)
- goto fail;
- }
-#endif /* USE_ARES */
-
outcurl->magic = CURLEASY_MAGIC_NUMBER;
/* we reach this point and thus we are OK */
@@ -1080,7 +1062,7 @@ fail:
#ifndef CURL_DISABLE_COOKIES
free(outcurl->cookies);
#endif
- Curl_dyn_free(&outcurl->state.headerb);
+ curlx_dyn_free(&outcurl->state.headerb);
Curl_altsvc_cleanup(&outcurl->asi);
Curl_hsts_cleanup(&outcurl->hsts);
Curl_freeset(outcurl);
@@ -1098,7 +1080,14 @@ void curl_easy_reset(CURL *d)
{
struct Curl_easy *data = d;
Curl_req_hard_reset(&data->req, data);
-
+ Curl_hash_clean(&data->meta_hash);
+
+ /* clear all meta data */
+ Curl_meta_reset(data);
+ /* clear any resolve data */
+ Curl_async_shutdown(data);
+ Curl_resolv_unlink(data, &data->state.dns[0]);
+ Curl_resolv_unlink(data, &data->state.dns[1]);
/* zero out UserDefined data: */
Curl_freeset(data);
memset(&data->set, 0, sizeof(struct UserDefined));
@@ -1110,7 +1099,7 @@ void curl_easy_reset(CURL *d)
/* zero out PureInfo data: */
Curl_initinfo(data);
- data->progress.flags |= PGRS_HIDE;
+ data->progress.hide = TRUE;
data->state.current_speed = -1; /* init to negative == impossible */
data->state.retrycount = 0; /* reset the retry counter */
@@ -1121,6 +1110,7 @@ void curl_easy_reset(CURL *d)
#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_DIGEST_AUTH)
Curl_http_auth_cleanup_digest(data);
#endif
+ data->master_mid = UINT_MAX;
}
/*
@@ -1398,3 +1388,30 @@ CURLcode curl_easy_ssls_export(CURL *d,
return CURLE_NOT_BUILT_IN;
#endif
}
+
+CURLcode Curl_meta_set(struct Curl_easy *data, const char *key,
+ void *meta_data, Curl_meta_dtor *meta_dtor)
+{
+ DEBUGASSERT(meta_data); /* never set to NULL */
+ if(!Curl_hash_add2(&data->meta_hash, CURL_UNCONST(key), strlen(key) + 1,
+ meta_data, meta_dtor)) {
+ meta_dtor(CURL_UNCONST(key), strlen(key) + 1, meta_data);
+ return CURLE_OUT_OF_MEMORY;
+ }
+ return CURLE_OK;
+}
+
+void Curl_meta_remove(struct Curl_easy *data, const char *key)
+{
+ Curl_hash_delete(&data->meta_hash, CURL_UNCONST(key), strlen(key) + 1);
+}
+
+void *Curl_meta_get(struct Curl_easy *data, const char *key)
+{
+ return Curl_hash_pick(&data->meta_hash, CURL_UNCONST(key), strlen(key) + 1);
+}
+
+void Curl_meta_reset(struct Curl_easy *data)
+{
+ Curl_hash_clean(&data->meta_hash);
+}
diff --git a/libs/libcurl/src/easygetopt.c b/libs/libcurl/src/easygetopt.c
index b54f1db880..e126075854 100644
--- a/libs/libcurl/src/easygetopt.c
+++ b/libs/libcurl/src/easygetopt.c
@@ -29,12 +29,12 @@
#ifndef CURL_DISABLE_GETOPTIONS
/* Lookups easy options at runtime */
-static struct curl_easyoption *lookup(const char *name, CURLoption id)
+static const struct curl_easyoption *lookup(const char *name, CURLoption id)
{
DEBUGASSERT(name || id);
DEBUGASSERT(!Curl_easyopts_check());
if(name || id) {
- struct curl_easyoption *o = &Curl_easyopts[0];
+ const struct curl_easyoption *o = &Curl_easyopts[0];
do {
if(name) {
if(strcasecompare(o->name, name))
diff --git a/libs/libcurl/src/easyoptions.c b/libs/libcurl/src/easyoptions.c
index 1ed53bc58a..8aadeec3ba 100644
--- a/libs/libcurl/src/easyoptions.c
+++ b/libs/libcurl/src/easyoptions.c
@@ -28,7 +28,7 @@
#include "easyoptions.h"
/* all easy setopt options listed in alphabetical order */
-struct curl_easyoption Curl_easyopts[] = {
+const struct curl_easyoption Curl_easyopts[] = {
{"ABSTRACT_UNIX_SOCKET", CURLOPT_ABSTRACT_UNIX_SOCKET, CURLOT_STRING, 0},
{"ACCEPTTIMEOUT_MS", CURLOPT_ACCEPTTIMEOUT_MS, CURLOT_LONG, 0},
{"ACCEPT_ENCODING", CURLOPT_ACCEPT_ENCODING, CURLOT_STRING, 0},
@@ -317,6 +317,8 @@ struct curl_easyoption Curl_easyopts[] = {
{"SSL_FALSESTART", CURLOPT_SSL_FALSESTART, CURLOT_LONG, 0},
{"SSL_OPTIONS", CURLOPT_SSL_OPTIONS, CURLOT_VALUES, 0},
{"SSL_SESSIONID_CACHE", CURLOPT_SSL_SESSIONID_CACHE, CURLOT_LONG, 0},
+ {"SSL_SIGNATURE_ALGORITHMS", CURLOPT_SSL_SIGNATURE_ALGORITHMS,
+ CURLOT_STRING, 0},
{"SSL_VERIFYHOST", CURLOPT_SSL_VERIFYHOST, CURLOT_LONG, 0},
{"SSL_VERIFYPEER", CURLOPT_SSL_VERIFYPEER, CURLOT_LONG, 0},
{"SSL_VERIFYSTATUS", CURLOPT_SSL_VERIFYSTATUS, CURLOT_LONG, 0},
@@ -378,6 +380,6 @@ struct curl_easyoption Curl_easyopts[] = {
*/
int Curl_easyopts_check(void)
{
- return (CURLOPT_LASTENTRY % 10000) != (327 + 1);
+ return (CURLOPT_LASTENTRY % 10000) != (328 + 1);
}
#endif
diff --git a/libs/libcurl/src/easyoptions.h b/libs/libcurl/src/easyoptions.h
index 4958aeca62..a60854fb89 100644
--- a/libs/libcurl/src/easyoptions.h
+++ b/libs/libcurl/src/easyoptions.h
@@ -29,7 +29,7 @@
#include <curl/curl.h>
/* generated table with all easy options */
-extern struct curl_easyoption Curl_easyopts[];
+extern const struct curl_easyoption Curl_easyopts[];
#ifdef DEBUGBUILD
int Curl_easyopts_check(void);
diff --git a/libs/libcurl/src/escape.c b/libs/libcurl/src/escape.c
index ba403bb466..0f836bcfac 100644
--- a/libs/libcurl/src/escape.c
+++ b/libs/libcurl/src/escape.c
@@ -32,9 +32,11 @@
struct Curl_easy;
#include "urldata.h"
-#include "warnless.h"
+#include "curlx/warnless.h"
#include "escape.h"
#include "strdup.h"
+#include "curlx/strparse.h"
+
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h"
@@ -69,7 +71,7 @@ char *curl_easy_escape(CURL *data, const char *string,
if(!length)
return strdup("");
- Curl_dyn_init(&d, length * 3 + 1);
+ curlx_dyn_init(&d, length * 3 + 1);
while(length--) {
/* treat the characters unsigned */
@@ -77,33 +79,21 @@ char *curl_easy_escape(CURL *data, const char *string,
if(ISUNRESERVED(in)) {
/* append this */
- if(Curl_dyn_addn(&d, &in, 1))
+ if(curlx_dyn_addn(&d, &in, 1))
return NULL;
}
else {
/* encode it */
- const char hex[] = "0123456789ABCDEF";
- char out[3]={'%'};
- out[1] = hex[in >> 4];
- out[2] = hex[in & 0xf];
- if(Curl_dyn_addn(&d, out, 3))
+ unsigned char out[3]={'%'};
+ Curl_hexbyte(&out[1], in, FALSE);
+ if(curlx_dyn_addn(&d, out, 3))
return NULL;
}
}
- return Curl_dyn_ptr(&d);
+ return curlx_dyn_ptr(&d);
}
-static const unsigned char hextable[] = {
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, /* 0x30 - 0x3f */
- 0, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x40 - 0x4f */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x50 - 0x5f */
- 0, 10, 11, 12, 13, 14, 15 /* 0x60 - 0x66 */
-};
-
-/* the input is a single hex digit */
-#define onehex2dec(x) hextable[x - '0']
-
/*
* Curl_urldecode() URL decodes the given string.
*
@@ -144,8 +134,8 @@ CURLcode Curl_urldecode(const char *string, size_t length,
if(('%' == in) && (alloc > 2) &&
ISXDIGIT(string[1]) && ISXDIGIT(string[2])) {
/* this is two hexadecimal digits following a '%' */
- in = (unsigned char)(onehex2dec(string[1]) << 4) | onehex2dec(string[2]);
-
+ in = (unsigned char)((Curl_hexval(string[1]) << 4) |
+ Curl_hexval(string[2]));
string += 3;
alloc -= 3;
}
@@ -219,13 +209,12 @@ void curl_free(void *p)
void Curl_hexencode(const unsigned char *src, size_t len, /* input length */
unsigned char *out, size_t olen) /* output buffer size */
{
- const char *hex = "0123456789abcdef";
DEBUGASSERT(src && len && (olen >= 3));
if(src && len && (olen >= 3)) {
while(len-- && (olen >= 3)) {
- *out++ = (unsigned char)hex[(*src & 0xF0) >> 4];
- *out++ = (unsigned char)hex[*src & 0x0F];
+ Curl_hexbyte(out, *src, TRUE);
++src;
+ out += 2;
olen -= 2;
}
*out = 0;
@@ -233,3 +222,17 @@ void Curl_hexencode(const unsigned char *src, size_t len, /* input length */
else if(olen)
*out = 0;
}
+
+/* Curl_hexbyte
+ *
+ * Output a single unsigned char as a two-digit hex number, lowercase or
+ * uppercase
+ */
+void Curl_hexbyte(unsigned char *dest, /* must fit two bytes */
+ unsigned char val,
+ bool lowercase)
+{
+ const unsigned char *t = lowercase ? Curl_ldigits : Curl_udigits;
+ dest[0] = t[val >> 4];
+ dest[1] = t[val & 0x0F];
+}
diff --git a/libs/libcurl/src/escape.h b/libs/libcurl/src/escape.h
index d2039af1e1..baa3f51ec3 100644
--- a/libs/libcurl/src/escape.h
+++ b/libs/libcurl/src/escape.h
@@ -41,4 +41,8 @@ CURLcode Curl_urldecode(const char *string, size_t length,
void Curl_hexencode(const unsigned char *src, size_t len, /* input length */
unsigned char *out, size_t olen); /* output buffer size */
+void Curl_hexbyte(unsigned char *dest, /* must fit two bytes */
+ unsigned char val,
+ bool lowercase);
+
#endif /* HEADER_CURL_ESCAPE_H */
diff --git a/libs/libcurl/src/fake_addrinfo.c b/libs/libcurl/src/fake_addrinfo.c
new file mode 100644
index 0000000000..f0272f69e0
--- /dev/null
+++ b/libs/libcurl/src/fake_addrinfo.c
@@ -0,0 +1,210 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+#include "fake_addrinfo.h"
+
+#ifdef USE_FAKE_GETADDRINFO
+
+#include <string.h>
+#include <stdlib.h>
+#include <ares.h>
+
+/* The last 3 #include files should be in this order */
+#include "curl_printf.h"
+#include "curl_memory.h"
+#include "memdebug.h"
+
+void r_freeaddrinfo(struct addrinfo *cahead)
+{
+ struct addrinfo *canext;
+ struct addrinfo *ca;
+
+ for(ca = cahead; ca; ca = canext) {
+ canext = ca->ai_next;
+ free(ca);
+ }
+}
+
+struct context {
+ struct ares_addrinfo *result;
+};
+
+static void async_addrinfo_cb(void *userp, int status, int timeouts,
+ struct ares_addrinfo *result)
+{
+ struct context *ctx = (struct context *)userp;
+ (void)timeouts;
+ if(ARES_SUCCESS == status) {
+ ctx->result = result;
+ }
+}
+
+/* convert the c-ares version into the "native" version */
+static struct addrinfo *mk_getaddrinfo(const struct ares_addrinfo *aihead)
+{
+ const struct ares_addrinfo_node *ai;
+ struct addrinfo *ca;
+ struct addrinfo *cafirst = NULL;
+ struct addrinfo *calast = NULL;
+ const char *name = aihead->name;
+
+ /* traverse the addrinfo list */
+ for(ai = aihead->nodes; ai != NULL; ai = ai->ai_next) {
+ size_t ss_size;
+ size_t namelen = name ? strlen(name) + 1 : 0;
+ /* ignore elements with unsupported address family, */
+ /* settle family-specific sockaddr structure size. */
+ if(ai->ai_family == AF_INET)
+ ss_size = sizeof(struct sockaddr_in);
+ else if(ai->ai_family == AF_INET6)
+ ss_size = sizeof(struct sockaddr_in6);
+ else
+ continue;
+
+ /* ignore elements without required address info */
+ if(!ai->ai_addr || !(ai->ai_addrlen > 0))
+ continue;
+
+ /* ignore elements with bogus address size */
+ if((size_t)ai->ai_addrlen < ss_size)
+ continue;
+
+ ca = malloc(sizeof(struct addrinfo) + ss_size + namelen);
+ if(!ca) {
+ r_freeaddrinfo(cafirst);
+ return NULL;
+ }
+
+ /* copy each structure member individually, member ordering, */
+ /* size, or padding might be different for each platform. */
+
+ ca->ai_flags = ai->ai_flags;
+ ca->ai_family = ai->ai_family;
+ ca->ai_socktype = ai->ai_socktype;
+ ca->ai_protocol = ai->ai_protocol;
+ ca->ai_addrlen = (curl_socklen_t)ss_size;
+ ca->ai_addr = NULL;
+ ca->ai_canonname = NULL;
+ ca->ai_next = NULL;
+
+ ca->ai_addr = (void *)((char *)ca + sizeof(struct addrinfo));
+ memcpy(ca->ai_addr, ai->ai_addr, ss_size);
+
+ if(namelen) {
+ ca->ai_canonname = (void *)((char *)ca->ai_addr + ss_size);
+ memcpy(ca->ai_canonname, name, namelen);
+
+ /* the name is only pointed to by the first entry in the "real"
+ addrinfo chain, so stop now */
+ name = NULL;
+ }
+
+ /* if the return list is empty, this becomes the first element */
+ if(!cafirst)
+ cafirst = ca;
+
+ /* add this element last in the return list */
+ if(calast)
+ calast->ai_next = ca;
+ calast = ca;
+ }
+
+ return cafirst;
+}
+
+/*
+ RETURN VALUE
+
+ getaddrinfo() returns 0 if it succeeds, or one of the following nonzero
+ error codes:
+
+ ...
+*/
+int r_getaddrinfo(const char *node,
+ const char *service,
+ const struct addrinfo *hints,
+ struct addrinfo **res)
+{
+ int status;
+ struct context ctx;
+ struct ares_options options;
+ int optmask = 0;
+ struct ares_addrinfo_hints ahints;
+ ares_channel channel;
+ int rc = 0;
+
+ memset(&options, 0, sizeof(options));
+ optmask |= ARES_OPT_EVENT_THREAD;
+ options.evsys = ARES_EVSYS_DEFAULT;
+
+ memset(&ahints, 0, sizeof(ahints));
+ memset(&ctx, 0, sizeof(ctx));
+
+ if(hints) {
+ ahints.ai_flags = hints->ai_flags;
+ ahints.ai_family = hints->ai_family;
+ ahints.ai_socktype = hints->ai_socktype;
+ ahints.ai_protocol = hints->ai_protocol;
+ }
+
+ status = ares_init_options(&channel, &options, optmask);
+ if(status)
+ return EAI_MEMORY; /* major problem */
+
+ else {
+ const char *env = getenv("CURL_DNS_SERVER");
+ if(env) {
+ rc = ares_set_servers_ports_csv(channel, env);
+ if(rc) {
+ fprintf(stderr, "ares_set_servers_ports_csv failed: %d", rc);
+ /* Cleanup */
+ ares_destroy(channel);
+ return EAI_MEMORY; /* we can't run */
+ }
+ }
+ }
+
+ ares_getaddrinfo(channel, node, service, &ahints,
+ async_addrinfo_cb, &ctx);
+
+ /* Wait until no more requests are left to be processed */
+ ares_queue_wait_empty(channel, -1);
+
+ if(ctx.result) {
+ /* convert the c-ares version */
+ *res = mk_getaddrinfo(ctx.result);
+ /* free the old */
+ ares_freeaddrinfo(ctx.result);
+ }
+ else
+ rc = EAI_NONAME; /* got nothing */
+
+ /* Cleanup */
+ ares_destroy(channel);
+
+ return rc;
+}
+
+#endif /* USE_FAKE_GETADDRINFO */
diff --git a/libs/libcurl/src/fake_addrinfo.h b/libs/libcurl/src/fake_addrinfo.h
new file mode 100644
index 0000000000..4483870e63
--- /dev/null
+++ b/libs/libcurl/src/fake_addrinfo.h
@@ -0,0 +1,54 @@
+#ifndef HEADER_FAKE_ADDRINFO_H
+#define HEADER_FAKE_ADDRINFO_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"
+
+#ifdef USE_ARES
+#include <ares.h>
+#endif
+
+#if defined(CURLDEBUG) && defined(USE_ARES) && defined(HAVE_GETADDRINFO) && \
+ (ARES_VERSION >= 0x011a00) /* >= 1.26. 0 */
+#define USE_FAKE_GETADDRINFO 1
+#endif
+
+#ifdef USE_FAKE_GETADDRINFO
+
+#ifdef HAVE_NETDB_H
+# include <netdb.h>
+#endif
+#ifdef HAVE_ARPA_INET_H
+# include <arpa/inet.h>
+#endif
+
+void r_freeaddrinfo(struct addrinfo *res);
+int r_getaddrinfo(const char *node,
+ const char *service,
+ const struct addrinfo *hints,
+ struct addrinfo **res);
+#endif /* USE_FAKE_GETADDRINFO */
+
+#endif /* HEADER_FAKE_ADDRINFO_H */
diff --git a/libs/libcurl/src/file.c b/libs/libcurl/src/file.c
index e02686cdb7..8b514cfd2d 100644
--- a/libs/libcurl/src/file.c
+++ b/libs/libcurl/src/file.c
@@ -70,7 +70,7 @@
#include "transfer.h"
#include "url.h"
#include "parsedate.h" /* for the week day and month names */
-#include "warnless.h"
+#include "curlx/warnless.h"
#include "curl_range.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
@@ -83,6 +83,16 @@
#define AMIGA_FILESYSTEM 1
#endif
+/* meta key for storing protocol meta at easy handle */
+#define CURL_META_FILE_EASY "meta:proto:file:easy"
+
+struct FILEPROTO {
+ char *path; /* the path we operate on */
+ char *freepath; /* pointer to the allocated block we must free, this might
+ differ from the 'path' pointer */
+ int fd; /* open file descriptor to read from! */
+};
+
/*
* Forward declarations.
*/
@@ -127,13 +137,34 @@ const struct Curl_handler Curl_handler_file = {
};
+static void file_cleanup(struct FILEPROTO *file)
+{
+ Curl_safefree(file->freepath);
+ file->path = NULL;
+ if(file->fd != -1) {
+ close(file->fd);
+ file->fd = -1;
+ }
+}
+
+static void file_easy_dtor(void *key, size_t klen, void *entry)
+{
+ struct FILEPROTO *file = entry;
+ (void)key;
+ (void)klen;
+ file_cleanup(file);
+ free(file);
+}
+
static CURLcode file_setup_connection(struct Curl_easy *data,
struct connectdata *conn)
{
+ struct FILEPROTO *filep;
(void)conn;
/* allocate the FILE specific struct */
- data->req.p.file = calloc(1, sizeof(struct FILEPROTO));
- if(!data->req.p.file)
+ filep = calloc(1, sizeof(*filep));
+ if(!filep ||
+ Curl_meta_set(data, CURL_META_FILE_EASY, filep, file_easy_dtor))
return CURLE_OUT_OF_MEMORY;
return CURLE_OK;
@@ -147,7 +178,7 @@ static CURLcode file_setup_connection(struct Curl_easy *data,
static CURLcode file_connect(struct Curl_easy *data, bool *done)
{
char *real_path;
- struct FILEPROTO *file = data->req.p.file;
+ struct FILEPROTO *file = Curl_meta_get(data, CURL_META_FILE_EASY);
int fd;
#ifdef DOS_FILESYSTEM
size_t i;
@@ -156,6 +187,9 @@ static CURLcode file_connect(struct Curl_easy *data, bool *done)
size_t real_path_len;
CURLcode result;
+ if(!file)
+ return CURLE_FAILED_INIT;
+
if(file->path) {
/* already connected.
* the handler->connect_it() is normally only called once, but
@@ -257,17 +291,12 @@ static CURLcode file_connect(struct Curl_easy *data, bool *done)
static CURLcode file_done(struct Curl_easy *data,
CURLcode status, bool premature)
{
- struct FILEPROTO *file = data->req.p.file;
+ struct FILEPROTO *file = Curl_meta_get(data, CURL_META_FILE_EASY);
(void)status; /* not used */
(void)premature; /* not used */
- if(file) {
- Curl_safefree(file->freepath);
- file->path = NULL;
- if(file->fd != -1)
- close(file->fd);
- file->fd = -1;
- }
+ if(file)
+ file_cleanup(file);
return CURLE_OK;
}
@@ -287,9 +316,9 @@ static CURLcode file_disconnect(struct Curl_easy *data,
#define DIRSEP '/'
#endif
-static CURLcode file_upload(struct Curl_easy *data)
+static CURLcode file_upload(struct Curl_easy *data,
+ struct FILEPROTO *file)
{
- struct FILEPROTO *file = data->req.p.file;
const char *dir = strchr(file->path, DIRSEP);
int fd;
int mode;
@@ -391,7 +420,7 @@ static CURLcode file_upload(struct Curl_easy *data)
if(Curl_pgrsUpdate(data))
result = CURLE_ABORTED_BY_CALLBACK;
else
- result = Curl_speedcheck(data, Curl_now());
+ result = Curl_speedcheck(data, curlx_now());
}
if(!result && Curl_pgrsUpdate(data))
result = CURLE_ABORTED_BY_CALLBACK;
@@ -418,6 +447,7 @@ static CURLcode file_do(struct Curl_easy *data, bool *done)
are supported. This means that files on remotely mounted directories
(via NFS, Samba, NT sharing) can be accessed through a file:// URL
*/
+ struct FILEPROTO *file = Curl_meta_get(data, CURL_META_FILE_EASY);
CURLcode result = CURLE_OK;
struct_stat statbuf; /* struct_stat instead of struct stat just to allow the
Windows version to have a different struct without
@@ -426,16 +456,15 @@ static CURLcode file_do(struct Curl_easy *data, bool *done)
bool size_known;
bool fstated = FALSE;
int fd;
- struct FILEPROTO *file;
char *xfer_buf;
size_t xfer_blen;
*done = TRUE; /* unconditionally */
+ if(!file)
+ return CURLE_FAILED_INIT;
if(data->state.upload)
- return file_upload(data);
-
- file = data->req.p.file;
+ return file_upload(data, file);
/* get the fd from the connection phase */
fd = file->fd;
@@ -596,7 +625,7 @@ static CURLcode file_do(struct Curl_easy *data, bool *done)
if(Curl_pgrsUpdate(data))
result = CURLE_ABORTED_BY_CALLBACK;
else
- result = Curl_speedcheck(data, Curl_now());
+ result = Curl_speedcheck(data, curlx_now());
if(result)
goto out;
}
diff --git a/libs/libcurl/src/file.h b/libs/libcurl/src/file.h
index 00d1adda54..5923f7e8fb 100644
--- a/libs/libcurl/src/file.h
+++ b/libs/libcurl/src/file.h
@@ -24,17 +24,6 @@
*
***************************************************************************/
-
-/****************************************************************************
- * FILE unique setup
- ***************************************************************************/
-struct FILEPROTO {
- char *path; /* the path we operate on */
- char *freepath; /* pointer to the allocated block we must free, this might
- differ from the 'path' pointer */
- int fd; /* open file descriptor to read from! */
-};
-
#ifndef CURL_DISABLE_FILE
extern const struct Curl_handler Curl_handler_file;
#endif
diff --git a/libs/libcurl/src/fileinfo.c b/libs/libcurl/src/fileinfo.c
index 1c313e5f2c..9613bcd004 100644
--- a/libs/libcurl/src/fileinfo.c
+++ b/libs/libcurl/src/fileinfo.c
@@ -40,7 +40,7 @@ void Curl_fileinfo_cleanup(struct fileinfo *finfo)
if(!finfo)
return;
- Curl_dyn_free(&finfo->buf);
+ curlx_dyn_free(&finfo->buf);
free(finfo);
}
#endif
diff --git a/libs/libcurl/src/fileinfo.h b/libs/libcurl/src/fileinfo.h
index bf32b3a003..cf465d6096 100644
--- a/libs/libcurl/src/fileinfo.h
+++ b/libs/libcurl/src/fileinfo.h
@@ -26,7 +26,7 @@
#include <curl/curl.h>
#include "llist.h"
-#include "dynbuf.h"
+#include "curlx/dynbuf.h"
struct fileinfo {
struct curl_fileinfo info;
diff --git a/libs/libcurl/src/fopen.c b/libs/libcurl/src/fopen.c
index d47b14d952..30489fcc30 100644
--- a/libs/libcurl/src/fopen.c
+++ b/libs/libcurl/src/fopen.c
@@ -66,7 +66,7 @@ static char *dirslash(const char *path)
size_t n;
struct dynbuf out;
DEBUGASSERT(path);
- Curl_dyn_init(&out, CURL_MAX_INPUT_LENGTH);
+ curlx_dyn_init(&out, CURL_MAX_INPUT_LENGTH);
n = strlen(path);
if(n) {
/* find the rightmost path separator, if any */
@@ -76,12 +76,12 @@ static char *dirslash(const char *path)
while(n && IS_SEP(path[n-1]))
--n;
}
- if(Curl_dyn_addn(&out, path, n))
+ if(curlx_dyn_addn(&out, path, n))
return NULL;
/* if there was a directory, append a single trailing slash */
- if(n && Curl_dyn_addn(&out, PATHSEP, 1))
+ if(n && curlx_dyn_addn(&out, PATHSEP, 1))
return NULL;
- return Curl_dyn_ptr(&out);
+ return curlx_dyn_ptr(&out);
}
/*
diff --git a/libs/libcurl/src/formdata.c b/libs/libcurl/src/formdata.c
index 248db0b27c..1105bba8e2 100644
--- a/libs/libcurl/src/formdata.c
+++ b/libs/libcurl/src/formdata.c
@@ -38,7 +38,7 @@ struct Curl_easy;
#include "sendf.h"
#include "strdup.h"
#include "rand.h"
-#include "warnless.h"
+#include "curlx/warnless.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h"
@@ -64,36 +64,31 @@ struct Curl_easy;
*
***************************************************************************/
static struct curl_httppost *
-AddHttpPost(char *name, size_t namelength,
- char *value, curl_off_t contentslength,
- char *buffer, size_t bufferlength,
- char *contenttype,
- long flags,
- struct curl_slist *contentHeader,
- char *showfilename, char *userp,
+AddHttpPost(struct FormInfo *src,
struct curl_httppost *parent_post,
struct curl_httppost **httppost,
struct curl_httppost **last_post)
{
struct curl_httppost *post;
- if(!namelength && name)
- namelength = strlen(name);
- if((bufferlength > LONG_MAX) || (namelength > LONG_MAX))
+ size_t namelength = src->namelength;
+ if(!namelength && src->name)
+ namelength = strlen(src->name);
+ if((src->bufferlength > LONG_MAX) || (namelength > LONG_MAX))
/* avoid overflow in typecasts below */
return NULL;
post = calloc(1, sizeof(struct curl_httppost));
if(post) {
- post->name = name;
+ post->name = src->name;
post->namelength = (long)namelength;
- post->contents = value;
- post->contentlen = contentslength;
- post->buffer = buffer;
- post->bufferlength = (long)bufferlength;
- post->contenttype = contenttype;
- post->contentheader = contentHeader;
- post->showfilename = showfilename;
- post->userp = userp;
- post->flags = flags | CURL_HTTPPOST_LARGE;
+ post->contents = src->value;
+ post->contentlen = src->contentslength;
+ post->buffer = src->buffer;
+ post->bufferlength = (long)src->bufferlength;
+ post->contenttype = src->contenttype;
+ post->flags = src->flags | CURL_HTTPPOST_LARGE;
+ post->contentheader = src->contentheader;
+ post->showfilename = src->showfilename;
+ post->userp = src->userp;
}
else
return NULL;
@@ -152,6 +147,28 @@ static struct FormInfo *AddFormInfo(char *value,
return form_info;
}
+static void free_formlist(struct FormInfo *ptr)
+{
+ for(; ptr != NULL; ptr = ptr->more) {
+ if(ptr->name_alloc) {
+ Curl_safefree(ptr->name);
+ ptr->name_alloc = FALSE;
+ }
+ if(ptr->value_alloc) {
+ Curl_safefree(ptr->value);
+ ptr->value_alloc = FALSE;
+ }
+ if(ptr->contenttype_alloc) {
+ Curl_safefree(ptr->contenttype);
+ ptr->contenttype_alloc = FALSE;
+ }
+ if(ptr->showfilename_alloc) {
+ Curl_safefree(ptr->showfilename);
+ ptr->showfilename_alloc = FALSE;
+ }
+ }
+}
+
/***************************************************************************
*
* FormAdd()
@@ -201,18 +218,123 @@ static struct FormInfo *AddFormInfo(char *value,
*
***************************************************************************/
+static CURLFORMcode FormAddCheck(struct FormInfo *first_form,
+ struct curl_httppost **httppost,
+ struct curl_httppost **last_post)
+{
+ const char *prevtype = NULL;
+ struct FormInfo *form = NULL;
+ struct curl_httppost *post = NULL;
+
+ /* go through the list, check for completeness and if everything is
+ * alright add the HttpPost item otherwise set retval accordingly */
+
+ for(form = first_form;
+ form != NULL;
+ form = form->more) {
+ if(((!form->name || !form->value) && !post) ||
+ ( (form->contentslength) &&
+ (form->flags & HTTPPOST_FILENAME) ) ||
+ ( (form->flags & HTTPPOST_FILENAME) &&
+ (form->flags & HTTPPOST_PTRCONTENTS) ) ||
+
+ ( (!form->buffer) &&
+ (form->flags & HTTPPOST_BUFFER) &&
+ (form->flags & HTTPPOST_PTRBUFFER) ) ||
+
+ ( (form->flags & HTTPPOST_READFILE) &&
+ (form->flags & HTTPPOST_PTRCONTENTS) )
+ ) {
+ return CURL_FORMADD_INCOMPLETE;
+ }
+ if(((form->flags & HTTPPOST_FILENAME) ||
+ (form->flags & HTTPPOST_BUFFER)) &&
+ !form->contenttype) {
+ char *f = (form->flags & HTTPPOST_BUFFER) ?
+ form->showfilename : form->value;
+ char const *type;
+ type = Curl_mime_contenttype(f);
+ if(!type)
+ type = prevtype;
+ if(!type)
+ type = FILE_CONTENTTYPE_DEFAULT;
+
+ /* our contenttype is missing */
+ form->contenttype = strdup(type);
+ if(!form->contenttype)
+ return CURL_FORMADD_MEMORY;
+
+ form->contenttype_alloc = TRUE;
+ }
+ if(form->name && form->namelength) {
+ if(memchr(form->name, 0, form->namelength))
+ return CURL_FORMADD_NULL;
+ }
+ if(!(form->flags & HTTPPOST_PTRNAME) && form->name) {
+ /* Note that there is small risk that form->name is NULL here if the app
+ passed in a bad combo, so we check for that. */
+
+ /* copy name (without strdup; possibly not null-terminated) */
+ char *dupname = Curl_memdup0(form->name, form->namelength ?
+ form->namelength : strlen(form->name));
+ if(!dupname)
+ return CURL_FORMADD_MEMORY;
+
+ form->name = dupname;
+ form->name_alloc = TRUE;
+ }
+ if(!(form->flags & (HTTPPOST_FILENAME | HTTPPOST_READFILE |
+ HTTPPOST_PTRCONTENTS | HTTPPOST_PTRBUFFER |
+ HTTPPOST_CALLBACK)) && form->value) {
+ /* copy value (without strdup; possibly contains null characters) */
+ size_t clen = (size_t) form->contentslength;
+ if(!clen)
+ clen = strlen(form->value) + 1;
+
+ form->value = Curl_memdup(form->value, clen);
+
+ if(!form->value)
+ return CURL_FORMADD_MEMORY;
+
+ form->value_alloc = TRUE;
+ }
+ post = AddHttpPost(form, post, httppost, last_post);
+
+ if(!post)
+ return CURL_FORMADD_MEMORY;
+
+ if(form->contenttype)
+ prevtype = form->contenttype;
+ }
+
+ return CURL_FORMADD_OK;
+}
+
+/* Shallow cleanup. Remove the newly created chain, the structs only and not
+ the content they point to */
+static void free_chain(struct curl_httppost *c)
+{
+ while(c) {
+ struct curl_httppost *next = c->next;
+ if(c->more)
+ free_chain(c->more);
+ free(c);
+ c = next;
+ }
+}
+
static
CURLFORMcode FormAdd(struct curl_httppost **httppost,
struct curl_httppost **last_post,
va_list params)
{
- struct FormInfo *first_form, *current_form, *form = NULL;
- CURLFORMcode return_value = CURL_FORMADD_OK;
- const char *prevtype = NULL;
- struct curl_httppost *post = NULL;
+ struct FormInfo *first_form, *curr, *form = NULL;
+ CURLFORMcode retval = CURL_FORMADD_OK;
CURLformoption option;
struct curl_forms *forms = NULL;
- char *array_value = NULL; /* value read from an array */
+ char *avalue = NULL;
+ struct curl_httppost *newchain = NULL;
+ struct curl_httppost *lastnode = NULL;
/* This is a state variable, that if TRUE means that we are parsing an
array that we got passed to us. If FALSE we are parsing the input
@@ -226,18 +348,18 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost,
if(!first_form)
return CURL_FORMADD_MEMORY;
- current_form = first_form;
+ curr = first_form;
/*
* Loop through all the options set. Break if we have an error to report.
*/
- while(return_value == CURL_FORMADD_OK) {
+ while(retval == CURL_FORMADD_OK) {
/* first see if we have more parts of the array param */
if(array_state && forms) {
/* get the upcoming option from the given array */
option = forms->option;
- array_value = (char *)CURL_UNCONST(forms->value);
+ avalue = (char *)CURL_UNCONST(forms->value);
forms++; /* advance this to next entry */
if(CURLFORM_END == option) {
@@ -259,13 +381,13 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost,
case CURLFORM_ARRAY:
if(array_state)
/* we do not support an array from within an array */
- return_value = CURL_FORMADD_ILLEGAL_ARRAY;
+ retval = CURL_FORMADD_ILLEGAL_ARRAY;
else {
forms = va_arg(params, struct curl_forms *);
if(forms)
array_state = TRUE;
else
- return_value = CURL_FORMADD_NULL;
+ retval = CURL_FORMADD_NULL;
}
break;
@@ -273,403 +395,253 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost,
* Set the Name property.
*/
case CURLFORM_PTRNAME:
- current_form->flags |= HTTPPOST_PTRNAME; /* fall through */
+ curr->flags |= HTTPPOST_PTRNAME; /* fall through */
FALLTHROUGH();
case CURLFORM_COPYNAME:
- if(current_form->name)
- return_value = CURL_FORMADD_OPTION_TWICE;
+ if(curr->name)
+ retval = CURL_FORMADD_OPTION_TWICE;
else {
- char *name = array_state ?
- array_value : va_arg(params, char *);
- if(name)
- current_form->name = name; /* store for the moment */
+ if(!array_state)
+ avalue = va_arg(params, char *);
+ if(avalue)
+ curr->name = avalue; /* store for the moment */
else
- return_value = CURL_FORMADD_NULL;
+ retval = CURL_FORMADD_NULL;
}
break;
case CURLFORM_NAMELENGTH:
- if(current_form->namelength)
- return_value = CURL_FORMADD_OPTION_TWICE;
+ if(curr->namelength)
+ retval = CURL_FORMADD_OPTION_TWICE;
else
- current_form->namelength =
- array_state ? (size_t)array_value : (size_t)va_arg(params, long);
+ curr->namelength =
+ array_state ? (size_t)avalue : (size_t)va_arg(params, long);
break;
/*
* Set the contents property.
*/
case CURLFORM_PTRCONTENTS:
- current_form->flags |= HTTPPOST_PTRCONTENTS;
+ curr->flags |= HTTPPOST_PTRCONTENTS;
FALLTHROUGH();
case CURLFORM_COPYCONTENTS:
- if(current_form->value)
- return_value = CURL_FORMADD_OPTION_TWICE;
+ if(curr->value)
+ retval = CURL_FORMADD_OPTION_TWICE;
else {
- char *value =
- array_state ? array_value : va_arg(params, char *);
- if(value)
- current_form->value = value; /* store for the moment */
+ if(!array_state)
+ avalue = va_arg(params, char *);
+ if(avalue)
+ curr->value = avalue; /* store for the moment */
else
- return_value = CURL_FORMADD_NULL;
+ retval = CURL_FORMADD_NULL;
}
break;
case CURLFORM_CONTENTSLENGTH:
- current_form->contentslength =
- array_state ? (size_t)array_value : (size_t)va_arg(params, long);
+ curr->contentslength =
+ array_state ? (size_t)avalue : (size_t)va_arg(params, long);
break;
case CURLFORM_CONTENTLEN:
- current_form->flags |= CURL_HTTPPOST_LARGE;
- current_form->contentslength =
- array_state ? (curl_off_t)(size_t)array_value :
+ curr->flags |= CURL_HTTPPOST_LARGE;
+ curr->contentslength =
+ array_state ? (curl_off_t)(size_t)avalue :
va_arg(params, curl_off_t);
break;
/* Get contents from a given filename */
case CURLFORM_FILECONTENT:
- if(current_form->flags & (HTTPPOST_PTRCONTENTS|HTTPPOST_READFILE))
- return_value = CURL_FORMADD_OPTION_TWICE;
+ if(curr->flags & (HTTPPOST_PTRCONTENTS|HTTPPOST_READFILE))
+ retval = CURL_FORMADD_OPTION_TWICE;
else {
- const char *filename = array_state ?
- array_value : va_arg(params, char *);
- if(filename) {
- current_form->value = strdup(filename);
- if(!current_form->value)
- return_value = CURL_FORMADD_MEMORY;
+ if(!array_state)
+ avalue = va_arg(params, char *);
+ if(avalue) {
+ curr->value = strdup(avalue);
+ if(!curr->value)
+ retval = CURL_FORMADD_MEMORY;
else {
- current_form->flags |= HTTPPOST_READFILE;
- current_form->value_alloc = TRUE;
+ curr->flags |= HTTPPOST_READFILE;
+ curr->value_alloc = TRUE;
}
}
else
- return_value = CURL_FORMADD_NULL;
+ retval = CURL_FORMADD_NULL;
}
break;
/* We upload a file */
case CURLFORM_FILE:
- {
- const char *filename = array_state ? array_value :
- va_arg(params, char *);
-
- if(current_form->value) {
- if(current_form->flags & HTTPPOST_FILENAME) {
- if(filename) {
- char *fname = strdup(filename);
- if(!fname)
- return_value = CURL_FORMADD_MEMORY;
+ if(!array_state)
+ avalue = va_arg(params, char *);
+
+ if(curr->value) {
+ if(curr->flags & HTTPPOST_FILENAME) {
+ if(avalue) {
+ char *fname = strdup(avalue);
+ if(!fname)
+ retval = CURL_FORMADD_MEMORY;
+ else {
+ form = AddFormInfo(fname, NULL, curr);
+ if(!form) {
+ free(fname);
+ retval = CURL_FORMADD_MEMORY;
+ }
else {
- form = AddFormInfo(fname, NULL, current_form);
- if(!form) {
- free(fname);
- return_value = CURL_FORMADD_MEMORY;
- }
- else {
- form->value_alloc = TRUE;
- current_form = form;
- form = NULL;
- }
+ form->value_alloc = TRUE;
+ curr = form;
+ form = NULL;
}
}
- else
- return_value = CURL_FORMADD_NULL;
}
else
- return_value = CURL_FORMADD_OPTION_TWICE;
+ retval = CURL_FORMADD_NULL;
}
- else {
- if(filename) {
- current_form->value = strdup(filename);
- if(!current_form->value)
- return_value = CURL_FORMADD_MEMORY;
- else {
- current_form->flags |= HTTPPOST_FILENAME;
- current_form->value_alloc = TRUE;
- }
+ else
+ retval = CURL_FORMADD_OPTION_TWICE;
+ }
+ else {
+ if(avalue) {
+ curr->value = strdup(avalue);
+ if(!curr->value)
+ retval = CURL_FORMADD_MEMORY;
+ else {
+ curr->flags |= HTTPPOST_FILENAME;
+ curr->value_alloc = TRUE;
}
- else
- return_value = CURL_FORMADD_NULL;
}
- break;
+ else
+ retval = CURL_FORMADD_NULL;
}
+ break;
case CURLFORM_BUFFERPTR:
- current_form->flags |= HTTPPOST_PTRBUFFER|HTTPPOST_BUFFER;
- if(current_form->buffer)
- return_value = CURL_FORMADD_OPTION_TWICE;
+ curr->flags |= HTTPPOST_PTRBUFFER|HTTPPOST_BUFFER;
+ if(curr->buffer)
+ retval = CURL_FORMADD_OPTION_TWICE;
else {
- char *buffer =
- array_state ? array_value : va_arg(params, char *);
- if(buffer) {
- current_form->buffer = buffer; /* store for the moment */
- current_form->value = buffer; /* make it non-NULL to be accepted
+ if(!array_state)
+ avalue = va_arg(params, char *);
+ if(avalue) {
+ curr->buffer = avalue; /* store for the moment */
+ curr->value = avalue; /* make it non-NULL to be accepted
as fine */
}
else
- return_value = CURL_FORMADD_NULL;
+ retval = CURL_FORMADD_NULL;
}
break;
case CURLFORM_BUFFERLENGTH:
- if(current_form->bufferlength)
- return_value = CURL_FORMADD_OPTION_TWICE;
+ if(curr->bufferlength)
+ retval = CURL_FORMADD_OPTION_TWICE;
else
- current_form->bufferlength =
- array_state ? (size_t)array_value : (size_t)va_arg(params, long);
+ curr->bufferlength =
+ array_state ? (size_t)avalue : (size_t)va_arg(params, long);
break;
case CURLFORM_STREAM:
- current_form->flags |= HTTPPOST_CALLBACK;
- if(current_form->userp)
- return_value = CURL_FORMADD_OPTION_TWICE;
+ curr->flags |= HTTPPOST_CALLBACK;
+ if(curr->userp)
+ retval = CURL_FORMADD_OPTION_TWICE;
else {
- char *userp =
- array_state ? array_value : va_arg(params, char *);
- if(userp) {
- current_form->userp = userp;
- current_form->value = userp; /* this is not strictly true but we
- derive a value from this later on
- and we need this non-NULL to be
- accepted as a fine form part */
+ if(!array_state)
+ avalue = va_arg(params, char *);
+ if(avalue) {
+ curr->userp = avalue;
+ curr->value = avalue; /* this is not strictly true but we derive a
+ value from this later on and we need this
+ non-NULL to be accepted as a fine form
+ part */
}
else
- return_value = CURL_FORMADD_NULL;
+ retval = CURL_FORMADD_NULL;
}
break;
case CURLFORM_CONTENTTYPE:
- {
- const char *contenttype =
- array_state ? array_value : va_arg(params, char *);
- if(current_form->contenttype) {
- if(current_form->flags & HTTPPOST_FILENAME) {
- if(contenttype) {
- char *type = strdup(contenttype);
- if(!type)
- return_value = CURL_FORMADD_MEMORY;
+ if(!array_state)
+ avalue = va_arg(params, char *);
+ if(curr->contenttype) {
+ if(curr->flags & HTTPPOST_FILENAME) {
+ if(avalue) {
+ char *type = strdup(avalue);
+ if(!type)
+ retval = CURL_FORMADD_MEMORY;
+ else {
+ form = AddFormInfo(NULL, type, curr);
+ if(!form) {
+ free(type);
+ retval = CURL_FORMADD_MEMORY;
+ }
else {
- form = AddFormInfo(NULL, type, current_form);
- if(!form) {
- free(type);
- return_value = CURL_FORMADD_MEMORY;
- }
- else {
- form->contenttype_alloc = TRUE;
- current_form = form;
- form = NULL;
- }
+ form->contenttype_alloc = TRUE;
+ curr = form;
+ form = NULL;
}
}
- else
- return_value = CURL_FORMADD_NULL;
}
else
- return_value = CURL_FORMADD_OPTION_TWICE;
+ retval = CURL_FORMADD_NULL;
}
- else {
- if(contenttype) {
- current_form->contenttype = strdup(contenttype);
- if(!current_form->contenttype)
- return_value = CURL_FORMADD_MEMORY;
- else
- current_form->contenttype_alloc = TRUE;
- }
+ else
+ retval = CURL_FORMADD_OPTION_TWICE;
+ }
+ else {
+ if(avalue) {
+ curr->contenttype = strdup(avalue);
+ if(!curr->contenttype)
+ retval = CURL_FORMADD_MEMORY;
else
- return_value = CURL_FORMADD_NULL;
+ curr->contenttype_alloc = TRUE;
}
- break;
+ else
+ retval = CURL_FORMADD_NULL;
}
+ break;
+
case CURLFORM_CONTENTHEADER:
{
/* this "cast increases required alignment of target type" but
we consider it OK anyway */
struct curl_slist *list = array_state ?
- (struct curl_slist *)(void *)array_value :
+ (struct curl_slist *)(void *)avalue :
va_arg(params, struct curl_slist *);
- if(current_form->contentheader)
- return_value = CURL_FORMADD_OPTION_TWICE;
+ if(curr->contentheader)
+ retval = CURL_FORMADD_OPTION_TWICE;
else
- current_form->contentheader = list;
+ curr->contentheader = list;
break;
}
case CURLFORM_FILENAME:
case CURLFORM_BUFFER:
- {
- const char *filename = array_state ? array_value :
- va_arg(params, char *);
- if(current_form->showfilename)
- return_value = CURL_FORMADD_OPTION_TWICE;
- else {
- current_form->showfilename = strdup(filename);
- if(!current_form->showfilename)
- return_value = CURL_FORMADD_MEMORY;
- else
- current_form->showfilename_alloc = TRUE;
- }
- break;
+ if(!array_state)
+ avalue = va_arg(params, char *);
+ if(curr->showfilename)
+ retval = CURL_FORMADD_OPTION_TWICE;
+ else {
+ curr->showfilename = strdup(avalue);
+ if(!curr->showfilename)
+ retval = CURL_FORMADD_MEMORY;
+ else
+ curr->showfilename_alloc = TRUE;
}
+ break;
+
default:
- return_value = CURL_FORMADD_UNKNOWN_OPTION;
+ retval = CURL_FORMADD_UNKNOWN_OPTION;
break;
}
}
- if(CURL_FORMADD_OK != return_value) {
+ if(!retval)
+ retval = FormAddCheck(first_form, &newchain, &lastnode);
+
+ if(retval)
/* On error, free allocated fields for all nodes of the FormInfo linked
list without deallocating nodes. List nodes are deallocated later on */
- struct FormInfo *ptr;
- for(ptr = first_form; ptr != NULL; ptr = ptr->more) {
- if(ptr->name_alloc) {
- Curl_safefree(ptr->name);
- ptr->name_alloc = FALSE;
- }
- if(ptr->value_alloc) {
- Curl_safefree(ptr->value);
- ptr->value_alloc = FALSE;
- }
- if(ptr->contenttype_alloc) {
- Curl_safefree(ptr->contenttype);
- ptr->contenttype_alloc = FALSE;
- }
- if(ptr->showfilename_alloc) {
- Curl_safefree(ptr->showfilename);
- ptr->showfilename_alloc = FALSE;
- }
- }
- }
-
- if(CURL_FORMADD_OK == return_value) {
- /* go through the list, check for completeness and if everything is
- * alright add the HttpPost item otherwise set return_value accordingly */
-
- post = NULL;
- for(form = first_form;
- form != NULL;
- form = form->more) {
- if(((!form->name || !form->value) && !post) ||
- ( (form->contentslength) &&
- (form->flags & HTTPPOST_FILENAME) ) ||
- ( (form->flags & HTTPPOST_FILENAME) &&
- (form->flags & HTTPPOST_PTRCONTENTS) ) ||
-
- ( (!form->buffer) &&
- (form->flags & HTTPPOST_BUFFER) &&
- (form->flags & HTTPPOST_PTRBUFFER) ) ||
-
- ( (form->flags & HTTPPOST_READFILE) &&
- (form->flags & HTTPPOST_PTRCONTENTS) )
- ) {
- return_value = CURL_FORMADD_INCOMPLETE;
- break;
- }
- if(((form->flags & HTTPPOST_FILENAME) ||
- (form->flags & HTTPPOST_BUFFER)) &&
- !form->contenttype) {
- char *f = (form->flags & HTTPPOST_BUFFER) ?
- form->showfilename : form->value;
- char const *type;
- type = Curl_mime_contenttype(f);
- if(!type)
- type = prevtype;
- if(!type)
- type = FILE_CONTENTTYPE_DEFAULT;
-
- /* our contenttype is missing */
- form->contenttype = strdup(type);
- if(!form->contenttype) {
- return_value = CURL_FORMADD_MEMORY;
- break;
- }
- form->contenttype_alloc = TRUE;
- }
- if(form->name && form->namelength) {
- /* Name should not contain nul bytes. */
- size_t i;
- for(i = 0; i < form->namelength; i++)
- if(!form->name[i]) {
- return_value = CURL_FORMADD_NULL;
- break;
- }
- if(return_value != CURL_FORMADD_OK)
- break;
- }
- if(!(form->flags & HTTPPOST_PTRNAME) &&
- (form == first_form) ) {
- /* Note that there is small risk that form->name is NULL here if the
- app passed in a bad combo, so we better check for that first. */
- if(form->name) {
- /* copy name (without strdup; possibly not null-terminated) */
- form->name = Curl_memdup0(form->name, form->namelength ?
- form->namelength :
- strlen(form->name));
- }
- if(!form->name) {
- return_value = CURL_FORMADD_MEMORY;
- break;
- }
- form->name_alloc = TRUE;
- }
- if(!(form->flags & (HTTPPOST_FILENAME | HTTPPOST_READFILE |
- HTTPPOST_PTRCONTENTS | HTTPPOST_PTRBUFFER |
- HTTPPOST_CALLBACK)) && form->value) {
- /* copy value (without strdup; possibly contains null characters) */
- size_t clen = (size_t) form->contentslength;
- if(!clen)
- clen = strlen(form->value) + 1;
-
- form->value = Curl_memdup(form->value, clen);
-
- if(!form->value) {
- return_value = CURL_FORMADD_MEMORY;
- break;
- }
- form->value_alloc = TRUE;
- }
- post = AddHttpPost(form->name, form->namelength,
- form->value, form->contentslength,
- form->buffer, form->bufferlength,
- form->contenttype, form->flags,
- form->contentheader, form->showfilename,
- form->userp,
- post, httppost,
- last_post);
-
- if(!post) {
- return_value = CURL_FORMADD_MEMORY;
- break;
- }
-
- if(form->contenttype)
- prevtype = form->contenttype;
- }
- if(CURL_FORMADD_OK != return_value) {
- /* On error, free allocated fields for nodes of the FormInfo linked
- list which are not already owned by the httppost linked list
- without deallocating nodes. List nodes are deallocated later on */
- struct FormInfo *ptr;
- for(ptr = form; ptr != NULL; ptr = ptr->more) {
- if(ptr->name_alloc) {
- Curl_safefree(ptr->name);
- ptr->name_alloc = FALSE;
- }
- if(ptr->value_alloc) {
- Curl_safefree(ptr->value);
- ptr->value_alloc = FALSE;
- }
- if(ptr->contenttype_alloc) {
- Curl_safefree(ptr->contenttype);
- ptr->contenttype_alloc = FALSE;
- }
- if(ptr->showfilename_alloc) {
- Curl_safefree(ptr->showfilename);
- ptr->showfilename_alloc = FALSE;
- }
- }
- }
- }
+ free_formlist(first_form);
/* Always deallocate FormInfo linked list nodes without touching node
fields given that these have either been deallocated or are owned
@@ -680,7 +652,19 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost,
first_form = ptr;
}
- return return_value;
+ if(!retval) {
+ /* Only if all is fine, link the new chain into the provided list */
+ if(*last_post)
+ (*last_post)->next = newchain;
+ else
+ (*httppost) = newchain;
+
+ (*last_post) = lastnode;
+ }
+ else
+ free_chain(newchain);
+
+ return retval;
}
/*
diff --git a/libs/libcurl/src/formdata.h b/libs/libcurl/src/formdata.h
index 9c5f3cd76b..ba30e79dbf 100644
--- a/libs/libcurl/src/formdata.h
+++ b/libs/libcurl/src/formdata.h
@@ -35,7 +35,6 @@ struct FormInfo {
char *value;
curl_off_t contentslength;
char *contenttype;
- long flags;
char *buffer; /* pointer to existing buffer used for file upload */
size_t bufferlength;
char *showfilename; /* The filename to show. If not set, the actual
@@ -43,10 +42,11 @@ struct FormInfo {
char *userp; /* pointer for the read callback */
struct curl_slist *contentheader;
struct FormInfo *more;
- bool name_alloc;
- bool value_alloc;
- bool contenttype_alloc;
- bool showfilename_alloc;
+ unsigned char flags;
+ BIT(name_alloc);
+ BIT(value_alloc);
+ BIT(contenttype_alloc);
+ BIT(showfilename_alloc);
};
CURLcode Curl_getformdata(CURL *data,
diff --git a/libs/libcurl/src/ftp.c b/libs/libcurl/src/ftp.c
index 450580fa87..2c667a5799 100644
--- a/libs/libcurl/src/ftp.c
+++ b/libs/libcurl/src/ftp.c
@@ -61,18 +61,18 @@
#include "connect.h"
#include "strerror.h"
#include "inet_ntop.h"
-#include "inet_pton.h"
+#include "curlx/inet_pton.h"
#include "select.h"
#include "parsedate.h" /* for the week day and month names */
#include "sockaddr.h" /* required for Curl_sockaddr_storage */
#include "multiif.h"
#include "url.h"
#include "speedcheck.h"
-#include "warnless.h"
+#include "curlx/warnless.h"
#include "http_proxy.h"
#include "socks.h"
#include "strdup.h"
-#include "strparse.h"
+#include "curlx/strparse.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h"
@@ -95,8 +95,7 @@
#ifdef CURL_DISABLE_VERBOSE_STRINGS
#define ftp_pasv_verbose(a,b,c,d) Curl_nop_stmt
-#define FTP_CSTATE(c) ""
-#define FTP_DSTATE(d) ""
+#define FTP_CSTATE(c) ((void)(c), "")
#else /* CURL_DISABLE_VERBOSE_STRINGS */
/* for tracing purposes */
static const char * const ftp_state_names[]={
@@ -136,23 +135,19 @@ static const char * const ftp_state_names[]={
"STOR",
"QUIT"
};
-#define FTP_CSTATE(c) ((c)? ftp_state_names[(c)->proto.ftpc.state] : "???")
-#define FTP_DSTATE(d) (((d) && (d)->conn)? \
- ftp_state_names[(d)->conn->proto.ftpc.state] : "???")
+#define FTP_CSTATE(ftpc) ((ftpc)? ftp_state_names[(ftpc)->state] : "???")
#endif /* !CURL_DISABLE_VERBOSE_STRINGS */
/* This is the ONLY way to change FTP state! */
static void _ftp_state(struct Curl_easy *data,
+ struct ftp_conn *ftpc,
ftpstate newstate
#ifdef DEBUGBUILD
, int lineno
#endif
)
{
- struct connectdata *conn = data->conn;
- struct ftp_conn *ftpc = &conn->proto.ftpc;
-
#if defined(CURL_DISABLE_VERBOSE_STRINGS)
#ifdef DEBUGBUILD
(void)lineno;
@@ -160,10 +155,10 @@ static void _ftp_state(struct Curl_easy *data,
#else /* CURL_DISABLE_VERBOSE_STRINGS */
if(ftpc->state != newstate)
#ifdef DEBUGBUILD
- CURL_TRC_FTP(data, "[%s] -> [%s] (line %d)", FTP_DSTATE(data),
+ CURL_TRC_FTP(data, "[%s] -> [%s] (line %d)", FTP_CSTATE(ftpc),
ftp_state_names[newstate], lineno);
#else
- CURL_TRC_FTP(data, "[%s] -> [%s]", FTP_DSTATE(data),
+ CURL_TRC_FTP(data, "[%s] -> [%s]", FTP_CSTATE(ftpc),
ftp_state_names[newstate]);
#endif
#endif /* !CURL_DISABLE_VERBOSE_STRINGS */
@@ -174,32 +169,40 @@ static void _ftp_state(struct Curl_easy *data,
/* Local API functions */
#ifndef DEBUGBUILD
-#define ftp_state(x,y) _ftp_state(x,y)
+#define ftp_state(x,y,z) _ftp_state(x,y,z)
#else /* !DEBUGBUILD */
-#define ftp_state(x,y) _ftp_state(x,y,__LINE__)
+#define ftp_state(x,y,z) _ftp_state(x,y,z,__LINE__)
#endif /* DEBUGBUILD */
static CURLcode ftp_sendquote(struct Curl_easy *data,
- struct connectdata *conn,
+ struct ftp_conn *ftpc,
struct curl_slist *quote);
-static CURLcode ftp_quit(struct Curl_easy *data, struct connectdata *conn);
-static CURLcode ftp_parse_url_path(struct Curl_easy *data);
-static CURLcode ftp_regular_transfer(struct Curl_easy *data, bool *done);
+static CURLcode ftp_quit(struct Curl_easy *data, struct ftp_conn *ftpc);
+static CURLcode ftp_parse_url_path(struct Curl_easy *data,
+ struct ftp_conn *ftpc,
+ struct FTP *ftp);
+static CURLcode ftp_regular_transfer(struct Curl_easy *data,
+ struct ftp_conn *ftpc,
+ struct FTP *ftp,
+ bool *done);
#ifndef CURL_DISABLE_VERBOSE_STRINGS
static void ftp_pasv_verbose(struct Curl_easy *data,
struct Curl_addrinfo *ai,
char *newhost, /* ASCII version */
int port);
#endif
-static CURLcode ftp_state_prepare_transfer(struct Curl_easy *data);
-static CURLcode ftp_state_mdtm(struct Curl_easy *data);
+static CURLcode ftp_state_mdtm(struct Curl_easy *data,
+ struct ftp_conn *ftpc,
+ struct FTP *ftp);
static CURLcode ftp_state_quote(struct Curl_easy *data,
+ struct ftp_conn *ftpc,
+ struct FTP *ftp,
bool init, ftpstate instate);
static CURLcode ftp_nb_type(struct Curl_easy *data,
- struct connectdata *conn,
+ struct ftp_conn *ftpc,
+ struct FTP *ftp,
bool ascii, ftpstate newstate);
-static int ftp_need_type(struct connectdata *conn,
- bool ascii);
+static int ftp_need_type(struct ftp_conn *ftpc, bool ascii);
static CURLcode ftp_do(struct Curl_easy *data, bool *done);
static CURLcode ftp_done(struct Curl_easy *data,
CURLcode, bool premature);
@@ -216,16 +219,26 @@ static CURLcode ftp_doing(struct Curl_easy *data,
bool *dophase_done);
static CURLcode ftp_setup_connection(struct Curl_easy *data,
struct connectdata *conn);
-static CURLcode init_wc_data(struct Curl_easy *data);
-static CURLcode wc_statemach(struct Curl_easy *data);
+static CURLcode init_wc_data(struct Curl_easy *data,
+ struct ftp_conn *ftpc,
+ struct FTP *ftp);
+static CURLcode wc_statemach(struct Curl_easy *data,
+ struct ftp_conn *ftpc,
+ struct FTP *ftp);
static void wc_data_dtor(void *ptr);
-static CURLcode ftp_state_retr(struct Curl_easy *data, curl_off_t filesize);
+static CURLcode ftp_state_retr(struct Curl_easy *data,
+ struct ftp_conn *ftpc,
+ struct FTP *ftp,
+ curl_off_t filesize);
static CURLcode ftp_readresp(struct Curl_easy *data,
+ struct ftp_conn *ftpc,
int sockindex,
struct pingpong *pp,
int *ftpcode,
size_t *size);
static CURLcode ftp_dophase_done(struct Curl_easy *data,
+ struct ftp_conn *ftpc,
+ struct FTP *ftp,
bool connected);
/*
@@ -292,9 +305,11 @@ const struct Curl_handler Curl_handler_ftps = {
};
#endif
-static void close_secondarysocket(struct Curl_easy *data)
+static void close_secondarysocket(struct Curl_easy *data,
+ struct ftp_conn *ftpc)
{
- CURL_TRC_FTP(data, "[%s] closing DATA connection", FTP_DSTATE(data));
+ (void)ftpc;
+ CURL_TRC_FTP(data, "[%s] closing DATA connection", FTP_CSTATE(ftpc));
Curl_conn_close(data, SECONDARYSOCKET);
Curl_conn_cf_discard_all(data, data->conn, SECONDARYSOCKET);
}
@@ -330,8 +345,7 @@ static void freedirs(struct ftp_conn *ftpc)
}
#ifdef CURL_PREFER_LF_LINEENDS
-/***********************************************************************
- *
+/*
* Lineend Conversions
* On ASCII transfers, e.g. directory listings, we might get lines
* ending in '\r\n' and we prefer just '\n'.
@@ -348,9 +362,12 @@ static CURLcode ftp_cw_lc_write(struct Curl_easy *data,
{
static const char nl = '\n';
struct ftp_cw_lc_ctx *ctx = writer->ctx;
+ struct ftp_conn *ftpc = Curl_conn_meta_get(data->conn, CURL_META_FTP_CONN);
- if(!(type & CLIENTWRITE_BODY) ||
- data->conn->proto.ftpc.transfertype != 'A')
+ if(!ftpc)
+ return CURLE_FAILED_INIT;
+
+ if(!(type & CLIENTWRITE_BODY) || ftpc->transfertype != 'A')
return Curl_cwriter_write(data, writer->next, type, buf, blen);
/* ASCII mode BODY data, convert lineends */
@@ -424,18 +441,18 @@ static const struct Curl_cwtype ftp_cw_lc = {
* ftp_check_ctrl_on_data_wait()
*
*/
-static CURLcode ftp_check_ctrl_on_data_wait(struct Curl_easy *data)
+static CURLcode ftp_check_ctrl_on_data_wait(struct Curl_easy *data,
+ struct ftp_conn *ftpc)
{
struct connectdata *conn = data->conn;
curl_socket_t ctrl_sock = conn->sock[FIRSTSOCKET];
- struct ftp_conn *ftpc = &conn->proto.ftpc;
struct pingpong *pp = &ftpc->pp;
ssize_t nread;
int ftpcode;
bool response = FALSE;
/* First check whether there is a cached response from server */
- if(Curl_dyn_len(&pp->recvbuf) && (*Curl_dyn_ptr(&pp->recvbuf) > '3')) {
+ if(curlx_dyn_len(&pp->recvbuf) && (*curlx_dyn_ptr(&pp->recvbuf) > '3')) {
/* Data connection could not be established, let's return */
infof(data, "There is negative response in cache while serv connect");
(void)Curl_GetFTPResponse(data, &nread, &ftpcode);
@@ -464,16 +481,16 @@ static CURLcode ftp_check_ctrl_on_data_wait(struct Curl_easy *data)
if(response) {
infof(data, "Ctrl conn has data while waiting for data conn");
if(pp->overflow > 3) {
- const char *r = Curl_dyn_ptr(&pp->recvbuf);
+ const char *r = curlx_dyn_ptr(&pp->recvbuf);
DEBUGASSERT((pp->overflow + pp->nfinal) <=
- Curl_dyn_len(&pp->recvbuf));
+ curlx_dyn_len(&pp->recvbuf));
/* move over the most recently handled response line */
r += pp->nfinal;
if(LASTLINE(r)) {
curl_off_t status;
- if(!Curl_str_number(&r, &status, 999) && (status == 226)) {
+ if(!curlx_str_number(&r, &status, 999) && (status == 226)) {
/* funny timing situation where we get the final message on the
control connection before traffic on the data connection has been
noticed. Leave the 226 in there and use this as a trigger to read
@@ -499,30 +516,30 @@ static CURLcode ftp_check_ctrl_on_data_wait(struct Curl_easy *data)
/***********************************************************************
*
- * InitiateTransfer()
+ * ftp_initiate_transfer()
*
* After connection from server is accepted this function is called to
* setup transfer parameters and initiate the data transfer.
*
*/
-static CURLcode InitiateTransfer(struct Curl_easy *data)
+static CURLcode ftp_initiate_transfer(struct Curl_easy *data,
+ struct ftp_conn *ftpc)
{
CURLcode result = CURLE_OK;
- struct connectdata *conn = data->conn;
bool connected;
- CURL_TRC_FTP(data, "InitiateTransfer()");
+ CURL_TRC_FTP(data, "ftp_initiate_transfer()");
result = Curl_conn_connect(data, SECONDARYSOCKET, TRUE, &connected);
if(result || !connected)
return result;
- if(conn->proto.ftpc.state_saved == FTP_STOR) {
+ if(ftpc->state_saved == FTP_STOR) {
/* When we know we are uploading a specified file, we can get the file
size prior to the actual upload. */
Curl_pgrsSetUploadSize(data, data->state.infilesize);
/* set the SO_SNDBUF for the secondary socket for those who need it */
- Curl_sndbuf_init(conn->sock[SECONDARYSOCKET]);
+ Curl_sndbuf_init(data->conn->sock[SECONDARYSOCKET]);
/* FTP upload, shutdown DATA, ignore shutdown errors, as we rely
* on the server response on the CONTROL connection. */
@@ -531,11 +548,11 @@ static CURLcode InitiateTransfer(struct Curl_easy *data)
else {
/* FTP download, shutdown, do not ignore errors */
Curl_xfer_setup2(data, CURL_XFER_RECV,
- conn->proto.ftpc.retr_size_saved, TRUE, FALSE);
+ ftpc->retr_size_saved, TRUE, FALSE);
}
- conn->proto.ftpc.pp.pending_resp = TRUE; /* expect server response */
- ftp_state(data, FTP_STOP);
+ ftpc->pp.pending_resp = TRUE; /* expect server response */
+ ftp_state(data, ftpc, FTP_STOP);
return CURLE_OK;
}
@@ -547,7 +564,7 @@ static bool ftp_endofresp(struct Curl_easy *data, struct connectdata *conn,
(void)data;
(void)conn;
- if((len > 3) && LASTLINE(line) && !Curl_str_number(&line, &status, 999)) {
+ if((len > 3) && LASTLINE(line) && !curlx_str_number(&line, &status, 999)) {
*code = (int)status;
return TRUE;
}
@@ -556,6 +573,7 @@ static bool ftp_endofresp(struct Curl_easy *data, struct connectdata *conn,
}
static CURLcode ftp_readresp(struct Curl_easy *data,
+ struct ftp_conn *ftpc,
int sockindex,
struct pingpong *pp,
int *ftpcode, /* return the ftp-code if done */
@@ -567,7 +585,7 @@ static CURLcode ftp_readresp(struct Curl_easy *data,
#ifdef HAVE_GSSAPI
{
struct connectdata *conn = data->conn;
- char * const buf = Curl_dyn_ptr(&data->conn->proto.ftpc.pp.recvbuf);
+ char * const buf = curlx_dyn_ptr(&ftpc->pp.recvbuf);
/* handle the security-oriented responses 6xx ***/
switch(code) {
@@ -588,7 +606,7 @@ static CURLcode ftp_readresp(struct Curl_easy *data,
#endif
/* store the latest code for later retrieval, except during shutdown */
- if(!data->conn->proto.ftpc.shutdown)
+ if(!ftpc->shutdown)
data->info.httpcode = code;
if(ftpcode)
@@ -603,7 +621,7 @@ static CURLcode ftp_readresp(struct Curl_easy *data,
* generically is a good idea.
*/
infof(data, "We got a 421 - timeout");
- ftp_state(data, FTP_STOP);
+ ftp_state(data, ftpc, FTP_STOP);
return CURLE_OPERATION_TIMEDOUT;
}
@@ -632,21 +650,22 @@ CURLcode Curl_GetFTPResponse(struct Curl_easy *data,
struct connectdata *conn = data->conn;
curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
CURLcode result = CURLE_OK;
- struct ftp_conn *ftpc = &conn->proto.ftpc;
+ struct ftp_conn *ftpc = Curl_conn_meta_get(data->conn, CURL_META_FTP_CONN);
struct pingpong *pp = &ftpc->pp;
size_t nread;
int cache_skip = 0;
int value_to_be_ignored = 0;
CURL_TRC_FTP(data, "getFTPResponse start");
-
+ *nreadp = 0;
if(ftpcode)
*ftpcode = 0; /* 0 for errors */
else
/* make the pointer point to something for the rest of this function */
ftpcode = &value_to_be_ignored;
- *nreadp = 0;
+ if(!ftpc)
+ return CURLE_FAILED_INIT;
while(!*ftpcode && !result) {
/* check and reset timeout value every lap */
@@ -676,7 +695,7 @@ CURLcode Curl_GetFTPResponse(struct Curl_easy *data,
*
*/
- if(Curl_dyn_len(&pp->recvbuf) && (cache_skip < 2)) {
+ if(curlx_dyn_len(&pp->recvbuf) && (cache_skip < 2)) {
/*
* There is a cache left since before. We then skipping the wait for
* socket action, unless this is the same cache like the previous round
@@ -706,11 +725,11 @@ CURLcode Curl_GetFTPResponse(struct Curl_easy *data,
break;
}
- result = ftp_readresp(data, FIRSTSOCKET, pp, ftpcode, &nread);
+ result = ftp_readresp(data, ftpc, FIRSTSOCKET, pp, ftpcode, &nread);
if(result)
break;
- if(!nread && Curl_dyn_len(&pp->recvbuf))
+ if(!nread && curlx_dyn_len(&pp->recvbuf))
/* bump cache skip counter as on repeated skips we must wait for more
data */
cache_skip++;
@@ -731,25 +750,24 @@ CURLcode Curl_GetFTPResponse(struct Curl_easy *data,
}
static CURLcode ftp_state_user(struct Curl_easy *data,
+ struct ftp_conn *ftpc,
struct connectdata *conn)
{
- CURLcode result = Curl_pp_sendf(data,
- &conn->proto.ftpc.pp, "USER %s",
+ CURLcode result = Curl_pp_sendf(data, &ftpc->pp, "USER %s",
conn->user ? conn->user : "");
if(!result) {
- struct ftp_conn *ftpc = &conn->proto.ftpc;
ftpc->ftp_trying_alternative = FALSE;
- ftp_state(data, FTP_USER);
+ ftp_state(data, ftpc, FTP_USER);
}
return result;
}
static CURLcode ftp_state_pwd(struct Curl_easy *data,
- struct connectdata *conn)
+ struct ftp_conn *ftpc)
{
- CURLcode result = Curl_pp_sendf(data, &conn->proto.ftpc.pp, "%s", "PWD");
+ CURLcode result = Curl_pp_sendf(data, &ftpc->pp, "%s", "PWD");
if(!result)
- ftp_state(data, FTP_PWD);
+ ftp_state(data, ftpc, FTP_PWD);
return result;
}
@@ -759,21 +777,25 @@ static int ftp_getsock(struct Curl_easy *data,
struct connectdata *conn,
curl_socket_t *socks)
{
- return Curl_pp_getsock(data, &conn->proto.ftpc.pp, socks);
+ struct ftp_conn *ftpc = Curl_conn_meta_get(conn, CURL_META_FTP_CONN);
+ return ftpc ? Curl_pp_getsock(data, &ftpc->pp, socks) : GETSOCK_BLANK;
}
/* For the FTP "DO_MORE" phase only */
static int ftp_domore_getsock(struct Curl_easy *data,
struct connectdata *conn, curl_socket_t *socks)
{
- struct ftp_conn *ftpc = &conn->proto.ftpc;
+ struct ftp_conn *ftpc = Curl_conn_meta_get(conn, CURL_META_FTP_CONN);
(void)data;
+ if(!ftpc)
+ return GETSOCK_BLANK;
+
/* When in DO_MORE state, we could be either waiting for us to connect to a
* remote site, or we could wait for that site to connect to us. Or just
* handle ordinary commands.
*/
- CURL_TRC_FTP(data, "[%s] ftp_domore_getsock()", FTP_DSTATE(data));
+ CURL_TRC_FTP(data, "[%s] ftp_domore_getsock()", FTP_CSTATE(ftpc));
if(FTP_STOP == ftpc->state) {
/* if stopped and still in this state, then we are also waiting for a
@@ -786,7 +808,7 @@ static int ftp_domore_getsock(struct Curl_easy *data,
* via its adjust_pollset() */
return GETSOCK_READSOCK(0);
}
- return Curl_pp_getsock(data, &conn->proto.ftpc.pp, socks);
+ return Curl_pp_getsock(data, &ftpc->pp, socks);
}
/* This is called after the FTP_QUOTE state is passed.
@@ -796,14 +818,14 @@ static int ftp_domore_getsock(struct Curl_easy *data,
missing ones, if that option is enabled.
*/
static CURLcode ftp_state_cwd(struct Curl_easy *data,
- struct connectdata *conn)
+ struct ftp_conn *ftpc,
+ struct FTP *ftp)
{
CURLcode result = CURLE_OK;
- struct ftp_conn *ftpc = &conn->proto.ftpc;
if(ftpc->cwddone)
/* already done and fine */
- result = ftp_state_mdtm(data);
+ result = ftp_state_mdtm(data, ftpc, ftp);
else {
/* FTPFILE_NOCWD with full path: expect ftpc->cwddone! */
DEBUGASSERT((data->set.ftp_filemethod != FTPFILE_NOCWD) ||
@@ -811,7 +833,7 @@ static CURLcode ftp_state_cwd(struct Curl_easy *data,
ftpc->count2 = 0; /* count2 counts failed CWDs */
- if(conn->bits.reuse && ftpc->entrypath &&
+ if(data->conn->bits.reuse && ftpc->entrypath &&
/* no need to go to entrypath when we have an absolute path */
!(ftpc->dirdepth && ftpc->dirs[0][0] == '/')) {
/* This is a reused connection. Since we change directory to where the
@@ -821,7 +843,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)
- ftp_state(data, FTP_CWD);
+ ftp_state(data, ftpc, FTP_CWD);
}
else {
if(ftpc->dirdepth) {
@@ -831,11 +853,11 @@ 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)
- ftp_state(data, FTP_CWD);
+ ftp_state(data, ftpc, FTP_CWD);
}
else {
/* No CWD necessary */
- result = ftp_state_mdtm(data);
+ result = ftp_state_mdtm(data, ftpc, ftp);
}
}
}
@@ -849,11 +871,11 @@ typedef enum {
} ftpport;
static CURLcode ftp_state_use_port(struct Curl_easy *data,
+ struct ftp_conn *ftpc,
ftpport fcmd) /* start with this */
{
CURLcode result = CURLE_FTP_PORT_FAILED;
struct connectdata *conn = data->conn;
- struct ftp_conn *ftpc = &conn->proto.ftpc;
curl_socket_t portsock = CURL_SOCKET_BAD;
char myhost[MAX_IPADR_LEN + 1] = "";
@@ -867,7 +889,6 @@ static CURLcode ftp_state_use_port(struct Curl_easy *data,
struct sockaddr_in6 * const sa6 = (void *)sa;
#endif
static const char mode[][5] = { "EPRT", "PORT" };
- enum resolve_t rc;
int error;
char *host = NULL;
char *string_ftpport = data->set.str[STRING_FTPPORT];
@@ -932,12 +953,12 @@ static CURLcode ftp_state_use_port(struct Curl_easy *data,
curl_off_t start;
curl_off_t end;
portp++;
- if(!Curl_str_number(&portp, &start, 0xffff)) {
+ if(!curlx_str_number(&portp, &start, 0xffff)) {
/* got the first number */
port_min = (unsigned short)start;
- if(!Curl_str_single(&portp, '-')) {
+ if(!curlx_str_single(&portp, '-')) {
/* got the dash */
- if(!Curl_str_number(&portp, &end, 0xffff))
+ if(!curlx_str_number(&portp, &end, 0xffff))
/* got the second number */
port_max = (unsigned short)end;
}
@@ -999,11 +1020,11 @@ static CURLcode ftp_state_use_port(struct Curl_easy *data,
switch(sa->sa_family) {
#ifdef USE_IPV6
case AF_INET6:
- r = curlx_inet_ntop(sa->sa_family, &sa6->sin6_addr, hbuf, sizeof(hbuf));
+ r = Curl_inet_ntop(sa->sa_family, &sa6->sin6_addr, hbuf, sizeof(hbuf));
break;
#endif
default:
- r = curlx_inet_ntop(sa->sa_family, &sa4->sin_addr, hbuf, sizeof(hbuf));
+ r = Curl_inet_ntop(sa->sa_family, &sa4->sin_addr, hbuf, sizeof(hbuf));
break;
}
if(!r) {
@@ -1014,14 +1035,12 @@ static CURLcode ftp_state_use_port(struct Curl_easy *data,
}
/* resolv ip/host to ip */
- rc = Curl_resolv(data, host, 0, FALSE, &dns_entry);
- if(rc == CURLRESOLV_PENDING)
- (void)Curl_resolver_wait_resolv(data, &dns_entry);
- if(dns_entry) {
+ res = NULL;
+ result = Curl_resolv_blocking(data, host, 0, conn->ip_version, &dns_entry);
+ if(!result) {
+ DEBUGASSERT(dns_entry);
res = dns_entry->addr;
}
- else
- res = NULL; /* failure! */
if(!res) {
failf(data, "failed to resolve the address provided to PORT: %s", host);
@@ -1045,7 +1064,7 @@ static CURLcode ftp_state_use_port(struct Curl_easy *data,
goto out;
}
CURL_TRC_FTP(data, "[%s] ftp_state_use_port(), opened socket",
- FTP_DSTATE(data));
+ FTP_CSTATE(ftpc));
/* step 3, bind to a suitable local address */
@@ -1107,7 +1126,7 @@ static CURLcode ftp_state_use_port(struct Curl_easy *data,
goto out;
}
CURL_TRC_FTP(data, "[%s] ftp_state_use_port(), socket bound to port %d",
- FTP_DSTATE(data), port);
+ FTP_CSTATE(ftpc), port);
/* step 4, listen on the socket */
@@ -1117,7 +1136,7 @@ static CURLcode ftp_state_use_port(struct Curl_easy *data,
goto out;
}
CURL_TRC_FTP(data, "[%s] ftp_state_use_port(), listening on %d",
- FTP_DSTATE(data), port);
+ FTP_CSTATE(ftpc), port);
/* step 5, send the proper FTP command */
@@ -1204,7 +1223,7 @@ static CURLcode ftp_state_use_port(struct Curl_easy *data,
/* store which command was sent */
ftpc->count1 = fcmd;
- ftp_state(data, FTP_PORT);
+ ftp_state(data, ftpc, FTP_PORT);
/* Replace any filter on SECONDARY with one listening on this socket */
result = Curl_conn_tcp_listen_set(data, conn, SECONDARYSOCKET, &portsock);
@@ -1216,7 +1235,7 @@ out:
if(dns_entry)
Curl_resolv_unlink(data, &dns_entry);
if(result) {
- ftp_state(data, FTP_STOP);
+ ftp_state(data, ftpc, FTP_STOP);
}
else {
/* successfully setup the list socket filter. Do we need more? */
@@ -1236,9 +1255,9 @@ out:
}
static CURLcode ftp_state_use_pasv(struct Curl_easy *data,
+ struct ftp_conn *ftpc,
struct connectdata *conn)
{
- struct ftp_conn *ftpc = &conn->proto.ftpc;
CURLcode result = CURLE_OK;
/*
Here's the executive summary on what to do:
@@ -1269,7 +1288,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;
- ftp_state(data, FTP_PASV);
+ ftp_state(data, ftpc, FTP_PASV);
infof(data, "Connect data stream passively");
}
return result;
@@ -1282,55 +1301,52 @@ static CURLcode ftp_state_use_pasv(struct Curl_easy *data,
* request is made. Thus, if an actual transfer is to be made this is where we
* take off for real.
*/
-static CURLcode ftp_state_prepare_transfer(struct Curl_easy *data)
+static CURLcode ftp_state_prepare_transfer(struct Curl_easy *data,
+ struct ftp_conn *ftpc,
+ struct FTP *ftp)
{
CURLcode result = CURLE_OK;
- struct FTP *ftp = data->req.p.ftp;
struct connectdata *conn = data->conn;
if(ftp->transfer != PPTRANSFER_BODY) {
/* does not transfer any data */
/* still possibly do PRE QUOTE jobs */
- ftp_state(data, FTP_RETR_PREQUOTE);
- result = ftp_state_quote(data, TRUE, FTP_RETR_PREQUOTE);
+ ftp_state(data, ftpc, FTP_RETR_PREQUOTE);
+ result = ftp_state_quote(data, ftpc, ftp, TRUE, FTP_RETR_PREQUOTE);
}
else if(data->set.ftp_use_port) {
/* We have chosen to use the PORT (or similar) command */
- result = ftp_state_use_port(data, EPRT);
+ result = ftp_state_use_port(data, ftpc, EPRT);
}
else {
/* We have chosen (this is default) to use the PASV (or similar) command */
if(data->set.ftp_use_pret) {
/* The user has requested that we send a PRET command
to prepare the server for the upcoming PASV */
- struct ftp_conn *ftpc = &conn->proto.ftpc;
- if(!conn->proto.ftpc.file)
+ if(!ftpc->file)
result = Curl_pp_sendf(data, &ftpc->pp, "PRET %s",
data->set.str[STRING_CUSTOMREQUEST] ?
data->set.str[STRING_CUSTOMREQUEST] :
(data->state.list_only ? "NLST" : "LIST"));
else if(data->state.upload)
- result = Curl_pp_sendf(data, &ftpc->pp, "PRET STOR %s",
- conn->proto.ftpc.file);
+ result = Curl_pp_sendf(data, &ftpc->pp, "PRET STOR %s", ftpc->file);
else
- result = Curl_pp_sendf(data, &ftpc->pp, "PRET RETR %s",
- conn->proto.ftpc.file);
+ result = Curl_pp_sendf(data, &ftpc->pp, "PRET RETR %s", ftpc->file);
if(!result)
- ftp_state(data, FTP_PRET);
+ ftp_state(data, ftpc, FTP_PRET);
}
else
- result = ftp_state_use_pasv(data, conn);
+ result = ftp_state_use_pasv(data, ftpc, conn);
}
return result;
}
static CURLcode ftp_state_rest(struct Curl_easy *data,
- struct connectdata *conn)
+ struct ftp_conn *ftpc,
+ struct FTP *ftp)
{
CURLcode result = CURLE_OK;
- struct FTP *ftp = data->req.p.ftp;
- struct ftp_conn *ftpc = &conn->proto.ftpc;
if((ftp->transfer != PPTRANSFER_BODY) && ftpc->file) {
/* if a "head"-like request is being made (on a file) */
@@ -1339,20 +1355,19 @@ 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)
- ftp_state(data, FTP_REST);
+ ftp_state(data, ftpc, FTP_REST);
}
else
- result = ftp_state_prepare_transfer(data);
+ result = ftp_state_prepare_transfer(data, ftpc, ftp);
return result;
}
static CURLcode ftp_state_size(struct Curl_easy *data,
- struct connectdata *conn)
+ struct ftp_conn *ftpc,
+ struct FTP *ftp)
{
CURLcode result = CURLE_OK;
- struct FTP *ftp = data->req.p.ftp;
- struct ftp_conn *ftpc = &conn->proto.ftpc;
if((ftp->transfer == PPTRANSFER_INFO) && ftpc->file) {
/* if a "head"-like request is being made (on a file) */
@@ -1360,19 +1375,19 @@ static CURLcode ftp_state_size(struct Curl_easy *data,
/* we know ftpc->file is a valid pointer to a filename */
result = Curl_pp_sendf(data, &ftpc->pp, "SIZE %s", ftpc->file);
if(!result)
- ftp_state(data, FTP_SIZE);
+ ftp_state(data, ftpc, FTP_SIZE);
}
else
- result = ftp_state_rest(data, conn);
+ result = ftp_state_rest(data, ftpc, ftp);
return result;
}
-static CURLcode ftp_state_list(struct Curl_easy *data)
+static CURLcode ftp_state_list(struct Curl_easy *data,
+ struct ftp_conn *ftpc,
+ struct FTP *ftp)
{
CURLcode result = CURLE_OK;
- struct FTP *ftp = data->req.p.ftp;
- struct connectdata *conn = data->conn;
/* If this output is to be machine-parsed, the NLST command might be better
to use, since the LIST command output is not specified or standard in any
@@ -1424,39 +1439,42 @@ static CURLcode ftp_state_list(struct Curl_easy *data)
if(!cmd)
return CURLE_OUT_OF_MEMORY;
- result = Curl_pp_sendf(data, &conn->proto.ftpc.pp, "%s", cmd);
+ result = Curl_pp_sendf(data, &ftpc->pp, "%s", cmd);
free(cmd);
if(!result)
- ftp_state(data, FTP_LIST);
+ ftp_state(data, ftpc, FTP_LIST);
return result;
}
-static CURLcode ftp_state_retr_prequote(struct Curl_easy *data)
+static CURLcode ftp_state_retr_prequote(struct Curl_easy *data,
+ struct ftp_conn *ftpc,
+ struct FTP *ftp)
{
/* We have sent the TYPE, now we must send the list of prequote strings */
- return ftp_state_quote(data, TRUE, FTP_RETR_PREQUOTE);
+ return ftp_state_quote(data, ftpc, ftp, TRUE, FTP_RETR_PREQUOTE);
}
-static CURLcode ftp_state_stor_prequote(struct Curl_easy *data)
+static CURLcode ftp_state_stor_prequote(struct Curl_easy *data,
+ struct ftp_conn *ftpc,
+ struct FTP *ftp)
{
/* We have sent the TYPE, now we must send the list of prequote strings */
- return ftp_state_quote(data, TRUE, FTP_STOR_PREQUOTE);
+ return ftp_state_quote(data, ftpc, ftp, TRUE, FTP_STOR_PREQUOTE);
}
-static CURLcode ftp_state_type(struct Curl_easy *data)
+static CURLcode ftp_state_type(struct Curl_easy *data,
+ struct ftp_conn *ftpc,
+ struct FTP *ftp)
{
CURLcode result = CURLE_OK;
- struct FTP *ftp = data->req.p.ftp;
- struct connectdata *conn = data->conn;
- struct ftp_conn *ftpc = &conn->proto.ftpc;
/* If we have selected NOBODY and HEADER, it means that we only want file
information. Which in FTP cannot be much more than the file size and
date. */
if(data->req.no_body && ftpc->file &&
- ftp_need_type(conn, data->state.prefer_ascii)) {
+ ftp_need_type(ftpc, data->state.prefer_ascii)) {
/* The SIZE command is _not_ RFC 959 specified, and therefore many servers
may not support it! It is however the only way we have to get a file's
size! */
@@ -1466,23 +1484,23 @@ static CURLcode ftp_state_type(struct Curl_easy *data)
/* Some servers return different sizes for different modes, and thus we
must set the proper type before we check the size */
- result = ftp_nb_type(data, conn, data->state.prefer_ascii, FTP_TYPE);
+ result = ftp_nb_type(data, ftpc, ftp, data->state.prefer_ascii, FTP_TYPE);
if(result)
return result;
}
else
- result = ftp_state_size(data, conn);
+ result = ftp_state_size(data, ftpc, ftp);
return result;
}
/* This is called after the CWD commands have been done in the beginning of
the DO phase */
-static CURLcode ftp_state_mdtm(struct Curl_easy *data)
+static CURLcode ftp_state_mdtm(struct Curl_easy *data,
+ struct ftp_conn *ftpc,
+ struct FTP *ftp)
{
CURLcode result = CURLE_OK;
- struct connectdata *conn = data->conn;
- struct ftp_conn *ftpc = &conn->proto.ftpc;
/* Requested time of file or time-depended transfer? */
if((data->set.get_filetime || data->set.timecondition) && ftpc->file) {
@@ -1492,10 +1510,10 @@ static CURLcode ftp_state_mdtm(struct Curl_easy *data)
result = Curl_pp_sendf(data, &ftpc->pp, "MDTM %s", ftpc->file);
if(!result)
- ftp_state(data, FTP_MDTM);
+ ftp_state(data, ftpc, FTP_MDTM);
}
else
- result = ftp_state_type(data);
+ result = ftp_state_type(data, ftpc, ftp);
return result;
}
@@ -1503,12 +1521,11 @@ static CURLcode ftp_state_mdtm(struct Curl_easy *data)
/* This is called after the TYPE and possible quote commands have been sent */
static CURLcode ftp_state_ul_setup(struct Curl_easy *data,
+ struct ftp_conn *ftpc,
+ struct FTP *ftp,
bool sizechecked)
{
CURLcode result = CURLE_OK;
- struct connectdata *conn = data->conn;
- struct FTP *ftp = data->req.p.ftp;
- struct ftp_conn *ftpc = &conn->proto.ftpc;
bool append = data->set.remote_append;
if((data->state.resume_from && !sizechecked) ||
@@ -1531,7 +1548,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)
- ftp_state(data, FTP_STOR_SIZE);
+ ftp_state(data, ftpc, FTP_STOR_SIZE);
return result;
}
@@ -1587,7 +1604,7 @@ static CURLcode ftp_state_ul_setup(struct Curl_easy *data,
* ftp_done() because we did not transfer anything! */
ftp->transfer = PPTRANSFER_NONE;
- ftp_state(data, FTP_STOP);
+ ftp_state(data, ftpc, FTP_STOP);
return CURLE_OK;
}
}
@@ -1597,19 +1614,18 @@ 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)
- ftp_state(data, FTP_STOR);
+ ftp_state(data, ftpc, FTP_STOR);
return result;
}
static CURLcode ftp_state_quote(struct Curl_easy *data,
+ struct ftp_conn *ftpc,
+ struct FTP *ftp,
bool init,
ftpstate instate)
{
CURLcode result = CURLE_OK;
- struct FTP *ftp = data->req.p.ftp;
- struct connectdata *conn = data->conn;
- struct ftp_conn *ftpc = &conn->proto.ftpc;
bool quote = FALSE;
struct curl_slist *item;
@@ -1658,7 +1674,7 @@ static CURLcode ftp_state_quote(struct Curl_easy *data,
result = Curl_pp_sendf(data, &ftpc->pp, "%s", cmd);
if(result)
return result;
- ftp_state(data, instate);
+ ftp_state(data, ftpc, instate);
quote = TRUE;
}
}
@@ -1668,15 +1684,15 @@ static CURLcode ftp_state_quote(struct Curl_easy *data,
switch(instate) {
case FTP_QUOTE:
default:
- result = ftp_state_cwd(data, conn);
+ result = ftp_state_cwd(data, ftpc, ftp);
break;
case FTP_RETR_PREQUOTE:
if(ftp->transfer != PPTRANSFER_BODY)
- ftp_state(data, FTP_STOP);
+ ftp_state(data, ftpc, FTP_STOP);
else {
if(ftpc->known_filesize != -1) {
Curl_pgrsSetDownloadSize(data, ftpc->known_filesize);
- result = ftp_state_retr(data, ftpc->known_filesize);
+ result = ftp_state_retr(data, ftpc, ftp, ftpc->known_filesize);
}
else {
if(data->set.ignorecl || data->state.prefer_ascii) {
@@ -1694,18 +1710,18 @@ static CURLcode ftp_state_quote(struct Curl_easy *data,
*/
result = Curl_pp_sendf(data, &ftpc->pp, "RETR %s", ftpc->file);
if(!result)
- ftp_state(data, FTP_RETR);
+ ftp_state(data, ftpc, FTP_RETR);
}
else {
result = Curl_pp_sendf(data, &ftpc->pp, "SIZE %s", ftpc->file);
if(!result)
- ftp_state(data, FTP_RETR_SIZE);
+ ftp_state(data, ftpc, FTP_RETR_SIZE);
}
}
}
break;
case FTP_STOR_PREQUOTE:
- result = ftp_state_ul_setup(data, FALSE);
+ result = ftp_state_ul_setup(data, ftpc, ftp, FALSE);
break;
case FTP_POSTQUOTE:
break;
@@ -1718,6 +1734,7 @@ static CURLcode ftp_state_quote(struct Curl_easy *data,
/* called from ftp_state_pasv_resp to switch to PASV in case of EPSV
problems */
static CURLcode ftp_epsv_disable(struct Curl_easy *data,
+ struct ftp_conn *ftpc,
struct connectdata *conn)
{
CURLcode result = CURLE_OK;
@@ -1739,11 +1756,11 @@ static CURLcode ftp_epsv_disable(struct Curl_easy *data,
Curl_conn_cf_discard_all(data, conn, SECONDARYSOCKET);
data->state.errorbuf = FALSE; /* allow error message to get
rewritten */
- result = Curl_pp_sendf(data, &conn->proto.ftpc.pp, "%s", "PASV");
+ result = Curl_pp_sendf(data, &ftpc->pp, "%s", "PASV");
if(!result) {
- conn->proto.ftpc.count1++;
+ ftpc->count1++;
/* remain in/go to the FTP_PASV state */
- ftp_state(data, FTP_PASV);
+ ftp_state(data, ftpc, FTP_PASV);
}
return result;
}
@@ -1773,7 +1790,7 @@ static bool match_pasv_6nums(const char *p,
return FALSE;
p++;
}
- if(Curl_str_number(&p, &num, 0xff))
+ if(curlx_str_number(&p, &num, 0xff))
return FALSE;
array[i] = (unsigned int)num;
}
@@ -1781,17 +1798,16 @@ static bool match_pasv_6nums(const char *p,
}
static CURLcode ftp_state_pasv_resp(struct Curl_easy *data,
+ struct ftp_conn *ftpc,
int ftpcode)
{
struct connectdata *conn = data->conn;
- struct ftp_conn *ftpc = &conn->proto.ftpc;
CURLcode result;
- struct Curl_dns_entry *addr = NULL;
- enum resolve_t rc;
+ struct Curl_dns_entry *dns = NULL;
unsigned short connectport; /* the local port connect() should use! */
struct pingpong *pp = &ftpc->pp;
char *str =
- Curl_dyn_ptr(&pp->recvbuf) + 4; /* start on the first letter */
+ curlx_dyn_ptr(&pp->recvbuf) + 4; /* start on the first letter */
/* if we come here again, make sure the former name is cleared */
Curl_safefree(ftpc->newhost);
@@ -1808,7 +1824,7 @@ static CURLcode ftp_state_pasv_resp(struct Curl_easy *data,
if((ptr[1] == sep) && (ptr[2] == sep) && ISDIGIT(ptr[3])) {
const char *p = &ptr[3];
curl_off_t num;
- if(Curl_str_number(&p, &num, 0xffff) || (*p != sep)) {
+ if(curlx_str_number(&p, &num, 0xffff) || (*p != sep)) {
failf(data, "Illegal port number in EPSV reply");
return CURLE_FTP_WEIRD_PASV_REPLY;
}
@@ -1869,7 +1885,7 @@ static CURLcode ftp_state_pasv_resp(struct Curl_easy *data,
}
else if(ftpc->count1 == 0) {
/* EPSV failed, move on to PASV */
- return ftp_epsv_disable(data, conn);
+ return ftp_epsv_disable(data, ftpc, conn);
}
else {
failf(data, "Bad PASV/EPSV response: %03d", ftpcode);
@@ -1885,16 +1901,12 @@ static CURLcode ftp_state_pasv_resp(struct Curl_easy *data,
*/
const char * const host_name = conn->bits.socksproxy ?
conn->socks_proxy.host.name : conn->http_proxy.host.name;
- rc = Curl_resolv(data, host_name, conn->primary.remote_port, FALSE, &addr);
- if(rc == CURLRESOLV_PENDING)
- /* BLOCKING, ignores the return code but 'addr' will be NULL in
- case of failure */
- (void)Curl_resolver_wait_resolv(data, &addr);
-
+ (void)Curl_resolv_blocking(data, host_name, conn->primary.remote_port,
+ conn->ip_version, &dns);
/* we connect to the proxy's port */
connectport = (unsigned short)conn->primary.remote_port;
- if(!addr) {
+ if(!dns) {
failf(data, "cannot resolve proxy host %s:%hu", host_name, connectport);
return CURLE_COULDNT_RESOLVE_PROXY;
}
@@ -1913,28 +1925,24 @@ static CURLcode ftp_state_pasv_resp(struct Curl_easy *data,
return CURLE_OUT_OF_MEMORY;
}
- rc = Curl_resolv(data, ftpc->newhost, ftpc->newport, FALSE, &addr);
- if(rc == CURLRESOLV_PENDING)
- /* BLOCKING */
- (void)Curl_resolver_wait_resolv(data, &addr);
-
+ (void)Curl_resolv_blocking(data, ftpc->newhost, ftpc->newport,
+ conn->ip_version, &dns);
connectport = ftpc->newport; /* we connect to the remote port */
- if(!addr) {
+ if(!dns) {
failf(data, "cannot resolve new host %s:%hu",
ftpc->newhost, connectport);
return CURLE_FTP_CANT_GET_HOST;
}
}
- result = Curl_conn_setup(data, conn, SECONDARYSOCKET, addr,
+ result = Curl_conn_setup(data, conn, SECONDARYSOCKET, dns,
conn->bits.ftp_use_data_ssl ?
CURL_CF_SSL_ENABLE : CURL_CF_SSL_DISABLE);
if(result) {
- Curl_resolv_unlink(data, &addr); /* we are done using this address */
if(ftpc->count1 == 0 && ftpcode == 229)
- return ftp_epsv_disable(data, conn);
+ return ftp_epsv_disable(data, ftpc, conn);
return result;
}
@@ -1948,9 +1956,7 @@ static CURLcode ftp_state_pasv_resp(struct Curl_easy *data,
if(data->set.verbose)
/* this just dumps information about this second connection */
- ftp_pasv_verbose(data, addr->addr, ftpc->newhost, connectport);
-
- Curl_resolv_unlink(data, &addr); /* we are done using this address */
+ ftp_pasv_verbose(data, dns->addr, ftpc->newhost, connectport);
free(conn->secondaryhostname);
conn->secondary_port = ftpc->newport;
@@ -1959,16 +1965,17 @@ static CURLcode ftp_state_pasv_resp(struct Curl_easy *data,
return CURLE_OUT_OF_MEMORY;
conn->bits.do_more = TRUE;
- ftp_state(data, FTP_STOP); /* this phase is completed */
+ ftp_state(data, ftpc, FTP_STOP); /* this phase is completed */
return result;
}
static CURLcode ftp_state_port_resp(struct Curl_easy *data,
+ struct ftp_conn *ftpc,
+ struct FTP *ftp,
int ftpcode)
{
struct connectdata *conn = data->conn;
- struct ftp_conn *ftpc = &conn->proto.ftpc;
ftpport fcmd = (ftpport)ftpc->count1;
CURLcode result = CURLE_OK;
@@ -1989,12 +1996,12 @@ static CURLcode ftp_state_port_resp(struct Curl_easy *data,
}
else
/* try next */
- result = ftp_state_use_port(data, fcmd);
+ result = ftp_state_use_port(data, ftpc, fcmd);
}
else {
infof(data, "Connect data stream actively");
- ftp_state(data, FTP_STOP); /* end of DO phase */
- result = ftp_dophase_done(data, FALSE);
+ ftp_state(data, ftpc, FTP_STOP); /* end of DO phase */
+ result = ftp_dophase_done(data, ftpc, ftp, FALSE);
}
return result;
@@ -2050,12 +2057,11 @@ static CURLcode client_write_header(struct Curl_easy *data,
}
static CURLcode ftp_state_mdtm_resp(struct Curl_easy *data,
+ struct ftp_conn *ftpc,
+ struct FTP *ftp,
int ftpcode)
{
CURLcode result = CURLE_OK;
- struct FTP *ftp = data->req.p.ftp;
- struct connectdata *conn = data->conn;
- struct ftp_conn *ftpc = &conn->proto.ftpc;
switch(ftpcode) {
case 213:
@@ -2064,7 +2070,7 @@ static CURLcode ftp_state_mdtm_resp(struct Curl_easy *data,
last .sss part is optional and means fractions of a second */
int year, month, day, hour, minute, second;
struct pingpong *pp = &ftpc->pp;
- char *resp = Curl_dyn_ptr(&pp->recvbuf) + 4;
+ char *resp = curlx_dyn_ptr(&pp->recvbuf) + 4;
if(ftp_213_date(resp, &year, &month, &day, &hour, &minute, &second)) {
/* we have a time, reformat it */
char timebuf[24];
@@ -2140,7 +2146,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;
- ftp_state(data, FTP_STOP);
+ ftp_state(data, ftpc, FTP_STOP);
return CURLE_OK;
}
break;
@@ -2149,7 +2155,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;
- ftp_state(data, FTP_STOP);
+ ftp_state(data, ftpc, FTP_STOP);
return CURLE_OK;
}
break;
@@ -2161,17 +2167,18 @@ static CURLcode ftp_state_mdtm_resp(struct Curl_easy *data,
}
if(!result)
- result = ftp_state_type(data);
+ result = ftp_state_type(data, ftpc, ftp);
return result;
}
static CURLcode ftp_state_type_resp(struct Curl_easy *data,
+ struct ftp_conn *ftpc,
+ struct FTP *ftp,
int ftpcode,
ftpstate instate)
{
CURLcode result = CURLE_OK;
- struct connectdata *conn = data->conn;
if(ftpcode/100 != 2) {
/* "sasserftpd" and "(u)r(x)bot ftpd" both responds with 226 after a
@@ -2185,26 +2192,25 @@ static CURLcode ftp_state_type_resp(struct Curl_easy *data,
ftpcode);
if(instate == FTP_TYPE)
- result = ftp_state_size(data, conn);
+ result = ftp_state_size(data, ftpc, ftp);
else if(instate == FTP_LIST_TYPE)
- result = ftp_state_list(data);
+ result = ftp_state_list(data, ftpc, ftp);
else if(instate == FTP_RETR_TYPE)
- result = ftp_state_retr_prequote(data);
+ result = ftp_state_retr_prequote(data, ftpc, ftp);
else if(instate == FTP_STOR_TYPE)
- result = ftp_state_stor_prequote(data);
+ result = ftp_state_stor_prequote(data, ftpc, ftp);
return result;
}
static CURLcode ftp_state_retr(struct Curl_easy *data,
+ struct ftp_conn *ftpc,
+ struct FTP *ftp,
curl_off_t filesize)
{
CURLcode result = CURLE_OK;
- struct FTP *ftp = data->req.p.ftp;
- struct connectdata *conn = data->conn;
- struct ftp_conn *ftpc = &conn->proto.ftpc;
- CURL_TRC_FTP(data, "[%s] ftp_state_retr()", FTP_DSTATE(data));
+ CURL_TRC_FTP(data, "[%s] ftp_state_retr()", FTP_CSTATE(ftpc));
if(data->set.max_filesize && (filesize > data->set.max_filesize)) {
failf(data, "Maximum file size exceeded");
return CURLE_FILESIZE_EXCEEDED;
@@ -2257,7 +2263,7 @@ static CURLcode ftp_state_retr(struct Curl_easy *data,
/* Set ->transfer so that we will not get any error in ftp_done()
* because we did not transfer the any file */
ftp->transfer = PPTRANSFER_NONE;
- ftp_state(data, FTP_STOP);
+ ftp_state(data, ftpc, FTP_STOP);
return CURLE_OK;
}
@@ -2268,26 +2274,28 @@ static CURLcode ftp_state_retr(struct Curl_easy *data,
result = Curl_pp_sendf(data, &ftpc->pp, "REST %" FMT_OFF_T,
data->state.resume_from);
if(!result)
- ftp_state(data, FTP_RETR_REST);
+ ftp_state(data, ftpc, FTP_RETR_REST);
}
else {
/* no resume */
result = Curl_pp_sendf(data, &ftpc->pp, "RETR %s", ftpc->file);
if(!result)
- ftp_state(data, FTP_RETR);
+ ftp_state(data, ftpc, FTP_RETR);
}
return result;
}
static CURLcode ftp_state_size_resp(struct Curl_easy *data,
+ struct ftp_conn *ftpc,
+ struct FTP *ftp,
int ftpcode,
ftpstate instate)
{
CURLcode result = CURLE_OK;
curl_off_t filesize = -1;
- char *buf = Curl_dyn_ptr(&data->conn->proto.ftpc.pp.recvbuf);
- size_t len = data->conn->proto.ftpc.pp.nfinal;
+ char *buf = curlx_dyn_ptr(&ftpc->pp.recvbuf);
+ size_t len = ftpc->pp.nfinal;
/* get the size from the ascii string: */
if(ftpcode == 213) {
@@ -2305,7 +2313,7 @@ static CURLcode ftp_state_size_resp(struct Curl_easy *data,
}
else
fdigit = start;
- if(Curl_str_number(&fdigit, &filesize, CURL_OFF_T_MAX))
+ if(curlx_str_number(&fdigit, &filesize, CURL_OFF_T_MAX))
filesize = -1; /* size remain unknown */
}
else if(ftpcode == 550) { /* "No such file or directory" */
@@ -2329,27 +2337,27 @@ static CURLcode ftp_state_size_resp(struct Curl_easy *data,
}
#endif
Curl_pgrsSetDownloadSize(data, filesize);
- result = ftp_state_rest(data, data->conn);
+ result = ftp_state_rest(data, ftpc, ftp);
}
else if(instate == FTP_RETR_SIZE) {
Curl_pgrsSetDownloadSize(data, filesize);
- result = ftp_state_retr(data, filesize);
+ result = ftp_state_retr(data, ftpc, ftp, filesize);
}
else if(instate == FTP_STOR_SIZE) {
data->state.resume_from = filesize;
- result = ftp_state_ul_setup(data, TRUE);
+ result = ftp_state_ul_setup(data, ftpc, ftp, TRUE);
}
return result;
}
static CURLcode ftp_state_rest_resp(struct Curl_easy *data,
- struct connectdata *conn,
+ struct ftp_conn *ftpc,
+ struct FTP *ftp,
int ftpcode,
ftpstate instate)
{
CURLcode result = CURLE_OK;
- struct ftp_conn *ftpc = &conn->proto.ftpc;
switch(instate) {
case FTP_REST:
@@ -2362,7 +2370,7 @@ static CURLcode ftp_state_rest_resp(struct Curl_easy *data,
return result;
}
#endif
- result = ftp_state_prepare_transfer(data);
+ result = ftp_state_prepare_transfer(data, ftpc, ftp);
break;
case FTP_RETR_REST:
@@ -2373,7 +2381,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)
- ftp_state(data, FTP_RETR);
+ ftp_state(data, ftpc, FTP_RETR);
}
break;
}
@@ -2382,26 +2390,25 @@ static CURLcode ftp_state_rest_resp(struct Curl_easy *data,
}
static CURLcode ftp_state_stor_resp(struct Curl_easy *data,
+ struct ftp_conn *ftpc,
int ftpcode, ftpstate instate)
{
CURLcode result = CURLE_OK;
- struct connectdata *conn = data->conn;
if(ftpcode >= 400) {
failf(data, "Failed FTP upload: %0d", ftpcode);
- ftp_state(data, FTP_STOP);
+ ftp_state(data, ftpc, FTP_STOP);
/* oops, we never close the sockets! */
return CURLE_UPLOAD_FAILED;
}
- conn->proto.ftpc.state_saved = instate;
+ ftpc->state_saved = instate;
/* PORT means we are now awaiting the server to connect to us. */
if(data->set.ftp_use_port) {
- struct ftp_conn *ftpc = &conn->proto.ftpc;
bool connected;
- ftp_state(data, FTP_STOP); /* no longer in STOR state */
+ ftp_state(data, ftpc, FTP_STOP); /* no longer in STOR state */
result = Curl_conn_connect(data, SECONDARYSOCKET, FALSE, &connected);
if(result)
@@ -2410,21 +2417,21 @@ static CURLcode ftp_state_stor_resp(struct Curl_easy *data,
if(!connected) {
infof(data, "Data conn was not available immediately");
ftpc->wait_data_conn = TRUE;
- return ftp_check_ctrl_on_data_wait(data);
+ return ftp_check_ctrl_on_data_wait(data, ftpc);
}
ftpc->wait_data_conn = FALSE;
}
- return InitiateTransfer(data);
+ return ftp_initiate_transfer(data, ftpc);
}
/* for LIST and RETR responses */
static CURLcode ftp_state_get_resp(struct Curl_easy *data,
+ struct ftp_conn *ftpc,
+ struct FTP *ftp,
int ftpcode,
ftpstate instate)
{
CURLcode result = CURLE_OK;
- struct FTP *ftp = data->req.p.ftp;
- struct connectdata *conn = data->conn;
if((ftpcode == 150) || (ftpcode == 125)) {
@@ -2469,7 +2476,7 @@ static CURLcode ftp_state_get_resp(struct Curl_easy *data,
*
* Example D above makes this parsing a little tricky */
const char *bytes;
- char *buf = Curl_dyn_ptr(&conn->proto.ftpc.pp.recvbuf);
+ char *buf = curlx_dyn_ptr(&ftpc->pp.recvbuf);
bytes = strstr(buf, " bytes");
if(bytes) {
long in = (long)(--bytes-buf);
@@ -2490,7 +2497,7 @@ static CURLcode ftp_state_get_resp(struct Curl_easy *data,
if(bytes) {
++bytes;
/* get the number! */
- if(Curl_str_number(&bytes, &size, CURL_OFF_T_MAX))
+ if(curlx_str_number(&bytes, &size, CURL_OFF_T_MAX))
size = 1;
}
}
@@ -2509,11 +2516,10 @@ static CURLcode ftp_state_get_resp(struct Curl_easy *data,
infof(data, "Getting file with size: %" FMT_OFF_T, size);
/* FTP download: */
- conn->proto.ftpc.state_saved = instate;
- conn->proto.ftpc.retr_size_saved = size;
+ ftpc->state_saved = instate;
+ ftpc->retr_size_saved = size;
if(data->set.ftp_use_port) {
- struct ftp_conn *ftpc = &conn->proto.ftpc;
bool connected;
result = Curl_conn_connect(data, SECONDARYSOCKET, FALSE, &connected);
@@ -2522,19 +2528,19 @@ static CURLcode ftp_state_get_resp(struct Curl_easy *data,
if(!connected) {
infof(data, "Data conn was not available immediately");
- ftp_state(data, FTP_STOP);
+ ftp_state(data, ftpc, FTP_STOP);
ftpc->wait_data_conn = TRUE;
- return ftp_check_ctrl_on_data_wait(data);
+ return ftp_check_ctrl_on_data_wait(data, ftpc);
}
ftpc->wait_data_conn = FALSE;
}
- return InitiateTransfer(data);
+ return ftp_initiate_transfer(data, ftpc);
}
else {
if((instate == FTP_LIST) && (ftpcode == 450)) {
/* simply no matching files in the dir listing */
ftp->transfer = PPTRANSFER_NONE; /* do not download anything */
- ftp_state(data, FTP_STOP); /* this phase is over */
+ ftp_state(data, ftpc, FTP_STOP); /* this phase is over */
}
else {
failf(data, "RETR response: %03d", ftpcode);
@@ -2548,12 +2554,12 @@ static CURLcode ftp_state_get_resp(struct Curl_easy *data,
}
/* after USER, PASS and ACCT */
-static CURLcode ftp_state_loggedin(struct Curl_easy *data)
+static CURLcode ftp_state_loggedin(struct Curl_easy *data,
+ struct ftp_conn *ftpc)
{
CURLcode result = CURLE_OK;
- struct connectdata *conn = data->conn;
- if(conn->bits.ftp_use_control_ssl) {
+ if(data->conn->bits.ftp_use_control_ssl) {
/* PBSZ = PROTECTION BUFFER SIZE.
The 'draft-murray-auth-ftp-ssl' (draft 12, page 7) says:
@@ -2568,44 +2574,43 @@ static CURLcode ftp_state_loggedin(struct Curl_easy *data)
parameter of '0' to indicate that no buffering is taking place
and the data connection should not be encapsulated.
*/
- result = Curl_pp_sendf(data, &conn->proto.ftpc.pp, "PBSZ %d", 0);
+ result = Curl_pp_sendf(data, &ftpc->pp, "PBSZ %d", 0);
if(!result)
- ftp_state(data, FTP_PBSZ);
+ ftp_state(data, ftpc, FTP_PBSZ);
}
else {
- result = ftp_state_pwd(data, conn);
+ result = ftp_state_pwd(data, ftpc);
}
return result;
}
/* for USER and PASS responses */
static CURLcode ftp_state_user_resp(struct Curl_easy *data,
+ struct ftp_conn *ftpc,
int ftpcode)
{
CURLcode result = CURLE_OK;
- struct connectdata *conn = data->conn;
- struct ftp_conn *ftpc = &conn->proto.ftpc;
/* some need password anyway, and others just return 2xx ignored */
if((ftpcode == 331) && (ftpc->state == FTP_USER)) {
/* 331 Password required for ...
(the server requires to send the user's password too) */
result = Curl_pp_sendf(data, &ftpc->pp, "PASS %s",
- conn->passwd ? conn->passwd : "");
+ data->conn->passwd ? data->conn->passwd : "");
if(!result)
- ftp_state(data, FTP_PASS);
+ ftp_state(data, ftpc, FTP_PASS);
}
else if(ftpcode/100 == 2) {
/* 230 User ... logged in.
(the user logged in with or without password) */
- result = ftp_state_loggedin(data);
+ result = ftp_state_loggedin(data, ftpc);
}
else if(ftpcode == 332) {
if(data->set.str[STRING_FTP_ACCOUNT]) {
result = Curl_pp_sendf(data, &ftpc->pp, "ACCT %s",
data->set.str[STRING_FTP_ACCOUNT]);
if(!result)
- ftp_state(data, FTP_ACCT);
+ ftp_state(data, ftpc, FTP_ACCT);
}
else {
failf(data, "ACCT requested but none available");
@@ -2626,7 +2631,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;
- ftp_state(data, FTP_USER);
+ ftp_state(data, ftpc, FTP_USER);
}
}
else {
@@ -2639,6 +2644,7 @@ static CURLcode ftp_state_user_resp(struct Curl_easy *data,
/* for ACCT response */
static CURLcode ftp_state_acct_resp(struct Curl_easy *data,
+ struct ftp_conn *ftpc,
int ftpcode)
{
CURLcode result = CURLE_OK;
@@ -2647,26 +2653,30 @@ static CURLcode ftp_state_acct_resp(struct Curl_easy *data,
result = CURLE_FTP_WEIRD_PASS_REPLY; /* FIX */
}
else
- result = ftp_state_loggedin(data);
+ result = ftp_state_loggedin(data, ftpc);
return result;
}
-static CURLcode ftp_statemachine(struct Curl_easy *data,
- struct connectdata *conn)
+static CURLcode ftp_pp_statemachine(struct Curl_easy *data,
+ struct connectdata *conn)
{
CURLcode result;
int ftpcode;
- struct ftp_conn *ftpc = &conn->proto.ftpc;
- struct pingpong *pp = &ftpc->pp;
+ struct ftp_conn *ftpc = Curl_conn_meta_get(conn, CURL_META_FTP_CONN);
+ struct FTP *ftp = Curl_meta_get(data, CURL_META_FTP_EASY);
+ struct pingpong *pp;
static const char * const ftpauth[] = { "SSL", "TLS" };
size_t nread = 0;
+ if(!ftpc || !ftp)
+ return CURLE_FAILED_INIT;
+ pp = &ftpc->pp;
if(pp->sendleft)
return Curl_pp_flushsend(data, pp);
- result = ftp_readresp(data, FIRSTSOCKET, pp, &ftpcode, &nread);
+ result = ftp_readresp(data, ftpc, FIRSTSOCKET, pp, &ftpcode, &nread);
if(result)
return result;
@@ -2678,7 +2688,7 @@ static CURLcode ftp_statemachine(struct Curl_easy *data,
/* 230 User logged in - already! Take as 220 if TLS required. */
if(data->set.use_ssl <= CURLUSESSL_TRY ||
conn->bits.ftp_use_control_ssl)
- return ftp_state_user_resp(data, ftpcode);
+ return ftp_state_user_resp(data, ftpc, ftpcode);
}
else if(ftpcode != 220) {
failf(data, "Got a %03d ftp-server response when 220 was expected",
@@ -2728,10 +2738,10 @@ static CURLcode ftp_statemachine(struct Curl_easy *data,
result = Curl_pp_sendf(data, &ftpc->pp, "AUTH %s",
ftpauth[ftpc->count1]);
if(!result)
- ftp_state(data, FTP_AUTH);
+ ftp_state(data, ftpc, FTP_AUTH);
}
else
- result = ftp_state_user(data, conn);
+ result = ftp_state_user(data, ftpc, conn);
break;
case FTP_AUTH:
@@ -2761,7 +2771,7 @@ static CURLcode ftp_statemachine(struct Curl_easy *data,
if(!result) {
conn->bits.ftp_use_data_ssl = FALSE; /* clear-text data */
conn->bits.ftp_use_control_ssl = TRUE; /* SSL on control */
- result = ftp_state_user(data, conn);
+ result = ftp_state_user(data, ftpc, conn);
}
}
else if(ftpc->count3 < 1) {
@@ -2777,17 +2787,17 @@ static CURLcode ftp_statemachine(struct Curl_easy *data,
result = CURLE_USE_SSL_FAILED;
else
/* ignore the failure and continue */
- result = ftp_state_user(data, conn);
+ result = ftp_state_user(data, ftpc, conn);
}
break;
case FTP_USER:
case FTP_PASS:
- result = ftp_state_user_resp(data, ftpcode);
+ result = ftp_state_user_resp(data, ftpc, ftpcode);
break;
case FTP_ACCT:
- result = ftp_state_acct_resp(data, ftpcode);
+ result = ftp_state_acct_resp(data, ftpc, ftpcode);
break;
case FTP_PBSZ:
@@ -2795,7 +2805,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)
- ftp_state(data, FTP_PROT);
+ ftp_state(data, ftpc, FTP_PROT);
break;
case FTP_PROT:
@@ -2814,10 +2824,10 @@ static CURLcode ftp_statemachine(struct Curl_easy *data,
*/
result = Curl_pp_sendf(data, &ftpc->pp, "%s", "CCC");
if(!result)
- ftp_state(data, FTP_CCC);
+ ftp_state(data, ftpc, FTP_CCC);
}
else
- result = ftp_state_pwd(data, conn);
+ result = ftp_state_pwd(data, ftpc);
break;
case FTP_CCC:
@@ -2836,16 +2846,16 @@ static CURLcode ftp_statemachine(struct Curl_easy *data,
}
if(!result)
/* Then continue as normal */
- result = ftp_state_pwd(data, conn);
+ result = ftp_state_pwd(data, ftpc);
break;
case FTP_PWD:
if(ftpcode == 257) {
- char *ptr = Curl_dyn_ptr(&pp->recvbuf) + 4; /* start on the first
- letter */
+ char *ptr = curlx_dyn_ptr(&pp->recvbuf) + 4; /* start on the first
+ letter */
bool entry_extracted = FALSE;
struct dynbuf out;
- Curl_dyn_init(&out, 1000);
+ curlx_dyn_init(&out, 1000);
/* Reply format is like
257<space>[rubbish]"<directory-name>"<space><commentary> and the
@@ -2866,18 +2876,18 @@ static CURLcode ftp_statemachine(struct Curl_easy *data,
if('\"' == *ptr) {
if('\"' == ptr[1]) {
/* "quote-doubling" */
- result = Curl_dyn_addn(&out, &ptr[1], 1);
+ result = curlx_dyn_addn(&out, &ptr[1], 1);
ptr++;
}
else {
/* end of path */
- if(Curl_dyn_len(&out))
+ if(curlx_dyn_len(&out))
entry_extracted = TRUE;
break; /* get out of this loop */
}
}
else
- result = Curl_dyn_addn(&out, ptr, 1);
+ result = curlx_dyn_addn(&out, ptr, 1);
if(result)
return result;
}
@@ -2894,7 +2904,7 @@ static CURLcode ftp_statemachine(struct Curl_easy *data,
The method used here is to check the server OS: we do it only
if the path name looks strange to minimize overhead on other
systems. */
- char *dir = Curl_dyn_ptr(&out);
+ char *dir = curlx_dyn_ptr(&out);
if(!ftpc->server_os && dir[0] != '/') {
result = Curl_pp_sendf(data, &ftpc->pp, "%s", "SYST");
@@ -2910,7 +2920,7 @@ static CURLcode ftp_statemachine(struct Curl_easy *data,
data->state.most_recent_ftp_entrypath = strdup(ftpc->entrypath);
if(!data->state.most_recent_ftp_entrypath)
return CURLE_OUT_OF_MEMORY;
- ftp_state(data, FTP_SYST);
+ ftp_state(data, ftpc, FTP_SYST);
break;
}
@@ -2925,17 +2935,17 @@ static CURLcode ftp_statemachine(struct Curl_easy *data,
}
else {
/* could not get the path */
- Curl_dyn_free(&out);
+ curlx_dyn_free(&out);
infof(data, "Failed to figure out path");
}
}
- ftp_state(data, FTP_STOP); /* we are done with the CONNECT phase! */
- CURL_TRC_FTP(data, "[%s] protocol connect phase DONE", FTP_DSTATE(data));
+ ftp_state(data, ftpc, FTP_STOP); /* we are done with CONNECT phase! */
+ CURL_TRC_FTP(data, "[%s] protocol connect phase DONE", FTP_CSTATE(ftpc));
break;
case FTP_SYST:
if(ftpcode == 215) {
- char *ptr = Curl_dyn_ptr(&pp->recvbuf) + 4; /* start on the first
+ char *ptr = curlx_dyn_ptr(&pp->recvbuf) + 4; /* start on the first
letter */
char *os;
char *start;
@@ -2962,7 +2972,7 @@ static CURLcode ftp_statemachine(struct Curl_easy *data,
/* remember target server OS */
free(ftpc->server_os);
ftpc->server_os = os;
- ftp_state(data, FTP_NAMEFMT);
+ ftp_state(data, ftpc, FTP_NAMEFMT);
break;
}
/* Nothing special for the target server. */
@@ -2974,19 +2984,19 @@ static CURLcode ftp_statemachine(struct Curl_easy *data,
/* Cannot identify server OS. Continue anyway and cross fingers. */
}
- ftp_state(data, FTP_STOP); /* we are done with the CONNECT phase! */
- CURL_TRC_FTP(data, "[%s] protocol connect phase DONE", FTP_DSTATE(data));
+ ftp_state(data, ftpc, FTP_STOP); /* we are done with CONNECT phase! */
+ CURL_TRC_FTP(data, "[%s] protocol connect phase DONE", FTP_CSTATE(ftpc));
break;
case FTP_NAMEFMT:
if(ftpcode == 250) {
/* Name format change successful: reload initial path. */
- ftp_state_pwd(data, conn);
+ ftp_state_pwd(data, ftpc);
break;
}
- ftp_state(data, FTP_STOP); /* we are done with the CONNECT phase! */
- CURL_TRC_FTP(data, "[%s] protocol connect phase DONE", FTP_DSTATE(data));
+ ftp_state(data, ftpc, FTP_STOP); /* we are done with CONNECT phase! */
+ CURL_TRC_FTP(data, "[%s] protocol connect phase DONE", FTP_CSTATE(ftpc));
break;
case FTP_QUOTE:
@@ -2999,7 +3009,7 @@ static CURLcode ftp_statemachine(struct Curl_easy *data,
result = CURLE_QUOTE_ERROR;
}
else
- result = ftp_state_quote(data, FALSE, ftpc->state);
+ result = ftp_state_quote(data, ftpc, ftp, FALSE, ftpc->state);
break;
case FTP_CWD:
@@ -3018,7 +3028,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)
- ftp_state(data, FTP_MKD);
+ ftp_state(data, ftpc, FTP_MKD);
}
else {
/* return failure */
@@ -3036,7 +3046,7 @@ static CURLcode ftp_statemachine(struct Curl_easy *data,
result = Curl_pp_sendf(data, &ftpc->pp, "CWD %s",
ftpc->dirs[ftpc->cwdcount - 1]);
else
- result = ftp_state_mdtm(data);
+ result = ftp_state_mdtm(data, ftpc, ftp);
}
break;
@@ -3047,7 +3057,7 @@ static CURLcode ftp_statemachine(struct Curl_easy *data,
result = CURLE_REMOTE_ACCESS_DENIED;
}
else {
- ftp_state(data, FTP_CWD);
+ ftp_state(data, ftpc, FTP_CWD);
/* send CWD */
result = Curl_pp_sendf(data, &ftpc->pp, "CWD %s",
ftpc->dirs[ftpc->cwdcount - 1]);
@@ -3055,25 +3065,25 @@ static CURLcode ftp_statemachine(struct Curl_easy *data,
break;
case FTP_MDTM:
- result = ftp_state_mdtm_resp(data, ftpcode);
+ result = ftp_state_mdtm_resp(data, ftpc, ftp, ftpcode);
break;
case FTP_TYPE:
case FTP_LIST_TYPE:
case FTP_RETR_TYPE:
case FTP_STOR_TYPE:
- result = ftp_state_type_resp(data, ftpcode, ftpc->state);
+ result = ftp_state_type_resp(data, ftpc, ftp, ftpcode, ftpc->state);
break;
case FTP_SIZE:
case FTP_RETR_SIZE:
case FTP_STOR_SIZE:
- result = ftp_state_size_resp(data, ftpcode, ftpc->state);
+ result = ftp_state_size_resp(data, ftpc, ftp, ftpcode, ftpc->state);
break;
case FTP_REST:
case FTP_RETR_REST:
- result = ftp_state_rest_resp(data, conn, ftpcode, ftpc->state);
+ result = ftp_state_rest_resp(data, ftpc, ftp, ftpcode, ftpc->state);
break;
case FTP_PRET:
@@ -3082,30 +3092,30 @@ static CURLcode ftp_statemachine(struct Curl_easy *data,
failf(data, "PRET command not accepted: %03d", ftpcode);
return CURLE_FTP_PRET_FAILED;
}
- result = ftp_state_use_pasv(data, conn);
+ result = ftp_state_use_pasv(data, ftpc, conn);
break;
case FTP_PASV:
- result = ftp_state_pasv_resp(data, ftpcode);
+ result = ftp_state_pasv_resp(data, ftpc, ftpcode);
break;
case FTP_PORT:
- result = ftp_state_port_resp(data, ftpcode);
+ result = ftp_state_port_resp(data, ftpc, ftp, ftpcode);
break;
case FTP_LIST:
case FTP_RETR:
- result = ftp_state_get_resp(data, ftpcode, ftpc->state);
+ result = ftp_state_get_resp(data, ftpc, ftp, ftpcode, ftpc->state);
break;
case FTP_STOR:
- result = ftp_state_stor_resp(data, ftpcode, ftpc->state);
+ result = ftp_state_stor_resp(data, ftpc, ftpcode, ftpc->state);
break;
case FTP_QUIT:
default:
/* internal error */
- ftp_state(data, FTP_STOP);
+ ftp_state(data, ftpc, FTP_STOP);
break;
}
} /* if(ftpcode) */
@@ -3115,11 +3125,10 @@ static CURLcode ftp_statemachine(struct Curl_easy *data,
/* called repeatedly until done from multi.c */
-static CURLcode ftp_multi_statemach(struct Curl_easy *data,
- bool *done)
+static CURLcode ftp_statemach(struct Curl_easy *data,
+ struct ftp_conn *ftpc,
+ bool *done)
{
- struct connectdata *conn = data->conn;
- struct ftp_conn *ftpc = &conn->proto.ftpc;
CURLcode result = Curl_pp_statemach(data, &ftpc->pp, FALSE, FALSE);
/* Check for the state outside of the Curl_socket_check() return code checks
@@ -3130,10 +3139,17 @@ static CURLcode ftp_multi_statemach(struct Curl_easy *data,
return result;
}
+/* called repeatedly until done from multi.c */
+static CURLcode ftp_multi_statemach(struct Curl_easy *data,
+ bool *done)
+{
+ struct ftp_conn *ftpc = Curl_conn_meta_get(data->conn, CURL_META_FTP_CONN);
+ return ftpc ? ftp_statemach(data, ftpc, done) : CURLE_FAILED_INIT;
+}
+
static CURLcode ftp_block_statemach(struct Curl_easy *data,
- struct connectdata *conn)
+ struct ftp_conn *ftpc)
{
- struct ftp_conn *ftpc = &conn->proto.ftpc;
struct pingpong *pp = &ftpc->pp;
CURLcode result = CURLE_OK;
@@ -3161,15 +3177,17 @@ static CURLcode ftp_connect(struct Curl_easy *data,
{
CURLcode result;
struct connectdata *conn = data->conn;
- struct ftp_conn *ftpc = &conn->proto.ftpc;
- struct pingpong *pp = &ftpc->pp;
+ struct ftp_conn *ftpc = Curl_conn_meta_get(data->conn, CURL_META_FTP_CONN);
+ struct pingpong *pp;
*done = FALSE; /* default to not done yet */
-
+ if(!ftpc)
+ return CURLE_FAILED_INIT;
+ pp = &ftpc->pp;
/* We always support persistent connections on ftp */
connkeep(conn, "FTP default");
- PINGPONG_SETUP(pp, ftp_statemachine, ftp_endofresp);
+ PINGPONG_SETUP(pp, ftp_pp_statemachine, ftp_endofresp);
if(Curl_conn_is_ssl(conn, FIRSTSOCKET)) {
/* BLOCKING */
@@ -3183,9 +3201,9 @@ static CURLcode ftp_connect(struct Curl_easy *data,
/* When we connect, we start in the state where we await the 220
response */
- ftp_state(data, FTP_WAIT220);
+ ftp_state(data, ftpc, FTP_WAIT220);
- result = ftp_multi_statemach(data, done);
+ result = ftp_statemach(data, ftpc, done);
return result;
}
@@ -3203,18 +3221,19 @@ static CURLcode ftp_done(struct Curl_easy *data, CURLcode status,
bool premature)
{
struct connectdata *conn = data->conn;
- struct FTP *ftp = data->req.p.ftp;
- struct ftp_conn *ftpc = &conn->proto.ftpc;
- struct pingpong *pp = &ftpc->pp;
+ struct FTP *ftp = Curl_meta_get(data, CURL_META_FTP_EASY);
+ struct ftp_conn *ftpc = Curl_conn_meta_get(data->conn, CURL_META_FTP_CONN);
+ struct pingpong *pp;
ssize_t nread;
int ftpcode;
CURLcode result = CURLE_OK;
char *rawPath = NULL;
size_t pathLen = 0;
- if(!ftp)
+ if(!ftp || !ftpc)
return CURLE_OK;
+ pp = &ftpc->pp;
switch(status) {
case CURLE_BAD_DOWNLOAD_RESUME:
case CURLE_FTP_WEIRD_PASV_REPLY:
@@ -3315,7 +3334,7 @@ static CURLcode ftp_done(struct Curl_easy *data, CURLcode status,
}
}
- close_secondarysocket(data);
+ close_secondarysocket(data, ftpc);
}
if(!result && (ftp->transfer == PPTRANSFER_BODY) && ftpc->ctl_valid &&
@@ -3329,7 +3348,7 @@ static CURLcode ftp_done(struct Curl_easy *data, CURLcode status,
timediff_t old_time = pp->response_time;
pp->response_time = 60*1000; /* give it only a minute for now */
- pp->response = Curl_now(); /* timeout relative now */
+ pp->response = curlx_now(); /* timeout relative now */
result = Curl_GetFTPResponse(data, &nread, &ftpcode);
@@ -3341,10 +3360,8 @@ static CURLcode ftp_done(struct Curl_easy *data, CURLcode status,
connclose(conn, "Timeout or similar in FTP DONE operation"); /* close */
}
- if(result) {
- Curl_safefree(ftp->pathalloc);
+ if(result)
return result;
- }
if(ftpc->dont_check && data->req.maxdownload > 0) {
/* we have just sent ABOR and there is no reliable way to check if it was
@@ -3412,9 +3429,8 @@ static CURLcode ftp_done(struct Curl_easy *data, CURLcode status,
/* Send any post-transfer QUOTE strings? */
if(!status && !result && !premature && data->set.postquote)
- result = ftp_sendquote(data, conn, data->set.postquote);
- CURL_TRC_FTP(data, "[%s] done, result=%d", FTP_DSTATE(data), result);
- Curl_safefree(ftp->pathalloc);
+ result = ftp_sendquote(data, ftpc, data->set.postquote);
+ CURL_TRC_FTP(data, "[%s] done, result=%d", FTP_CSTATE(ftpc), result);
return result;
}
@@ -3430,10 +3446,10 @@ static CURLcode ftp_done(struct Curl_easy *data, CURLcode status,
static
CURLcode ftp_sendquote(struct Curl_easy *data,
- struct connectdata *conn, struct curl_slist *quote)
+ struct ftp_conn *ftpc,
+ struct curl_slist *quote)
{
struct curl_slist *item;
- struct ftp_conn *ftpc = &conn->proto.ftpc;
struct pingpong *pp = &ftpc->pp;
item = quote;
@@ -3457,7 +3473,7 @@ CURLcode ftp_sendquote(struct Curl_easy *data,
result = Curl_pp_sendf(data, &ftpc->pp, "%s", cmd);
if(!result) {
- pp->response = Curl_now(); /* timeout relative now */
+ pp->response = curlx_now(); /* timeout relative now */
result = Curl_GetFTPResponse(data, &nread, &ftpcode);
}
if(result)
@@ -3481,10 +3497,10 @@ CURLcode ftp_sendquote(struct Curl_easy *data,
*
* Returns TRUE if we in the current situation should send TYPE
*/
-static int ftp_need_type(struct connectdata *conn,
+static int ftp_need_type(struct ftp_conn *ftpc,
bool ascii_wanted)
{
- return conn->proto.ftpc.transfertype != (ascii_wanted ? 'A' : 'I');
+ return ftpc->transfertype != (ascii_wanted ? 'A' : 'I');
}
/***********************************************************************
@@ -3496,21 +3512,21 @@ static int ftp_need_type(struct connectdata *conn,
* If the transfer type is not sent, simulate on OK response in newstate
*/
static CURLcode ftp_nb_type(struct Curl_easy *data,
- struct connectdata *conn,
+ struct ftp_conn *ftpc,
+ struct FTP *ftp,
bool ascii, ftpstate newstate)
{
- struct ftp_conn *ftpc = &conn->proto.ftpc;
CURLcode result;
char want = (char)(ascii ? 'A' : 'I');
if(ftpc->transfertype == want) {
- ftp_state(data, newstate);
- return ftp_state_type_resp(data, 200, newstate);
+ ftp_state(data, ftpc, newstate);
+ return ftp_state_type_resp(data, ftpc, ftp, 200, newstate);
}
result = Curl_pp_sendf(data, &ftpc->pp, "TYPE %c", want);
if(!result) {
- ftp_state(data, newstate);
+ ftp_state(data, ftpc, newstate);
/* keep track of our current transfer type */
ftpc->transfertype = want;
@@ -3554,16 +3570,17 @@ ftp_pasv_verbose(struct Curl_easy *data,
static CURLcode ftp_do_more(struct Curl_easy *data, int *completep)
{
struct connectdata *conn = data->conn;
- struct ftp_conn *ftpc = &conn->proto.ftpc;
+ struct ftp_conn *ftpc = Curl_conn_meta_get(data->conn, CURL_META_FTP_CONN);
+ struct FTP *ftp = Curl_meta_get(data, CURL_META_FTP_EASY);
CURLcode result = CURLE_OK;
bool connected = FALSE;
bool complete = FALSE;
-
/* the ftp struct is inited in ftp_connect(). If we are connecting to an HTTP
* proxy then the state will not be valid until after that connection is
* complete */
- struct FTP *ftp = NULL;
+ if(!ftpc || !ftp)
+ return CURLE_FAILED_INIT;
/* if the second connection has been set up, try to connect it fully
* to the remote host. This may not complete at this time, for several
* reasons:
@@ -3580,20 +3597,17 @@ static CURLcode ftp_do_more(struct Curl_easy *data, int *completep)
if(result && !is_eptr && (ftpc->count1 == 0)) {
*completep = -1; /* go back to DOING please */
/* this is a EPSV connect failing, try PASV instead */
- return ftp_epsv_disable(data, conn);
+ return ftp_epsv_disable(data, ftpc, conn);
}
*completep = (int)complete;
return result;
}
}
- /* Curl_proxy_connect might have moved the protocol state */
- ftp = data->req.p.ftp;
-
if(ftpc->state) {
/* already in a state so skip the initial commands.
They are only done to kickstart the do_more state */
- result = ftp_multi_statemach(data, &complete);
+ result = ftp_statemach(data, ftpc, &complete);
*completep = (int)complete;
@@ -3622,7 +3636,7 @@ static CURLcode ftp_do_more(struct Curl_easy *data, int *completep)
if(serv_conned) {
/* It looks data connection is established */
ftpc->wait_data_conn = FALSE;
- result = InitiateTransfer(data);
+ result = ftp_initiate_transfer(data, ftpc);
if(result)
return result;
@@ -3631,19 +3645,23 @@ static CURLcode ftp_do_more(struct Curl_easy *data, int *completep)
connected back to us */
}
else {
- result = ftp_check_ctrl_on_data_wait(data);
+ result = ftp_check_ctrl_on_data_wait(data, ftpc);
if(result)
return result;
}
}
else if(data->state.upload) {
- result = ftp_nb_type(data, conn, data->state.prefer_ascii,
+ result = ftp_nb_type(data, ftpc, ftp, data->state.prefer_ascii,
FTP_STOR_TYPE);
if(result)
return result;
- result = ftp_multi_statemach(data, &complete);
- *completep = (int)complete;
+ result = ftp_statemach(data, ftpc, &complete);
+ /* ftp_nb_type() might have skipped sending `TYPE A|I` when not
+ * deemed necessary and directly sent `STORE name`. If this was
+ * then complete, but we are still waiting on the data connection,
+ * the transfer has not been initiated yet. */
+ *completep = (int)(ftpc->wait_data_conn ? 0 : complete);
}
else {
/* download */
@@ -3665,20 +3683,20 @@ static CURLcode ftp_do_more(struct Curl_easy *data, int *completep)
/* But only if a body transfer was requested. */
if(ftp->transfer == PPTRANSFER_BODY) {
- result = ftp_nb_type(data, conn, TRUE, FTP_LIST_TYPE);
+ result = ftp_nb_type(data, ftpc, ftp, TRUE, FTP_LIST_TYPE);
if(result)
return result;
}
/* otherwise just fall through */
}
else {
- result = ftp_nb_type(data, conn, data->state.prefer_ascii,
+ result = ftp_nb_type(data, ftpc, ftp, data->state.prefer_ascii,
FTP_RETR_TYPE);
if(result)
return result;
}
- result = ftp_multi_statemach(data, &complete);
+ result = ftp_statemach(data, ftpc, &complete);
*completep = (int)complete;
}
return result;
@@ -3690,7 +3708,7 @@ static CURLcode ftp_do_more(struct Curl_easy *data, int *completep)
if(!ftpc->wait_data_conn) {
/* no waiting for the data connection so this is now complete */
*completep = 1;
- CURL_TRC_FTP(data, "[%s] DO-MORE phase ends with %d", FTP_DSTATE(data),
+ CURL_TRC_FTP(data, "[%s] DO-MORE phase ends with %d", FTP_CSTATE(ftpc),
(int)result);
}
@@ -3709,41 +3727,42 @@ static CURLcode ftp_do_more(struct Curl_easy *data, int *completep)
static
CURLcode ftp_perform(struct Curl_easy *data,
+ struct ftp_conn *ftpc,
+ struct FTP *ftp,
bool *connected, /* connect status after PASV / PORT */
bool *dophase_done)
{
/* this is FTP and no proxy */
CURLcode result = CURLE_OK;
- CURL_TRC_FTP(data, "[%s] DO phase starts", FTP_DSTATE(data));
+ CURL_TRC_FTP(data, "[%s] DO phase starts", FTP_CSTATE(ftpc));
if(data->req.no_body) {
/* requested no body means no transfer... */
- struct FTP *ftp = data->req.p.ftp;
ftp->transfer = PPTRANSFER_INFO;
}
*dophase_done = FALSE; /* not done yet */
/* start the first command in the DO phase */
- result = ftp_state_quote(data, TRUE, FTP_QUOTE);
+ result = ftp_state_quote(data, ftpc, ftp, TRUE, FTP_QUOTE);
if(result)
return result;
/* run the state-machine */
- result = ftp_multi_statemach(data, dophase_done);
+ result = ftp_statemach(data, ftpc, dophase_done);
*connected = Curl_conn_is_connected(data->conn, SECONDARYSOCKET);
if(*connected)
infof(data, "[FTP] [%s] perform, DATA connection established",
- FTP_DSTATE(data));
+ FTP_CSTATE(ftpc));
else
CURL_TRC_FTP(data, "[%s] perform, awaiting DATA connect",
- FTP_DSTATE(data));
+ FTP_CSTATE(ftpc));
if(*dophase_done)
- CURL_TRC_FTP(data, "[%s] DO phase is complete1", FTP_DSTATE(data));
+ CURL_TRC_FTP(data, "[%s] DO phase is complete1", FTP_CSTATE(ftpc));
return result;
}
@@ -3756,10 +3775,11 @@ static void wc_data_dtor(void *ptr)
free(ftpwc);
}
-static CURLcode init_wc_data(struct Curl_easy *data)
+static CURLcode init_wc_data(struct Curl_easy *data,
+ struct ftp_conn *ftpc,
+ struct FTP *ftp)
{
char *last_slash;
- struct FTP *ftp = data->req.p.ftp;
char *path = ftp->path;
struct WildcardData *wildcard = data->wildcard;
CURLcode result = CURLE_OK;
@@ -3770,7 +3790,7 @@ static CURLcode init_wc_data(struct Curl_easy *data)
last_slash++;
if(last_slash[0] == '\0') {
wildcard->state = CURLWC_CLEAN;
- return ftp_parse_url_path(data);
+ return ftp_parse_url_path(data, ftpc, ftp);
}
wildcard->pattern = strdup(last_slash);
if(!wildcard->pattern)
@@ -3786,7 +3806,7 @@ static CURLcode init_wc_data(struct Curl_easy *data)
}
else { /* only list */
wildcard->state = CURLWC_CLEAN;
- return ftp_parse_url_path(data);
+ return ftp_parse_url_path(data, ftpc, ftp);
}
}
@@ -3815,7 +3835,7 @@ static CURLcode init_wc_data(struct Curl_easy *data)
data->set.ftp_filemethod = FTPFILE_MULTICWD;
/* try to parse ftp URL */
- result = ftp_parse_url_path(data);
+ result = ftp_parse_url_path(data, ftpc, ftp);
if(result) {
goto fail;
}
@@ -3849,16 +3869,17 @@ fail:
return result;
}
-static CURLcode wc_statemach(struct Curl_easy *data)
+static CURLcode wc_statemach(struct Curl_easy *data,
+ struct ftp_conn *ftpc,
+ struct FTP *ftp)
{
struct WildcardData * const wildcard = data->wildcard;
- struct connectdata *conn = data->conn;
CURLcode result = CURLE_OK;
for(;;) {
switch(wildcard->state) {
case CURLWC_INIT:
- result = init_wc_data(data);
+ result = init_wc_data(data, ftpc, ftp);
if(wildcard->state == CURLWC_CLEAN)
/* only listing! */
return result;
@@ -3890,10 +3911,8 @@ static CURLcode wc_statemach(struct Curl_easy *data)
case CURLWC_DOWNLOADING: {
/* filelist has at least one file, lets get first one */
- struct ftp_conn *ftpc = &conn->proto.ftpc;
struct Curl_llist_node *head = Curl_llist_head(&wildcard->filelist);
struct curl_fileinfo *finfo = Curl_node_elem(head);
- struct FTP *ftp = data->req.p.ftp;
char *tmp_path = aprintf("%s%s", wildcard->path, finfo->filename);
if(!tmp_path)
@@ -3930,7 +3949,7 @@ static CURLcode wc_statemach(struct Curl_easy *data)
if(finfo->flags & CURLFINFOFLAG_KNOWN_SIZE)
ftpc->known_filesize = finfo->size;
- result = ftp_parse_url_path(data);
+ result = ftp_parse_url_path(data, ftpc, ftp);
if(result)
return result;
@@ -3994,10 +4013,12 @@ static CURLcode wc_statemach(struct Curl_easy *data)
static CURLcode ftp_do(struct Curl_easy *data, bool *done)
{
CURLcode result = CURLE_OK;
- struct connectdata *conn = data->conn;
- struct ftp_conn *ftpc = &conn->proto.ftpc;
+ struct ftp_conn *ftpc = Curl_conn_meta_get(data->conn, CURL_META_FTP_CONN);
+ struct FTP *ftp = Curl_meta_get(data, CURL_META_FTP_EASY);
*done = FALSE; /* default to false */
+ if(!ftpc || !ftp)
+ return CURLE_FAILED_INIT;
ftpc->wait_data_conn = FALSE; /* default to no such wait */
#ifdef CURL_PREFER_LF_LINEENDS
@@ -4019,7 +4040,7 @@ static CURLcode ftp_do(struct Curl_easy *data, bool *done)
#endif /* CURL_PREFER_LF_LINEENDS */
if(data->state.wildcardmatch) {
- result = wc_statemach(data);
+ result = wc_statemach(data, ftpc, ftp);
if(data->wildcard->state == CURLWC_SKIP ||
data->wildcard->state == CURLWC_DONE) {
/* do not call ftp_regular_transfer */
@@ -4029,12 +4050,12 @@ static CURLcode ftp_do(struct Curl_easy *data, bool *done)
return result;
}
else { /* no wildcard FSM needed */
- result = ftp_parse_url_path(data);
+ result = ftp_parse_url_path(data, ftpc, ftp);
if(result)
return result;
}
- result = ftp_regular_transfer(data, done);
+ result = ftp_regular_transfer(data, ftpc, ftp, done);
return result;
}
@@ -4049,25 +4070,26 @@ static CURLcode ftp_do(struct Curl_easy *data, bool *done)
* connection.
*
*/
-static CURLcode ftp_quit(struct Curl_easy *data, struct connectdata *conn)
+static CURLcode ftp_quit(struct Curl_easy *data,
+ struct ftp_conn *ftpc)
{
CURLcode result = CURLE_OK;
- if(conn->proto.ftpc.ctl_valid) {
+ if(ftpc->ctl_valid) {
CURL_TRC_FTP(data, "sending QUIT to close session");
- result = Curl_pp_sendf(data, &conn->proto.ftpc.pp, "%s", "QUIT");
+ result = Curl_pp_sendf(data, &ftpc->pp, "%s", "QUIT");
if(result) {
failf(data, "Failure sending QUIT command: %s",
curl_easy_strerror(result));
- conn->proto.ftpc.ctl_valid = FALSE; /* mark control connection as bad */
- connclose(conn, "QUIT command failed"); /* mark for connection closure */
- ftp_state(data, FTP_STOP);
+ ftpc->ctl_valid = FALSE; /* mark control connection as bad */
+ connclose(data->conn, "QUIT command failed"); /* mark for closure */
+ ftp_state(data, ftpc, FTP_STOP);
return result;
}
- ftp_state(data, FTP_QUIT);
+ ftp_state(data, ftpc, FTP_QUIT);
- result = ftp_block_statemach(data, conn);
+ result = ftp_block_statemach(data, ftpc);
}
return result;
@@ -4084,9 +4106,10 @@ static CURLcode ftp_disconnect(struct Curl_easy *data,
struct connectdata *conn,
bool dead_connection)
{
- struct ftp_conn *ftpc = &conn->proto.ftpc;
- struct pingpong *pp = &ftpc->pp;
+ struct ftp_conn *ftpc = Curl_conn_meta_get(conn, CURL_META_FTP_CONN);
+ if(!ftpc)
+ return CURLE_FAILED_INIT;
/* We cannot send quit unconditionally. If this connection is stale or
bad in any way, sending quit and waiting around here will make the
disconnect wait in vain and cause more problems than we need to.
@@ -4099,15 +4122,7 @@ static CURLcode ftp_disconnect(struct Curl_easy *data,
ftpc->ctl_valid = FALSE;
/* The FTP session may or may not have been allocated/setup at this point! */
- (void)ftp_quit(data, conn); /* ignore errors on the QUIT */
-
- freedirs(ftpc);
- Curl_safefree(ftpc->account);
- Curl_safefree(ftpc->alternative_to_user);
- Curl_safefree(ftpc->entrypath);
- Curl_safefree(ftpc->prevpath);
- Curl_safefree(ftpc->server_os);
- Curl_pp_disconnect(pp);
+ (void)ftp_quit(data, ftpc); /* ignore errors on the QUIT */
return CURLE_OK;
}
@@ -4119,12 +4134,10 @@ static CURLcode ftp_disconnect(struct Curl_easy *data,
*
*/
static
-CURLcode ftp_parse_url_path(struct Curl_easy *data)
+CURLcode ftp_parse_url_path(struct Curl_easy *data,
+ struct ftp_conn *ftpc,
+ struct FTP *ftp)
{
- /* the ftp struct is already inited in ftp_connect() */
- struct FTP *ftp = data->req.p.ftp;
- struct connectdata *conn = data->conn;
- struct ftp_conn *ftpc = &conn->proto.ftpc;
const char *slashPos = NULL;
const char *fileName = NULL;
CURLcode result = CURLE_OK;
@@ -4247,7 +4260,7 @@ CURLcode ftp_parse_url_path(struct Curl_easy *data)
if((data->set.ftp_filemethod == FTPFILE_NOCWD) && (rawPath[0] == '/'))
ftpc->cwddone = TRUE; /* skip CWD for absolute paths */
else { /* newly created FTP connections are already in entry path */
- const char *oldPath = conn->bits.reuse ? ftpc->prevpath : "";
+ const char *oldPath = data->conn->bits.reuse ? ftpc->prevpath : "";
if(oldPath) {
size_t n = pathLen;
if(data->set.ftp_filemethod == FTPFILE_NOCWD)
@@ -4267,18 +4280,17 @@ CURLcode ftp_parse_url_path(struct Curl_easy *data)
}
/* call this when the DO phase has completed */
-static CURLcode ftp_dophase_done(struct Curl_easy *data, bool connected)
+static CURLcode ftp_dophase_done(struct Curl_easy *data,
+ struct ftp_conn *ftpc,
+ struct FTP *ftp,
+ bool connected)
{
- struct connectdata *conn = data->conn;
- struct FTP *ftp = data->req.p.ftp;
- struct ftp_conn *ftpc = &conn->proto.ftpc;
-
if(connected) {
int completed;
CURLcode result = ftp_do_more(data, &completed);
if(result) {
- close_secondarysocket(data);
+ close_secondarysocket(data, ftpc);
return result;
}
}
@@ -4288,7 +4300,7 @@ static CURLcode ftp_dophase_done(struct Curl_easy *data, bool connected)
Curl_xfer_setup_nop(data);
else if(!connected)
/* since we did not connect now, we want do_more to get called */
- conn->bits.do_more = TRUE;
+ data->conn->bits.do_more = TRUE;
ftpc->ctl_valid = TRUE; /* seems good */
@@ -4299,14 +4311,20 @@ static CURLcode ftp_dophase_done(struct Curl_easy *data, bool connected)
static CURLcode ftp_doing(struct Curl_easy *data,
bool *dophase_done)
{
- CURLcode result = ftp_multi_statemach(data, dophase_done);
+ struct ftp_conn *ftpc = Curl_conn_meta_get(data->conn, CURL_META_FTP_CONN);
+ struct FTP *ftp = Curl_meta_get(data, CURL_META_FTP_EASY);
+ CURLcode result;
+
+ if(!ftpc || !ftp)
+ return CURLE_FAILED_INIT;
+ result = ftp_statemach(data, ftpc, dophase_done);
if(result)
- CURL_TRC_FTP(data, "[%s] DO phase failed", FTP_DSTATE(data));
+ CURL_TRC_FTP(data, "[%s] DO phase failed", FTP_CSTATE(ftpc));
else if(*dophase_done) {
- result = ftp_dophase_done(data, FALSE /* not connected */);
+ result = ftp_dophase_done(data, ftpc, ftp, FALSE /* not connected */);
- CURL_TRC_FTP(data, "[%s] DO phase is complete2", FTP_DSTATE(data));
+ CURL_TRC_FTP(data, "[%s] DO phase is complete2", FTP_CSTATE(ftpc));
}
return result;
}
@@ -4325,12 +4343,12 @@ static CURLcode ftp_doing(struct Curl_easy *data,
*/
static
CURLcode ftp_regular_transfer(struct Curl_easy *data,
+ struct ftp_conn *ftpc,
+ struct FTP *ftp,
bool *dophase_done)
{
CURLcode result = CURLE_OK;
bool connected = FALSE;
- struct connectdata *conn = data->conn;
- struct ftp_conn *ftpc = &conn->proto.ftpc;
data->req.size = -1; /* make sure this is unknown at this point */
Curl_pgrsSetUploadCounter(data, 0);
@@ -4340,7 +4358,7 @@ CURLcode ftp_regular_transfer(struct Curl_easy *data,
ftpc->ctl_valid = TRUE; /* starts good */
- result = ftp_perform(data,
+ result = ftp_perform(data, ftpc, ftp,
&connected, /* have we connected after PASV/PORT */
dophase_done); /* all commands in the DO-phase done? */
@@ -4350,7 +4368,7 @@ CURLcode ftp_regular_transfer(struct Curl_easy *data,
/* the DO phase has not completed yet */
return CURLE_OK;
- result = ftp_dophase_done(data, connected);
+ result = ftp_dophase_done(data, ftpc, ftp, connected);
if(result)
return result;
@@ -4361,23 +4379,53 @@ CURLcode ftp_regular_transfer(struct Curl_easy *data,
return result;
}
+static void ftp_easy_dtor(void *key, size_t klen, void *entry)
+{
+ struct FTP *ftp = entry;
+ (void)key;
+ (void)klen;
+ Curl_safefree(ftp->pathalloc);
+ free(ftp);
+}
+
+static void ftp_conn_dtor(void *key, size_t klen, void *entry)
+{
+ struct ftp_conn *ftpc = entry;
+ (void)key;
+ (void)klen;
+ freedirs(ftpc);
+ Curl_safefree(ftpc->account);
+ Curl_safefree(ftpc->alternative_to_user);
+ Curl_safefree(ftpc->entrypath);
+ Curl_safefree(ftpc->prevpath);
+ Curl_safefree(ftpc->server_os);
+ Curl_pp_disconnect(&ftpc->pp);
+ free(ftpc);
+}
+
static CURLcode ftp_setup_connection(struct Curl_easy *data,
struct connectdata *conn)
{
char *type;
struct FTP *ftp;
CURLcode result = CURLE_OK;
- struct ftp_conn *ftpc = &conn->proto.ftpc;
+ struct ftp_conn *ftpc;
+
+ ftp = calloc(1, sizeof(*ftp));
+ if(!ftp ||
+ Curl_meta_set(data, CURL_META_FTP_EASY, ftp, ftp_easy_dtor))
+ return CURLE_OUT_OF_MEMORY;
- ftp = calloc(1, sizeof(struct FTP));
- if(!ftp)
+ ftpc = calloc(1, sizeof(*ftpc));
+ if(!ftpc ||
+ Curl_conn_meta_set(conn, CURL_META_FTP_CONN, ftpc, ftp_conn_dtor))
return CURLE_OUT_OF_MEMORY;
/* clone connection related data that is FTP specific */
if(data->set.str[STRING_FTP_ACCOUNT]) {
ftpc->account = strdup(data->set.str[STRING_FTP_ACCOUNT]);
if(!ftpc->account) {
- free(ftp);
+ Curl_conn_meta_remove(conn, CURL_META_FTP_CONN);
return CURLE_OUT_OF_MEMORY;
}
}
@@ -4386,11 +4434,10 @@ static CURLcode ftp_setup_connection(struct Curl_easy *data,
strdup(data->set.str[STRING_FTP_ALTERNATIVE_TO_USER]);
if(!ftpc->alternative_to_user) {
Curl_safefree(ftpc->account);
- free(ftp);
+ Curl_conn_meta_remove(conn, CURL_META_FTP_CONN);
return CURLE_OUT_OF_MEMORY;
}
}
- data->req.p.ftp = ftp;
ftp->path = &data->state.up.path[1]; /* do not include the initial slash */
@@ -4430,8 +4477,23 @@ static CURLcode ftp_setup_connection(struct Curl_easy *data,
ftpc->use_ssl = data->set.use_ssl;
ftpc->ccc = data->set.ftp_ccc;
- CURL_TRC_FTP(data, "[%s] setup connection -> %d", FTP_CSTATE(conn), result);
+ CURL_TRC_FTP(data, "[%s] setup connection -> %d", FTP_CSTATE(ftpc), result);
return result;
}
+bool ftp_conns_match(struct connectdata *needle, struct connectdata *conn)
+{
+ struct ftp_conn *nftpc = Curl_conn_meta_get(needle, CURL_META_FTP_CONN);
+ struct ftp_conn *cftpc = Curl_conn_meta_get(conn, CURL_META_FTP_CONN);
+ /* Also match ACCOUNT, ALTERNATIVE-TO-USER, USE_SSL and CCC options */
+ if(!nftpc || !cftpc ||
+ Curl_timestrcmp(nftpc->account, cftpc->account) ||
+ Curl_timestrcmp(nftpc->alternative_to_user,
+ cftpc->alternative_to_user) ||
+ (nftpc->use_ssl != cftpc->use_ssl) ||
+ (nftpc->ccc != cftpc->ccc))
+ return FALSE;
+ return TRUE;
+}
+
#endif /* CURL_DISABLE_FTP */
diff --git a/libs/libcurl/src/ftp.h b/libs/libcurl/src/ftp.h
index ef133a074b..c210cbc87c 100644
--- a/libs/libcurl/src/ftp.h
+++ b/libs/libcurl/src/ftp.h
@@ -37,6 +37,9 @@ extern const struct Curl_handler Curl_handler_ftps;
CURLcode Curl_GetFTPResponse(struct Curl_easy *data, ssize_t *nread,
int *ftpcode);
+
+bool ftp_conns_match(struct connectdata *needle, struct connectdata *conn);
+
#endif /* CURL_DISABLE_FTP */
/****************************************************************************
@@ -163,6 +166,11 @@ struct ftp_conn {
BIT(shutdown); /* connection is being shutdown, e.g. QUIT */
};
+/* meta key for storing `struct FTP` as easy meta data */
+#define CURL_META_FTP_EASY "meta:proto:ftp:easy"
+/* meta key for storing `struct ftp_conn` as connection meta data */
+#define CURL_META_FTP_CONN "meta:proto:ftp:conn"
+
#define DEFAULT_ACCEPT_TIMEOUT 60000 /* milliseconds == one minute */
#endif /* HEADER_CURL_FTP_H */
diff --git a/libs/libcurl/src/ftplistparser.c b/libs/libcurl/src/ftplistparser.c
index 31b8d0463e..67470bd55f 100644
--- a/libs/libcurl/src/ftplistparser.c
+++ b/libs/libcurl/src/ftplistparser.c
@@ -50,7 +50,7 @@
#include "ftplistparser.h"
#include "curl_fnmatch.h"
#include "multiif.h"
-#include "strparse.h"
+#include "curlx/strparse.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
@@ -318,7 +318,7 @@ static CURLcode ftp_pl_insert_finfo(struct Curl_easy *data,
struct curl_fileinfo *finfo = &infop->info;
/* set the finfo pointers */
- char *str = Curl_dyn_ptr(&infop->buf);
+ char *str = curlx_dyn_ptr(&infop->buf);
finfo->filename = str + parser->offsets.filename;
finfo->strings.group = parser->offsets.group ?
str + parser->offsets.group : NULL;
@@ -363,6 +363,574 @@ static CURLcode ftp_pl_insert_finfo(struct Curl_easy *data,
#define MAX_FTPLIST_BUFFER 10000 /* arbitrarily set */
+static CURLcode unix_filetype(const char c, curlfiletype *t)
+{
+ switch(c) {
+ case '-':
+ *t = CURLFILETYPE_FILE;
+ break;
+ case 'd':
+ *t = CURLFILETYPE_DIRECTORY;
+ break;
+ case 'l':
+ *t = CURLFILETYPE_SYMLINK;
+ break;
+ case 'p':
+ *t = CURLFILETYPE_NAMEDPIPE;
+ break;
+ case 's':
+ *t = CURLFILETYPE_SOCKET;
+ break;
+ case 'c':
+ *t = CURLFILETYPE_DEVICE_CHAR;
+ break;
+ case 'b':
+ *t = CURLFILETYPE_DEVICE_BLOCK;
+ break;
+ case 'D':
+ *t = CURLFILETYPE_DOOR;
+ break;
+ default:
+ return CURLE_FTP_BAD_FILE_LIST;
+ }
+ return CURLE_OK;
+}
+
+static CURLcode parse_unix(struct Curl_easy *data,
+ struct ftp_parselist_data *parser,
+ struct fileinfo *infop,
+ const char c)
+{
+ struct curl_fileinfo *finfo = &infop->info;
+ size_t len = curlx_dyn_len(&infop->buf);
+ char *mem = curlx_dyn_ptr(&infop->buf);
+ CURLcode result = CURLE_OK;
+
+ switch(parser->state.UNIX.main) {
+ case PL_UNIX_TOTALSIZE:
+ switch(parser->state.UNIX.sub.total_dirsize) {
+ case PL_UNIX_TOTALSIZE_INIT:
+ if(c == 't') {
+ parser->state.UNIX.sub.total_dirsize = PL_UNIX_TOTALSIZE_READING;
+ parser->item_length++;
+ }
+ else {
+ parser->state.UNIX.main = PL_UNIX_FILETYPE;
+ /* continue to fall through */
+ }
+ break;
+ case PL_UNIX_TOTALSIZE_READING:
+ parser->item_length++;
+ if(c == '\r') {
+ parser->item_length--;
+ if(len)
+ curlx_dyn_setlen(&infop->buf, --len);
+ }
+ else if(c == '\n') {
+ mem[parser->item_length - 1] = 0;
+ if(!strncmp("total ", mem, 6)) {
+ const char *endptr = mem + 6;
+ /* here we can deal with directory size, pass the leading
+ whitespace and then the digits */
+ curlx_str_passblanks(&endptr);
+ while(ISDIGIT(*endptr))
+ endptr++;
+ if(*endptr) {
+ return CURLE_FTP_BAD_FILE_LIST;
+ }
+ parser->state.UNIX.main = PL_UNIX_FILETYPE;
+ curlx_dyn_reset(&infop->buf);
+ }
+ else
+ return CURLE_FTP_BAD_FILE_LIST;
+
+ }
+ break;
+ }
+ if(parser->state.UNIX.main != PL_UNIX_FILETYPE)
+ break;
+ FALLTHROUGH();
+ case PL_UNIX_FILETYPE:
+ result = unix_filetype(c, &finfo->filetype);
+ if(result)
+ return result;
+ parser->state.UNIX.main = PL_UNIX_PERMISSION;
+ parser->item_length = 0;
+ parser->item_offset = 1;
+ break;
+ case PL_UNIX_PERMISSION:
+ parser->item_length++;
+ if((parser->item_length <= 9) && !strchr("rwx-tTsS", c))
+ return CURLE_FTP_BAD_FILE_LIST;
+
+ else if(parser->item_length == 10) {
+ unsigned int perm;
+ if(c != ' ')
+ return CURLE_FTP_BAD_FILE_LIST;
+
+ mem[10] = 0; /* terminate permissions */
+ perm = ftp_pl_get_permission(mem + parser->item_offset);
+ if(perm & FTP_LP_MALFORMATED_PERM)
+ return CURLE_FTP_BAD_FILE_LIST;
+
+ parser->file_data->info.flags |= CURLFINFOFLAG_KNOWN_PERM;
+ parser->file_data->info.perm = perm;
+ parser->offsets.perm = parser->item_offset;
+
+ parser->item_length = 0;
+ parser->state.UNIX.main = PL_UNIX_HLINKS;
+ parser->state.UNIX.sub.hlinks = PL_UNIX_HLINKS_PRESPACE;
+ }
+ break;
+ case PL_UNIX_HLINKS:
+ switch(parser->state.UNIX.sub.hlinks) {
+ case PL_UNIX_HLINKS_PRESPACE:
+ if(c != ' ') {
+ if(ISDIGIT(c) && len) {
+ parser->item_offset = len - 1;
+ parser->item_length = 1;
+ parser->state.UNIX.sub.hlinks = PL_UNIX_HLINKS_NUMBER;
+ }
+ else
+ return CURLE_FTP_BAD_FILE_LIST;
+ }
+ break;
+ case PL_UNIX_HLINKS_NUMBER:
+ parser->item_length ++;
+ if(c == ' ') {
+ const char *p = &mem[parser->item_offset];
+ curl_off_t hlinks;
+ mem[parser->item_offset + parser->item_length - 1] = 0;
+
+ if(!curlx_str_number(&p, &hlinks, LONG_MAX)) {
+ parser->file_data->info.flags |= CURLFINFOFLAG_KNOWN_HLINKCOUNT;
+ parser->file_data->info.hardlinks = (long)hlinks;
+ }
+ parser->item_length = 0;
+ parser->item_offset = 0;
+ parser->state.UNIX.main = PL_UNIX_USER;
+ parser->state.UNIX.sub.user = PL_UNIX_USER_PRESPACE;
+ }
+ else if(!ISDIGIT(c))
+ return CURLE_FTP_BAD_FILE_LIST;
+
+ break;
+ }
+ break;
+ case PL_UNIX_USER:
+ switch(parser->state.UNIX.sub.user) {
+ case PL_UNIX_USER_PRESPACE:
+ if(c != ' ' && len) {
+ parser->item_offset = len - 1;
+ parser->item_length = 1;
+ parser->state.UNIX.sub.user = PL_UNIX_USER_PARSING;
+ }
+ break;
+ case PL_UNIX_USER_PARSING:
+ parser->item_length++;
+ if(c == ' ') {
+ mem[parser->item_offset + parser->item_length - 1] = 0;
+ parser->offsets.user = parser->item_offset;
+ parser->state.UNIX.main = PL_UNIX_GROUP;
+ parser->state.UNIX.sub.group = PL_UNIX_GROUP_PRESPACE;
+ parser->item_offset = 0;
+ parser->item_length = 0;
+ }
+ break;
+ }
+ break;
+ case PL_UNIX_GROUP:
+ switch(parser->state.UNIX.sub.group) {
+ case PL_UNIX_GROUP_PRESPACE:
+ if(c != ' ' && len) {
+ parser->item_offset = len - 1;
+ parser->item_length = 1;
+ parser->state.UNIX.sub.group = PL_UNIX_GROUP_NAME;
+ }
+ break;
+ case PL_UNIX_GROUP_NAME:
+ parser->item_length++;
+ if(c == ' ') {
+ mem[parser->item_offset + parser->item_length - 1] = 0;
+ parser->offsets.group = parser->item_offset;
+ parser->state.UNIX.main = PL_UNIX_SIZE;
+ parser->state.UNIX.sub.size = PL_UNIX_SIZE_PRESPACE;
+ parser->item_offset = 0;
+ parser->item_length = 0;
+ }
+ break;
+ }
+ break;
+ case PL_UNIX_SIZE:
+ switch(parser->state.UNIX.sub.size) {
+ case PL_UNIX_SIZE_PRESPACE:
+ if(c != ' ') {
+ if(ISDIGIT(c) && len) {
+ parser->item_offset = len - 1;
+ parser->item_length = 1;
+ parser->state.UNIX.sub.size = PL_UNIX_SIZE_NUMBER;
+ }
+ else
+ return CURLE_FTP_BAD_FILE_LIST;
+ }
+ break;
+ case PL_UNIX_SIZE_NUMBER:
+ parser->item_length++;
+ if(c == ' ') {
+ const char *p = mem + parser->item_offset;
+ curl_off_t fsize;
+ mem[parser->item_offset + parser->item_length - 1] = 0;
+ if(!curlx_str_numblanks(&p, &fsize)) {
+ if(p[0] == '\0' && fsize != CURL_OFF_T_MAX) {
+ parser->file_data->info.flags |= CURLFINFOFLAG_KNOWN_SIZE;
+ parser->file_data->info.size = fsize;
+ }
+ parser->item_length = 0;
+ parser->item_offset = 0;
+ parser->state.UNIX.main = PL_UNIX_TIME;
+ parser->state.UNIX.sub.time = PL_UNIX_TIME_PREPART1;
+ }
+ }
+ else if(!ISDIGIT(c))
+ return CURLE_FTP_BAD_FILE_LIST;
+
+ break;
+ }
+ break;
+ case PL_UNIX_TIME:
+ switch(parser->state.UNIX.sub.time) {
+ case PL_UNIX_TIME_PREPART1:
+ if(c != ' ') {
+ if(ISALNUM(c) && len) {
+ parser->item_offset = len -1;
+ parser->item_length = 1;
+ parser->state.UNIX.sub.time = PL_UNIX_TIME_PART1;
+ }
+ else
+ return CURLE_FTP_BAD_FILE_LIST;
+ }
+ break;
+ case PL_UNIX_TIME_PART1:
+ parser->item_length++;
+ if(c == ' ')
+ parser->state.UNIX.sub.time = PL_UNIX_TIME_PREPART2;
+
+ else if(!ISALNUM(c) && c != '.')
+ return CURLE_FTP_BAD_FILE_LIST;
+
+ break;
+ case PL_UNIX_TIME_PREPART2:
+ parser->item_length++;
+ if(c != ' ') {
+ if(ISALNUM(c))
+ parser->state.UNIX.sub.time = PL_UNIX_TIME_PART2;
+ else
+ return CURLE_FTP_BAD_FILE_LIST;
+ }
+ break;
+ case PL_UNIX_TIME_PART2:
+ parser->item_length++;
+ if(c == ' ')
+ parser->state.UNIX.sub.time = PL_UNIX_TIME_PREPART3;
+ else if(!ISALNUM(c) && c != '.')
+ return CURLE_FTP_BAD_FILE_LIST;
+ break;
+ case PL_UNIX_TIME_PREPART3:
+ parser->item_length++;
+ if(c != ' ') {
+ if(ISALNUM(c))
+ parser->state.UNIX.sub.time = PL_UNIX_TIME_PART3;
+ else
+ return CURLE_FTP_BAD_FILE_LIST;
+ }
+ break;
+ case PL_UNIX_TIME_PART3:
+ parser->item_length++;
+ if(c == ' ') {
+ mem[parser->item_offset + parser->item_length -1] = 0;
+ parser->offsets.time = parser->item_offset;
+ if(finfo->filetype == CURLFILETYPE_SYMLINK) {
+ parser->state.UNIX.main = PL_UNIX_SYMLINK;
+ parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_PRESPACE;
+ }
+ else {
+ parser->state.UNIX.main = PL_UNIX_FILENAME;
+ parser->state.UNIX.sub.filename = PL_UNIX_FILENAME_PRESPACE;
+ }
+ }
+ else if(!ISALNUM(c) && c != '.' && c != ':')
+ return CURLE_FTP_BAD_FILE_LIST;
+ break;
+ }
+ break;
+ case PL_UNIX_FILENAME:
+ switch(parser->state.UNIX.sub.filename) {
+ case PL_UNIX_FILENAME_PRESPACE:
+ if(c != ' ' && len) {
+ parser->item_offset = len - 1;
+ parser->item_length = 1;
+ parser->state.UNIX.sub.filename = PL_UNIX_FILENAME_NAME;
+ }
+ break;
+ case PL_UNIX_FILENAME_NAME:
+ parser->item_length++;
+ if(c == '\r')
+ parser->state.UNIX.sub.filename = PL_UNIX_FILENAME_WINDOWSEOL;
+
+ else if(c == '\n') {
+ mem[parser->item_offset + parser->item_length - 1] = 0;
+ parser->offsets.filename = parser->item_offset;
+ parser->state.UNIX.main = PL_UNIX_FILETYPE;
+ result = ftp_pl_insert_finfo(data, infop);
+ if(result)
+ return result;
+ }
+ break;
+ case PL_UNIX_FILENAME_WINDOWSEOL:
+ if(c == '\n') {
+ mem[parser->item_offset + parser->item_length - 1] = 0;
+ parser->offsets.filename = parser->item_offset;
+ parser->state.UNIX.main = PL_UNIX_FILETYPE;
+ result = ftp_pl_insert_finfo(data, infop);
+ if(result)
+ return result;
+ }
+ else
+ return CURLE_FTP_BAD_FILE_LIST;
+
+ break;
+ }
+ break;
+ case PL_UNIX_SYMLINK:
+ switch(parser->state.UNIX.sub.symlink) {
+ case PL_UNIX_SYMLINK_PRESPACE:
+ if(c != ' ' && len) {
+ parser->item_offset = len - 1;
+ parser->item_length = 1;
+ parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_NAME;
+ }
+ break;
+ case PL_UNIX_SYMLINK_NAME:
+ parser->item_length++;
+ if(c == ' ')
+ parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_PRETARGET1;
+
+ else if(c == '\r' || c == '\n')
+ return CURLE_FTP_BAD_FILE_LIST;
+
+ break;
+ case PL_UNIX_SYMLINK_PRETARGET1:
+ parser->item_length++;
+ if(c == '-')
+ parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_PRETARGET2;
+
+ else if(c == '\r' || c == '\n')
+ return CURLE_FTP_BAD_FILE_LIST;
+ else
+ parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_NAME;
+ break;
+ case PL_UNIX_SYMLINK_PRETARGET2:
+ parser->item_length++;
+ if(c == '>')
+ parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_PRETARGET3;
+ else if(c == '\r' || c == '\n')
+ return CURLE_FTP_BAD_FILE_LIST;
+ else
+ parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_NAME;
+
+ break;
+ case PL_UNIX_SYMLINK_PRETARGET3:
+ parser->item_length++;
+ if(c == ' ') {
+ parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_PRETARGET4;
+ /* now place where is symlink following */
+ mem[parser->item_offset + parser->item_length - 4] = 0;
+ parser->offsets.filename = parser->item_offset;
+ parser->item_length = 0;
+ parser->item_offset = 0;
+ }
+ else if(c == '\r' || c == '\n')
+ return CURLE_FTP_BAD_FILE_LIST;
+ else
+ parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_NAME;
+ break;
+ case PL_UNIX_SYMLINK_PRETARGET4:
+ if(c != '\r' && c != '\n' && len) {
+ parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_TARGET;
+ parser->item_offset = len - 1;
+ parser->item_length = 1;
+ }
+ else
+ return CURLE_FTP_BAD_FILE_LIST;
+
+ break;
+ case PL_UNIX_SYMLINK_TARGET:
+ parser->item_length++;
+ if(c == '\r')
+ parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_WINDOWSEOL;
+
+ else if(c == '\n') {
+ mem[parser->item_offset + parser->item_length - 1] = 0;
+ parser->offsets.symlink_target = parser->item_offset;
+ result = ftp_pl_insert_finfo(data, infop);
+ if(result)
+ return result;
+
+ parser->state.UNIX.main = PL_UNIX_FILETYPE;
+ }
+ break;
+ case PL_UNIX_SYMLINK_WINDOWSEOL:
+ if(c == '\n') {
+ mem[parser->item_offset + parser->item_length - 1] = 0;
+ parser->offsets.symlink_target = parser->item_offset;
+ result = ftp_pl_insert_finfo(data, infop);
+ if(result)
+ return result;
+
+ parser->state.UNIX.main = PL_UNIX_FILETYPE;
+ }
+ else
+ return CURLE_FTP_BAD_FILE_LIST;
+
+ break;
+ }
+ break;
+ }
+ return CURLE_OK;
+}
+
+static CURLcode parse_winnt(struct Curl_easy *data,
+ struct ftp_parselist_data *parser,
+ struct fileinfo *infop,
+ const char c)
+{
+ struct curl_fileinfo *finfo = &infop->info;
+ size_t len = curlx_dyn_len(&infop->buf);
+ char *mem = curlx_dyn_ptr(&infop->buf);
+ CURLcode result = CURLE_OK;
+
+ switch(parser->state.NT.main) {
+ case PL_WINNT_DATE:
+ parser->item_length++;
+ if(parser->item_length < 9) {
+ if(!strchr("0123456789-", c)) { /* only simple control */
+ return CURLE_FTP_BAD_FILE_LIST;
+ }
+ }
+ else if(parser->item_length == 9) {
+ if(c == ' ') {
+ parser->state.NT.main = PL_WINNT_TIME;
+ parser->state.NT.sub.time = PL_WINNT_TIME_PRESPACE;
+ }
+ else
+ return CURLE_FTP_BAD_FILE_LIST;
+ }
+ else
+ return CURLE_FTP_BAD_FILE_LIST;
+ break;
+ case PL_WINNT_TIME:
+ parser->item_length++;
+ switch(parser->state.NT.sub.time) {
+ case PL_WINNT_TIME_PRESPACE:
+ if(!ISBLANK(c))
+ parser->state.NT.sub.time = PL_WINNT_TIME_TIME;
+ break;
+ case PL_WINNT_TIME_TIME:
+ if(c == ' ') {
+ parser->offsets.time = parser->item_offset;
+ mem[parser->item_offset + parser->item_length -1] = 0;
+ parser->state.NT.main = PL_WINNT_DIRORSIZE;
+ parser->state.NT.sub.dirorsize = PL_WINNT_DIRORSIZE_PRESPACE;
+ parser->item_length = 0;
+ }
+ else if(!strchr("APM0123456789:", c))
+ return CURLE_FTP_BAD_FILE_LIST;
+ break;
+ }
+ break;
+ case PL_WINNT_DIRORSIZE:
+ switch(parser->state.NT.sub.dirorsize) {
+ case PL_WINNT_DIRORSIZE_PRESPACE:
+ if(c != ' ' && len) {
+ parser->item_offset = len - 1;
+ parser->item_length = 1;
+ parser->state.NT.sub.dirorsize = PL_WINNT_DIRORSIZE_CONTENT;
+ }
+ break;
+ case PL_WINNT_DIRORSIZE_CONTENT:
+ parser->item_length ++;
+ if(c == ' ') {
+ mem[parser->item_offset + parser->item_length - 1] = 0;
+ if(strcmp("<DIR>", mem + parser->item_offset) == 0) {
+ finfo->filetype = CURLFILETYPE_DIRECTORY;
+ finfo->size = 0;
+ }
+ else {
+ const char *p = mem + parser->item_offset;
+ if(curlx_str_numblanks(&p, &finfo->size)) {
+ return CURLE_FTP_BAD_FILE_LIST;
+ }
+ /* correct file type */
+ parser->file_data->info.filetype = CURLFILETYPE_FILE;
+ }
+
+ parser->file_data->info.flags |= CURLFINFOFLAG_KNOWN_SIZE;
+ parser->item_length = 0;
+ parser->state.NT.main = PL_WINNT_FILENAME;
+ parser->state.NT.sub.filename = PL_WINNT_FILENAME_PRESPACE;
+ }
+ break;
+ }
+ break;
+ case PL_WINNT_FILENAME:
+ switch(parser->state.NT.sub.filename) {
+ case PL_WINNT_FILENAME_PRESPACE:
+ if(c != ' ' && len) {
+ parser->item_offset = len -1;
+ parser->item_length = 1;
+ parser->state.NT.sub.filename = PL_WINNT_FILENAME_CONTENT;
+ }
+ break;
+ case PL_WINNT_FILENAME_CONTENT:
+ parser->item_length++;
+ if(!len)
+ return CURLE_FTP_BAD_FILE_LIST;
+ if(c == '\r') {
+ parser->state.NT.sub.filename = PL_WINNT_FILENAME_WINEOL;
+ mem[len - 1] = 0;
+ }
+ else if(c == '\n') {
+ parser->offsets.filename = parser->item_offset;
+ mem[len - 1] = 0;
+ result = ftp_pl_insert_finfo(data, infop);
+ if(result)
+ return result;
+
+ parser->state.NT.main = PL_WINNT_DATE;
+ parser->state.NT.sub.filename = PL_WINNT_FILENAME_PRESPACE;
+ }
+ break;
+ case PL_WINNT_FILENAME_WINEOL:
+ if(c == '\n') {
+ parser->offsets.filename = parser->item_offset;
+ result = ftp_pl_insert_finfo(data, infop);
+ if(result)
+ return result;
+
+ parser->state.NT.main = PL_WINNT_DATE;
+ parser->state.NT.sub.filename = PL_WINNT_FILENAME_PRESPACE;
+ }
+ else
+ return CURLE_FTP_BAD_FILE_LIST;
+
+ break;
+ }
+ break;
+ }
+
+ return CURLE_OK;
+}
+
size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
void *connptr)
{
@@ -390,11 +958,8 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
}
while(i < bufflen) { /* FSM */
- char *mem;
- size_t len; /* number of bytes of data in the dynbuf */
char c = buffer[i];
struct fileinfo *infop;
- struct curl_fileinfo *finfo;
if(!parser->file_data) { /* tmp file data is not allocated yet */
parser->file_data = Curl_fileinfo_alloc();
if(!parser->file_data) {
@@ -403,622 +968,31 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
}
parser->item_offset = 0;
parser->item_length = 0;
- Curl_dyn_init(&parser->file_data->buf, MAX_FTPLIST_BUFFER);
+ curlx_dyn_init(&parser->file_data->buf, MAX_FTPLIST_BUFFER);
}
infop = parser->file_data;
- finfo = &infop->info;
- if(Curl_dyn_addn(&infop->buf, &c, 1)) {
+ if(curlx_dyn_addn(&infop->buf, &c, 1)) {
parser->error = CURLE_OUT_OF_MEMORY;
goto fail;
}
- len = Curl_dyn_len(&infop->buf);
- mem = Curl_dyn_ptr(&infop->buf);
switch(parser->os_type) {
case OS_TYPE_UNIX:
- switch(parser->state.UNIX.main) {
- case PL_UNIX_TOTALSIZE:
- switch(parser->state.UNIX.sub.total_dirsize) {
- case PL_UNIX_TOTALSIZE_INIT:
- if(c == 't') {
- parser->state.UNIX.sub.total_dirsize = PL_UNIX_TOTALSIZE_READING;
- parser->item_length++;
- }
- else {
- parser->state.UNIX.main = PL_UNIX_FILETYPE;
- /* start FSM again not considering size of directory */
- Curl_dyn_reset(&infop->buf);
- continue;
- }
- break;
- case PL_UNIX_TOTALSIZE_READING:
- parser->item_length++;
- if(c == '\r') {
- parser->item_length--;
- Curl_dyn_setlen(&infop->buf, --len);
- }
- else if(c == '\n') {
- mem[parser->item_length - 1] = 0;
- if(!strncmp("total ", mem, 6)) {
- const char *endptr = mem + 6;
- /* here we can deal with directory size, pass the leading
- whitespace and then the digits */
- Curl_str_passblanks(&endptr);
- while(ISDIGIT(*endptr))
- endptr++;
- if(*endptr) {
- parser->error = CURLE_FTP_BAD_FILE_LIST;
- goto fail;
- }
- parser->state.UNIX.main = PL_UNIX_FILETYPE;
- Curl_dyn_reset(&infop->buf);
- }
- else {
- parser->error = CURLE_FTP_BAD_FILE_LIST;
- goto fail;
- }
- }
- break;
- }
- break;
- case PL_UNIX_FILETYPE:
- switch(c) {
- case '-':
- finfo->filetype = CURLFILETYPE_FILE;
- break;
- case 'd':
- finfo->filetype = CURLFILETYPE_DIRECTORY;
- break;
- case 'l':
- finfo->filetype = CURLFILETYPE_SYMLINK;
- break;
- case 'p':
- finfo->filetype = CURLFILETYPE_NAMEDPIPE;
- break;
- case 's':
- finfo->filetype = CURLFILETYPE_SOCKET;
- break;
- case 'c':
- finfo->filetype = CURLFILETYPE_DEVICE_CHAR;
- break;
- case 'b':
- finfo->filetype = CURLFILETYPE_DEVICE_BLOCK;
- break;
- case 'D':
- finfo->filetype = CURLFILETYPE_DOOR;
- break;
- default:
- parser->error = CURLE_FTP_BAD_FILE_LIST;
- goto fail;
- }
- parser->state.UNIX.main = PL_UNIX_PERMISSION;
- parser->item_length = 0;
- parser->item_offset = 1;
- break;
- case PL_UNIX_PERMISSION:
- parser->item_length++;
- if(parser->item_length <= 9) {
- if(!strchr("rwx-tTsS", c)) {
- parser->error = CURLE_FTP_BAD_FILE_LIST;
- goto fail;
- }
- }
- else if(parser->item_length == 10) {
- unsigned int perm;
- if(c != ' ') {
- parser->error = CURLE_FTP_BAD_FILE_LIST;
- goto fail;
- }
- mem[10] = 0; /* terminate permissions */
- perm = ftp_pl_get_permission(mem + parser->item_offset);
- if(perm & FTP_LP_MALFORMATED_PERM) {
- parser->error = CURLE_FTP_BAD_FILE_LIST;
- goto fail;
- }
- parser->file_data->info.flags |= CURLFINFOFLAG_KNOWN_PERM;
- parser->file_data->info.perm = perm;
- parser->offsets.perm = parser->item_offset;
-
- parser->item_length = 0;
- parser->state.UNIX.main = PL_UNIX_HLINKS;
- parser->state.UNIX.sub.hlinks = PL_UNIX_HLINKS_PRESPACE;
- }
- break;
- case PL_UNIX_HLINKS:
- switch(parser->state.UNIX.sub.hlinks) {
- case PL_UNIX_HLINKS_PRESPACE:
- if(c != ' ') {
- if(ISDIGIT(c)) {
- parser->item_offset = len - 1;
- parser->item_length = 1;
- parser->state.UNIX.sub.hlinks = PL_UNIX_HLINKS_NUMBER;
- }
- else {
- parser->error = CURLE_FTP_BAD_FILE_LIST;
- goto fail;
- }
- }
- break;
- case PL_UNIX_HLINKS_NUMBER:
- parser->item_length ++;
- if(c == ' ') {
- const char *p = &mem[parser->item_offset];
- curl_off_t hlinks;
- mem[parser->item_offset + parser->item_length - 1] = 0;
-
- if(!Curl_str_number(&p, &hlinks, LONG_MAX)) {
- parser->file_data->info.flags |= CURLFINFOFLAG_KNOWN_HLINKCOUNT;
- parser->file_data->info.hardlinks = (long)hlinks;
- }
- parser->item_length = 0;
- parser->item_offset = 0;
- parser->state.UNIX.main = PL_UNIX_USER;
- parser->state.UNIX.sub.user = PL_UNIX_USER_PRESPACE;
- }
- else if(!ISDIGIT(c)) {
- parser->error = CURLE_FTP_BAD_FILE_LIST;
- goto fail;
- }
- break;
- }
- break;
- case PL_UNIX_USER:
- switch(parser->state.UNIX.sub.user) {
- case PL_UNIX_USER_PRESPACE:
- if(c != ' ') {
- parser->item_offset = len - 1;
- parser->item_length = 1;
- parser->state.UNIX.sub.user = PL_UNIX_USER_PARSING;
- }
- break;
- case PL_UNIX_USER_PARSING:
- parser->item_length++;
- if(c == ' ') {
- mem[parser->item_offset + parser->item_length - 1] = 0;
- parser->offsets.user = parser->item_offset;
- parser->state.UNIX.main = PL_UNIX_GROUP;
- parser->state.UNIX.sub.group = PL_UNIX_GROUP_PRESPACE;
- parser->item_offset = 0;
- parser->item_length = 0;
- }
- break;
- }
- break;
- case PL_UNIX_GROUP:
- switch(parser->state.UNIX.sub.group) {
- case PL_UNIX_GROUP_PRESPACE:
- if(c != ' ') {
- parser->item_offset = len - 1;
- parser->item_length = 1;
- parser->state.UNIX.sub.group = PL_UNIX_GROUP_NAME;
- }
- break;
- case PL_UNIX_GROUP_NAME:
- parser->item_length++;
- if(c == ' ') {
- mem[parser->item_offset + parser->item_length - 1] = 0;
- parser->offsets.group = parser->item_offset;
- parser->state.UNIX.main = PL_UNIX_SIZE;
- parser->state.UNIX.sub.size = PL_UNIX_SIZE_PRESPACE;
- parser->item_offset = 0;
- parser->item_length = 0;
- }
- break;
- }
- break;
- case PL_UNIX_SIZE:
- switch(parser->state.UNIX.sub.size) {
- case PL_UNIX_SIZE_PRESPACE:
- if(c != ' ') {
- if(ISDIGIT(c)) {
- parser->item_offset = len - 1;
- parser->item_length = 1;
- parser->state.UNIX.sub.size = PL_UNIX_SIZE_NUMBER;
- }
- else {
- parser->error = CURLE_FTP_BAD_FILE_LIST;
- goto fail;
- }
- }
- break;
- case PL_UNIX_SIZE_NUMBER:
- parser->item_length++;
- if(c == ' ') {
- const char *p = mem + parser->item_offset;
- curl_off_t fsize;
- mem[parser->item_offset + parser->item_length - 1] = 0;
- if(!Curl_str_numblanks(&p, &fsize)) {
- if(p[0] == '\0' && fsize != CURL_OFF_T_MAX) {
- parser->file_data->info.flags |= CURLFINFOFLAG_KNOWN_SIZE;
- parser->file_data->info.size = fsize;
- }
- parser->item_length = 0;
- parser->item_offset = 0;
- parser->state.UNIX.main = PL_UNIX_TIME;
- parser->state.UNIX.sub.time = PL_UNIX_TIME_PREPART1;
- }
- }
- else if(!ISDIGIT(c)) {
- parser->error = CURLE_FTP_BAD_FILE_LIST;
- goto fail;
- }
- break;
- }
- break;
- case PL_UNIX_TIME:
- switch(parser->state.UNIX.sub.time) {
- case PL_UNIX_TIME_PREPART1:
- if(c != ' ') {
- if(ISALNUM(c)) {
- parser->item_offset = len -1;
- parser->item_length = 1;
- parser->state.UNIX.sub.time = PL_UNIX_TIME_PART1;
- }
- else {
- parser->error = CURLE_FTP_BAD_FILE_LIST;
- goto fail;
- }
- }
- break;
- case PL_UNIX_TIME_PART1:
- parser->item_length++;
- if(c == ' ') {
- parser->state.UNIX.sub.time = PL_UNIX_TIME_PREPART2;
- }
- else if(!ISALNUM(c) && c != '.') {
- parser->error = CURLE_FTP_BAD_FILE_LIST;
- goto fail;
- }
- break;
- case PL_UNIX_TIME_PREPART2:
- parser->item_length++;
- if(c != ' ') {
- if(ISALNUM(c)) {
- parser->state.UNIX.sub.time = PL_UNIX_TIME_PART2;
- }
- else {
- parser->error = CURLE_FTP_BAD_FILE_LIST;
- goto fail;
- }
- }
- break;
- case PL_UNIX_TIME_PART2:
- parser->item_length++;
- if(c == ' ') {
- parser->state.UNIX.sub.time = PL_UNIX_TIME_PREPART3;
- }
- else if(!ISALNUM(c) && c != '.') {
- parser->error = CURLE_FTP_BAD_FILE_LIST;
- goto fail;
- }
- break;
- case PL_UNIX_TIME_PREPART3:
- parser->item_length++;
- if(c != ' ') {
- if(ISALNUM(c)) {
- parser->state.UNIX.sub.time = PL_UNIX_TIME_PART3;
- }
- else {
- parser->error = CURLE_FTP_BAD_FILE_LIST;
- goto fail;
- }
- }
- break;
- case PL_UNIX_TIME_PART3:
- parser->item_length++;
- if(c == ' ') {
- mem[parser->item_offset + parser->item_length -1] = 0;
- parser->offsets.time = parser->item_offset;
- /*
- if(ftp_pl_gettime(parser, finfo->mem + parser->item_offset)) {
- parser->file_data->flags |= CURLFINFOFLAG_KNOWN_TIME;
- }
- */
- if(finfo->filetype == CURLFILETYPE_SYMLINK) {
- parser->state.UNIX.main = PL_UNIX_SYMLINK;
- parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_PRESPACE;
- }
- else {
- parser->state.UNIX.main = PL_UNIX_FILENAME;
- parser->state.UNIX.sub.filename = PL_UNIX_FILENAME_PRESPACE;
- }
- }
- else if(!ISALNUM(c) && c != '.' && c != ':') {
- parser->error = CURLE_FTP_BAD_FILE_LIST;
- goto fail;
- }
- break;
- }
- break;
- case PL_UNIX_FILENAME:
- switch(parser->state.UNIX.sub.filename) {
- case PL_UNIX_FILENAME_PRESPACE:
- if(c != ' ') {
- parser->item_offset = len - 1;
- parser->item_length = 1;
- parser->state.UNIX.sub.filename = PL_UNIX_FILENAME_NAME;
- }
- break;
- case PL_UNIX_FILENAME_NAME:
- parser->item_length++;
- if(c == '\r') {
- parser->state.UNIX.sub.filename = PL_UNIX_FILENAME_WINDOWSEOL;
- }
- else if(c == '\n') {
- mem[parser->item_offset + parser->item_length - 1] = 0;
- parser->offsets.filename = parser->item_offset;
- parser->state.UNIX.main = PL_UNIX_FILETYPE;
- result = ftp_pl_insert_finfo(data, infop);
- if(result) {
- parser->error = result;
- goto fail;
- }
- }
- break;
- case PL_UNIX_FILENAME_WINDOWSEOL:
- if(c == '\n') {
- mem[parser->item_offset + parser->item_length - 1] = 0;
- parser->offsets.filename = parser->item_offset;
- parser->state.UNIX.main = PL_UNIX_FILETYPE;
- result = ftp_pl_insert_finfo(data, infop);
- if(result) {
- parser->error = result;
- goto fail;
- }
- }
- else {
- parser->error = CURLE_FTP_BAD_FILE_LIST;
- goto fail;
- }
- break;
- }
- break;
- case PL_UNIX_SYMLINK:
- switch(parser->state.UNIX.sub.symlink) {
- case PL_UNIX_SYMLINK_PRESPACE:
- if(c != ' ') {
- parser->item_offset = len - 1;
- parser->item_length = 1;
- parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_NAME;
- }
- break;
- case PL_UNIX_SYMLINK_NAME:
- parser->item_length++;
- if(c == ' ') {
- parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_PRETARGET1;
- }
- else if(c == '\r' || c == '\n') {
- parser->error = CURLE_FTP_BAD_FILE_LIST;
- goto fail;
- }
- break;
- case PL_UNIX_SYMLINK_PRETARGET1:
- parser->item_length++;
- if(c == '-') {
- parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_PRETARGET2;
- }
- else if(c == '\r' || c == '\n') {
- parser->error = CURLE_FTP_BAD_FILE_LIST;
- goto fail;
- }
- else {
- parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_NAME;
- }
- break;
- case PL_UNIX_SYMLINK_PRETARGET2:
- parser->item_length++;
- if(c == '>') {
- parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_PRETARGET3;
- }
- else if(c == '\r' || c == '\n') {
- parser->error = CURLE_FTP_BAD_FILE_LIST;
- goto fail;
- }
- else {
- parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_NAME;
- }
- break;
- case PL_UNIX_SYMLINK_PRETARGET3:
- parser->item_length++;
- if(c == ' ') {
- parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_PRETARGET4;
- /* now place where is symlink following */
- mem[parser->item_offset + parser->item_length - 4] = 0;
- parser->offsets.filename = parser->item_offset;
- parser->item_length = 0;
- parser->item_offset = 0;
- }
- else if(c == '\r' || c == '\n') {
- parser->error = CURLE_FTP_BAD_FILE_LIST;
- goto fail;
- }
- else {
- parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_NAME;
- }
- break;
- case PL_UNIX_SYMLINK_PRETARGET4:
- if(c != '\r' && c != '\n') {
- parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_TARGET;
- parser->item_offset = len - 1;
- parser->item_length = 1;
- }
- else {
- parser->error = CURLE_FTP_BAD_FILE_LIST;
- goto fail;
- }
- break;
- case PL_UNIX_SYMLINK_TARGET:
- parser->item_length++;
- if(c == '\r') {
- parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_WINDOWSEOL;
- }
- else if(c == '\n') {
- mem[parser->item_offset + parser->item_length - 1] = 0;
- parser->offsets.symlink_target = parser->item_offset;
- result = ftp_pl_insert_finfo(data, infop);
- if(result) {
- parser->error = result;
- goto fail;
- }
- parser->state.UNIX.main = PL_UNIX_FILETYPE;
- }
- break;
- case PL_UNIX_SYMLINK_WINDOWSEOL:
- if(c == '\n') {
- mem[parser->item_offset + parser->item_length - 1] = 0;
- parser->offsets.symlink_target = parser->item_offset;
- result = ftp_pl_insert_finfo(data, infop);
- if(result) {
- parser->error = result;
- goto fail;
- }
- parser->state.UNIX.main = PL_UNIX_FILETYPE;
- }
- else {
- parser->error = CURLE_FTP_BAD_FILE_LIST;
- goto fail;
- }
- break;
- }
- break;
- }
+ result = parse_unix(data, parser, infop, c);
break;
case OS_TYPE_WIN_NT:
- switch(parser->state.NT.main) {
- case PL_WINNT_DATE:
- parser->item_length++;
- if(parser->item_length < 9) {
- if(!strchr("0123456789-", c)) { /* only simple control */
- parser->error = CURLE_FTP_BAD_FILE_LIST;
- goto fail;
- }
- }
- else if(parser->item_length == 9) {
- if(c == ' ') {
- parser->state.NT.main = PL_WINNT_TIME;
- parser->state.NT.sub.time = PL_WINNT_TIME_PRESPACE;
- }
- else {
- parser->error = CURLE_FTP_BAD_FILE_LIST;
- goto fail;
- }
- }
- else {
- parser->error = CURLE_FTP_BAD_FILE_LIST;
- goto fail;
- }
- break;
- case PL_WINNT_TIME:
- parser->item_length++;
- switch(parser->state.NT.sub.time) {
- case PL_WINNT_TIME_PRESPACE:
- if(!ISBLANK(c)) {
- parser->state.NT.sub.time = PL_WINNT_TIME_TIME;
- }
- break;
- case PL_WINNT_TIME_TIME:
- if(c == ' ') {
- parser->offsets.time = parser->item_offset;
- mem[parser->item_offset + parser->item_length -1] = 0;
- parser->state.NT.main = PL_WINNT_DIRORSIZE;
- parser->state.NT.sub.dirorsize = PL_WINNT_DIRORSIZE_PRESPACE;
- parser->item_length = 0;
- }
- else if(!strchr("APM0123456789:", c)) {
- parser->error = CURLE_FTP_BAD_FILE_LIST;
- goto fail;
- }
- break;
- }
- break;
- case PL_WINNT_DIRORSIZE:
- switch(parser->state.NT.sub.dirorsize) {
- case PL_WINNT_DIRORSIZE_PRESPACE:
- if(c != ' ') {
- parser->item_offset = len - 1;
- parser->item_length = 1;
- parser->state.NT.sub.dirorsize = PL_WINNT_DIRORSIZE_CONTENT;
- }
- break;
- case PL_WINNT_DIRORSIZE_CONTENT:
- parser->item_length ++;
- if(c == ' ') {
- mem[parser->item_offset + parser->item_length - 1] = 0;
- if(strcmp("<DIR>", mem + parser->item_offset) == 0) {
- finfo->filetype = CURLFILETYPE_DIRECTORY;
- finfo->size = 0;
- }
- else {
- const char *p = mem + parser->item_offset;
- if(Curl_str_numblanks(&p, &finfo->size)) {
- parser->error = CURLE_FTP_BAD_FILE_LIST;
- goto fail;
- }
- /* correct file type */
- parser->file_data->info.filetype = CURLFILETYPE_FILE;
- }
-
- parser->file_data->info.flags |= CURLFINFOFLAG_KNOWN_SIZE;
- parser->item_length = 0;
- parser->state.NT.main = PL_WINNT_FILENAME;
- parser->state.NT.sub.filename = PL_WINNT_FILENAME_PRESPACE;
- }
- break;
- }
- break;
- case PL_WINNT_FILENAME:
- switch(parser->state.NT.sub.filename) {
- case PL_WINNT_FILENAME_PRESPACE:
- if(c != ' ') {
- parser->item_offset = len -1;
- parser->item_length = 1;
- parser->state.NT.sub.filename = PL_WINNT_FILENAME_CONTENT;
- }
- break;
- case PL_WINNT_FILENAME_CONTENT:
- parser->item_length++;
- if(c == '\r') {
- parser->state.NT.sub.filename = PL_WINNT_FILENAME_WINEOL;
- mem[len - 1] = 0;
- }
- else if(c == '\n') {
- parser->offsets.filename = parser->item_offset;
- mem[len - 1] = 0;
- result = ftp_pl_insert_finfo(data, infop);
- if(result) {
- parser->error = result;
- goto fail;
- }
- parser->state.NT.main = PL_WINNT_DATE;
- parser->state.NT.sub.filename = PL_WINNT_FILENAME_PRESPACE;
- }
- break;
- case PL_WINNT_FILENAME_WINEOL:
- if(c == '\n') {
- parser->offsets.filename = parser->item_offset;
- result = ftp_pl_insert_finfo(data, infop);
- if(result) {
- parser->error = result;
- goto fail;
- }
- parser->state.NT.main = PL_WINNT_DATE;
- parser->state.NT.sub.filename = PL_WINNT_FILENAME_PRESPACE;
- }
- else {
- parser->error = CURLE_FTP_BAD_FILE_LIST;
- goto fail;
- }
- break;
- }
- break;
- }
+ result = parse_winnt(data, parser, infop, c);
break;
default:
retsize = bufflen + 1;
goto fail;
}
+ if(result) {
+ parser->error = result;
+ goto fail;
+ }
i++;
}
diff --git a/libs/libcurl/src/getinfo.c b/libs/libcurl/src/getinfo.c
index 8f0f213213..2e5c0d5cbe 100644
--- a/libs/libcurl/src/getinfo.c
+++ b/libs/libcurl/src/getinfo.c
@@ -31,7 +31,7 @@
#include "vtls/vtls.h"
#include "connect.h" /* Curl_getconnectinfo() */
#include "progress.h"
-#include "strparse.h"
+#include "curlx/strparse.h"
/* The last #include files should be: */
#include "curl_memory.h"
@@ -207,7 +207,7 @@ static CURLcode getinfo_long(struct Curl_easy *data, CURLINFO info,
const char *timestr = getenv("CURL_TIME");
if(timestr) {
curl_off_t val;
- Curl_str_number(&timestr, &val, TIME_T_MAX);
+ curlx_str_number(&timestr, &val, TIME_T_MAX);
switch(info) {
case CURLINFO_LOCAL_PORT:
*param_longp = (long)val;
@@ -220,7 +220,7 @@ static CURLcode getinfo_long(struct Curl_easy *data, CURLINFO info,
timestr = getenv("CURL_DEBUG_SIZE");
if(timestr) {
curl_off_t val;
- Curl_str_number(&timestr, &val, LONG_MAX);
+ curlx_str_number(&timestr, &val, LONG_MAX);
switch(info) {
case CURLINFO_HEADER_SIZE:
case CURLINFO_REQUEST_SIZE:
@@ -384,7 +384,7 @@ static CURLcode getinfo_offt(struct Curl_easy *data, CURLINFO info,
const char *timestr = getenv("CURL_TIME");
if(timestr) {
curl_off_t val;
- Curl_str_number(&timestr, &val, CURL_OFF_T_MAX);
+ curlx_str_number(&timestr, &val, CURL_OFF_T_MAX);
switch(info) {
case CURLINFO_TOTAL_TIME_T:
@@ -422,11 +422,11 @@ static CURLcode getinfo_offt(struct Curl_easy *data, CURLINFO info,
*param_offt = data->progress.ul.speed;
break;
case CURLINFO_CONTENT_LENGTH_DOWNLOAD_T:
- *param_offt = (data->progress.flags & PGRS_DL_SIZE_KNOWN) ?
+ *param_offt = data->progress.dl_size_known ?
data->progress.dl.total_size : -1;
break;
case CURLINFO_CONTENT_LENGTH_UPLOAD_T:
- *param_offt = (data->progress.flags & PGRS_UL_SIZE_KNOWN) ?
+ *param_offt = data->progress.ul_size_known ?
data->progress.ul.total_size : -1;
break;
case CURLINFO_TOTAL_TIME_T:
@@ -483,7 +483,7 @@ static CURLcode getinfo_double(struct Curl_easy *data, CURLINFO info,
const char *timestr = getenv("CURL_TIME");
if(timestr) {
curl_off_t val;
- Curl_str_number(&timestr, &val, CURL_OFF_T_MAX);
+ curlx_str_number(&timestr, &val, CURL_OFF_T_MAX);
switch(info) {
case CURLINFO_TOTAL_TIME:
@@ -534,11 +534,11 @@ static CURLcode getinfo_double(struct Curl_easy *data, CURLINFO info,
*param_doublep = (double)data->progress.ul.speed;
break;
case CURLINFO_CONTENT_LENGTH_DOWNLOAD:
- *param_doublep = (data->progress.flags & PGRS_DL_SIZE_KNOWN) ?
+ *param_doublep = data->progress.dl_size_known ?
(double)data->progress.dl.total_size : -1;
break;
case CURLINFO_CONTENT_LENGTH_UPLOAD:
- *param_doublep = (data->progress.flags & PGRS_UL_SIZE_KNOWN) ?
+ *param_doublep = data->progress.ul_size_known ?
(double)data->progress.ul.total_size : -1;
break;
case CURLINFO_REDIRECT_TIME:
diff --git a/libs/libcurl/src/gopher.c b/libs/libcurl/src/gopher.c
index 05e7ff8fed..fd7ff2cb19 100644
--- a/libs/libcurl/src/gopher.c
+++ b/libs/libcurl/src/gopher.c
@@ -39,7 +39,7 @@
#include "vtls/vtls.h"
#include "url.h"
#include "escape.h"
-#include "warnless.h"
+#include "curlx/warnless.h"
#include "curl_printf.h"
#include "curl_memory.h"
/* The last #include file should be: */
diff --git a/libs/libcurl/src/hash.c b/libs/libcurl/src/hash.c
index a6551e8bed..1b98c2b3ae 100644
--- a/libs/libcurl/src/hash.c
+++ b/libs/libcurl/src/hash.c
@@ -352,7 +352,7 @@ size_t Curl_hash_str(void *key, size_t key_length, size_t slots_num)
return (h % slots_num);
}
-size_t Curl_str_key_compare(void *k1, size_t key1_len,
+size_t curlx_str_key_compare(void *k1, size_t key1_len,
void *k2, size_t key2_len)
{
if((key1_len == key2_len) && !memcmp(k1, k2, key1_len))
diff --git a/libs/libcurl/src/hash.h b/libs/libcurl/src/hash.h
index 6e1c5790da..61daf8fd21 100644
--- a/libs/libcurl/src/hash.h
+++ b/libs/libcurl/src/hash.h
@@ -98,7 +98,7 @@ void Curl_hash_clean(struct Curl_hash *h);
void Curl_hash_clean_with_criterium(struct Curl_hash *h, void *user,
int (*comp)(void *, void *));
size_t Curl_hash_str(void *key, size_t key_length, size_t slots_num);
-size_t Curl_str_key_compare(void *k1, size_t key1_len, void *k2,
+size_t curlx_str_key_compare(void *k1, size_t key1_len, void *k2,
size_t key2_len);
void Curl_hash_start_iterate(struct Curl_hash *hash,
struct Curl_hash_iterator *iter);
diff --git a/libs/libcurl/src/headers.c b/libs/libcurl/src/headers.c
index daae4fe45b..821e9e289c 100644
--- a/libs/libcurl/src/headers.c
+++ b/libs/libcurl/src/headers.c
@@ -29,7 +29,7 @@
#include "strcase.h"
#include "sendf.h"
#include "headers.h"
-#include "strparse.h"
+#include "curlx/strparse.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
@@ -313,6 +313,11 @@ CURLcode Curl_headers_push(struct Curl_easy *data, const char *header,
return CURLE_WEIRD_SERVER_REPLY;
}
}
+ if(Curl_llist_count(&data->state.httphdrs) >= MAX_HTTP_RESP_HEADER_COUNT) {
+ failf(data, "Too many response headers, %d is max",
+ MAX_HTTP_RESP_HEADER_COUNT);
+ return CURLE_TOO_LARGE;
+ }
hs = calloc(1, sizeof(*hs) + hlen);
if(!hs)
@@ -331,8 +336,10 @@ CURLcode Curl_headers_push(struct Curl_easy *data, const char *header,
Curl_llist_append(&data->state.httphdrs, hs, &hs->node);
data->state.prevhead = hs;
}
- else
+ else {
+ failf(data, "Invalid response header");
free(hs);
+ }
return result;
}
diff --git a/libs/libcurl/src/hmac.c b/libs/libcurl/src/hmac.c
index f88b19dccd..3d8743dcf2 100644
--- a/libs/libcurl/src/hmac.c
+++ b/libs/libcurl/src/hmac.c
@@ -34,7 +34,7 @@
#include "curl_hmac.h"
#include "curl_memory.h"
-#include "warnless.h"
+#include "curlx/warnless.h"
/* The last #include file should be: */
#include "memdebug.h"
diff --git a/libs/libcurl/src/hostasyn.c b/libs/libcurl/src/hostasyn.c
deleted file mode 100644
index 96cbc9788d..0000000000
--- a/libs/libcurl/src/hostasyn.c
+++ /dev/null
@@ -1,121 +0,0 @@
-/***************************************************************************
- * _ _ ____ _
- * 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"
-
-/***********************************************************************
- * Only for builds using asynchronous name resolves
- **********************************************************************/
-#ifdef CURLRES_ASYNCH
-
-#ifdef HAVE_NETINET_IN_H
-#include <netinet/in.h>
-#endif
-#ifdef HAVE_NETDB_H
-#include <netdb.h>
-#endif
-#ifdef HAVE_ARPA_INET_H
-#include <arpa/inet.h>
-#endif
-#ifdef __VMS
-#include <in.h>
-#include <inet.h>
-#endif
-
-#include "urldata.h"
-#include "sendf.h"
-#include "hostip.h"
-#include "hash.h"
-#include "share.h"
-#include "url.h"
-#include "curl_memory.h"
-/* The last #include file should be: */
-#include "memdebug.h"
-
-/*
- * Curl_addrinfo_callback() gets called by ares, gethostbyname_thread()
- * or getaddrinfo_thread() when we got the name resolved (or not!).
- *
- * If the status argument is CURL_ASYNC_SUCCESS, this function takes
- * ownership of the Curl_addrinfo passed, storing the resolved data
- * in the DNS cache.
- *
- * The storage operation locks and unlocks the DNS cache.
- */
-CURLcode Curl_addrinfo_callback(struct Curl_easy *data,
- int status,
- struct Curl_addrinfo *ai)
-{
- struct Curl_dns_entry *dns = NULL;
- CURLcode result = CURLE_OK;
-
- if(CURL_ASYNC_SUCCESS == status) {
- if(ai) {
- if(data->share)
- Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);
-
- dns = Curl_cache_addr(data, ai,
- data->conn->host.dispname, 0,
- data->state.async.port, FALSE);
- if(data->share)
- Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
-
- if(!dns) {
- /* failed to store, cleanup and return error */
- Curl_freeaddrinfo(ai);
- result = CURLE_OUT_OF_MEMORY;
- }
- }
- else {
- result = CURLE_OUT_OF_MEMORY;
- }
- }
-
- data->state.async.dns = dns;
-
- /* Set async.done TRUE last in this function since it may be used multi-
- threaded and once this is TRUE the other thread may read fields from the
- async struct */
- data->state.async.done = TRUE;
-
- /* IPv4: The input hostent struct will be freed by ares when we return from
- this function */
- return result;
-}
-
-/*
- * Curl_getaddrinfo() is the generic low-level name resolve API within this
- * source file. There are several versions of this function - for different
- * name resolve layers (selected at build-time). They all take this same set
- * of arguments
- */
-struct Curl_addrinfo *Curl_getaddrinfo(struct Curl_easy *data,
- const char *hostname,
- int port,
- int *waitp)
-{
- return Curl_resolver_getaddrinfo(data, hostname, port, waitp);
-}
-
-#endif /* CURLRES_ASYNCH */
diff --git a/libs/libcurl/src/hostip.c b/libs/libcurl/src/hostip.c
index 57fd167377..97c7ea9e68 100644
--- a/libs/libcurl/src/hostip.c
+++ b/libs/libcurl/src/hostip.c
@@ -48,19 +48,21 @@
#include "urldata.h"
#include "sendf.h"
+#include "connect.h"
#include "hostip.h"
#include "hash.h"
#include "rand.h"
#include "share.h"
#include "url.h"
#include "inet_ntop.h"
-#include "inet_pton.h"
+#include "curlx/inet_pton.h"
#include "multiif.h"
#include "doh.h"
-#include "warnless.h"
+#include "curlx/warnless.h"
+#include "select.h"
#include "strcase.h"
#include "easy_lock.h"
-#include "strparse.h"
+#include "curlx/strparse.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
@@ -106,20 +108,18 @@
* The host*.c sources files are split up like this:
*
* hostip.c - method-independent resolver functions and utility functions
- * hostasyn.c - functions for asynchronous name resolves
- * hostsyn.c - functions for synchronous name resolves
* hostip4.c - IPv4 specific functions
* hostip6.c - IPv6 specific functions
- *
+ * asyn.h - common functions for all async resolvers
* The two asynchronous name resolver backends are implemented in:
- * asyn-ares.c - functions for ares-using name resolves
- * asyn-thread.c - functions for threaded name resolves
-
+ * asyn-ares.c - async resolver using c-ares
+ * asyn-thread.c - async resolver using POSIX threads
+ *
* The hostip.h is the united header file for all this. It defines the
* CURLRES_* defines based on the config*.h and curl_setup.h defines.
*/
-static void hostcache_unlink_entry(void *entry);
+static void dnscache_entry_free(struct Curl_dns_entry *dns);
#ifndef CURL_DISABLE_VERBOSE_STRINGS
static void show_resolve_info(struct Curl_easy *data,
@@ -145,14 +145,14 @@ void Curl_printable_address(const struct Curl_addrinfo *ai, char *buf,
case AF_INET: {
const struct sockaddr_in *sa4 = (const void *)ai->ai_addr;
const struct in_addr *ipaddr4 = &sa4->sin_addr;
- (void)curlx_inet_ntop(ai->ai_family, (const void *)ipaddr4, buf, bufsize);
+ (void)Curl_inet_ntop(ai->ai_family, (const void *)ipaddr4, buf, bufsize);
break;
}
#ifdef USE_IPV6
case AF_INET6: {
const struct sockaddr_in6 *sa6 = (const void *)ai->ai_addr;
const struct in6_addr *ipaddr6 = &sa6->sin6_addr;
- (void)curlx_inet_ntop(ai->ai_family, (const void *)ipaddr6, buf, bufsize);
+ (void)Curl_inet_ntop(ai->ai_family, (const void *)ipaddr6, buf, bufsize);
break;
}
#endif
@@ -166,9 +166,9 @@ void Curl_printable_address(const struct Curl_addrinfo *ai, char *buf,
* the DNS caching. Without alloc. Return length of the id string.
*/
static size_t
-create_hostcache_id(const char *name,
- size_t nlen, /* 0 or actual name length */
- int port, char *ptr, size_t buflen)
+create_dnscache_id(const char *name,
+ size_t nlen, /* 0 or actual name length */
+ int port, char *ptr, size_t buflen)
{
size_t len = nlen ? nlen : strlen(name);
DEBUGASSERT(buflen >= MAX_HOSTCACHE_LEN);
@@ -179,7 +179,7 @@ create_hostcache_id(const char *name,
return msnprintf(&ptr[len], 7, ":%u", port) + len;
}
-struct hostcache_prune_data {
+struct dnscache_prune_data {
time_t now;
time_t oldest; /* oldest time in cache not pruned. */
int max_age_sec;
@@ -193,10 +193,10 @@ struct hostcache_prune_data {
* cache.
*/
static int
-hostcache_entry_is_stale(void *datap, void *hc)
+dnscache_entry_is_stale(void *datap, void *hc)
{
- struct hostcache_prune_data *prune =
- (struct hostcache_prune_data *) datap;
+ struct dnscache_prune_data *prune =
+ (struct dnscache_prune_data *) datap;
struct Curl_dns_entry *dns = (struct Curl_dns_entry *) hc;
if(dns->timestamp) {
@@ -215,10 +215,10 @@ hostcache_entry_is_stale(void *datap, void *hc)
* Returns the 'age' of the oldest still kept entry.
*/
static time_t
-hostcache_prune(struct Curl_hash *hostcache, int cache_timeout,
- time_t now)
+dnscache_prune(struct Curl_hash *hostcache, int cache_timeout,
+ time_t now)
{
- struct hostcache_prune_data user;
+ struct dnscache_prune_data user;
user.max_age_sec = cache_timeout;
user.now = now;
@@ -226,33 +226,56 @@ hostcache_prune(struct Curl_hash *hostcache, int cache_timeout,
Curl_hash_clean_with_criterium(hostcache,
(void *) &user,
- hostcache_entry_is_stale);
+ dnscache_entry_is_stale);
return user.oldest;
}
+static struct Curl_dnscache *dnscache_get(struct Curl_easy *data)
+{
+ if(data->share && data->share->specifier & (1 << CURL_LOCK_DATA_DNS))
+ return &data->share->dnscache;
+ if(data->multi)
+ return &data->multi->dnscache;
+ return NULL;
+}
+
+static void dnscache_lock(struct Curl_easy *data,
+ struct Curl_dnscache *dnscache)
+{
+ if(data->share && dnscache == &data->share->dnscache)
+ Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);
+}
+
+static void dnscache_unlock(struct Curl_easy *data,
+ struct Curl_dnscache *dnscache)
+{
+ if(data->share && dnscache == &data->share->dnscache)
+ Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
+}
+
/*
* Library-wide function for pruning the DNS cache. This function takes and
* returns the appropriate locks.
*/
-void Curl_hostcache_prune(struct Curl_easy *data)
+void Curl_dnscache_prune(struct Curl_easy *data)
{
+ struct Curl_dnscache *dnscache = dnscache_get(data);
time_t now;
/* the timeout may be set -1 (forever) */
int timeout = data->set.dns_cache_timeout;
- if(!data->dns.hostcache)
+ if(!dnscache)
/* NULL hostcache means we cannot do it */
return;
- if(data->share)
- Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);
+ dnscache_lock(data, dnscache);
now = time(NULL);
do {
/* Remove outdated and unused entries from the hostcache */
- time_t oldest = hostcache_prune(data->dns.hostcache, timeout, now);
+ time_t oldest = dnscache_prune(&dnscache->entries, timeout, now);
if(oldest < INT_MAX)
timeout = (int)oldest; /* we know it fits */
@@ -262,10 +285,9 @@ void Curl_hostcache_prune(struct Curl_easy *data)
/* if the cache size is still too big, use the oldest age as new
prune limit */
} while(timeout &&
- (Curl_hash_count(data->dns.hostcache) > MAX_DNS_CACHE_SIZE));
+ (Curl_hash_count(&dnscache->entries) > MAX_DNS_CACHE_SIZE));
- if(data->share)
- Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
+ dnscache_unlock(data, dnscache);
}
#ifdef USE_ALARM_TIMEOUT
@@ -278,50 +300,56 @@ static curl_simple_lock curl_jmpenv_lock;
/* lookup address, returns entry if found and not stale */
static struct Curl_dns_entry *fetch_addr(struct Curl_easy *data,
+ struct Curl_dnscache *dnscache,
const char *hostname,
- int port)
+ int port,
+ int ip_version)
{
struct Curl_dns_entry *dns = NULL;
char entry_id[MAX_HOSTCACHE_LEN];
+ size_t entry_len;
+
+ if(!dnscache)
+ return NULL;
/* Create an entry id, based upon the hostname and port */
- size_t entry_len = create_hostcache_id(hostname, 0, port,
- entry_id, sizeof(entry_id));
+ entry_len = create_dnscache_id(hostname, 0, port,
+ entry_id, sizeof(entry_id));
/* See if it is already in our dns cache */
- dns = Curl_hash_pick(data->dns.hostcache, entry_id, entry_len + 1);
+ dns = Curl_hash_pick(&dnscache->entries, entry_id, entry_len + 1);
/* No entry found in cache, check if we might have a wildcard entry */
if(!dns && data->state.wildcard_resolve) {
- entry_len = create_hostcache_id("*", 1, port, entry_id, sizeof(entry_id));
+ entry_len = create_dnscache_id("*", 1, port, entry_id, sizeof(entry_id));
/* See if it is already in our dns cache */
- dns = Curl_hash_pick(data->dns.hostcache, entry_id, entry_len + 1);
+ dns = Curl_hash_pick(&dnscache->entries, entry_id, entry_len + 1);
}
if(dns && (data->set.dns_cache_timeout != -1)) {
/* See whether the returned entry is stale. Done before we release lock */
- struct hostcache_prune_data user;
+ struct dnscache_prune_data user;
user.now = time(NULL);
user.max_age_sec = data->set.dns_cache_timeout;
user.oldest = 0;
- if(hostcache_entry_is_stale(&user, dns)) {
+ if(dnscache_entry_is_stale(&user, dns)) {
infof(data, "Hostname in DNS cache was stale, zapped");
dns = NULL; /* the memory deallocation is being handled by the hash */
- Curl_hash_delete(data->dns.hostcache, entry_id, entry_len + 1);
+ Curl_hash_delete(&dnscache->entries, entry_id, entry_len + 1);
}
}
/* See if the returned entry matches the required resolve mode */
- if(dns && data->conn->ip_version != CURL_IPRESOLVE_WHATEVER) {
+ if(dns && ip_version != CURL_IPRESOLVE_WHATEVER) {
int pf = PF_INET;
bool found = FALSE;
struct Curl_addrinfo *addr = dns->addr;
#ifdef PF_INET6
- if(data->conn->ip_version == CURL_IPRESOLVE_V6)
+ if(ip_version == CURL_IPRESOLVE_V6)
pf = PF_INET6;
#endif
@@ -336,14 +364,14 @@ static struct Curl_dns_entry *fetch_addr(struct Curl_easy *data,
if(!found) {
infof(data, "Hostname in DNS cache does not have needed family, zapped");
dns = NULL; /* the memory deallocation is being handled by the hash */
- Curl_hash_delete(data->dns.hostcache, entry_id, entry_len + 1);
+ Curl_hash_delete(&dnscache->entries, entry_id, entry_len + 1);
}
}
return dns;
}
/*
- * Curl_fetch_addr() fetches a 'Curl_dns_entry' already in the DNS cache.
+ * Curl_dnscache_get() fetches a 'Curl_dns_entry' already in the DNS cache.
*
* Curl_resolv() checks initially and multi_runsingle() checks each time
* it discovers the handle in the state WAITRESOLVE whether the hostname
@@ -357,22 +385,21 @@ static struct Curl_dns_entry *fetch_addr(struct Curl_easy *data,
* use, or we will leak memory!
*/
struct Curl_dns_entry *
-Curl_fetch_addr(struct Curl_easy *data,
- const char *hostname,
- int port)
+Curl_dnscache_get(struct Curl_easy *data,
+ const char *hostname,
+ int port,
+ int ip_version)
{
+ struct Curl_dnscache *dnscache = dnscache_get(data);
struct Curl_dns_entry *dns = NULL;
- if(data->share)
- Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);
-
- dns = fetch_addr(data, hostname, port);
+ dnscache_lock(data, dnscache);
+ dns = fetch_addr(data, dnscache, hostname, port, ip_version);
if(dns)
dns->refcount++; /* we use it! */
- if(data->share)
- Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
+ dnscache_unlock(data, dnscache);
return dns;
}
@@ -459,34 +486,24 @@ UNITTEST CURLcode Curl_shuffle_addr(struct Curl_easy *data,
}
#endif
-/*
- * Curl_cache_addr() stores a 'Curl_addrinfo' struct in the DNS cache.
- *
- * When calling Curl_resolv() has resulted in a response with a returned
- * address, we call this function to store the information in the dns
- * cache etc
- *
- * Returns the Curl_dns_entry entry pointer or NULL if the storage failed.
- */
struct Curl_dns_entry *
-Curl_cache_addr(struct Curl_easy *data,
- struct Curl_addrinfo *addr,
- const char *hostname,
- size_t hostlen, /* length or zero */
- int port,
- bool permanent)
+Curl_dnscache_mk_entry(struct Curl_easy *data,
+ struct Curl_addrinfo *addr,
+ const char *hostname,
+ size_t hostlen, /* length or zero */
+ int port,
+ bool permanent)
{
- char entry_id[MAX_HOSTCACHE_LEN];
- size_t entry_len;
struct Curl_dns_entry *dns;
- struct Curl_dns_entry *dns2;
#ifndef CURL_DISABLE_SHUFFLE_DNS
/* shuffle addresses if requested */
if(data->set.dns_shuffle_addresses) {
CURLcode result = Curl_shuffle_addr(data, &addr);
- if(result)
+ if(result) {
+ Curl_freeaddrinfo(addr);
return NULL;
+ }
}
#endif
if(!hostlen)
@@ -495,13 +512,10 @@ Curl_cache_addr(struct Curl_easy *data,
/* Create a new cache entry */
dns = calloc(1, sizeof(struct Curl_dns_entry) + hostlen);
if(!dns) {
+ Curl_freeaddrinfo(addr);
return NULL;
}
- /* Create an entry id, based upon the hostname and port */
- entry_len = create_hostcache_id(hostname, hostlen, port,
- entry_id, sizeof(entry_id));
-
dns->refcount = 1; /* the cache has the first reference */
dns->addr = addr; /* this is the address(es) */
if(permanent)
@@ -515,11 +529,36 @@ Curl_cache_addr(struct Curl_easy *data,
if(hostlen)
memcpy(dns->hostname, hostname, hostlen);
+ return dns;
+}
+
+static struct Curl_dns_entry *
+dnscache_add_addr(struct Curl_easy *data,
+ struct Curl_dnscache *dnscache,
+ struct Curl_addrinfo *addr,
+ const char *hostname,
+ size_t hlen, /* length or zero */
+ int port,
+ bool permanent)
+{
+ char entry_id[MAX_HOSTCACHE_LEN];
+ size_t entry_len;
+ struct Curl_dns_entry *dns;
+ struct Curl_dns_entry *dns2;
+
+ dns = Curl_dnscache_mk_entry(data, addr, hostname, hlen, port, permanent);
+ if(!dns)
+ return NULL;
+
+ /* Create an entry id, based upon the hostname and port */
+ entry_len = create_dnscache_id(hostname, hlen, port,
+ entry_id, sizeof(entry_id));
+
/* Store the resolved data in our DNS cache. */
- dns2 = Curl_hash_add(data->dns.hostcache, entry_id, entry_len + 1,
+ dns2 = Curl_hash_add(&dnscache->entries, entry_id, entry_len + 1,
(void *)dns);
if(!dns2) {
- free(dns);
+ dnscache_entry_free(dns);
return NULL;
}
@@ -528,6 +567,30 @@ Curl_cache_addr(struct Curl_easy *data,
return dns;
}
+CURLcode Curl_dnscache_add(struct Curl_easy *data,
+ struct Curl_dns_entry *entry)
+{
+ struct Curl_dnscache *dnscache = dnscache_get(data);
+ char id[MAX_HOSTCACHE_LEN];
+ size_t idlen;
+
+ if(!dnscache)
+ return CURLE_FAILED_INIT;
+ /* Create an entry id, based upon the hostname and port */
+ idlen = create_dnscache_id(entry->hostname, 0, entry->hostport,
+ id, sizeof(id));
+
+ /* Store the resolved data in our DNS cache and up ref count */
+ dnscache_lock(data, dnscache);
+ if(!Curl_hash_add(&dnscache->entries, id, idlen + 1, (void *)entry)) {
+ dnscache_unlock(data, dnscache);
+ return CURLE_OUT_OF_MEMORY;
+ }
+ entry->refcount++;
+ dnscache_unlock(data, dnscache);
+ return CURLE_OK;
+}
+
#ifdef USE_IPV6
/* return a static IPv6 ::1 for the name */
static struct Curl_addrinfo *get_localhost6(int port, const char *name)
@@ -662,15 +725,63 @@ bool Curl_host_is_ipnum(const char *hostname)
/* return TRUE if 'part' is a case insensitive tail of 'full' */
-static bool tailmatch(const char *full, const char *part)
+static bool tailmatch(const char *full, size_t flen,
+ const char *part, size_t plen)
{
- size_t plen = strlen(part);
- size_t flen = strlen(full);
if(plen > flen)
return FALSE;
return strncasecompare(part, &full[flen - plen], plen);
}
+static struct Curl_addrinfo *
+convert_ipaddr_direct(const char *hostname, int port, bool *is_ipaddr)
+{
+ struct in_addr in;
+ *is_ipaddr = FALSE;
+ /* First check if this is an IPv4 address string */
+ if(curlx_inet_pton(AF_INET, hostname, &in) > 0) {
+ /* This is a dotted IP address 123.123.123.123-style */
+ *is_ipaddr = TRUE;
+#ifdef USE_RESOLVE_ON_IPS
+ (void)port;
+ return NULL;
+#else
+ return Curl_ip2addr(AF_INET, &in, hostname, port);
+#endif
+ }
+#ifdef USE_IPV6
+ else {
+ struct in6_addr in6;
+ /* check if this is an IPv6 address string */
+ if(curlx_inet_pton(AF_INET6, hostname, &in6) > 0) {
+ /* This is an IPv6 address literal */
+ *is_ipaddr = TRUE;
+#ifdef USE_RESOLVE_ON_IPS
+ return NULL;
+#else
+ return Curl_ip2addr(AF_INET6, &in6, hostname, port);
+#endif
+ }
+ }
+#endif /* USE_IPV6 */
+ return NULL;
+}
+
+static bool can_resolve_ip_version(struct Curl_easy *data, int ip_version)
+{
+#ifdef CURLRES_IPV6
+ if(ip_version == CURL_IPRESOLVE_V6 && !Curl_ipv6works(data))
+ return FALSE;
+#elif defined(CURLRES_IPV4)
+ (void)data;
+ if(ip_version == CURL_IPRESOLVE_V6)
+ return FALSE;
+#else
+#error either CURLRES_IPV6 or CURLRES_IPV4 need to be defined
+#endif
+ return TRUE;
+}
+
/*
* Curl_resolv() is the main name resolve function within libcurl. It resolves
* a name and returns a pointer to the entry in the 'entry' argument (if one
@@ -682,184 +793,168 @@ static bool tailmatch(const char *full, const char *part)
* done using this struct) to decrease the reference counter again.
*
* Return codes:
- *
- * CURLRESOLV_ERROR (-1) = error, no pointer
- * CURLRESOLV_RESOLVED (0) = OK, pointer provided
- * CURLRESOLV_PENDING (1) = waiting for response, no pointer
+ * CURLE_OK = success, *entry set to non-NULL
+ * CURLE_AGAIN = resolving in progress, *entry == NULL
+ * CURLE_COULDNT_RESOLVE_HOST = error, *entry == NULL
+ * CURLE_OPERATION_TIMEDOUT = timeout expired, *entry == NULL
*/
-
-enum resolve_t Curl_resolv(struct Curl_easy *data,
- const char *hostname,
- int port,
- bool allowDOH,
- struct Curl_dns_entry **entry)
+CURLcode Curl_resolv(struct Curl_easy *data,
+ const char *hostname,
+ int port,
+ int ip_version,
+ bool allowDOH,
+ struct Curl_dns_entry **entry)
{
+ struct Curl_dnscache *dnscache = dnscache_get(data);
struct Curl_dns_entry *dns = NULL;
- CURLcode result;
- enum resolve_t rc = CURLRESOLV_ERROR; /* default to failure */
- struct connectdata *conn = data->conn;
+ struct Curl_addrinfo *addr = NULL;
+ int respwait = 0;
+ bool is_ipaddr;
+ size_t hostname_len;
+
+#ifndef CURL_DISABLE_DOH
+ data->conn->bits.doh = FALSE; /* default is not */
+#else
+ (void)allowDOH;
+#endif
+ if(!dnscache)
+ goto error;
+
/* We should intentionally error and not resolve .onion TLDs */
- size_t hostname_len = strlen(hostname);
+ hostname_len = strlen(hostname);
if(hostname_len >= 7 &&
(curl_strequal(&hostname[hostname_len - 6], ".onion") ||
curl_strequal(&hostname[hostname_len - 7], ".onion."))) {
failf(data, "Not resolving .onion address (RFC 7686)");
- return CURLRESOLV_ERROR;
+ goto error;
}
- *entry = NULL;
-#ifndef CURL_DISABLE_DOH
- conn->bits.doh = FALSE; /* default is not */
-#else
- (void)allowDOH;
-#endif
-
- if(data->share)
- Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);
-
- dns = fetch_addr(data, hostname, port);
+ /* Let's check our DNS cache first */
+ dnscache_lock(data, dnscache);
+ dns = fetch_addr(data, dnscache, hostname, port, ip_version);
+ if(dns)
+ dns->refcount++; /* we pass out the reference. */
+ dnscache_unlock(data, dnscache);
if(dns) {
infof(data, "Hostname %s was found in DNS cache", hostname);
- dns->refcount++; /* we use it! */
- rc = CURLRESOLV_RESOLVED;
+ goto out;
}
- if(data->share)
- Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
+ /* No luck, we need to resolve hostname. Notify user callback. */
+ if(data->set.resolver_start) {
+ void *resolver = NULL;
+ int st;
+#ifdef CURLRES_ASYNCH
+ if(Curl_async_get_impl(data, &resolver))
+ goto error;
+#endif
+ Curl_set_in_callback(data, TRUE);
+ st = data->set.resolver_start(resolver, NULL,
+ data->set.resolver_start_client);
+ Curl_set_in_callback(data, FALSE);
+ if(st)
+ goto error;
+ }
- if(!dns) {
- /* The entry was not in the cache. Resolve it to IP address */
+ /* shortcut literal IP addresses, if we are not told to resolve them. */
+ addr = convert_ipaddr_direct(hostname, port, &is_ipaddr);
+ if(addr)
+ goto out;
- struct Curl_addrinfo *addr = NULL;
- int respwait = 0;
-#if !defined(CURL_DISABLE_DOH) || !defined(USE_RESOLVE_ON_IPS)
- struct in_addr in;
-#endif
-#ifndef CURL_DISABLE_DOH
#ifndef USE_RESOLVE_ON_IPS
- const
+ /* allowed to convert, hostname is IP address, then NULL means error */
+ if(is_ipaddr)
+ goto error;
#endif
- bool ipnum = FALSE;
+
+ /* Really need a resolver for hostname. */
+ if(ip_version == CURL_IPRESOLVE_V6 && !Curl_ipv6works(data))
+ goto error;
+
+ if(!is_ipaddr &&
+ (strcasecompare(hostname, "localhost") ||
+ strcasecompare(hostname, "localhost.") ||
+ tailmatch(hostname, hostname_len, STRCONST(".localhost")) ||
+ tailmatch(hostname, hostname_len, STRCONST(".localhost.")))) {
+ addr = get_localhost(port, hostname);
+ }
+#ifndef CURL_DISABLE_DOH
+ else if(!is_ipaddr && allowDOH && data->set.doh) {
+ addr = Curl_doh(data, hostname, port, ip_version, &respwait);
+ }
#endif
+ else {
+ /* Can we provide the requested IP specifics in resolving? */
+ if(!can_resolve_ip_version(data, ip_version))
+ goto error;
- /* notify the resolver start callback */
- if(data->set.resolver_start) {
- int st;
- Curl_set_in_callback(data, TRUE);
- st = data->set.resolver_start(
#ifdef CURLRES_ASYNCH
- data->state.async.resolver,
+ addr = Curl_async_getaddrinfo(data, hostname, port, ip_version, &respwait);
#else
- NULL,
+ respwait = 0; /* no async waiting here */
+ addr = Curl_sync_getaddrinfo(data, hostname, port, ip_version);
#endif
- NULL,
- data->set.resolver_start_client);
- Curl_set_in_callback(data, FALSE);
- if(st)
- return CURLRESOLV_ERROR;
- }
-
-#ifndef USE_RESOLVE_ON_IPS
- /* First check if this is an IPv4 address string */
- if(curlx_inet_pton(AF_INET, hostname, &in) > 0) {
- /* This is a dotted IP address 123.123.123.123-style */
- addr = Curl_ip2addr(AF_INET, &in, hostname, port);
- if(!addr)
- return CURLRESOLV_ERROR;
- }
-#ifdef USE_IPV6
- else {
- struct in6_addr in6;
- /* check if this is an IPv6 address string */
- if(curlx_inet_pton(AF_INET6, hostname, &in6) > 0) {
- /* This is an IPv6 address literal */
- addr = Curl_ip2addr(AF_INET6, &in6, hostname, port);
- if(!addr)
- return CURLRESOLV_ERROR;
- }
- }
-#endif /* USE_IPV6 */
-
-#else /* if USE_RESOLVE_ON_IPS */
-#ifndef CURL_DISABLE_DOH
- /* First check if this is an IPv4 address string */
- if(curlx_inet_pton(AF_INET, hostname, &in) > 0)
- /* This is a dotted IP address 123.123.123.123-style */
- ipnum = TRUE;
-#ifdef USE_IPV6
- else {
- struct in6_addr in6;
- /* check if this is an IPv6 address string */
- if(curlx_inet_pton(AF_INET6, hostname, &in6) > 0)
- /* This is an IPv6 address literal */
- ipnum = TRUE;
- }
-#endif /* USE_IPV6 */
-#endif /* CURL_DISABLE_DOH */
-
-#endif /* !USE_RESOLVE_ON_IPS */
-
- if(!addr) {
- if(conn->ip_version == CURL_IPRESOLVE_V6 && !Curl_ipv6works(data))
- return CURLRESOLV_ERROR;
+ }
- if(strcasecompare(hostname, "localhost") ||
- strcasecompare(hostname, "localhost.") ||
- tailmatch(hostname, ".localhost") ||
- tailmatch(hostname, ".localhost."))
- addr = get_localhost(port, hostname);
-#ifndef CURL_DISABLE_DOH
- else if(allowDOH && data->set.doh && !ipnum)
- addr = Curl_doh(data, hostname, port, &respwait);
-#endif
- else {
- /* Check what IP specifics the app has requested and if we can provide
- * it. If not, bail out. */
- if(!Curl_ipvalid(data, conn))
- return CURLRESOLV_ERROR;
- /* If Curl_getaddrinfo() returns NULL, 'respwait' might be set to a
- non-zero value indicating that we need to wait for the response to
- the resolve call */
- addr = Curl_getaddrinfo(data, hostname, port, &respwait);
- }
- }
- if(!addr) {
- if(respwait) {
- /* the response to our resolve call will come asynchronously at
- a later time, good or bad */
- /* First, check that we have not received the info by now */
- result = Curl_resolv_check(data, &dns);
- if(result) /* error detected */
- return CURLRESOLV_ERROR;
- if(dns)
- rc = CURLRESOLV_RESOLVED; /* pointer provided */
- else
- rc = CURLRESOLV_PENDING; /* no info yet */
- }
+out:
+ /* We either have found a `dns` or looked up the `addr`
+ * or `respwait` is set for an async operation.
+ * Everything else is a failure to resolve. */
+ if(dns) {
+ *entry = dns;
+ return CURLE_OK;
+ }
+ else if(addr) {
+ /* we got a response, create a dns entry, add to cache, return */
+ dns = Curl_dnscache_mk_entry(data, addr, hostname, 0, port, FALSE);
+ if(!dns)
+ goto error;
+ if(Curl_dnscache_add(data, dns))
+ goto error;
+ show_resolve_info(data, dns);
+ *entry = dns;
+ return CURLE_OK;
+ }
+ else if(respwait) {
+ if(!Curl_resolv_check(data, &dns)) {
+ *entry = dns;
+ return dns ? CURLE_OK : CURLE_AGAIN;
}
- else {
- if(data->share)
- Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);
-
- /* we got a response, store it in the cache */
- dns = Curl_cache_addr(data, addr, hostname, 0, port, FALSE);
+ }
+error:
+ if(dns)
+ Curl_resolv_unlink(data, &dns);
+ *entry = NULL;
+ Curl_async_shutdown(data);
+ return CURLE_COULDNT_RESOLVE_HOST;
+}
- if(data->share)
- Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
+CURLcode Curl_resolv_blocking(struct Curl_easy *data,
+ const char *hostname,
+ int port,
+ int ip_version,
+ struct Curl_dns_entry **dnsentry)
+{
+ CURLcode result;
- if(!dns)
- /* returned failure, bail out nicely */
- Curl_freeaddrinfo(addr);
- else {
- rc = CURLRESOLV_RESOLVED;
- show_resolve_info(data, dns);
- }
+ *dnsentry = NULL;
+ result = Curl_resolv(data, hostname, port, ip_version, FALSE, dnsentry);
+ switch(result) {
+ case CURLE_OK:
+ DEBUGASSERT(*dnsentry);
+ return CURLE_OK;
+ case CURLE_AGAIN:
+ DEBUGASSERT(!*dnsentry);
+ result = Curl_async_await(data, dnsentry);
+ if(result || !*dnsentry) {
+ /* close the connection, since we cannot return failure here without
+ cleaning up this connection properly. */
+ connclose(data->conn, "async resolve failed");
}
+ return result;
+ default:
+ return result;
}
-
- *entry = dns;
-
- return rc;
}
#ifdef USE_ALARM_TIMEOUT
@@ -891,18 +986,18 @@ void alarmfunc(int sig)
* is ignored.
*
* Return codes:
- *
- * CURLRESOLV_TIMEDOUT(-2) = warning, time too short or previous alarm expired
- * CURLRESOLV_ERROR (-1) = error, no pointer
- * CURLRESOLV_RESOLVED (0) = OK, pointer provided
- * CURLRESOLV_PENDING (1) = waiting for response, no pointer
+ * CURLE_OK = success, *entry set to non-NULL
+ * CURLE_AGAIN = resolving in progress, *entry == NULL
+ * CURLE_COULDNT_RESOLVE_HOST = error, *entry == NULL
+ * CURLE_OPERATION_TIMEDOUT = timeout expired, *entry == NULL
*/
-enum resolve_t Curl_resolv_timeout(struct Curl_easy *data,
- const char *hostname,
- int port,
- struct Curl_dns_entry **entry,
- timediff_t timeoutms)
+CURLcode Curl_resolv_timeout(struct Curl_easy *data,
+ const char *hostname,
+ int port,
+ int ip_version,
+ struct Curl_dns_entry **entry,
+ timediff_t timeoutms)
{
#ifdef USE_ALARM_TIMEOUT
#ifdef HAVE_SIGACTION
@@ -917,13 +1012,13 @@ enum resolve_t Curl_resolv_timeout(struct Curl_easy *data,
volatile long timeout;
volatile unsigned int prev_alarm = 0;
#endif /* USE_ALARM_TIMEOUT */
- enum resolve_t rc;
+ CURLcode result;
*entry = NULL;
if(timeoutms < 0)
/* got an already expired timeout */
- return CURLRESOLV_TIMEDOUT;
+ return CURLE_OPERATION_TIMEDOUT;
#ifdef USE_ALARM_TIMEOUT
if(data->set.no_signal)
@@ -932,10 +1027,14 @@ enum resolve_t Curl_resolv_timeout(struct Curl_easy *data,
else
timeout = (timeoutms > LONG_MAX) ? LONG_MAX : (long)timeoutms;
- if(!timeout || data->set.doh)
+ if(!timeout
+#ifndef CURL_DISABLE_DOH
+ || data->set.doh
+#endif
+ )
/* USE_ALARM_TIMEOUT defined, but no timeout actually requested or resolve
done using DoH */
- return Curl_resolv(data, hostname, port, TRUE, entry);
+ return Curl_resolv(data, hostname, port, ip_version, TRUE, entry);
if(timeout < 1000) {
/* The alarm() function only provides integer second resolution, so if
@@ -943,7 +1042,7 @@ enum resolve_t Curl_resolv_timeout(struct Curl_easy *data,
failf(data,
"remaining timeout of %ld too small to resolve via SIGALRM method",
timeout);
- return CURLRESOLV_TIMEDOUT;
+ return CURLE_OPERATION_TIMEDOUT;
}
/* This allows us to time-out from the name resolver, as the timeout
will generate a signal and we will siglongjmp() from that here.
@@ -956,7 +1055,7 @@ enum resolve_t Curl_resolv_timeout(struct Curl_easy *data,
if(sigsetjmp(curl_jmpenv, 1)) {
/* this is coming from a siglongjmp() after an alarm signal */
failf(data, "name lookup timed out");
- rc = CURLRESOLV_ERROR;
+ result = CURLE_OPERATION_TIMEDOUT;
goto clean_up;
}
else {
@@ -987,19 +1086,19 @@ enum resolve_t Curl_resolv_timeout(struct Curl_easy *data,
prev_alarm = alarm(curlx_sltoui(timeout/1000L));
}
-#else
+#else /* USE_ALARM_TIMEOUT */
#ifndef CURLRES_ASYNCH
if(timeoutms)
infof(data, "timeout on name lookup is not supported");
#else
(void)timeoutms; /* timeoutms not used with an async resolver */
#endif
-#endif /* USE_ALARM_TIMEOUT */
+#endif /* else USE_ALARM_TIMEOUT */
/* Perform the actual name resolution. This might be interrupted by an
* alarm if it takes too long.
*/
- rc = Curl_resolv(data, hostname, port, TRUE, entry);
+ result = Curl_resolv(data, hostname, port, ip_version, TRUE, entry);
#ifdef USE_ALARM_TIMEOUT
clean_up:
@@ -1027,7 +1126,7 @@ clean_up:
the time we spent until now! */
if(prev_alarm) {
/* there was an alarm() set before us, now put it back */
- timediff_t elapsed_secs = Curl_timediff(Curl_now(),
+ timediff_t elapsed_secs = curlx_timediff(curlx_now(),
data->conn->created) / 1000;
/* the alarm period is counted in even number of seconds */
@@ -1040,7 +1139,7 @@ clean_up:
will not, and zero would be to switch it off so we never set it to
less than 1! */
alarm(1);
- rc = CURLRESOLV_TIMEDOUT;
+ result = CURLE_OPERATION_TIMEDOUT;
failf(data, "Previous alarm fired off");
}
else
@@ -1048,7 +1147,19 @@ clean_up:
}
#endif /* USE_ALARM_TIMEOUT */
- return rc;
+ return result;
+}
+
+static void dnscache_entry_free(struct Curl_dns_entry *dns)
+{
+ Curl_freeaddrinfo(dns->addr);
+#ifdef USE_HTTPSRR
+ if(dns->hinfo) {
+ Curl_httpsrr_cleanup(dns->hinfo);
+ free(dns->hinfo);
+ }
+#endif
+ free(dns);
}
/*
@@ -1060,71 +1171,49 @@ clean_up:
*/
void Curl_resolv_unlink(struct Curl_easy *data, struct Curl_dns_entry **pdns)
{
- struct Curl_dns_entry *dns = *pdns;
- *pdns = NULL;
- if(data && data->share)
- Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);
-
- hostcache_unlink_entry(dns);
-
- if(data && data->share)
- Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
+ if(*pdns) {
+ struct Curl_dnscache *dnscache = dnscache_get(data);
+ struct Curl_dns_entry *dns = *pdns;
+ *pdns = NULL;
+ dnscache_lock(data, dnscache);
+ dns->refcount--;
+ if(dns->refcount == 0)
+ dnscache_entry_free(dns);
+ dnscache_unlock(data, dnscache);
+ }
}
-/*
- * File-internal: release cache dns entry reference, free if inuse drops to 0
- */
-static void hostcache_unlink_entry(void *entry)
+static void dnscache_entry_dtor(void *entry)
{
struct Curl_dns_entry *dns = (struct Curl_dns_entry *) entry;
DEBUGASSERT(dns && (dns->refcount > 0));
-
dns->refcount--;
- if(dns->refcount == 0) {
- Curl_freeaddrinfo(dns->addr);
-#ifdef USE_HTTPSRR
- if(dns->hinfo) {
- Curl_httpsrr_cleanup(dns->hinfo);
- free(dns->hinfo);
- }
-#endif
- free(dns);
- }
+ if(dns->refcount == 0)
+ dnscache_entry_free(dns);
}
/*
- * Curl_init_dnscache() inits a new DNS cache.
+ * Curl_dnscache_init() inits a new DNS cache.
*/
-void Curl_init_dnscache(struct Curl_hash *hash, size_t size)
+void Curl_dnscache_init(struct Curl_dnscache *dns, size_t size)
{
- Curl_hash_init(hash, size, Curl_hash_str, Curl_str_key_compare,
- hostcache_unlink_entry);
+ Curl_hash_init(&dns->entries, size, Curl_hash_str, curlx_str_key_compare,
+ dnscache_entry_dtor);
}
-/*
- * Curl_hostcache_clean()
- *
- * This _can_ be called with 'data' == NULL but then of course no locking
- * can be done!
- */
-
-void Curl_hostcache_clean(struct Curl_easy *data,
- struct Curl_hash *hash)
+void Curl_dnscache_destroy(struct Curl_dnscache *dns)
{
- if(data && data->share)
- Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);
-
- Curl_hash_clean(hash);
-
- if(data && data->share)
- Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
+ Curl_hash_destroy(&dns->entries);
}
-
CURLcode Curl_loadhostpairs(struct Curl_easy *data)
{
+ struct Curl_dnscache *dnscache = dnscache_get(data);
struct curl_slist *hostp;
+ if(!dnscache)
+ return CURLE_FAILED_INIT;
+
/* Default is no wildcard found */
data->state.wildcard_resolve = FALSE;
@@ -1138,32 +1227,28 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data)
curl_off_t num = 0;
size_t entry_len;
host++;
- if(!Curl_str_single(&host, '[')) {
- if(Curl_str_until(&host, &source, MAX_IPADR_LEN, ']') ||
- Curl_str_single(&host, ']') ||
- Curl_str_single(&host, ':'))
+ if(!curlx_str_single(&host, '[')) {
+ if(curlx_str_until(&host, &source, MAX_IPADR_LEN, ']') ||
+ curlx_str_single(&host, ']') ||
+ curlx_str_single(&host, ':'))
continue;
}
else {
- if(Curl_str_until(&host, &source, 4096, ':') ||
- Curl_str_single(&host, ':')) {
+ if(curlx_str_until(&host, &source, 4096, ':') ||
+ curlx_str_single(&host, ':')) {
continue;
}
}
- if(!Curl_str_number(&host, &num, 0xffff)) {
+ if(!curlx_str_number(&host, &num, 0xffff)) {
/* Create an entry id, based upon the hostname and port */
- entry_len = create_hostcache_id(Curl_str(&source),
- Curl_strlen(&source), (int)num,
- entry_id, sizeof(entry_id));
- if(data->share)
- Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);
-
+ entry_len = create_dnscache_id(curlx_str(&source),
+ curlx_strlen(&source), (int)num,
+ entry_id, sizeof(entry_id));
+ dnscache_lock(data, dnscache);
/* delete entry, ignore if it did not exist */
- Curl_hash_delete(data->dns.hostcache, entry_id, entry_len + 1);
-
- if(data->share)
- Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
+ Curl_hash_delete(&dnscache->entries, entry_id, entry_len + 1);
+ dnscache_unlock(data, dnscache);
}
}
else {
@@ -1182,18 +1267,18 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data)
host++;
permanent = FALSE;
}
- if(!Curl_str_single(&host, '[')) {
- if(Curl_str_until(&host, &source, MAX_IPADR_LEN, ']') ||
- Curl_str_single(&host, ']'))
+ if(!curlx_str_single(&host, '[')) {
+ if(curlx_str_until(&host, &source, MAX_IPADR_LEN, ']') ||
+ curlx_str_single(&host, ']'))
continue;
}
else {
- if(Curl_str_until(&host, &source, 4096, ':'))
+ if(curlx_str_until(&host, &source, 4096, ':'))
continue;
}
- if(Curl_str_single(&host, ':') ||
- Curl_str_number(&host, &port, 0xffff) ||
- Curl_str_single(&host, ':'))
+ if(curlx_str_single(&host, ':') ||
+ curlx_str_number(&host, &port, 0xffff) ||
+ curlx_str_single(&host, ':'))
goto err;
#if !defined(CURL_DISABLE_VERBOSE_STRINGS)
@@ -1205,14 +1290,14 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data)
struct Curl_str target;
struct Curl_addrinfo *ai;
- if(!Curl_str_single(&host, '[')) {
- if(Curl_str_until(&host, &target, MAX_IPADR_LEN, ']') ||
- Curl_str_single(&host, ']'))
+ if(!curlx_str_single(&host, '[')) {
+ if(curlx_str_until(&host, &target, MAX_IPADR_LEN, ']') ||
+ curlx_str_single(&host, ']'))
goto err;
}
else {
- if(Curl_str_until(&host, &target, 4096, ',')) {
- if(Curl_str_single(&host, ','))
+ if(curlx_str_until(&host, &target, 4096, ',')) {
+ if(curlx_str_single(&host, ','))
goto err;
/* survive nothing but just a comma */
continue;
@@ -1222,17 +1307,17 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data)
if(memchr(target.str, ':', target.len)) {
infof(data, "Ignoring resolve address '%s', missing IPv6 support.",
address);
- if(Curl_str_single(&host, ','))
+ if(curlx_str_single(&host, ','))
goto err;
continue;
}
#endif
- if(Curl_strlen(&target) >= sizeof(address))
+ if(curlx_strlen(&target) >= sizeof(address))
goto err;
- memcpy(address, Curl_str(&target), Curl_strlen(&target));
- address[Curl_strlen(&target)] = '\0';
+ memcpy(address, curlx_str(&target), curlx_strlen(&target));
+ address[curlx_strlen(&target)] = '\0';
ai = Curl_str2addr(address, (int)port);
if(!ai) {
@@ -1247,7 +1332,7 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data)
else {
head = tail = ai;
}
- if(Curl_str_single(&host, ','))
+ if(curlx_str_single(&host, ','))
break;
}
@@ -1264,20 +1349,19 @@ err:
}
/* Create an entry id, based upon the hostname and port */
- entry_len = create_hostcache_id(Curl_str(&source), Curl_strlen(&source),
- (int)port,
- entry_id, sizeof(entry_id));
+ entry_len = create_dnscache_id(curlx_str(&source), curlx_strlen(&source),
+ (int)port,
+ entry_id, sizeof(entry_id));
- if(data->share)
- Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);
+ dnscache_lock(data, dnscache);
/* See if it is already in our dns cache */
- dns = Curl_hash_pick(data->dns.hostcache, entry_id, entry_len + 1);
+ dns = Curl_hash_pick(&dnscache->entries, entry_id, entry_len + 1);
if(dns) {
infof(data, "RESOLVE %.*s:%" CURL_FORMAT_CURL_OFF_T
- " - old addresses discarded", (int)Curl_strlen(&source),
- Curl_str(&source), port);
+ " - old addresses discarded", (int)curlx_strlen(&source),
+ curlx_str(&source), port);
/* delete old entry, there are two reasons for this
1. old entry may have different addresses.
2. even if entry with correct addresses is already in the cache,
@@ -1289,33 +1373,31 @@ err:
4. when adding a non-permanent entry, we want it to get a "fresh"
timeout that starts _now_. */
- Curl_hash_delete(data->dns.hostcache, entry_id, entry_len + 1);
+ Curl_hash_delete(&dnscache->entries, entry_id, entry_len + 1);
}
/* put this new host in the cache */
- dns = Curl_cache_addr(data, head, Curl_str(&source),
- Curl_strlen(&source), (int)port, permanent);
+ dns = dnscache_add_addr(data, dnscache, head, curlx_str(&source),
+ curlx_strlen(&source), (int)port, permanent);
if(dns) {
/* release the returned reference; the cache itself will keep the
* entry alive: */
dns->refcount--;
}
- if(data->share)
- Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
+ dnscache_unlock(data, dnscache);
- if(!dns) {
- Curl_freeaddrinfo(head);
+ if(!dns)
return CURLE_OUT_OF_MEMORY;
- }
+
#ifndef CURL_DISABLE_VERBOSE_STRINGS
infof(data, "Added %.*s:%" CURL_FORMAT_CURL_OFF_T ":%s to DNS cache%s",
- (int)Curl_strlen(&source), Curl_str(&source), port, addresses,
+ (int)curlx_strlen(&source), curlx_str(&source), port, addresses,
permanent ? "" : " (non-permanent)");
#endif
/* Wildcard hostname */
- if(Curl_str_casecompare(&source, "*")) {
+ if(curlx_str_casecompare(&source, "*")) {
infof(data, "RESOLVE *:%" CURL_FORMAT_CURL_OFF_T " using wildcard",
port);
data->state.wildcard_resolve = TRUE;
@@ -1351,9 +1433,9 @@ static void show_resolve_info(struct Curl_easy *data,
infof(data, "Host %s:%d was resolved.",
(dns->hostname[0] ? dns->hostname : "(none)"), dns->hostport);
- Curl_dyn_init(&out[0], 1024);
+ curlx_dyn_init(&out[0], 1024);
#ifdef CURLRES_IPV6
- Curl_dyn_init(&out[1], 1024);
+ curlx_dyn_init(&out[1], 1024);
#endif
while(a) {
@@ -1365,10 +1447,10 @@ static void show_resolve_info(struct Curl_easy *data,
char buf[MAX_IPADR_LEN];
struct dynbuf *d = &out[(a->ai_family != PF_INET)];
Curl_printable_address(a, buf, sizeof(buf));
- if(Curl_dyn_len(d))
- result = Curl_dyn_addn(d, ", ", 2);
+ if(curlx_dyn_len(d))
+ result = curlx_dyn_addn(d, ", ", 2);
if(!result)
- result = Curl_dyn_add(d, buf);
+ result = curlx_dyn_add(d, buf);
if(result) {
infof(data, "too many IP, cannot show");
goto fail;
@@ -1379,38 +1461,55 @@ static void show_resolve_info(struct Curl_easy *data,
#ifdef CURLRES_IPV6
infof(data, "IPv6: %s",
- (Curl_dyn_len(&out[1]) ? Curl_dyn_ptr(&out[1]) : "(none)"));
+ (curlx_dyn_len(&out[1]) ? curlx_dyn_ptr(&out[1]) : "(none)"));
#endif
infof(data, "IPv4: %s",
- (Curl_dyn_len(&out[0]) ? Curl_dyn_ptr(&out[0]) : "(none)"));
+ (curlx_dyn_len(&out[0]) ? curlx_dyn_ptr(&out[0]) : "(none)"));
fail:
- Curl_dyn_free(&out[0]);
+ curlx_dyn_free(&out[0]);
#ifdef CURLRES_IPV6
- Curl_dyn_free(&out[1]);
+ curlx_dyn_free(&out[1]);
#endif
}
#endif
+#ifdef USE_CURL_ASYNC
CURLcode Curl_resolv_check(struct Curl_easy *data,
struct Curl_dns_entry **dns)
{
CURLcode result;
-#if defined(CURL_DISABLE_DOH) && !defined(CURLRES_ASYNCH)
- (void)data;
- (void)dns;
-#endif
+
+ /* If async resolving is ongoing, this must be set */
+ if(!data->state.async.hostname)
+ return CURLE_FAILED_INIT;
+
+ /* check if we have the name resolved by now (from someone else) */
+ *dns = Curl_dnscache_get(data, data->state.async.hostname,
+ data->state.async.port,
+ data->state.async.ip_version);
+ if(*dns) {
+ /* Tell a possibly async resolver we no longer need the results. */
+ infof(data, "Hostname '%s' was found in DNS cache",
+ data->state.async.hostname);
+ Curl_async_shutdown(data);
+ data->state.async.dns = *dns;
+ data->state.async.done = TRUE;
+ return CURLE_OK;
+ }
+
#ifndef CURL_DISABLE_DOH
if(data->conn->bits.doh) {
result = Curl_doh_is_resolved(data, dns);
}
else
#endif
- result = Curl_resolver_is_resolved(data, dns);
+ result = Curl_async_is_resolved(data, dns);
if(*dns)
show_resolve_info(data, *dns);
return result;
}
+#endif
int Curl_resolv_getsock(struct Curl_easy *data,
curl_socket_t *socks)
@@ -1422,7 +1521,7 @@ int Curl_resolv_getsock(struct Curl_easy *data,
sockets */
return GETSOCK_BLANK;
#endif
- return Curl_resolver_getsock(data, socks);
+ return Curl_async_getsock(data, socks);
#else
(void)data;
(void)socks;
@@ -1435,19 +1534,21 @@ int Curl_resolv_getsock(struct Curl_easy *data,
Note: this function disconnects and frees the conn data in case of
resolve failure */
-CURLcode Curl_once_resolved(struct Curl_easy *data, bool *protocol_done)
+CURLcode Curl_once_resolved(struct Curl_easy *data,
+ struct Curl_dns_entry *dns,
+ bool *protocol_done)
{
CURLcode result;
struct connectdata *conn = data->conn;
#ifdef USE_CURL_ASYNC
if(data->state.async.dns) {
- conn->dns_entry = data->state.async.dns;
+ DEBUGASSERT(data->state.async.dns == dns);
data->state.async.dns = NULL;
}
#endif
- result = Curl_setup_conn(data, protocol_done);
+ result = Curl_setup_conn(data, dns, protocol_done);
if(result) {
Curl_detach_connection(data);
@@ -1464,25 +1565,21 @@ CURLcode Curl_once_resolved(struct Curl_easy *data, bool *protocol_done)
#ifdef USE_CURL_ASYNC
CURLcode Curl_resolver_error(struct Curl_easy *data)
{
- const char *host_or_proxy;
- CURLcode result;
+ struct connectdata *conn = data->conn;
+ const char *host_or_proxy = "host";
+ const char *name = conn->host.dispname;
+ CURLcode result = CURLE_COULDNT_RESOLVE_HOST;
#ifndef CURL_DISABLE_PROXY
- struct connectdata *conn = data->conn;
- if(conn->bits.httpproxy) {
+ if(conn->bits.proxy) {
host_or_proxy = "proxy";
result = CURLE_COULDNT_RESOLVE_PROXY;
+ name = conn->socks_proxy.host.name ? conn->socks_proxy.host.dispname :
+ conn->http_proxy.host.dispname;
}
- else
#endif
- {
- host_or_proxy = "host";
- result = CURLE_COULDNT_RESOLVE_HOST;
- }
-
- failf(data, "Could not resolve %s: %s", host_or_proxy,
- data->conn->host.dispname);
+ failf(data, "Could not resolve %s: %s", host_or_proxy, name);
return result;
}
#endif /* USE_CURL_ASYNC */
diff --git a/libs/libcurl/src/hostip.h b/libs/libcurl/src/hostip.h
index 6f28e7eec7..331a4a57d8 100644
--- a/libs/libcurl/src/hostip.h
+++ b/libs/libcurl/src/hostip.h
@@ -27,7 +27,7 @@
#include "curl_setup.h"
#include "hash.h"
#include "curl_addrinfo.h"
-#include "timeval.h" /* for timediff_t */
+#include "curlx/timeval.h" /* for timediff_t */
#include "asyn.h"
#include "httpsrr.h"
@@ -61,15 +61,6 @@ enum alpnid {
ALPN_h3 = CURLALTSVC_H3
};
-/*
- * Curl_global_host_cache_init() initializes and sets up a global DNS cache.
- * Global DNS cache is general badness. Do not use. This will be removed in
- * a future version. Use the share interface instead!
- *
- * Returns a struct Curl_hash pointer on success, NULL on failure.
- */
-struct Curl_hash *Curl_global_host_cache_init(void);
-
struct Curl_dns_entry {
struct Curl_addrinfo *addr;
#ifdef USE_HTTPSRR
@@ -85,6 +76,10 @@ struct Curl_dns_entry {
char hostname[1];
};
+struct Curl_dnscache {
+ struct Curl_hash entries;
+};
+
bool Curl_host_is_ipnum(const char *hostname);
/*
@@ -94,22 +89,24 @@ bool Curl_host_is_ipnum(const char *hostname);
* The returned data *MUST* be "released" with Curl_resolv_unlink() after
* use, or we will leak memory!
*/
-/* return codes */
-enum resolve_t {
- CURLRESOLV_TIMEDOUT = -2,
- CURLRESOLV_ERROR = -1,
- CURLRESOLV_RESOLVED = 0,
- CURLRESOLV_PENDING = 1
-};
-enum resolve_t Curl_resolv(struct Curl_easy *data,
- const char *hostname,
- int port,
- bool allowDOH,
- struct Curl_dns_entry **dnsentry);
-enum resolve_t Curl_resolv_timeout(struct Curl_easy *data,
- const char *hostname, int port,
- struct Curl_dns_entry **dnsentry,
- timediff_t timeoutms);
+CURLcode Curl_resolv(struct Curl_easy *data,
+ const char *hostname,
+ int port,
+ int ip_version,
+ bool allowDOH,
+ struct Curl_dns_entry **dnsentry);
+
+CURLcode Curl_resolv_blocking(struct Curl_easy *data,
+ const char *hostname,
+ int port,
+ int ip_version,
+ struct Curl_dns_entry **dnsentry);
+
+CURLcode Curl_resolv_timeout(struct Curl_easy *data,
+ const char *hostname, int port,
+ int ip_version,
+ struct Curl_dns_entry **dnsentry,
+ timediff_t timeoutms);
#ifdef USE_IPV6
/*
@@ -120,49 +117,25 @@ bool Curl_ipv6works(struct Curl_easy *data);
#define Curl_ipv6works(x) FALSE
#endif
-/*
- * Curl_ipvalid() checks what CURL_IPRESOLVE_* requirements that might've
- * been set and returns TRUE if they are OK.
- */
-bool Curl_ipvalid(struct Curl_easy *data, struct connectdata *conn);
-
-
-/*
- * Curl_getaddrinfo() is the generic low-level name resolve API within this
- * source file. There are several versions of this function - for different
- * name resolve layers (selected at build-time). They all take this same set
- * of arguments
- */
-struct Curl_addrinfo *Curl_getaddrinfo(struct Curl_easy *data,
- const char *hostname,
- int port,
- int *waitp);
-
/* unlink a dns entry, potentially shared with a cache */
void Curl_resolv_unlink(struct Curl_easy *data,
struct Curl_dns_entry **pdns);
/* init a new dns cache */
-void Curl_init_dnscache(struct Curl_hash *hash, size_t hashsize);
+void Curl_dnscache_init(struct Curl_dnscache *dns, size_t hashsize);
+
+void Curl_dnscache_destroy(struct Curl_dnscache *dns);
/* prune old entries from the DNS cache */
-void Curl_hostcache_prune(struct Curl_easy *data);
+void Curl_dnscache_prune(struct Curl_easy *data);
/* IPv4 threadsafe resolve function used for synch and asynch builds */
struct Curl_addrinfo *Curl_ipv4_resolve_r(const char *hostname, int port);
-CURLcode Curl_once_resolved(struct Curl_easy *data, bool *protocol_connect);
-
-/*
- * Curl_addrinfo_callback() is used when we build with any asynch specialty.
- * Handles end of async request processing. Inserts ai into hostcache when
- * status is CURL_ASYNC_SUCCESS. Twiddles fields in conn to indicate async
- * request completed whether successful or failed.
- */
-CURLcode Curl_addrinfo_callback(struct Curl_easy *data,
- int status,
- struct Curl_addrinfo *ai);
+CURLcode Curl_once_resolved(struct Curl_easy *data,
+ struct Curl_dns_entry *dns,
+ bool *protocol_connect);
/*
* Curl_printable_address() returns a printable version of the 1st address
@@ -173,67 +146,72 @@ void Curl_printable_address(const struct Curl_addrinfo *ip,
char *buf, size_t bufsize);
/*
- * Curl_fetch_addr() fetches a 'Curl_dns_entry' already in the DNS cache.
+ * Make a `Curl_dns_entry`.
+ * Creates a dnscache entry *without* adding it to a dnscache. This allows
+ * further modifications of the entry *before* then adding it to a cache.
*
- * Returns the Curl_dns_entry entry pointer or NULL if not in the cache.
+ * The entry is created with a reference count of 1.
+ * Use `Curl_resolv_unlink()` to release your hold on it.
*
- * The returned data *MUST* be "released" with Curl_resolv_unlink() after
- * use, or we will leak memory!
+ * The call takes ownership of `addr`and makes a copy of `hostname`.
+ *
+ * Returns entry or NULL on OOM.
*/
struct Curl_dns_entry *
-Curl_fetch_addr(struct Curl_easy *data,
- const char *hostname,
- int port);
+Curl_dnscache_mk_entry(struct Curl_easy *data,
+ struct Curl_addrinfo *addr,
+ const char *hostname,
+ size_t hostlen, /* length or zero */
+ int port,
+ bool permanent);
/*
- * Curl_cache_addr() stores a 'Curl_addrinfo' struct in the DNS cache.
- * @param permanent iff TRUE, entry will never become stale
- * Returns the Curl_dns_entry entry pointer or NULL if the storage failed.
+ * Curl_dnscache_get() fetches a 'Curl_dns_entry' already in the DNS cache.
+ *
+ * Returns the Curl_dns_entry entry pointer or NULL if not in the cache.
+ *
+ * The returned data *MUST* be "released" with Curl_resolv_unlink() after
+ * use, or we will leak memory!
*/
struct Curl_dns_entry *
-Curl_cache_addr(struct Curl_easy *data, struct Curl_addrinfo *addr,
- const char *hostname, size_t hostlen, int port,
- bool permanent);
-
-/*
- * Function provided by the resolver backend to set DNS servers to use.
- */
-CURLcode Curl_set_dns_servers(struct Curl_easy *data, char *servers);
-
-/*
- * Function provided by the resolver backend to set
- * outgoing interface to use for DNS requests
- */
-CURLcode Curl_set_dns_interface(struct Curl_easy *data,
- const char *interf);
-
-/*
- * Function provided by the resolver backend to set
- * local IPv4 address to use as source address for DNS requests
- */
-CURLcode Curl_set_dns_local_ip4(struct Curl_easy *data,
- const char *local_ip4);
+Curl_dnscache_get(struct Curl_easy *data,
+ const char *hostname,
+ int port, int ip_version);
/*
- * Function provided by the resolver backend to set
- * local IPv6 address to use as source address for DNS requests
+ * Curl_dnscache_addr() adds `entry` to the cache, increasing its
+ * reference count on success.
*/
-CURLcode Curl_set_dns_local_ip6(struct Curl_easy *data,
- const char *local_ip6);
-
-/*
- * Clean off entries from the cache
- */
-void Curl_hostcache_clean(struct Curl_easy *data, struct Curl_hash *hash);
+CURLcode Curl_dnscache_add(struct Curl_easy *data,
+ struct Curl_dns_entry *entry);
/*
* Populate the cache with specified entries from CURLOPT_RESOLVE.
*/
CURLcode Curl_loadhostpairs(struct Curl_easy *data);
+
+#ifdef USE_CURL_ASYNC
CURLcode Curl_resolv_check(struct Curl_easy *data,
struct Curl_dns_entry **dns);
+#else
+#define Curl_resolv_check(x,y) CURLE_NOT_BUILT_IN
+#endif
int Curl_resolv_getsock(struct Curl_easy *data,
curl_socket_t *socks);
CURLcode Curl_resolver_error(struct Curl_easy *data);
+
+#ifdef CURLRES_SYNCH
+/*
+ * Curl_sync_getaddrinfo() is the non-async low-level name resolve API.
+ * There are several versions of this function - depending on IPV6
+ * support and platform.
+ */
+struct Curl_addrinfo *Curl_sync_getaddrinfo(struct Curl_easy *data,
+ const char *hostname,
+ int port,
+ int ip_version);
+
+#endif
+
#endif /* HEADER_CURL_HOSTIP_H */
diff --git a/libs/libcurl/src/hostip4.c b/libs/libcurl/src/hostip4.c
index 80ee26f452..bdce12f5d5 100644
--- a/libs/libcurl/src/hostip4.c
+++ b/libs/libcurl/src/hostip4.c
@@ -54,24 +54,11 @@
#include "curl_memory.h"
#include "memdebug.h"
-/*
- * Curl_ipvalid() checks what CURL_IPRESOLVE_* requirements that might've
- * been set and returns TRUE if they are OK.
- */
-bool Curl_ipvalid(struct Curl_easy *data, struct connectdata *conn)
-{
- (void)data;
- if(conn->ip_version == CURL_IPRESOLVE_V6)
- /* An IPv6 address was requested and we cannot get/use one */
- return FALSE;
-
- return TRUE; /* OK, proceed */
-}
#ifdef CURLRES_SYNCH
/*
- * Curl_getaddrinfo() - the IPv4 synchronous version.
+ * Curl_sync_getaddrinfo() - the IPv4 synchronous version.
*
* The original code to this function was from the Dancer source code, written
* by Bjorn Reese, it has since been patched and modified considerably.
@@ -86,19 +73,18 @@ bool Curl_ipvalid(struct Curl_easy *data, struct connectdata *conn)
* flavours have thread-safe versions of the plain gethostbyname() etc.
*
*/
-struct Curl_addrinfo *Curl_getaddrinfo(struct Curl_easy *data,
- const char *hostname,
- int port,
- int *waitp)
+struct Curl_addrinfo *Curl_sync_getaddrinfo(struct Curl_easy *data,
+ const char *hostname,
+ int port,
+ int ip_version)
{
struct Curl_addrinfo *ai = NULL;
+ (void)ip_version;
#ifdef CURL_DISABLE_VERBOSE_STRINGS
(void)data;
#endif
- *waitp = 0; /* synchronous response only */
-
ai = Curl_ipv4_resolve_r(hostname, port);
if(!ai)
infof(data, "Curl_ipv4_resolve_r failed for %s", hostname);
diff --git a/libs/libcurl/src/hostip6.c b/libs/libcurl/src/hostip6.c
index e0c9af56d2..4a61ead046 100644
--- a/libs/libcurl/src/hostip6.c
+++ b/libs/libcurl/src/hostip6.c
@@ -49,25 +49,13 @@
#include "hash.h"
#include "share.h"
#include "url.h"
-#include "inet_pton.h"
+#include "curlx/inet_pton.h"
#include "connect.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h"
#include "memdebug.h"
-/*
- * Curl_ipvalid() checks what CURL_IPRESOLVE_* requirements that might've
- * been set and returns TRUE if they are OK.
- */
-bool Curl_ipvalid(struct Curl_easy *data, struct connectdata *conn)
-{
- if(conn->ip_version == CURL_IPRESOLVE_V6)
- return Curl_ipv6works(data);
-
- return TRUE;
-}
-
#if defined(CURLRES_SYNCH)
#ifdef DEBUG_ADDRINFO
@@ -87,7 +75,7 @@ static void dump_addrinfo(const struct Curl_addrinfo *ai)
#endif
/*
- * Curl_getaddrinfo() when built IPv6-enabled (non-threading and
+ * Curl_sync_getaddrinfo() when built IPv6-enabled (non-threading and
* non-ares version).
*
* Returns name information about the given hostname and port number. If
@@ -95,10 +83,10 @@ static void dump_addrinfo(const struct Curl_addrinfo *ai)
* to memory we need to free after use. That memory *MUST* be freed with
* Curl_freeaddrinfo(), nothing else.
*/
-struct Curl_addrinfo *Curl_getaddrinfo(struct Curl_easy *data,
- const char *hostname,
- int port,
- int *waitp)
+struct Curl_addrinfo *Curl_sync_getaddrinfo(struct Curl_easy *data,
+ const char *hostname,
+ int port,
+ int ip_version)
{
struct addrinfo hints;
struct Curl_addrinfo *res;
@@ -110,9 +98,7 @@ struct Curl_addrinfo *Curl_getaddrinfo(struct Curl_easy *data,
#endif
int pf = PF_INET;
- *waitp = 0; /* synchronous response only */
-
- if((data->conn->ip_version != CURL_IPRESOLVE_V4) && Curl_ipv6works(data))
+ if((ip_version != CURL_IPRESOLVE_V4) && Curl_ipv6works(data))
/* The stack seems to be IPv6-enabled */
pf = PF_UNSPEC;
diff --git a/libs/libcurl/src/hostsyn.c b/libs/libcurl/src/hostsyn.c
deleted file mode 100644
index 6cbe679a23..0000000000
--- a/libs/libcurl/src/hostsyn.c
+++ /dev/null
@@ -1,104 +0,0 @@
-/***************************************************************************
- * _ _ ____ _
- * 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"
-
-/***********************************************************************
- * Only for builds using synchronous name resolves
- **********************************************************************/
-#ifdef CURLRES_SYNCH
-
-#ifdef HAVE_NETINET_IN_H
-#include <netinet/in.h>
-#endif
-#ifdef HAVE_NETDB_H
-#include <netdb.h>
-#endif
-#ifdef HAVE_ARPA_INET_H
-#include <arpa/inet.h>
-#endif
-#ifdef __VMS
-#include <in.h>
-#include <inet.h>
-#endif
-
-#include "urldata.h"
-#include "sendf.h"
-#include "hostip.h"
-#include "hash.h"
-#include "share.h"
-#include "url.h"
-#include "curl_memory.h"
-/* The last #include file should be: */
-#include "memdebug.h"
-
-/*
- * Function provided by the resolver backend to set DNS servers to use.
- */
-CURLcode Curl_set_dns_servers(struct Curl_easy *data,
- char *servers)
-{
- (void)data;
- (void)servers;
- return CURLE_NOT_BUILT_IN;
-
-}
-
-/*
- * Function provided by the resolver backend to set
- * outgoing interface to use for DNS requests
- */
-CURLcode Curl_set_dns_interface(struct Curl_easy *data,
- const char *interf)
-{
- (void)data;
- (void)interf;
- return CURLE_NOT_BUILT_IN;
-}
-
-/*
- * Function provided by the resolver backend to set
- * local IPv4 address to use as source address for DNS requests
- */
-CURLcode Curl_set_dns_local_ip4(struct Curl_easy *data,
- const char *local_ip4)
-{
- (void)data;
- (void)local_ip4;
- return CURLE_NOT_BUILT_IN;
-}
-
-/*
- * Function provided by the resolver backend to set
- * local IPv6 address to use as source address for DNS requests
- */
-CURLcode Curl_set_dns_local_ip6(struct Curl_easy *data,
- const char *local_ip6)
-{
- (void)data;
- (void)local_ip6;
- return CURLE_NOT_BUILT_IN;
-}
-
-#endif /* truly sync */
diff --git a/libs/libcurl/src/hsts.c b/libs/libcurl/src/hsts.c
index f6363ae29d..5aea001792 100644
--- a/libs/libcurl/src/hsts.c
+++ b/libs/libcurl/src/hsts.c
@@ -40,7 +40,7 @@
#include "rename.h"
#include "share.h"
#include "strdup.h"
-#include "strparse.h"
+#include "curlx/strparse.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
@@ -62,7 +62,7 @@ static time_t hsts_debugtime(void *unused)
(void)unused;
if(timestr) {
curl_off_t val;
- if(!Curl_str_number(&timestr, &val, TIME_T_MAX))
+ if(!curlx_str_number(&timestr, &val, TIME_T_MAX))
val += (curl_off_t)deltatime;
return (time_t)val;
}
@@ -154,7 +154,7 @@ CURLcode Curl_hsts_parse(struct hsts *h, const char *hostname,
return CURLE_OK;
do {
- Curl_str_passblanks(&p);
+ curlx_str_passblanks(&p);
if(strncasecompare("max-age", p, 7)) {
bool quoted = FALSE;
int rc;
@@ -163,15 +163,15 @@ CURLcode Curl_hsts_parse(struct hsts *h, const char *hostname,
return CURLE_BAD_FUNCTION_ARGUMENT;
p += 7;
- Curl_str_passblanks(&p);
- if(Curl_str_single(&p, '='))
+ curlx_str_passblanks(&p);
+ if(curlx_str_single(&p, '='))
return CURLE_BAD_FUNCTION_ARGUMENT;
- Curl_str_passblanks(&p);
+ curlx_str_passblanks(&p);
- if(!Curl_str_single(&p, '\"'))
+ if(!curlx_str_single(&p, '\"'))
quoted = TRUE;
- rc = Curl_str_number(&p, &expires, TIME_T_MAX);
+ rc = curlx_str_number(&p, &expires, TIME_T_MAX);
if(rc == STRE_OVERFLOW)
expires = CURL_OFF_T_MAX;
else if(rc)
@@ -198,7 +198,7 @@ CURLcode Curl_hsts_parse(struct hsts *h, const char *hostname,
p++;
}
- Curl_str_passblanks(&p);
+ curlx_str_passblanks(&p);
if(*p == ';')
p++;
} while(*p);
@@ -417,10 +417,10 @@ static CURLcode hsts_add(struct hsts *h, const char *line)
struct Curl_str host;
struct Curl_str date;
- if(Curl_str_word(&line, &host, MAX_HSTS_HOSTLEN) ||
- Curl_str_singlespace(&line) ||
- Curl_str_quotedword(&line, &date, MAX_HSTS_DATELEN) ||
- Curl_str_newline(&line))
+ if(curlx_str_word(&line, &host, MAX_HSTS_HOSTLEN) ||
+ curlx_str_singlespace(&line) ||
+ curlx_str_quotedword(&line, &date, MAX_HSTS_DATELEN) ||
+ curlx_str_newline(&line))
;
else {
CURLcode result = CURLE_OK;
@@ -428,26 +428,26 @@ static CURLcode hsts_add(struct hsts *h, const char *line)
struct stsentry *e;
char dbuf[MAX_HSTS_DATELEN + 1];
time_t expires;
- const char *hp = Curl_str(&host);
+ const char *hp = curlx_str(&host);
/* The date parser works on a null terminated string. The maximum length
- is upheld by Curl_str_quotedword(). */
- memcpy(dbuf, Curl_str(&date), Curl_strlen(&date));
- dbuf[Curl_strlen(&date)] = 0;
+ is upheld by curlx_str_quotedword(). */
+ memcpy(dbuf, curlx_str(&date), curlx_strlen(&date));
+ dbuf[curlx_strlen(&date)] = 0;
expires = strcmp(dbuf, UNLIMITED) ? Curl_getdate_capped(dbuf) :
TIME_T_MAX;
if(hp[0] == '.') {
- Curl_str_nudge(&host, 1);
+ curlx_str_nudge(&host, 1);
subdomain = TRUE;
}
/* only add it if not already present */
- e = Curl_hsts(h, Curl_str(&host), Curl_strlen(&host), subdomain);
+ e = Curl_hsts(h, curlx_str(&host), curlx_strlen(&host), subdomain);
if(!e)
- result = hsts_create(h, Curl_str(&host), Curl_strlen(&host),
+ result = hsts_create(h, curlx_str(&host), curlx_strlen(&host),
subdomain, expires);
- else if(Curl_str_casecompare(&host, e->host)) {
+ else if(curlx_str_casecompare(&host, e->host)) {
/* the same hostname, use the largest expire time */
if(expires > e->expires)
e->expires = expires;
@@ -526,10 +526,10 @@ static CURLcode hsts_load(struct hsts *h, const char *file)
fp = fopen(file, FOPEN_READTEXT);
if(fp) {
struct dynbuf buf;
- Curl_dyn_init(&buf, MAX_HSTS_LINE);
+ curlx_dyn_init(&buf, MAX_HSTS_LINE);
while(Curl_get_line(&buf, fp)) {
- const char *lineptr = Curl_dyn_ptr(&buf);
- Curl_str_passblanks(&lineptr);
+ const char *lineptr = curlx_dyn_ptr(&buf);
+ curlx_str_passblanks(&lineptr);
/*
* Skip empty or commented lines, since we know the line will have a
@@ -540,7 +540,7 @@ static CURLcode hsts_load(struct hsts *h, const char *file)
hsts_add(h, lineptr);
}
- Curl_dyn_free(&buf); /* free the line buffer */
+ curlx_dyn_free(&buf); /* free the line buffer */
fclose(fp);
}
return result;
diff --git a/libs/libcurl/src/hsts.h b/libs/libcurl/src/hsts.h
index 486923c5fb..5eaa81e112 100644
--- a/libs/libcurl/src/hsts.h
+++ b/libs/libcurl/src/hsts.h
@@ -36,8 +36,8 @@ extern time_t deltatime;
struct stsentry {
struct Curl_llist_node node;
const char *host;
- bool includeSubDomains;
curl_off_t expires; /* the timestamp of this entry's expiry */
+ BIT(includeSubDomains);
};
/* The HSTS cache. Needs to be able to tailmatch hostnames. */
diff --git a/libs/libcurl/src/http.c b/libs/libcurl/src/http.c
index 68e1812cfd..69147a4699 100644
--- a/libs/libcurl/src/http.c
+++ b/libs/libcurl/src/http.c
@@ -54,7 +54,7 @@
#include "formdata.h"
#include "mime.h"
#include "progress.h"
-#include "curl_base64.h"
+#include "curlx/base64.h"
#include "cookie.h"
#include "vauth/vauth.h"
#include "vtls/vtls.h"
@@ -76,7 +76,7 @@
#include "strcase.h"
#include "content_encoding.h"
#include "http_proxy.h"
-#include "warnless.h"
+#include "curlx/warnless.h"
#include "http2.h"
#include "cfilters.h"
#include "connect.h"
@@ -85,7 +85,7 @@
#include "hsts.h"
#include "ws.h"
#include "curl_ctype.h"
-#include "strparse.h"
+#include "curlx/strparse.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
@@ -116,7 +116,7 @@ static CURLcode http_req_set_reader(struct Curl_easy *data,
const char **tep);
static CURLcode http_size(struct Curl_easy *data);
static CURLcode http_statusline(struct Curl_easy *data,
- struct connectdata *conn);
+ struct connectdata *conn);
static CURLcode http_target(struct Curl_easy *data, struct connectdata *conn,
struct dynbuf *req);
static CURLcode http_useragent(struct Curl_easy *data);
@@ -285,12 +285,12 @@ char *Curl_copy_header_value(const char *header)
struct Curl_str out;
/* find the end of the header name */
- if(!Curl_str_cspn(&header, &out, ";:") &&
- (!Curl_str_single(&header, ':') || !Curl_str_single(&header, ';'))) {
- Curl_str_untilnl(&header, &out, MAX_HTTP_RESP_HEADER_SIZE);
- Curl_str_trimblanks(&out);
+ if(!curlx_str_cspn(&header, &out, ";:") &&
+ (!curlx_str_single(&header, ':') || !curlx_str_single(&header, ';'))) {
+ curlx_str_untilnl(&header, &out, MAX_HTTP_RESP_HEADER_SIZE);
+ curlx_str_trimblanks(&out);
- return Curl_memdup0(Curl_str(&out), Curl_strlen(&out));
+ return Curl_memdup0(curlx_str(&out), curlx_strlen(&out));
}
/* bad input */
return NULL;
@@ -336,7 +336,7 @@ static CURLcode http_output_basic(struct Curl_easy *data, bool proxy)
if(!out)
return CURLE_OUT_OF_MEMORY;
- result = Curl_base64_encode(out, strlen(out), &authorization, &size);
+ result = curlx_base64_encode(out, strlen(out), &authorization, &size);
if(result)
goto fail;
@@ -768,12 +768,12 @@ Curl_http_output_auth(struct Curl_easy *data,
#ifndef CURL_DISABLE_PROXY
(conn->bits.httpproxy && conn->bits.proxy_user_passwd) ||
#endif
- data->state.aptr.user ||
+ data->state.aptr.user ||
#ifdef USE_SPNEGO
- authhost->want & CURLAUTH_NEGOTIATE ||
- authproxy->want & CURLAUTH_NEGOTIATE ||
+ authhost->want & CURLAUTH_NEGOTIATE ||
+ authproxy->want & CURLAUTH_NEGOTIATE ||
#endif
- data->set.str[STRING_BEARER])
+ data->set.str[STRING_BEARER])
/* continue please */;
else {
authhost->done = TRUE;
@@ -1073,14 +1073,14 @@ CURLcode Curl_http_input_auth(struct Curl_easy *data, bool proxy,
auth++;
else
break;
- Curl_str_passblanks(&auth);
+ curlx_str_passblanks(&auth);
}
+ return result;
#else
(void) proxy;
/* nothing to do when disabled */
+ return CURLE_OK;
#endif
-
- return result;
}
/**
@@ -1474,15 +1474,15 @@ Curl_compareheader(const char *headerline, /* line to check */
/* pass the header */
p = &headerline[hlen];
- if(Curl_str_untilnl(&p, &val, MAX_HTTP_RESP_HEADER_SIZE))
+ if(curlx_str_untilnl(&p, &val, MAX_HTTP_RESP_HEADER_SIZE))
return FALSE;
- Curl_str_trimblanks(&val);
+ curlx_str_trimblanks(&val);
/* find the content string in the rest of the line */
- if(Curl_strlen(&val) >= clen) {
+ if(curlx_strlen(&val) >= clen) {
size_t len;
- p = Curl_str(&val);
- for(len = Curl_strlen(&val); len >= Curl_strlen(&val); len--, p++) {
+ p = curlx_str(&val);
+ for(len = curlx_strlen(&val); len >= curlx_strlen(&val); len--, p++) {
if(strncasecompare(p, content, clen))
return TRUE; /* match! */
}
@@ -1533,7 +1533,7 @@ CURLcode Curl_http_done(struct Curl_easy *data,
data->state.authhost.multipass = FALSE;
data->state.authproxy.multipass = FALSE;
- Curl_dyn_reset(&data->state.headerb);
+ curlx_dyn_reset(&data->state.headerb);
if(status)
return status;
@@ -1654,19 +1654,19 @@ CURLcode Curl_add_custom_headers(struct Curl_easy *data,
/* explicitly asked to send header without content is done by a header
that ends with a semicolon, but there must be no colon present in the
name */
- if(!Curl_str_until(&p, &name, MAX_HTTP_RESP_HEADER_SIZE, ';') &&
- !Curl_str_single(&p, ';') &&
- !Curl_str_single(&p, '\0') &&
- !memchr(Curl_str(&name), ':', Curl_strlen(&name)))
+ if(!curlx_str_until(&p, &name, MAX_HTTP_RESP_HEADER_SIZE, ';') &&
+ !curlx_str_single(&p, ';') &&
+ !curlx_str_single(&p, '\0') &&
+ !memchr(curlx_str(&name), ':', curlx_strlen(&name)))
blankheader = TRUE;
else {
p = origp;
- if(!Curl_str_until(&p, &name, MAX_HTTP_RESP_HEADER_SIZE, ':') &&
- !Curl_str_single(&p, ':')) {
+ if(!curlx_str_until(&p, &name, MAX_HTTP_RESP_HEADER_SIZE, ':') &&
+ !curlx_str_single(&p, ':')) {
struct Curl_str val;
- Curl_str_untilnl(&p, &val, MAX_HTTP_RESP_HEADER_SIZE);
- Curl_str_trimblanks(&val);
- if(!Curl_strlen(&val))
+ curlx_str_untilnl(&p, &val, MAX_HTTP_RESP_HEADER_SIZE);
+ curlx_str_trimblanks(&val);
+ if(!curlx_strlen(&val))
/* no content, don't send this */
continue;
}
@@ -1681,41 +1681,41 @@ CURLcode Curl_add_custom_headers(struct Curl_easy *data,
/* a Host: header was sent already, do not pass on any custom
Host: header as that will produce *two* in the same
request! */
- Curl_str_casecompare(&name, "Host"))
+ curlx_str_casecompare(&name, "Host"))
;
else if(data->state.httpreq == HTTPREQ_POST_FORM &&
/* this header (extended by formdata.c) is sent later */
- Curl_str_casecompare(&name, "Content-Type"))
+ curlx_str_casecompare(&name, "Content-Type"))
;
else if(data->state.httpreq == HTTPREQ_POST_MIME &&
/* this header is sent later */
- Curl_str_casecompare(&name, "Content-Type"))
+ curlx_str_casecompare(&name, "Content-Type"))
;
else if(data->req.authneg &&
/* while doing auth neg, do not allow the custom length since
we will force length zero then */
- Curl_str_casecompare(&name, "Content-Length"))
+ curlx_str_casecompare(&name, "Content-Length"))
;
else if(data->state.aptr.te &&
/* when asking for Transfer-Encoding, do not pass on a custom
Connection: */
- Curl_str_casecompare(&name, "Connection"))
+ curlx_str_casecompare(&name, "Connection"))
;
else if((httpversion >= 20) &&
- Curl_str_casecompare(&name, "Transfer-Encoding"))
+ curlx_str_casecompare(&name, "Transfer-Encoding"))
/* HTTP/2 does not support chunked requests */
;
- else if((Curl_str_casecompare(&name, "Authorization") ||
- Curl_str_casecompare(&name, "Cookie")) &&
+ else if((curlx_str_casecompare(&name, "Authorization") ||
+ curlx_str_casecompare(&name, "Cookie")) &&
/* be careful of sending this potentially sensitive header to
other hosts */
!Curl_auth_allowed_to_host(data))
;
else if(blankheader)
- result = Curl_dyn_addf(req, "%.*s:\r\n", (int)Curl_strlen(&name),
- Curl_str(&name));
+ result = curlx_dyn_addf(req, "%.*s:\r\n", (int)curlx_strlen(&name),
+ curlx_str(&name));
else
- result = Curl_dyn_addf(req, "%s\r\n", origp);
+ result = curlx_dyn_addf(req, "%s\r\n", origp);
if(result)
return result;
@@ -1790,7 +1790,7 @@ CURLcode Curl_add_timecondition(struct Curl_easy *data,
tm->tm_min,
tm->tm_sec);
- result = Curl_dyn_add(req, datestr);
+ result = curlx_dyn_add(req, datestr);
return result;
}
#else
@@ -2014,7 +2014,7 @@ static CURLcode http_target(struct Curl_easy *data,
curl_url_cleanup(h);
/* target or URL */
- result = Curl_dyn_add(r, data->set.str[STRING_TARGET] ?
+ result = curlx_dyn_add(r, data->set.str[STRING_TARGET] ?
data->set.str[STRING_TARGET] : url);
free(url);
if(result)
@@ -2035,8 +2035,8 @@ static CURLcode http_target(struct Curl_easy *data,
}
}
if(!type) {
- result = Curl_dyn_addf(r, ";type=%c",
- data->state.prefer_ascii ? 'a' : 'i');
+ result = curlx_dyn_addf(r, ";type=%c",
+ data->state.prefer_ascii ? 'a' : 'i');
if(result)
return result;
}
@@ -2049,11 +2049,11 @@ static CURLcode http_target(struct Curl_easy *data,
(void)conn; /* not used in disabled-proxy builds */
#endif
{
- result = Curl_dyn_add(r, path);
+ result = curlx_dyn_add(r, path);
if(result)
return result;
if(query)
- result = Curl_dyn_addf(r, "?%s", query);
+ result = curlx_dyn_addf(r, "?%s", query);
}
return result;
@@ -2311,7 +2311,7 @@ static CURLcode addexpect(struct Curl_easy *data, struct dynbuf *r,
operations (as there is one packet coming back from the web server) */
curl_off_t client_len = Curl_creader_client_length(data);
if(client_len > EXPECT_100_THRESHOLD || client_len < 0) {
- result = Curl_dyn_addn(r, STRCONST("Expect: 100-continue\r\n"));
+ result = curlx_dyn_addn(r, STRCONST("Expect: 100-continue\r\n"));
if(result)
return result;
*announced_exp100 = TRUE;
@@ -2355,8 +2355,8 @@ static CURLcode http_req_complete(struct Curl_easy *data,
!Curl_checkheaders(data, STRCONST("Content-Length")))) {
/* we allow replacing this header if not during auth negotiation,
although it is not very wise to actually set your own */
- result = Curl_dyn_addf(r, "Content-Length: %" FMT_OFF_T "\r\n",
- req_clen);
+ result = curlx_dyn_addf(r, "Content-Length: %" FMT_OFF_T "\r\n",
+ req_clen);
}
if(result)
goto out;
@@ -2368,7 +2368,7 @@ static CURLcode http_req_complete(struct Curl_easy *data,
struct curl_slist *hdr;
for(hdr = data->state.mimepost->curlheaders; hdr; hdr = hdr->next) {
- result = Curl_dyn_addf(r, "%s\r\n", hdr->data);
+ result = curlx_dyn_addf(r, "%s\r\n", hdr->data);
if(result)
goto out;
}
@@ -2376,8 +2376,8 @@ static CURLcode http_req_complete(struct Curl_easy *data,
#endif
if(httpreq == HTTPREQ_POST) {
if(!Curl_checkheaders(data, STRCONST("Content-Type"))) {
- result = Curl_dyn_addn(r, STRCONST("Content-Type: application/"
- "x-www-form-urlencoded\r\n"));
+ result = curlx_dyn_addn(r, STRCONST("Content-Type: application/"
+ "x-www-form-urlencoded\r\n"));
if(result)
goto out;
}
@@ -2391,7 +2391,7 @@ static CURLcode http_req_complete(struct Curl_easy *data,
}
/* end of headers */
- result = Curl_dyn_addn(r, STRCONST("\r\n"));
+ result = curlx_dyn_addn(r, STRCONST("\r\n"));
if(!result) {
Curl_pgrsSetUploadSize(data, req_clen);
if(announced_exp100)
@@ -2447,7 +2447,7 @@ static CURLcode http_cookies(struct Curl_easy *data,
if(co->value) {
size_t add;
if(!count) {
- result = Curl_dyn_addn(r, STRCONST("Cookie: "));
+ result = curlx_dyn_addn(r, STRCONST("Cookie: "));
if(result)
break;
}
@@ -2458,8 +2458,8 @@ static CURLcode http_cookies(struct Curl_easy *data,
linecap = TRUE;
break;
}
- result = Curl_dyn_addf(r, "%s%s=%s", count ? "; " : "",
- co->name, co->value);
+ result = curlx_dyn_addf(r, "%s%s=%s", count ? "; " : "",
+ co->name, co->value);
if(result)
break;
clen += add + (count ? 2 : 0);
@@ -2470,14 +2470,14 @@ static CURLcode http_cookies(struct Curl_easy *data,
}
if(addcookies && !result && !linecap) {
if(!count)
- result = Curl_dyn_addn(r, STRCONST("Cookie: "));
+ result = curlx_dyn_addn(r, STRCONST("Cookie: "));
if(!result) {
- result = Curl_dyn_addf(r, "%s%s", count ? "; " : "", addcookies);
+ result = curlx_dyn_addf(r, "%s%s", count ? "; " : "", addcookies);
count++;
}
}
if(count && !result)
- result = Curl_dyn_addn(r, STRCONST("\r\n"));
+ result = curlx_dyn_addn(r, STRCONST("\r\n"));
if(result)
return result;
@@ -2766,19 +2766,19 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
goto fail;
/* initialize a dynamic send-buffer */
- Curl_dyn_init(&req, DYN_HTTP_REQUEST);
+ curlx_dyn_init(&req, DYN_HTTP_REQUEST);
/* make sure the header buffer is reset - if there are leftovers from a
previous transfer */
- Curl_dyn_reset(&data->state.headerb);
+ curlx_dyn_reset(&data->state.headerb);
/* add the main request stuff */
/* GET/HEAD/POST/PUT */
- result = Curl_dyn_addf(&req, "%s ", request);
+ result = curlx_dyn_addf(&req, "%s ", request);
if(!result)
result = http_target(data, conn, &req);
if(result) {
- Curl_dyn_free(&req);
+ curlx_dyn_free(&req);
goto fail;
}
@@ -2787,62 +2787,62 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
altused = aprintf("Alt-Used: %s:%d\r\n",
conn->conn_to_host.name, conn->conn_to_port);
if(!altused) {
- Curl_dyn_free(&req);
+ curlx_dyn_free(&req);
return CURLE_OUT_OF_MEMORY;
}
}
#endif
result =
- Curl_dyn_addf(&req,
- " HTTP/%s\r\n" /* HTTP version */
- "%s" /* host */
- "%s" /* proxyuserpwd */
- "%s" /* userpwd */
- "%s" /* range */
- "%s" /* user agent */
- "%s" /* accept */
- "%s" /* TE: */
- "%s" /* accept-encoding */
- "%s" /* referer */
- "%s" /* Proxy-Connection */
- "%s" /* transfer-encoding */
- "%s",/* Alt-Used */
-
- httpstring,
- (data->state.aptr.host ? data->state.aptr.host : ""),
+ curlx_dyn_addf(&req,
+ " HTTP/%s\r\n" /* HTTP version */
+ "%s" /* host */
+ "%s" /* proxyuserpwd */
+ "%s" /* userpwd */
+ "%s" /* range */
+ "%s" /* user agent */
+ "%s" /* accept */
+ "%s" /* TE: */
+ "%s" /* accept-encoding */
+ "%s" /* referer */
+ "%s" /* Proxy-Connection */
+ "%s" /* transfer-encoding */
+ "%s",/* Alt-Used */
+
+ httpstring,
+ (data->state.aptr.host ? data->state.aptr.host : ""),
#ifndef CURL_DISABLE_PROXY
- data->state.aptr.proxyuserpwd ?
- data->state.aptr.proxyuserpwd : "",
+ data->state.aptr.proxyuserpwd ?
+ data->state.aptr.proxyuserpwd : "",
#else
- "",
+ "",
#endif
- data->state.aptr.userpwd ? data->state.aptr.userpwd : "",
- (data->state.use_range && data->state.aptr.rangeline) ?
- data->state.aptr.rangeline : "",
- (data->set.str[STRING_USERAGENT] &&
- *data->set.str[STRING_USERAGENT] &&
- data->state.aptr.uagent) ?
- data->state.aptr.uagent : "",
- p_accept ? p_accept : "",
- data->state.aptr.te ? data->state.aptr.te : "",
- (data->set.str[STRING_ENCODING] &&
- *data->set.str[STRING_ENCODING] &&
- data->state.aptr.accept_encoding) ?
- data->state.aptr.accept_encoding : "",
- (data->state.referer && data->state.aptr.ref) ?
- data->state.aptr.ref : "" /* Referer: <data> */,
+ data->state.aptr.userpwd ? data->state.aptr.userpwd : "",
+ (data->state.use_range && data->state.aptr.rangeline) ?
+ data->state.aptr.rangeline : "",
+ (data->set.str[STRING_USERAGENT] &&
+ *data->set.str[STRING_USERAGENT] &&
+ data->state.aptr.uagent) ?
+ data->state.aptr.uagent : "",
+ p_accept ? p_accept : "",
+ data->state.aptr.te ? data->state.aptr.te : "",
+ (data->set.str[STRING_ENCODING] &&
+ *data->set.str[STRING_ENCODING] &&
+ data->state.aptr.accept_encoding) ?
+ data->state.aptr.accept_encoding : "",
+ (data->state.referer && data->state.aptr.ref) ?
+ data->state.aptr.ref : "" /* Referer: <data> */,
#ifndef CURL_DISABLE_PROXY
- (conn->bits.httpproxy &&
- !conn->bits.tunnel_proxy &&
- !Curl_checkheaders(data, STRCONST("Proxy-Connection")) &&
- !Curl_checkProxyheaders(data, conn,
- STRCONST("Proxy-Connection"))) ?
- "Proxy-Connection: Keep-Alive\r\n":"",
+ (conn->bits.httpproxy &&
+ !conn->bits.tunnel_proxy &&
+ !Curl_checkheaders(data, STRCONST("Proxy-Connection")) &&
+ !Curl_checkProxyheaders(data, conn,
+ STRCONST("Proxy-Connection"))) ?
+ "Proxy-Connection: Keep-Alive\r\n":"",
#else
- "",
+ "",
#endif
- te,
- altused ? altused : ""
+ te,
+ altused ? altused : ""
);
/* clear userpwd and proxyuserpwd to avoid reusing old credentials
@@ -2854,7 +2854,7 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
free(altused);
if(result) {
- Curl_dyn_free(&req);
+ curlx_dyn_free(&req);
goto fail;
}
@@ -2865,7 +2865,7 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
over SSL */
result = Curl_http2_request_upgrade(&req, data);
if(result) {
- Curl_dyn_free(&req);
+ curlx_dyn_free(&req);
return result;
}
}
@@ -2886,7 +2886,7 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
if(!result)
result = Curl_req_send(data, &req, httpversion);
}
- Curl_dyn_free(&req);
+ curlx_dyn_free(&req);
if(result)
goto fail;
@@ -3026,7 +3026,7 @@ static CURLcode http_header(struct Curl_easy *data,
HD_VAL(hd, hdlen, "Content-Length:") : NULL;
if(v) {
curl_off_t contentlength;
- int offt = Curl_str_numblanks(&v, &contentlength);
+ int offt = curlx_str_numblanks(&v, &contentlength);
if(offt == STRE_OK) {
k->size = contentlength;
@@ -3118,7 +3118,7 @@ static CURLcode http_header(struct Curl_easy *data,
/* if it truly stopped on a digit */
if(ISDIGIT(*ptr)) {
- if(!Curl_str_number(&ptr, &k->offset, CURL_OFF_T_MAX) &&
+ if(!curlx_str_number(&ptr, &k->offset, CURL_OFF_T_MAX) &&
(data->state.resume_from == k->offset))
/* we asked for a resume and we got it */
k->content_range = TRUE;
@@ -3229,7 +3229,7 @@ static CURLcode http_header(struct Curl_easy *data,
/* Retry-After = HTTP-date / delay-seconds */
curl_off_t retry_after = 0; /* zero for unknown or "now" */
time_t date;
- Curl_str_passblanks(&v);
+ curlx_str_passblanks(&v);
/* try it as a date first, because a date can otherwise start with and
get treated as a number */
@@ -3243,7 +3243,7 @@ static CURLcode http_header(struct Curl_easy *data,
}
else
/* Try it as a decimal number */
- Curl_str_number(&v, &retry_after, CURL_OFF_T_MAX);
+ curlx_str_number(&v, &retry_after, CURL_OFF_T_MAX);
/* limit to 6 hours max. this is not documented so that it can be changed
in the future if necessary. */
if(retry_after > 21600)
@@ -3858,8 +3858,8 @@ static CURLcode http_rw_hd(struct Curl_easy *data,
struct dynbuf last_header;
size_t consumed;
- Curl_dyn_init(&last_header, hdlen + 1);
- result = Curl_dyn_addn(&last_header, hd, hdlen);
+ curlx_dyn_init(&last_header, hdlen + 1);
+ result = curlx_dyn_addn(&last_header, hd, hdlen);
if(result)
return result;
@@ -3867,12 +3867,12 @@ static CURLcode http_rw_hd(struct Curl_easy *data,
/* Caveat: we clear anything in the header brigade, because a
* response might switch HTTP version which may call use recursively.
* Not nice, but that is currently the way of things. */
- Curl_dyn_reset(&data->state.headerb);
- result = http_on_response(data, Curl_dyn_ptr(&last_header),
- Curl_dyn_len(&last_header),
+ curlx_dyn_reset(&data->state.headerb);
+ result = http_on_response(data, curlx_dyn_ptr(&last_header),
+ curlx_dyn_len(&last_header),
buf_remain, blen, &consumed);
*pconsumed += consumed;
- Curl_dyn_free(&last_header);
+ curlx_dyn_free(&last_header);
return result;
}
@@ -3897,7 +3897,7 @@ static CURLcode http_rw_hd(struct Curl_easy *data,
*/
const char *p = hd;
- Curl_str_passblanks(&p);
+ curlx_str_passblanks(&p);
if(!strncmp(p, "HTTP/", 5)) {
p += 5;
switch(*p) {
@@ -3960,11 +3960,11 @@ static CURLcode http_rw_hd(struct Curl_easy *data,
curl_off_t status;
/* we set the max string a little excessive to forgive some leading
spaces */
- if(!Curl_str_until(&p, &ver, 32, ' ') &&
- !Curl_str_single(&p, ' ') &&
- !Curl_str_number(&p, &status, 999)) {
- Curl_str_trimblanks(&ver);
- if(Curl_str_cmp(&ver, "RTSP/1.0")) {
+ if(!curlx_str_until(&p, &ver, 32, ' ') &&
+ !curlx_str_single(&p, ' ') &&
+ !curlx_str_number(&p, &status, 999)) {
+ curlx_str_trimblanks(&ver);
+ if(curlx_str_cmp(&ver, "RTSP/1.0")) {
k->httpcode = (int)status;
fine_statusline = TRUE;
k->httpversion = 11; /* RTSP acts like HTTP 1.1 */
@@ -4034,7 +4034,7 @@ static CURLcode http_parse_headers(struct Curl_easy *data,
if(!end_ptr) {
/* Not a complete header line within buffer, append the data to
the end of the headerbuff. */
- result = Curl_dyn_addn(&data->state.headerb, buf, blen);
+ result = curlx_dyn_addn(&data->state.headerb, buf, blen);
if(result)
return result;
*pconsumed += blen;
@@ -4043,8 +4043,8 @@ static CURLcode http_parse_headers(struct Curl_easy *data,
/* check if this looks like a protocol header */
statusline st =
checkprotoprefix(data, conn,
- Curl_dyn_ptr(&data->state.headerb),
- Curl_dyn_len(&data->state.headerb));
+ curlx_dyn_ptr(&data->state.headerb),
+ curlx_dyn_len(&data->state.headerb));
if(st == STATUS_BAD) {
/* this is not the beginning of a protocol first header line.
@@ -4068,7 +4068,7 @@ static CURLcode http_parse_headers(struct Curl_easy *data,
/* decrease the size of the remaining (supposed) header line */
consumed = (end_ptr - buf) + 1;
- result = Curl_dyn_addn(&data->state.headerb, buf, consumed);
+ result = curlx_dyn_addn(&data->state.headerb, buf, consumed);
if(result)
return result;
blen -= consumed;
@@ -4082,8 +4082,8 @@ static CURLcode http_parse_headers(struct Curl_easy *data,
if(!k->headerline) {
/* the first read header */
statusline st = checkprotoprefix(data, conn,
- Curl_dyn_ptr(&data->state.headerb),
- Curl_dyn_len(&data->state.headerb));
+ curlx_dyn_ptr(&data->state.headerb),
+ curlx_dyn_len(&data->state.headerb));
if(st == STATUS_BAD) {
streamclose(conn, "bad HTTP: No end-of-message indicator");
/* this is not the beginning of a protocol first header line.
@@ -4102,13 +4102,13 @@ static CURLcode http_parse_headers(struct Curl_easy *data,
}
}
- result = http_rw_hd(data, Curl_dyn_ptr(&data->state.headerb),
- Curl_dyn_len(&data->state.headerb),
+ result = http_rw_hd(data, curlx_dyn_ptr(&data->state.headerb),
+ curlx_dyn_len(&data->state.headerb),
buf, blen, &consumed);
/* We are done with this line. We reset because response
* processing might switch to HTTP/2 and that might call us
* directly again. */
- Curl_dyn_reset(&data->state.headerb);
+ curlx_dyn_reset(&data->state.headerb);
if(consumed) {
blen -= consumed;
buf += consumed;
@@ -4123,7 +4123,7 @@ static CURLcode http_parse_headers(struct Curl_easy *data,
buffer. */
out:
if(!k->header && !leftover_body) {
- Curl_dyn_free(&data->state.headerb);
+ curlx_dyn_free(&data->state.headerb);
}
return CURLE_OK;
}
@@ -4161,15 +4161,15 @@ CURLcode Curl_http_write_resp_hds(struct Curl_easy *data,
result = http_parse_headers(data, buf, blen, pconsumed);
if(!result && !data->req.header) {
- if(!data->req.no_body && Curl_dyn_len(&data->state.headerb)) {
+ if(!data->req.no_body && curlx_dyn_len(&data->state.headerb)) {
/* leftover from parsing something that turned out not
* to be a header, only happens if we allow for
* HTTP/0.9 like responses */
result = Curl_client_write(data, CLIENTWRITE_BODY,
- Curl_dyn_ptr(&data->state.headerb),
- Curl_dyn_len(&data->state.headerb));
+ curlx_dyn_ptr(&data->state.headerb),
+ curlx_dyn_len(&data->state.headerb));
}
- Curl_dyn_free(&data->state.headerb);
+ curlx_dyn_free(&data->state.headerb);
}
return result;
}
@@ -4278,7 +4278,7 @@ static CURLcode req_assign_url_authority(struct httpreq *req, CURLU *url)
CURLcode result = CURLE_URL_MALFORMAT;
user = pass = host = port = NULL;
- Curl_dyn_init(&buf, DYN_HTTP_REQUEST);
+ curlx_dyn_init(&buf, DYN_HTTP_REQUEST);
uc = curl_url_get(url, CURLUPART_HOST, &host, 0);
if(uc && uc != CURLUE_NO_HOST)
@@ -4302,27 +4302,27 @@ static CURLcode req_assign_url_authority(struct httpreq *req, CURLU *url)
}
if(user) {
- result = Curl_dyn_add(&buf, user);
+ result = curlx_dyn_add(&buf, user);
if(result)
goto out;
if(pass) {
- result = Curl_dyn_addf(&buf, ":%s", pass);
+ result = curlx_dyn_addf(&buf, ":%s", pass);
if(result)
goto out;
}
- result = Curl_dyn_add(&buf, "@");
+ result = curlx_dyn_add(&buf, "@");
if(result)
goto out;
}
- result = Curl_dyn_add(&buf, host);
+ result = curlx_dyn_add(&buf, host);
if(result)
goto out;
if(port) {
- result = Curl_dyn_addf(&buf, ":%s", port);
+ result = curlx_dyn_addf(&buf, ":%s", port);
if(result)
goto out;
}
- req->authority = strdup(Curl_dyn_ptr(&buf));
+ req->authority = strdup(curlx_dyn_ptr(&buf));
if(!req->authority)
goto out;
result = CURLE_OK;
@@ -4332,7 +4332,7 @@ out:
free(pass);
free(host);
free(port);
- Curl_dyn_free(&buf);
+ curlx_dyn_free(&buf);
return result;
}
@@ -4344,7 +4344,7 @@ static CURLcode req_assign_url_path(struct httpreq *req, CURLU *url)
CURLcode result = CURLE_URL_MALFORMAT;
path = query = NULL;
- Curl_dyn_init(&buf, DYN_HTTP_REQUEST);
+ curlx_dyn_init(&buf, DYN_HTTP_REQUEST);
uc = curl_url_get(url, CURLUPART_PATH, &path, CURLU_PATH_AS_IS);
if(uc)
@@ -4362,16 +4362,16 @@ static CURLcode req_assign_url_path(struct httpreq *req, CURLU *url)
}
else {
if(path) {
- result = Curl_dyn_add(&buf, path);
+ result = curlx_dyn_add(&buf, path);
if(result)
goto out;
}
if(query) {
- result = Curl_dyn_addf(&buf, "?%s", query);
+ result = curlx_dyn_addf(&buf, "?%s", query);
if(result)
goto out;
}
- req->path = strdup(Curl_dyn_ptr(&buf));
+ req->path = strdup(curlx_dyn_ptr(&buf));
if(!req->path)
goto out;
}
@@ -4380,7 +4380,7 @@ static CURLcode req_assign_url_path(struct httpreq *req, CURLU *url)
out:
free(path);
free(query);
- Curl_dyn_free(&buf);
+ curlx_dyn_free(&buf);
return result;
}
@@ -4445,7 +4445,6 @@ struct name_const {
/* keep them sorted by length! */
static struct name_const H2_NON_FIELD[] = {
- { STRCONST("TE") },
{ STRCONST("Host") },
{ STRCONST("Upgrade") },
{ STRCONST("Connection") },
@@ -4454,15 +4453,44 @@ static struct name_const H2_NON_FIELD[] = {
{ STRCONST("Transfer-Encoding") },
};
-static bool h2_non_field(const char *name, size_t namelen)
+static bool h2_permissible_field(struct dynhds_entry *e)
{
size_t i;
for(i = 0; i < CURL_ARRAYSIZE(H2_NON_FIELD); ++i) {
- if(namelen < H2_NON_FIELD[i].namelen)
+ if(e->namelen < H2_NON_FIELD[i].namelen)
+ return TRUE;
+ if(e->namelen == H2_NON_FIELD[i].namelen &&
+ strcasecompare(H2_NON_FIELD[i].name, e->name))
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static bool http_TE_has_token(const char *fvalue, const char *token)
+{
+ while(*fvalue) {
+ struct Curl_str name;
+
+ /* skip to first token */
+ while(ISBLANK(*fvalue) || *fvalue == ',')
+ fvalue++;
+ if(curlx_str_cspn(&fvalue, &name, " \t\r;,"))
return FALSE;
- if(namelen == H2_NON_FIELD[i].namelen &&
- strcasecompare(H2_NON_FIELD[i].name, name))
+ if(curlx_str_casecompare(&name, token))
return TRUE;
+
+ /* skip any remainder after token, e.g. parameters with quoted strings */
+ while(*fvalue && *fvalue != ',') {
+ if(*fvalue == '"') {
+ struct Curl_str qw;
+ /* if we do not cleanly find a quoted word here, the header value
+ * does not follow HTTP syntax and we reject */
+ if(curlx_str_quotedword(&fvalue, &qw, CURL_MAX_HTTP_HEADER))
+ return FALSE;
+ }
+ else
+ fvalue++;
+ }
}
return FALSE;
}
@@ -4485,7 +4513,7 @@ CURLcode Curl_http_req_to_h2(struct dynhds *h2_headers,
scheme = Curl_checkheaders(data, STRCONST(HTTP_PSEUDO_SCHEME));
if(scheme) {
scheme += sizeof(HTTP_PSEUDO_SCHEME);
- Curl_str_passblanks(&scheme);
+ curlx_str_passblanks(&scheme);
infof(data, "set pseudo header %s to %s", HTTP_PSEUDO_SCHEME, scheme);
}
else {
@@ -4521,7 +4549,14 @@ CURLcode Curl_http_req_to_h2(struct dynhds *h2_headers,
}
for(i = 0; !result && i < Curl_dynhds_count(&req->headers); ++i) {
e = Curl_dynhds_getn(&req->headers, i);
- if(!h2_non_field(e->name, e->namelen)) {
+ /* "TE" is special in that it is only permissible when it
+ * has only value "trailers". RFC 9113 ch. 8.2.2 */
+ if(e->namelen == 2 && strcasecompare("TE", e->name)) {
+ if(http_TE_has_token(e->value, "trailers"))
+ result = Curl_dynhds_add(h2_headers, e->name, e->namelen,
+ "trailers", sizeof("trailers") - 1);
+ }
+ else if(h2_permissible_field(e)) {
result = Curl_dynhds_add(h2_headers, e->name, e->namelen,
e->value, e->valuelen);
}
@@ -4613,7 +4648,7 @@ static CURLcode cr_exp100_read(struct Curl_easy *data,
DEBUGF(infof(data, "cr_exp100_read, start AWAITING_CONTINUE, "
"timeout %ldms", data->set.expect_100_timeout));
ctx->state = EXP100_AWAITING_CONTINUE;
- ctx->start = Curl_now();
+ ctx->start = curlx_now();
Curl_expire(data, data->set.expect_100_timeout, EXPIRE_100_TIMEOUT);
data->req.keepon &= ~KEEP_SEND;
data->req.keepon |= KEEP_SEND_TIMED;
@@ -4626,7 +4661,7 @@ static CURLcode cr_exp100_read(struct Curl_easy *data,
*eos = FALSE;
return CURLE_READ_ERROR;
case EXP100_AWAITING_CONTINUE:
- ms = Curl_timediff(Curl_now(), ctx->start);
+ ms = curlx_timediff(curlx_now(), ctx->start);
if(ms < data->set.expect_100_timeout) {
DEBUGF(infof(data, "cr_exp100_read, AWAITING_CONTINUE, not expired"));
data->req.keepon &= ~KEEP_SEND;
diff --git a/libs/libcurl/src/http.h b/libs/libcurl/src/http.h
index e97abc0a28..5b05e74be9 100644
--- a/libs/libcurl/src/http.h
+++ b/libs/libcurl/src/http.h
@@ -174,6 +174,10 @@ CURLcode Curl_http_follow(struct Curl_easy *data, const char *newurl,
version. This count includes CONNECT response headers. */
#define MAX_HTTP_RESP_HEADER_SIZE (300*1024)
+/* MAX_HTTP_RESP_HEADER_COUNT is the maximum number of response headers that
+ libcurl allows for a single HTTP response, including CONNECT and
+ redirects. */
+#define MAX_HTTP_RESP_HEADER_COUNT 5000
#endif /* CURL_DISABLE_HTTP */
diff --git a/libs/libcurl/src/http1.c b/libs/libcurl/src/http1.c
index 8a1278112c..301c402dbc 100644
--- a/libs/libcurl/src/http1.c
+++ b/libs/libcurl/src/http1.c
@@ -44,14 +44,14 @@ 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_dyn_init(&parser->scratch, max_line_len);
+ curlx_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_dyn_free(&parser->scratch);
+ curlx_dyn_free(&parser->scratch);
parser->req = NULL;
parser->done = FALSE;
}
@@ -108,18 +108,18 @@ static ssize_t next_line(struct h1_req_parser *parser,
if(parser->line) {
parser->line = NULL;
parser->line_len = 0;
- Curl_dyn_reset(&parser->scratch);
+ curlx_dyn_reset(&parser->scratch);
}
nread = detect_line(parser, buf, buflen, err);
if(nread >= 0) {
- if(Curl_dyn_len(&parser->scratch)) {
+ if(curlx_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);
+ *err = curlx_dyn_addn(&parser->scratch, parser->line, parser->line_len);
if(*err)
return -1;
- parser->line = Curl_dyn_ptr(&parser->scratch);
- parser->line_len = Curl_dyn_len(&parser->scratch);
+ parser->line = curlx_dyn_ptr(&parser->scratch);
+ parser->line_len = curlx_dyn_len(&parser->scratch);
}
*err = trim_line(parser, options);
if(*err)
@@ -127,7 +127,8 @@ static ssize_t next_line(struct h1_req_parser *parser,
}
else if(*err == CURLE_AGAIN) {
/* no line end in `buf`, add it to our scratch */
- *err = Curl_dyn_addn(&parser->scratch, (const unsigned char *)buf, buflen);
+ *err = curlx_dyn_addn(&parser->scratch, (const unsigned char *)buf,
+ buflen);
nread = (*err) ? -1 : (ssize_t)buflen;
}
return nread;
@@ -299,7 +300,7 @@ ssize_t Curl_h1_req_parse_read(struct h1_req_parser *parser,
goto out;
}
parser->done = TRUE;
- Curl_dyn_reset(&parser->scratch);
+ curlx_dyn_reset(&parser->scratch);
/* last chance adjustments */
}
else {
@@ -321,13 +322,13 @@ CURLcode Curl_h1_req_write_head(struct httpreq *req, int http_minor,
{
CURLcode result;
- result = Curl_dyn_addf(dbuf, "%s %s%s%s%s HTTP/1.%d\r\n",
- req->method,
- req->scheme ? req->scheme : "",
- req->scheme ? "://" : "",
- req->authority ? req->authority : "",
- req->path ? req->path : "",
- http_minor);
+ result = curlx_dyn_addf(dbuf, "%s %s%s%s%s HTTP/1.%d\r\n",
+ req->method,
+ req->scheme ? req->scheme : "",
+ req->scheme ? "://" : "",
+ req->authority ? req->authority : "",
+ req->path ? req->path : "",
+ http_minor);
if(result)
goto out;
@@ -335,7 +336,7 @@ CURLcode Curl_h1_req_write_head(struct httpreq *req, int http_minor,
if(result)
goto out;
- result = Curl_dyn_addn(dbuf, STRCONST("\r\n"));
+ result = curlx_dyn_addn(dbuf, STRCONST("\r\n"));
out:
return result;
diff --git a/libs/libcurl/src/http1.h b/libs/libcurl/src/http1.h
index 650c984922..581048c944 100644
--- a/libs/libcurl/src/http1.h
+++ b/libs/libcurl/src/http1.h
@@ -42,7 +42,7 @@ struct h1_req_parser {
const char *line;
size_t max_line_len;
size_t line_len;
- bool done;
+ BIT(done);
};
void Curl_h1_req_parse_init(struct h1_req_parser *parser, size_t max_line_len);
diff --git a/libs/libcurl/src/http2.c b/libs/libcurl/src/http2.c
index a19ce0aff4..6d072b454c 100644
--- a/libs/libcurl/src/http2.c
+++ b/libs/libcurl/src/http2.c
@@ -29,13 +29,13 @@
#include <nghttp2/nghttp2.h>
#include "urldata.h"
#include "bufq.h"
-#include "hash_offt.h"
+#include "uint-hash.h"
#include "http1.h"
#include "http2.h"
#include "http.h"
#include "sendf.h"
#include "select.h"
-#include "curl_base64.h"
+#include "curlx/base64.h"
#include "strcase.h"
#include "multiif.h"
#include "url.h"
@@ -44,8 +44,9 @@
#include "connect.h"
#include "rand.h"
#include "strdup.h"
+#include "curlx/strparse.h"
#include "transfer.h"
-#include "dynbuf.h"
+#include "curlx/dynbuf.h"
#include "headers.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
@@ -135,12 +136,15 @@ struct cf_h2_ctx {
struct bufc_pool stream_bufcp; /* spares for stream buffers */
struct dynbuf scratch; /* scratch buffer for temp use */
- struct Curl_hash_offt streams; /* hash of `data->mid` to `h2_stream_ctx` */
+ struct uint_hash streams; /* hash of `data->mid` to `h2_stream_ctx` */
size_t drain_total; /* sum of all stream's UrlState drain */
uint32_t max_concurrent_streams;
uint32_t goaway_error; /* goaway error code from server */
int32_t remote_max_sid; /* max id processed by server */
int32_t local_max_sid; /* max id processed by us */
+#ifdef DEBUGBUILD
+ int32_t stream_win_max; /* max h2 stream window size */
+#endif
BIT(initialized);
BIT(via_h1_upgrade);
BIT(conn_closed);
@@ -155,17 +159,29 @@ struct cf_h2_ctx {
#define CF_CTX_CALL_DATA(cf) \
((struct cf_h2_ctx *)(cf)->ctx)->call_data
-static void h2_stream_hash_free(curl_off_t id, void *stream);
+static void h2_stream_hash_free(unsigned int id, void *stream);
static void cf_h2_ctx_init(struct cf_h2_ctx *ctx, bool via_h1_upgrade)
{
Curl_bufcp_init(&ctx->stream_bufcp, H2_CHUNK_SIZE, H2_STREAM_POOL_SPARES);
Curl_bufq_initp(&ctx->inbufq, &ctx->stream_bufcp, H2_NW_RECV_CHUNKS, 0);
Curl_bufq_initp(&ctx->outbufq, &ctx->stream_bufcp, H2_NW_SEND_CHUNKS, 0);
- Curl_dyn_init(&ctx->scratch, CURL_MAX_HTTP_HEADER);
- Curl_hash_offt_init(&ctx->streams, 63, h2_stream_hash_free);
+ curlx_dyn_init(&ctx->scratch, CURL_MAX_HTTP_HEADER);
+ Curl_uint_hash_init(&ctx->streams, 63, h2_stream_hash_free);
ctx->remote_max_sid = 2147483647;
ctx->via_h1_upgrade = via_h1_upgrade;
+#ifdef DEBUGBUILD
+ {
+ const char *p = getenv("CURL_H2_STREAM_WIN_MAX");
+
+ ctx->stream_win_max = H2_STREAM_WINDOW_SIZE_MAX;
+ if(p) {
+ curl_off_t l;
+ if(!curlx_str_number(&p, &l, INT_MAX))
+ ctx->stream_win_max = (int32_t)l;
+ }
+ }
+#endif
ctx->initialized = TRUE;
}
@@ -175,8 +191,8 @@ static void cf_h2_ctx_free(struct cf_h2_ctx *ctx)
Curl_bufq_free(&ctx->inbufq);
Curl_bufq_free(&ctx->outbufq);
Curl_bufcp_free(&ctx->stream_bufcp);
- Curl_dyn_free(&ctx->scratch);
- Curl_hash_offt_destroy(&ctx->streams);
+ curlx_dyn_free(&ctx->scratch);
+ Curl_uint_hash_destroy(&ctx->streams);
memset(ctx, 0, sizeof(*ctx));
}
free(ctx);
@@ -190,7 +206,7 @@ static void cf_h2_ctx_close(struct cf_h2_ctx *ctx)
}
static CURLcode h2_progress_egress(struct Curl_cfilter *cf,
- struct Curl_easy *data);
+ struct Curl_easy *data);
/**
* All about the H2 internals of a stream
@@ -221,8 +237,9 @@ struct h2_stream_ctx {
BIT(write_paused); /* stream write is paused */
};
-#define H2_STREAM_CTX(ctx,data) ((struct h2_stream_ctx *)(\
- data? Curl_hash_offt_get(&(ctx)->streams, (data)->mid) : NULL))
+#define H2_STREAM_CTX(ctx,data) \
+ ((struct h2_stream_ctx *)( \
+ data? Curl_uint_hash_get(&(ctx)->streams, (data)->mid) : NULL))
static struct h2_stream_ctx *h2_stream_ctx_create(struct cf_h2_ctx *ctx)
{
@@ -266,7 +283,7 @@ static void h2_stream_ctx_free(struct h2_stream_ctx *stream)
free(stream);
}
-static void h2_stream_hash_free(curl_off_t id, void *stream)
+static void h2_stream_hash_free(unsigned int id, void *stream)
{
(void)id;
DEBUGASSERT(stream);
@@ -285,7 +302,15 @@ static int32_t cf_h2_get_desired_local_win(struct Curl_cfilter *cf,
* This gets less precise the higher the latency. */
return (int32_t)data->set.max_recv_speed;
}
+#ifdef DEBUGBUILD
+ else {
+ struct cf_h2_ctx *ctx = cf->ctx;
+ CURL_TRC_CF(data, cf, "stream_win_max=%d", ctx->stream_win_max);
+ return ctx->stream_win_max;
+ }
+#else
return H2_STREAM_WINDOW_SIZE_MAX;
+#endif
}
static CURLcode cf_h2_update_local_win(struct Curl_cfilter *cf,
@@ -302,6 +327,13 @@ static CURLcode cf_h2_update_local_win(struct Curl_cfilter *cf,
int32_t wsize = nghttp2_session_get_stream_effective_local_window_size(
ctx->h2, stream->id);
if(dwsize > wsize) {
+ rv = nghttp2_session_set_local_window_size(ctx->h2, NGHTTP2_FLAG_NONE,
+ stream->id, dwsize);
+ if(rv) {
+ failf(data, "[%d] nghttp2 set_local_window_size(%d) failed: "
+ "%s(%d)", stream->id, dwsize, nghttp2_strerror(rv), rv);
+ return CURLE_HTTP2;
+ }
rv = nghttp2_submit_window_update(ctx->h2, NGHTTP2_FLAG_NONE,
stream->id, dwsize - wsize);
if(rv) {
@@ -383,7 +415,7 @@ static CURLcode http2_data_setup(struct Curl_cfilter *cf,
if(!stream)
return CURLE_OUT_OF_MEMORY;
- if(!Curl_hash_offt_set(&ctx->streams, data->mid, stream)) {
+ if(!Curl_uint_hash_set(&ctx->streams, data->mid, stream)) {
h2_stream_ctx_free(stream);
return CURLE_OUT_OF_MEMORY;
}
@@ -421,7 +453,7 @@ static void http2_data_done(struct Curl_cfilter *cf, struct Curl_easy *data)
nghttp2_session_send(ctx->h2);
}
- Curl_hash_offt_remove(&ctx->streams, data->mid);
+ Curl_uint_hash_remove(&ctx->streams, data->mid);
}
static int h2_client_new(struct Curl_cfilter *cf,
@@ -430,7 +462,7 @@ static int h2_client_new(struct Curl_cfilter *cf,
struct cf_h2_ctx *ctx = cf->ctx;
nghttp2_option *o;
nghttp2_mem mem = {NULL, Curl_nghttp2_malloc, Curl_nghttp2_free,
- Curl_nghttp2_calloc, Curl_nghttp2_realloc};
+ Curl_nghttp2_calloc, Curl_nghttp2_realloc};
int rc = nghttp2_option_new(&o);
if(rc)
@@ -1030,8 +1062,8 @@ static int push_promise(struct Curl_cfilter *cf,
newhandle->req.maxdownload = -1;
newhandle->req.size = -1;
- CURL_TRC_CF(data, cf, "promise easy handle added to multi, mid=%"
- FMT_OFF_T, newhandle->mid);
+ CURL_TRC_CF(data, cf, "promise easy handle added to multi, mid=%u",
+ newhandle->mid);
rv = nghttp2_session_set_stream_user_data(ctx->h2,
newstream->id,
newhandle);
@@ -1690,15 +1722,15 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame,
cf_h2_header_error(cf, data_s, stream, result);
return NGHTTP2_ERR_CALLBACK_FAILURE;
}
- Curl_dyn_reset(&ctx->scratch);
- result = Curl_dyn_addn(&ctx->scratch, STRCONST("HTTP/2 "));
+ curlx_dyn_reset(&ctx->scratch);
+ result = curlx_dyn_addn(&ctx->scratch, STRCONST("HTTP/2 "));
if(!result)
- result = Curl_dyn_addn(&ctx->scratch, value, valuelen);
+ result = curlx_dyn_addn(&ctx->scratch, value, valuelen);
if(!result)
- result = Curl_dyn_addn(&ctx->scratch, STRCONST(" \r\n"));
+ result = curlx_dyn_addn(&ctx->scratch, STRCONST(" \r\n"));
if(!result)
- h2_xfer_write_resp_hd(cf, data_s, stream, Curl_dyn_ptr(&ctx->scratch),
- Curl_dyn_len(&ctx->scratch), FALSE);
+ h2_xfer_write_resp_hd(cf, data_s, stream, curlx_dyn_ptr(&ctx->scratch),
+ curlx_dyn_len(&ctx->scratch), FALSE);
if(result) {
cf_h2_header_error(cf, data_s, stream, result);
return NGHTTP2_ERR_CALLBACK_FAILURE;
@@ -1715,17 +1747,17 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame,
/* nghttp2 guarantees that namelen > 0, and :status was already
received, and this is not pseudo-header field . */
/* convert to an HTTP1-style header */
- Curl_dyn_reset(&ctx->scratch);
- result = Curl_dyn_addn(&ctx->scratch, (const char *)name, namelen);
+ curlx_dyn_reset(&ctx->scratch);
+ result = curlx_dyn_addn(&ctx->scratch, (const char *)name, namelen);
if(!result)
- result = Curl_dyn_addn(&ctx->scratch, STRCONST(": "));
+ result = curlx_dyn_addn(&ctx->scratch, STRCONST(": "));
if(!result)
- result = Curl_dyn_addn(&ctx->scratch, (const char *)value, valuelen);
+ result = curlx_dyn_addn(&ctx->scratch, (const char *)value, valuelen);
if(!result)
- result = Curl_dyn_addn(&ctx->scratch, STRCONST("\r\n"));
+ result = curlx_dyn_addn(&ctx->scratch, STRCONST("\r\n"));
if(!result)
- h2_xfer_write_resp_hd(cf, data_s, stream, Curl_dyn_ptr(&ctx->scratch),
- Curl_dyn_len(&ctx->scratch), FALSE);
+ h2_xfer_write_resp_hd(cf, data_s, stream, curlx_dyn_ptr(&ctx->scratch),
+ curlx_dyn_len(&ctx->scratch), FALSE);
if(result) {
cf_h2_header_error(cf, data_s, stream, result);
return NGHTTP2_ERR_CALLBACK_FAILURE;
@@ -1818,22 +1850,22 @@ CURLcode Curl_http2_request_upgrade(struct dynbuf *req,
binlen = populate_binsettings(binsettings, data);
if(binlen <= 0) {
failf(data, "nghttp2 unexpectedly failed on pack_settings_payload");
- Curl_dyn_free(req);
+ curlx_dyn_free(req);
return CURLE_FAILED_INIT;
}
- result = Curl_base64url_encode((const char *)binsettings, (size_t)binlen,
- &base64, &blen);
+ result = curlx_base64url_encode((const char *)binsettings, (size_t)binlen,
+ &base64, &blen);
if(result) {
- Curl_dyn_free(req);
+ curlx_dyn_free(req);
return result;
}
- result = Curl_dyn_addf(req,
- "Connection: Upgrade, HTTP2-Settings\r\n"
- "Upgrade: %s\r\n"
- "HTTP2-Settings: %s\r\n",
- NGHTTP2_CLEARTEXT_PROTO_VERSION_ID, base64);
+ result = curlx_dyn_addf(req,
+ "Connection: Upgrade, HTTP2-Settings\r\n"
+ "Upgrade: %s\r\n"
+ "HTTP2-Settings: %s\r\n",
+ NGHTTP2_CLEARTEXT_PROTO_VERSION_ID, base64);
free(base64);
k->upgr101 = UPGR101_H2;
@@ -1893,25 +1925,25 @@ static ssize_t http2_handle_stream_close(struct Curl_cfilter *cf,
size_t i;
*err = CURLE_OK;
- Curl_dyn_init(&dbuf, DYN_TRAILERS);
+ curlx_dyn_init(&dbuf, DYN_TRAILERS);
for(i = 0; i < Curl_dynhds_count(&stream->resp_trailers); ++i) {
e = Curl_dynhds_getn(&stream->resp_trailers, i);
if(!e)
break;
- Curl_dyn_reset(&dbuf);
- *err = Curl_dyn_addf(&dbuf, "%.*s: %.*s\x0d\x0a",
- (int)e->namelen, e->name,
- (int)e->valuelen, e->value);
+ curlx_dyn_reset(&dbuf);
+ *err = curlx_dyn_addf(&dbuf, "%.*s: %.*s\x0d\x0a",
+ (int)e->namelen, e->name,
+ (int)e->valuelen, e->value);
if(*err)
break;
- Curl_debug(data, CURLINFO_HEADER_IN, Curl_dyn_ptr(&dbuf),
- Curl_dyn_len(&dbuf));
+ Curl_debug(data, CURLINFO_HEADER_IN, curlx_dyn_ptr(&dbuf),
+ curlx_dyn_len(&dbuf));
*err = Curl_client_write(data, CLIENTWRITE_HEADER|CLIENTWRITE_TRAILER,
- Curl_dyn_ptr(&dbuf), Curl_dyn_len(&dbuf));
+ curlx_dyn_ptr(&dbuf), curlx_dyn_len(&dbuf));
if(*err)
break;
}
- Curl_dyn_free(&dbuf);
+ curlx_dyn_free(&dbuf);
if(*err)
goto out;
}
@@ -2123,7 +2155,7 @@ static ssize_t cf_h2_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
* a read() is called anyway. It is not clear what the calling sequence
* is for such a case. */
failf(data, "http/2 recv on a transfer never opened "
- "or already cleared, mid=%" FMT_OFF_T, data->mid);
+ "or already cleared, mid=%u", data->mid);
*err = CURLE_HTTP2;
return -1;
}
@@ -2775,7 +2807,7 @@ static CURLcode cf_h2_query(struct Curl_cfilter *cf,
CF_DATA_SAVE(save, cf, data);
if(nghttp2_session_check_request_allowed(ctx->h2) == 0) {
/* the limit is what we have in use right now */
- effective_max = CONN_INUSE(cf->conn);
+ effective_max = CONN_ATTACHED(cf->conn);
}
else {
effective_max = ctx->max_concurrent_streams;
diff --git a/libs/libcurl/src/http_aws_sigv4.c b/libs/libcurl/src/http_aws_sigv4.c
index 0c796566f2..754e3777a8 100644
--- a/libs/libcurl/src/http_aws_sigv4.c
+++ b/libs/libcurl/src/http_aws_sigv4.c
@@ -35,7 +35,7 @@
#include "parsedate.h"
#include "sendf.h"
#include "escape.h"
-#include "strparse.h"
+#include "curlx/strparse.h"
#include <time.h>
@@ -63,6 +63,27 @@
/* hex-encoded with trailing null */
#define SHA256_HEX_LENGTH (2 * CURL_SHA256_DIGEST_LENGTH + 1)
+#define MAX_QUERY_COMPONENTS 128
+
+struct pair {
+ struct dynbuf key;
+ struct dynbuf value;
+};
+
+static void dyn_array_free(struct dynbuf *db, size_t num_elements);
+static void pair_array_free(struct pair *pair_array, size_t num_elements);
+static CURLcode split_to_dyn_array(const char *source,
+ struct dynbuf db[MAX_QUERY_COMPONENTS],
+ size_t *num_splits);
+static bool is_reserved_char(const char c);
+static CURLcode uri_encode_path(struct Curl_str *original_path,
+ struct dynbuf *new_path);
+static CURLcode encode_query_component(char *component, size_t len,
+ struct dynbuf *db);
+static CURLcode http_aws_decode_encode(const char *in, size_t in_len,
+ struct dynbuf *out);
+static bool should_urlencode(struct Curl_str *service_name);
+
static void sha256_to_hex(char *dst, unsigned char *sha)
{
Curl_hexencode(sha, CURL_SHA256_DIGEST_LENGTH,
@@ -95,7 +116,7 @@ static void trim_headers(struct curl_slist *head)
store = (char *)CURL_UNCONST(value);
/* skip leading whitespace */
- Curl_str_passblanks(&value);
+ curlx_str_passblanks(&value);
while(*value) {
int space = 0;
@@ -172,9 +193,9 @@ static CURLcode merge_duplicate_headers(struct curl_slist *head)
char *colon_next;
char *val_next;
- Curl_dyn_init(&buf, CURL_MAX_HTTP_HEADER);
+ curlx_dyn_init(&buf, CURL_MAX_HTTP_HEADER);
- result = Curl_dyn_add(&buf, curr->data);
+ result = curlx_dyn_add(&buf, curr->data);
if(result)
return result;
@@ -182,16 +203,16 @@ static CURLcode merge_duplicate_headers(struct curl_slist *head)
DEBUGASSERT(colon_next);
val_next = colon_next + 1;
- result = Curl_dyn_addn(&buf, ",", 1);
+ result = curlx_dyn_addn(&buf, ",", 1);
if(result)
return result;
- result = Curl_dyn_add(&buf, val_next);
+ result = curlx_dyn_add(&buf, val_next);
if(result)
return result;
free(curr->data);
- curr->data = Curl_dyn_ptr(&buf);
+ curr->data = curlx_dyn_ptr(&buf);
curr->next = next->next;
free(next->data);
@@ -319,7 +340,7 @@ static CURLcode make_headers(struct Curl_easy *data,
goto fail;
}
++value;
- Curl_str_passblanks(&value);
+ curlx_str_passblanks(&value);
endp = value;
while(*endp && ISALNUM(*endp))
++endp;
@@ -357,9 +378,9 @@ static CURLcode make_headers(struct Curl_easy *data,
for(l = head; l; l = l->next) {
char *tmp;
- if(Curl_dyn_add(canonical_headers, l->data))
+ if(curlx_dyn_add(canonical_headers, l->data))
goto fail;
- if(Curl_dyn_add(canonical_headers, "\n"))
+ if(curlx_dyn_add(canonical_headers, "\n"))
goto fail;
tmp = strchr(l->data, ':');
@@ -367,10 +388,10 @@ static CURLcode make_headers(struct Curl_easy *data,
*tmp = 0;
if(l != head) {
- if(Curl_dyn_add(signed_headers, ";"))
+ if(curlx_dyn_add(signed_headers, ";"))
goto fail;
}
- if(Curl_dyn_add(signed_headers, l->data))
+ if(curlx_dyn_add(signed_headers, l->data))
goto fail;
}
@@ -390,8 +411,7 @@ fail:
static const char *parse_content_sha_hdr(struct Curl_easy *data,
const char *provider1,
size_t plen,
- size_t *value_len)
-{
+ size_t *value_len) {
char key[CONTENT_SHA256_KEY_LEN];
size_t key_len;
const char *value;
@@ -409,7 +429,7 @@ static const char *parse_content_sha_hdr(struct Curl_easy *data,
return NULL;
++value;
- Curl_str_passblanks(&value);
+ curlx_str_passblanks(&value);
len = strlen(value);
while(len > 0 && ISBLANK(value[len-1]))
@@ -478,152 +498,176 @@ fail:
return ret;
}
-struct pair {
- const char *p;
- size_t len;
-};
-
static int compare_func(const void *a, const void *b)
{
+
const struct pair *aa = a;
const struct pair *bb = b;
+ const size_t aa_key_len = curlx_dyn_len(&aa->key);
+ const size_t bb_key_len = curlx_dyn_len(&bb->key);
+ const size_t aa_value_len = curlx_dyn_len(&aa->value);
+ const size_t bb_value_len = curlx_dyn_len(&bb->value);
+ int compare;
+
/* If one element is empty, the other is always sorted higher */
- if(aa->len == 0 && bb->len == 0)
+
+ /* Compare keys */
+ if((aa_key_len == 0) && (bb_key_len == 0))
return 0;
- if(aa->len == 0)
+ if(aa_key_len == 0)
return -1;
- if(bb->len == 0)
+ if(bb_key_len == 0)
return 1;
- return strncmp(aa->p, bb->p, aa->len < bb->len ? aa->len : bb->len);
-}
+ compare = strcmp(curlx_dyn_ptr(&aa->key), curlx_dyn_ptr(&bb->key));
+ if(compare) {
+ return compare;
+ }
+
+ /* Compare values */
+ if((aa_value_len == 0) && (bb_value_len == 0))
+ return 0;
+ if(aa_value_len == 0)
+ return -1;
+ if(bb_value_len == 0)
+ return 1;
+ compare = strcmp(curlx_dyn_ptr(&aa->value), curlx_dyn_ptr(&bb->value));
-#define MAX_QUERYPAIRS 64
+ return compare;
-/**
- * found_equals have a double meaning,
- * detect if an equal have been found when called from canon_query,
- * and mark that this function is called to compute the path,
- * if found_equals is NULL.
- */
-static CURLcode canon_string(const char *q, size_t len,
- struct dynbuf *dq, bool *found_equals)
+}
+
+UNITTEST CURLcode canon_path(const char *q, size_t len,
+ struct dynbuf *new_path,
+ bool do_uri_encode)
{
CURLcode result = CURLE_OK;
- for(; len && !result; q++, len--) {
- if(ISALNUM(*q))
- result = Curl_dyn_addn(dq, q, 1);
- else {
- switch(*q) {
- case '-':
- case '.':
- case '_':
- case '~':
- /* allowed as-is */
- result = Curl_dyn_addn(dq, q, 1);
- break;
- case '%':
- /* uppercase the following if hexadecimal */
- if(ISXDIGIT(q[1]) && ISXDIGIT(q[2])) {
- char tmp[3]="%";
- tmp[1] = Curl_raw_toupper(q[1]);
- tmp[2] = Curl_raw_toupper(q[2]);
- result = Curl_dyn_addn(dq, tmp, 3);
- q += 2;
- len -= 2;
- }
- else
- /* '%' without a following two-digit hex, encode it */
- result = Curl_dyn_addn(dq, "%25", 3);
- break;
- default: {
- const char hex[] = "0123456789ABCDEF";
- char out[3]={'%'};
-
- if(!found_equals) {
- /* if found_equals is NULL assuming, been in path */
- if(*q == '/') {
- /* allowed as if */
- result = Curl_dyn_addn(dq, q, 1);
- break;
- }
- }
- else {
- /* allowed as-is */
- if(*q == '=') {
- result = Curl_dyn_addn(dq, q, 1);
- *found_equals = TRUE;
- break;
- }
- }
- /* URL encode */
- out[1] = hex[((unsigned char)*q) >> 4];
- out[2] = hex[*q & 0xf];
- result = Curl_dyn_addn(dq, out, 3);
- break;
- }
- }
- }
+ struct Curl_str original_path;
+
+ curlx_str_assign(&original_path, q, len);
+
+ /* Normalized path will be either the same or shorter than the original
+ * path, plus trailing slash */
+
+ if(do_uri_encode)
+ result = uri_encode_path(&original_path, new_path);
+ else
+ result = curlx_dyn_addn(new_path, q, len);
+
+ if(!result) {
+ if(curlx_dyn_len(new_path) == 0)
+ result = curlx_dyn_add(new_path, "/");
}
+
return result;
}
-
-static CURLcode canon_query(struct Curl_easy *data,
- const char *query, struct dynbuf *dq)
+UNITTEST CURLcode canon_query(const char *query, struct dynbuf *dq)
{
CURLcode result = CURLE_OK;
- int entry = 0;
- int i;
- const char *p = query;
- struct pair array[MAX_QUERYPAIRS];
- struct pair *ap = &array[0];
+
+ struct dynbuf query_array[MAX_QUERY_COMPONENTS];
+ struct pair encoded_query_array[MAX_QUERY_COMPONENTS];
+ size_t num_query_components;
+ size_t counted_query_components = 0;
+ size_t index;
+
if(!query)
return result;
- /* sort the name=value pairs first */
- do {
- char *amp;
- entry++;
- ap->p = p;
- amp = strchr(p, '&');
- if(amp)
- ap->len = amp - p; /* excluding the ampersand */
+ result = split_to_dyn_array(query, &query_array[0],
+ &num_query_components);
+ if(result) {
+ goto fail;
+ }
+
+ /* Create list of pairs, each pair containing an encoded query
+ * component */
+
+ for(index = 0; index < num_query_components; index++) {
+ const char *in_key;
+ size_t in_key_len;
+ char *offset;
+ size_t query_part_len = curlx_dyn_len(&query_array[index]);
+ char *query_part = curlx_dyn_ptr(&query_array[index]);
+
+ in_key = query_part;
+
+ offset = strchr(query_part, '=');
+ /* If there is no equals, this key has no value */
+ if(!offset) {
+ in_key_len = strlen(in_key);
+ }
else {
- ap->len = strlen(p);
- break;
+ in_key_len = offset - in_key;
}
- ap++;
- p = amp + 1;
- } while(entry < MAX_QUERYPAIRS);
- if(entry == MAX_QUERYPAIRS) {
- /* too many query pairs for us */
- failf(data, "aws-sigv4: too many query pairs in URL");
- return CURLE_URL_MALFORMAT;
- }
-
- qsort(&array[0], entry, sizeof(struct pair), compare_func);
-
- ap = &array[0];
- for(i = 0; !result && (i < entry); i++, ap++) {
- const char *q = ap->p;
- bool found_equals = FALSE;
- if(!ap->len)
- continue;
- result = canon_string(q, ap->len, dq, &found_equals);
- if(!result && !found_equals) {
- /* queries without value still need an equals */
- result = Curl_dyn_addn(dq, "=", 1);
+
+ curlx_dyn_init(&encoded_query_array[index].key, query_part_len*3 + 1);
+ curlx_dyn_init(&encoded_query_array[index].value, query_part_len*3 + 1);
+ counted_query_components++;
+
+ /* Decode/encode the key */
+ result = http_aws_decode_encode(in_key, in_key_len,
+ &encoded_query_array[index].key);
+ if(result) {
+ goto fail;
+ }
+
+ /* Decode/encode the value if it exists */
+ if(offset && offset != (query_part + query_part_len - 1)) {
+ size_t in_value_len;
+ const char *in_value = offset + 1;
+ in_value_len = query_part + query_part_len - (offset + 1);
+ result = http_aws_decode_encode(in_value, in_value_len,
+ &encoded_query_array[index].value);
+ if(result) {
+ goto fail;
+ }
}
- if(!result && i < entry - 1) {
- /* insert ampersands between query pairs */
- result = Curl_dyn_addn(dq, "&", 1);
+ else {
+ /* If there is no value, the value is an empty string */
+ curlx_dyn_init(&encoded_query_array[index].value, 2);
+ result = curlx_dyn_addn(&encoded_query_array[index].value, "", 1);
+ }
+
+ if(result) {
+ goto fail;
}
}
+
+ /* Sort the encoded query components by key and value */
+ qsort(&encoded_query_array, num_query_components,
+ sizeof(struct pair), compare_func);
+
+ /* Append the query components together to make a full query string */
+ for(index = 0; index < num_query_components; index++) {
+
+ if(index)
+ result = curlx_dyn_addn(dq, "&", 1);
+ if(!result) {
+ char *key_ptr = curlx_dyn_ptr(&encoded_query_array[index].key);
+ char *value_ptr = curlx_dyn_ptr(&encoded_query_array[index].value);
+ size_t vlen = curlx_dyn_len(&encoded_query_array[index].value);
+ if(value_ptr && vlen) {
+ result = curlx_dyn_addf(dq, "%s=%s", key_ptr, value_ptr);
+ }
+ else {
+ /* Empty value is always encoded to key= */
+ result = curlx_dyn_addf(dq, "%s=", key_ptr);
+ }
+ }
+ if(result)
+ break;
+ }
+
+fail:
+ if(counted_query_components)
+ /* the encoded_query_array might not be initialized yet */
+ pair_array_free(&encoded_query_array[0], counted_query_components);
+ dyn_array_free(&query_array[0], num_query_components);
return result;
}
-
CURLcode Curl_output_aws_sigv4(struct Curl_easy *data)
{
CURLcode result = CURLE_OUT_OF_MEMORY;
@@ -660,16 +704,21 @@ CURLcode Curl_output_aws_sigv4(struct Curl_easy *data)
unsigned char sign1[CURL_SHA256_DIGEST_LENGTH] = {0};
char *auth_headers = NULL;
+ if(data->set.path_as_is) {
+ failf(data, "Cannot use sigv4 authentication with path-as-is flag");
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ }
+
if(Curl_checkheaders(data, STRCONST("Authorization"))) {
/* Authorization already present, Bailing out */
return CURLE_OK;
}
/* we init those buffers here, so goto fail will free initialized dynbuf */
- Curl_dyn_init(&canonical_headers, CURL_MAX_HTTP_HEADER);
- Curl_dyn_init(&canonical_query, CURL_MAX_HTTP_HEADER);
- Curl_dyn_init(&signed_headers, CURL_MAX_HTTP_HEADER);
- Curl_dyn_init(&canonical_path, CURL_MAX_HTTP_HEADER);
+ curlx_dyn_init(&canonical_headers, CURL_MAX_HTTP_HEADER);
+ curlx_dyn_init(&canonical_query, CURL_MAX_HTTP_HEADER);
+ curlx_dyn_init(&signed_headers, CURL_MAX_HTTP_HEADER);
+ curlx_dyn_init(&canonical_path, CURL_MAX_HTTP_HEADER);
/*
* Parameters parsing
@@ -678,69 +727,70 @@ CURLcode Curl_output_aws_sigv4(struct Curl_easy *data)
* AWS is the default because most of non-amazon providers
* are still using aws:amz as a prefix.
*/
- line = data->set.str[STRING_AWS_SIGV4] ?
- data->set.str[STRING_AWS_SIGV4] : "aws:amz";
+ line = data->set.str[STRING_AWS_SIGV4];
+ if(!line || !*line)
+ line = "aws:amz";
/* provider0[:provider1[:region[:service]]]
No string can be longer than N bytes of non-whitespace
*/
- if(Curl_str_until(&line, &provider0, MAX_SIGV4_LEN, ':')) {
+ if(curlx_str_until(&line, &provider0, MAX_SIGV4_LEN, ':')) {
failf(data, "first aws-sigv4 provider cannot be empty");
result = CURLE_BAD_FUNCTION_ARGUMENT;
goto fail;
}
- if(Curl_str_single(&line, ':') ||
- Curl_str_until(&line, &provider1, MAX_SIGV4_LEN, ':')) {
+ if(curlx_str_single(&line, ':') ||
+ curlx_str_until(&line, &provider1, MAX_SIGV4_LEN, ':')) {
provider1 = provider0;
}
- else if(Curl_str_single(&line, ':') ||
- Curl_str_until(&line, &region, MAX_SIGV4_LEN, ':') ||
- Curl_str_single(&line, ':') ||
- Curl_str_until(&line, &service, MAX_SIGV4_LEN, ':')) {
+ else if(curlx_str_single(&line, ':') ||
+ curlx_str_until(&line, &region, MAX_SIGV4_LEN, ':') ||
+ curlx_str_single(&line, ':') ||
+ curlx_str_until(&line, &service, MAX_SIGV4_LEN, ':')) {
/* nothing to do */
}
- if(!Curl_strlen(&service)) {
+ if(!curlx_strlen(&service)) {
const char *p = hostname;
- if(Curl_str_until(&p, &service, MAX_SIGV4_LEN, '.') ||
- Curl_str_single(&p, '.')) {
+ if(curlx_str_until(&p, &service, MAX_SIGV4_LEN, '.') ||
+ curlx_str_single(&p, '.')) {
failf(data, "aws-sigv4: service missing in parameters and hostname");
result = CURLE_URL_MALFORMAT;
goto fail;
}
infof(data, "aws_sigv4: picked service %.*s from host",
- (int)Curl_strlen(&service), Curl_str(&service));
+ (int)curlx_strlen(&service), curlx_str(&service));
- if(!Curl_strlen(&region)) {
- if(Curl_str_until(&p, &region, MAX_SIGV4_LEN, '.') ||
- Curl_str_single(&p, '.')) {
+ if(!curlx_strlen(&region)) {
+ if(curlx_str_until(&p, &region, MAX_SIGV4_LEN, '.') ||
+ curlx_str_single(&p, '.')) {
failf(data, "aws-sigv4: region missing in parameters and hostname");
result = CURLE_URL_MALFORMAT;
goto fail;
}
infof(data, "aws_sigv4: picked region %.*s from host",
- (int)Curl_strlen(&region), Curl_str(&region));
+ (int)curlx_strlen(&region), curlx_str(&region));
}
}
Curl_http_method(data, conn, &method, &httpreq);
payload_hash =
- parse_content_sha_hdr(data, Curl_str(&provider1), Curl_strlen(&provider1),
- &payload_hash_len);
+ parse_content_sha_hdr(data, curlx_str(&provider1),
+ curlx_strlen(&provider1), &payload_hash_len);
if(!payload_hash) {
/* AWS S3 requires a x-amz-content-sha256 header, and supports special
* values like UNSIGNED-PAYLOAD */
- bool sign_as_s3 = Curl_str_casecompare(&provider0, "aws") &&
- Curl_str_casecompare(&service, "s3");
+ bool sign_as_s3 = curlx_str_casecompare(&provider0, "aws") &&
+ curlx_str_casecompare(&service, "s3");
if(sign_as_s3)
- result = calc_s3_payload_hash(data, httpreq, Curl_str(&provider1),
- Curl_strlen(&provider1), sha_hash, sha_hex,
- content_sha256_hdr);
+ result = calc_s3_payload_hash(data, httpreq, curlx_str(&provider1),
+ curlx_strlen(&provider1), sha_hash,
+ sha_hex, content_sha256_hdr);
else
result = calc_payload_hash(data, sha_hash, sha_hex);
if(result)
@@ -772,7 +822,7 @@ CURLcode Curl_output_aws_sigv4(struct Curl_easy *data)
}
result = make_headers(data, hostname, timestamp,
- Curl_str(&provider1), Curl_strlen(&provider1),
+ curlx_str(&provider1), curlx_strlen(&provider1),
&date_header, content_sha256_hdr,
&canonical_headers, &signed_headers);
if(result)
@@ -788,12 +838,13 @@ CURLcode Curl_output_aws_sigv4(struct Curl_easy *data)
memcpy(date, timestamp, sizeof(date));
date[sizeof(date) - 1] = 0;
- result = canon_query(data, data->state.up.query, &canonical_query);
+ result = canon_query(data->state.up.query, &canonical_query);
if(result)
goto fail;
- result = canon_string(data->state.up.path, strlen(data->state.up.path),
- &canonical_path, NULL);
+ result = canon_path(data->state.up.path, strlen(data->state.up.path),
+ &canonical_path,
+ should_urlencode(&service));
if(result)
goto fail;
result = CURLE_OUT_OF_MEMORY;
@@ -806,29 +857,30 @@ CURLcode Curl_output_aws_sigv4(struct Curl_easy *data)
"%s\n" /* SignedHeaders */
"%.*s", /* HashedRequestPayload in hex */
method,
- Curl_dyn_ptr(&canonical_path),
- Curl_dyn_ptr(&canonical_query) ?
- Curl_dyn_ptr(&canonical_query) : "",
- Curl_dyn_ptr(&canonical_headers),
- Curl_dyn_ptr(&signed_headers),
+ curlx_dyn_ptr(&canonical_path),
+ curlx_dyn_ptr(&canonical_query) ?
+ curlx_dyn_ptr(&canonical_query) : "",
+ curlx_dyn_ptr(&canonical_headers),
+ curlx_dyn_ptr(&signed_headers),
(int)payload_hash_len, payload_hash);
if(!canonical_request)
goto fail;
- DEBUGF(infof(data, "Canonical request: %s", canonical_request));
+ infof(data, "aws_sigv4: Canonical request (enclosed in []) - [%s]",
+ canonical_request);
request_type = aprintf("%.*s4_request",
- (int)Curl_strlen(&provider0), Curl_str(&provider0));
+ (int)curlx_strlen(&provider0), curlx_str(&provider0));
if(!request_type)
goto fail;
/* provider0 is lowercased *after* aprintf() so that the buffer can be
written to */
- Curl_strntolower(request_type, request_type, Curl_strlen(&provider0));
+ Curl_strntolower(request_type, request_type, curlx_strlen(&provider0));
credential_scope = aprintf("%s/%.*s/%.*s/%s", date,
- (int)Curl_strlen(&region), Curl_str(&region),
- (int)Curl_strlen(&service), Curl_str(&service),
+ (int)curlx_strlen(&region), curlx_str(&region),
+ (int)curlx_strlen(&service), curlx_str(&service),
request_type);
if(!credential_scope)
goto fail;
@@ -847,7 +899,7 @@ CURLcode Curl_output_aws_sigv4(struct Curl_easy *data)
"%s\n" /* RequestDateTime */
"%s\n" /* CredentialScope */
"%s", /* HashedCanonicalRequest in hex */
- (int)Curl_strlen(&provider0), Curl_str(&provider0),
+ (int)curlx_strlen(&provider0), curlx_str(&provider0),
timestamp,
credential_scope,
sha_hex);
@@ -855,26 +907,32 @@ CURLcode Curl_output_aws_sigv4(struct Curl_easy *data)
goto fail;
/* make provider0 part done uppercase */
- Curl_strntoupper(str_to_sign, Curl_str(&provider0), Curl_strlen(&provider0));
+ Curl_strntoupper(str_to_sign, curlx_str(&provider0),
+ curlx_strlen(&provider0));
+
+ infof(data, "aws_sigv4: String to sign (enclosed in []) - [%s]",
+ str_to_sign);
- secret = aprintf("%.*s4%s", (int)Curl_strlen(&provider0),
- Curl_str(&provider0), data->state.aptr.passwd ?
+ secret = aprintf("%.*s4%s", (int)curlx_strlen(&provider0),
+ curlx_str(&provider0), data->state.aptr.passwd ?
data->state.aptr.passwd : "");
if(!secret)
goto fail;
/* make provider0 part done uppercase */
- Curl_strntoupper(secret, Curl_str(&provider0), Curl_strlen(&provider0));
+ Curl_strntoupper(secret, curlx_str(&provider0), curlx_strlen(&provider0));
HMAC_SHA256(secret, strlen(secret), date, strlen(date), sign0);
HMAC_SHA256(sign0, sizeof(sign0),
- Curl_str(&region), Curl_strlen(&region), sign1);
+ curlx_str(&region), curlx_strlen(&region), sign1);
HMAC_SHA256(sign1, sizeof(sign1),
- Curl_str(&service), Curl_strlen(&service), sign0);
+ curlx_str(&service), curlx_strlen(&service), sign0);
HMAC_SHA256(sign0, sizeof(sign0), request_type, strlen(request_type), sign1);
HMAC_SHA256(sign1, sizeof(sign1), str_to_sign, strlen(str_to_sign), sign0);
sha256_to_hex(sha_hex, sign0);
+ infof(data, "aws_sigv4: Signature - %s", sha_hex);
+
auth_headers = aprintf("Authorization: %.*s4-HMAC-SHA256 "
"Credential=%s/%s, "
"SignedHeaders=%s, "
@@ -886,10 +944,10 @@ CURLcode Curl_output_aws_sigv4(struct Curl_easy *data)
*/
"%s"
"%s", /* optional sha256 header includes \r\n */
- (int)Curl_strlen(&provider0), Curl_str(&provider0),
+ (int)curlx_strlen(&provider0), curlx_str(&provider0),
user,
credential_scope,
- Curl_dyn_ptr(&signed_headers),
+ curlx_dyn_ptr(&signed_headers),
sha_hex,
date_header ? date_header : "",
content_sha256_hdr);
@@ -898,7 +956,7 @@ CURLcode Curl_output_aws_sigv4(struct Curl_easy *data)
}
/* provider 0 uppercase */
Curl_strntoupper(&auth_headers[sizeof("Authorization: ") - 1],
- Curl_str(&provider0), Curl_strlen(&provider0));
+ curlx_str(&provider0), curlx_strlen(&provider0));
free(data->state.aptr.userpwd);
data->state.aptr.userpwd = auth_headers;
@@ -906,10 +964,10 @@ CURLcode Curl_output_aws_sigv4(struct Curl_easy *data)
result = CURLE_OK;
fail:
- Curl_dyn_free(&canonical_query);
- Curl_dyn_free(&canonical_path);
- Curl_dyn_free(&canonical_headers);
- Curl_dyn_free(&signed_headers);
+ curlx_dyn_free(&canonical_query);
+ curlx_dyn_free(&canonical_path);
+ curlx_dyn_free(&canonical_headers);
+ curlx_dyn_free(&signed_headers);
free(canonical_request);
free(request_type);
free(credential_scope);
@@ -919,4 +977,176 @@ fail:
return result;
}
+/*
+* Frees all allocated strings in a dynbuf pair array, and the dynbuf itself
+*/
+
+static void pair_array_free(struct pair *pair_array, size_t num_elements)
+{
+ size_t index;
+
+ for(index = 0; index != num_elements; index++) {
+ curlx_dyn_free(&pair_array[index].key);
+ curlx_dyn_free(&pair_array[index].value);
+ }
+
+}
+
+/*
+* Frees all allocated strings in a split dynbuf, and the dynbuf itself
+*/
+
+static void dyn_array_free(struct dynbuf *db, size_t num_elements)
+{
+ size_t index;
+
+ for(index = 0; index < num_elements; index++)
+ curlx_dyn_free((&db[index]));
+}
+
+/*
+* Splits source string by SPLIT_BY, and creates an array of dynbuf in db.
+* db is initialized by this function.
+* Caller is responsible for freeing the array elements with dyn_array_free
+*/
+
+#define SPLIT_BY '&'
+
+static CURLcode split_to_dyn_array(const char *source,
+ struct dynbuf db[MAX_QUERY_COMPONENTS],
+ size_t *num_splits_out)
+{
+ CURLcode result = CURLE_OK;
+ size_t len = strlen(source);
+ size_t pos; /* Position in result buffer */
+ size_t start = 0; /* Start of current segment */
+ size_t segment_length = 0;
+ size_t index = 0;
+ size_t num_splits = 0;
+
+ /* Split source_ptr on SPLIT_BY and store the segment offsets and length in
+ * array */
+ for(pos = 0; pos < len; pos++) {
+ if(source[pos] == SPLIT_BY) {
+ if(segment_length) {
+ curlx_dyn_init(&db[index], segment_length + 1);
+ result = curlx_dyn_addn(&db[index], &source[start],
+ segment_length);
+ if(result)
+ goto fail;
+
+ segment_length = 0;
+ index++;
+ if(++num_splits == MAX_QUERY_COMPONENTS) {
+ result = CURLE_TOO_LARGE;
+ goto fail;
+ }
+ }
+ start = pos + 1;
+ }
+ else {
+ segment_length++;
+ }
+ }
+
+ if(segment_length) {
+ curlx_dyn_init(&db[index], segment_length + 1);
+ result = curlx_dyn_addn(&db[index], &source[start], segment_length);
+ if(!result) {
+ if(++num_splits == MAX_QUERY_COMPONENTS)
+ result = CURLE_TOO_LARGE;
+ }
+ }
+fail:
+ *num_splits_out = num_splits;
+ return result;
+}
+
+
+static bool is_reserved_char(const char c)
+{
+ return (ISALNUM(c) || ISURLPUNTCS(c));
+}
+
+static CURLcode uri_encode_path(struct Curl_str *original_path,
+ struct dynbuf *new_path)
+{
+ const char *p = curlx_str(original_path);
+ size_t i;
+
+ for(i = 0; i < curlx_strlen(original_path); i++) {
+ /* Do not encode slashes or unreserved chars from RFC 3986 */
+ CURLcode result = CURLE_OK;
+ unsigned char c = p[i];
+ if(is_reserved_char(c) || c == '/')
+ result = curlx_dyn_addn(new_path, &c, 1);
+ else
+ result = curlx_dyn_addf(new_path, "%%%02X", c);
+ if(result)
+ return result;
+ }
+
+ return CURLE_OK;
+}
+
+
+static CURLcode encode_query_component(char *component, size_t len,
+ struct dynbuf *db)
+{
+ size_t i;
+ for(i = 0; i < len; i++) {
+ CURLcode result = CURLE_OK;
+ unsigned char this_char = component[i];
+
+ if(is_reserved_char(this_char))
+ /* Escape unreserved chars from RFC 3986 */
+ result = curlx_dyn_addn(db, &this_char, 1);
+ else if(this_char == '+')
+ /* Encode '+' as space */
+ result = curlx_dyn_add(db, "%20");
+ else
+ result = curlx_dyn_addf(db, "%%%02X", this_char);
+ if(result)
+ return result;
+ }
+
+ return CURLE_OK;
+}
+
+/*
+* Populates a dynbuf containing url_encode(url_decode(in))
+*/
+
+static CURLcode http_aws_decode_encode(const char *in, size_t in_len,
+ struct dynbuf *out)
+{
+ char *out_s;
+ size_t out_s_len;
+ CURLcode result =
+ Curl_urldecode(in, in_len, &out_s, &out_s_len, REJECT_NADA);
+
+ if(!result) {
+ result = encode_query_component(out_s, out_s_len, out);
+ Curl_safefree(out_s);
+ }
+ return result;
+}
+
+static bool should_urlencode(struct Curl_str *service_name)
+{
+ /*
+ * These services require unmodified (not additionally url encoded) URL
+ * paths.
+ * should_urlencode == true is equivalent to should_urlencode_uri_path
+ * from the AWS SDK. Urls are already normalized by the curl url parser
+ */
+
+ if(curlx_str_cmp(service_name, "s3") ||
+ curlx_str_cmp(service_name, "s3-express") ||
+ curlx_str_cmp(service_name, "s3-outposts")) {
+ return false;
+ }
+ return true;
+}
+
#endif /* !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_AWS) */
diff --git a/libs/libcurl/src/http_aws_sigv4.h b/libs/libcurl/src/http_aws_sigv4.h
index 7d55ba5251..79865fe715 100644
--- a/libs/libcurl/src/http_aws_sigv4.h
+++ b/libs/libcurl/src/http_aws_sigv4.h
@@ -24,8 +24,18 @@
*
***************************************************************************/
#include "curl_setup.h"
+#include "curlx/dynbuf.h"
+#include "urldata.h"
+#include "curlx/strparse.h"
/* this is for creating aws_sigv4 header output */
CURLcode Curl_output_aws_sigv4(struct Curl_easy *data);
+#ifdef UNITTESTS
+UNITTEST CURLcode canon_path(const char *q, size_t len,
+ struct dynbuf *new_path,
+ bool normalize);
+UNITTEST CURLcode canon_query(const char *query, struct dynbuf *dq);
+#endif
+
#endif /* HEADER_CURL_HTTP_AWS_SIGV4_H */
diff --git a/libs/libcurl/src/http_chunks.c b/libs/libcurl/src/http_chunks.c
index e1a77e557c..1180c0bcfa 100644
--- a/libs/libcurl/src/http_chunks.c
+++ b/libs/libcurl/src/http_chunks.c
@@ -30,12 +30,12 @@
#include "curl_printf.h"
#include "curl_trc.h"
#include "sendf.h" /* for the client write stuff */
-#include "dynbuf.h"
+#include "curlx/dynbuf.h"
#include "content_encoding.h"
#include "http.h"
#include "multiif.h"
-#include "strparse.h"
-#include "warnless.h"
+#include "curlx/strparse.h"
+#include "curlx/warnless.h"
/* The last #include files should be: */
#include "curl_memory.h"
@@ -85,7 +85,7 @@ void Curl_httpchunk_init(struct Curl_easy *data, struct Curl_chunker *ch,
ch->hexindex = 0; /* start at 0 */
ch->state = CHUNK_HEX; /* we get hex first! */
ch->last_code = CHUNKE_OK;
- Curl_dyn_init(&ch->trailer, DYN_H1_TRAILER);
+ curlx_dyn_init(&ch->trailer, DYN_H1_TRAILER);
ch->ignore_body = ignore_body;
}
@@ -96,14 +96,14 @@ void Curl_httpchunk_reset(struct Curl_easy *data, struct Curl_chunker *ch,
ch->hexindex = 0; /* start at 0 */
ch->state = CHUNK_HEX; /* we get hex first! */
ch->last_code = CHUNKE_OK;
- Curl_dyn_reset(&ch->trailer);
+ curlx_dyn_reset(&ch->trailer);
ch->ignore_body = ignore_body;
}
void Curl_httpchunk_free(struct Curl_easy *data, struct Curl_chunker *ch)
{
(void)data;
- Curl_dyn_free(&ch->trailer);
+ curlx_dyn_free(&ch->trailer);
}
bool Curl_httpchunk_is_done(struct Curl_easy *data, struct Curl_chunker *ch)
@@ -170,7 +170,7 @@ static CURLcode httpchunk_readwrite(struct Curl_easy *data,
/* blen and buf are unmodified */
ch->hexbuffer[ch->hexindex] = 0;
p = &ch->hexbuffer[0];
- if(Curl_str_hex(&p, &ch->datasize, CURL_OFF_T_MAX)) {
+ if(curlx_str_hex(&p, &ch->datasize, CURL_OFF_T_MAX)) {
failf(data, "invalid chunk size: '%s'", ch->hexbuffer);
ch->state = CHUNK_FAILED;
ch->last_code = CHUNKE_ILLEGAL_HEX;
@@ -251,21 +251,20 @@ static CURLcode httpchunk_readwrite(struct Curl_easy *data,
case CHUNK_TRAILER:
if((*buf == 0x0d) || (*buf == 0x0a)) {
- char *tr = Curl_dyn_ptr(&ch->trailer);
+ char *tr = curlx_dyn_ptr(&ch->trailer);
/* this is the end of a trailer, but if the trailer was zero bytes
there was no trailer and we move on */
if(tr) {
- size_t trlen;
- result = Curl_dyn_addn(&ch->trailer, STRCONST("\x0d\x0a"));
+ result = curlx_dyn_addn(&ch->trailer, STRCONST("\x0d\x0a"));
if(result) {
ch->state = CHUNK_FAILED;
ch->last_code = CHUNKE_OUT_OF_MEMORY;
return result;
}
- tr = Curl_dyn_ptr(&ch->trailer);
- trlen = Curl_dyn_len(&ch->trailer);
+ tr = curlx_dyn_ptr(&ch->trailer);
if(!data->set.http_te_skip) {
+ size_t trlen = curlx_dyn_len(&ch->trailer);
if(cw_next)
result = Curl_cwriter_write(data, cw_next,
CLIENTWRITE_HEADER|
@@ -282,7 +281,7 @@ static CURLcode httpchunk_readwrite(struct Curl_easy *data,
return result;
}
}
- Curl_dyn_reset(&ch->trailer);
+ curlx_dyn_reset(&ch->trailer);
ch->state = CHUNK_TRAILER_CR;
if(*buf == 0x0a)
/* already on the LF */
@@ -295,7 +294,7 @@ static CURLcode httpchunk_readwrite(struct Curl_easy *data,
}
}
else {
- result = Curl_dyn_addn(&ch->trailer, buf, 1);
+ result = curlx_dyn_addn(&ch->trailer, buf, 1);
if(result) {
ch->state = CHUNK_FAILED;
ch->last_code = CHUNKE_OUT_OF_MEMORY;
diff --git a/libs/libcurl/src/http_chunks.h b/libs/libcurl/src/http_chunks.h
index e124882203..6c05d76cb4 100644
--- a/libs/libcurl/src/http_chunks.h
+++ b/libs/libcurl/src/http_chunks.h
@@ -26,7 +26,7 @@
#ifndef CURL_DISABLE_HTTP
-#include "dynbuf.h"
+#include "curlx/dynbuf.h"
struct connectdata;
diff --git a/libs/libcurl/src/http_digest.c b/libs/libcurl/src/http_digest.c
index 1b4c6109a4..2dee57057e 100644
--- a/libs/libcurl/src/http_digest.c
+++ b/libs/libcurl/src/http_digest.c
@@ -30,7 +30,7 @@
#include "strcase.h"
#include "vauth/vauth.h"
#include "http_digest.h"
-#include "strparse.h"
+#include "curlx/strparse.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
@@ -63,7 +63,7 @@ CURLcode Curl_input_digest(struct Curl_easy *data,
return CURLE_BAD_CONTENT_ENCODING;
header += strlen("Digest");
- Curl_str_passblanks(&header);
+ curlx_str_passblanks(&header);
return Curl_auth_decode_digest_http_message(header, digest);
}
diff --git a/libs/libcurl/src/http_negotiate.c b/libs/libcurl/src/http_negotiate.c
index 4ee77718c4..ffa6906b74 100644
--- a/libs/libcurl/src/http_negotiate.c
+++ b/libs/libcurl/src/http_negotiate.c
@@ -32,7 +32,7 @@
#include "http_negotiate.h"
#include "vauth/vauth.h"
#include "vtls/vtls.h"
-#include "strparse.h"
+#include "curlx/strparse.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
@@ -87,7 +87,7 @@ CURLcode Curl_input_negotiate(struct Curl_easy *data, struct connectdata *conn,
/* Obtain the input token, if any */
header += strlen("Negotiate");
- Curl_str_passblanks(&header);
+ curlx_str_passblanks(&header);
len = strlen(header);
neg_ctx->havenegdata = len != 0;
@@ -110,8 +110,8 @@ CURLcode Curl_input_negotiate(struct Curl_easy *data, struct connectdata *conn,
#endif
/* Check if the connection is using SSL and get the channel binding data */
#ifdef HAVE_GSSAPI
- Curl_dyn_init(&neg_ctx->channel_binding_data, SSL_CB_MAX_SIZE + 1);
#ifdef USE_SSL
+ curlx_dyn_init(&neg_ctx->channel_binding_data, SSL_CB_MAX_SIZE + 1);
if(Curl_conn_is_ssl(conn, FIRSTSOCKET)) {
result = Curl_ssl_get_channel_binding(
data, FIRSTSOCKET, &neg_ctx->channel_binding_data);
@@ -120,6 +120,8 @@ CURLcode Curl_input_negotiate(struct Curl_easy *data, struct connectdata *conn,
return result;
}
}
+#else
+ curlx_dyn_init(&neg_ctx->channel_binding_data, 1);
#endif /* USE_SSL */
#endif /* HAVE_GSSAPI */
@@ -128,7 +130,7 @@ CURLcode Curl_input_negotiate(struct Curl_easy *data, struct connectdata *conn,
host, header, neg_ctx);
#ifdef HAVE_GSSAPI
- Curl_dyn_free(&neg_ctx->channel_binding_data);
+ curlx_dyn_free(&neg_ctx->channel_binding_data);
#endif
if(result)
diff --git a/libs/libcurl/src/http_ntlm.c b/libs/libcurl/src/http_ntlm.c
index cbde614da2..21d1845286 100644
--- a/libs/libcurl/src/http_ntlm.c
+++ b/libs/libcurl/src/http_ntlm.c
@@ -38,10 +38,10 @@
#include "strcase.h"
#include "http_ntlm.h"
#include "curl_ntlm_core.h"
-#include "curl_base64.h"
+#include "curlx/base64.h"
#include "vauth/vauth.h"
#include "url.h"
-#include "strparse.h"
+#include "curlx/strparse.h"
/* SSL backend-specific #if branches in this file must be kept in the order
documented in curl_ntlm_core. */
@@ -71,12 +71,12 @@ CURLcode Curl_input_ntlm(struct Curl_easy *data,
if(checkprefix("NTLM", header)) {
header += strlen("NTLM");
- Curl_str_passblanks(&header);
+ curlx_str_passblanks(&header);
if(*header) {
unsigned char *hdr;
size_t hdrlen;
- result = Curl_base64_decode(header, &hdr, &hdrlen);
+ result = curlx_base64_decode(header, &hdr, &hdrlen);
if(!result) {
struct bufref hdrbuf;
@@ -205,7 +205,7 @@ CURLcode Curl_output_ntlm(struct Curl_easy *data, bool proxy)
ntlm, &ntlmmsg);
if(!result) {
DEBUGASSERT(Curl_bufref_len(&ntlmmsg) != 0);
- result = Curl_base64_encode((const char *) Curl_bufref_ptr(&ntlmmsg),
+ result = curlx_base64_encode((const char *) Curl_bufref_ptr(&ntlmmsg),
Curl_bufref_len(&ntlmmsg), &base64, &len);
if(!result) {
free(*allocuserpwd);
@@ -224,8 +224,8 @@ CURLcode Curl_output_ntlm(struct Curl_easy *data, bool proxy)
result = Curl_auth_create_ntlm_type3_message(data, userp, passwdp,
ntlm, &ntlmmsg);
if(!result && Curl_bufref_len(&ntlmmsg)) {
- result = Curl_base64_encode((const char *) Curl_bufref_ptr(&ntlmmsg),
- Curl_bufref_len(&ntlmmsg), &base64, &len);
+ result = curlx_base64_encode((const char *) Curl_bufref_ptr(&ntlmmsg),
+ Curl_bufref_len(&ntlmmsg), &base64, &len);
if(!result) {
free(*allocuserpwd);
*allocuserpwd = aprintf("%sAuthorization: NTLM %s\r\n",
diff --git a/libs/libcurl/src/http_proxy.c b/libs/libcurl/src/http_proxy.c
index 58a157b391..a2fb414a0c 100644
--- a/libs/libcurl/src/http_proxy.c
+++ b/libs/libcurl/src/http_proxy.c
@@ -38,12 +38,12 @@
#include "cf-h1-proxy.h"
#include "cf-h2-proxy.h"
#include "connect.h"
-#include "curlx.h"
+#include "strcase.h"
#include "vtls/vtls.h"
#include "transfer.h"
#include "multiif.h"
#include "vauth/vauth.h"
-#include "strparse.h"
+#include "curlx/strparse.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
@@ -109,7 +109,7 @@ static CURLcode dynhds_add_custom(struct Curl_easy *data,
name = headers->data;
namelen = ptr - headers->data;
ptr++; /* pass the colon */
- Curl_str_passblanks(&ptr);
+ curlx_str_passblanks(&ptr);
if(*ptr) {
value = ptr;
valuelen = strlen(value);
@@ -131,7 +131,7 @@ static CURLcode dynhds_add_custom(struct Curl_easy *data,
name = headers->data;
namelen = ptr - headers->data;
ptr++; /* pass the semicolon */
- Curl_str_passblanks(&ptr);
+ curlx_str_passblanks(&ptr);
if(!*ptr) {
/* quirk #2, send an empty header */
value = "";
diff --git a/libs/libcurl/src/httpsrr.c b/libs/libcurl/src/httpsrr.c
index a948361ba4..8111d0fc6e 100644
--- a/libs/libcurl/src/httpsrr.c
+++ b/libs/libcurl/src/httpsrr.c
@@ -38,76 +38,67 @@
#include "curl_memory.h"
#include "memdebug.h"
-CURLcode Curl_httpsrr_decode_alpn(const unsigned char *cp, size_t len,
- unsigned char *alpns)
+#define MAX_ALPN_LENGTH 255
+
+static CURLcode httpsrr_decode_alpn(const char *cp, size_t len,
+ unsigned char *alpns)
{
/*
- * spec here is as per RFC 9460, section-7.1.1
- * encoding is a concatenated list of strings each preceded by a one
- * octet length
- * output is comma-sep list of the strings
- * implementations may or may not handle quoting of comma within
- * string values, so we might see a comma within the wire format
- * version of a string, in which case we will precede that by a
- * backslash - same goes for a backslash character, and of course
- * we need to use two backslashes in strings when we mean one;-)
+ * The wire-format value for "alpn" consists of at least one alpn-id
+ * prefixed by its length as a single octet, and these length-value pairs
+ * are concatenated to form the SvcParamValue. These pairs MUST exactly fill
+ * the SvcParamValue; otherwise, the SvcParamValue is malformed.
*/
- struct dynbuf dval;
int idnum = 0;
- Curl_dyn_init(&dval, DYN_DOH_RESPONSE);
while(len > 0) {
size_t tlen = (size_t) *cp++;
- size_t i;
enum alpnid id;
len--;
if(tlen > len)
- goto err;
- /* add escape char if needed, clunky but easier to read */
- for(i = 0; i != tlen; i++) {
- if('\\' == *cp || ',' == *cp) {
- if(Curl_dyn_addn(&dval, "\\", 1))
- goto err;
- }
- if(Curl_dyn_addn(&dval, cp++, 1))
- goto err;
- }
- len -= tlen;
+ return CURLE_BAD_CONTENT_ENCODING;
/* we only store ALPN ids we know about */
- id = Curl_alpn2alpnid(Curl_dyn_ptr(&dval), Curl_dyn_len(&dval));
+ id = Curl_alpn2alpnid(cp, tlen);
if(id != ALPN_none) {
if(idnum == MAX_HTTPSRR_ALPNS)
break;
- alpns[idnum++] = (unsigned char)id;
+ if(idnum && memchr(alpns, id, idnum))
+ /* this ALPN id is already stored */
+ ;
+ else
+ alpns[idnum++] = (unsigned char)id;
}
- Curl_dyn_reset(&dval);
+ cp += tlen;
+ len -= tlen;
}
- Curl_dyn_free(&dval);
if(idnum < MAX_HTTPSRR_ALPNS)
alpns[idnum] = ALPN_none; /* terminate the list */
return CURLE_OK;
-err:
- Curl_dyn_free(&dval);
- return CURLE_BAD_CONTENT_ENCODING;
}
CURLcode Curl_httpsrr_set(struct Curl_easy *data,
struct Curl_https_rrinfo *hi,
uint16_t rrkey, const uint8_t *val, size_t vlen)
{
+ CURLcode result = CURLE_OK;
switch(rrkey) {
+ case HTTPS_RR_CODE_MANDATORY:
+ CURL_TRC_DNS(data, "HTTPS RR MANDATORY left to implement");
+ break;
case HTTPS_RR_CODE_ALPN: /* str_list */
- Curl_httpsrr_decode_alpn(val, vlen, hi->alpns);
+ result = httpsrr_decode_alpn((const char *)val, vlen, hi->alpns);
CURL_TRC_DNS(data, "HTTPS RR ALPN: %u %u %u %u",
hi->alpns[0], hi->alpns[1], hi->alpns[2], hi->alpns[3]);
break;
case HTTPS_RR_CODE_NO_DEF_ALPN:
+ if(vlen) /* no data */
+ return CURLE_BAD_FUNCTION_ARGUMENT;
hi->no_def_alpn = TRUE;
CURL_TRC_DNS(data, "HTTPS RR no-def-alpn");
break;
case HTTPS_RR_CODE_IPV4: /* addr4 list */
- if(!vlen)
+ if(!vlen || (vlen & 3)) /* the size must be 4-byte aligned */
return CURLE_BAD_FUNCTION_ARGUMENT;
hi->ipv4hints = Curl_memdup(val, vlen);
if(!hi->ipv4hints)
@@ -125,7 +116,7 @@ CURLcode Curl_httpsrr_set(struct Curl_easy *data,
CURL_TRC_DNS(data, "HTTPS RR ECH");
break;
case HTTPS_RR_CODE_IPV6: /* addr6 list */
- if(!vlen)
+ if(!vlen || (vlen & 15)) /* the size must be 16-byte aligned */
return CURLE_BAD_FUNCTION_ARGUMENT;
hi->ipv6hints = Curl_memdup(val, vlen);
if(!hi->ipv6hints)
@@ -143,7 +134,7 @@ CURLcode Curl_httpsrr_set(struct Curl_easy *data,
CURL_TRC_DNS(data, "HTTPS RR unknown code");
break;
}
- return CURLE_OK;
+ return result;
}
struct Curl_https_rrinfo *
@@ -168,31 +159,23 @@ void Curl_httpsrr_cleanup(struct Curl_https_rrinfo *rrinfo)
static CURLcode httpsrr_opt(struct Curl_easy *data,
const ares_dns_rr_t *rr,
- ares_dns_rr_key_t key, size_t idx)
+ ares_dns_rr_key_t key, size_t idx,
+ struct Curl_https_rrinfo *hinfo)
{
- size_t len = 0;
const unsigned char *val = NULL;
unsigned short code;
- struct thread_data *res = &data->state.async.thdata;
- struct Curl_https_rrinfo *hi = &res->hinfo;
+ size_t len = 0;
code = ares_dns_rr_get_opt(rr, key, idx, &val, &len);
- return Curl_httpsrr_set(data, hi, code, val, len);
+ return Curl_httpsrr_set(data, hinfo, code, val, len);
}
-void Curl_dnsrec_done_cb(void *arg, ares_status_t status,
- size_t timeouts,
- const ares_dns_record_t *dnsrec)
+CURLcode Curl_httpsrr_from_ares(struct Curl_easy *data,
+ const ares_dns_record_t *dnsrec,
+ struct Curl_https_rrinfo *hinfo)
{
- struct Curl_easy *data = arg;
CURLcode result = CURLE_OK;
size_t i;
- struct thread_data *res = &data->state.async.thdata;
-
- res->num_pending--;
- (void)timeouts;
- if((ARES_SUCCESS != status) || !dnsrec)
- return;
for(i = 0; i < ares_dns_record_rr_cnt(dnsrec, ARES_SECTION_ANSWER); i++) {
const char *target;
@@ -205,24 +188,24 @@ void Curl_dnsrec_done_cb(void *arg, ares_status_t status,
is in ServiceMode */
target = ares_dns_rr_get_str(rr, ARES_RR_HTTPS_TARGET);
if(target && target[0]) {
- res->hinfo.target = strdup(target);
- if(!res->hinfo.target) {
+ hinfo->target = strdup(target);
+ if(!hinfo->target) {
result = CURLE_OUT_OF_MEMORY;
goto out;
}
- CURL_TRC_DNS(data, "HTTPS RR target: %s", res->hinfo.target);
+ CURL_TRC_DNS(data, "HTTPS RR target: %s", hinfo->target);
}
CURL_TRC_DNS(data, "HTTPS RR priority: %u",
ares_dns_rr_get_u16(rr, ARES_RR_HTTPS_PRIORITY));
for(opt = 0; opt < ares_dns_rr_get_opt_cnt(rr, ARES_RR_HTTPS_PARAMS);
opt++) {
- result = httpsrr_opt(data, rr, ARES_RR_HTTPS_PARAMS, opt);
+ result = httpsrr_opt(data, rr, ARES_RR_HTTPS_PARAMS, opt, hinfo);
if(result)
break;
}
}
out:
- res->result = result;
+ return result;
}
#endif /* USE_ARES */
diff --git a/libs/libcurl/src/httpsrr.h b/libs/libcurl/src/httpsrr.h
index ca5a5b3936..fdcfdacf07 100644
--- a/libs/libcurl/src/httpsrr.h
+++ b/libs/libcurl/src/httpsrr.h
@@ -53,7 +53,7 @@ struct Curl_https_rrinfo {
/* store parsed alpnid entries in the array, end with ALPN_none */
int port; /* -1 means not set */
uint16_t priority;
- bool no_def_alpn; /* keytag = 2 */
+ BIT(no_def_alpn); /* keytag = 2 */
};
CURLcode Curl_httpsrr_set(struct Curl_easy *data,
@@ -68,6 +68,7 @@ void Curl_httpsrr_cleanup(struct Curl_https_rrinfo *rrinfo);
/*
* Code points for DNS wire format SvcParams as per RFC 9460
*/
+#define HTTPS_RR_CODE_MANDATORY 0x00
#define HTTPS_RR_CODE_ALPN 0x01
#define HTTPS_RR_CODE_NO_DEF_ALPN 0x02
#define HTTPS_RR_CODE_PORT 0x03
@@ -75,14 +76,10 @@ void Curl_httpsrr_cleanup(struct Curl_https_rrinfo *rrinfo);
#define HTTPS_RR_CODE_ECH 0x05
#define HTTPS_RR_CODE_IPV6 0x06
-CURLcode Curl_httpsrr_decode_alpn(const unsigned char *cp, size_t len,
- unsigned char *alpns);
-
#if defined(USE_ARES)
-void Curl_dnsrec_done_cb(void *arg, ares_status_t status,
- size_t timeouts,
- const ares_dns_record_t *dnsrec);
-
+CURLcode Curl_httpsrr_from_ares(struct Curl_easy *data,
+ const ares_dns_record_t *dnsrec,
+ struct Curl_https_rrinfo *hinfo);
#endif /* USE_ARES */
#endif /* USE_HTTPSRR */
diff --git a/libs/libcurl/src/idn.c b/libs/libcurl/src/idn.c
index 085417d051..9708745f99 100644
--- a/libs/libcurl/src/idn.c
+++ b/libs/libcurl/src/idn.c
@@ -30,8 +30,8 @@
#include "urldata.h"
#include "idn.h"
#include "sendf.h"
-#include "curl_multibyte.h"
-#include "warnless.h"
+#include "curlx/multibyte.h"
+#include "curlx/warnless.h"
#ifdef USE_LIBIDN2
#include <idn2.h>
diff --git a/libs/libcurl/src/if2ip.c b/libs/libcurl/src/if2ip.c
index 4c1b5453c1..2a4444d3e5 100644
--- a/libs/libcurl/src/if2ip.c
+++ b/libs/libcurl/src/if2ip.c
@@ -93,7 +93,7 @@ unsigned int Curl_ipv6_scope(const struct sockaddr *sa)
}
#endif
-#ifndef CURL_DISABLE_BINDLOCAL
+#if !defined(CURL_DISABLE_BINDLOCAL) || !defined(CURL_DISABLE_FTP)
#if defined(HAVE_GETIFADDRS)
@@ -162,7 +162,7 @@ if2ip_result_t Curl_if2ip(int af,
addr =
&((struct sockaddr_in *)(void *)iface->ifa_addr)->sin_addr;
res = IF2IP_FOUND;
- ip = curlx_inet_ntop(af, addr, ipstr, sizeof(ipstr));
+ ip = Curl_inet_ntop(af, addr, ipstr, sizeof(ipstr));
msnprintf(buf, buf_size, "%s%s", ip, scope);
break;
}
@@ -235,7 +235,7 @@ if2ip_result_t Curl_if2ip(int af,
s = (struct sockaddr_in *)(void *)&req.ifr_addr;
memcpy(&in, &s->sin_addr, sizeof(in));
- r = curlx_inet_ntop(s->sin_family, &in, buf, buf_size);
+ r = Curl_inet_ntop(s->sin_family, &in, buf, buf_size);
sclose(dummy);
if(!r)
@@ -266,4 +266,4 @@ if2ip_result_t Curl_if2ip(int af,
#endif
-#endif /* CURL_DISABLE_BINDLOCAL */
+#endif /* CURL_DISABLE_BINDLOCAL && CURL_DISABLE_FTP */
diff --git a/libs/libcurl/src/imap.c b/libs/libcurl/src/imap.c
index f28c1a7e75..7a84ed473b 100644
--- a/libs/libcurl/src/imap.c
+++ b/libs/libcurl/src/imap.c
@@ -36,7 +36,7 @@
***************************************************************************/
#include "curl_setup.h"
-#include "dynbuf.h"
+#include "curlx/dynbuf.h"
#ifndef CURL_DISABLE_IMAP
@@ -65,7 +65,7 @@
#include "socks.h"
#include "imap.h"
#include "mime.h"
-#include "strparse.h"
+#include "curlx/strparse.h"
#include "strcase.h"
#include "vtls/vtls.h"
#include "cfilters.h"
@@ -75,7 +75,7 @@
#include "url.h"
#include "bufref.h"
#include "curl_sasl.h"
-#include "warnless.h"
+#include "curlx/warnless.h"
#include "curl_ctype.h"
/* The last 3 #include files should be in this order */
@@ -83,8 +83,73 @@
#include "curl_memory.h"
#include "memdebug.h"
+
+/* meta key for storing protocol meta at easy handle */
+#define CURL_META_IMAP_EASY "meta:proto:imap:easy"
+/* meta key for storing protocol meta at connection */
+#define CURL_META_IMAP_CONN "meta:proto:imap:conn"
+
+typedef enum {
+ IMAP_STOP, /* do nothing state, stops the state machine */
+ IMAP_SERVERGREET, /* waiting for the initial greeting immediately after
+ a connect */
+ IMAP_CAPABILITY,
+ IMAP_STARTTLS,
+ IMAP_UPGRADETLS, /* asynchronously upgrade the connection to SSL/TLS
+ (multi mode only) */
+ IMAP_AUTHENTICATE,
+ IMAP_LOGIN,
+ IMAP_LIST,
+ IMAP_SELECT,
+ IMAP_FETCH,
+ IMAP_FETCH_FINAL,
+ IMAP_APPEND,
+ IMAP_APPEND_FINAL,
+ IMAP_SEARCH,
+ IMAP_LOGOUT,
+ IMAP_LAST /* never used */
+} imapstate;
+
+/* imap_conn is used for struct connection-oriented data */
+struct imap_conn {
+ struct pingpong pp;
+ struct SASL sasl; /* SASL-related parameters */
+ struct dynbuf dyn; /* for the IMAP commands */
+ char *mailbox; /* The last selected mailbox */
+ char *mailbox_uidvalidity; /* UIDVALIDITY parsed from select response */
+ imapstate state; /* Always use imap.c:state() to change state! */
+ char resptag[5]; /* Response tag to wait for */
+ unsigned char preftype; /* Preferred authentication type */
+ unsigned char cmdid; /* Last used command ID */
+ BIT(ssldone); /* Is connect() over SSL done? */
+ BIT(preauth); /* Is this connection PREAUTH? */
+ BIT(tls_supported); /* StartTLS capability supported by server */
+ BIT(login_disabled); /* LOGIN command disabled by server */
+ BIT(ir_supported); /* Initial response supported by server */
+};
+
+/* This IMAP struct is used in the Curl_easy. All IMAP data that is
+ connection-oriented must be in imap_conn to properly deal with the fact that
+ perhaps the Curl_easy is changed between the times the connection is
+ used. */
+struct IMAP {
+ curl_pp_transfer transfer;
+ char *mailbox; /* Mailbox to select */
+ char *uidvalidity; /* UIDVALIDITY to check in select */
+ char *uid; /* Message UID to fetch */
+ char *mindex; /* Index in mail box of mail to fetch */
+ char *section; /* Message SECTION to fetch */
+ char *partial; /* Message PARTIAL to fetch */
+ char *query; /* Query to search for */
+ char *custom; /* Custom request */
+ char *custom_params; /* Parameters for the custom request */
+};
+
+
/* Local API functions */
-static CURLcode imap_regular_transfer(struct Curl_easy *data, bool *done);
+static CURLcode imap_regular_transfer(struct Curl_easy *data,
+ struct IMAP *imap,
+ bool *done);
static CURLcode imap_do(struct Curl_easy *data, bool *done);
static CURLcode imap_done(struct Curl_easy *data, CURLcode status,
bool premature);
@@ -98,11 +163,15 @@ static CURLcode imap_doing(struct Curl_easy *data, bool *dophase_done);
static CURLcode imap_setup_connection(struct Curl_easy *data,
struct connectdata *conn);
static char *imap_atom(const char *str, bool escape_only);
-static CURLcode imap_sendf(struct Curl_easy *data, const char *fmt, ...)
- CURL_PRINTF(2, 3);
-static CURLcode imap_parse_url_options(struct connectdata *conn);
-static CURLcode imap_parse_url_path(struct Curl_easy *data);
-static CURLcode imap_parse_custom_request(struct Curl_easy *data);
+static CURLcode imap_sendf(struct Curl_easy *data,
+ struct imap_conn *imapc,
+ const char *fmt, ...) CURL_PRINTF(3, 4);
+static CURLcode imap_parse_url_options(struct connectdata *conn,
+ struct imap_conn *imapc);
+static CURLcode imap_parse_url_path(struct Curl_easy *data,
+ struct IMAP *imap);
+static CURLcode imap_parse_custom_request(struct Curl_easy *data,
+ struct IMAP *imap);
static CURLcode imap_perform_authenticate(struct Curl_easy *data,
const char *mech,
const struct bufref *initresp);
@@ -112,6 +181,7 @@ static CURLcode imap_continue_authenticate(struct Curl_easy *data,
static CURLcode imap_cancel_authenticate(struct Curl_easy *data,
const char *mech);
static CURLcode imap_get_message(struct Curl_easy *data, struct bufref *out);
+static void imap_easy_reset(struct IMAP *imap);
/*
* IMAP protocol handler.
@@ -249,12 +319,19 @@ static bool imap_matchresp(const char *line, size_t len, const char *cmd)
static bool imap_endofresp(struct Curl_easy *data, struct connectdata *conn,
const char *line, size_t len, int *resp)
{
- struct IMAP *imap = data->req.p.imap;
- struct imap_conn *imapc = &conn->proto.imapc;
- const char *id = imapc->resptag;
- size_t id_len = strlen(id);
+ struct imap_conn *imapc = Curl_conn_meta_get(conn, CURL_META_IMAP_CONN);
+ struct IMAP *imap = Curl_meta_get(data, CURL_META_IMAP_EASY);
+ const char *id;
+ size_t id_len;
+
+ DEBUGASSERT(imapc);
+ DEBUGASSERT(imap);
+ if(!imapc || !imap)
+ return FALSE;
/* Do we have a tagged command response? */
+ id = imapc->resptag;
+ id_len = strlen(id);
if(len >= id_len + 1 && !memcmp(id, line, id_len) && line[id_len] == ' ') {
line += id_len + 1;
len -= id_len + 1;
@@ -280,17 +357,17 @@ static bool imap_endofresp(struct Curl_easy *data, struct connectdata *conn,
case IMAP_LIST:
if((!imap->custom && !imap_matchresp(line, len, "LIST")) ||
- (imap->custom && !imap_matchresp(line, len, imap->custom) &&
- (!strcasecompare(imap->custom, "STORE") ||
- !imap_matchresp(line, len, "FETCH")) &&
- !strcasecompare(imap->custom, "SELECT") &&
- !strcasecompare(imap->custom, "EXAMINE") &&
- !strcasecompare(imap->custom, "SEARCH") &&
- !strcasecompare(imap->custom, "EXPUNGE") &&
- !strcasecompare(imap->custom, "LSUB") &&
- !strcasecompare(imap->custom, "UID") &&
- !strcasecompare(imap->custom, "GETQUOTAROOT") &&
- !strcasecompare(imap->custom, "NOOP")))
+ (imap->custom && !imap_matchresp(line, len, imap->custom) &&
+ (!strcasecompare(imap->custom, "STORE") ||
+ !imap_matchresp(line, len, "FETCH")) &&
+ !strcasecompare(imap->custom, "SELECT") &&
+ !strcasecompare(imap->custom, "EXAMINE") &&
+ !strcasecompare(imap->custom, "SEARCH") &&
+ !strcasecompare(imap->custom, "EXPUNGE") &&
+ !strcasecompare(imap->custom, "LSUB") &&
+ !strcasecompare(imap->custom, "UID") &&
+ !strcasecompare(imap->custom, "GETQUOTAROOT") &&
+ !strcasecompare(imap->custom, "NOOP")))
return FALSE;
break;
@@ -322,8 +399,8 @@ static bool imap_endofresp(struct Curl_easy *data, struct connectdata *conn,
a space and optionally some text as per RFC-3501 for the AUTHENTICATE and
APPEND commands and as outlined in Section 4. Examples of RFC-4959 but
some email servers ignore this and only send a single + instead. */
- if(imap && !imap->custom && ((len == 3 && line[0] == '+') ||
- (len >= 2 && !memcmp("+ ", line, 2)))) {
+ if(!imap->custom && ((len == 3 && line[0] == '+') ||
+ (len >= 2 && !memcmp("+ ", line, 2)))) {
switch(imapc->state) {
/* States which are interested in continuation responses */
case IMAP_AUTHENTICATE:
@@ -351,9 +428,16 @@ static bool imap_endofresp(struct Curl_easy *data, struct connectdata *conn,
*/
static CURLcode imap_get_message(struct Curl_easy *data, struct bufref *out)
{
- char *message = Curl_dyn_ptr(&data->conn->proto.imapc.pp.recvbuf);
- size_t len = data->conn->proto.imapc.pp.nfinal;
+ struct imap_conn *imapc =
+ Curl_conn_meta_get(data->conn, CURL_META_IMAP_CONN);
+ char *message;
+ size_t len;
+
+ if(!imapc)
+ return CURLE_FAILED_INIT;
+ message = curlx_dyn_ptr(&imapc->pp.recvbuf);
+ len = imapc->pp.nfinal;
if(len > 2) {
/* Find the start of the message */
len -= 2;
@@ -383,9 +467,10 @@ static CURLcode imap_get_message(struct Curl_easy *data, struct bufref *out)
*
* This is the ONLY way to change IMAP state!
*/
-static void imap_state(struct Curl_easy *data, imapstate newstate)
+static void imap_state(struct Curl_easy *data,
+ struct imap_conn *imapc,
+ imapstate newstate)
{
- struct imap_conn *imapc = &data->conn->proto.imapc;
#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
/* for debug purposes */
static const char * const names[]={
@@ -411,7 +496,7 @@ static void imap_state(struct Curl_easy *data, imapstate newstate)
infof(data, "IMAP %p state change from %s to %s",
(void *)imapc, names[imapc->state], names[newstate]);
#endif
-
+ (void)data;
imapc->state = newstate;
}
@@ -423,19 +508,19 @@ static void imap_state(struct Curl_easy *data, imapstate newstate)
* supported capabilities.
*/
static CURLcode imap_perform_capability(struct Curl_easy *data,
- struct connectdata *conn)
+ struct imap_conn *imapc)
{
CURLcode result = CURLE_OK;
- struct imap_conn *imapc = &conn->proto.imapc;
+
imapc->sasl.authmechs = SASL_AUTH_NONE; /* No known auth. mechanisms yet */
imapc->sasl.authused = SASL_AUTH_NONE; /* Clear the auth. mechanism used */
imapc->tls_supported = FALSE; /* Clear the TLS capability */
/* Send the CAPABILITY command */
- result = imap_sendf(data, "CAPABILITY");
+ result = imap_sendf(data, imapc, "CAPABILITY");
if(!result)
- imap_state(data, IMAP_CAPABILITY);
+ imap_state(data, imapc, IMAP_CAPABILITY);
return result;
}
@@ -446,13 +531,14 @@ static CURLcode imap_perform_capability(struct Curl_easy *data,
*
* Sends the STARTTLS command to start the upgrade to TLS.
*/
-static CURLcode imap_perform_starttls(struct Curl_easy *data)
+static CURLcode imap_perform_starttls(struct Curl_easy *data,
+ struct imap_conn *imapc)
{
/* Send the STARTTLS command */
- CURLcode result = imap_sendf(data, "STARTTLS");
+ CURLcode result = imap_sendf(data, imapc, "STARTTLS");
if(!result)
- imap_state(data, IMAP_STARTTLS);
+ imap_state(data, imapc, IMAP_STARTTLS);
return result;
}
@@ -464,11 +550,11 @@ static CURLcode imap_perform_starttls(struct Curl_easy *data)
* Performs the upgrade to TLS.
*/
static CURLcode imap_perform_upgrade_tls(struct Curl_easy *data,
+ struct imap_conn *imapc,
struct connectdata *conn)
{
#ifdef USE_SSL
/* Start the SSL connection */
- struct imap_conn *imapc = &conn->proto.imapc;
CURLcode result;
bool ssldone = FALSE;
@@ -487,12 +573,13 @@ static CURLcode imap_perform_upgrade_tls(struct Curl_easy *data,
if(!result && ssldone) {
imapc->ssldone = ssldone;
/* perform CAPA now, changes imapc->state out of IMAP_UPGRADETLS */
- result = imap_perform_capability(data, conn);
+ result = imap_perform_capability(data, imapc);
}
out:
return result;
#else
(void)data;
+ (void)imapc;
(void)conn;
return CURLE_NOT_BUILT_IN;
#endif
@@ -505,6 +592,7 @@ out:
* Sends a clear text LOGIN command to authenticate with.
*/
static CURLcode imap_perform_login(struct Curl_easy *data,
+ struct imap_conn *imapc,
struct connectdata *conn)
{
CURLcode result = CURLE_OK;
@@ -514,7 +602,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 do not */
if(!data->state.aptr.user) {
- imap_state(data, IMAP_STOP);
+ imap_state(data, imapc, IMAP_STOP);
return result;
}
@@ -524,14 +612,14 @@ static CURLcode imap_perform_login(struct Curl_easy *data,
passwd = imap_atom(conn->passwd, FALSE);
/* Send the LOGIN command */
- result = imap_sendf(data, "LOGIN %s %s", user ? user : "",
+ result = imap_sendf(data, imapc, "LOGIN %s %s", user ? user : "",
passwd ? passwd : "");
free(user);
free(passwd);
if(!result)
- imap_state(data, IMAP_LOGIN);
+ imap_state(data, imapc, IMAP_LOGIN);
return result;
}
@@ -547,16 +635,20 @@ static CURLcode imap_perform_authenticate(struct Curl_easy *data,
const char *mech,
const struct bufref *initresp)
{
+ struct imap_conn *imapc =
+ Curl_conn_meta_get(data->conn, CURL_META_IMAP_CONN);
CURLcode result = CURLE_OK;
const char *ir = (const char *) Curl_bufref_ptr(initresp);
+ if(!imapc)
+ return CURLE_FAILED_INIT;
if(ir) {
/* Send the AUTHENTICATE command with the initial response */
- result = imap_sendf(data, "AUTHENTICATE %s %s", mech, ir);
+ result = imap_sendf(data, imapc, "AUTHENTICATE %s %s", mech, ir);
}
else {
/* Send the AUTHENTICATE command */
- result = imap_sendf(data, "AUTHENTICATE %s", mech);
+ result = imap_sendf(data, imapc, "AUTHENTICATE %s", mech);
}
return result;
@@ -572,10 +664,12 @@ static CURLcode imap_continue_authenticate(struct Curl_easy *data,
const char *mech,
const struct bufref *resp)
{
- struct imap_conn *imapc = &data->conn->proto.imapc;
+ struct imap_conn *imapc =
+ Curl_conn_meta_get(data->conn, CURL_META_IMAP_CONN);
(void)mech;
-
+ if(!imapc)
+ return CURLE_FAILED_INIT;
return Curl_pp_sendf(data, &imapc->pp,
"%s", (const char *) Curl_bufref_ptr(resp));
}
@@ -589,10 +683,12 @@ static CURLcode imap_continue_authenticate(struct Curl_easy *data,
static CURLcode imap_cancel_authenticate(struct Curl_easy *data,
const char *mech)
{
- struct imap_conn *imapc = &data->conn->proto.imapc;
+ struct imap_conn *imapc =
+ Curl_conn_meta_get(data->conn, CURL_META_IMAP_CONN);
(void)mech;
-
+ if(!imapc)
+ return CURLE_FAILED_INIT;
return Curl_pp_sendf(data, &imapc->pp, "*");
}
@@ -605,17 +701,16 @@ static CURLcode imap_cancel_authenticate(struct Curl_easy *data,
* mechanism not be available between the client and server.
*/
static CURLcode imap_perform_authentication(struct Curl_easy *data,
- struct connectdata *conn)
+ struct imap_conn *imapc)
{
CURLcode result = CURLE_OK;
- struct imap_conn *imapc = &conn->proto.imapc;
saslprogress progress;
/* Check if already authenticated OR if there is enough data to authenticate
with and end the connect phase if we do not */
if(imapc->preauth ||
!Curl_sasl_can_authenticate(&imapc->sasl, data)) {
- imap_state(data, IMAP_STOP);
+ imap_state(data, imapc, IMAP_STOP);
return result;
}
@@ -624,15 +719,12 @@ static CURLcode imap_perform_authentication(struct Curl_easy *data,
if(!result) {
if(progress == SASL_INPROGRESS)
- imap_state(data, IMAP_AUTHENTICATE);
+ imap_state(data, imapc, IMAP_AUTHENTICATE);
else if(!imapc->login_disabled && (imapc->preftype & IMAP_TYPE_CLEARTEXT))
/* Perform clear text authentication */
- result = imap_perform_login(data, conn);
- else {
- /* Other mechanisms not supported */
- infof(data, "No known authentication mechanisms supported");
- result = CURLE_LOGIN_DENIED;
- }
+ result = imap_perform_login(data, imapc, data->conn);
+ else
+ result = Curl_sasl_is_blocked(&imapc->sasl, data);
}
return result;
@@ -644,14 +736,15 @@ static CURLcode imap_perform_authentication(struct Curl_easy *data,
*
* Sends a LIST command or an alternative custom request.
*/
-static CURLcode imap_perform_list(struct Curl_easy *data)
+static CURLcode imap_perform_list(struct Curl_easy *data,
+ struct imap_conn *imapc,
+ struct IMAP *imap)
{
CURLcode result = CURLE_OK;
- struct IMAP *imap = data->req.p.imap;
if(imap->custom)
/* Send the custom request */
- result = imap_sendf(data, "%s%s", imap->custom,
+ result = imap_sendf(data, imapc, "%s%s", imap->custom,
imap->custom_params ? imap->custom_params : "");
else {
/* Make sure the mailbox is in the correct atom format if necessary */
@@ -661,13 +754,13 @@ static CURLcode imap_perform_list(struct Curl_easy *data)
return CURLE_OUT_OF_MEMORY;
/* Send the LIST command */
- result = imap_sendf(data, "LIST \"%s\" *", mailbox);
+ result = imap_sendf(data, imapc, "LIST \"%s\" *", mailbox);
free(mailbox);
}
if(!result)
- imap_state(data, IMAP_LIST);
+ imap_state(data, imapc, IMAP_LIST);
return result;
}
@@ -678,12 +771,11 @@ static CURLcode imap_perform_list(struct Curl_easy *data)
*
* Sends a SELECT command to ask the server to change the selected mailbox.
*/
-static CURLcode imap_perform_select(struct Curl_easy *data)
+static CURLcode imap_perform_select(struct Curl_easy *data,
+ struct imap_conn *imapc,
+ struct IMAP *imap)
{
CURLcode result = CURLE_OK;
- struct connectdata *conn = data->conn;
- struct IMAP *imap = data->req.p.imap;
- struct imap_conn *imapc = &conn->proto.imapc;
char *mailbox;
/* Invalidate old information as we are switching mailboxes */
@@ -702,12 +794,12 @@ static CURLcode imap_perform_select(struct Curl_easy *data)
return CURLE_OUT_OF_MEMORY;
/* Send the SELECT command */
- result = imap_sendf(data, "SELECT %s", mailbox);
+ result = imap_sendf(data, imapc, "SELECT %s", mailbox);
free(mailbox);
if(!result)
- imap_state(data, IMAP_SELECT);
+ imap_state(data, imapc, IMAP_SELECT);
return result;
}
@@ -718,30 +810,31 @@ static CURLcode imap_perform_select(struct Curl_easy *data)
*
* Sends a FETCH command to initiate the download of a message.
*/
-static CURLcode imap_perform_fetch(struct Curl_easy *data)
+static CURLcode imap_perform_fetch(struct Curl_easy *data,
+ struct imap_conn *imapc,
+ struct IMAP *imap)
{
CURLcode result = CURLE_OK;
- struct IMAP *imap = data->req.p.imap;
/* Check we have a UID */
if(imap->uid) {
/* Send the FETCH command */
if(imap->partial)
- result = imap_sendf(data, "UID FETCH %s BODY[%s]<%s>",
+ result = imap_sendf(data, imapc, "UID FETCH %s BODY[%s]<%s>",
imap->uid, imap->section ? imap->section : "",
imap->partial);
else
- result = imap_sendf(data, "UID FETCH %s BODY[%s]",
+ result = imap_sendf(data, imapc, "UID FETCH %s BODY[%s]",
imap->uid, imap->section ? imap->section : "");
}
else if(imap->mindex) {
/* Send the FETCH command */
if(imap->partial)
- result = imap_sendf(data, "FETCH %s BODY[%s]<%s>",
+ result = imap_sendf(data, imapc, "FETCH %s BODY[%s]<%s>",
imap->mindex, imap->section ? imap->section : "",
imap->partial);
else
- result = imap_sendf(data, "FETCH %s BODY[%s]",
+ result = imap_sendf(data, imapc, "FETCH %s BODY[%s]",
imap->mindex, imap->section ? imap->section : "");
}
else {
@@ -749,7 +842,7 @@ static CURLcode imap_perform_fetch(struct Curl_easy *data)
return CURLE_URL_MALFORMAT;
}
if(!result)
- imap_state(data, IMAP_FETCH);
+ imap_state(data, imapc, IMAP_FETCH);
return result;
}
@@ -760,10 +853,11 @@ static CURLcode imap_perform_fetch(struct Curl_easy *data)
*
* Sends an APPEND command to initiate the upload of a message.
*/
-static CURLcode imap_perform_append(struct Curl_easy *data)
+static CURLcode imap_perform_append(struct Curl_easy *data,
+ struct imap_conn *imapc,
+ struct IMAP *imap)
{
CURLcode result = CURLE_OK;
- struct IMAP *imap = data->req.p.imap;
char *mailbox;
struct dynbuf flags;
@@ -815,7 +909,7 @@ static CURLcode imap_perform_append(struct Curl_easy *data)
return CURLE_OUT_OF_MEMORY;
/* Generate flags string and send the APPEND command */
- Curl_dyn_init(&flags, 100);
+ curlx_dyn_init(&flags, 100);
if(data->set.upload_flags) {
int i;
struct ulbits ulflag[] = {
@@ -828,33 +922,34 @@ static CURLcode imap_perform_append(struct Curl_easy *data)
};
result = CURLE_OUT_OF_MEMORY;
- if(Curl_dyn_add(&flags, " (")) {
+ if(curlx_dyn_add(&flags, " (")) {
goto cleanup;
}
for(i = 0; ulflag[i].bit; i++) {
if(data->set.upload_flags & ulflag[i].bit) {
- if((Curl_dyn_len(&flags) > 2 && Curl_dyn_add(&flags, " ")) ||
- Curl_dyn_add(&flags, "\\") || Curl_dyn_add(&flags, ulflag[i].flag))
- goto cleanup;
+ if((curlx_dyn_len(&flags) > 2 && curlx_dyn_add(&flags, " ")) ||
+ curlx_dyn_add(&flags, "\\") ||
+ curlx_dyn_add(&flags, ulflag[i].flag))
+ goto cleanup;
}
}
- if(Curl_dyn_add(&flags, ")"))
+ if(curlx_dyn_add(&flags, ")"))
goto cleanup;
}
- else if(Curl_dyn_add(&flags, ""))
+ else if(curlx_dyn_add(&flags, ""))
goto cleanup;
- result = imap_sendf(data, "APPEND %s%s {%" FMT_OFF_T "}",
- mailbox, Curl_dyn_ptr(&flags), data->state.infilesize);
+ result = imap_sendf(data, imapc, "APPEND %s%s {%" FMT_OFF_T "}",
+ mailbox, curlx_dyn_ptr(&flags), data->state.infilesize);
cleanup:
- Curl_dyn_free(&flags);
+ curlx_dyn_free(&flags);
free(mailbox);
if(!result)
- imap_state(data, IMAP_APPEND);
+ imap_state(data, imapc, IMAP_APPEND);
return result;
}
@@ -865,10 +960,11 @@ cleanup:
*
* Sends a SEARCH command.
*/
-static CURLcode imap_perform_search(struct Curl_easy *data)
+static CURLcode imap_perform_search(struct Curl_easy *data,
+ struct imap_conn *imapc,
+ struct IMAP *imap)
{
CURLcode result = CURLE_OK;
- struct IMAP *imap = data->req.p.imap;
/* Check we have a query string */
if(!imap->query) {
@@ -877,10 +973,10 @@ static CURLcode imap_perform_search(struct Curl_easy *data)
}
/* Send the SEARCH command */
- result = imap_sendf(data, "SEARCH %s", imap->query);
+ result = imap_sendf(data, imapc, "SEARCH %s", imap->query);
if(!result)
- imap_state(data, IMAP_SEARCH);
+ imap_state(data, imapc, IMAP_SEARCH);
return result;
}
@@ -891,28 +987,28 @@ static CURLcode imap_perform_search(struct Curl_easy *data)
*
* Performs the logout action prior to sclose() being called.
*/
-static CURLcode imap_perform_logout(struct Curl_easy *data)
+static CURLcode imap_perform_logout(struct Curl_easy *data,
+ struct imap_conn *imapc)
{
/* Send the LOGOUT command */
- CURLcode result = imap_sendf(data, "LOGOUT");
+ CURLcode result = imap_sendf(data, imapc, "LOGOUT");
if(!result)
- imap_state(data, IMAP_LOGOUT);
+ imap_state(data, imapc, IMAP_LOGOUT);
return result;
}
/* For the initial server greeting */
static CURLcode imap_state_servergreet_resp(struct Curl_easy *data,
+ struct imap_conn *imapc,
int imapcode,
imapstate instate)
{
- struct connectdata *conn = data->conn;
(void)instate; /* no use for this yet */
if(imapcode == IMAP_RESP_PREAUTH) {
/* PREAUTH */
- struct imap_conn *imapc = &conn->proto.imapc;
imapc->preauth = TRUE;
infof(data, "PREAUTH connection, already authenticated");
}
@@ -921,18 +1017,18 @@ static CURLcode imap_state_servergreet_resp(struct Curl_easy *data,
return CURLE_WEIRD_SERVER_REPLY;
}
- return imap_perform_capability(data, conn);
+ return imap_perform_capability(data, imapc);
}
/* For CAPABILITY responses */
static CURLcode imap_state_capability_resp(struct Curl_easy *data,
+ struct imap_conn *imapc,
int imapcode,
imapstate instate)
{
CURLcode result = CURLE_OK;
struct connectdata *conn = data->conn;
- struct imap_conn *imapc = &conn->proto.imapc;
- const char *line = Curl_dyn_ptr(&imapc->pp.recvbuf);
+ const char *line = curlx_dyn_ptr(&imapc->pp.recvbuf);
(void)instate; /* no use for this yet */
@@ -992,33 +1088,33 @@ static CURLcode imap_state_capability_resp(struct Curl_easy *data,
/* PREAUTH is not compatible with STARTTLS. */
if(imapcode == IMAP_RESP_OK && imapc->tls_supported && !imapc->preauth) {
/* Switch to TLS connection now */
- result = imap_perform_starttls(data);
+ result = imap_perform_starttls(data, imapc);
}
else if(data->set.use_ssl <= CURLUSESSL_TRY)
- result = imap_perform_authentication(data, conn);
+ result = imap_perform_authentication(data, imapc);
else {
failf(data, "STARTTLS not available.");
result = CURLE_USE_SSL_FAILED;
}
}
else
- result = imap_perform_authentication(data, conn);
+ result = imap_perform_authentication(data, imapc);
return result;
}
/* For STARTTLS responses */
static CURLcode imap_state_starttls_resp(struct Curl_easy *data,
+ struct imap_conn *imapc,
int imapcode,
imapstate instate)
{
CURLcode result = CURLE_OK;
- struct connectdata *conn = data->conn;
(void)instate; /* no use for this yet */
/* Pipelining in response is forbidden. */
- if(data->conn->proto.imapc.pp.overflow)
+ if(imapc->pp.overflow)
return CURLE_WEIRD_SERVER_REPLY;
if(imapcode != IMAP_RESP_OK) {
@@ -1027,22 +1123,21 @@ static CURLcode imap_state_starttls_resp(struct Curl_easy *data,
result = CURLE_USE_SSL_FAILED;
}
else
- result = imap_perform_authentication(data, conn);
+ result = imap_perform_authentication(data, imapc);
}
else
- imap_state(data, IMAP_UPGRADETLS);
+ imap_state(data, imapc, IMAP_UPGRADETLS);
return result;
}
/* For SASL authentication responses */
static CURLcode imap_state_auth_resp(struct Curl_easy *data,
- struct connectdata *conn,
+ struct imap_conn *imapc,
int imapcode,
imapstate instate)
{
CURLcode result = CURLE_OK;
- struct imap_conn *imapc = &conn->proto.imapc;
saslprogress progress;
(void)instate; /* no use for this yet */
@@ -1051,12 +1146,12 @@ static CURLcode imap_state_auth_resp(struct Curl_easy *data,
if(!result)
switch(progress) {
case SASL_DONE:
- imap_state(data, IMAP_STOP); /* Authenticated */
+ imap_state(data, imapc, IMAP_STOP); /* Authenticated */
break;
case SASL_IDLE: /* No mechanism left after cancellation */
if((!imapc->login_disabled) && (imapc->preftype & IMAP_TYPE_CLEARTEXT))
/* Perform clear text authentication */
- result = imap_perform_login(data, conn);
+ result = imap_perform_login(data, imapc, data->conn);
else {
failf(data, "Authentication cancelled");
result = CURLE_LOGIN_DENIED;
@@ -1071,6 +1166,7 @@ static CURLcode imap_state_auth_resp(struct Curl_easy *data,
/* For LOGIN responses */
static CURLcode imap_state_login_resp(struct Curl_easy *data,
+ struct imap_conn *imapc,
int imapcode,
imapstate instate)
{
@@ -1083,19 +1179,20 @@ static CURLcode imap_state_login_resp(struct Curl_easy *data,
}
else
/* End of connect phase */
- imap_state(data, IMAP_STOP);
+ imap_state(data, imapc, IMAP_STOP);
return result;
}
/* For LIST and SEARCH responses */
static CURLcode imap_state_listsearch_resp(struct Curl_easy *data,
+ struct imap_conn *imapc,
int imapcode,
imapstate instate)
{
CURLcode result = CURLE_OK;
- char *line = Curl_dyn_ptr(&data->conn->proto.imapc.pp.recvbuf);
- size_t len = data->conn->proto.imapc.pp.nfinal;
+ char *line = curlx_dyn_ptr(&imapc->pp.recvbuf);
+ size_t len = imapc->pp.nfinal;
(void)instate; /* No use for this yet */
@@ -1105,20 +1202,20 @@ static CURLcode imap_state_listsearch_resp(struct Curl_easy *data,
result = CURLE_QUOTE_ERROR;
else
/* End of DO phase */
- imap_state(data, IMAP_STOP);
+ imap_state(data, imapc, IMAP_STOP);
return result;
}
/* For SELECT responses */
-static CURLcode imap_state_select_resp(struct Curl_easy *data, int imapcode,
+static CURLcode imap_state_select_resp(struct Curl_easy *data,
+ struct imap_conn *imapc,
+ struct IMAP *imap,
+ int imapcode,
imapstate instate)
{
CURLcode result = CURLE_OK;
- struct connectdata *conn = data->conn;
- struct IMAP *imap = data->req.p.imap;
- struct imap_conn *imapc = &conn->proto.imapc;
- const char *line = Curl_dyn_ptr(&data->conn->proto.imapc.pp.recvbuf);
+ const char *line = curlx_dyn_ptr(&imapc->pp.recvbuf);
(void)instate; /* no use for this yet */
@@ -1131,11 +1228,11 @@ static CURLcode imap_state_select_resp(struct Curl_easy *data, int imapcode,
len++;
if(len && (p[len] == ']')) {
struct dynbuf uid;
- Curl_dyn_init(&uid, 20);
- if(Curl_dyn_addn(&uid, p, len))
+ curlx_dyn_init(&uid, 20);
+ if(curlx_dyn_addn(&uid, p, len))
return CURLE_OUT_OF_MEMORY;
free(imapc->mailbox_uidvalidity);
- imapc->mailbox_uidvalidity = Curl_dyn_ptr(&uid);
+ imapc->mailbox_uidvalidity = curlx_dyn_ptr(&uid);
}
}
}
@@ -1154,11 +1251,11 @@ static CURLcode imap_state_select_resp(struct Curl_easy *data, int imapcode,
return CURLE_OUT_OF_MEMORY;
if(imap->custom)
- result = imap_perform_list(data);
+ result = imap_perform_list(data, imapc, imap);
else if(imap->query)
- result = imap_perform_search(data);
+ result = imap_perform_search(data, imapc, imap);
else
- result = imap_perform_fetch(data);
+ result = imap_perform_fetch(data, imapc, imap);
}
}
else {
@@ -1171,14 +1268,14 @@ static CURLcode imap_state_select_resp(struct Curl_easy *data, int imapcode,
/* For the (first line of the) FETCH responses */
static CURLcode imap_state_fetch_resp(struct Curl_easy *data,
- struct connectdata *conn, int imapcode,
+ struct imap_conn *imapc,
+ int imapcode,
imapstate instate)
{
CURLcode result = CURLE_OK;
- struct imap_conn *imapc = &conn->proto.imapc;
struct pingpong *pp = &imapc->pp;
- const char *ptr = Curl_dyn_ptr(&data->conn->proto.imapc.pp.recvbuf);
- size_t len = data->conn->proto.imapc.pp.nfinal;
+ const char *ptr = curlx_dyn_ptr(&imapc->pp.recvbuf);
+ size_t len = imapc->pp.nfinal;
bool parsed = FALSE;
curl_off_t size = 0;
@@ -1186,7 +1283,7 @@ static CURLcode imap_state_fetch_resp(struct Curl_easy *data,
if(imapcode != '*') {
Curl_pgrsSetDownloadSize(data, -1);
- imap_state(data, IMAP_STOP);
+ imap_state(data, imapc, IMAP_STOP);
return CURLE_REMOTE_FILE_NOT_FOUND;
}
@@ -1195,8 +1292,8 @@ static CURLcode imap_state_fetch_resp(struct Curl_easy *data,
ptr = memchr(ptr, '{', len);
if(ptr) {
ptr++;
- if(!Curl_str_number(&ptr, &size, CURL_OFF_T_MAX) &&
- !Curl_str_single(&ptr, '}'))
+ if(!curlx_str_number(&ptr, &size, CURL_OFF_T_MAX) &&
+ !curlx_str_single(&ptr, '}'))
parsed = TRUE;
}
@@ -1211,7 +1308,7 @@ static CURLcode imap_state_fetch_resp(struct Curl_easy *data,
size_t chunk = pp->overflow;
/* keep only the overflow */
- Curl_dyn_tail(&pp->recvbuf, chunk);
+ curlx_dyn_tail(&pp->recvbuf, chunk);
pp->nfinal = 0; /* done */
if(chunk > (size_t)size)
@@ -1220,11 +1317,11 @@ static CURLcode imap_state_fetch_resp(struct Curl_easy *data,
if(!chunk) {
/* no size, we are done with the data */
- imap_state(data, IMAP_STOP);
+ imap_state(data, imapc, IMAP_STOP);
return CURLE_OK;
}
result = Curl_client_write(data, CLIENTWRITE_BODY,
- Curl_dyn_ptr(&pp->recvbuf), chunk);
+ curlx_dyn_ptr(&pp->recvbuf), chunk);
if(result)
return result;
@@ -1235,12 +1332,12 @@ static CURLcode imap_state_fetch_resp(struct Curl_easy *data,
if(pp->overflow > chunk) {
/* remember the remaining trailing overflow data */
pp->overflow -= chunk;
- Curl_dyn_tail(&pp->recvbuf, pp->overflow);
+ curlx_dyn_tail(&pp->recvbuf, pp->overflow);
}
else {
pp->overflow = 0; /* handled */
/* Free the cache */
- Curl_dyn_reset(&pp->recvbuf);
+ curlx_dyn_reset(&pp->recvbuf);
}
}
@@ -1263,13 +1360,14 @@ static CURLcode imap_state_fetch_resp(struct Curl_easy *data,
}
/* End of DO phase */
- imap_state(data, IMAP_STOP);
+ imap_state(data, imapc, IMAP_STOP);
return result;
}
/* For final FETCH responses performed after the download */
static CURLcode imap_state_fetch_final_resp(struct Curl_easy *data,
+ struct imap_conn *imapc,
int imapcode,
imapstate instate)
{
@@ -1281,13 +1379,15 @@ static CURLcode imap_state_fetch_final_resp(struct Curl_easy *data,
result = CURLE_WEIRD_SERVER_REPLY;
else
/* End of DONE phase */
- imap_state(data, IMAP_STOP);
+ imap_state(data, imapc, IMAP_STOP);
return result;
}
/* For APPEND responses */
-static CURLcode imap_state_append_resp(struct Curl_easy *data, int imapcode,
+static CURLcode imap_state_append_resp(struct Curl_easy *data,
+ struct imap_conn *imapc,
+ int imapcode,
imapstate instate)
{
CURLcode result = CURLE_OK;
@@ -1304,7 +1404,7 @@ static CURLcode imap_state_append_resp(struct Curl_easy *data, int imapcode,
Curl_xfer_setup1(data, CURL_XFER_SEND, -1, FALSE);
/* End of DO phase */
- imap_state(data, IMAP_STOP);
+ imap_state(data, imapc, IMAP_STOP);
}
return result;
@@ -1312,6 +1412,7 @@ static CURLcode imap_state_append_resp(struct Curl_easy *data, int imapcode,
/* For final APPEND responses performed after the upload */
static CURLcode imap_state_append_final_resp(struct Curl_easy *data,
+ struct imap_conn *imapc,
int imapcode,
imapstate instate)
{
@@ -1323,25 +1424,29 @@ static CURLcode imap_state_append_final_resp(struct Curl_easy *data,
result = CURLE_UPLOAD_FAILED;
else
/* End of DONE phase */
- imap_state(data, IMAP_STOP);
+ imap_state(data, imapc, IMAP_STOP);
return result;
}
-static CURLcode imap_statemachine(struct Curl_easy *data,
- struct connectdata *conn)
+static CURLcode imap_pp_statemachine(struct Curl_easy *data,
+ struct connectdata *conn)
{
CURLcode result = CURLE_OK;
int imapcode;
- struct imap_conn *imapc = &conn->proto.imapc;
- struct pingpong *pp = &imapc->pp;
+ struct imap_conn *imapc = Curl_conn_meta_get(conn, CURL_META_IMAP_CONN);
+ struct IMAP *imap = Curl_meta_get(data, CURL_META_IMAP_EASY);
+ struct pingpong *pp;
size_t nread = 0;
- (void)data;
+ (void)data;
+ if(!imapc || !imap)
+ return CURLE_FAILED_INIT;
+ pp = &imapc->pp;
/* Busy upgrading the connection; right now all I/O is SSL/TLS, not IMAP */
upgrade_tls:
if(imapc->state == IMAP_UPGRADETLS) {
- result = imap_perform_upgrade_tls(data, conn);
+ result = imap_perform_upgrade_tls(data, imapc, conn);
if(result || (imapc->state == IMAP_UPGRADETLS))
return result;
}
@@ -1366,15 +1471,16 @@ upgrade_tls:
/* We have now received a full IMAP server response */
switch(imapc->state) {
case IMAP_SERVERGREET:
- result = imap_state_servergreet_resp(data, imapcode, imapc->state);
+ result = imap_state_servergreet_resp(data, imapc,
+ imapcode, imapc->state);
break;
case IMAP_CAPABILITY:
- result = imap_state_capability_resp(data, imapcode, imapc->state);
+ result = imap_state_capability_resp(data, imapc, imapcode, imapc->state);
break;
case IMAP_STARTTLS:
- result = imap_state_starttls_resp(data, imapcode, imapc->state);
+ result = imap_state_starttls_resp(data, imapc, imapcode, imapc->state);
/* During UPGRADETLS, leave the read loop as we need to connect
* (e.g. TLS handshake) before we continue sending/receiving. */
if(!result && (imapc->state == IMAP_UPGRADETLS))
@@ -1382,42 +1488,45 @@ upgrade_tls:
break;
case IMAP_AUTHENTICATE:
- result = imap_state_auth_resp(data, conn, imapcode, imapc->state);
+ result = imap_state_auth_resp(data, imapc, imapcode, imapc->state);
break;
case IMAP_LOGIN:
- result = imap_state_login_resp(data, imapcode, imapc->state);
+ result = imap_state_login_resp(data, imapc, imapcode, imapc->state);
break;
case IMAP_LIST:
case IMAP_SEARCH:
- result = imap_state_listsearch_resp(data, imapcode, imapc->state);
+ result = imap_state_listsearch_resp(data, imapc, imapcode, imapc->state);
break;
case IMAP_SELECT:
- result = imap_state_select_resp(data, imapcode, imapc->state);
+ result = imap_state_select_resp(data, imapc, imap,
+ imapcode, imapc->state);
break;
case IMAP_FETCH:
- result = imap_state_fetch_resp(data, conn, imapcode, imapc->state);
+ result = imap_state_fetch_resp(data, imapc, imapcode, imapc->state);
break;
case IMAP_FETCH_FINAL:
- result = imap_state_fetch_final_resp(data, imapcode, imapc->state);
+ result = imap_state_fetch_final_resp(data, imapc,
+ imapcode, imapc->state);
break;
case IMAP_APPEND:
- result = imap_state_append_resp(data, imapcode, imapc->state);
+ result = imap_state_append_resp(data, imapc, imapcode, imapc->state);
break;
case IMAP_APPEND_FINAL:
- result = imap_state_append_final_resp(data, imapcode, imapc->state);
+ result = imap_state_append_final_resp(data, imapc,
+ imapcode, imapc->state);
break;
case IMAP_LOGOUT:
default:
/* internal error */
- imap_state(data, IMAP_STOP);
+ imap_state(data, imapc, IMAP_STOP);
break;
}
} while(!result && imapc->state != IMAP_STOP && Curl_pp_moredata(pp));
@@ -1429,9 +1538,12 @@ upgrade_tls:
static CURLcode imap_multi_statemach(struct Curl_easy *data, bool *done)
{
CURLcode result = CURLE_OK;
- struct connectdata *conn = data->conn;
- struct imap_conn *imapc = &conn->proto.imapc;
+ struct imap_conn *imapc =
+ Curl_conn_meta_get(data->conn, CURL_META_IMAP_CONN);
+ *done = FALSE;
+ if(!imapc)
+ return CURLE_FAILED_INIT;
result = Curl_pp_statemach(data, &imapc->pp, FALSE, FALSE);
*done = (imapc->state == IMAP_STOP);
@@ -1439,11 +1551,10 @@ static CURLcode imap_multi_statemach(struct Curl_easy *data, bool *done)
}
static CURLcode imap_block_statemach(struct Curl_easy *data,
- struct connectdata *conn,
+ struct imap_conn *imapc,
bool disconnecting)
{
CURLcode result = CURLE_OK;
- struct imap_conn *imapc = &conn->proto.imapc;
while(imapc->state != IMAP_STOP && !result)
result = Curl_pp_statemach(data, &imapc->pp, TRUE, disconnecting);
@@ -1451,26 +1562,14 @@ static CURLcode imap_block_statemach(struct Curl_easy *data,
return result;
}
-/* Allocate and initialize the struct IMAP for the current Curl_easy if
- required */
-static CURLcode imap_init(struct Curl_easy *data)
-{
- CURLcode result = CURLE_OK;
- struct IMAP *imap;
-
- imap = data->req.p.imap = calloc(1, sizeof(struct IMAP));
- if(!imap)
- result = CURLE_OUT_OF_MEMORY;
-
- return result;
-}
-
/* For the IMAP "protocol connect" and "doing" phases only */
static int imap_getsock(struct Curl_easy *data,
struct connectdata *conn,
curl_socket_t *socks)
{
- return Curl_pp_getsock(data, &conn->proto.imapc.pp, socks);
+ struct imap_conn *imapc = Curl_conn_meta_get(conn, CURL_META_IMAP_CONN);
+ return imapc ?
+ Curl_pp_getsock(data, &imapc->pp, socks) : GETSOCK_BLANK;
}
/***********************************************************************
@@ -1485,35 +1584,24 @@ static int imap_getsock(struct Curl_easy *data,
*/
static CURLcode imap_connect(struct Curl_easy *data, bool *done)
{
+ struct imap_conn *imapc =
+ Curl_conn_meta_get(data->conn, CURL_META_IMAP_CONN);
CURLcode result = CURLE_OK;
- struct connectdata *conn = data->conn;
- struct imap_conn *imapc = &conn->proto.imapc;
- struct pingpong *pp = &imapc->pp;
*done = FALSE; /* default to not done yet */
+ if(!imapc)
+ return CURLE_FAILED_INIT;
/* We always support persistent connections in IMAP */
- connkeep(conn, "IMAP default");
-
- if(!imapc->initialised) {
- PINGPONG_SETUP(pp, imap_statemachine, imap_endofresp);
-
- /* Set the default preferred authentication type and mechanism */
- imapc->preftype = IMAP_TYPE_ANY;
- Curl_sasl_init(&imapc->sasl, data, &saslimap);
-
- Curl_dyn_init(&imapc->dyn, DYN_IMAP_CMD);
- Curl_pp_init(pp);
- imapc->initialised = TRUE;
- }
+ connkeep(data->conn, "IMAP default");
/* Parse the URL options */
- result = imap_parse_url_options(conn);
+ result = imap_parse_url_options(data->conn, imapc);
if(result)
return result;
/* Start off waiting for the server greeting response */
- imap_state(data, IMAP_SERVERGREET);
+ imap_state(data, imapc, IMAP_SERVERGREET);
/* Start off with an response id of '*' */
strcpy(imapc->resptag, "*");
@@ -1537,10 +1625,13 @@ static CURLcode imap_done(struct Curl_easy *data, CURLcode status,
{
CURLcode result = CURLE_OK;
struct connectdata *conn = data->conn;
- struct IMAP *imap = data->req.p.imap;
+ struct imap_conn *imapc = Curl_conn_meta_get(conn, CURL_META_IMAP_CONN);
+ struct IMAP *imap = Curl_meta_get(data, CURL_META_IMAP_EASY);
(void)premature;
+ if(!imapc)
+ return CURLE_FAILED_INIT;
if(!imap)
return CURLE_OK;
@@ -1554,33 +1645,20 @@ static CURLcode imap_done(struct Curl_easy *data, CURLcode status,
/* Handle responses after FETCH or APPEND transfer has finished */
if(!data->state.upload && !IS_MIME_POST(data))
- imap_state(data, IMAP_FETCH_FINAL);
+ imap_state(data, imapc, IMAP_FETCH_FINAL);
else {
/* End the APPEND command first by sending an empty line */
- result = Curl_pp_sendf(data, &conn->proto.imapc.pp, "%s", "");
+ result = Curl_pp_sendf(data, &imapc->pp, "%s", "");
if(!result)
- imap_state(data, IMAP_APPEND_FINAL);
+ imap_state(data, imapc, IMAP_APPEND_FINAL);
}
/* Run the state-machine */
if(!result)
- result = imap_block_statemach(data, conn, FALSE);
+ result = imap_block_statemach(data, imapc, FALSE);
}
- /* Cleanup our per-request based variables */
- Curl_safefree(imap->mailbox);
- Curl_safefree(imap->uidvalidity);
- Curl_safefree(imap->uid);
- Curl_safefree(imap->mindex);
- Curl_safefree(imap->section);
- Curl_safefree(imap->partial);
- Curl_safefree(imap->query);
- Curl_safefree(imap->custom);
- Curl_safefree(imap->custom_params);
-
- /* Clear the transfer mode for the next request */
- imap->transfer = PPTRANSFER_BODY;
-
+ imap_easy_reset(imap);
return result;
}
@@ -1597,11 +1675,13 @@ static CURLcode imap_perform(struct Curl_easy *data, bool *connected,
/* This is IMAP and no proxy */
CURLcode result = CURLE_OK;
struct connectdata *conn = data->conn;
- struct IMAP *imap = data->req.p.imap;
- struct imap_conn *imapc = &conn->proto.imapc;
+ struct imap_conn *imapc = Curl_conn_meta_get(conn, CURL_META_IMAP_CONN);
+ struct IMAP *imap = Curl_meta_get(data, CURL_META_IMAP_EASY);
bool selected = FALSE;
DEBUGF(infof(data, "DO phase starts"));
+ if(!imapc || !imap)
+ return CURLE_FAILED_INIT;
if(data->req.no_body) {
/* Requested no body means no transfer */
@@ -1621,23 +1701,23 @@ static CURLcode imap_perform(struct Curl_easy *data, bool *connected,
/* Start the first command in the DO phase */
if(data->state.upload || IS_MIME_POST(data))
/* APPEND can be executed directly */
- result = imap_perform_append(data);
+ result = imap_perform_append(data, imapc, imap);
else if(imap->custom && (selected || !imap->mailbox))
/* Custom command using the same mailbox or no mailbox */
- result = imap_perform_list(data);
+ result = imap_perform_list(data, imapc, imap);
else if(!imap->custom && selected && (imap->uid || imap->mindex))
/* FETCH from the same mailbox */
- result = imap_perform_fetch(data);
+ result = imap_perform_fetch(data, imapc, imap);
else if(!imap->custom && selected && imap->query)
/* SEARCH the current mailbox */
- result = imap_perform_search(data);
+ result = imap_perform_search(data, imapc, imap);
else if(imap->mailbox && !selected &&
(imap->custom || imap->uid || imap->mindex || imap->query))
/* SELECT the mailbox */
- result = imap_perform_select(data);
+ result = imap_perform_select(data, imapc, imap);
else
/* LIST */
- result = imap_perform_list(data);
+ result = imap_perform_list(data, imapc, imap);
if(result)
return result;
@@ -1664,20 +1744,23 @@ static CURLcode imap_perform(struct Curl_easy *data, bool *connected,
*/
static CURLcode imap_do(struct Curl_easy *data, bool *done)
{
+ struct IMAP *imap = Curl_meta_get(data, CURL_META_IMAP_EASY);
CURLcode result = CURLE_OK;
*done = FALSE; /* default to false */
+ if(!imap)
+ return CURLE_FAILED_INIT;
/* Parse the URL path */
- result = imap_parse_url_path(data);
+ result = imap_parse_url_path(data, imap);
if(result)
return result;
/* Parse the custom request */
- result = imap_parse_custom_request(data);
+ result = imap_parse_custom_request(data, imap);
if(result)
return result;
- result = imap_regular_transfer(data, done);
+ result = imap_regular_transfer(data, imap, done);
return result;
}
@@ -1692,10 +1775,10 @@ static CURLcode imap_do(struct Curl_easy *data, bool *done)
static CURLcode imap_disconnect(struct Curl_easy *data,
struct connectdata *conn, bool dead_connection)
{
- struct imap_conn *imapc = &conn->proto.imapc;
- (void)data;
+ struct imap_conn *imapc = Curl_conn_meta_get(conn, CURL_META_IMAP_CONN);
- if(imapc->initialised) {
+ (void)data;
+ if(imapc) {
/* We cannot send quit unconditionally. If this connection is stale or
bad in any way, sending quit and waiting around here will make the
disconnect wait in vain and cause more problems than we need to. */
@@ -1703,31 +1786,21 @@ static CURLcode imap_disconnect(struct Curl_easy *data,
/* The IMAP session may or may not have been allocated/setup at this
point! */
if(!dead_connection && conn->bits.protoconnstart) {
- if(!imap_perform_logout(data))
- (void)imap_block_statemach(data, conn, TRUE); /* ignore errors */
+ if(!imap_perform_logout(data, imapc))
+ (void)imap_block_statemach(data, imapc, TRUE); /* ignore errors */
}
- /* Disconnect from the server */
- Curl_pp_disconnect(&imapc->pp);
- Curl_dyn_free(&imapc->dyn);
-
/* Cleanup the SASL module */
Curl_sasl_cleanup(conn, imapc->sasl.authused);
-
- /* Cleanup our connection based variables */
- Curl_safefree(imapc->mailbox);
- Curl_safefree(imapc->mailbox_uidvalidity);
- memset(imapc, 0, sizeof(*imapc));
}
-
return CURLE_OK;
}
/* Call this when the DO phase has completed */
-static CURLcode imap_dophase_done(struct Curl_easy *data, bool connected)
+static CURLcode imap_dophase_done(struct Curl_easy *data,
+ struct IMAP *imap,
+ bool connected)
{
- struct IMAP *imap = data->req.p.imap;
-
(void)connected;
if(imap->transfer != PPTRANSFER_BODY)
@@ -1740,12 +1813,17 @@ static CURLcode imap_dophase_done(struct Curl_easy *data, bool connected)
/* Called from multi.c while DOing */
static CURLcode imap_doing(struct Curl_easy *data, bool *dophase_done)
{
- CURLcode result = imap_multi_statemach(data, dophase_done);
+ struct IMAP *imap = Curl_meta_get(data, CURL_META_IMAP_EASY);
+ CURLcode result;
+ if(!imap)
+ return CURLE_FAILED_INIT;
+
+ result = imap_multi_statemach(data, dophase_done);
if(result)
DEBUGF(infof(data, "DO phase failed"));
else if(*dophase_done) {
- result = imap_dophase_done(data, FALSE /* not connected */);
+ result = imap_dophase_done(data, imap, FALSE /* not connected */);
DEBUGF(infof(data, "DO phase is complete"));
}
@@ -1763,6 +1841,7 @@ static CURLcode imap_doing(struct Curl_easy *data, bool *dophase_done)
* remote host.
*/
static CURLcode imap_regular_transfer(struct Curl_easy *data,
+ struct IMAP *imap,
bool *dophase_done)
{
CURLcode result = CURLE_OK;
@@ -1782,17 +1861,77 @@ static CURLcode imap_regular_transfer(struct Curl_easy *data,
/* Perform post DO phase operations if necessary */
if(!result && *dophase_done)
- result = imap_dophase_done(data, connected);
+ result = imap_dophase_done(data, imap, connected);
return result;
}
+static void imap_easy_reset(struct IMAP *imap)
+{
+ Curl_safefree(imap->mailbox);
+ Curl_safefree(imap->uidvalidity);
+ Curl_safefree(imap->uid);
+ Curl_safefree(imap->mindex);
+ Curl_safefree(imap->section);
+ Curl_safefree(imap->partial);
+ Curl_safefree(imap->query);
+ Curl_safefree(imap->custom);
+ Curl_safefree(imap->custom_params);
+ /* Clear the transfer mode for the next request */
+ imap->transfer = PPTRANSFER_BODY;
+}
+
+static void imap_easy_dtor(void *key, size_t klen, void *entry)
+{
+ struct IMAP *imap = entry;
+ (void)key;
+ (void)klen;
+ imap_easy_reset(imap);
+ free(imap);
+}
+
+static void imap_conn_dtor(void *key, size_t klen, void *entry)
+{
+ struct imap_conn *imapc = entry;
+ (void)key;
+ (void)klen;
+ Curl_pp_disconnect(&imapc->pp);
+ curlx_dyn_free(&imapc->dyn);
+ Curl_safefree(imapc->mailbox);
+ Curl_safefree(imapc->mailbox_uidvalidity);
+ free(imapc);
+}
+
static CURLcode imap_setup_connection(struct Curl_easy *data,
struct connectdata *conn)
{
- /* Initialise the IMAP layer */
- (void)conn;
- return imap_init(data);
+ struct imap_conn *imapc;
+ struct pingpong *pp;
+ struct IMAP *imap;
+
+ imapc = calloc(1, sizeof(*imapc));
+ if(!imapc)
+ return CURLE_OUT_OF_MEMORY;
+
+ pp = &imapc->pp;
+ PINGPONG_SETUP(pp, imap_pp_statemachine, imap_endofresp);
+
+ /* Set the default preferred authentication type and mechanism */
+ imapc->preftype = IMAP_TYPE_ANY;
+ Curl_sasl_init(&imapc->sasl, data, &saslimap);
+
+ curlx_dyn_init(&imapc->dyn, DYN_IMAP_CMD);
+ Curl_pp_init(pp);
+
+ if(Curl_conn_meta_set(conn, CURL_META_IMAP_CONN, imapc, imap_conn_dtor))
+ return CURLE_OUT_OF_MEMORY;
+
+ imap = calloc(1, sizeof(struct IMAP));
+ if(!imap ||
+ Curl_meta_set(data, CURL_META_IMAP_EASY, imap, imap_easy_dtor))
+ return CURLE_OUT_OF_MEMORY;
+
+ return CURLE_OK;
}
/***********************************************************************
@@ -1803,10 +1942,11 @@ static CURLcode imap_setup_connection(struct Curl_easy *data,
*
* Designed to never block.
*/
-static CURLcode imap_sendf(struct Curl_easy *data, const char *fmt, ...)
+static CURLcode imap_sendf(struct Curl_easy *data,
+ struct imap_conn *imapc,
+ const char *fmt, ...)
{
CURLcode result = CURLE_OK;
- struct imap_conn *imapc = &data->conn->proto.imapc;
DEBUGASSERT(fmt);
@@ -1816,10 +1956,10 @@ static CURLcode imap_sendf(struct Curl_easy *data, const char *fmt, ...)
++imapc->cmdid);
/* start with a blank buffer */
- Curl_dyn_reset(&imapc->dyn);
+ curlx_dyn_reset(&imapc->dyn);
/* append tag + space + fmt */
- result = Curl_dyn_addf(&imapc->dyn, "%s %s", imapc->resptag, fmt);
+ result = curlx_dyn_addf(&imapc->dyn, "%s %s", imapc->resptag, fmt);
if(!result) {
va_list ap;
va_start(ap, fmt);
@@ -1827,7 +1967,7 @@ static CURLcode imap_sendf(struct Curl_easy *data, const char *fmt, ...)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wformat-nonliteral"
#endif
- result = Curl_pp_vsendf(data, &imapc->pp, Curl_dyn_ptr(&imapc->dyn), ap);
+ result = Curl_pp_vsendf(data, &imapc->pp, curlx_dyn_ptr(&imapc->dyn), ap);
#ifdef __clang__
#pragma clang diagnostic pop
#endif
@@ -1861,24 +2001,24 @@ static char *imap_atom(const char *str, bool escape_only)
/* nothing to escape, return a strdup */
return strdup(str);
- Curl_dyn_init(&line, 2000);
+ curlx_dyn_init(&line, 2000);
- if(!escape_only && Curl_dyn_addn(&line, "\"", 1))
+ if(!escape_only && curlx_dyn_addn(&line, "\"", 1))
return NULL;
while(*str) {
if((*str == '\\' || *str == '"') &&
- Curl_dyn_addn(&line, "\\", 1))
+ curlx_dyn_addn(&line, "\\", 1))
return NULL;
- if(Curl_dyn_addn(&line, str, 1))
+ if(curlx_dyn_addn(&line, str, 1))
return NULL;
str++;
}
- if(!escape_only && Curl_dyn_addn(&line, "\"", 1))
+ if(!escape_only && curlx_dyn_addn(&line, "\"", 1))
return NULL;
- return Curl_dyn_ptr(&line);
+ return curlx_dyn_ptr(&line);
}
/***********************************************************************
@@ -1920,10 +2060,10 @@ static bool imap_is_bchar(char ch)
*
* Parse the URL login options.
*/
-static CURLcode imap_parse_url_options(struct connectdata *conn)
+static CURLcode imap_parse_url_options(struct connectdata *conn,
+ struct imap_conn *imapc)
{
CURLcode result = CURLE_OK;
- struct imap_conn *imapc = &conn->proto.imapc;
const char *ptr = conn->options;
bool prefer_login = FALSE;
@@ -1984,11 +2124,11 @@ static CURLcode imap_parse_url_options(struct connectdata *conn)
* Parse the URL path into separate path components.
*
*/
-static CURLcode imap_parse_url_path(struct Curl_easy *data)
+static CURLcode imap_parse_url_path(struct Curl_easy *data,
+ struct IMAP *imap)
{
/* The imap struct is already initialised in imap_connect() */
CURLcode result = CURLE_OK;
- struct IMAP *imap = data->req.p.imap;
const char *begin = &data->state.up.path[1]; /* skip leading slash */
const char *ptr = begin;
@@ -2116,10 +2256,10 @@ static CURLcode imap_parse_url_path(struct Curl_easy *data)
*
* Parse the custom request.
*/
-static CURLcode imap_parse_custom_request(struct Curl_easy *data)
+static CURLcode imap_parse_custom_request(struct Curl_easy *data,
+ struct IMAP *imap)
{
CURLcode result = CURLE_OK;
- struct IMAP *imap = data->req.p.imap;
const char *custom = data->set.str[STRING_CUSTOMREQUEST];
if(custom) {
diff --git a/libs/libcurl/src/imap.h b/libs/libcurl/src/imap.h
index b83a49ec3f..93a0aaa3e4 100644
--- a/libs/libcurl/src/imap.h
+++ b/libs/libcurl/src/imap.h
@@ -27,66 +27,6 @@
#include "pingpong.h"
#include "curl_sasl.h"
-/****************************************************************************
- * IMAP unique setup
- ***************************************************************************/
-typedef enum {
- IMAP_STOP, /* do nothing state, stops the state machine */
- IMAP_SERVERGREET, /* waiting for the initial greeting immediately after
- a connect */
- IMAP_CAPABILITY,
- IMAP_STARTTLS,
- IMAP_UPGRADETLS, /* asynchronously upgrade the connection to SSL/TLS
- (multi mode only) */
- IMAP_AUTHENTICATE,
- IMAP_LOGIN,
- IMAP_LIST,
- IMAP_SELECT,
- IMAP_FETCH,
- IMAP_FETCH_FINAL,
- IMAP_APPEND,
- IMAP_APPEND_FINAL,
- IMAP_SEARCH,
- IMAP_LOGOUT,
- IMAP_LAST /* never used */
-} imapstate;
-
-/* This IMAP struct is used in the Curl_easy. All IMAP data that is
- connection-oriented must be in imap_conn to properly deal with the fact that
- perhaps the Curl_easy is changed between the times the connection is
- used. */
-struct IMAP {
- curl_pp_transfer transfer;
- char *mailbox; /* Mailbox to select */
- char *uidvalidity; /* UIDVALIDITY to check in select */
- char *uid; /* Message UID to fetch */
- char *mindex; /* Index in mail box of mail to fetch */
- char *section; /* Message SECTION to fetch */
- char *partial; /* Message PARTIAL to fetch */
- char *query; /* Query to search for */
- char *custom; /* Custom request */
- char *custom_params; /* Parameters for the custom request */
-};
-
-/* imap_conn is used for struct connection-oriented data in the connectdata
- struct */
-struct imap_conn {
- struct pingpong pp;
- struct SASL sasl; /* SASL-related parameters */
- struct dynbuf dyn; /* for the IMAP commands */
- char *mailbox; /* The last selected mailbox */
- char *mailbox_uidvalidity; /* UIDVALIDITY parsed from select response */
- imapstate state; /* Always use imap.c:state() to change state! */
- char resptag[5]; /* Response tag to wait for */
- unsigned char preftype; /* Preferred authentication type */
- unsigned char cmdid; /* Last used command ID */
- BIT(ssldone); /* Is connect() over SSL done? */
- BIT(preauth); /* Is this connection PREAUTH? */
- BIT(tls_supported); /* StartTLS capability supported by server */
- BIT(login_disabled); /* LOGIN command disabled by server */
- BIT(ir_supported); /* Initial response supported by server */
- BIT(initialised); /* members have been initialised */
-};
extern const struct Curl_handler Curl_handler_imap;
extern const struct Curl_handler Curl_handler_imaps;
diff --git a/libs/libcurl/src/inet_ntop.c b/libs/libcurl/src/inet_ntop.c
index 9122e00898..0c7c178182 100644
--- a/libs/libcurl/src/inet_ntop.c
+++ b/libs/libcurl/src/inet_ntop.c
@@ -196,7 +196,7 @@ static char *inet_ntop6(const unsigned char *src, char *dst, size_t size)
* code. This is to avoid losing the actual last Winsock error. When this
* function returns NULL, check errno not SOCKERRNO.
*/
-char *curlx_inet_ntop(int af, const void *src, char *buf, size_t size)
+char *Curl_inet_ntop(int af, const void *src, char *buf, size_t size)
{
switch(af) {
case AF_INET:
diff --git a/libs/libcurl/src/inet_ntop.h b/libs/libcurl/src/inet_ntop.h
index dd32bb656d..6c02c68e41 100644
--- a/libs/libcurl/src/inet_ntop.h
+++ b/libs/libcurl/src/inet_ntop.h
@@ -26,7 +26,7 @@
#include "curl_setup.h"
-char *curlx_inet_ntop(int af, const void *addr, char *buf, size_t size);
+char *Curl_inet_ntop(int af, const void *addr, char *buf, size_t size);
#ifdef HAVE_INET_NTOP
#ifdef HAVE_NETINET_IN_H
@@ -39,12 +39,12 @@ char *curlx_inet_ntop(int af, const void *addr, char *buf, size_t size);
#include <arpa/inet.h>
#endif
#ifdef __AMIGA__
-#define curlx_inet_ntop(af,addr,buf,size) \
- (char *)inet_ntop(af, CURL_UNCONST(addr), (unsigned char *)buf, \
- (curl_socklen_t)(size))
+#define Curl_inet_ntop(af,addr,buf,size) \
+ (char *)inet_ntop(af, CURL_UNCONST(addr), (unsigned char *)buf, \
+ (curl_socklen_t)(size))
#else
-#define curlx_inet_ntop(af,addr,buf,size) \
- inet_ntop(af, addr, buf, (curl_socklen_t)(size))
+#define Curl_inet_ntop(af,addr,buf,size) \
+ inet_ntop(af, addr, buf, (curl_socklen_t)(size))
#endif
#endif
diff --git a/libs/libcurl/src/krb5.c b/libs/libcurl/src/krb5.c
index ec2bc21ead..35c9e60fc1 100644
--- a/libs/libcurl/src/krb5.c
+++ b/libs/libcurl/src/krb5.c
@@ -46,15 +46,16 @@
#endif
#include "urldata.h"
+#include "url.h"
#include "cfilters.h"
#include "cf-socket.h"
-#include "curl_base64.h"
+#include "curlx/base64.h"
#include "ftp.h"
#include "curl_gssapi.h"
#include "sendf.h"
#include "transfer.h"
#include "curl_krb5.h"
-#include "warnless.h"
+#include "curlx/warnless.h"
#include "strcase.h"
#include "strdup.h"
@@ -217,6 +218,10 @@ krb5_auth(void *app_data, struct Curl_easy *data, struct connectdata *conn)
struct sockaddr_in *remote_addr =
(struct sockaddr_in *)CURL_UNCONST(&conn->remote_addr->curl_sa_addr);
char *stringp;
+ struct ftp_conn *ftpc = Curl_conn_meta_get(conn, CURL_META_FTP_CONN);
+
+ if(!ftpc)
+ return -2;
if(getsockname(conn->sock[FIRSTSOCKET],
(struct sockaddr *)&conn->local_addr, &l) < 0)
@@ -242,8 +247,7 @@ krb5_auth(void *app_data, struct Curl_easy *data, struct connectdata *conn)
if(Curl_GetFTPResponse(data, &nread, NULL))
return -1;
else {
- struct pingpong *pp = &conn->proto.ftpc.pp;
- char *line = Curl_dyn_ptr(&pp->recvbuf);
+ char *line = curlx_dyn_ptr(&ftpc->pp.recvbuf);
if(line[0] != '3')
return -1;
}
@@ -304,7 +308,7 @@ krb5_auth(void *app_data, struct Curl_easy *data, struct connectdata *conn)
if(output_buffer.length) {
char *cmd;
- result = Curl_base64_encode((char *)output_buffer.value,
+ result = curlx_base64_encode((char *)output_buffer.value,
output_buffer.length, &p, &base64_sz);
if(result) {
infof(data, "base64-encoding: %s", curl_easy_strerror(result));
@@ -331,9 +335,8 @@ krb5_auth(void *app_data, struct Curl_easy *data, struct connectdata *conn)
break;
}
else {
- struct pingpong *pp = &conn->proto.ftpc.pp;
- size_t len = Curl_dyn_len(&pp->recvbuf);
- p = Curl_dyn_ptr(&pp->recvbuf);
+ size_t len = curlx_dyn_len(&ftpc->pp.recvbuf);
+ p = curlx_dyn_ptr(&ftpc->pp.recvbuf);
if((len < 4) || (p[0] != '2' && p[0] != '3')) {
infof(data, "Server did not accept auth data");
ret = AUTH_ERROR;
@@ -348,7 +351,7 @@ krb5_auth(void *app_data, struct Curl_easy *data, struct connectdata *conn)
if(p) {
unsigned char *outptr;
size_t outlen;
- result = Curl_base64_decode(p + 5, &outptr, &outlen);
+ result = curlx_base64_decode(p + 5, &outptr, &outlen);
if(result) {
failf(data, "base64-decoding: %s", curl_easy_strerror(result));
ret = AUTH_CONTINUE;
@@ -537,7 +540,7 @@ static CURLcode read_data(struct Curl_easy *data, int sockindex,
if(len > CURL_MAX_INPUT_LENGTH)
return CURLE_TOO_LARGE;
- Curl_dyn_reset(&buf->buf);
+ curlx_dyn_reset(&buf->buf);
}
else
return CURLE_RECV_ERROR;
@@ -548,18 +551,18 @@ static CURLcode read_data(struct Curl_easy *data, int sockindex,
result = socket_read(data, sockindex, buffer, (size_t)nread);
if(result)
return result;
- result = Curl_dyn_addn(&buf->buf, buffer, nread);
+ result = curlx_dyn_addn(&buf->buf, buffer, nread);
if(result)
return result;
len -= nread;
} while(len);
/* this decodes the dynbuf *in place* */
nread = conn->mech->decode(conn->app_data,
- Curl_dyn_ptr(&buf->buf),
+ curlx_dyn_ptr(&buf->buf),
len, conn->data_prot, conn);
if(nread < 0)
return CURLE_RECV_ERROR;
- Curl_dyn_setlen(&buf->buf, nread);
+ curlx_dyn_setlen(&buf->buf, nread);
buf->index = 0;
return CURLE_OK;
}
@@ -567,10 +570,10 @@ static CURLcode read_data(struct Curl_easy *data, int sockindex,
static size_t
buffer_read(struct krb5buffer *buf, void *data, size_t len)
{
- size_t size = Curl_dyn_len(&buf->buf);
+ size_t size = curlx_dyn_len(&buf->buf);
if(size - buf->index < len)
len = size - buf->index;
- memcpy(data, Curl_dyn_ptr(&buf->buf) + buf->index, len);
+ memcpy(data, curlx_dyn_ptr(&buf->buf) + buf->index, len);
buf->index += len;
return len;
}
@@ -605,7 +608,7 @@ static ssize_t sec_recv(struct Curl_easy *data, int sockindex,
while(len > 0) {
if(read_data(data, sockindex, &conn->in_buffer))
return -1;
- if(Curl_dyn_len(&conn->in_buffer.buf) == 0) {
+ if(curlx_dyn_len(&conn->in_buffer.buf) == 0) {
if(bytes_read > 0)
conn->in_buffer.eof_flag = 1;
return bytes_read;
@@ -645,7 +648,7 @@ static void do_sec_send(struct Curl_easy *data, struct connectdata *conn,
return; /* error */
if(iscmd) {
- error = Curl_base64_encode(buffer, curlx_sitouz(bytes),
+ error = curlx_base64_encode(buffer, curlx_sitouz(bytes),
&cmd_buffer, &cmd_size);
if(error) {
free(buffer);
@@ -723,7 +726,7 @@ int Curl_sec_read_msg(struct Curl_easy *data, struct connectdata *conn,
DEBUGASSERT(level > PROT_NONE && level < PROT_LAST);
- error = Curl_base64_decode(buffer + 4, (unsigned char **)&buf, &decoded_sz);
+ error = curlx_base64_decode(buffer + 4, (unsigned char **)&buf, &decoded_sz);
if(error || decoded_sz == 0)
return -1;
@@ -781,9 +784,12 @@ static int sec_set_protection_level(struct Curl_easy *data)
if(level) {
char *pbsz;
unsigned int buffer_size = 1 << 20; /* 1048576 */
- struct pingpong *pp = &conn->proto.ftpc.pp;
+ struct ftp_conn *ftpc = Curl_conn_meta_get(conn, CURL_META_FTP_CONN);
char *line;
+ if(!ftpc)
+ return -2;
+
code = ftp_send_command(data, "PBSZ %u", buffer_size);
if(code < 0)
return -1;
@@ -794,7 +800,7 @@ static int sec_set_protection_level(struct Curl_easy *data)
}
conn->buffer_size = buffer_size;
- line = Curl_dyn_ptr(&pp->recvbuf);
+ line = curlx_dyn_ptr(&ftpc->pp.recvbuf);
pbsz = strstr(line, "PBSZ=");
if(pbsz) {
/* stick to default value if the check fails */
@@ -916,7 +922,7 @@ Curl_sec_login(struct Curl_easy *data, struct connectdata *conn)
void
Curl_sec_conn_init(struct connectdata *conn)
{
- Curl_dyn_init(&conn->in_buffer.buf, CURL_MAX_INPUT_LENGTH);
+ curlx_dyn_init(&conn->in_buffer.buf, CURL_MAX_INPUT_LENGTH);
conn->in_buffer.index = 0;
conn->in_buffer.eof_flag = 0;
}
@@ -927,7 +933,7 @@ Curl_sec_conn_destroy(struct connectdata *conn)
if(conn->mech && conn->mech->end)
conn->mech->end(conn->app_data);
Curl_safefree(conn->app_data);
- Curl_dyn_free(&conn->in_buffer.buf);
+ curlx_dyn_free(&conn->in_buffer.buf);
conn->in_buffer.index = 0;
conn->in_buffer.eof_flag = 0;
conn->sec_complete = 0;
diff --git a/libs/libcurl/src/ldap.c b/libs/libcurl/src/ldap.c
index 27b2b66845..f38653e3e0 100644
--- a/libs/libcurl/src/ldap.c
+++ b/libs/libcurl/src/ldap.c
@@ -89,10 +89,10 @@
#include "progress.h"
#include "transfer.h"
#include "strcase.h"
-#include "strparse.h"
+#include "curlx/strparse.h"
#include "curl_ldap.h"
-#include "curl_multibyte.h"
-#include "curl_base64.h"
+#include "curlx/multibyte.h"
+#include "curlx/base64.h"
#include "connect.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
@@ -629,8 +629,8 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done)
if((attr_len > 7) &&
(strcmp(";binary", attr + (attr_len - 7)) == 0)) {
/* Binary attribute, encode to base64. */
- result = Curl_base64_encode(vals[i]->bv_val, vals[i]->bv_len,
- &val_b64, &val_b64_sz);
+ result = curlx_base64_encode(vals[i]->bv_val, vals[i]->bv_len,
+ &val_b64, &val_b64_sz);
if(result) {
ldap_value_free_len(vals);
FREE_ON_WINLDAP(attr);
@@ -729,7 +729,7 @@ static void _ldap_trace(const char *fmt, ...)
if(do_trace == -1) {
const char *env = getenv("CURL_TRACE");
curl_off_t e = 0;
- if(!Curl_str_number(&env, &e, INT_MAX))
+ if(!curlx_str_number(&env, &e, INT_MAX))
do_trace = e > 0;
}
if(!do_trace)
@@ -884,7 +884,7 @@ static int _ldap_url_parse2(struct Curl_easy *data,
CURLcode result;
struct Curl_str out;
- if(Curl_str_until(&atp, &out, 1024, ','))
+ if(curlx_str_until(&atp, &out, 1024, ','))
break;
LDAP_TRACE(("attr[%zu] '%.*s'\n", i, (int)out.len, out.str));
@@ -913,7 +913,7 @@ static int _ldap_url_parse2(struct Curl_easy *data,
#endif
ludp->lud_attrs_dups++;
- if(Curl_str_single(&atp, ','))
+ if(curlx_str_single(&atp, ','))
break;
}
}
diff --git a/libs/libcurl/src/md4.c b/libs/libcurl/src/md4.c
index 2b28b08bd3..cae64ae332 100644
--- a/libs/libcurl/src/md4.c
+++ b/libs/libcurl/src/md4.c
@@ -30,7 +30,7 @@
#include "strdup.h"
#include "curl_md4.h"
-#include "warnless.h"
+#include "curlx/warnless.h"
#ifdef USE_OPENSSL
#include <openssl/opensslv.h>
diff --git a/libs/libcurl/src/md5.c b/libs/libcurl/src/md5.c
index abcdd0b093..ba67184d05 100644
--- a/libs/libcurl/src/md5.c
+++ b/libs/libcurl/src/md5.c
@@ -32,7 +32,7 @@
#include "curl_md5.h"
#include "curl_hmac.h"
-#include "warnless.h"
+#include "curlx/warnless.h"
#ifdef USE_MBEDTLS
#include <mbedtls/version.h>
diff --git a/libs/libcurl/src/memdebug.c b/libs/libcurl/src/memdebug.c
index fa7bb66257..0f09683f58 100644
--- a/libs/libcurl/src/memdebug.c
+++ b/libs/libcurl/src/memdebug.c
@@ -378,6 +378,24 @@ curl_socket_t curl_dbg_accept(curl_socket_t s, void *saddr, void *saddrlen,
return sockfd;
}
+#ifdef HAVE_ACCEPT4
+curl_socket_t curl_dbg_accept4(curl_socket_t s, void *saddr, void *saddrlen,
+ int flags,
+ int line, const char *source)
+{
+ struct sockaddr *addr = (struct sockaddr *)saddr;
+ curl_socklen_t *addrlen = (curl_socklen_t *)saddrlen;
+
+ curl_socket_t sockfd = accept4(s, addr, addrlen, flags);
+
+ if(source && (sockfd != CURL_SOCKET_BAD))
+ curl_dbg_log("FD %s:%d accept() = %" FMT_SOCKET_T "\n",
+ source, line, sockfd);
+
+ return sockfd;
+}
+#endif
+
/* separate function to allow libcurl to mark a "faked" close */
void curl_dbg_mark_sclose(curl_socket_t sockfd, int line, const char *source)
{
diff --git a/libs/libcurl/src/memdebug.h b/libs/libcurl/src/memdebug.h
index d4fa5f8e77..de7fbd0cb0 100644
--- a/libs/libcurl/src/memdebug.h
+++ b/libs/libcurl/src/memdebug.h
@@ -92,6 +92,11 @@ CURL_EXTERN int curl_dbg_sclose(curl_socket_t sockfd,
int line, const char *source);
CURL_EXTERN curl_socket_t curl_dbg_accept(curl_socket_t s, void *a, void *alen,
int line, const char *source);
+#ifdef HAVE_ACCEPT4
+CURL_EXTERN curl_socket_t curl_dbg_accept4(curl_socket_t s, void *saddr,
+ void *saddrlen, int flags,
+ int line, const char *source);
+#endif
#ifdef HAVE_SOCKETPAIR
CURL_EXTERN int curl_dbg_socketpair(int domain, int type, int protocol,
curl_socket_t socket_vector[2],
@@ -159,6 +164,11 @@ CURL_EXTERN ALLOC_FUNC
#undef accept /* for those with accept as a macro */
#define accept(sock,addr,len)\
curl_dbg_accept(sock, addr, len, __LINE__, __FILE__)
+#ifdef HAVE_ACCEPT4
+#undef accept4 /* for those with accept4 as a macro */
+#define accept4(sock,addr,len,flags)\
+ curl_dbg_accept4(sock, addr, len, flags, __LINE__, __FILE__)
+#endif
#ifdef HAVE_SOCKETPAIR
#define socketpair(domain,type,protocol,socket_vector)\
curl_dbg_socketpair((int)domain, type, protocol, socket_vector, \
diff --git a/libs/libcurl/src/mime.c b/libs/libcurl/src/mime.c
index 16e63d0ef9..35200a059b 100644
--- a/libs/libcurl/src/mime.c
+++ b/libs/libcurl/src/mime.c
@@ -29,10 +29,11 @@
struct Curl_easy;
#include "mime.h"
-#include "warnless.h"
+#include "curlx/warnless.h"
#include "urldata.h"
#include "sendf.h"
#include "strdup.h"
+#include "curlx/base64.h"
#if !defined(CURL_DISABLE_MIME) && (!defined(CURL_DISABLE_HTTP) || \
!defined(CURL_DISABLE_SMTP) || \
@@ -45,7 +46,7 @@ struct Curl_easy;
#include "rand.h"
#include "slist.h"
#include "strcase.h"
-#include "dynbuf.h"
+#include "curlx/dynbuf.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h"
@@ -87,10 +88,6 @@ static const struct mime_encoder encoders[] = {
{ZERO_NULL, ZERO_NULL, ZERO_NULL}
};
-/* Base64 encoding table */
-static const char base64enc[] =
- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
-
/* Quoted-printable character class table.
*
* We cannot rely on ctype functions since quoted-printable input data
@@ -318,19 +315,19 @@ static char *escape_string(struct Curl_easy *data,
if(strategy == MIMESTRATEGY_MAIL || (data && (data->set.mime_formescape)))
table = mimetable;
- Curl_dyn_init(&db, CURL_MAX_INPUT_LENGTH);
+ curlx_dyn_init(&db, CURL_MAX_INPUT_LENGTH);
- for(result = Curl_dyn_addn(&db, STRCONST("")); !result && *src; src++) {
+ for(result = curlx_dyn_addn(&db, STRCONST("")); !result && *src; src++) {
for(p = table; *p && **p != *src; p++)
;
if(*p)
- result = Curl_dyn_add(&db, *p + 1);
+ result = curlx_dyn_add(&db, *p + 1);
else
- result = Curl_dyn_addn(&db, src, 1);
+ result = curlx_dyn_addn(&db, src, 1);
}
- return Curl_dyn_ptr(&db);
+ return curlx_dyn_ptr(&db);
}
/* Check if header matches. */
@@ -472,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++ = base64enc[(i >> 18) & 0x3F];
- *ptr++ = base64enc[(i >> 12) & 0x3F];
- *ptr++ = base64enc[(i >> 6) & 0x3F];
- *ptr++ = base64enc[i & 0x3F];
+ *ptr++ = Curl_base64encdec[(i >> 18) & 0x3F];
+ *ptr++ = Curl_base64encdec[(i >> 12) & 0x3F];
+ *ptr++ = Curl_base64encdec[(i >> 6) & 0x3F];
+ *ptr++ = Curl_base64encdec[i & 0x3F];
cursize += 4;
st->pos += 4;
size -= 4;
@@ -499,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] = base64enc[(i >> 18) & 0x3F];
- ptr[1] = base64enc[(i >> 12) & 0x3F];
+ ptr[0] = Curl_base64encdec[(i >> 18) & 0x3F];
+ ptr[1] = Curl_base64encdec[(i >> 12) & 0x3F];
if(++st->bufbeg != st->bufend) {
- ptr[2] = base64enc[(i >> 6) & 0x3F];
+ ptr[2] = Curl_base64encdec[(i >> 6) & 0x3F];
st->bufbeg++;
}
cursize += 4;
diff --git a/libs/libcurl/src/mprintf.c b/libs/libcurl/src/mprintf.c
index 28f0844e66..2bf9b37571 100644
--- a/libs/libcurl/src/mprintf.c
+++ b/libs/libcurl/src/mprintf.c
@@ -23,18 +23,14 @@
*/
#include "curl_setup.h"
-#include "dynbuf.h"
+#include "curlx/dynbuf.h"
#include "curl_printf.h"
-#include "strparse.h"
+#include "curlx/strparse.h"
#include "curl_memory.h"
/* The last #include file should be: */
#include "memdebug.h"
-/*
- * If SIZEOF_SIZE_T has not been defined, default to the size of long.
- */
-
#ifdef HAVE_LONGLONG
# define LONG_LONG_TYPE long long
# define HAVE_LONG_LONG_TYPE
@@ -68,17 +64,16 @@
#endif
/* Lower-case digits. */
-static const char lower_digits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
+const unsigned char Curl_ldigits[] = "0123456789abcdef";
/* Upper-case digits. */
-static const char upper_digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
-
-#define OUTCHAR(x) \
- do { \
- if(!stream((unsigned char)x, userp)) \
- done++; \
- else \
- return done; /* return on failure */ \
+const unsigned char Curl_udigits[] = "0123456789ABCDEF";
+
+#define OUTCHAR(x) \
+ do { \
+ if(stream((unsigned char)x, userp)) \
+ return TRUE; \
+ (*donep)++; \
} while(0)
/* Data type to read from the arglist */
@@ -173,8 +168,8 @@ struct asprintf {
static int dollarstring(const char *p, const char **end)
{
curl_off_t num;
- if(Curl_str_number(&p, &num, MAX_PARAMETERS) ||
- Curl_str_single(&p, '$') || !num)
+ if(curlx_str_number(&p, &num, MAX_PARAMETERS) ||
+ curlx_str_single(&p, '$') || !num)
return -1;
*end = p;
return (int)num - 1;
@@ -306,7 +301,7 @@ static int parsefmt(const char *format,
is_neg = ('-' == *fmt);
if(is_neg)
fmt++;
- if(Curl_str_number(&fmt, &num, INT_MAX))
+ if(curlx_str_number(&fmt, &num, INT_MAX))
return PFMT_PREC;
precision = (int)num;
if(is_neg)
@@ -378,7 +373,7 @@ static int parsefmt(const char *format,
curl_off_t num;
flags |= FLAGS_WIDTH;
fmt--;
- if(Curl_str_number(&fmt, &num, INT_MAX))
+ if(curlx_str_number(&fmt, &num, INT_MAX))
return PFMT_WIDTH;
width = (int)num;
break;
@@ -624,6 +619,333 @@ static int parsefmt(const char *format,
return PFMT_OK;
}
+struct mproperty {
+ int width; /* Width of a field. */
+ int prec; /* Precision of a field. */
+ unsigned int flags;
+};
+
+static bool out_double(void *userp,
+ int (*stream)(unsigned char, void *),
+ struct mproperty *p,
+ double dnum,
+ char *work, int *donep)
+{
+ char formatbuf[32]="%";
+ char *fptr = &formatbuf[1];
+ size_t left = sizeof(formatbuf)-strlen(formatbuf);
+ int flags = p->flags;
+ int width = p->width;
+ int prec = p->prec;
+
+ if(flags & FLAGS_LEFT)
+ *fptr++ = '-';
+ if(flags & FLAGS_SHOWSIGN)
+ *fptr++ = '+';
+ if(flags & FLAGS_SPACE)
+ *fptr++ = ' ';
+ if(flags & FLAGS_ALT)
+ *fptr++ = '#';
+
+ *fptr = 0;
+
+ if(width >= 0) {
+ size_t dlen;
+ if(width >= BUFFSIZE)
+ width = BUFFSIZE - 1;
+ /* RECURSIVE USAGE */
+ dlen = (size_t)curl_msnprintf(fptr, left, "%d", width);
+ fptr += dlen;
+ left -= dlen;
+ }
+ if(prec >= 0) {
+ /* for each digit in the integer part, we can have one less
+ precision */
+ int maxprec = BUFFSIZE - 1;
+ double val = dnum;
+ int len;
+ if(prec > maxprec)
+ prec = maxprec - 1;
+ if(width > 0 && prec <= width)
+ maxprec -= width;
+ while(val >= 10.0) {
+ val /= 10;
+ maxprec--;
+ }
+
+ if(prec > maxprec)
+ prec = maxprec - 1;
+ if(prec < 0)
+ prec = 0;
+ /* RECURSIVE USAGE */
+ len = curl_msnprintf(fptr, left, ".%d", prec);
+ fptr += len;
+ }
+ if(flags & FLAGS_LONG)
+ *fptr++ = 'l';
+
+ if(flags & FLAGS_FLOATE)
+ *fptr++ = (char)((flags & FLAGS_UPPER) ? 'E' : 'e');
+ else if(flags & FLAGS_FLOATG)
+ *fptr++ = (char)((flags & FLAGS_UPPER) ? 'G' : 'g');
+ else
+ *fptr++ = 'f';
+
+ *fptr = 0; /* and a final null-termination */
+
+#ifdef __clang__
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wformat-nonliteral"
+#endif
+ /* NOTE NOTE NOTE!! Not all sprintf implementations return number of
+ output characters */
+#ifdef HAVE_SNPRINTF
+ /* !checksrc! disable LONGLINE */
+ /* NOLINTNEXTLINE(clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling) */
+ (snprintf)(work, BUFFSIZE, formatbuf, dnum);
+#ifdef _WIN32
+ /* Old versions of the Windows CRT do not terminate the snprintf output
+ buffer if it reaches the max size so we do that here. */
+ work[BUFFSIZE - 1] = 0;
+#endif
+#else
+ (sprintf)(work, formatbuf, dnum);
+#endif
+#ifdef __clang__
+#pragma clang diagnostic pop
+#endif
+ DEBUGASSERT(strlen(work) < BUFFSIZE);
+ while(*work) {
+ if(stream(*work++, userp))
+ return TRUE;
+ (*donep)++;
+ }
+ return 0;
+}
+
+static bool out_number(void *userp,
+ int (*stream)(unsigned char, void *),
+ struct mproperty *p,
+ mp_uintmax_t num,
+ mp_intmax_t nums,
+ char *work, int *donep)
+{
+ const unsigned char *digits = Curl_ldigits;
+ int flags = p->flags;
+ int width = p->width;
+ int prec = p->prec;
+ bool is_alt = flags & FLAGS_ALT;
+ bool is_neg = FALSE;
+ int base = 10;
+
+ /* 'workend' points to the final buffer byte position, but with an extra
+ byte as margin to avoid the (FALSE?) warning Coverity gives us
+ otherwise */
+ char *workend = &work[BUFFSIZE - 2];
+ char *w;
+
+ if(flags & FLAGS_CHAR) {
+ /* Character. */
+ if(!(flags & FLAGS_LEFT))
+ while(--width > 0)
+ OUTCHAR(' ');
+ OUTCHAR((char) num);
+ if(flags & FLAGS_LEFT)
+ while(--width > 0)
+ OUTCHAR(' ');
+ return FALSE;
+ }
+ if(flags & FLAGS_OCTAL)
+ /* Octal unsigned integer */
+ base = 8;
+
+ else if(flags & FLAGS_HEX) {
+ /* Hexadecimal unsigned integer */
+ digits = (flags & FLAGS_UPPER) ? Curl_udigits : Curl_ldigits;
+ base = 16;
+ }
+ else if(flags & FLAGS_UNSIGNED)
+ /* Decimal unsigned integer */
+ ;
+
+ else {
+ /* Decimal integer. */
+ is_neg = (nums < 0);
+ if(is_neg) {
+ /* signed_num might fail to hold absolute negative minimum by 1 */
+ mp_intmax_t signed_num; /* Used to convert negative in positive. */
+ signed_num = nums + (mp_intmax_t)1;
+ signed_num = -signed_num;
+ num = (mp_uintmax_t)signed_num;
+ num += (mp_uintmax_t)1;
+ }
+ }
+
+ /* Supply a default precision if none was given. */
+ if(prec == -1)
+ prec = 1;
+
+ /* Put the number in WORK. */
+ w = workend;
+ DEBUGASSERT(base <= 16);
+ switch(base) {
+ case 10:
+ while(num > 0) {
+ *w-- = (char)('0' + (num % 10));
+ num /= 10;
+ }
+ break;
+ default:
+ while(num > 0) {
+ *w-- = digits[num % base];
+ num /= base;
+ }
+ break;
+ }
+ width -= (int)(workend - w);
+ prec -= (int)(workend - w);
+
+ if(is_alt && base == 8 && prec <= 0) {
+ *w-- = '0';
+ --width;
+ }
+
+ if(prec > 0) {
+ width -= prec;
+ while(prec-- > 0 && w >= work)
+ *w-- = '0';
+ }
+
+ if(is_alt && base == 16)
+ width -= 2;
+
+ if(is_neg || (flags & FLAGS_SHOWSIGN) || (flags & FLAGS_SPACE))
+ --width;
+
+ if(!(flags & FLAGS_LEFT) && !(flags & FLAGS_PAD_NIL))
+ while(width-- > 0)
+ OUTCHAR(' ');
+
+ if(is_neg)
+ OUTCHAR('-');
+ else if(flags & FLAGS_SHOWSIGN)
+ OUTCHAR('+');
+ else if(flags & FLAGS_SPACE)
+ OUTCHAR(' ');
+
+ if(is_alt && base == 16) {
+ OUTCHAR('0');
+ if(flags & FLAGS_UPPER)
+ OUTCHAR('X');
+ else
+ OUTCHAR('x');
+ }
+
+ if(!(flags & FLAGS_LEFT) && (flags & FLAGS_PAD_NIL))
+ while(width-- > 0)
+ OUTCHAR('0');
+
+ /* Write the number. */
+ while(++w <= workend) {
+ OUTCHAR(*w);
+ }
+
+ if(flags & FLAGS_LEFT)
+ while(width-- > 0)
+ OUTCHAR(' ');
+
+ return FALSE;
+}
+
+static const char nilstr[] = "(nil)";
+
+static bool out_string(void *userp,
+ int (*stream)(unsigned char, void *),
+ struct mproperty *p,
+ const char *str,
+ int *donep)
+{
+ int flags = p->flags;
+ int width = p->width;
+ int prec = p->prec;
+ size_t len;
+
+ if(!str) {
+ /* Write null string if there is space. */
+ if(prec == -1 || prec >= (int) sizeof(nilstr) - 1) {
+ str = nilstr;
+ len = sizeof(nilstr) - 1;
+ /* Disable quotes around (nil) */
+ flags &= ~(unsigned int)FLAGS_ALT;
+ }
+ else {
+ str = "";
+ len = 0;
+ }
+ }
+ else if(prec != -1)
+ len = (size_t)prec;
+ else if(*str == '\0')
+ len = 0;
+ else
+ len = strlen(str);
+
+ width -= (len > INT_MAX) ? INT_MAX : (int)len;
+
+ if(flags & FLAGS_ALT)
+ OUTCHAR('"');
+
+ if(!(flags & FLAGS_LEFT))
+ while(width-- > 0)
+ OUTCHAR(' ');
+
+ for(; len && *str; len--)
+ OUTCHAR(*str++);
+ if(flags & FLAGS_LEFT)
+ while(width-- > 0)
+ OUTCHAR(' ');
+
+ if(flags & FLAGS_ALT)
+ OUTCHAR('"');
+
+ return FALSE;
+}
+
+static bool out_pointer(void *userp,
+ int (*stream)(unsigned char, void *),
+ struct mproperty *p,
+ const char *ptr,
+ char *work,
+ int *donep)
+{
+ /* Generic pointer. */
+ if(ptr) {
+ size_t num = (size_t) ptr;
+
+ /* If the pointer is not NULL, write it as a %#x spec. */
+ p->flags |= FLAGS_HEX|FLAGS_ALT;
+ if(out_number(userp, stream, p, num, 0, work, donep))
+ return TRUE;
+ }
+ else {
+ /* Write "(nil)" for a nil pointer. */
+ const char *point;
+ int width = p->width;
+ int flags = p->flags;
+
+ width -= (int)(sizeof(nilstr) - 1);
+ if(flags & FLAGS_LEFT)
+ while(width-- > 0)
+ OUTCHAR(' ');
+ for(point = nilstr; *point; ++point)
+ OUTCHAR(*point);
+ if(!(flags & FLAGS_LEFT))
+ while(width-- > 0)
+ OUTCHAR(' ');
+ }
+ return FALSE;
+}
+
/*
* formatf() - the general printf function.
*
@@ -648,8 +970,6 @@ static int formatf(
const char *format, /* %-formatted string */
va_list ap_save) /* list of parameters */
{
- static const char nilstr[] = "(nil)";
- const char *digits = lower_digits; /* Base-36 digits for numbers. */
int done = 0; /* number of characters written */
int i;
int ocount = 0; /* number of output segments */
@@ -659,370 +979,102 @@ static int formatf(
struct va_input input[MAX_PARAMETERS];
char work[BUFFSIZE + 2];
- /* 'workend' points to the final buffer byte position, but with an extra
- byte as margin to avoid the (FALSE?) warning Coverity gives us
- otherwise */
- char *workend = &work[BUFFSIZE - 2];
-
/* Parse the format string */
if(parsefmt(format, output, input, &ocount, &icount, ap_save))
return 0;
for(i = 0; i < ocount; i++) {
struct outsegment *optr = &output[i];
- struct va_input *iptr;
- bool is_alt; /* Format spec modifiers. */
- int width; /* Width of a field. */
- int prec; /* Precision of a field. */
- bool is_neg; /* Decimal integer is negative. */
- unsigned long base; /* Base of a number to be written. */
- mp_uintmax_t num; /* Integral values to be written. */
- mp_intmax_t signed_num; /* Used to convert negative in positive. */
- char *w;
+ struct va_input *iptr = &input[optr->input];
+ struct mproperty p;
size_t outlen = optr->outlen;
- unsigned int flags = optr->flags;
if(outlen) {
const char *str = optr->start;
- for(; outlen && *str; outlen--)
- OUTCHAR(*str++);
+ for(; outlen && *str; outlen--) {
+ if(stream(*str++, userp))
+ return done;
+ done++;
+ }
if(optr->flags & FLAGS_SUBSTR)
/* this is just a substring */
continue;
}
+ p.flags = optr->flags;
+
/* pick up the specified width */
- if(flags & FLAGS_WIDTHPARAM) {
- width = (int)input[optr->width].val.nums;
- if(width < 0) {
+ if(p.flags & FLAGS_WIDTHPARAM) {
+ p.width = (int)input[optr->width].val.nums;
+ if(p.width < 0) {
/* "A negative field width is taken as a '-' flag followed by a
positive field width." */
- if(width == INT_MIN)
- width = INT_MAX;
+ if(p.width == INT_MIN)
+ p.width = INT_MAX;
else
- width = -width;
- flags |= FLAGS_LEFT;
- flags &= ~(unsigned int)FLAGS_PAD_NIL;
+ p.width = -p.width;
+ p.flags |= FLAGS_LEFT;
+ p.flags &= ~(unsigned int)FLAGS_PAD_NIL;
}
}
else
- width = optr->width;
+ p.width = optr->width;
/* pick up the specified precision */
- if(flags & FLAGS_PRECPARAM) {
- prec = (int)input[optr->precision].val.nums;
- if(prec < 0)
+ if(p.flags & FLAGS_PRECPARAM) {
+ p.prec = (int)input[optr->precision].val.nums;
+ if(p.prec < 0)
/* "A negative precision is taken as if the precision were
omitted." */
- prec = -1;
+ p.prec = -1;
}
- else if(flags & FLAGS_PREC)
- prec = optr->precision;
+ else if(p.flags & FLAGS_PREC)
+ p.prec = optr->precision;
else
- prec = -1;
-
- is_alt = (flags & FLAGS_ALT) ? 1 : 0;
- iptr = &input[optr->input];
+ p.prec = -1;
switch(iptr->type) {
case FORMAT_INTU:
case FORMAT_LONGU:
case FORMAT_LONGLONGU:
- flags |= FLAGS_UNSIGNED;
- FALLTHROUGH();
+ p.flags |= FLAGS_UNSIGNED;
+ if(out_number(userp, stream, &p, iptr->val.numu, 0, work, &done))
+ return done;
+ break;
+
case FORMAT_INT:
case FORMAT_LONG:
case FORMAT_LONGLONG:
- num = iptr->val.numu;
- if(flags & FLAGS_CHAR) {
- /* Character. */
- if(!(flags & FLAGS_LEFT))
- while(--width > 0)
- OUTCHAR(' ');
- OUTCHAR((char) num);
- if(flags & FLAGS_LEFT)
- while(--width > 0)
- OUTCHAR(' ');
- break;
- }
- if(flags & FLAGS_OCTAL) {
- /* Octal unsigned integer */
- base = 8;
- is_neg = FALSE;
- }
- else if(flags & FLAGS_HEX) {
- /* Hexadecimal unsigned integer */
- digits = (flags & FLAGS_UPPER) ? upper_digits : lower_digits;
- base = 16;
- is_neg = FALSE;
- }
- else if(flags & FLAGS_UNSIGNED) {
- /* Decimal unsigned integer */
- base = 10;
- is_neg = FALSE;
- }
- else {
- /* Decimal integer. */
- base = 10;
-
- is_neg = (iptr->val.nums < (mp_intmax_t)0);
- if(is_neg) {
- /* signed_num might fail to hold absolute negative minimum by 1 */
- signed_num = iptr->val.nums + (mp_intmax_t)1;
- signed_num = -signed_num;
- num = (mp_uintmax_t)signed_num;
- num += (mp_uintmax_t)1;
- }
- }
-number:
- /* Supply a default precision if none was given. */
- if(prec == -1)
- prec = 1;
-
- /* Put the number in WORK. */
- w = workend;
- switch(base) {
- case 10:
- while(num > 0) {
- *w-- = (char)('0' + (num % 10));
- num /= 10;
- }
- break;
- default:
- while(num > 0) {
- *w-- = digits[num % base];
- num /= base;
- }
- break;
- }
- width -= (int)(workend - w);
- prec -= (int)(workend - w);
-
- if(is_alt && base == 8 && prec <= 0) {
- *w-- = '0';
- --width;
- }
-
- if(prec > 0) {
- width -= prec;
- while(prec-- > 0 && w >= work)
- *w-- = '0';
- }
-
- if(is_alt && base == 16)
- width -= 2;
-
- if(is_neg || (flags & FLAGS_SHOWSIGN) || (flags & FLAGS_SPACE))
- --width;
-
- if(!(flags & FLAGS_LEFT) && !(flags & FLAGS_PAD_NIL))
- while(width-- > 0)
- OUTCHAR(' ');
-
- if(is_neg)
- OUTCHAR('-');
- else if(flags & FLAGS_SHOWSIGN)
- OUTCHAR('+');
- else if(flags & FLAGS_SPACE)
- OUTCHAR(' ');
-
- if(is_alt && base == 16) {
- OUTCHAR('0');
- if(flags & FLAGS_UPPER)
- OUTCHAR('X');
- else
- OUTCHAR('x');
- }
-
- if(!(flags & FLAGS_LEFT) && (flags & FLAGS_PAD_NIL))
- while(width-- > 0)
- OUTCHAR('0');
-
- /* Write the number. */
- while(++w <= workend) {
- OUTCHAR(*w);
- }
-
- if(flags & FLAGS_LEFT)
- while(width-- > 0)
- OUTCHAR(' ');
+ if(out_number(userp, stream, &p, iptr->val.numu,
+ iptr->val.nums, work, &done))
+ return done;
break;
- case FORMAT_STRING: {
- const char *str;
- size_t len;
-
- str = iptr->val.str;
- if(!str) {
- /* Write null string if there is space. */
- if(prec == -1 || prec >= (int) sizeof(nilstr) - 1) {
- str = nilstr;
- len = sizeof(nilstr) - 1;
- /* Disable quotes around (nil) */
- flags &= ~(unsigned int)FLAGS_ALT;
- }
- else {
- str = "";
- len = 0;
- }
- }
- else if(prec != -1)
- len = (size_t)prec;
- else if(*str == '\0')
- len = 0;
- else
- len = strlen(str);
-
- width -= (len > INT_MAX) ? INT_MAX : (int)len;
-
- if(flags & FLAGS_ALT)
- OUTCHAR('"');
-
- if(!(flags & FLAGS_LEFT))
- while(width-- > 0)
- OUTCHAR(' ');
-
- for(; len && *str; len--)
- OUTCHAR(*str++);
- if(flags & FLAGS_LEFT)
- while(width-- > 0)
- OUTCHAR(' ');
-
- if(flags & FLAGS_ALT)
- OUTCHAR('"');
+ case FORMAT_STRING:
+ if(out_string(userp, stream, &p, iptr->val.str, &done))
+ return done;
break;
- }
case FORMAT_PTR:
- /* Generic pointer. */
- if(iptr->val.ptr) {
- /* If the pointer is not NULL, write it as a %#x spec. */
- base = 16;
- digits = (flags & FLAGS_UPPER) ? upper_digits : lower_digits;
- is_alt = TRUE;
- num = (size_t) iptr->val.ptr;
- is_neg = FALSE;
- goto number;
- }
- else {
- /* Write "(nil)" for a nil pointer. */
- const char *point;
-
- width -= (int)(sizeof(nilstr) - 1);
- if(flags & FLAGS_LEFT)
- while(width-- > 0)
- OUTCHAR(' ');
- for(point = nilstr; *point != '\0'; ++point)
- OUTCHAR(*point);
- if(!(flags & FLAGS_LEFT))
- while(width-- > 0)
- OUTCHAR(' ');
- }
+ if(out_pointer(userp, stream, &p, iptr->val.ptr, work, &done))
+ return done;
break;
- case FORMAT_DOUBLE: {
- char formatbuf[32]="%";
- char *fptr = &formatbuf[1];
- size_t left = sizeof(formatbuf)-strlen(formatbuf);
- int len;
-
- if(flags & FLAGS_WIDTH)
- width = optr->width;
-
- if(flags & FLAGS_PREC)
- prec = optr->precision;
-
- if(flags & FLAGS_LEFT)
- *fptr++ = '-';
- if(flags & FLAGS_SHOWSIGN)
- *fptr++ = '+';
- if(flags & FLAGS_SPACE)
- *fptr++ = ' ';
- if(flags & FLAGS_ALT)
- *fptr++ = '#';
-
- *fptr = 0;
-
- if(width >= 0) {
- size_t dlen;
- if(width >= BUFFSIZE)
- width = BUFFSIZE - 1;
- /* RECURSIVE USAGE */
- dlen = (size_t)curl_msnprintf(fptr, left, "%d", width);
- fptr += dlen;
- left -= dlen;
- }
- if(prec >= 0) {
- /* for each digit in the integer part, we can have one less
- precision */
- int maxprec = BUFFSIZE - 1;
- double val = iptr->val.dnum;
- if(prec > maxprec)
- prec = maxprec - 1;
- if(width > 0 && prec <= width)
- maxprec -= width;
- while(val >= 10.0) {
- val /= 10;
- maxprec--;
- }
-
- if(prec > maxprec)
- prec = maxprec - 1;
- if(prec < 0)
- prec = 0;
- /* RECURSIVE USAGE */
- len = curl_msnprintf(fptr, left, ".%d", prec);
- fptr += len;
- }
- if(flags & FLAGS_LONG)
- *fptr++ = 'l';
-
- if(flags & FLAGS_FLOATE)
- *fptr++ = (char)((flags & FLAGS_UPPER) ? 'E' : 'e');
- else if(flags & FLAGS_FLOATG)
- *fptr++ = (char)((flags & FLAGS_UPPER) ? 'G' : 'g');
- else
- *fptr++ = 'f';
-
- *fptr = 0; /* and a final null-termination */
-
-#ifdef __clang__
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wformat-nonliteral"
-#endif
- /* NOTE NOTE NOTE!! Not all sprintf implementations return number of
- output characters */
-#ifdef HAVE_SNPRINTF
- /* !checksrc! disable LONGLINE */
- /* NOLINTNEXTLINE(clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling) */
- (snprintf)(work, BUFFSIZE, formatbuf, iptr->val.dnum);
-#ifdef _WIN32
- /* Old versions of the Windows CRT do not terminate the snprintf output
- buffer if it reaches the max size so we do that here. */
- work[BUFFSIZE - 1] = 0;
-#endif
-#else
- (sprintf)(work, formatbuf, iptr->val.dnum);
-#endif
-#ifdef __clang__
-#pragma clang diagnostic pop
-#endif
- DEBUGASSERT(strlen(work) < BUFFSIZE);
- for(fptr = work; *fptr; fptr++)
- OUTCHAR(*fptr);
+ case FORMAT_DOUBLE:
+ if(out_double(userp, stream, &p, iptr->val.dnum, work, &done))
+ return done;
break;
- }
case FORMAT_INTPTR:
/* Answer the count of characters written. */
#ifdef HAVE_LONG_LONG_TYPE
- if(flags & FLAGS_LONGLONG)
+ if(p.flags & FLAGS_LONGLONG)
*(LONG_LONG_TYPE *) iptr->val.ptr = (LONG_LONG_TYPE)done;
else
#endif
- if(flags & FLAGS_LONG)
+ if(p.flags & FLAGS_LONG)
*(long *) iptr->val.ptr = (long)done;
- else if(!(flags & FLAGS_SHORT))
+ else if(!(p.flags & FLAGS_SHORT))
*(int *) iptr->val.ptr = (int)done;
else
*(short *) iptr->val.ptr = (short)done;
@@ -1087,7 +1139,7 @@ int curl_msnprintf(char *buffer, size_t maxlength, const char *format, ...)
static int alloc_addbyter(unsigned char outc, void *f)
{
struct asprintf *infop = f;
- CURLcode result = Curl_dyn_addn(infop->b, &outc, 1);
+ CURLcode result = curlx_dyn_addn(infop->b, &outc, 1);
if(result) {
infop->merr = result == CURLE_TOO_LARGE ? MERR_TOO_LARGE : MERR_MEM;
return 1 ; /* fail */
@@ -1096,7 +1148,7 @@ static int alloc_addbyter(unsigned char outc, void *f)
}
/* appends the formatted string, returns MERR error code */
-int Curl_dyn_vprintf(struct dynbuf *dyn, const char *format, va_list ap_save)
+int curlx_dyn_vprintf(struct dynbuf *dyn, const char *format, va_list ap_save)
{
struct asprintf info;
info.b = dyn;
@@ -1104,7 +1156,7 @@ int Curl_dyn_vprintf(struct dynbuf *dyn, const char *format, va_list ap_save)
(void)formatf(&info, alloc_addbyter, format, ap_save);
if(info.merr) {
- Curl_dyn_free(info.b);
+ curlx_dyn_free(info.b);
return info.merr;
}
return 0;
@@ -1115,16 +1167,16 @@ char *curl_mvaprintf(const char *format, va_list ap_save)
struct asprintf info;
struct dynbuf dyn;
info.b = &dyn;
- Curl_dyn_init(info.b, DYN_APRINTF);
+ curlx_dyn_init(info.b, DYN_APRINTF);
info.merr = MERR_OK;
(void)formatf(&info, alloc_addbyter, format, ap_save);
if(info.merr) {
- Curl_dyn_free(info.b);
+ curlx_dyn_free(info.b);
return NULL;
}
- if(Curl_dyn_len(info.b))
- return Curl_dyn_ptr(info.b);
+ if(curlx_dyn_len(info.b))
+ return curlx_dyn_ptr(info.b);
return strdup("");
}
diff --git a/libs/libcurl/src/mqtt.c b/libs/libcurl/src/mqtt.c
index eae4b4ceb7..568ca4ceab 100644
--- a/libs/libcurl/src/mqtt.c
+++ b/libs/libcurl/src/mqtt.c
@@ -37,7 +37,7 @@
#include "strdup.h"
#include "url.h"
#include "escape.h"
-#include "warnless.h"
+#include "curlx/warnless.h"
#include "curl_printf.h"
#include "curl_memory.h"
#include "multiif.h"
@@ -46,17 +46,59 @@
/* The last #include file should be: */
#include "memdebug.h"
+/* first byte is command.
+ second byte is for flags. */
#define MQTT_MSG_CONNECT 0x10
/* #define MQTT_MSG_CONNACK 0x20 */
#define MQTT_MSG_PUBLISH 0x30
#define MQTT_MSG_SUBSCRIBE 0x82
#define MQTT_MSG_SUBACK 0x90
#define MQTT_MSG_DISCONNECT 0xe0
+#define MQTT_MSG_PINGREQ 0xC0
+#define MQTT_MSG_PINGRESP 0xD0
#define MQTT_CONNACK_LEN 2
#define MQTT_SUBACK_LEN 3
#define MQTT_CLIENTID_LEN 12 /* "curl0123abcd" */
+/* meta key for storing protocol meta at easy handle */
+#define CURL_META_MQTT_EASY "meta:proto:mqtt:easy"
+/* meta key for storing protocol meta at connection */
+#define CURL_META_MQTT_CONN "meta:proto:mqtt:conn"
+
+enum mqttstate {
+ MQTT_FIRST, /* 0 */
+ MQTT_REMAINING_LENGTH, /* 1 */
+ MQTT_CONNACK, /* 2 */
+ MQTT_SUBACK, /* 3 */
+ MQTT_SUBACK_COMING, /* 4 - the SUBACK remainder */
+ MQTT_PUBWAIT, /* 5 - wait for publish */
+ MQTT_PUB_REMAIN, /* 6 - wait for the remainder of the publish */
+
+ MQTT_NOSTATE /* 7 - never used an actual state */
+};
+
+struct mqtt_conn {
+ enum mqttstate state;
+ enum mqttstate nextstate; /* switch to this after remaining length is
+ done */
+ unsigned int packetid;
+};
+
+/* protocol-specific transfer-related data */
+struct MQTT {
+ struct dynbuf sendbuf;
+ /* when receiving */
+ struct dynbuf recvbuf;
+ size_t npacket; /* byte counter */
+ size_t remaining_length;
+ unsigned char pkt_hd[4]; /* for decoding the arriving packet length */
+ struct curltime lastTime; /* last time we sent or received data */
+ unsigned char firstbyte;
+ BIT(pingsent); /* 1 while we wait for ping response */
+};
+
+
/*
* Forward declarations.
*/
@@ -99,45 +141,72 @@ const struct Curl_handler Curl_handler_mqtt = {
PROTOPT_NONE /* flags */
};
+static void mqtt_easy_dtor(void *key, size_t klen, void *entry)
+{
+ struct MQTT *mq = entry;
+ (void)key;
+ (void)klen;
+ curlx_dyn_free(&mq->sendbuf);
+ curlx_dyn_free(&mq->recvbuf);
+ free(mq);
+}
+
+static void mqtt_conn_dtor(void *key, size_t klen, void *entry)
+{
+ (void)key;
+ (void)klen;
+ free(entry);
+}
+
static CURLcode mqtt_setup_conn(struct Curl_easy *data,
struct connectdata *conn)
{
- /* allocate the HTTP-specific struct for the Curl_easy, only to survive
- during this request */
+ /* setup MQTT specific meta data at easy handle and connection */
+ struct mqtt_conn *mqtt;
struct MQTT *mq;
- (void)conn;
- DEBUGASSERT(data->req.p.mqtt == NULL);
+
+ mqtt = calloc(1, sizeof(*mqtt));
+ if(!mqtt ||
+ Curl_conn_meta_set(conn, CURL_META_MQTT_CONN, mqtt, mqtt_conn_dtor))
+ return CURLE_OUT_OF_MEMORY;
mq = calloc(1, sizeof(struct MQTT));
if(!mq)
return CURLE_OUT_OF_MEMORY;
- Curl_dyn_init(&mq->recvbuf, DYN_MQTT_RECV);
- Curl_dyn_init(&mq->sendbuf, DYN_MQTT_SEND);
- data->req.p.mqtt = mq;
+ curlx_dyn_init(&mq->recvbuf, DYN_MQTT_RECV);
+ curlx_dyn_init(&mq->sendbuf, DYN_MQTT_SEND);
+ if(Curl_meta_set(data, CURL_META_MQTT_EASY, mq, mqtt_easy_dtor))
+ return CURLE_OUT_OF_MEMORY;
return CURLE_OK;
}
static CURLcode mqtt_send(struct Curl_easy *data,
const char *buf, size_t len)
{
- struct MQTT *mq = data->req.p.mqtt;
size_t n;
- CURLcode result = Curl_xfer_send(data, buf, len, FALSE, &n);
+ CURLcode result;
+ struct MQTT *mq = Curl_meta_get(data, CURL_META_MQTT_EASY);
+
+ if(!mq)
+ return CURLE_FAILED_INIT;
+
+ result = Curl_xfer_send(data, buf, len, FALSE, &n);
if(result)
return result;
+ mq->lastTime = curlx_now();
Curl_debug(data, CURLINFO_HEADER_OUT, buf, (size_t)n);
if(len != n) {
size_t nsend = len - n;
- if(Curl_dyn_len(&mq->sendbuf)) {
- DEBUGASSERT(Curl_dyn_len(&mq->sendbuf) >= nsend);
- result = Curl_dyn_tail(&mq->sendbuf, nsend); /* keep this much */
+ if(curlx_dyn_len(&mq->sendbuf)) {
+ DEBUGASSERT(curlx_dyn_len(&mq->sendbuf) >= nsend);
+ result = curlx_dyn_tail(&mq->sendbuf, nsend); /* keep this much */
}
else {
- result = Curl_dyn_addn(&mq->sendbuf, &buf[n], nsend);
+ result = curlx_dyn_addn(&mq->sendbuf, &buf[n], nsend);
}
}
else
- Curl_dyn_reset(&mq->sendbuf);
+ curlx_dyn_reset(&mq->sendbuf);
return result;
}
@@ -344,20 +413,19 @@ end:
static CURLcode mqtt_disconnect(struct Curl_easy *data)
{
- CURLcode result = CURLE_OK;
- struct MQTT *mq = data->req.p.mqtt;
- result = mqtt_send(data, "\xe0\x00", 2);
- Curl_dyn_free(&mq->sendbuf);
- Curl_dyn_free(&mq->recvbuf);
- return result;
+ return mqtt_send(data, "\xe0\x00", 2);
}
static CURLcode mqtt_recv_atleast(struct Curl_easy *data, size_t nbytes)
{
- struct MQTT *mq = data->req.p.mqtt;
- size_t rlen = Curl_dyn_len(&mq->recvbuf);
+ struct MQTT *mq = Curl_meta_get(data, CURL_META_MQTT_EASY);
+ size_t rlen;
CURLcode result;
+ if(!mq)
+ return CURLE_FAILED_INIT;
+ rlen = curlx_dyn_len(&mq->recvbuf);
+
if(rlen < nbytes) {
unsigned char readbuf[1024];
ssize_t nread;
@@ -367,42 +435,49 @@ static CURLcode mqtt_recv_atleast(struct Curl_easy *data, size_t nbytes)
if(result)
return result;
DEBUGASSERT(nread >= 0);
- if(Curl_dyn_addn(&mq->recvbuf, readbuf, (size_t)nread))
+ if(curlx_dyn_addn(&mq->recvbuf, readbuf, (size_t)nread))
return CURLE_OUT_OF_MEMORY;
- rlen = Curl_dyn_len(&mq->recvbuf);
+ rlen = curlx_dyn_len(&mq->recvbuf);
}
return (rlen >= nbytes) ? CURLE_OK : CURLE_AGAIN;
}
static void mqtt_recv_consume(struct Curl_easy *data, size_t nbytes)
{
- struct MQTT *mq = data->req.p.mqtt;
- size_t rlen = Curl_dyn_len(&mq->recvbuf);
- if(rlen <= nbytes)
- Curl_dyn_reset(&mq->recvbuf);
- else
- Curl_dyn_tail(&mq->recvbuf, rlen - nbytes);
+ struct MQTT *mq = Curl_meta_get(data, CURL_META_MQTT_EASY);
+ DEBUGASSERT(mq);
+ if(mq) {
+ size_t rlen = curlx_dyn_len(&mq->recvbuf);
+ if(rlen <= nbytes)
+ curlx_dyn_reset(&mq->recvbuf);
+ else
+ curlx_dyn_tail(&mq->recvbuf, rlen - nbytes);
+ }
}
static CURLcode mqtt_verify_connack(struct Curl_easy *data)
{
- struct MQTT *mq = data->req.p.mqtt;
+ struct MQTT *mq = Curl_meta_get(data, CURL_META_MQTT_EASY);
CURLcode result;
char *ptr;
+ DEBUGASSERT(mq);
+ if(!mq)
+ return CURLE_FAILED_INIT;
+
result = mqtt_recv_atleast(data, MQTT_CONNACK_LEN);
if(result)
goto fail;
/* verify CONNACK */
- DEBUGASSERT(Curl_dyn_len(&mq->recvbuf) >= MQTT_CONNACK_LEN);
- ptr = Curl_dyn_ptr(&mq->recvbuf);
+ DEBUGASSERT(curlx_dyn_len(&mq->recvbuf) >= MQTT_CONNACK_LEN);
+ ptr = curlx_dyn_ptr(&mq->recvbuf);
Curl_debug(data, CURLINFO_HEADER_IN, ptr, MQTT_CONNACK_LEN);
if(ptr[0] != 0x00 || ptr[1] != 0x00) {
failf(data, "Expected %02x%02x but got %02x%02x",
0x00, 0x00, ptr[0], ptr[1]);
- Curl_dyn_reset(&mq->recvbuf);
+ curlx_dyn_reset(&mq->recvbuf);
result = CURLE_WEIRD_SERVER_REPLY;
goto fail;
}
@@ -439,12 +514,16 @@ static CURLcode mqtt_subscribe(struct Curl_easy *data)
char encodedsize[4];
size_t n;
struct connectdata *conn = data->conn;
+ struct mqtt_conn *mqtt = Curl_conn_meta_get(conn, CURL_META_MQTT_CONN);
+
+ if(!mqtt)
+ return CURLE_FAILED_INIT;
result = mqtt_get_topic(data, &topic, &topiclen);
if(result)
goto fail;
- conn->proto.mqtt.packetid++;
+ mqtt->packetid++;
packetlen = topiclen + 5; /* packetid + topic (has a two byte length field)
+ 2 bytes topic length + QoS byte */
@@ -459,8 +538,8 @@ static CURLcode mqtt_subscribe(struct Curl_easy *data)
packet[0] = MQTT_MSG_SUBSCRIBE;
memcpy(&packet[1], encodedsize, n);
- packet[1 + n] = (conn->proto.mqtt.packetid >> 8) & 0xff;
- packet[2 + n] = conn->proto.mqtt.packetid & 0xff;
+ packet[1 + n] = (mqtt->packetid >> 8) & 0xff;
+ packet[2 + n] = mqtt->packetid & 0xff;
packet[3 + n] = (topiclen >> 8) & 0xff;
packet[4 + n ] = topiclen & 0xff;
memcpy(&packet[5 + n], topic, topiclen);
@@ -479,25 +558,28 @@ fail:
*/
static CURLcode mqtt_verify_suback(struct Curl_easy *data)
{
- struct MQTT *mq = data->req.p.mqtt;
+ struct MQTT *mq = Curl_meta_get(data, CURL_META_MQTT_EASY);
struct connectdata *conn = data->conn;
- struct mqtt_conn *mqtt = &conn->proto.mqtt;
+ struct mqtt_conn *mqtt = Curl_conn_meta_get(conn, CURL_META_MQTT_CONN);
CURLcode result;
char *ptr;
+ if(!mqtt || !mq)
+ return CURLE_FAILED_INIT;
+
result = mqtt_recv_atleast(data, MQTT_SUBACK_LEN);
if(result)
goto fail;
/* verify SUBACK */
- DEBUGASSERT(Curl_dyn_len(&mq->recvbuf) >= MQTT_SUBACK_LEN);
- ptr = Curl_dyn_ptr(&mq->recvbuf);
+ DEBUGASSERT(curlx_dyn_len(&mq->recvbuf) >= MQTT_SUBACK_LEN);
+ ptr = curlx_dyn_ptr(&mq->recvbuf);
Curl_debug(data, CURLINFO_HEADER_IN, ptr, MQTT_SUBACK_LEN);
if(((unsigned char)ptr[0]) != ((mqtt->packetid >> 8) & 0xff) ||
((unsigned char)ptr[1]) != (mqtt->packetid & 0xff) ||
ptr[2] != 0x00) {
- Curl_dyn_reset(&mq->recvbuf);
+ curlx_dyn_reset(&mq->recvbuf);
result = CURLE_WEIRD_SERVER_REPLY;
goto fail;
}
@@ -601,7 +683,10 @@ static void mqstate(struct Curl_easy *data,
enum mqttstate nextstate) /* used if state == FIRST */
{
struct connectdata *conn = data->conn;
- struct mqtt_conn *mqtt = &conn->proto.mqtt;
+ struct mqtt_conn *mqtt = Curl_conn_meta_get(conn, CURL_META_MQTT_CONN);
+ DEBUGASSERT(mqtt);
+ if(!mqtt)
+ return;
#ifdef DEBUGBUILD
infof(data, "%s (from %s) (next is %s)",
statenames[state],
@@ -620,10 +705,14 @@ static CURLcode mqtt_read_publish(struct Curl_easy *data, bool *done)
struct connectdata *conn = data->conn;
ssize_t nread;
size_t remlen;
- struct mqtt_conn *mqtt = &conn->proto.mqtt;
- struct MQTT *mq = data->req.p.mqtt;
+ struct mqtt_conn *mqtt = Curl_conn_meta_get(conn, CURL_META_MQTT_CONN);
+ struct MQTT *mq = Curl_meta_get(data, CURL_META_MQTT_EASY);
unsigned char packet;
+ DEBUGASSERT(mqtt);
+ if(!mqtt || !mq)
+ return CURLE_FAILED_INIT;
+
switch(mqtt->state) {
MQTT_SUBACK_COMING:
case MQTT_SUBACK_COMING:
@@ -687,6 +776,9 @@ MQTT_SUBACK_COMING:
goto end;
}
+ /* we received something */
+ mq->lastTime = curlx_now();
+
/* if QoS is set, message contains packet id */
result = Curl_client_write(data, CLIENTWRITE_BODY, buffer, nread);
if(result)
@@ -709,9 +801,15 @@ end:
static CURLcode mqtt_do(struct Curl_easy *data, bool *done)
{
+ struct MQTT *mq = Curl_meta_get(data, CURL_META_MQTT_EASY);
CURLcode result = CURLE_OK;
*done = FALSE; /* unconditionally */
+ if(!mq)
+ return CURLE_FAILED_INIT;
+ mq->lastTime = curlx_now();
+ mq->pingsent = FALSE;
+
result = mqtt_connect(data);
if(result) {
failf(data, "Error %d sending MQTT CONNECT request", result);
@@ -724,32 +822,73 @@ static CURLcode mqtt_do(struct Curl_easy *data, bool *done)
static CURLcode mqtt_done(struct Curl_easy *data,
CURLcode status, bool premature)
{
- struct MQTT *mq = data->req.p.mqtt;
+ struct MQTT *mq = Curl_meta_get(data, CURL_META_MQTT_EASY);
(void)status;
(void)premature;
- Curl_dyn_free(&mq->sendbuf);
- Curl_dyn_free(&mq->recvbuf);
+ if(mq) {
+ curlx_dyn_free(&mq->sendbuf);
+ curlx_dyn_free(&mq->recvbuf);
+ }
return CURLE_OK;
}
+/* we ping regularly to avoid being disconnected by the server */
+static CURLcode mqtt_ping(struct Curl_easy *data)
+{
+ struct MQTT *mq = Curl_meta_get(data, CURL_META_MQTT_EASY);
+ CURLcode result = CURLE_OK;
+ struct connectdata *conn = data->conn;
+ struct mqtt_conn *mqtt = Curl_conn_meta_get(conn, CURL_META_MQTT_CONN);
+
+ if(!mqtt || !mq)
+ return CURLE_FAILED_INIT;
+
+ if(mqtt->state == MQTT_FIRST &&
+ !mq->pingsent &&
+ data->set.upkeep_interval_ms > 0) {
+ struct curltime t = curlx_now();
+ timediff_t diff = curlx_timediff(t, mq->lastTime);
+
+ if(diff > data->set.upkeep_interval_ms) {
+ /* 0xC0 is PINGREQ, and 0x00 is remaining length */
+ unsigned char packet[2] = { 0xC0, 0x00 };
+ size_t packetlen = sizeof(packet);
+
+ result = mqtt_send(data, (char *)packet, packetlen);
+ if(!result) {
+ mq->pingsent = TRUE;
+ }
+ infof(data, "mqtt_ping: sent ping request.");
+ }
+ }
+ return result;
+}
+
static CURLcode mqtt_doing(struct Curl_easy *data, bool *done)
{
+ struct MQTT *mq = Curl_meta_get(data, CURL_META_MQTT_EASY);
CURLcode result = CURLE_OK;
- struct mqtt_conn *mqtt = &data->conn->proto.mqtt;
- struct MQTT *mq = data->req.p.mqtt;
ssize_t nread;
unsigned char recvbyte;
+ struct mqtt_conn *mqtt = Curl_conn_meta_get(data->conn, CURL_META_MQTT_CONN);
+
+ if(!mqtt || !mq)
+ return CURLE_FAILED_INIT;
*done = FALSE;
- if(Curl_dyn_len(&mq->sendbuf)) {
+ if(curlx_dyn_len(&mq->sendbuf)) {
/* send the remainder of an outgoing packet */
- result = mqtt_send(data, Curl_dyn_ptr(&mq->sendbuf),
- Curl_dyn_len(&mq->sendbuf));
+ result = mqtt_send(data, curlx_dyn_ptr(&mq->sendbuf),
+ curlx_dyn_len(&mq->sendbuf));
if(result)
return result;
}
+ result = mqtt_ping(data);
+ if(result)
+ return result;
+
infof(data, "mqtt_doing: state [%d]", (int) mqtt->state);
switch(mqtt->state) {
case MQTT_FIRST:
@@ -764,6 +903,10 @@ static CURLcode mqtt_doing(struct Curl_easy *data, bool *done)
break;
}
Curl_debug(data, CURLINFO_HEADER_IN, (const char *)&mq->firstbyte, 1);
+
+ /* we received something */
+ mq->lastTime = curlx_now();
+
/* remember the first byte */
mq->npacket = 0;
mqstate(data, MQTT_REMAINING_LENGTH, MQTT_NOSTATE);
@@ -794,6 +937,13 @@ static CURLcode mqtt_doing(struct Curl_easy *data, bool *done)
infof(data, "Got DISCONNECT");
*done = TRUE;
}
+
+ /* ping response */
+ if(mq->firstbyte == MQTT_MSG_PINGRESP) {
+ infof(data, "Received ping response.");
+ mq->pingsent = FALSE;
+ mqstate(data, MQTT_FIRST, MQTT_PUBWAIT);
+ }
break;
case MQTT_CONNACK:
result = mqtt_verify_connack(data);
diff --git a/libs/libcurl/src/mqtt.h b/libs/libcurl/src/mqtt.h
index 6393e0c552..53997588ee 100644
--- a/libs/libcurl/src/mqtt.h
+++ b/libs/libcurl/src/mqtt.h
@@ -28,34 +28,4 @@
extern const struct Curl_handler Curl_handler_mqtt;
#endif
-enum mqttstate {
- MQTT_FIRST, /* 0 */
- MQTT_REMAINING_LENGTH, /* 1 */
- MQTT_CONNACK, /* 2 */
- MQTT_SUBACK, /* 3 */
- MQTT_SUBACK_COMING, /* 4 - the SUBACK remainder */
- MQTT_PUBWAIT, /* 5 - wait for publish */
- MQTT_PUB_REMAIN, /* 6 - wait for the remainder of the publish */
-
- MQTT_NOSTATE /* 7 - never used an actual state */
-};
-
-struct mqtt_conn {
- enum mqttstate state;
- enum mqttstate nextstate; /* switch to this after remaining length is
- done */
- unsigned int packetid;
-};
-
-/* protocol-specific transfer-related data */
-struct MQTT {
- struct dynbuf sendbuf;
- /* when receiving */
- struct dynbuf recvbuf;
- size_t npacket; /* byte counter */
- size_t remaining_length;
- unsigned char pkt_hd[4]; /* for decoding the arriving packet length */
- unsigned char firstbyte;
-};
-
#endif /* HEADER_CURL_MQTT_H */
diff --git a/libs/libcurl/src/multi.c b/libs/libcurl/src/multi.c
index 1e63e54a45..942331df87 100644
--- a/libs/libcurl/src/multi.c
+++ b/libs/libcurl/src/multi.c
@@ -38,10 +38,10 @@
#include "multiif.h"
#include "multi_ev.h"
#include "sendf.h"
-#include "timeval.h"
+#include "curlx/timeval.h"
#include "http.h"
#include "select.h"
-#include "warnless.h"
+#include "curlx/warnless.h"
#include "speedcheck.h"
#include "conncache.h"
#include "multihandle.h"
@@ -58,6 +58,9 @@
#include "curl_memory.h"
#include "memdebug.h"
+/* initial multi->xfers table size for a full multi */
+#define CURL_XFER_TABLE_SIZE 512
+
/*
CURL_SOCKET_HASH_TABLE_SIZE should be a prime number. Increasing it from 97
to 911 takes on a 32-bit machine 4 x 804 = 3211 more bytes. Still, every
@@ -103,6 +106,9 @@ static CURLMcode multi_timeout(struct Curl_multi *multi,
long *timeout_ms);
static void process_pending_handles(struct Curl_multi *multi);
static void multi_xfer_bufs_free(struct Curl_multi *multi);
+#ifdef DEBUGBUILD
+static void multi_xfer_tbl_dump(struct Curl_multi *multi);
+#endif
/* function pointer called once when switching TO a state */
typedef void (*init_multistate_func)(struct Curl_easy *data);
@@ -166,10 +172,12 @@ static void mstate(struct Curl_easy *data, CURLMstate state
data->mstate = state;
if(state == MSTATE_COMPLETED) {
- /* changing to COMPLETED means there is one less easy handle 'alive' */
- DEBUGASSERT(data->multi->num_alive > 0);
- data->multi->num_alive--;
- if(!data->multi->num_alive) {
+ /* changing to COMPLETED means it is in process and needs to go */
+ DEBUGASSERT(Curl_uint_bset_contains(&data->multi->process, data->mid));
+ Curl_uint_bset_remove(&data->multi->process, data->mid);
+ Curl_uint_bset_remove(&data->multi->pending, data->mid); /* to be sure */
+
+ if(Curl_uint_bset_empty(&data->multi->process)) {
/* free the transfer buffer when we have no more active transfers */
multi_xfer_bufs_free(data->multi);
}
@@ -209,7 +217,8 @@ static void multi_addmsg(struct Curl_multi *multi, struct Curl_message *msg)
Curl_llist_append(&multi->msglist, msg, &msg->list);
}
-struct Curl_multi *Curl_multi_handle(size_t ev_hashsize, /* event hash */
+struct Curl_multi *Curl_multi_handle(unsigned int xfer_table_size,
+ size_t ev_hashsize, /* event hash */
size_t chashsize, /* connection hash */
size_t dnssize, /* dns hash */
size_t sesssize) /* TLS session cache */
@@ -221,11 +230,25 @@ struct Curl_multi *Curl_multi_handle(size_t ev_hashsize, /* event hash */
multi->magic = CURL_MULTI_HANDLE;
- Curl_init_dnscache(&multi->hostcache, dnssize);
+ Curl_dnscache_init(&multi->dnscache, dnssize);
Curl_multi_ev_init(multi, ev_hashsize);
-
+ Curl_uint_tbl_init(&multi->xfers, NULL);
+ Curl_uint_bset_init(&multi->process);
+ Curl_uint_bset_init(&multi->pending);
+ Curl_uint_bset_init(&multi->msgsent);
Curl_hash_init(&multi->proto_hash, 23,
- Curl_hash_str, Curl_str_key_compare, ph_freeentry);
+ Curl_hash_str, curlx_str_key_compare, ph_freeentry);
+ Curl_llist_init(&multi->msglist, NULL);
+
+ multi->multiplexing = TRUE;
+ multi->max_concurrent_streams = 100;
+ multi->last_timeout_ms = -1;
+
+ if(Curl_uint_bset_resize(&multi->process, xfer_table_size) ||
+ Curl_uint_bset_resize(&multi->pending, xfer_table_size) ||
+ Curl_uint_bset_resize(&multi->msgsent, xfer_table_size) ||
+ Curl_uint_tbl_resize(&multi->xfers, xfer_table_size))
+ goto error;
multi->admin = curl_easy_init();
if(!multi->admin)
@@ -238,25 +261,16 @@ struct Curl_multi *Curl_multi_handle(size_t ev_hashsize, /* event hash */
if(getenv("CURL_DEBUG"))
multi->admin->set.verbose = TRUE;
#endif
+ Curl_uint_tbl_add(&multi->xfers, multi->admin, &multi->admin->mid);
if(Curl_cshutdn_init(&multi->cshutdn, multi))
goto error;
- if(Curl_cpool_init(&multi->cpool, multi->admin, NULL, chashsize))
- goto error;
+ Curl_cpool_init(&multi->cpool, multi->admin, NULL, chashsize);
if(Curl_ssl_scache_create(sesssize, 2, &multi->ssl_scache))
goto error;
- Curl_llist_init(&multi->msglist, NULL);
- Curl_llist_init(&multi->process, NULL);
- Curl_llist_init(&multi->pending, NULL);
- Curl_llist_init(&multi->msgsent, NULL);
-
- multi->multiplexing = TRUE;
- multi->max_concurrent_streams = 100;
- multi->last_timeout_ms = -1;
-
#ifdef USE_WINSOCK
multi->wsa_event = WSACreateEvent();
if(multi->wsa_event == WSA_INVALID_EVENT)
@@ -276,7 +290,7 @@ error:
Curl_multi_ev_cleanup(multi);
Curl_hash_destroy(&multi->proto_hash);
- Curl_hash_destroy(&multi->hostcache);
+ Curl_dnscache_destroy(&multi->dnscache);
Curl_cpool_destroy(&multi->cpool);
Curl_cshutdn_destroy(&multi->cshutdn, multi->admin);
Curl_ssl_scache_destroy(multi->ssl_scache);
@@ -285,13 +299,19 @@ error:
Curl_close(&multi->admin);
}
+ Curl_uint_bset_destroy(&multi->process);
+ Curl_uint_bset_destroy(&multi->pending);
+ Curl_uint_bset_destroy(&multi->msgsent);
+ Curl_uint_tbl_destroy(&multi->xfers);
+
free(multi);
return NULL;
}
CURLM *curl_multi_init(void)
{
- return Curl_multi_handle(CURL_SOCKET_HASH_TABLE_SIZE,
+ return Curl_multi_handle(CURL_XFER_TABLE_SIZE,
+ CURL_SOCKET_HASH_TABLE_SIZE,
CURL_CONNECTION_HASH_SIZE,
CURL_DNS_HASH_SIZE,
CURL_TLS_SESSION_SIZE);
@@ -311,6 +331,43 @@ static void multi_warn_debug(struct Curl_multi *multi, struct Curl_easy *data)
#define multi_warn_debug(x,y) Curl_nop_stmt
#endif
+
+static CURLMcode multi_xfers_add(struct Curl_multi *multi,
+ struct Curl_easy *data)
+{
+ /* We want `multi->xfers` to have "sufficient" free rows, so that we do
+ * have to reuse the `mid` from a just removed easy right away.
+ * Since uint_tbl and uint_bset is quite memory efficient,
+ * regard less than 25% free as insufficient.
+ * (for low capacities, e.g. multi_easy, 4 or less). */
+ unsigned int capacity = Curl_uint_tbl_capacity(&multi->xfers);
+ unsigned int unused = capacity - Curl_uint_tbl_count(&multi->xfers);
+ unsigned int min_unused = CURLMAX(capacity >> 2, 4);
+
+ if(unused <= min_unused) {
+ /* make it a 64 multiple, since our bitsets frow by that and
+ * small (easy_multi) grows to at least 64 on first resize. */
+ unsigned int newsize = ((capacity + min_unused) + 63) / 64;
+ /* Grow the bitsets first. Should one fail, we do not need
+ * to downsize the already resized ones. The sets continue
+ * to work properly when larger than the table, but not
+ * the other way around. */
+ if(Curl_uint_bset_resize(&multi->process, newsize) ||
+ Curl_uint_bset_resize(&multi->pending, newsize) ||
+ Curl_uint_bset_resize(&multi->msgsent, newsize) ||
+ Curl_uint_tbl_resize(&multi->xfers, newsize))
+ return CURLM_OUT_OF_MEMORY;
+ CURL_TRC_M(data, "increased xfer table size to %u", newsize);
+ }
+ /* Insert the easy into the table now that MUST have room for it */
+ if(!Curl_uint_tbl_add(&multi->xfers, data, &data->mid)) {
+ DEBUGASSERT(0);
+ return CURLM_OUT_OF_MEMORY;
+ }
+ return CURLM_OK;
+}
+
+
CURLMcode curl_multi_add_handle(CURLM *m, CURL *d)
{
CURLMcode rc;
@@ -335,10 +392,15 @@ CURLMcode curl_multi_add_handle(CURLM *m, CURL *d)
if(multi->dead) {
/* a "dead" handle cannot get added transfers while any existing easy
handles are still alive - but if there are none alive anymore, it is
- fine to start over and unmark the "deadness" of this handle */
- if(multi->num_alive)
+ fine to start over and unmark the "deadness" of this handle.
+ This means only the admin handle MUST be present. */
+ if((Curl_uint_tbl_count(&multi->xfers) != 1) ||
+ !Curl_uint_tbl_contains(&multi->xfers, 0))
return CURLM_ABORTED_BY_CALLBACK;
multi->dead = FALSE;
+ Curl_uint_bset_clear(&multi->process);
+ Curl_uint_bset_clear(&multi->pending);
+ Curl_uint_bset_clear(&multi->msgsent);
}
if(data->multi_easy) {
@@ -348,6 +410,10 @@ CURLMcode curl_multi_add_handle(CURLM *m, CURL *d)
data->multi_easy = NULL;
}
+ /* Insert the easy into the multi->xfers table, assigning it a `mid`. */
+ if(multi_xfers_add(multi, data))
+ return CURLM_OUT_OF_MEMORY;
+
/* Initialize timeout list for this handle */
Curl_llist_init(&data->state.timeoutlist, NULL);
@@ -377,20 +443,14 @@ CURLMcode curl_multi_add_handle(CURLM *m, CURL *d)
rc = Curl_update_timer(multi);
if(rc) {
data->multi = NULL; /* not anymore */
+ Curl_uint_tbl_remove(&multi->xfers, data->mid);
+ data->mid = UINT_MAX;
return rc;
}
/* set the easy handle */
multistate(data, MSTATE_INIT);
- /* for multi interface connections, we share DNS cache automatically if the
- easy handle's one is currently not set. */
- if(!data->dns.hostcache ||
- (data->dns.hostcachetype == HCACHE_NONE)) {
- data->dns.hostcache = &multi->hostcache;
- data->dns.hostcachetype = HCACHE_MULTI;
- }
-
#ifdef USE_LIBPSL
/* Do the same for PSL. */
if(data->share && (data->share->specifier & (1 << CURL_LOCK_DATA_PSL)))
@@ -399,19 +459,9 @@ CURLMcode curl_multi_add_handle(CURLM *m, CURL *d)
data->psl = &multi->psl;
#endif
- /* add the easy handle to the process list */
- Curl_llist_append(&multi->process, data, &data->multi_queue);
-
- /* increase the node-counter */
- multi->num_easy++;
-
- /* increase the alive-counter */
- multi->num_alive++;
-
- /* the identifier inside the multi instance */
- data->mid = multi->next_easy_mid++;
- if(multi->next_easy_mid <= 0)
- multi->next_easy_mid = 0;
+ /* add the easy handle to the process set */
+ Curl_uint_bset_add(&multi->process, data->mid);
+ ++multi->xfers_alive;
Curl_cpool_xfer_init(data);
multi_warn_debug(multi, data);
@@ -425,7 +475,9 @@ CURLMcode curl_multi_add_handle(CURLM *m, CURL *d)
data->set.server_response_timeout;
multi->admin->set.no_signal = data->set.no_signal;
- CURL_TRC_M(data, "added, transfers=%u", multi->num_easy);
+ CURL_TRC_M(data, "added to multi, mid=%u, running=%u, total=%u",
+ data->mid, Curl_multi_xfers_running(multi),
+ Curl_uint_tbl_count(&multi->xfers));
return CURLM_OK;
}
@@ -457,19 +509,21 @@ static void multi_done_locked(struct connectdata *conn,
Curl_detach_connection(data);
+ CURL_TRC_M(data, "multi_done_locked, in use=%u",
+ Curl_uint_spbset_count(&conn->xfers_attached));
if(CONN_INUSE(conn)) {
/* Stop if still used. */
- CURL_TRC_M(data, "Connection still in use %zu, no more multi_done now!",
- Curl_llist_count(&conn->easyq));
+ CURL_TRC_M(data, "Connection still in use %u, no more multi_done now!",
+ Curl_uint_spbset_count(&conn->xfers_attached));
return;
}
data->state.done = TRUE; /* called just now! */
data->state.recent_conn_id = conn->connection_id;
- if(conn->dns_entry)
- Curl_resolv_unlink(data, &conn->dns_entry); /* done with this */
- Curl_hostcache_prune(data);
+ Curl_resolv_unlink(data, &data->state.dns[0]); /* done with this */
+ Curl_resolv_unlink(data, &data->state.dns[1]);
+ Curl_dnscache_prune(data);
/* if data->set.reuse_forbid is TRUE, it means the libcurl client has
forced us to close this connection. This is ignored for requests taking
@@ -547,8 +601,8 @@ static CURLcode multi_done(struct Curl_easy *data,
/* Stop if multi_done() has already been called */
return CURLE_OK;
- /* Stop the resolver and free its own resources (but not dns_entry yet). */
- Curl_resolver_kill(data);
+ /* Shut down any ongoing async resolver operation. */
+ Curl_async_shutdown(data);
/* Cleanup possible redirect junk */
Curl_safefree(data->req.newurl);
@@ -623,6 +677,7 @@ CURLMcode curl_multi_remove_handle(CURLM *m, CURL *d)
struct Curl_llist_node *e;
CURLMcode rc;
bool removed_timer = FALSE;
+ unsigned int mid;
/* First, make some basic checks that the CURLM handle is a good handle */
if(!GOOD_MULTI_HANDLE(multi))
@@ -640,7 +695,11 @@ CURLMcode curl_multi_remove_handle(CURLM *m, CURL *d)
if(data->multi != multi)
return CURLM_BAD_EASY_HANDLE;
- if(!multi->num_easy) {
+ if(data->mid == UINT_MAX) {
+ DEBUGASSERT(0);
+ return CURLM_INTERNAL_ERROR;
+ }
+ if(Curl_uint_tbl_get(&multi->xfers, data->mid) != data) {
DEBUGASSERT(0);
return CURLM_INTERNAL_ERROR;
}
@@ -652,12 +711,6 @@ CURLMcode curl_multi_remove_handle(CURLM *m, CURL *d)
/* If the 'state' is not INIT or COMPLETED, we might need to do something
nice to put the easy_handle in a good known state when this returns. */
- if(premature) {
- /* this handle is "alive" so we need to count down the total number of
- alive connections when this is removed */
- multi->num_alive--;
- }
-
if(data->conn &&
data->mstate > MSTATE_DO &&
data->mstate < MSTATE_COMPLETED) {
@@ -680,15 +733,9 @@ CURLMcode curl_multi_remove_handle(CURLM *m, CURL *d)
called. Do it after multi_done() in case that sets another time! */
removed_timer = Curl_expire_clear(data);
- /* the handle is in a list, remove it from whichever it is */
- Curl_node_remove(&data->multi_queue);
-
- if(data->dns.hostcachetype == HCACHE_MULTI) {
- /* stop using the multi handle's DNS cache, *after* the possible
- multi_done() call above */
- data->dns.hostcache = NULL;
- data->dns.hostcachetype = HCACHE_NONE;
- }
+ /* If in `msgsent`, it was deducted from `multi->xfers_alive` already. */
+ if(!Curl_uint_bset_contains(&multi->msgsent, data->mid))
+ --multi->xfers_alive;
Curl_wildcard_dtor(&data->wildcard);
@@ -741,12 +788,19 @@ CURLMcode curl_multi_remove_handle(CURLM *m, CURL *d)
}
}
- data->multi = NULL; /* clear the association to this multi handle */
- data->mid = -1;
+ /* clear the association to this multi handle */
+ mid = data->mid;
+ DEBUGASSERT(Curl_uint_tbl_contains(&multi->xfers, mid));
+ Curl_uint_tbl_remove(&multi->xfers, mid);
+ Curl_uint_bset_remove(&multi->process, mid);
+ Curl_uint_bset_remove(&multi->pending, mid);
+ Curl_uint_bset_remove(&multi->msgsent, mid);
+ data->multi = NULL;
+ data->mid = UINT_MAX;
+ data->master_mid = UINT_MAX;
/* NOTE NOTE NOTE
We do not touch the easy handle here! */
- multi->num_easy--; /* one less to care about now */
process_pending_handles(multi);
if(removed_timer) {
@@ -755,7 +809,9 @@ CURLMcode curl_multi_remove_handle(CURLM *m, CURL *d)
return rc;
}
- CURL_TRC_M(data, "removed, transfers=%u", multi->num_easy);
+ CURL_TRC_M(data, "removed from multi, mid=%u, running=%u, total=%u",
+ mid, Curl_multi_xfers_running(multi),
+ Curl_uint_tbl_count(&multi->xfers));
return CURLM_OK;
}
@@ -775,7 +831,9 @@ void Curl_detach_connection(struct Curl_easy *data)
{
struct connectdata *conn = data->conn;
if(conn) {
- Curl_node_remove(&data->conn_queue);
+ Curl_uint_spbset_remove(&conn->xfers_attached, data->mid);
+ if(Curl_uint_spbset_empty(&conn->xfers_attached))
+ conn->attached_multi = NULL;
}
data->conn = NULL;
}
@@ -792,7 +850,12 @@ void Curl_attach_connection(struct Curl_easy *data,
DEBUGASSERT(!data->conn);
DEBUGASSERT(conn);
data->conn = conn;
- Curl_llist_append(&conn->easyq, data, &data->conn_queue);
+ Curl_uint_spbset_add(&conn->xfers_attached, data->mid);
+ /* all attached transfers must be from the same multi */
+ if(!conn->attached_multi)
+ conn->attached_multi = data->multi;
+ DEBUGASSERT(conn->attached_multi == data->multi);
+
if(conn->handler && conn->handler->attach)
conn->handler->attach(data, conn);
}
@@ -1024,9 +1087,8 @@ CURLMcode curl_multi_fdset(CURLM *m,
Some easy handles may not have connected to the remote host yet,
and then we must make sure that is done. */
int this_max_fd = -1;
- struct Curl_llist_node *e;
struct Curl_multi *multi = m;
- unsigned int i;
+ unsigned int i, mid;
(void)exc_fd_set; /* not used */
if(!GOOD_MULTI_HANDLE(multi))
@@ -1035,30 +1097,37 @@ CURLMcode curl_multi_fdset(CURLM *m,
if(multi->in_callback)
return CURLM_RECURSIVE_API_CALL;
- for(e = Curl_llist_head(&multi->process); e; e = Curl_node_next(e)) {
- struct Curl_easy *data = Curl_node_elem(e);
- struct easy_pollset ps;
-
- Curl_multi_getsock(data, &ps, "curl_multi_fdset");
+ if(Curl_uint_bset_first(&multi->process, &mid)) {
+ do {
+ struct Curl_easy *data = Curl_multi_get_easy(multi, mid);
+ struct easy_pollset ps;
- for(i = 0; i < ps.num; i++) {
- if(!FDSET_SOCK(ps.sockets[i]))
- /* pretend it does not exist */
+ if(!data) {
+ DEBUGASSERT(0);
continue;
+ }
+
+ Curl_multi_getsock(data, &ps, "curl_multi_fdset");
+ for(i = 0; i < ps.num; i++) {
+ if(!FDSET_SOCK(ps.sockets[i]))
+ /* pretend it does not exist */
+ continue;
#if defined(__DJGPP__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Warith-conversion"
#endif
- if(ps.actions[i] & CURL_POLL_IN)
- FD_SET(ps.sockets[i], read_fd_set);
- if(ps.actions[i] & CURL_POLL_OUT)
- FD_SET(ps.sockets[i], write_fd_set);
+ if(ps.actions[i] & CURL_POLL_IN)
+ FD_SET(ps.sockets[i], read_fd_set);
+ if(ps.actions[i] & CURL_POLL_OUT)
+ FD_SET(ps.sockets[i], write_fd_set);
#if defined(__DJGPP__)
#pragma GCC diagnostic pop
#endif
- if((int)ps.sockets[i] > this_max_fd)
- this_max_fd = (int)ps.sockets[i];
+ if((int)ps.sockets[i] > this_max_fd)
+ this_max_fd = (int)ps.sockets[i];
+ }
}
+ while(Curl_uint_bset_next(&multi->process, mid, &mid));
}
Curl_cshutdn_setfds(&multi->cshutdn, multi->admin,
@@ -1076,9 +1145,8 @@ CURLMcode curl_multi_waitfds(CURLM *m,
{
struct Curl_waitfds cwfds;
CURLMcode result = CURLM_OK;
- struct Curl_llist_node *e;
struct Curl_multi *multi = m;
- unsigned int need = 0;
+ unsigned int need = 0, mid;
if(!ufds && (size || !fd_count))
return CURLM_BAD_FUNCTION_ARGUMENT;
@@ -1090,12 +1158,19 @@ CURLMcode curl_multi_waitfds(CURLM *m,
return CURLM_RECURSIVE_API_CALL;
Curl_waitfds_init(&cwfds, ufds, size);
- for(e = Curl_llist_head(&multi->process); e; e = Curl_node_next(e)) {
- struct Curl_easy *data = Curl_node_elem(e);
- struct easy_pollset ps;
-
- Curl_multi_getsock(data, &ps, "curl_multi_waitfds");
- need += Curl_waitfds_add_ps(&cwfds, &ps);
+ if(Curl_uint_bset_first(&multi->process, &mid)) {
+ do {
+ struct Curl_easy *data = Curl_multi_get_easy(multi, mid);
+ struct easy_pollset ps;
+ if(!data) {
+ DEBUGASSERT(0);
+ Curl_uint_bset_remove(&multi->process, mid);
+ continue;
+ }
+ Curl_multi_getsock(data, &ps, "curl_multi_waitfds");
+ need += Curl_waitfds_add_ps(&cwfds, &ps);
+ }
+ while(Curl_uint_bset_next(&multi->process, mid, &mid));
}
need += Curl_cshutdn_add_waitfds(&multi->cshutdn, multi->admin, &cwfds);
@@ -1143,7 +1218,7 @@ static CURLMcode multi_wait(struct Curl_multi *multi,
struct curl_pollfds cpfds;
unsigned int curl_nfds = 0; /* how many pfds are for curl transfers */
CURLMcode result = CURLM_OK;
- struct Curl_llist_node *e;
+ unsigned int mid;
#ifdef USE_WINSOCK
WSANETWORKEVENTS wsa_events;
@@ -1165,15 +1240,22 @@ static CURLMcode multi_wait(struct Curl_multi *multi,
Curl_pollfds_init(&cpfds, a_few_on_stack, NUM_POLLS_ON_STACK);
/* Add the curl handles to our pollfds first */
- for(e = Curl_llist_head(&multi->process); e; e = Curl_node_next(e)) {
- struct Curl_easy *data = Curl_node_elem(e);
- struct easy_pollset ps;
-
- Curl_multi_getsock(data, &ps, "multi_wait");
- if(Curl_pollfds_add_ps(&cpfds, &ps)) {
- result = CURLM_OUT_OF_MEMORY;
- goto out;
+ if(Curl_uint_bset_first(&multi->process, &mid)) {
+ do {
+ struct Curl_easy *data = Curl_multi_get_easy(multi, mid);
+ struct easy_pollset ps;
+ if(!data) {
+ DEBUGASSERT(0);
+ Curl_uint_bset_remove(&multi->process, mid);
+ continue;
+ }
+ Curl_multi_getsock(data, &ps, "multi_wait");
+ if(Curl_pollfds_add_ps(&cpfds, &ps)) {
+ result = CURLM_OUT_OF_MEMORY;
+ goto out;
+ }
}
+ while(Curl_uint_bset_next(&multi->process, mid, &mid));
}
if(Curl_cshutdn_add_pollfds(&multi->cshutdn, multi->admin, &cpfds)) {
@@ -1408,7 +1490,7 @@ CURLMcode curl_multi_wakeup(CURLM *m)
and before cleanup */
if(multi->wakeup_pair[1] != CURL_SOCKET_BAD) {
while(1) {
-#ifdef HAVE_EVENTFD
+#ifdef USE_EVENTFD
/* eventfd has a stringent rule of requiring the 8-byte buffer when
calling write(2) on it */
const uint64_t buf[1] = { 1 };
@@ -1485,10 +1567,15 @@ CURLMcode Curl_multi_add_perform(struct Curl_multi *multi,
rc = curl_multi_add_handle(multi, data);
if(!rc) {
struct SingleRequest *k = &data->req;
+ CURLcode result;
/* pass in NULL for 'conn' here since we do not want to init the
connection, only this transfer */
- Curl_init_do(data, NULL);
+ result = Curl_init_do(data, NULL);
+ if(result) {
+ curl_multi_remove_handle(multi, data);
+ return CURLM_INTERNAL_ERROR;
+ }
/* take this handle to the perform state right away */
multistate(data, MSTATE_PERFORMING);
@@ -1553,22 +1640,22 @@ static bool multi_handle_timeout(struct Curl_easy *data,
since = data->progress.t_startop;
if(data->mstate == MSTATE_RESOLVING)
failf(data, "Resolving timed out after %" FMT_TIMEDIFF_T
- " milliseconds", Curl_timediff(*now, since));
+ " milliseconds", curlx_timediff(*now, since));
else if(data->mstate == MSTATE_CONNECTING)
failf(data, "Connection timed out after %" FMT_TIMEDIFF_T
- " milliseconds", Curl_timediff(*now, since));
+ " milliseconds", curlx_timediff(*now, since));
else {
struct SingleRequest *k = &data->req;
if(k->size != -1) {
failf(data, "Operation timed out after %" FMT_TIMEDIFF_T
" milliseconds with %" FMT_OFF_T " out of %"
FMT_OFF_T " bytes received",
- Curl_timediff(*now, since), k->bytecount, k->size);
+ curlx_timediff(*now, since), k->bytecount, k->size);
}
else {
failf(data, "Operation timed out after %" FMT_TIMEDIFF_T
" milliseconds with %" FMT_OFF_T " bytes received",
- Curl_timediff(*now, since), k->bytecount);
+ curlx_timediff(*now, since), k->bytecount);
}
}
*result = CURLE_OPERATION_TIMEDOUT;
@@ -2066,37 +2153,12 @@ static CURLMcode state_resolving(struct Curl_multi *multi,
CURLcode *resultp)
{
struct Curl_dns_entry *dns = NULL;
- struct connectdata *conn = data->conn;
- const char *hostname;
- CURLcode result = CURLE_OK;
+ CURLcode result;
CURLMcode rc = CURLM_OK;
- DEBUGASSERT(conn);
-#ifndef CURL_DISABLE_PROXY
- if(conn->bits.httpproxy)
- hostname = conn->http_proxy.host.name;
- else
-#endif
- if(conn->bits.conn_to_host)
- hostname = conn->conn_to_host.name;
- else
- hostname = conn->host.name;
-
- /* check if we have the name resolved by now */
- dns = Curl_fetch_addr(data, hostname, conn->primary.remote_port);
-
- if(dns) {
-#ifdef USE_CURL_ASYNC
- data->state.async.dns = dns;
- data->state.async.done = TRUE;
-#endif
- result = CURLE_OK;
- infof(data, "Hostname '%s' was found in DNS cache", hostname);
- }
-
- if(!dns)
- result = Curl_resolv_check(data, &dns);
-
+ result = Curl_resolv_check(data, &dns);
+ CURL_TRC_DNS(data, "Curl_resolv_check() -> %d, %s",
+ result, dns ? "found" : "missing");
/* Update sockets here, because the socket(s) may have been closed and the
application thus needs to be told, even if it is likely that the same
socket(s) will again be used further down. If the name has not yet been
@@ -2110,7 +2172,7 @@ static CURLMcode state_resolving(struct Curl_multi *multi,
bool connected;
/* Perform the next step in the connection phase, and then move on to the
WAITCONNECT state */
- result = Curl_once_resolved(data, &connected);
+ result = Curl_once_resolved(data, dns, &connected);
if(result)
/* if Curl_once_resolved() returns failure, the connection struct is
@@ -2150,10 +2212,9 @@ static CURLMcode state_connect(struct Curl_multi *multi,
/* There was no connection available. We will go to the pending state and
wait for an available connection. */
multistate(data, MSTATE_PENDING);
- /* unlink from process list */
- Curl_node_remove(&data->multi_queue);
- /* add handle to pending list */
- Curl_llist_append(&multi->pending, data, &data->multi_queue);
+ /* move from process to pending set */
+ Curl_uint_bset_remove(&multi->process, data->mid);
+ Curl_uint_bset_add(&multi->pending, data->mid);
*resultp = CURLE_OK;
return rc;
}
@@ -2548,9 +2609,22 @@ statemachine_end:
}
if(MSTATE_COMPLETED == data->mstate) {
- if(data->set.fmultidone) {
- /* signal via callback instead */
- data->set.fmultidone(data, result);
+ if(data->master_mid != UINT_MAX) {
+ /* A sub transfer, not for msgsent to application */
+ struct Curl_easy *mdata;
+
+ CURL_TRC_M(data, "sub xfer done for master %u", data->master_mid);
+ mdata = Curl_multi_get_easy(multi, data->master_mid);
+ if(mdata) {
+ if(mdata->sub_xfer_done)
+ mdata->sub_xfer_done(mdata, data, result);
+ else
+ CURL_TRC_M(data, "master easy %u without sub_xfer_done callback.",
+ data->master_mid);
+ }
+ else {
+ CURL_TRC_M(data, "master easy %u already gone.", data->master_mid);
+ }
}
else {
/* now fill in the Curl_message with this info */
@@ -2565,10 +2639,11 @@ statemachine_end:
}
multistate(data, MSTATE_MSGSENT);
- /* unlink from the process list */
- Curl_node_remove(&data->multi_queue);
- /* add this handle msgsent list */
- Curl_llist_append(&multi->msgsent, data, &data->multi_queue);
+ /* remove from the other sets, add to msgsent */
+ Curl_uint_bset_remove(&multi->process, data->mid);
+ Curl_uint_bset_remove(&multi->pending, data->mid);
+ Curl_uint_bset_add(&multi->msgsent, data->mid);
+ --multi->xfers_alive;
return CURLM_OK;
}
} while((rc == CURLM_CALL_MULTI_PERFORM) || multi_ischanged(multi, FALSE));
@@ -2582,11 +2657,9 @@ CURLMcode curl_multi_perform(CURLM *m, int *running_handles)
{
CURLMcode returncode = CURLM_OK;
struct Curl_tree *t = NULL;
- struct curltime now = Curl_now();
- struct Curl_llist_node *e;
- struct Curl_llist_node *n = NULL;
+ struct curltime now = curlx_now();
struct Curl_multi *multi = m;
- bool first = TRUE;
+ unsigned int mid;
SIGPIPE_VARIABLE(pipe_st);
if(!GOOD_MULTI_HANDLE(multi))
@@ -2596,34 +2669,26 @@ CURLMcode curl_multi_perform(CURLM *m, int *running_handles)
return CURLM_RECURSIVE_API_CALL;
sigpipe_init(&pipe_st);
- for(e = Curl_llist_head(&multi->process); e; e = n) {
- struct Curl_easy *data = Curl_node_elem(e);
- CURLMcode result;
- unsigned int num_alive = multi->num_alive;
- /* Do the loop and only alter the signal ignore state if the next handle
- has a different NO_SIGNAL state than the previous */
- if(first) {
- CURL_TRC_M(data, "multi_perform(running=%u)", multi->num_alive);
- first = FALSE;
- }
-
- /* the current node might be unlinked in multi_runsingle(), get the next
- pointer now */
- n = Curl_node_next(e);
-
- if(data && data != multi->admin) {
- /* connection pool handle is processed below */
- sigpipe_apply(data, &pipe_st);
- result = multi_runsingle(multi, &now, data);
- if(result)
- returncode = result;
+ if(Curl_uint_bset_first(&multi->process, &mid)) {
+ CURL_TRC_M(multi->admin, "multi_perform(running=%u)",
+ Curl_multi_xfers_running(multi));
+ do {
+ struct Curl_easy *data = Curl_multi_get_easy(multi, mid);
+ CURLMcode result;
+ if(!data) {
+ DEBUGASSERT(0);
+ Curl_uint_bset_remove(&multi->process, mid);
+ continue;
+ }
+ if(data != multi->admin) {
+ /* admin handle is processed below */
+ sigpipe_apply(data, &pipe_st);
+ result = multi_runsingle(multi, &now, data);
+ if(result)
+ returncode = result;
+ }
}
- if(num_alive != multi->num_alive)
- /* Since more than one handle can be removed in a single call to
- multi_runsingle(), we cannot easily continue on the next node when a
- node has been removed since that node might ALSO have been
- removed. */
- n = Curl_llist_head(&multi->process);
+ while(Curl_uint_bset_next(&multi->process, mid, &mid));
}
sigpipe_apply(multi->admin, &pipe_st);
@@ -2660,8 +2725,10 @@ CURLMcode curl_multi_perform(CURLM *m, int *running_handles)
}
} while(t);
- if(running_handles)
- *running_handles = (int)multi->num_alive;
+ if(running_handles) {
+ unsigned int running = Curl_multi_xfers_running(multi);
+ *running_handles = (running < INT_MAX) ? (int)running : INT_MAX;
+ }
if(CURLM_OK >= returncode)
returncode = Curl_update_timer(multi);
@@ -2669,69 +2736,58 @@ CURLMcode curl_multi_perform(CURLM *m, int *running_handles)
return returncode;
}
-/* unlink_all_msgsent_handles() moves all nodes back from the msgsent list to
- the process list */
-static void unlink_all_msgsent_handles(struct Curl_multi *multi)
-{
- struct Curl_llist_node *e;
- struct Curl_llist_node *n;
- for(e = Curl_llist_head(&multi->msgsent); e; e = n) {
- struct Curl_easy *data = Curl_node_elem(e);
- n = Curl_node_next(e);
- if(data) {
- DEBUGASSERT(data->mstate == MSTATE_MSGSENT);
- Curl_node_remove(&data->multi_queue);
- /* put it into the process list */
- Curl_llist_append(&multi->process, data, &data->multi_queue);
- }
- }
-}
-
CURLMcode curl_multi_cleanup(CURLM *m)
{
struct Curl_multi *multi = m;
if(GOOD_MULTI_HANDLE(multi)) {
- struct Curl_llist_node *e;
- struct Curl_llist_node *n;
+ void *entry;
+ unsigned int mid;
if(multi->in_callback)
return CURLM_RECURSIVE_API_CALL;
- /* move the pending and msgsent entries back to process
- so that there is just one list to iterate over */
- unlink_all_msgsent_handles(multi);
- process_pending_handles(multi);
+ /* First remove all remaining easy handles,
+ * close internal ones. admin handle is special */
+ if(Curl_uint_tbl_first(&multi->xfers, &mid, &entry)) {
+ do {
+ struct Curl_easy *data = entry;
+ if(!GOOD_EASY_HANDLE(data))
+ return CURLM_BAD_HANDLE;
- /* First remove all remaining easy handles */
- for(e = Curl_llist_head(&multi->process); e; e = n) {
- struct Curl_easy *data = Curl_node_elem(e);
-
- if(!GOOD_EASY_HANDLE(data))
- return CURLM_BAD_HANDLE;
-
- n = Curl_node_next(e);
- if(!data->state.done && data->conn)
- /* if DONE was never called for this handle */
- (void)multi_done(data, CURLE_OK, TRUE);
- if(data->dns.hostcachetype == HCACHE_MULTI) {
- /* clear out the usage of the shared DNS cache */
- Curl_hostcache_clean(data, data->dns.hostcache);
- data->dns.hostcache = NULL;
- data->dns.hostcachetype = HCACHE_NONE;
- }
+#ifdef DEBUGBUILD
+ if(mid != data->mid) {
+ CURL_TRC_M(data, "multi_cleanup: still present with mid=%u, "
+ "but unexpected data->mid=%u\n", mid, data->mid);
+ DEBUGASSERT(0);
+ }
+#endif
+
+ if(data == multi->admin)
+ continue;
+
+ if(!data->state.done && data->conn)
+ /* if DONE was never called for this handle */
+ (void)multi_done(data, CURLE_OK, TRUE);
- data->multi = NULL; /* clear the association */
+ data->multi = NULL; /* clear the association */
+ Curl_uint_tbl_remove(&multi->xfers, mid);
+ data->mid = UINT_MAX;
#ifdef USE_LIBPSL
- if(data->psl == &multi->psl)
- data->psl = NULL;
+ if(data->psl == &multi->psl)
+ data->psl = NULL;
#endif
- if(data->state.internal)
- Curl_close(&data);
+ if(data->state.internal)
+ Curl_close(&data);
+ }
+ while(Curl_uint_tbl_next(&multi->xfers, mid, &mid, &entry));
}
+
Curl_cpool_destroy(&multi->cpool);
Curl_cshutdn_destroy(&multi->cshutdn, multi->admin);
if(multi->admin) {
+ CURL_TRC_M(multi->admin, "multi_cleanup, closing admin handle, done");
multi->admin->multi = NULL;
+ Curl_uint_tbl_remove(&multi->xfers, multi->admin->mid);
Curl_close(&multi->admin);
}
@@ -2739,7 +2795,7 @@ CURLMcode curl_multi_cleanup(CURLM *m)
Curl_multi_ev_cleanup(multi);
Curl_hash_destroy(&multi->proto_hash);
- Curl_hash_destroy(&multi->hostcache);
+ Curl_dnscache_destroy(&multi->dnscache);
Curl_psl_destroy(&multi->psl);
Curl_ssl_scache_destroy(multi->ssl_scache);
@@ -2748,13 +2804,23 @@ CURLMcode curl_multi_cleanup(CURLM *m)
#else
#ifdef ENABLE_WAKEUP
wakeup_close(multi->wakeup_pair[0]);
-#ifndef HAVE_EVENTFD
+#ifndef USE_EVENTFD
wakeup_close(multi->wakeup_pair[1]);
#endif
#endif
#endif
multi_xfer_bufs_free(multi);
+#ifdef DEBUGBUILD
+ if(Curl_uint_tbl_count(&multi->xfers)) {
+ multi_xfer_tbl_dump(multi);
+ DEBUGASSERT(0);
+ }
+#endif
+ Curl_uint_bset_destroy(&multi->process);
+ Curl_uint_bset_destroy(&multi->pending);
+ Curl_uint_bset_destroy(&multi->msgsent);
+ Curl_uint_tbl_destroy(&multi->xfers);
free(multi);
return CURLM_OK;
@@ -2838,7 +2904,7 @@ static CURLMcode add_next_timeout(struct curltime now,
for(e = Curl_llist_head(list); e;) {
struct Curl_llist_node *n = Curl_node_next(e);
struct time_node *node = Curl_node_elem(e);
- timediff_t diff = Curl_timediff_us(node->time, now);
+ timediff_t diff = curlx_timediff_us(node->time, now);
if(diff <= 0)
/* remove outdated entry */
Curl_node_remove(e);
@@ -2931,7 +2997,7 @@ static CURLMcode multi_socket(struct Curl_multi *multi,
(void)ev_bitmask;
memset(&mrc, 0, sizeof(mrc));
mrc.multi = multi;
- mrc.now = Curl_now();
+ mrc.now = curlx_now();
sigpipe_init(&mrc.pipe_st);
if(checkall) {
@@ -2940,7 +3006,7 @@ static CURLMcode multi_socket(struct Curl_multi *multi,
if(result != CURLM_BAD_HANDLE) {
/* Reassess event status of all active transfers */
- result = Curl_multi_ev_assess_xfer_list(multi, &multi->process);
+ result = Curl_multi_ev_assess_xfer_bset(multi, &multi->process);
}
mrc.run_cpool = TRUE;
goto out;
@@ -2969,7 +3035,7 @@ static CURLMcode multi_socket(struct Curl_multi *multi,
* to set a 0 timeout and call us again, we run them here.
* Do that only once or it might be unfair to transfers on other
* sockets. */
- mrc.now = Curl_now();
+ mrc.now = curlx_now();
result = multi_run_expired(&mrc);
}
@@ -2983,8 +3049,10 @@ out:
if(multi_ischanged(multi, TRUE))
process_pending_handles(multi);
- if(running_handles)
- *running_handles = (int)multi->num_alive;
+ if(running_handles) {
+ unsigned int running = Curl_multi_xfers_running(multi);
+ *running_handles = (running < INT_MAX) ? (int)running : INT_MAX;
+ }
if(CURLM_OK >= result)
result = Curl_update_timer(multi);
@@ -3109,7 +3177,7 @@ static CURLMcode multi_timeout(struct Curl_multi *multi,
if(multi->timetree) {
/* we have a tree of expire times */
- struct curltime now = Curl_now();
+ struct curltime now = curlx_now();
/* splay the lowest to the bottom */
multi->timetree = Curl_splay(tv_zero, multi->timetree);
@@ -3120,9 +3188,9 @@ static CURLMcode multi_timeout(struct Curl_multi *multi,
/* 'multi->timetree' will be non-NULL here but the compilers sometimes
yell at us if we assume so */
if(multi->timetree &&
- Curl_timediff_us(multi->timetree->key, now) > 0) {
+ curlx_timediff_us(multi->timetree->key, now) > 0) {
/* some time left before expiration */
- timediff_t diff = Curl_timediff_ceil(multi->timetree->key, now);
+ timediff_t diff = curlx_timediff_ceil(multi->timetree->key, now);
/* this should be safe even on 32-bit archs, as we do not use that
overly long timeouts */
*timeout_ms = (long)diff;
@@ -3195,7 +3263,7 @@ CURLMcode Curl_update_timer(struct Curl_multi *multi)
#endif
set_value = TRUE;
}
- else if(Curl_timediff_us(multi->last_expire_ts, expire_ts)) {
+ else if(curlx_timediff_us(multi->last_expire_ts, expire_ts)) {
/* We had a timeout before and have one now, the absolute timestamp
* differs. The relative timeout_ms may be the same, but the starting
* point differs. Let the application restart its timer. */
@@ -3279,7 +3347,7 @@ multi_addtimeout(struct Curl_easy *data,
/* find the correct spot in the list */
for(e = Curl_llist_head(timeoutlist); e; e = Curl_node_next(e)) {
struct time_node *check = Curl_node_elem(e);
- timediff_t diff = Curl_timediff(check->time, node->time);
+ timediff_t diff = curlx_timediff(check->time, node->time);
if(diff > 0)
break;
prev = e;
@@ -3328,7 +3396,7 @@ void Curl_expire_ex(struct Curl_easy *data,
/* This means that the struct is added as a node in the splay tree.
Compare if the new time is earlier, and only remove-old/add-new if it
is. */
- timediff_t diff = Curl_timediff(set, *curr_expire);
+ timediff_t diff = curlx_timediff(set, *curr_expire);
int rc;
if(diff > 0) {
@@ -3366,7 +3434,7 @@ void Curl_expire_ex(struct Curl_easy *data,
*/
void Curl_expire(struct Curl_easy *data, timediff_t milli, expire_id id)
{
- struct curltime now = Curl_now();
+ struct curltime now = curlx_now();
Curl_expire_ex(data, &now, milli, id);
}
@@ -3434,11 +3502,9 @@ static void move_pending_to_connect(struct Curl_multi *multi,
{
DEBUGASSERT(data->mstate == MSTATE_PENDING);
- /* Remove this node from the pending list */
- Curl_node_remove(&data->multi_queue);
-
- /* put it into the process list */
- Curl_llist_append(&multi->process, data, &data->multi_queue);
+ /* Remove this node from the pending set, add into process set */
+ Curl_uint_bset_remove(&multi->pending, data->mid);
+ Curl_uint_bset_add(&multi->process, data->mid);
multistate(data, MSTATE_CONNECT);
@@ -3462,10 +3528,15 @@ static void move_pending_to_connect(struct Curl_multi *multi,
*/
static void process_pending_handles(struct Curl_multi *multi)
{
- struct Curl_llist_node *e = Curl_llist_head(&multi->pending);
- if(e) {
- struct Curl_easy *data = Curl_node_elem(e);
- move_pending_to_connect(multi, data);
+ unsigned int mid;
+ if(Curl_uint_bset_first(&multi->pending, &mid)) {
+ do {
+ struct Curl_easy *data = Curl_multi_get_easy(multi, mid);
+ DEBUGASSERT(data);
+ if(data)
+ move_pending_to_connect(multi, data);
+ }
+ while(Curl_uint_bset_next(&multi->pending, mid, &mid));
}
}
@@ -3489,15 +3560,20 @@ unsigned int Curl_multi_max_concurrent_streams(struct Curl_multi *multi)
CURL **curl_multi_get_handles(CURLM *m)
{
struct Curl_multi *multi = m;
- CURL **a = malloc(sizeof(struct Curl_easy *) * (multi->num_easy + 1));
+ void *entry;
+ unsigned int count = Curl_uint_tbl_count(&multi->xfers);
+ CURL **a = malloc(sizeof(struct Curl_easy *) * (count + 1));
if(a) {
- unsigned int i = 0;
- struct Curl_llist_node *e;
- for(e = Curl_llist_head(&multi->process); e; e = Curl_node_next(e)) {
- struct Curl_easy *data = Curl_node_elem(e);
- DEBUGASSERT(i < multi->num_easy);
- if(!data->state.internal)
- a[i++] = data;
+ unsigned int i = 0, mid;
+
+ if(Curl_uint_tbl_first(&multi->xfers, &mid, &entry)) {
+ do {
+ struct Curl_easy *data = entry;
+ DEBUGASSERT(i < count);
+ if(!data->state.internal)
+ a[i++] = data;
+ }
+ while(Curl_uint_tbl_next(&multi->xfers, mid, &mid, &entry));
}
a[i] = NULL; /* last entry is a NULL */
}
@@ -3669,31 +3745,53 @@ static void multi_xfer_bufs_free(struct Curl_multi *multi)
multi->xfer_sockbuf_borrowed = FALSE;
}
-struct Curl_easy *Curl_multi_get_handle(struct Curl_multi *multi,
- curl_off_t mid)
+struct Curl_easy *Curl_multi_get_easy(struct Curl_multi *multi,
+ unsigned int mid)
{
+ struct Curl_easy *data = mid ? Curl_uint_tbl_get(&multi->xfers, mid) : NULL;
+ if(data && GOOD_EASY_HANDLE(data))
+ return data;
+ CURL_TRC_M(multi->admin, "invalid easy handle in xfer table for mid=%u",
+ mid);
+ Curl_uint_tbl_remove(&multi->xfers, mid);
+ return NULL;
+}
- if(mid >= 0) {
- struct Curl_easy *data;
- struct Curl_llist_node *e;
+unsigned int Curl_multi_xfers_running(struct Curl_multi *multi)
+{
+ return multi->xfers_alive;
+}
- for(e = Curl_llist_head(&multi->process); e; e = Curl_node_next(e)) {
- data = Curl_node_elem(e);
- if(data->mid == mid)
- return data;
- }
- /* may be in msgsent queue */
- for(e = Curl_llist_head(&multi->msgsent); e; e = Curl_node_next(e)) {
- data = Curl_node_elem(e);
- if(data->mid == mid)
- return data;
- }
- /* may be in pending queue */
- for(e = Curl_llist_head(&multi->pending); e; e = Curl_node_next(e)) {
- data = Curl_node_elem(e);
- if(data->mid == mid)
- return data;
- }
+#ifdef DEBUGBUILD
+static void multi_xfer_dump(struct Curl_multi *multi, unsigned int mid,
+ void *entry)
+{
+ struct Curl_easy *data = entry;
+
+ (void)multi;
+ if(!data) {
+ fprintf(stderr, "mid=%u, entry=NULL, bug in xfer table?\n", mid);
}
- return NULL;
+ else {
+ fprintf(stderr, "mid=%u, magic=%s, p=%p, id=%" FMT_OFF_T ", url=%s\n",
+ mid, (data->magic == CURLEASY_MAGIC_NUMBER) ? "GOOD" : "BAD!",
+ (void *)data, data->id, data->state.url);
+ }
+}
+
+static void multi_xfer_tbl_dump(struct Curl_multi *multi)
+{
+ unsigned int mid;
+ void *entry;
+ fprintf(stderr, "=== multi xfer table (count=%u, capacity=%u\n",
+ Curl_uint_tbl_count(&multi->xfers),
+ Curl_uint_tbl_capacity(&multi->xfers));
+ if(Curl_uint_tbl_first(&multi->xfers, &mid, &entry)) {
+ multi_xfer_dump(multi, mid, entry);
+ while(Curl_uint_tbl_next(&multi->xfers, mid, &mid, &entry))
+ multi_xfer_dump(multi, mid, entry);
+ }
+ fprintf(stderr, "===\n");
+ fflush(stderr);
}
+#endif /* DEBUGBUILD */
diff --git a/libs/libcurl/src/multi_ev.c b/libs/libcurl/src/multi_ev.c
index 541bc0a739..55fe3614d7 100644
--- a/libs/libcurl/src/multi_ev.c
+++ b/libs/libcurl/src/multi_ev.c
@@ -27,13 +27,17 @@
#include <curl/curl.h>
#include "urldata.h"
+#include "url.h"
#include "cfilters.h"
#include "curl_trc.h"
#include "multiif.h"
-#include "timeval.h"
+#include "curlx/timeval.h"
#include "multi_ev.h"
#include "select.h"
-#include "warnless.h"
+#include "uint-bset.h"
+#include "uint-spbset.h"
+#include "uint-table.h"
+#include "curlx/warnless.h"
#include "multihandle.h"
#include "socks.h"
/* The last 3 #include files should be in this order */
@@ -47,15 +51,14 @@ static void mev_in_callback(struct Curl_multi *multi, bool value)
multi->in_callback = value;
}
-#define CURL_MEV_XFER_HASH_SIZE 13
#define CURL_MEV_CONN_HASH_SIZE 3
/* Information about a socket for which we inform the libcurl application
* what to supervise (CURL_POLL_IN/CURL_POLL_OUT/CURL_POLL_REMOVE)
*/
struct mev_sh_entry {
- struct Curl_hash_offt xfers; /* hash of transfers using this socket */
- struct Curl_hash_offt conns; /* hash of connections using this socket */
+ struct uint_spbset xfers; /* bitset of transfers `mid`s on this socket */
+ struct connectdata *conn; /* connection using this socket or NULL */
void *user_data; /* libcurl app data via curl_multi_assign() */
unsigned int action; /* CURL_POLL_IN/CURL_POLL_OUT we last told the
* libcurl application to watch out for */
@@ -81,8 +84,7 @@ static size_t mev_sh_entry_compare(void *k1, size_t k1_len,
static void mev_sh_entry_dtor(void *freethis)
{
struct mev_sh_entry *entry = (struct mev_sh_entry *)freethis;
- Curl_hash_offt_destroy(&entry->xfers);
- Curl_hash_offt_destroy(&entry->conns);
+ Curl_uint_spbset_destroy(&entry->xfers);
free(entry);
}
@@ -114,8 +116,7 @@ mev_sh_entry_add(struct Curl_hash *sh, curl_socket_t s)
if(!check)
return NULL; /* major failure */
- Curl_hash_offt_init(&check->xfers, CURL_MEV_XFER_HASH_SIZE, NULL);
- Curl_hash_offt_init(&check->conns, CURL_MEV_CONN_HASH_SIZE, NULL);
+ Curl_uint_spbset_init(&check->xfers);
/* make/add new hash entry */
if(!Curl_hash_add(sh, (char *)&s, sizeof(curl_socket_t), check)) {
@@ -134,19 +135,19 @@ static void mev_sh_entry_kill(struct Curl_multi *multi, curl_socket_t s)
static size_t mev_sh_entry_user_count(struct mev_sh_entry *e)
{
- return Curl_hash_offt_count(&e->xfers) + Curl_hash_offt_count(&e->conns);
+ return Curl_uint_spbset_count(&e->xfers) + (e->conn ? 1 : 0);
}
static bool mev_sh_entry_xfer_known(struct mev_sh_entry *e,
struct Curl_easy *data)
{
- return !!Curl_hash_offt_get(&e->xfers, data->mid);
+ return Curl_uint_spbset_contains(&e->xfers, data->mid);
}
static bool mev_sh_entry_conn_known(struct mev_sh_entry *e,
struct connectdata *conn)
{
- return !!Curl_hash_offt_get(&e->conns, conn->connection_id);
+ return (e->conn == conn);
}
static bool mev_sh_entry_xfer_add(struct mev_sh_entry *e,
@@ -154,7 +155,7 @@ static bool mev_sh_entry_xfer_add(struct mev_sh_entry *e,
{
/* detect weird values */
DEBUGASSERT(mev_sh_entry_user_count(e) < 100000);
- return !!Curl_hash_offt_set(&e->xfers, data->mid, data);
+ return Curl_uint_spbset_add(&e->xfers, data->mid);
}
static bool mev_sh_entry_conn_add(struct mev_sh_entry *e,
@@ -162,20 +163,32 @@ static bool mev_sh_entry_conn_add(struct mev_sh_entry *e,
{
/* detect weird values */
DEBUGASSERT(mev_sh_entry_user_count(e) < 100000);
- return !!Curl_hash_offt_set(&e->conns, conn->connection_id, conn);
+ DEBUGASSERT(!e->conn);
+ if(e->conn)
+ return FALSE;
+ e->conn = conn;
+ return TRUE;
}
static bool mev_sh_entry_xfer_remove(struct mev_sh_entry *e,
struct Curl_easy *data)
{
- return Curl_hash_offt_remove(&e->xfers, data->mid);
+ bool present = Curl_uint_spbset_contains(&e->xfers, data->mid);
+ if(present)
+ Curl_uint_spbset_remove(&e->xfers, data->mid);
+ return present;
}
static bool mev_sh_entry_conn_remove(struct mev_sh_entry *e,
struct connectdata *conn)
{
- return Curl_hash_offt_remove(&e->conns, conn->connection_id);
+ DEBUGASSERT(e->conn == conn);
+ if(e->conn == conn) {
+ e->conn = NULL;
+ return TRUE;
+ }
+ return FALSE;
}
/* Purge any information about socket `s`.
@@ -339,11 +352,11 @@ static CURLMcode mev_pollset_diff(struct Curl_multi *multi,
return CURLM_OUT_OF_MEMORY;
}
CURL_TRC_M(data, "ev entry fd=%" FMT_SOCKET_T ", added %s #%" FMT_OFF_T
- ", total=%zu/%zu (xfer/conn)", s,
+ ", total=%u/%d (xfer/conn)", s,
conn ? "connection" : "transfer",
conn ? conn->connection_id : data->mid,
- Curl_hash_offt_count(&entry->xfers),
- Curl_hash_offt_count(&entry->conns));
+ Curl_uint_spbset_count(&entry->xfers),
+ entry->conn ? 1 : 0);
}
else {
for(j = 0; j < prev_ps->num; j++) {
@@ -409,9 +422,9 @@ static CURLMcode mev_pollset_diff(struct Curl_multi *multi,
if(mresult)
return mresult;
CURL_TRC_M(data, "ev entry fd=%" FMT_SOCKET_T ", removed transfer, "
- "total=%zu/%zu (xfer/conn)", s,
- Curl_hash_offt_count(&entry->xfers),
- Curl_hash_offt_count(&entry->conns));
+ "total=%u/%d (xfer/conn)", s,
+ Curl_uint_spbset_count(&entry->xfers),
+ entry->conn ? 1 : 0);
}
else {
mresult = mev_forget_socket(multi, data, s, "last user gone");
@@ -425,31 +438,47 @@ static CURLMcode mev_pollset_diff(struct Curl_multi *multi,
return CURLM_OK;
}
+static void mev_pollset_dtor(void *key, size_t klen, void *entry)
+{
+ (void)key;
+ (void)klen;
+ free(entry);
+}
+
static struct easy_pollset*
-mev_add_new_pollset(struct Curl_hash_offt *h, curl_off_t id)
+mev_add_new_conn_pollset(struct connectdata *conn)
{
struct easy_pollset *ps;
ps = calloc(1, sizeof(*ps));
if(!ps)
return NULL;
- if(!Curl_hash_offt_set(h, id, ps)) {
- free(ps);
+ if(Curl_conn_meta_set(conn, CURL_META_MEV_POLLSET, ps, mev_pollset_dtor))
+ return NULL;
+ return ps;
+}
+
+static struct easy_pollset*
+mev_add_new_xfer_pollset(struct Curl_easy *data)
+{
+ struct easy_pollset *ps;
+
+ ps = calloc(1, sizeof(*ps));
+ if(!ps)
+ return NULL;
+ if(Curl_meta_set(data, CURL_META_MEV_POLLSET, ps, mev_pollset_dtor))
return NULL;
- }
return ps;
}
static struct easy_pollset *
-mev_get_last_pollset(struct Curl_multi *multi,
- struct Curl_easy *data,
+mev_get_last_pollset(struct Curl_easy *data,
struct connectdata *conn)
{
if(data) {
if(conn)
- return Curl_hash_offt_get(&multi->ev.conn_pollsets,
- conn->connection_id);
- return Curl_hash_offt_get(&multi->ev.xfer_pollsets, data->mid);
+ return Curl_conn_meta_get(conn, CURL_META_MEV_POLLSET);
+ return Curl_meta_get(data, CURL_META_MEV_POLLSET);
}
return NULL;
}
@@ -473,14 +502,13 @@ static CURLMcode mev_assess(struct Curl_multi *multi,
struct easy_pollset ps, *last_ps;
mev_init_cur_pollset(&ps, data, conn);
- last_ps = mev_get_last_pollset(multi, data, conn);
+ last_ps = mev_get_last_pollset(data, conn);
if(!last_ps && ps.num) {
if(conn)
- last_ps = mev_add_new_pollset(&multi->ev.conn_pollsets,
- conn->connection_id);
+ last_ps = mev_add_new_conn_pollset(conn);
else
- last_ps = mev_add_new_pollset(&multi->ev.xfer_pollsets, data->mid);
+ last_ps = mev_add_new_xfer_pollset(data);
if(!last_ps)
return CURLM_OUT_OF_MEMORY;
}
@@ -506,16 +534,19 @@ CURLMcode Curl_multi_ev_assess_conn(struct Curl_multi *multi,
return mev_assess(multi, data, conn);
}
-CURLMcode Curl_multi_ev_assess_xfer_list(struct Curl_multi *multi,
- struct Curl_llist *list)
+CURLMcode Curl_multi_ev_assess_xfer_bset(struct Curl_multi *multi,
+ struct uint_bset *set)
{
- struct Curl_llist_node *e;
+ unsigned int mid;
CURLMcode result = CURLM_OK;
- if(multi && multi->socket_cb) {
- for(e = Curl_llist_head(list); e && !result; e = Curl_node_next(e)) {
- result = Curl_multi_ev_assess_xfer(multi, Curl_node_elem(e));
+ if(multi && multi->socket_cb && Curl_uint_bset_first(set, &mid)) {
+ do {
+ struct Curl_easy *data = Curl_multi_get_easy(multi, mid);
+ if(data)
+ result = Curl_multi_ev_assess_xfer(multi, data);
}
+ while(!result && Curl_uint_bset_next(set, mid, &mid));
}
return result;
}
@@ -532,21 +563,6 @@ CURLMcode Curl_multi_ev_assign(struct Curl_multi *multi,
return CURLM_OK;
}
-static bool mev_xfer_expire_cb(curl_off_t id, void *value, void *user_data)
-{
- const struct curltime *nowp = user_data;
- struct Curl_easy *data = value;
-
- DEBUGASSERT(data);
- DEBUGASSERT(data->magic == CURLEASY_MAGIC_NUMBER);
- if(data && id >= 0) {
- /* Expire with out current now, so we will get it below when
- * asking the splaytree for expired transfers. */
- Curl_expire_ex(data, nowp, 0, EXPIRE_RUN_NOW);
- }
- return TRUE;
-}
-
void Curl_multi_ev_expire_xfers(struct Curl_multi *multi,
curl_socket_t s,
const struct curltime *nowp,
@@ -563,10 +579,22 @@ void Curl_multi_ev_expire_xfers(struct Curl_multi *multi,
asked to get removed, so thus we better survive stray socket actions
and just move on. */
if(entry) {
- Curl_hash_offt_visit(&entry->xfers, mev_xfer_expire_cb,
- CURL_UNCONST(nowp));
+ struct Curl_easy *data;
+ unsigned int mid;
+
+ if(Curl_uint_spbset_first(&entry->xfers, &mid)) {
+ do {
+ data = Curl_multi_get_easy(multi, mid);
+ if(data) {
+ /* Expire with out current now, so we will get it below when
+ * asking the splaytree for expired transfers. */
+ Curl_expire_ex(data, nowp, 0, EXPIRE_RUN_NOW);
+ }
+ }
+ while(Curl_uint_spbset_next(&entry->xfers, mid, &mid));
+ }
- if(Curl_hash_offt_count(&entry->conns))
+ if(entry->conn)
*run_cpool = TRUE;
}
}
@@ -581,9 +609,9 @@ void Curl_multi_ev_xfer_done(struct Curl_multi *multi,
struct Curl_easy *data)
{
DEBUGASSERT(!data->conn); /* transfer should have been detached */
- if(data->mid >= 0) {
+ if(data != multi->admin) {
(void)mev_assess(multi, data, NULL);
- Curl_hash_offt_remove(&multi->ev.xfer_pollsets, data->mid);
+ Curl_meta_remove(data, CURL_META_MEV_POLLSET);
}
}
@@ -592,30 +620,18 @@ void Curl_multi_ev_conn_done(struct Curl_multi *multi,
struct connectdata *conn)
{
(void)mev_assess(multi, data, conn);
- Curl_hash_offt_remove(&multi->ev.conn_pollsets, conn->connection_id);
+ Curl_conn_meta_remove(conn, CURL_META_MEV_POLLSET);
}
#define CURL_MEV_PS_HASH_SLOTS (991) /* nice prime */
-static void mev_hash_pollset_free(curl_off_t id, void *entry)
-{
- (void)id;
- free(entry);
-}
-
void Curl_multi_ev_init(struct Curl_multi *multi, size_t hashsize)
{
Curl_hash_init(&multi->ev.sh_entries, hashsize, mev_sh_entry_hash,
mev_sh_entry_compare, mev_sh_entry_dtor);
- Curl_hash_offt_init(&multi->ev.xfer_pollsets,
- CURL_MEV_PS_HASH_SLOTS, mev_hash_pollset_free);
- Curl_hash_offt_init(&multi->ev.conn_pollsets,
- CURL_MEV_PS_HASH_SLOTS, mev_hash_pollset_free);
}
void Curl_multi_ev_cleanup(struct Curl_multi *multi)
{
Curl_hash_destroy(&multi->ev.sh_entries);
- Curl_hash_offt_destroy(&multi->ev.xfer_pollsets);
- Curl_hash_offt_destroy(&multi->ev.conn_pollsets);
}
diff --git a/libs/libcurl/src/multi_ev.h b/libs/libcurl/src/multi_ev.h
index 50761f6639..73356ec42e 100644
--- a/libs/libcurl/src/multi_ev.h
+++ b/libs/libcurl/src/multi_ev.h
@@ -25,16 +25,17 @@
***************************************************************************/
#include "hash.h"
-#include "hash_offt.h"
struct Curl_easy;
struct Curl_multi;
struct easy_pollset;
+struct uint_bset;
+
+/* meta key for event pollset at easy handle or connection */
+#define CURL_META_MEV_POLLSET "meta:mev:ps"
struct curl_multi_ev {
struct Curl_hash sh_entries;
- struct Curl_hash_offt xfer_pollsets;
- struct Curl_hash_offt conn_pollsets;
};
/* Setup/teardown of multi event book-keeping. */
@@ -53,8 +54,8 @@ CURLMcode Curl_multi_ev_assign(struct Curl_multi *multi, curl_socket_t s,
CURLMcode Curl_multi_ev_assess_xfer(struct Curl_multi *multi,
struct Curl_easy *data);
/* Assess all easy handles on the list */
-CURLMcode Curl_multi_ev_assess_xfer_list(struct Curl_multi *multi,
- struct Curl_llist *list);
+CURLMcode Curl_multi_ev_assess_xfer_bset(struct Curl_multi *multi,
+ struct uint_bset *set);
/* Assess the connection by getting its current pollset */
CURLMcode Curl_multi_ev_assess_conn(struct Curl_multi *multi,
struct Curl_easy *data,
diff --git a/libs/libcurl/src/multihandle.h b/libs/libcurl/src/multihandle.h
index 1bf77b7822..9a5425aef9 100644
--- a/libs/libcurl/src/multihandle.h
+++ b/libs/libcurl/src/multihandle.h
@@ -28,9 +28,13 @@
#include "hash.h"
#include "conncache.h"
#include "cshutdn.h"
+#include "hostip.h"
#include "multi_ev.h"
#include "psl.h"
#include "socketpair.h"
+#include "uint-bset.h"
+#include "uint-spbset.h"
+#include "uint-table.h"
struct connectdata;
struct Curl_easy;
@@ -89,19 +93,18 @@ struct Curl_multi {
this multi handle with an easy handle. Set this to CURL_MULTI_HANDLE. */
unsigned int magic;
- unsigned int num_easy; /* amount of entries in the linked list above. */
- unsigned int num_alive; /* amount of easy handles that are added but have
- not yet reached COMPLETE state */
+ unsigned int xfers_alive; /* amount of added transfers that have
+ not yet reached COMPLETE state */
+ struct uint_tbl xfers; /* transfers added to this multi */
+ /* Each transfer's mid may be present in at most one of these */
+ struct uint_bset process; /* transfer being processed */
+ struct uint_bset pending; /* transfers in waiting (conn limit etc.) */
+ struct uint_bset msgsent; /* transfers done with message for application */
struct Curl_llist msglist; /* a list of messages from completed transfers */
- /* Each added easy handle is added to ONE of these three lists */
- struct Curl_llist process; /* not in PENDING or MSGSENT */
- struct Curl_llist pending; /* in PENDING */
- struct Curl_llist msgsent; /* in MSGSENT */
- curl_off_t next_easy_mid; /* next multi-id for easy handle added */
-
- struct Curl_easy *admin; /* internal easy handle for admin operations */
+ struct Curl_easy *admin; /* internal easy handle for admin operations.
+ gets assigned `mid` 0 on multi init */
/* callback function and user data pointer for the *socket() API */
curl_socket_callback socket_cb;
@@ -111,7 +114,7 @@ struct Curl_multi {
curl_push_callback push_cb;
void *push_userp;
- struct Curl_hash hostcache; /* Hostname cache */
+ struct Curl_dnscache dnscache; /* DNS cache */
struct Curl_ssl_scache *ssl_scache; /* TLS session pool */
#ifdef USE_LIBPSL
diff --git a/libs/libcurl/src/multiif.h b/libs/libcurl/src/multiif.h
index d70a4549fd..a8701cce62 100644
--- a/libs/libcurl/src/multiif.h
+++ b/libs/libcurl/src/multiif.h
@@ -47,7 +47,8 @@ void Curl_multi_connchanged(struct Curl_multi *multi);
/* Internal version of curl_multi_init() accepts size parameters for the
socket, connection and dns hashes */
-struct Curl_multi *Curl_multi_handle(size_t hashsize,
+struct Curl_multi *Curl_multi_handle(unsigned int xfer_table_size,
+ size_t hashsize,
size_t chashsize,
size_t dnssize,
size_t sesssize);
@@ -163,9 +164,13 @@ CURLcode Curl_multi_xfer_sockbuf_borrow(struct Curl_easy *data,
void Curl_multi_xfer_sockbuf_release(struct Curl_easy *data, char *buf);
/**
- * Get the transfer handle for the given id. Returns NULL if not found.
+ * Get the easy handle for the given mid.
+ * Returns NULL if not found.
*/
-struct Curl_easy *Curl_multi_get_handle(struct Curl_multi *multi,
- curl_off_t id);
+struct Curl_easy *Curl_multi_get_easy(struct Curl_multi *multi,
+ unsigned int mid);
+
+/* Get the # of transfers current in process/pending. */
+unsigned int Curl_multi_xfers_running(struct Curl_multi *multi);
#endif /* HEADER_CURL_MULTIIF_H */
diff --git a/libs/libcurl/src/netrc.c b/libs/libcurl/src/netrc.c
index 7ed1ea204a..41af08009d 100644
--- a/libs/libcurl/src/netrc.c
+++ b/libs/libcurl/src/netrc.c
@@ -39,7 +39,7 @@
#include "netrc.h"
#include "strcase.h"
#include "curl_get_line.h"
-#include "strparse.h"
+#include "curlx/strparse.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
@@ -78,18 +78,18 @@ static NETRCcode file2memory(const char *filename, struct dynbuf *filebuf)
NETRCcode ret = NETRC_FILE_MISSING; /* if it cannot open the file */
FILE *file = fopen(filename, FOPEN_READTEXT);
struct dynbuf linebuf;
- Curl_dyn_init(&linebuf, MAX_NETRC_LINE);
+ curlx_dyn_init(&linebuf, MAX_NETRC_LINE);
if(file) {
ret = NETRC_OK;
while(Curl_get_line(&linebuf, file)) {
CURLcode result;
- const char *line = Curl_dyn_ptr(&linebuf);
+ const char *line = curlx_dyn_ptr(&linebuf);
/* skip comments on load */
- Curl_str_passblanks(&line);
+ curlx_str_passblanks(&line);
if(*line == '#')
continue;
- result = Curl_dyn_add(filebuf, line);
+ result = curlx_dyn_add(filebuf, line);
if(result) {
ret = curl2netrc(result);
goto done;
@@ -97,7 +97,7 @@ static NETRCcode file2memory(const char *filename, struct dynbuf *filebuf)
}
}
done:
- Curl_dyn_free(&linebuf);
+ curlx_dyn_free(&linebuf);
if(file)
fclose(file);
return ret;
@@ -126,7 +126,7 @@ static NETRCcode parsenetrc(struct store_netrc *store,
struct dynbuf token;
struct dynbuf *filebuf = &store->filebuf;
DEBUGASSERT(!*passwordp);
- Curl_dyn_init(&token, MAX_NETRC_TOKEN);
+ curlx_dyn_init(&token, MAX_NETRC_TOKEN);
if(!store->loaded) {
NETRCcode ret = file2memory(netrcfile, filebuf);
@@ -135,15 +135,15 @@ static NETRCcode parsenetrc(struct store_netrc *store,
store->loaded = TRUE;
}
- netrcbuffer = Curl_dyn_ptr(filebuf);
+ netrcbuffer = curlx_dyn_ptr(filebuf);
while(!done) {
const char *tok = netrcbuffer;
while(tok && !done) {
const char *tok_end;
bool quoted;
- Curl_dyn_reset(&token);
- Curl_str_passblanks(&tok);
+ curlx_dyn_reset(&token);
+ curlx_str_passblanks(&tok);
/* tok is first non-space letter */
if(state == MACDEF) {
if((*tok == '\n') || (*tok == '\r'))
@@ -169,7 +169,7 @@ static NETRCcode parsenetrc(struct store_netrc *store,
retcode = NETRC_SYNTAX_ERROR;
goto out;
}
- result = Curl_dyn_addn(&token, tok, len);
+ result = curlx_dyn_addn(&token, tok, len);
if(result) {
retcode = curl2netrc(result);
goto out;
@@ -206,7 +206,7 @@ static NETRCcode parsenetrc(struct store_netrc *store,
endquote = TRUE;
break;
}
- result = Curl_dyn_addn(&token, &s, 1);
+ result = curlx_dyn_addn(&token, &s, 1);
if(result) {
retcode = curl2netrc(result);
goto out;
@@ -220,7 +220,12 @@ static NETRCcode parsenetrc(struct store_netrc *store,
}
}
- tok = Curl_dyn_ptr(&token);
+ if(curlx_dyn_len(&token))
+ tok = curlx_dyn_ptr(&token);
+ else
+ /* since tok might actually be NULL for no content, set it to blank
+ to avoid having to deal with it being NULL */
+ tok = "";
switch(state) {
case NOTHING:
@@ -332,7 +337,7 @@ static NETRCcode parsenetrc(struct store_netrc *store,
} /* while !done */
out:
- Curl_dyn_free(&token);
+ curlx_dyn_free(&token);
if(!retcode) {
if(!password && our_login) {
/* success without a password, set a blank one */
@@ -351,7 +356,7 @@ out:
*passwordp = password;
}
else {
- Curl_dyn_free(filebuf);
+ curlx_dyn_free(filebuf);
if(!specific_login)
free(login);
free(password);
@@ -456,12 +461,12 @@ NETRCcode Curl_parsenetrc(struct store_netrc *store, const char *host,
void Curl_netrc_init(struct store_netrc *s)
{
- Curl_dyn_init(&s->filebuf, MAX_NETRC_FILE);
+ curlx_dyn_init(&s->filebuf, MAX_NETRC_FILE);
s->loaded = FALSE;
}
void Curl_netrc_cleanup(struct store_netrc *s)
{
- Curl_dyn_free(&s->filebuf);
+ curlx_dyn_free(&s->filebuf);
s->loaded = FALSE;
}
#endif
diff --git a/libs/libcurl/src/netrc.h b/libs/libcurl/src/netrc.h
index de87097d88..0d44f986a0 100644
--- a/libs/libcurl/src/netrc.h
+++ b/libs/libcurl/src/netrc.h
@@ -26,7 +26,7 @@
#include "curl_setup.h"
#ifndef CURL_DISABLE_NETRC
-#include "dynbuf.h"
+#include "curlx/dynbuf.h"
struct store_netrc {
struct dynbuf filebuf;
diff --git a/libs/libcurl/src/noproxy.c b/libs/libcurl/src/noproxy.c
index 9ba35e8780..6ab99566f3 100644
--- a/libs/libcurl/src/noproxy.c
+++ b/libs/libcurl/src/noproxy.c
@@ -26,10 +26,10 @@
#ifndef CURL_DISABLE_PROXY
-#include "inet_pton.h"
+#include "curlx/inet_pton.h"
#include "strcase.h"
#include "noproxy.h"
-#include "strparse.h"
+#include "curlx/strparse.h"
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
@@ -178,7 +178,7 @@ bool Curl_check_noproxy(const char *name, const char *no_proxy)
bool match = FALSE;
/* pass blanks */
- Curl_str_passblanks(&p);
+ curlx_str_passblanks(&p);
token = p;
/* pass over the pattern */
@@ -247,7 +247,7 @@ bool Curl_check_noproxy(const char *name, const char *no_proxy)
return TRUE;
} /* if(tokenlen) */
/* pass blanks after pattern */
- Curl_str_passblanks(&p);
+ curlx_str_passblanks(&p);
/* if not a comma, this ends the loop */
if(*p != ',')
break;
diff --git a/libs/libcurl/src/openldap.c b/libs/libcurl/src/openldap.c
index acfc9a8f05..3a70cec8e7 100644
--- a/libs/libcurl/src/openldap.c
+++ b/libs/libcurl/src/openldap.c
@@ -41,12 +41,13 @@
#include <ldap.h>
#include "urldata.h"
+#include "url.h"
#include <curl/curl.h>
#include "sendf.h"
#include "vtls/vtls.h"
#include "transfer.h"
#include "curl_ldap.h"
-#include "curl_base64.h"
+#include "curlx/base64.h"
#include "cfilters.h"
#include "connect.h"
#include "curl_sasl.h"
@@ -202,15 +203,20 @@ struct ldapreqinfo {
int nument;
};
+/* meta key for storing ldapconninfo at easy handle */
+#define CURL_META_LDAP_EASY "meta:proto:ldap:easy"
+/* meta key for storing ldapconninfo at connection */
+#define CURL_META_LDAP_CONN "meta:proto:ldap:conn"
+
+
/*
* oldap_state()
*
* This is the ONLY way to change LDAP state!
*/
-static void oldap_state(struct Curl_easy *data, ldapstate newstate)
+static void oldap_state(struct Curl_easy *data, struct ldapconninfo *li,
+ ldapstate newstate)
{
- struct ldapconninfo *ldapc = data->conn->proto.ldapc;
-
#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
/* for debug purposes */
static const char * const names[] = {
@@ -225,12 +231,12 @@ static void oldap_state(struct Curl_easy *data, ldapstate newstate)
/* LAST */
};
- if(ldapc->state != newstate)
+ if(li->state != newstate)
infof(data, "LDAP %p state change from %s to %s",
- (void *)ldapc, names[ldapc->state], names[newstate]);
+ (void *)li, names[li->state], names[newstate]);
#endif
-
- ldapc->state = newstate;
+ (void)data;
+ li->state = newstate;
}
/* Map some particular LDAP error codes to CURLcode values. */
@@ -288,9 +294,13 @@ static CURLcode oldap_url_parse(struct Curl_easy *data, LDAPURLDesc **ludp)
static CURLcode oldap_parse_login_options(struct connectdata *conn)
{
CURLcode result = CURLE_OK;
- struct ldapconninfo *li = conn->proto.ldapc;
+ struct ldapconninfo *li = Curl_conn_meta_get(conn, CURL_META_LDAP_CONN);
const char *ptr = conn->options;
+ DEBUGASSERT(li);
+ if(!li)
+ return CURLE_FAILED_INIT;
+
while(!result && ptr && *ptr) {
const char *key = ptr;
const char *value;
@@ -334,7 +344,12 @@ static CURLcode oldap_setup_connection(struct Curl_easy *data,
*/
static CURLcode oldap_get_message(struct Curl_easy *data, struct bufref *out)
{
- struct berval *servercred = data->conn->proto.ldapc->servercred;
+ struct ldapconninfo *li =
+ Curl_conn_meta_get(data->conn, CURL_META_LDAP_CONN);
+ struct berval *servercred = li ? li->servercred : NULL;
+ DEBUGASSERT(li);
+ if(!li)
+ return CURLE_FAILED_INIT;
if(!servercred || !servercred->bv_val)
return CURLE_WEIRD_SERVER_REPLY;
@@ -349,11 +364,14 @@ static CURLcode oldap_perform_auth(struct Curl_easy *data, const char *mech,
const struct bufref *initresp)
{
struct connectdata *conn = data->conn;
- struct ldapconninfo *li = conn->proto.ldapc;
+ struct ldapconninfo *li = Curl_conn_meta_get(conn, CURL_META_LDAP_CONN);
struct berval cred;
struct berval *pcred = &cred;
int rc;
+ DEBUGASSERT(li);
+ if(!li)
+ return CURLE_FAILED_INIT;
cred.bv_val = (char *)CURL_UNCONST(Curl_bufref_ptr(initresp));
cred.bv_len = Curl_bufref_len(initresp);
if(!cred.bv_val)
@@ -371,11 +389,13 @@ static CURLcode oldap_continue_auth(struct Curl_easy *data, const char *mech,
const struct bufref *resp)
{
struct connectdata *conn = data->conn;
- struct ldapconninfo *li = conn->proto.ldapc;
+ struct ldapconninfo *li = Curl_conn_meta_get(conn, CURL_META_LDAP_CONN);
struct berval cred;
struct berval *pcred = &cred;
int rc;
+ if(!li)
+ return CURLE_FAILED_INIT;
cred.bv_val = (char *)CURL_UNCONST(Curl_bufref_ptr(resp));
cred.bv_len = Curl_bufref_len(resp);
if(!cred.bv_val)
@@ -391,11 +411,15 @@ static CURLcode oldap_continue_auth(struct Curl_easy *data, const char *mech,
*/
static CURLcode oldap_cancel_auth(struct Curl_easy *data, const char *mech)
{
- struct ldapconninfo *li = data->conn->proto.ldapc;
- int rc = ldap_sasl_bind(li->ld, NULL, LDAP_SASL_NULL, NULL, NULL, NULL,
- &li->msgid);
+ struct ldapconninfo *li =
+ Curl_conn_meta_get(data->conn, CURL_META_LDAP_CONN);
+ int rc;
(void)mech;
+ if(!li)
+ return CURLE_FAILED_INIT;
+ rc = ldap_sasl_bind(li->ld, NULL, LDAP_SASL_NULL, NULL, NULL, NULL,
+ &li->msgid);
if(rc != LDAP_SUCCESS)
return oldap_map_error(rc, CURLE_LDAP_CANNOT_BIND);
return CURLE_OK;
@@ -405,11 +429,13 @@ static CURLcode oldap_cancel_auth(struct Curl_easy *data, const char *mech)
static CURLcode oldap_perform_bind(struct Curl_easy *data, ldapstate newstate)
{
struct connectdata *conn = data->conn;
- struct ldapconninfo *li = conn->proto.ldapc;
+ struct ldapconninfo *li = Curl_conn_meta_get(conn, CURL_META_LDAP_CONN);
char *binddn = NULL;
struct berval passwd;
int rc;
+ if(!li)
+ return CURLE_FAILED_INIT;
passwd.bv_val = NULL;
passwd.bv_len = 0;
@@ -425,39 +451,47 @@ static CURLcode oldap_perform_bind(struct Curl_easy *data, ldapstate newstate)
return oldap_map_error(rc,
data->state.aptr.user ?
CURLE_LOGIN_DENIED : CURLE_LDAP_CANNOT_BIND);
- oldap_state(data, newstate);
+ oldap_state(data, li, newstate);
return CURLE_OK;
}
/* Query the supported SASL authentication mechanisms. */
static CURLcode oldap_perform_mechs(struct Curl_easy *data)
{
- struct ldapconninfo *li = data->conn->proto.ldapc;
+ struct ldapconninfo *li =
+ Curl_conn_meta_get(data->conn, CURL_META_LDAP_CONN);
int rc;
static const char * const supportedSASLMechanisms[] = {
"supportedSASLMechanisms",
NULL
};
+ if(!li)
+ return CURLE_FAILED_INIT;
rc = ldap_search_ext(li->ld, "", LDAP_SCOPE_BASE, "(objectclass=*)",
(char **)CURL_UNCONST(supportedSASLMechanisms), 0,
NULL, NULL, NULL, 0, &li->msgid);
if(rc != LDAP_SUCCESS)
return oldap_map_error(rc, CURLE_LOGIN_DENIED);
- oldap_state(data, OLDAP_MECHS);
+ oldap_state(data, li, OLDAP_MECHS);
return CURLE_OK;
}
/* Starts SASL bind. */
static CURLcode oldap_perform_sasl(struct Curl_easy *data)
{
+ struct ldapconninfo *li =
+ Curl_conn_meta_get(data->conn, CURL_META_LDAP_CONN);
saslprogress progress = SASL_IDLE;
- struct ldapconninfo *li = data->conn->proto.ldapc;
- CURLcode result = Curl_sasl_start(&li->sasl, data, TRUE, &progress);
+ CURLcode result;
+
+ if(!li)
+ return CURLE_FAILED_INIT;
+ result = Curl_sasl_start(&li->sasl, data, TRUE, &progress);
- oldap_state(data, OLDAP_SASL);
+ oldap_state(data, li, OLDAP_SASL);
if(!result && progress != SASL_INPROGRESS)
- result = CURLE_LOGIN_DENIED;
+ result = Curl_sasl_is_blocked(&li->sasl, data);
return result;
}
@@ -466,17 +500,22 @@ static Sockbuf_IO ldapsb_tls;
static bool ssl_installed(struct connectdata *conn)
{
- return conn->proto.ldapc->recv != NULL;
+ struct ldapconninfo *li = Curl_conn_meta_get(conn, CURL_META_LDAP_CONN);
+ return li && li->recv != NULL;
}
static CURLcode oldap_ssl_connect(struct Curl_easy *data, ldapstate newstate)
{
struct connectdata *conn = data->conn;
- struct ldapconninfo *li = conn->proto.ldapc;
+ struct ldapconninfo *li = Curl_conn_meta_get(conn, CURL_META_LDAP_CONN);
bool ssldone = FALSE;
- CURLcode result = Curl_conn_connect(data, FIRSTSOCKET, FALSE, &ssldone);
+ CURLcode result;
+
+ if(!li)
+ return CURLE_FAILED_INIT;
+ result = Curl_conn_connect(data, FIRSTSOCKET, FALSE, &ssldone);
if(!result) {
- oldap_state(data, newstate);
+ oldap_state(data, li, newstate);
if(ssldone) {
Sockbuf *sb;
@@ -495,45 +534,72 @@ static CURLcode oldap_ssl_connect(struct Curl_easy *data, ldapstate newstate)
/* Send the STARTTLS request */
static CURLcode oldap_perform_starttls(struct Curl_easy *data)
{
- struct ldapconninfo *li = data->conn->proto.ldapc;
- int rc = ldap_start_tls(li->ld, NULL, NULL, &li->msgid);
+ struct ldapconninfo *li =
+ Curl_conn_meta_get(data->conn, CURL_META_LDAP_CONN);
+ int rc;
+ if(!li)
+ return CURLE_FAILED_INIT;
+ rc = ldap_start_tls(li->ld, NULL, NULL, &li->msgid);
if(rc != LDAP_SUCCESS)
return oldap_map_error(rc, CURLE_USE_SSL_FAILED);
- oldap_state(data, OLDAP_STARTTLS);
+ oldap_state(data, li, OLDAP_STARTTLS);
return CURLE_OK;
}
#endif
+static void oldap_easy_dtor(void *key, size_t klen, void *entry)
+{
+ struct ldapreqinfo *lr = entry;
+ (void)key;
+ (void)klen;
+ free(lr);
+}
+
+static void oldap_conn_dtor(void *key, size_t klen, void *entry)
+{
+ struct ldapconninfo *li = entry;
+ (void)key;
+ (void)klen;
+ if(li->ld) {
+ ldap_unbind_ext(li->ld, NULL, NULL);
+ li->ld = NULL;
+ }
+ free(li);
+}
+
static CURLcode oldap_connect(struct Curl_easy *data, bool *done)
{
struct connectdata *conn = data->conn;
struct ldapconninfo *li;
static const int version = LDAP_VERSION3;
+ char *hosturl = NULL;
+ CURLcode result;
int rc;
- char *hosturl;
#ifdef CURL_OPENLDAP_DEBUG
static int do_trace = -1;
#endif
(void)done;
- DEBUGASSERT(!conn->proto.ldapc);
li = calloc(1, sizeof(struct ldapconninfo));
- if(!li)
- return CURLE_OUT_OF_MEMORY;
- else {
- CURLcode result;
- li->proto = ldap_pvt_url_scheme2proto(data->state.up.scheme);
- conn->proto.ldapc = li;
+ if(!li) {
+ result = CURLE_OUT_OF_MEMORY;
+ goto out;
+ }
- /* Initialize the SASL storage */
- Curl_sasl_init(&li->sasl, data, &saslldap);
+ result = Curl_conn_meta_set(conn, CURL_META_LDAP_CONN, li, oldap_conn_dtor);
+ if(result)
+ goto out;
- result = oldap_parse_login_options(conn);
- if(result)
- return result;
- }
+ li->proto = ldap_pvt_url_scheme2proto(data->state.up.scheme);
+
+ /* Initialize the SASL storage */
+ Curl_sasl_init(&li->sasl, data, &saslldap);
+
+ result = oldap_parse_login_options(conn);
+ if(result)
+ goto out;
hosturl = aprintf("%s://%s%s%s:%d",
conn->handler->scheme,
@@ -541,24 +607,24 @@ static CURLcode oldap_connect(struct Curl_easy *data, bool *done)
conn->host.name,
conn->bits.ipv6_ip ? "]" : "",
conn->remote_port);
- if(!hosturl)
- return CURLE_OUT_OF_MEMORY;
+ if(!hosturl) {
+ result = CURLE_OUT_OF_MEMORY;
+ goto out;
+ }
rc = ldap_init_fd(conn->sock[FIRSTSOCKET], li->proto, hosturl, &li->ld);
if(rc) {
failf(data, "LDAP local: Cannot connect to %s, %s",
hosturl, ldap_err2string(rc));
- free(hosturl);
- return CURLE_COULDNT_CONNECT;
+ result = CURLE_COULDNT_CONNECT;
+ goto out;
}
- free(hosturl);
-
#ifdef CURL_OPENLDAP_DEBUG
if(do_trace < 0) {
const char *env = getenv("CURL_OPENLDAP_TRACE");
curl_off_t e = 0;
- if(!Curl_str_number(&env, &e, INT_MAX))
+ if(!curlx_str_number(&env, &e, INT_MAX))
do_trace = e > 0;
}
if(do_trace)
@@ -572,23 +638,30 @@ static CURLcode oldap_connect(struct Curl_easy *data, bool *done)
ldap_set_option(li->ld, LDAP_OPT_REFERRALS, LDAP_OPT_OFF);
#ifdef USE_SSL
- if(Curl_conn_is_ssl(conn, FIRSTSOCKET))
- return oldap_ssl_connect(data, OLDAP_SSL);
+ if(Curl_conn_is_ssl(conn, FIRSTSOCKET)) {
+ result = oldap_ssl_connect(data, OLDAP_SSL);
+ goto out;
+ }
if(data->set.use_ssl) {
- CURLcode result = oldap_perform_starttls(data);
-
+ result = oldap_perform_starttls(data);
if(!result || data->set.use_ssl != CURLUSESSL_TRY)
- return result;
+ goto out;
}
#endif
- if(li->sasl.prefmech != SASL_AUTH_NONE)
- return oldap_perform_mechs(data);
+ if(li->sasl.prefmech != SASL_AUTH_NONE) {
+ result = oldap_perform_mechs(data);
+ goto out;
+ }
/* Force bind even if anonymous bind is not needed in protocol version 3
to detect missing version 3 support. */
- return oldap_perform_bind(data, OLDAP_BIND);
+ result = oldap_perform_bind(data, OLDAP_BIND);
+
+out:
+ free(hosturl);
+ return result;
}
/* Handle the supported SASL mechanisms query response */
@@ -596,12 +669,14 @@ static CURLcode oldap_state_mechs_resp(struct Curl_easy *data,
LDAPMessage *msg, int code)
{
struct connectdata *conn = data->conn;
- struct ldapconninfo *li = conn->proto.ldapc;
+ struct ldapconninfo *li = Curl_conn_meta_get(conn, CURL_META_LDAP_CONN);
int rc;
BerElement *ber = NULL;
CURLcode result = CURLE_OK;
struct berval bv, *bvals;
+ if(!li)
+ return CURLE_FAILED_INIT;
switch(ldap_msgtype(msg)) {
case LDAP_RES_SEARCH_ENTRY:
/* Got a list of supported SASL mechanisms. */
@@ -661,11 +736,13 @@ static CURLcode oldap_state_sasl_resp(struct Curl_easy *data,
LDAPMessage *msg, int code)
{
struct connectdata *conn = data->conn;
- struct ldapconninfo *li = conn->proto.ldapc;
+ struct ldapconninfo *li = Curl_conn_meta_get(conn, CURL_META_LDAP_CONN);
CURLcode result = CURLE_OK;
saslprogress progress;
int rc;
+ if(!li)
+ return CURLE_FAILED_INIT;
li->servercred = NULL;
rc = ldap_parse_sasl_bind_result(li->ld, msg, &li->servercred, 0);
if(rc != LDAP_SUCCESS) {
@@ -675,7 +752,7 @@ static CURLcode oldap_state_sasl_resp(struct Curl_easy *data,
else {
result = Curl_sasl_continue(&li->sasl, data, code, &progress);
if(!result && progress != SASL_INPROGRESS)
- oldap_state(data, OLDAP_STOP);
+ oldap_state(data, li, OLDAP_STOP);
}
if(li->servercred)
@@ -688,11 +765,14 @@ static CURLcode oldap_state_bind_resp(struct Curl_easy *data, LDAPMessage *msg,
int code)
{
struct connectdata *conn = data->conn;
- struct ldapconninfo *li = conn->proto.ldapc;
+ struct ldapconninfo *li = Curl_conn_meta_get(conn, CURL_META_LDAP_CONN);
CURLcode result = CURLE_OK;
struct berval *bv = NULL;
int rc;
+ if(!li)
+ return CURLE_FAILED_INIT;
+
if(code != LDAP_SUCCESS)
return oldap_map_error(code, CURLE_LDAP_CANNOT_BIND);
@@ -703,7 +783,7 @@ static CURLcode oldap_state_bind_resp(struct Curl_easy *data, LDAPMessage *msg,
result = oldap_map_error(rc, CURLE_LDAP_CANNOT_BIND);
}
else
- oldap_state(data, OLDAP_STOP);
+ oldap_state(data, li, OLDAP_STOP);
if(bv)
ber_bvfree(bv);
@@ -714,12 +794,15 @@ static CURLcode oldap_connecting(struct Curl_easy *data, bool *done)
{
CURLcode result = CURLE_OK;
struct connectdata *conn = data->conn;
- struct ldapconninfo *li = conn->proto.ldapc;
+ struct ldapconninfo *li = Curl_conn_meta_get(conn, CURL_META_LDAP_CONN);
LDAPMessage *msg = NULL;
struct timeval tv = {0, 0};
int code = LDAP_SUCCESS;
int rc;
+ if(!li)
+ return CURLE_FAILED_INIT;
+
if(li->state != OLDAP_SSL && li->state != OLDAP_TLS) {
/* Get response to last command. */
rc = ldap_result(li->ld, li->msgid, LDAP_MSG_ONE, &tv, &msg);
@@ -800,7 +883,7 @@ static CURLcode oldap_connecting(struct Curl_easy *data, bool *done)
result = oldap_perform_bind(data, OLDAP_BIND);
else {
/* Version 3 supported: no bind required */
- oldap_state(data, OLDAP_STOP);
+ oldap_state(data, li, OLDAP_STOP);
result = CURLE_OK;
}
}
@@ -840,7 +923,7 @@ static CURLcode oldap_disconnect(struct Curl_easy *data,
struct connectdata *conn,
bool dead_connection)
{
- struct ldapconninfo *li = conn->proto.ldapc;
+ struct ldapconninfo *li = Curl_conn_meta_get(conn, CURL_META_LDAP_CONN);
(void) dead_connection;
#ifndef USE_SSL
(void)data;
@@ -859,8 +942,6 @@ static CURLcode oldap_disconnect(struct Curl_easy *data,
li->ld = NULL;
}
Curl_sasl_cleanup(conn, li->sasl.authused);
- conn->proto.ldapc = NULL;
- free(li);
}
return CURLE_OK;
}
@@ -868,50 +949,55 @@ static CURLcode oldap_disconnect(struct Curl_easy *data,
static CURLcode oldap_do(struct Curl_easy *data, bool *done)
{
struct connectdata *conn = data->conn;
- struct ldapconninfo *li = conn->proto.ldapc;
+ struct ldapconninfo *li = Curl_conn_meta_get(conn, CURL_META_LDAP_CONN);
struct ldapreqinfo *lr;
CURLcode result;
int rc;
LDAPURLDesc *lud;
int msgid;
+ if(!li)
+ return CURLE_FAILED_INIT;
connkeep(conn, "OpenLDAP do");
infof(data, "LDAP local: %s", data->state.url);
result = oldap_url_parse(data, &lud);
- if(!result) {
+ if(result)
+ goto out;
+
#ifdef USE_SSL
- if(ssl_installed(conn)) {
- Sockbuf *sb;
- /* re-install the libcurl SSL handlers into the sockbuf. */
- ldap_get_option(li->ld, LDAP_OPT_SOCKBUF, &sb);
- ber_sockbuf_add_io(sb, &ldapsb_tls, LBER_SBIOD_LEVEL_TRANSPORT, data);
- }
+ if(ssl_installed(conn)) {
+ Sockbuf *sb;
+ /* re-install the libcurl SSL handlers into the sockbuf. */
+ ldap_get_option(li->ld, LDAP_OPT_SOCKBUF, &sb);
+ ber_sockbuf_add_io(sb, &ldapsb_tls, LBER_SBIOD_LEVEL_TRANSPORT, data);
+ }
#endif
- rc = ldap_search_ext(li->ld, lud->lud_dn, lud->lud_scope,
- lud->lud_filter, lud->lud_attrs, 0,
- NULL, NULL, NULL, 0, &msgid);
- ldap_free_urldesc(lud);
- if(rc != LDAP_SUCCESS) {
- failf(data, "LDAP local: ldap_search_ext %s", ldap_err2string(rc));
- result = CURLE_LDAP_SEARCH_FAILED;
- }
- else {
- lr = calloc(1, sizeof(struct ldapreqinfo));
- if(!lr) {
- ldap_abandon_ext(li->ld, msgid, NULL, NULL);
- result = CURLE_OUT_OF_MEMORY;
- }
- else {
- lr->msgid = msgid;
- data->req.p.ldap = lr;
- Curl_xfer_setup1(data, CURL_XFER_RECV, -1, FALSE);
- *done = TRUE;
- }
- }
+ rc = ldap_search_ext(li->ld, lud->lud_dn, lud->lud_scope,
+ lud->lud_filter, lud->lud_attrs, 0,
+ NULL, NULL, NULL, 0, &msgid);
+ ldap_free_urldesc(lud);
+ if(rc != LDAP_SUCCESS) {
+ failf(data, "LDAP local: ldap_search_ext %s", ldap_err2string(rc));
+ result = CURLE_LDAP_SEARCH_FAILED;
+ goto out;
}
+
+ lr = calloc(1, sizeof(struct ldapreqinfo));
+ if(!lr ||
+ Curl_meta_set(data, CURL_META_LDAP_EASY, lr, oldap_easy_dtor)) {
+ ldap_abandon_ext(li->ld, msgid, NULL, NULL);
+ result = CURLE_OUT_OF_MEMORY;
+ goto out;
+ }
+
+ lr->msgid = msgid;
+ Curl_xfer_setup1(data, CURL_XFER_RECV, -1, FALSE);
+ *done = TRUE;
+
+out:
return result;
}
@@ -919,7 +1005,7 @@ static CURLcode oldap_done(struct Curl_easy *data, CURLcode res,
bool premature)
{
struct connectdata *conn = data->conn;
- struct ldapreqinfo *lr = data->req.p.ldap;
+ struct ldapreqinfo *lr = Curl_meta_get(data, CURL_META_LDAP_EASY);
(void)res;
(void)premature;
@@ -927,12 +1013,13 @@ static CURLcode oldap_done(struct Curl_easy *data, CURLcode res,
if(lr) {
/* if there was a search in progress, abandon it */
if(lr->msgid) {
- struct ldapconninfo *li = conn->proto.ldapc;
- ldap_abandon_ext(li->ld, lr->msgid, NULL, NULL);
+ struct ldapconninfo *li = Curl_conn_meta_get(conn, CURL_META_LDAP_CONN);
+ if(li && li->ld) {
+ ldap_abandon_ext(li->ld, lr->msgid, NULL, NULL);
+ }
lr->msgid = 0;
}
- data->req.p.ldap = NULL;
- free(lr);
+ Curl_meta_remove(data, CURL_META_LDAP_EASY);
}
return CURLE_OK;
@@ -965,8 +1052,8 @@ static ssize_t oldap_recv(struct Curl_easy *data, int sockindex, char *buf,
size_t len, CURLcode *err)
{
struct connectdata *conn = data->conn;
- struct ldapconninfo *li = conn->proto.ldapc;
- struct ldapreqinfo *lr = data->req.p.ldap;
+ struct ldapconninfo *li = Curl_conn_meta_get(conn, CURL_META_LDAP_CONN);
+ struct ldapreqinfo *lr = Curl_meta_get(data, CURL_META_LDAP_EASY);
int rc;
LDAPMessage *msg = NULL;
BerElement *ber = NULL;
@@ -980,6 +1067,10 @@ static ssize_t oldap_recv(struct Curl_easy *data, int sockindex, char *buf,
(void)len;
(void)buf;
(void)sockindex;
+ if(!li || !lr) {
+ *err = CURLE_FAILED_INIT;
+ return -1;
+ }
rc = ldap_result(li->ld, lr->msgid, LDAP_MSG_ONE, &tv, &msg);
if(rc < 0) {
@@ -1086,8 +1177,8 @@ static ssize_t oldap_recv(struct Curl_easy *data, int sockindex, char *buf,
/* Binary value, encode to base64. */
if(bvals[i].bv_len)
- result = Curl_base64_encode(bvals[i].bv_val, bvals[i].bv_len,
- &val_b64, &val_b64_sz);
+ result = curlx_base64_encode(bvals[i].bv_val, bvals[i].bv_len,
+ &val_b64, &val_b64_sz);
if(!result)
result = client_write(data, STRCONST(": "), val_b64, val_b64_sz,
STRCONST("\n"));
@@ -1165,9 +1256,13 @@ ldapsb_tls_read(Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len)
if(data) {
struct connectdata *conn = data->conn;
if(conn) {
- struct ldapconninfo *li = conn->proto.ldapc;
+ struct ldapconninfo *li = Curl_conn_meta_get(conn, CURL_META_LDAP_CONN);
CURLcode err = CURLE_RECV_ERROR;
+ if(!li) {
+ SET_SOCKERRNO(SOCKEINVAL);
+ return -1;
+ }
ret = (li->recv)(data, FIRSTSOCKET, buf, len, &err);
if(ret < 0 && err == CURLE_AGAIN) {
SET_SOCKERRNO(SOCKEWOULDBLOCK);
@@ -1176,7 +1271,6 @@ ldapsb_tls_read(Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len)
}
return ret;
}
-
static ber_slen_t
ldapsb_tls_write(Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len)
{
@@ -1185,8 +1279,13 @@ ldapsb_tls_write(Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len)
if(data) {
struct connectdata *conn = data->conn;
if(conn) {
- struct ldapconninfo *li = conn->proto.ldapc;
+ struct ldapconninfo *li = Curl_conn_meta_get(conn, CURL_META_LDAP_CONN);
CURLcode err = CURLE_SEND_ERROR;
+
+ if(!li) {
+ SET_SOCKERRNO(SOCKEINVAL);
+ return -1;
+ }
ret = (li->send)(data, FIRSTSOCKET, buf, len, FALSE, &err);
if(ret < 0 && err == CURLE_AGAIN) {
SET_SOCKERRNO(SOCKEWOULDBLOCK);
diff --git a/libs/libcurl/src/optiontable.pl b/libs/libcurl/src/optiontable.pl
index 07e66769d6..31e3c8c620 100644
--- a/libs/libcurl/src/optiontable.pl
+++ b/libs/libcurl/src/optiontable.pl
@@ -31,7 +31,7 @@ print <<HEAD
#include "easyoptions.h"
/* all easy setopt options listed in alphabetical order */
-struct curl_easyoption Curl_easyopts[] = {
+const struct curl_easyoption Curl_easyopts[] = {
HEAD
;
@@ -109,7 +109,7 @@ while(<STDIN>) {
$o =~ s/^CURLOPT_//;
$n =~ s/^CURLOPT_//;
$alias{$o} = $n;
- push @names, $o,
+ push @names, $o;
}
}
}
diff --git a/libs/libcurl/src/parsedate.c b/libs/libcurl/src/parsedate.c
index 46c9feb14f..343fa9dcfe 100644
--- a/libs/libcurl/src/parsedate.c
+++ b/libs/libcurl/src/parsedate.c
@@ -81,9 +81,9 @@
#include <curl/curl.h>
#include "strcase.h"
-#include "warnless.h"
+#include "curlx/warnless.h"
#include "parsedate.h"
-#include "strparse.h"
+#include "curlx/strparse.h"
/*
* parsedate()
@@ -106,7 +106,7 @@ static int parsedate(const char *date, time_t *output);
#endif
#if !defined(CURL_DISABLE_PARSEDATE) || !defined(CURL_DISABLE_FTP) || \
- !defined(CURL_DISABLE_FILE)
+ !defined(CURL_DISABLE_FILE) || defined(USE_GNUTLS)
/* These names are also used by FTP and FILE code */
const char * const Curl_wkday[] =
{"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"};
@@ -423,7 +423,7 @@ static int parsedate(const char *date, time_t *output)
curl_off_t lval;
int num_digits = 0;
const char *p = date;
- if(Curl_str_number(&p, &lval, 99999999))
+ if(curlx_str_number(&p, &lval, 99999999))
return PARSEDATE_FAIL;
/* we know num_digits cannot be larger than 8 */
diff --git a/libs/libcurl/src/pingpong.c b/libs/libcurl/src/pingpong.c
index f4ac9e163c..4f0171ad3d 100644
--- a/libs/libcurl/src/pingpong.c
+++ b/libs/libcurl/src/pingpong.c
@@ -54,7 +54,7 @@ timediff_t Curl_pp_state_timeout(struct Curl_easy *data,
timediff_t timeout_ms; /* in milliseconds */
timediff_t response_time = (data->set.server_response_timeout) ?
data->set.server_response_timeout : pp->response_time;
- struct curltime now = Curl_now();
+ struct curltime now = curlx_now();
/* if CURLOPT_SERVER_RESPONSE_TIMEOUT is set, use that to determine
remaining time, or use pp->response because SERVER_RESPONSE_TIMEOUT is
@@ -63,7 +63,7 @@ timediff_t Curl_pp_state_timeout(struct Curl_easy *data,
/* Without a requested timeout, we only wait 'response_time' seconds for the
full response to arrive before we bail out */
- timeout_ms = response_time - Curl_timediff(now, pp->response);
+ timeout_ms = response_time - curlx_timediff(now, pp->response);
if(data->set.timeout && !disconnecting) {
/* if timeout is requested, find out how much overall remains */
@@ -127,7 +127,7 @@ CURLcode Curl_pp_statemach(struct Curl_easy *data,
if(Curl_pgrsUpdate(data))
result = CURLE_ABORTED_BY_CALLBACK;
else
- result = Curl_speedcheck(data, Curl_now());
+ result = Curl_speedcheck(data, curlx_now());
if(result)
return result;
@@ -150,10 +150,10 @@ void Curl_pp_init(struct pingpong *pp)
{
DEBUGASSERT(!pp->initialised);
pp->nread_resp = 0;
- pp->response = Curl_now(); /* start response time-out now! */
+ pp->response = curlx_now(); /* start response time-out now! */
pp->pending_resp = TRUE;
- Curl_dyn_init(&pp->sendbuf, DYN_PINGPPONG_CMD);
- Curl_dyn_init(&pp->recvbuf, DYN_PINGPPONG_CMD);
+ curlx_dyn_init(&pp->sendbuf, DYN_PINGPPONG_CMD);
+ curlx_dyn_init(&pp->recvbuf, DYN_PINGPPONG_CMD);
pp->initialised = TRUE;
}
@@ -190,19 +190,19 @@ CURLcode Curl_pp_vsendf(struct Curl_easy *data,
/* cannot send without a connection! */
return CURLE_SEND_ERROR;
- Curl_dyn_reset(&pp->sendbuf);
- result = Curl_dyn_vaddf(&pp->sendbuf, fmt, args);
+ curlx_dyn_reset(&pp->sendbuf);
+ result = curlx_dyn_vaddf(&pp->sendbuf, fmt, args);
if(result)
return result;
/* append CRLF */
- result = Curl_dyn_addn(&pp->sendbuf, "\r\n", 2);
+ result = curlx_dyn_addn(&pp->sendbuf, "\r\n", 2);
if(result)
return result;
pp->pending_resp = TRUE;
- write_len = Curl_dyn_len(&pp->sendbuf);
- s = Curl_dyn_ptr(&pp->sendbuf);
+ write_len = curlx_dyn_len(&pp->sendbuf);
+ s = curlx_dyn_ptr(&pp->sendbuf);
#ifdef HAVE_GSSAPI
conn->data_prot = PROT_CMD;
@@ -231,7 +231,7 @@ CURLcode Curl_pp_vsendf(struct Curl_easy *data,
else {
pp->sendthis = NULL;
pp->sendleft = pp->sendsize = 0;
- pp->response = Curl_now();
+ pp->response = curlx_now();
}
return CURLE_OK;
@@ -305,10 +305,10 @@ CURLcode Curl_pp_readresp(struct Curl_easy *data,
if(pp->nfinal) {
/* a previous call left this many bytes in the beginning of the buffer as
that was the final line; now ditch that */
- size_t full = Curl_dyn_len(&pp->recvbuf);
+ size_t full = curlx_dyn_len(&pp->recvbuf);
/* trim off the "final" leading part */
- Curl_dyn_tail(&pp->recvbuf, full - pp->nfinal);
+ curlx_dyn_tail(&pp->recvbuf, full - pp->nfinal);
pp->nfinal = 0; /* now gone */
}
@@ -326,7 +326,7 @@ CURLcode Curl_pp_readresp(struct Curl_easy *data,
return CURLE_RECV_ERROR;
}
- result = Curl_dyn_addn(&pp->recvbuf, buffer, gotbytes);
+ result = curlx_dyn_addn(&pp->recvbuf, buffer, gotbytes);
if(result)
return result;
@@ -336,8 +336,8 @@ CURLcode Curl_pp_readresp(struct Curl_easy *data,
}
do {
- char *line = Curl_dyn_ptr(&pp->recvbuf);
- char *nl = memchr(line, '\n', Curl_dyn_len(&pp->recvbuf));
+ char *line = curlx_dyn_ptr(&pp->recvbuf);
+ char *nl = memchr(line, '\n', curlx_dyn_len(&pp->recvbuf));
if(nl) {
/* a newline is CRLF in pp-talk, so the CR is ignored as
the line is not really terminated until the LF comes */
@@ -363,8 +363,8 @@ CURLcode Curl_pp_readresp(struct Curl_easy *data,
parsers). Store the overflow counter to inform about additional
data in this buffer after the endofresp line. */
pp->nfinal = length;
- if(Curl_dyn_len(&pp->recvbuf) > length)
- pp->overflow = Curl_dyn_len(&pp->recvbuf) - length;
+ if(curlx_dyn_len(&pp->recvbuf) > length)
+ pp->overflow = curlx_dyn_len(&pp->recvbuf) - length;
else
pp->overflow = 0;
*size = pp->nread_resp; /* size of the response */
@@ -372,11 +372,11 @@ CURLcode Curl_pp_readresp(struct Curl_easy *data,
gotbytes = 0; /* force break out of outer loop */
break;
}
- if(Curl_dyn_len(&pp->recvbuf) > length)
+ if(curlx_dyn_len(&pp->recvbuf) > length)
/* keep the remaining piece */
- Curl_dyn_tail((&pp->recvbuf), Curl_dyn_len(&pp->recvbuf) - length);
+ curlx_dyn_tail((&pp->recvbuf), curlx_dyn_len(&pp->recvbuf) - length);
else
- Curl_dyn_reset(&pp->recvbuf);
+ curlx_dyn_reset(&pp->recvbuf);
}
else {
/* without a newline, there is no overflow */
@@ -442,7 +442,7 @@ CURLcode Curl_pp_flushsend(struct Curl_easy *data,
else {
pp->sendthis = NULL;
pp->sendleft = pp->sendsize = 0;
- pp->response = Curl_now();
+ pp->response = curlx_now();
}
return CURLE_OK;
}
@@ -450,8 +450,8 @@ CURLcode Curl_pp_flushsend(struct Curl_easy *data,
CURLcode Curl_pp_disconnect(struct pingpong *pp)
{
if(pp->initialised) {
- Curl_dyn_free(&pp->sendbuf);
- Curl_dyn_free(&pp->recvbuf);
+ curlx_dyn_free(&pp->sendbuf);
+ curlx_dyn_free(&pp->recvbuf);
memset(pp, 0, sizeof(*pp));
}
return CURLE_OK;
@@ -459,7 +459,7 @@ CURLcode Curl_pp_disconnect(struct pingpong *pp)
bool Curl_pp_moredata(struct pingpong *pp)
{
- return !pp->sendleft && Curl_dyn_len(&pp->recvbuf) > pp->nfinal;
+ return !pp->sendleft && curlx_dyn_len(&pp->recvbuf) > pp->nfinal;
}
#endif
diff --git a/libs/libcurl/src/pingpong.h b/libs/libcurl/src/pingpong.h
index bc29c15175..46a02d763e 100644
--- a/libs/libcurl/src/pingpong.h
+++ b/libs/libcurl/src/pingpong.h
@@ -48,9 +48,6 @@ typedef enum {
*/
struct pingpong {
size_t nread_resp; /* number of bytes currently read of a server response */
- bool pending_resp; /* set TRUE when a server response is pending or in
- progress, and is cleared once the last response is
- read */
char *sendthis; /* pointer to a buffer that is to be sent to the server */
size_t sendleft; /* number of bytes left to send from the sendthis buffer */
size_t sendsize; /* total size of the sendthis buffer */
@@ -71,13 +68,16 @@ struct pingpong {
bool (*endofresp)(struct Curl_easy *data, struct connectdata *conn,
const char *ptr, size_t len, int *code);
BIT(initialised);
+ BIT(pending_resp); /* set TRUE when a server response is pending or in
+ progress, and is cleared once the last response is
+ read */
};
#define PINGPONG_SETUP(pp,s,e) \
do { \
- pp->response_time = RESP_TIMEOUT; \
- pp->statemachine = s; \
- pp->endofresp = e; \
+ (pp)->response_time = RESP_TIMEOUT; \
+ (pp)->statemachine = s; \
+ (pp)->endofresp = e; \
} while(0)
/*
diff --git a/libs/libcurl/src/pop3.c b/libs/libcurl/src/pop3.c
index 3df22dae84..ae64e0452b 100644
--- a/libs/libcurl/src/pop3.c
+++ b/libs/libcurl/src/pop3.c
@@ -64,6 +64,7 @@
#include "escape.h"
#include "http.h" /* for HTTP proxy tunnel stuff */
#include "socks.h"
+#include "pingpong.h"
#include "pop3.h"
#include "strcase.h"
#include "vtls/vtls.h"
@@ -75,13 +76,75 @@
#include "bufref.h"
#include "curl_sasl.h"
#include "curl_md5.h"
-#include "warnless.h"
+#include "curlx/warnless.h"
#include "strdup.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h"
#include "memdebug.h"
+/* Authentication type flags */
+#define POP3_TYPE_CLEARTEXT (1 << 0)
+#define POP3_TYPE_APOP (1 << 1)
+#define POP3_TYPE_SASL (1 << 2)
+
+/* Authentication type values */
+#define POP3_TYPE_NONE 0
+#define POP3_TYPE_ANY (POP3_TYPE_CLEARTEXT|POP3_TYPE_APOP|POP3_TYPE_SASL)
+
+/* This is the 5-bytes End-Of-Body marker for POP3 */
+#define POP3_EOB "\x0d\x0a\x2e\x0d\x0a"
+#define POP3_EOB_LEN 5
+
+/* meta key for storing protocol meta at easy handle */
+#define CURL_META_POP3_EASY "meta:proto:pop3:easy"
+/* meta key for storing protocol meta at connection */
+#define CURL_META_POP3_CONN "meta:proto:pop3:conn"
+
+/*
+ * POP3 easy handle state
+ */
+struct POP3 {
+ curl_pp_transfer transfer;
+ char *id; /* Message ID */
+ char *custom; /* Custom Request */
+};
+
+/*
+ * POP3 connection state
+ */
+typedef enum {
+ POP3_STOP, /* do nothing state, stops the state machine */
+ POP3_SERVERGREET, /* waiting for the initial greeting immediately after
+ a connect */
+ POP3_CAPA,
+ POP3_STARTTLS,
+ POP3_UPGRADETLS, /* asynchronously upgrade the connection to SSL/TLS
+ (multi mode only) */
+ POP3_AUTH,
+ POP3_APOP,
+ POP3_USER,
+ POP3_PASS,
+ POP3_COMMAND,
+ POP3_QUIT,
+ POP3_LAST /* never used */
+} pop3state;
+
+struct pop3_conn {
+ struct pingpong pp;
+ pop3state state; /* Always use pop3.c:state() to change state! */
+ size_t eob; /* Number of bytes of the EOB (End Of Body) that
+ have been received so far */
+ size_t strip; /* Number of bytes from the start to ignore as
+ non-body */
+ struct SASL sasl; /* SASL-related storage */
+ char *apoptimestamp; /* APOP timestamp from the server greeting */
+ unsigned char authtypes; /* Accepted authentication types */
+ unsigned char preftype; /* Preferred authentication type */
+ BIT(ssldone); /* Is connect() over SSL done? */
+ BIT(tls_supported); /* StartTLS capability supported by server */
+};
+
/* Local API functions */
static CURLcode pop3_regular_transfer(struct Curl_easy *data, bool *done);
static CURLcode pop3_do(struct Curl_easy *data, bool *done);
@@ -246,8 +309,11 @@ static bool pop3_is_multiline(const char *cmdline)
static bool pop3_endofresp(struct Curl_easy *data, struct connectdata *conn,
const char *line, size_t len, int *resp)
{
- struct pop3_conn *pop3c = &conn->proto.pop3c;
+ struct pop3_conn *pop3c = Curl_conn_meta_get(conn, CURL_META_POP3_CONN);
(void)data;
+ DEBUGASSERT(pop3c);
+ if(!pop3c) /* internal error */
+ return TRUE;
/* Do we have an error response? */
if(len >= 4 && !memcmp("-ERR", line, 4)) {
@@ -294,9 +360,15 @@ static bool pop3_endofresp(struct Curl_easy *data, struct connectdata *conn,
*/
static CURLcode pop3_get_message(struct Curl_easy *data, struct bufref *out)
{
- char *message = Curl_dyn_ptr(&data->conn->proto.pop3c.pp.recvbuf);
- size_t len = data->conn->proto.pop3c.pp.nfinal;
-
+ struct pop3_conn *pop3c =
+ Curl_conn_meta_get(data->conn, CURL_META_POP3_CONN);
+ char *message;
+ size_t len;
+
+ if(!pop3c)
+ return CURLE_FAILED_INIT;
+ message = curlx_dyn_ptr(&pop3c->pp.recvbuf);
+ len = pop3c->pp.nfinal;
if(len > 2) {
/* Find the start of the message */
len -= 2;
@@ -328,30 +400,33 @@ static CURLcode pop3_get_message(struct Curl_easy *data, struct bufref *out)
*/
static void pop3_state(struct Curl_easy *data, pop3state newstate)
{
- struct pop3_conn *pop3c = &data->conn->proto.pop3c;
+ struct pop3_conn *pop3c =
+ Curl_conn_meta_get(data->conn, CURL_META_POP3_CONN);
+ if(pop3c) {
#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
- /* for debug purposes */
- static const char * const names[] = {
- "STOP",
- "SERVERGREET",
- "CAPA",
- "STARTTLS",
- "UPGRADETLS",
- "AUTH",
- "APOP",
- "USER",
- "PASS",
- "COMMAND",
- "QUIT",
- /* LAST */
- };
-
- if(pop3c->state != newstate)
- infof(data, "POP3 %p state change from %s to %s",
- (void *)pop3c, names[pop3c->state], names[newstate]);
+ /* for debug purposes */
+ static const char * const names[] = {
+ "STOP",
+ "SERVERGREET",
+ "CAPA",
+ "STARTTLS",
+ "UPGRADETLS",
+ "AUTH",
+ "APOP",
+ "USER",
+ "PASS",
+ "COMMAND",
+ "QUIT",
+ /* LAST */
+ };
+
+ if(pop3c->state != newstate)
+ infof(data, "POP3 %p state change from %s to %s",
+ (void *)pop3c, names[pop3c->state], names[newstate]);
#endif
- pop3c->state = newstate;
+ pop3c->state = newstate;
+ }
}
/***********************************************************************
@@ -364,8 +439,11 @@ static void pop3_state(struct Curl_easy *data, pop3state newstate)
static CURLcode pop3_perform_capa(struct Curl_easy *data,
struct connectdata *conn)
{
+ struct pop3_conn *pop3c = Curl_conn_meta_get(conn, CURL_META_POP3_CONN);
CURLcode result = CURLE_OK;
- struct pop3_conn *pop3c = &conn->proto.pop3c;
+
+ if(!pop3c)
+ return CURLE_FAILED_INIT;
pop3c->sasl.authmechs = SASL_AUTH_NONE; /* No known auth. mechanisms yet */
pop3c->sasl.authused = SASL_AUTH_NONE; /* Clear the auth. mechanism used */
@@ -389,9 +467,14 @@ static CURLcode pop3_perform_capa(struct Curl_easy *data,
static CURLcode pop3_perform_starttls(struct Curl_easy *data,
struct connectdata *conn)
{
- /* Send the STLS command */
- CURLcode result = Curl_pp_sendf(data, &conn->proto.pop3c.pp, "%s", "STLS");
+ struct pop3_conn *pop3c = Curl_conn_meta_get(conn, CURL_META_POP3_CONN);
+ CURLcode result;
+ if(!pop3c)
+ return CURLE_FAILED_INIT;
+
+ /* Send the STLS command */
+ result = Curl_pp_sendf(data, &pop3c->pp, "%s", "STLS");
if(!result)
pop3_state(data, POP3_STARTTLS);
@@ -409,10 +492,13 @@ static CURLcode pop3_perform_upgrade_tls(struct Curl_easy *data,
{
#ifdef USE_SSL
/* Start the SSL connection */
- struct pop3_conn *pop3c = &conn->proto.pop3c;
+ struct pop3_conn *pop3c = Curl_conn_meta_get(conn, CURL_META_POP3_CONN);
CURLcode result;
bool ssldone = FALSE;
+ if(!pop3c)
+ return CURLE_FAILED_INIT;
+
if(!Curl_conn_is_ssl(conn, FIRSTSOCKET)) {
result = Curl_ssl_cfilter_add(data, conn, FIRSTSOCKET);
if(result)
@@ -448,8 +534,12 @@ out:
static CURLcode pop3_perform_user(struct Curl_easy *data,
struct connectdata *conn)
{
+ struct pop3_conn *pop3c = Curl_conn_meta_get(conn, CURL_META_POP3_CONN);
CURLcode result = CURLE_OK;
+ if(!pop3c)
+ return CURLE_FAILED_INIT;
+
/* Check we have a username and password to authenticate with and end the
connect phase if we do not */
if(!data->state.aptr.user) {
@@ -459,7 +549,7 @@ static CURLcode pop3_perform_user(struct Curl_easy *data,
}
/* Send the USER command */
- result = Curl_pp_sendf(data, &conn->proto.pop3c.pp, "USER %s",
+ result = Curl_pp_sendf(data, &pop3c->pp, "USER %s",
conn->user ? conn->user : "");
if(!result)
pop3_state(data, POP3_USER);
@@ -477,13 +567,16 @@ static CURLcode pop3_perform_user(struct Curl_easy *data,
static CURLcode pop3_perform_apop(struct Curl_easy *data,
struct connectdata *conn)
{
+ struct pop3_conn *pop3c = Curl_conn_meta_get(conn, CURL_META_POP3_CONN);
CURLcode result = CURLE_OK;
- struct pop3_conn *pop3c = &conn->proto.pop3c;
size_t i;
struct MD5_context *ctxt;
unsigned char digest[MD5_DIGEST_LEN];
char secret[2 * MD5_DIGEST_LEN + 1];
+ if(!pop3c)
+ return CURLE_FAILED_INIT;
+
/* Check we have a username and password to authenticate with and end the
connect phase if we do not */
if(!data->state.aptr.user) {
@@ -530,10 +623,14 @@ static CURLcode pop3_perform_auth(struct Curl_easy *data,
const char *mech,
const struct bufref *initresp)
{
+ struct pop3_conn *pop3c =
+ Curl_conn_meta_get(data->conn, CURL_META_POP3_CONN);
CURLcode result = CURLE_OK;
- struct pop3_conn *pop3c = &data->conn->proto.pop3c;
const char *ir = (const char *) Curl_bufref_ptr(initresp);
+ if(!pop3c)
+ return CURLE_FAILED_INIT;
+
if(ir) { /* AUTH <mech> ...<crlf> */
/* Send the AUTH command with the initial response */
result = Curl_pp_sendf(data, &pop3c->pp, "AUTH %s %s", mech, ir);
@@ -556,9 +653,12 @@ static CURLcode pop3_continue_auth(struct Curl_easy *data,
const char *mech,
const struct bufref *resp)
{
- struct pop3_conn *pop3c = &data->conn->proto.pop3c;
+ struct pop3_conn *pop3c =
+ Curl_conn_meta_get(data->conn, CURL_META_POP3_CONN);
(void)mech;
+ if(!pop3c)
+ return CURLE_FAILED_INIT;
return Curl_pp_sendf(data, &pop3c->pp,
"%s", (const char *) Curl_bufref_ptr(resp));
@@ -572,9 +672,12 @@ static CURLcode pop3_continue_auth(struct Curl_easy *data,
*/
static CURLcode pop3_cancel_auth(struct Curl_easy *data, const char *mech)
{
- struct pop3_conn *pop3c = &data->conn->proto.pop3c;
+ struct pop3_conn *pop3c =
+ Curl_conn_meta_get(data->conn, CURL_META_POP3_CONN);
(void)mech;
+ if(!pop3c)
+ return CURLE_FAILED_INIT;
return Curl_pp_sendf(data, &pop3c->pp, "*");
}
@@ -590,10 +693,13 @@ static CURLcode pop3_cancel_auth(struct Curl_easy *data, const char *mech)
static CURLcode pop3_perform_authentication(struct Curl_easy *data,
struct connectdata *conn)
{
+ struct pop3_conn *pop3c = Curl_conn_meta_get(conn, CURL_META_POP3_CONN);
CURLcode result = CURLE_OK;
- struct pop3_conn *pop3c = &conn->proto.pop3c;
saslprogress progress = SASL_IDLE;
+ if(!pop3c)
+ return CURLE_FAILED_INIT;
+
/* Check we have enough data to authenticate with and end the
connect phase if we do not */
if(!Curl_sasl_can_authenticate(&pop3c->sasl, data)) {
@@ -620,11 +726,8 @@ static CURLcode pop3_perform_authentication(struct Curl_easy *data,
if(pop3c->authtypes & pop3c->preftype & POP3_TYPE_CLEARTEXT)
/* Perform clear text authentication */
result = pop3_perform_user(data, conn);
- else {
- /* Other mechanisms not supported */
- infof(data, "No known authentication mechanisms supported");
- result = CURLE_LOGIN_DENIED;
- }
+ else
+ result = Curl_sasl_is_blocked(&pop3c->sasl, data);
}
return result;
@@ -640,9 +743,13 @@ static CURLcode pop3_perform_command(struct Curl_easy *data)
{
CURLcode result = CURLE_OK;
struct connectdata *conn = data->conn;
- struct POP3 *pop3 = data->req.p.pop3;
+ struct POP3 *pop3 = Curl_meta_get(data, CURL_META_POP3_EASY);
+ struct pop3_conn *pop3c = Curl_conn_meta_get(conn, CURL_META_POP3_CONN);
const char *command = NULL;
+ if(!pop3 || !pop3c)
+ return CURLE_FAILED_INIT;
+
/* Calculate the default command */
if(pop3->id[0] == '\0' || data->set.list_only) {
command = "LIST";
@@ -659,10 +766,9 @@ static CURLcode pop3_perform_command(struct Curl_easy *data)
/* Send the command */
if(pop3->id[0] != '\0')
- result = Curl_pp_sendf(data, &conn->proto.pop3c.pp, "%s %s",
- command, pop3->id);
+ result = Curl_pp_sendf(data, &pop3c->pp, "%s %s", command, pop3->id);
else
- result = Curl_pp_sendf(data, &conn->proto.pop3c.pp, "%s", command);
+ result = Curl_pp_sendf(data, &pop3c->pp, "%s", command);
if(!result) {
pop3_state(data, POP3_COMMAND);
@@ -681,9 +787,14 @@ static CURLcode pop3_perform_command(struct Curl_easy *data)
static CURLcode pop3_perform_quit(struct Curl_easy *data,
struct connectdata *conn)
{
- /* Send the QUIT command */
- CURLcode result = Curl_pp_sendf(data, &conn->proto.pop3c.pp, "%s", "QUIT");
+ struct pop3_conn *pop3c = Curl_conn_meta_get(conn, CURL_META_POP3_CONN);
+ CURLcode result;
+
+ if(!pop3c)
+ return CURLE_FAILED_INIT;
+ /* Send the QUIT command */
+ result = Curl_pp_sendf(data, &pop3c->pp, "%s", "QUIT");
if(!result)
pop3_state(data, POP3_QUIT);
@@ -697,11 +808,16 @@ static CURLcode pop3_state_servergreet_resp(struct Curl_easy *data,
{
CURLcode result = CURLE_OK;
struct connectdata *conn = data->conn;
- struct pop3_conn *pop3c = &conn->proto.pop3c;
- const char *line = Curl_dyn_ptr(&data->conn->proto.pop3c.pp.recvbuf);
- size_t len = data->conn->proto.pop3c.pp.nfinal;
+ struct pop3_conn *pop3c = Curl_conn_meta_get(conn, CURL_META_POP3_CONN);
+ const char *line;
+ size_t len;
(void)instate; /* no use for this yet */
+ if(!pop3c)
+ return CURLE_FAILED_INIT;
+
+ line = curlx_dyn_ptr(&pop3c->pp.recvbuf);
+ len = pop3c->pp.nfinal;
if(pop3code != '+') {
failf(data, "Got unexpected pop3-server response");
@@ -747,11 +863,16 @@ static CURLcode pop3_state_capa_resp(struct Curl_easy *data, int pop3code,
{
CURLcode result = CURLE_OK;
struct connectdata *conn = data->conn;
- struct pop3_conn *pop3c = &conn->proto.pop3c;
- const char *line = Curl_dyn_ptr(&data->conn->proto.pop3c.pp.recvbuf);
- size_t len = data->conn->proto.pop3c.pp.nfinal;
+ struct pop3_conn *pop3c = Curl_conn_meta_get(conn, CURL_META_POP3_CONN);
+ const char *line;
+ size_t len;
(void)instate; /* no use for this yet */
+ if(!pop3c)
+ return CURLE_FAILED_INIT;
+
+ line = curlx_dyn_ptr(&pop3c->pp.recvbuf);
+ len = pop3c->pp.nfinal;
/* Do we have a untagged continuation response? */
if(pop3code == '*') {
@@ -832,11 +953,15 @@ static CURLcode pop3_state_starttls_resp(struct Curl_easy *data,
int pop3code,
pop3state instate)
{
+ struct pop3_conn *pop3c = Curl_conn_meta_get(conn, CURL_META_POP3_CONN);
CURLcode result = CURLE_OK;
(void)instate; /* no use for this yet */
+ if(!pop3c)
+ return CURLE_FAILED_INIT;
+
/* Pipelining in response is forbidden. */
- if(data->conn->proto.pop3c.pp.overflow)
+ if(pop3c->pp.overflow)
return CURLE_WEIRD_SERVER_REPLY;
if(pop3code != '+') {
@@ -860,10 +985,12 @@ static CURLcode pop3_state_auth_resp(struct Curl_easy *data,
{
CURLcode result = CURLE_OK;
struct connectdata *conn = data->conn;
- struct pop3_conn *pop3c = &conn->proto.pop3c;
+ struct pop3_conn *pop3c = Curl_conn_meta_get(conn, CURL_META_POP3_CONN);
saslprogress progress;
(void)instate; /* no use for this yet */
+ if(!pop3c)
+ return CURLE_FAILED_INIT;
result = Curl_sasl_continue(&pop3c->sasl, data, pop3code, &progress);
if(!result)
@@ -919,15 +1046,19 @@ static CURLcode pop3_state_user_resp(struct Curl_easy *data, int pop3code,
{
CURLcode result = CURLE_OK;
struct connectdata *conn = data->conn;
+ struct pop3_conn *pop3c = Curl_conn_meta_get(conn, CURL_META_POP3_CONN);
(void)instate; /* no use for this yet */
+ if(!pop3c)
+ return CURLE_FAILED_INIT;
+
if(pop3code != '+') {
failf(data, "Access denied. %c", pop3code);
result = CURLE_LOGIN_DENIED;
}
else
/* Send the PASS command */
- result = Curl_pp_sendf(data, &conn->proto.pop3c.pp, "PASS %s",
+ result = Curl_pp_sendf(data, &pop3c->pp, "PASS %s",
conn->passwd ? conn->passwd : "");
if(!result)
pop3_state(data, POP3_PASS);
@@ -960,12 +1091,15 @@ static CURLcode pop3_state_command_resp(struct Curl_easy *data,
{
CURLcode result = CURLE_OK;
struct connectdata *conn = data->conn;
- struct POP3 *pop3 = data->req.p.pop3;
- struct pop3_conn *pop3c = &conn->proto.pop3c;
- struct pingpong *pp = &pop3c->pp;
+ struct POP3 *pop3 = Curl_meta_get(data, CURL_META_POP3_EASY);
+ struct pop3_conn *pop3c = Curl_conn_meta_get(conn, CURL_META_POP3_CONN);
+ struct pingpong *pp;
(void)instate; /* no use for this yet */
+ if(!pop3 || !pop3c)
+ return CURLE_FAILED_INIT;
+ pp = &pop3c->pp;
if(pop3code != '+') {
pop3_state(data, POP3_STOP);
return CURLE_WEIRD_SERVER_REPLY;
@@ -991,18 +1125,18 @@ static CURLcode pop3_state_command_resp(struct Curl_easy *data,
the body */
/* keep only the overflow */
- Curl_dyn_tail(&pp->recvbuf, pp->overflow);
+ curlx_dyn_tail(&pp->recvbuf, pp->overflow);
pp->nfinal = 0; /* done */
if(!data->req.no_body) {
- result = pop3_write(data, Curl_dyn_ptr(&pp->recvbuf),
- Curl_dyn_len(&pp->recvbuf), FALSE);
+ result = pop3_write(data, curlx_dyn_ptr(&pp->recvbuf),
+ curlx_dyn_len(&pp->recvbuf), FALSE);
if(result)
return result;
}
/* reset the buffer */
- Curl_dyn_reset(&pp->recvbuf);
+ curlx_dyn_reset(&pp->recvbuf);
pp->overflow = 0;
}
}
@@ -1018,13 +1152,17 @@ static CURLcode pop3_state_command_resp(struct Curl_easy *data,
static CURLcode pop3_statemachine(struct Curl_easy *data,
struct connectdata *conn)
{
+ struct pop3_conn *pop3c = Curl_conn_meta_get(conn, CURL_META_POP3_CONN);
CURLcode result = CURLE_OK;
int pop3code;
- struct pop3_conn *pop3c = &conn->proto.pop3c;
- struct pingpong *pp = &pop3c->pp;
+ struct pingpong *pp;
size_t nread = 0;
(void)data;
+ if(!pop3c)
+ return CURLE_FAILED_INIT;
+
+ pp = &pop3c->pp;
/* Busy upgrading the connection; right now all I/O is SSL/TLS, not POP3 */
upgrade_tls:
if(pop3c->state == POP3_UPGRADETLS) {
@@ -1105,8 +1243,10 @@ static CURLcode pop3_multi_statemach(struct Curl_easy *data, bool *done)
{
CURLcode result = CURLE_OK;
struct connectdata *conn = data->conn;
- struct pop3_conn *pop3c = &conn->proto.pop3c;
+ struct pop3_conn *pop3c = Curl_conn_meta_get(conn, CURL_META_POP3_CONN);
+ if(!pop3c)
+ return CURLE_FAILED_INIT;
result = Curl_pp_statemach(data, &pop3c->pp, FALSE, FALSE);
*done = (pop3c->state == POP3_STOP);
@@ -1118,7 +1258,10 @@ static CURLcode pop3_block_statemach(struct Curl_easy *data,
bool disconnecting)
{
CURLcode result = CURLE_OK;
- struct pop3_conn *pop3c = &conn->proto.pop3c;
+ struct pop3_conn *pop3c = Curl_conn_meta_get(conn, CURL_META_POP3_CONN);
+
+ if(!pop3c)
+ return CURLE_FAILED_INIT;
while(pop3c->state != POP3_STOP && !result)
result = Curl_pp_statemach(data, &pop3c->pp, TRUE, disconnecting);
@@ -1126,25 +1269,14 @@ static CURLcode pop3_block_statemach(struct Curl_easy *data,
return result;
}
-/* Allocate and initialize the POP3 struct for the current Curl_easy if
- required */
-static CURLcode pop3_init(struct Curl_easy *data)
-{
- CURLcode result = CURLE_OK;
- struct POP3 *pop3;
-
- pop3 = data->req.p.pop3 = calloc(1, sizeof(struct POP3));
- if(!pop3)
- result = CURLE_OUT_OF_MEMORY;
-
- return result;
-}
-
/* For the POP3 "protocol connect" and "doing" phases only */
static int pop3_getsock(struct Curl_easy *data,
struct connectdata *conn, curl_socket_t *socks)
{
- return Curl_pp_getsock(data, &conn->proto.pop3c.pp, socks);
+ struct pop3_conn *pop3c = Curl_conn_meta_get(conn, CURL_META_POP3_CONN);
+ if(pop3c)
+ return Curl_pp_getsock(data, &pop3c->pp, socks);
+ return GETSOCK_BLANK;
}
/***********************************************************************
@@ -1161,10 +1293,12 @@ static CURLcode pop3_connect(struct Curl_easy *data, bool *done)
{
CURLcode result = CURLE_OK;
struct connectdata *conn = data->conn;
- struct pop3_conn *pop3c = &conn->proto.pop3c;
- struct pingpong *pp = &pop3c->pp;
+ struct pop3_conn *pop3c = Curl_conn_meta_get(conn, CURL_META_POP3_CONN);
+ struct pingpong *pp = pop3c ? &pop3c->pp : NULL;
*done = FALSE; /* default to not done yet */
+ if(!pop3c)
+ return CURLE_FAILED_INIT;
/* We always support persistent connections in POP3 */
connkeep(conn, "POP3 default");
@@ -1204,7 +1338,7 @@ static CURLcode pop3_done(struct Curl_easy *data, CURLcode status,
bool premature)
{
CURLcode result = CURLE_OK;
- struct POP3 *pop3 = data->req.p.pop3;
+ struct POP3 *pop3 = Curl_meta_get(data, CURL_META_POP3_EASY);
(void)premature;
@@ -1238,7 +1372,10 @@ static CURLcode pop3_perform(struct Curl_easy *data, bool *connected,
{
/* This is POP3 and no proxy */
CURLcode result = CURLE_OK;
- struct POP3 *pop3 = data->req.p.pop3;
+ struct POP3 *pop3 = Curl_meta_get(data, CURL_META_POP3_EASY);
+
+ if(!pop3)
+ return CURLE_FAILED_INIT;
DEBUGF(infof(data, "DO phase starts"));
@@ -1303,9 +1440,12 @@ static CURLcode pop3_do(struct Curl_easy *data, bool *done)
static CURLcode pop3_disconnect(struct Curl_easy *data,
struct connectdata *conn, bool dead_connection)
{
- struct pop3_conn *pop3c = &conn->proto.pop3c;
+ struct pop3_conn *pop3c = Curl_conn_meta_get(conn, CURL_META_POP3_CONN);
(void)data;
+ if(!pop3c)
+ return CURLE_FAILED_INIT;
+
/* We cannot send quit unconditionally. If this connection is stale or
bad in any way, sending quit and waiting around here will make the
disconnect wait in vain and cause more problems than we need to. */
@@ -1386,12 +1526,44 @@ static CURLcode pop3_regular_transfer(struct Curl_easy *data,
return result;
}
+static void pop3_easy_dtor(void *key, size_t klen, void *entry)
+{
+ struct POP3 *pop3 = entry;
+ (void)key;
+ (void)klen;
+ DEBUGASSERT(pop3);
+ /* Cleanup our per-request based variables */
+ Curl_safefree(pop3->id);
+ Curl_safefree(pop3->custom);
+ free(pop3);
+}
+
+static void pop3_conn_dtor(void *key, size_t klen, void *entry)
+{
+ struct pop3_conn *pop3c = entry;
+ (void)key;
+ (void)klen;
+ DEBUGASSERT(pop3c);
+ Curl_pp_disconnect(&pop3c->pp);
+ Curl_safefree(pop3c->apoptimestamp);
+ free(pop3c);
+}
+
static CURLcode pop3_setup_connection(struct Curl_easy *data,
struct connectdata *conn)
{
- /* Initialise the POP3 layer */
- (void)conn;
- return pop3_init(data);
+ struct pop3_conn *pop3c;
+ struct POP3 *pop3 = calloc(1, sizeof(*pop3));
+ if(!pop3 ||
+ Curl_meta_set(data, CURL_META_POP3_EASY, pop3, pop3_easy_dtor))
+ return CURLE_OUT_OF_MEMORY;
+
+ pop3c = calloc(1, sizeof(*pop3c));
+ if(!pop3c ||
+ Curl_conn_meta_set(conn, CURL_META_POP3_CONN, pop3c, pop3_conn_dtor))
+ return CURLE_OUT_OF_MEMORY;
+
+ return CURLE_OK;
}
/***********************************************************************
@@ -1402,10 +1574,13 @@ static CURLcode pop3_setup_connection(struct Curl_easy *data,
*/
static CURLcode pop3_parse_url_options(struct connectdata *conn)
{
+ struct pop3_conn *pop3c = Curl_conn_meta_get(conn, CURL_META_POP3_CONN);
CURLcode result = CURLE_OK;
- struct pop3_conn *pop3c = &conn->proto.pop3c;
const char *ptr = conn->options;
+ if(!pop3c)
+ return CURLE_FAILED_INIT;
+
while(!result && ptr && *ptr) {
const char *key = ptr;
const char *value;
@@ -1460,9 +1635,11 @@ static CURLcode pop3_parse_url_options(struct connectdata *conn)
static CURLcode pop3_parse_url_path(struct Curl_easy *data)
{
/* The POP3 struct is already initialised in pop3_connect() */
- struct POP3 *pop3 = data->req.p.pop3;
+ struct POP3 *pop3 = Curl_meta_get(data, CURL_META_POP3_EASY);
const char *path = &data->state.up.path[1]; /* skip leading path */
+ if(!pop3)
+ return CURLE_FAILED_INIT;
/* URL decode the path for the message ID */
return Curl_urldecode(path, 0, &pop3->id, NULL, REJECT_CTRL);
}
@@ -1476,9 +1653,11 @@ static CURLcode pop3_parse_url_path(struct Curl_easy *data)
static CURLcode pop3_parse_custom_request(struct Curl_easy *data)
{
CURLcode result = CURLE_OK;
- struct POP3 *pop3 = data->req.p.pop3;
+ struct POP3 *pop3 = Curl_meta_get(data, CURL_META_POP3_EASY);
const char *custom = data->set.str[STRING_CUSTOMREQUEST];
+ if(!pop3)
+ return CURLE_FAILED_INIT;
/* URL decode the custom request */
if(custom)
result = Curl_urldecode(custom, 0, &pop3->custom, NULL, REJECT_CTRL);
@@ -1500,12 +1679,15 @@ static CURLcode pop3_write(struct Curl_easy *data, const char *str,
CURLcode result = CURLE_OK;
struct SingleRequest *k = &data->req;
struct connectdata *conn = data->conn;
- struct pop3_conn *pop3c = &conn->proto.pop3c;
+ struct pop3_conn *pop3c = Curl_conn_meta_get(conn, CURL_META_POP3_CONN);
bool strip_dot = FALSE;
size_t last = 0;
size_t i;
(void)is_eos;
+ if(!pop3c)
+ return CURLE_FAILED_INIT;
+
/* Search through the buffer looking for the end-of-body marker which is
5 bytes (0d 0a 2e 0d 0a). Note that a line starting with a dot matches
the eob so the server will have prefixed it with an extra dot which we
diff --git a/libs/libcurl/src/pop3.h b/libs/libcurl/src/pop3.h
index ce0d5f6dc2..be57486d48 100644
--- a/libs/libcurl/src/pop3.h
+++ b/libs/libcurl/src/pop3.h
@@ -24,70 +24,7 @@
*
***************************************************************************/
-#include "pingpong.h"
-#include "curl_sasl.h"
-
-/****************************************************************************
- * POP3 unique setup
- ***************************************************************************/
-typedef enum {
- POP3_STOP, /* do nothing state, stops the state machine */
- POP3_SERVERGREET, /* waiting for the initial greeting immediately after
- a connect */
- POP3_CAPA,
- POP3_STARTTLS,
- POP3_UPGRADETLS, /* asynchronously upgrade the connection to SSL/TLS
- (multi mode only) */
- POP3_AUTH,
- POP3_APOP,
- POP3_USER,
- POP3_PASS,
- POP3_COMMAND,
- POP3_QUIT,
- POP3_LAST /* never used */
-} pop3state;
-
-/* This POP3 struct is used in the Curl_easy. All POP3 data that is
- connection-oriented must be in pop3_conn to properly deal with the fact that
- perhaps the Curl_easy is changed between the times the connection is
- used. */
-struct POP3 {
- curl_pp_transfer transfer;
- char *id; /* Message ID */
- char *custom; /* Custom Request */
-};
-
-/* pop3_conn is used for struct connection-oriented data in the connectdata
- struct */
-struct pop3_conn {
- struct pingpong pp;
- pop3state state; /* Always use pop3.c:state() to change state! */
- size_t eob; /* Number of bytes of the EOB (End Of Body) that
- have been received so far */
- size_t strip; /* Number of bytes from the start to ignore as
- non-body */
- struct SASL sasl; /* SASL-related storage */
- char *apoptimestamp; /* APOP timestamp from the server greeting */
- unsigned char authtypes; /* Accepted authentication types */
- unsigned char preftype; /* Preferred authentication type */
- BIT(ssldone); /* Is connect() over SSL done? */
- BIT(tls_supported); /* StartTLS capability supported by server */
-};
-
extern const struct Curl_handler Curl_handler_pop3;
extern const struct Curl_handler Curl_handler_pop3s;
-/* Authentication type flags */
-#define POP3_TYPE_CLEARTEXT (1 << 0)
-#define POP3_TYPE_APOP (1 << 1)
-#define POP3_TYPE_SASL (1 << 2)
-
-/* Authentication type values */
-#define POP3_TYPE_NONE 0
-#define POP3_TYPE_ANY (POP3_TYPE_CLEARTEXT|POP3_TYPE_APOP|POP3_TYPE_SASL)
-
-/* This is the 5-bytes End-Of-Body marker for POP3 */
-#define POP3_EOB "\x0d\x0a\x2e\x0d\x0a"
-#define POP3_EOB_LEN 5
-
#endif /* HEADER_CURL_POP3_H */
diff --git a/libs/libcurl/src/progress.c b/libs/libcurl/src/progress.c
index 8556cd2221..b8887786d8 100644
--- a/libs/libcurl/src/progress.c
+++ b/libs/libcurl/src/progress.c
@@ -28,7 +28,7 @@
#include "sendf.h"
#include "multiif.h"
#include "progress.h"
-#include "timeval.h"
+#include "curlx/timeval.h"
#include "curl_printf.h"
/* check rate limits within this many recent milliseconds, at minimum. */
@@ -136,8 +136,7 @@ int Curl_pgrsDone(struct Curl_easy *data)
if(rc)
return rc;
- if(!(data->progress.flags & PGRS_HIDE) &&
- !data->progress.callback)
+ if(!data->progress.hide && !data->progress.callback)
/* only output if we do not use a progress callback and we are not
* hidden */
fprintf(data->set.err, "\n");
@@ -181,7 +180,7 @@ void Curl_pgrsTimeWas(struct Curl_easy *data, timerid timer,
case TIMER_POSTQUEUE:
/* Queue time is accumulative from all involved redirects */
data->progress.t_postqueue +=
- Curl_timediff_us(timestamp, data->progress.t_startqueue);
+ curlx_timediff_us(timestamp, data->progress.t_startqueue);
break;
case TIMER_STARTACCEPT:
data->progress.t_acceptdata = timestamp;
@@ -217,13 +216,13 @@ void Curl_pgrsTimeWas(struct Curl_easy *data, timerid timer,
delta = &data->progress.t_posttransfer;
break;
case TIMER_REDIRECT:
- data->progress.t_redirect = Curl_timediff_us(timestamp,
+ data->progress.t_redirect = curlx_timediff_us(timestamp,
data->progress.start);
data->progress.t_startqueue = timestamp;
break;
}
if(delta) {
- timediff_t us = Curl_timediff_us(timestamp, data->progress.t_startsingle);
+ timediff_t us = curlx_timediff_us(timestamp, data->progress.t_startsingle);
if(us < 1)
us = 1; /* make sure at least one microsecond passed */
*delta += us;
@@ -239,7 +238,7 @@ void Curl_pgrsTimeWas(struct Curl_easy *data, timerid timer,
*/
struct curltime Curl_pgrsTime(struct Curl_easy *data, timerid timer)
{
- struct curltime now = Curl_now();
+ struct curltime now = curlx_now();
Curl_pgrsTimeWas(data, timer, now);
return now;
@@ -247,18 +246,20 @@ struct curltime Curl_pgrsTime(struct Curl_easy *data, timerid timer)
void Curl_pgrsStartNow(struct Curl_easy *data)
{
- data->progress.speeder_c = 0; /* reset the progress meter display */
- data->progress.start = Curl_now();
- data->progress.is_t_startransfer_set = FALSE;
- data->progress.ul.limit.start = data->progress.start;
- data->progress.dl.limit.start = data->progress.start;
- data->progress.ul.limit.start_size = 0;
- data->progress.dl.limit.start_size = 0;
- data->progress.dl.cur_size = 0;
- data->progress.ul.cur_size = 0;
- /* clear all bits except HIDE and HEADERS_OUT */
- data->progress.flags &= PGRS_HIDE|PGRS_HEADERS_OUT;
- Curl_ratelimit(data, data->progress.start);
+ struct Progress *p = &data->progress;
+ p->speeder_c = 0; /* reset the progress meter display */
+ p->start = curlx_now();
+ p->is_t_startransfer_set = FALSE;
+ p->ul.limit.start = p->start;
+ p->dl.limit.start = p->start;
+ p->ul.limit.start_size = 0;
+ p->dl.limit.start_size = 0;
+ p->dl.cur_size = 0;
+ p->ul.cur_size = 0;
+ /* the sizes are unknown at start */
+ p->dl_size_known = FALSE;
+ p->ul_size_known = FALSE;
+ Curl_ratelimit(data, p->start);
}
/*
@@ -308,7 +309,7 @@ timediff_t Curl_pgrsLimitWaitTime(struct pgrs_dir *d,
* 'actual' is the time in milliseconds it took to actually download the
* last 'size' bytes.
*/
- actual = Curl_timediff_ceil(now, d->limit.start);
+ actual = curlx_timediff_ceil(now, d->limit.start);
if(actual < minimum) {
/* if it downloaded the data faster than the limit, make it wait the
difference */
@@ -334,14 +335,14 @@ void Curl_ratelimit(struct Curl_easy *data, struct curltime now)
{
/* do not set a new stamp unless the time since last update is long enough */
if(data->set.max_recv_speed) {
- if(Curl_timediff(now, data->progress.dl.limit.start) >=
+ if(curlx_timediff(now, data->progress.dl.limit.start) >=
MIN_RATE_LIMIT_PERIOD) {
data->progress.dl.limit.start = now;
data->progress.dl.limit.start_size = data->progress.dl.cur_size;
}
}
if(data->set.max_send_speed) {
- if(Curl_timediff(now, data->progress.ul.limit.start) >=
+ if(curlx_timediff(now, data->progress.ul.limit.start) >=
MIN_RATE_LIMIT_PERIOD) {
data->progress.ul.limit.start = now;
data->progress.ul.limit.start_size = data->progress.ul.cur_size;
@@ -361,11 +362,11 @@ void Curl_pgrsSetDownloadSize(struct Curl_easy *data, curl_off_t size)
{
if(size >= 0) {
data->progress.dl.total_size = size;
- data->progress.flags |= PGRS_DL_SIZE_KNOWN;
+ data->progress.dl_size_known = TRUE;
}
else {
data->progress.dl.total_size = 0;
- data->progress.flags &= ~PGRS_DL_SIZE_KNOWN;
+ data->progress.dl_size_known = FALSE;
}
}
@@ -373,11 +374,11 @@ void Curl_pgrsSetUploadSize(struct Curl_easy *data, curl_off_t size)
{
if(size >= 0) {
data->progress.ul.total_size = size;
- data->progress.flags |= PGRS_UL_SIZE_KNOWN;
+ data->progress.ul_size_known = TRUE;
}
else {
data->progress.ul.total_size = 0;
- data->progress.flags &= ~PGRS_UL_SIZE_KNOWN;
+ data->progress.ul_size_known = FALSE;
}
}
@@ -407,7 +408,7 @@ static bool progress_calc(struct Curl_easy *data, struct curltime now)
struct Progress * const p = &data->progress;
/* The time spent so far (from the start) in microseconds */
- p->timespent = Curl_timediff_us(now, p->start);
+ p->timespent = curlx_timediff_us(now, p->start);
p->dl.speed = trspeed(p->dl.cur_size, p->timespent);
p->ul.speed = trspeed(p->ul.cur_size, p->timespent);
@@ -447,7 +448,7 @@ static bool progress_calc(struct Curl_easy *data, struct curltime now)
checkindex = (p->speeder_c >= CURR_TIME) ? p->speeder_c%CURR_TIME : 0;
/* Figure out the exact time for the time span */
- span_ms = Curl_timediff(now, p->speeder_time[checkindex]);
+ span_ms = curlx_timediff(now, p->speeder_time[checkindex]);
if(0 == span_ms)
span_ms = 1; /* at least one millisecond MUST have passed */
@@ -509,12 +510,13 @@ static void progress_meter(struct Curl_easy *data)
struct pgrs_estimate total_estm;
curl_off_t total_cur_size;
curl_off_t total_expected_size;
+ curl_off_t dl_size;
char time_left[10];
char time_total[10];
char time_spent[10];
curl_off_t cur_secs = (curl_off_t)p->timespent/1000000; /* seconds */
- if(!(p->flags & PGRS_HEADERS_OUT)) {
+ if(!p->headers_out) {
if(data->state.resume_from) {
fprintf(data->set.err,
"** Resuming transfer from byte position %" FMT_OFF_T "\n",
@@ -525,12 +527,12 @@ static void progress_meter(struct Curl_easy *data)
"Time Time Time Current\n"
" Dload Upload "
"Total Spent Left Speed\n");
- p->flags |= PGRS_HEADERS_OUT; /* headers are shown */
+ p->headers_out = TRUE; /* headers are shown */
}
/* Figure out the estimated time of arrival for upload and download */
- pgrs_estimates(&p->ul, (p->flags & PGRS_UL_SIZE_KNOWN), &ul_estm);
- pgrs_estimates(&p->dl, (p->flags & PGRS_DL_SIZE_KNOWN), &dl_estm);
+ pgrs_estimates(&p->ul, (bool)p->ul_size_known, &ul_estm);
+ pgrs_estimates(&p->dl, (bool)p->dl_size_known, &dl_estm);
/* Since both happen at the same time, total expected duration is max. */
total_estm.secs = CURLMAX(ul_estm.secs, dl_estm.secs);
@@ -541,8 +543,16 @@ static void progress_meter(struct Curl_easy *data)
/* Get the total amount of data expected to get transferred */
total_expected_size =
- ((p->flags & PGRS_UL_SIZE_KNOWN) ? p->ul.total_size : p->ul.cur_size) +
- ((p->flags & PGRS_DL_SIZE_KNOWN) ? p->dl.total_size : p->dl.cur_size);
+ p->ul_size_known ? p->ul.total_size : p->ul.cur_size;
+
+ dl_size =
+ p->dl_size_known ? p->dl.total_size : p->dl.cur_size;
+
+ /* integer overflow check */
+ if((CURL_OFF_T_MAX - total_expected_size) < dl_size)
+ total_expected_size = CURL_OFF_T_MAX; /* capped */
+ else
+ total_expected_size += dl_size;
/* We have transferred this much so far */
total_cur_size = p->dl.cur_size + p->ul.cur_size;
@@ -584,7 +594,7 @@ static void progress_meter(struct Curl_easy *data)
*/
static int pgrsupdate(struct Curl_easy *data, bool showprogress)
{
- if(!(data->progress.flags & PGRS_HIDE)) {
+ if(!data->progress.hide) {
if(data->set.fxferinfo) {
int result;
/* There is a callback set, call that */
@@ -627,7 +637,7 @@ static int pgrsupdate(struct Curl_easy *data, bool showprogress)
int Curl_pgrsUpdate(struct Curl_easy *data)
{
- struct curltime now = Curl_now(); /* what time is it */
+ struct curltime now = curlx_now(); /* what time is it */
bool showprogress = progress_calc(data, now);
return pgrsupdate(data, showprogress);
}
@@ -637,6 +647,6 @@ int Curl_pgrsUpdate(struct Curl_easy *data)
*/
void Curl_pgrsUpdate_nometer(struct Curl_easy *data)
{
- struct curltime now = Curl_now(); /* what time is it */
+ struct curltime now = curlx_now(); /* what time is it */
(void)progress_calc(data, now);
}
diff --git a/libs/libcurl/src/progress.h b/libs/libcurl/src/progress.h
index 5386e1bd3f..baad4ee14c 100644
--- a/libs/libcurl/src/progress.h
+++ b/libs/libcurl/src/progress.h
@@ -24,7 +24,7 @@
*
***************************************************************************/
-#include "timeval.h"
+#include "curlx/timeval.h"
typedef enum {
@@ -71,9 +71,4 @@ void Curl_pgrsTimeWas(struct Curl_easy *data, timerid timer,
void Curl_pgrsEarlyData(struct Curl_easy *data, curl_off_t sent);
-#define PGRS_HIDE (1<<4)
-#define PGRS_UL_SIZE_KNOWN (1<<5)
-#define PGRS_DL_SIZE_KNOWN (1<<6)
-#define PGRS_HEADERS_OUT (1<<7) /* set when the headers have been written */
-
#endif /* HEADER_CURL_PROGRESS_H */
diff --git a/libs/libcurl/src/psl.c b/libs/libcurl/src/psl.c
index 605abe61cc..22703ff234 100644
--- a/libs/libcurl/src/psl.c
+++ b/libs/libcurl/src/psl.c
@@ -48,7 +48,7 @@ void Curl_psl_destroy(struct PslCache *pslcache)
static time_t now_seconds(void)
{
- struct curltime now = Curl_now();
+ struct curltime now = curlx_now();
return now.tv_sec;
}
diff --git a/libs/libcurl/src/psl.h b/libs/libcurl/src/psl.h
index cce64ea740..9aa2ea2a04 100644
--- a/libs/libcurl/src/psl.h
+++ b/libs/libcurl/src/psl.h
@@ -34,7 +34,7 @@ struct Curl_easy;
struct PslCache {
const psl_ctx_t *psl; /* The PSL. */
time_t expires; /* Time this PSL life expires. */
- bool dynamic; /* PSL should be released when no longer needed. */
+ BIT(dynamic); /* PSL should be released when no longer needed. */
};
const psl_ctx_t *Curl_psl_use(struct Curl_easy *easy);
diff --git a/libs/libcurl/src/rand.c b/libs/libcurl/src/rand.c
index 00ba581689..be106e6ad8 100644
--- a/libs/libcurl/src/rand.c
+++ b/libs/libcurl/src/rand.c
@@ -37,7 +37,7 @@
#include "urldata.h"
#include "vtls/vtls.h"
#include "sendf.h"
-#include "timeval.h"
+#include "curlx/timeval.h"
#include "rand.h"
#include "escape.h"
@@ -130,7 +130,7 @@ static CURLcode weak_random(struct Curl_easy *data,
static bool seeded = FALSE;
unsigned int rnd;
if(!seeded) {
- struct curltime now = Curl_now();
+ struct curltime now = curlx_now();
randseed += (unsigned int)now.tv_usec + (unsigned int)now.tv_sec;
randseed = randseed * 1103515245 + 12345;
randseed = randseed * 1103515245 + 12345;
@@ -191,12 +191,11 @@ static CURLcode randit(struct Curl_easy *data, unsigned int *rnd,
* Curl_rand() stores 'num' number of random unsigned characters in the buffer
* 'rnd' points to.
*
- * If libcurl is built without TLS support or with a TLS backend that lacks a
- * proper random API (Rustls or mbedTLS), this function will use "weak"
- * random.
+ * If libcurl is built without TLS support or arc4random, this function will
+ * use "weak" random.
*
- * When built *with* TLS support and a backend that offers strong random, it
- * will return error if it cannot provide strong random values.
+ * When built *with* TLS support, it will return error if it cannot provide
+ * strong random values.
*
* NOTE: 'data' may be passed in as NULL when coming from external API without
* easy handle!
diff --git a/libs/libcurl/src/rename.c b/libs/libcurl/src/rename.c
index 89eab2e057..f4f5ac13b0 100644
--- a/libs/libcurl/src/rename.c
+++ b/libs/libcurl/src/rename.c
@@ -29,8 +29,8 @@
#if (!defined(CURL_DISABLE_HTTP) || !defined(CURL_DISABLE_COOKIES)) || \
!defined(CURL_DISABLE_ALTSVC)
-#include "curl_multibyte.h"
-#include "timeval.h"
+#include "curlx/multibyte.h"
+#include "curlx/timeval.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
@@ -45,7 +45,7 @@ int Curl_rename(const char *oldpath, const char *newpath)
MoveFileEx() will overwrite and is usually atomic, however it fails
when there are open handles to the file. */
const int max_wait_ms = 1000;
- struct curltime start = Curl_now();
+ struct curltime start = curlx_now();
TCHAR *tchar_oldpath = curlx_convert_UTF8_to_tchar(oldpath);
TCHAR *tchar_newpath = curlx_convert_UTF8_to_tchar(newpath);
for(;;) {
@@ -55,7 +55,7 @@ int Curl_rename(const char *oldpath, const char *newpath)
curlx_unicodefree(tchar_newpath);
break;
}
- diff = Curl_timediff(Curl_now(), start);
+ diff = curlx_timediff(curlx_now(), start);
if(diff < 0 || diff > max_wait_ms) {
curlx_unicodefree(tchar_oldpath);
curlx_unicodefree(tchar_newpath);
diff --git a/libs/libcurl/src/request.c b/libs/libcurl/src/request.c
index 2a6239eb41..9b11fa2aec 100644
--- a/libs/libcurl/src/request.c
+++ b/libs/libcurl/src/request.c
@@ -26,7 +26,7 @@
#include "urldata.h"
#include "cfilters.h"
-#include "dynbuf.h"
+#include "curlx/dynbuf.h"
#include "doh.h"
#include "multiif.h"
#include "progress.h"
@@ -34,7 +34,7 @@
#include "sendf.h"
#include "transfer.h"
#include "url.h"
-#include "strparse.h"
+#include "curlx/strparse.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
@@ -95,7 +95,7 @@ CURLcode Curl_req_soft_reset(struct SingleRequest *req,
CURLcode Curl_req_start(struct SingleRequest *req,
struct Curl_easy *data)
{
- req->start = Curl_now();
+ req->start = curlx_now();
return Curl_req_soft_reset(req, data);
}
@@ -118,9 +118,6 @@ void Curl_req_hard_reset(struct SingleRequest *req, struct Curl_easy *data)
{
struct curltime t0 = {0, 0};
- /* This is a bit ugly. `req->p` is a union and we assume we can
- * free this safely without leaks. */
- Curl_safefree(req->p.ftp);
Curl_safefree(req->newurl);
Curl_client_reset(data);
if(req->sendbuf_init)
@@ -171,17 +168,10 @@ void Curl_req_hard_reset(struct SingleRequest *req, struct Curl_easy *data)
void Curl_req_free(struct SingleRequest *req, struct Curl_easy *data)
{
- /* This is a bit ugly. `req->p` is a union and we assume we can
- * free this safely without leaks. */
- Curl_safefree(req->p.ftp);
Curl_safefree(req->newurl);
if(req->sendbuf_init)
Curl_bufq_free(&req->sendbuf);
Curl_client_cleanup(data);
-
-#ifndef CURL_DISABLE_DOH
- Curl_doh_cleanup(data);
-#endif
}
static CURLcode xfer_send(struct Curl_easy *data,
@@ -202,7 +192,7 @@ static CURLcode xfer_send(struct Curl_easy *data,
const char *p = getenv("CURL_SMALLREQSEND");
if(p) {
curl_off_t body_small;
- if(!Curl_str_number(&p, &body_small, body_len))
+ if(!curlx_str_number(&p, &body_small, body_len))
blen = hds_len + (size_t)body_small;
}
}
@@ -391,8 +381,8 @@ CURLcode Curl_req_send(struct Curl_easy *data, struct dynbuf *req,
return CURLE_FAILED_INIT;
data->req.httpversion_sent = httpversion;
- buf = Curl_dyn_ptr(req);
- blen = Curl_dyn_len(req);
+ buf = curlx_dyn_ptr(req);
+ blen = curlx_dyn_len(req);
if(!Curl_creader_total_length(data)) {
/* Request without body. Try to send directly from the buf given. */
data->req.eos_read = TRUE;
diff --git a/libs/libcurl/src/request.h b/libs/libcurl/src/request.h
index f0c8edc006..8e56f2d246 100644
--- a/libs/libcurl/src/request.h
+++ b/libs/libcurl/src/request.h
@@ -32,9 +32,6 @@
/* forward declarations */
struct UserDefined;
-#ifndef CURL_DISABLE_DOH
-struct doh_probes;
-#endif
enum expect100 {
EXP100_SEND_DATA, /* enough waiting, just send the body now */
@@ -102,24 +99,6 @@ struct SingleRequest {
char *newurl; /* Set to the new URL to use when a redirect or a retry is
wanted */
- /* Allocated protocol-specific data. Each protocol handler makes sure this
- points to data it needs. */
- union {
- struct FILEPROTO *file;
- struct FTP *ftp;
- struct IMAP *imap;
- struct ldapreqinfo *ldap;
- struct MQTT *mqtt;
- struct POP3 *pop3;
- struct RTSP *rtsp;
- struct smb_request *smb;
- struct SMTP *smtp;
- struct SSHPROTO *ssh;
- struct TELNET *telnet;
- } p;
-#ifndef CURL_DISABLE_DOH
- struct doh_probes *doh; /* DoH specific data for this request */
-#endif
#ifndef CURL_DISABLE_COOKIES
unsigned char setcookies;
#endif
diff --git a/libs/libcurl/src/rtsp.c b/libs/libcurl/src/rtsp.c
index d625c539c3..9e3169accc 100644
--- a/libs/libcurl/src/rtsp.c
+++ b/libs/libcurl/src/rtsp.c
@@ -40,12 +40,42 @@
#include "connect.h"
#include "cfilters.h"
#include "strdup.h"
-#include "strparse.h"
+#include "curlx/strparse.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h"
#include "memdebug.h"
+
+/* meta key for storing protocol meta at easy handle */
+#define CURL_META_RTSP_EASY "meta:proto:rtsp:easy"
+/* meta key for storing protocol meta at connection */
+#define CURL_META_RTSP_CONN "meta:proto:rtsp:conn"
+
+typedef enum {
+ RTP_PARSE_SKIP,
+ RTP_PARSE_CHANNEL,
+ RTP_PARSE_LEN,
+ RTP_PARSE_DATA
+} rtp_parse_st;
+
+/* RTSP Connection data
+ * Currently, only used for tracking incomplete RTP data reads */
+struct rtsp_conn {
+ struct dynbuf buf;
+ int rtp_channel;
+ size_t rtp_len;
+ rtp_parse_st state;
+ BIT(in_header);
+};
+
+/* RTSP transfer data */
+struct RTSP {
+ long CSeq_sent; /* CSeq of this request */
+ long CSeq_recv; /* CSeq received */
+};
+
+
#define RTP_PKT_LENGTH(p) ((((unsigned int)((unsigned char)((p)[2]))) << 8) | \
((unsigned int)((unsigned char)((p)[3]))))
@@ -53,8 +83,6 @@
static CURLcode rtsp_do(struct Curl_easy *data, bool *done);
static CURLcode rtsp_done(struct Curl_easy *data, CURLcode, bool premature);
static CURLcode rtsp_connect(struct Curl_easy *data, bool *done);
-static CURLcode rtsp_disconnect(struct Curl_easy *data,
- struct connectdata *conn, bool dead);
static int rtsp_getsock_do(struct Curl_easy *data,
struct connectdata *conn, curl_socket_t *socks);
@@ -113,7 +141,7 @@ const struct Curl_handler Curl_handler_rtsp = {
rtsp_getsock_do, /* doing_getsock */
ZERO_NULL, /* domore_getsock */
ZERO_NULL, /* perform_getsock */
- rtsp_disconnect, /* disconnect */
+ ZERO_NULL, /* disconnect */
rtsp_rtp_write_resp, /* write_resp */
ZERO_NULL, /* write_resp_hd */
rtsp_conncheck, /* connection_check */
@@ -127,20 +155,39 @@ const struct Curl_handler Curl_handler_rtsp = {
#define MAX_RTP_BUFFERSIZE 1000000 /* arbitrary */
+static void rtsp_easy_dtor(void *key, size_t klen, void *entry)
+{
+ struct RTSP *rtsp = entry;
+ (void)key;
+ (void)klen;
+ free(rtsp);
+}
+
+static void rtsp_conn_dtor(void *key, size_t klen, void *entry)
+{
+ struct rtsp_conn *rtspc = entry;
+ (void)key;
+ (void)klen;
+ curlx_dyn_free(&rtspc->buf);
+ free(rtspc);
+}
+
static CURLcode rtsp_setup_connection(struct Curl_easy *data,
struct connectdata *conn)
{
- struct rtsp_conn *rtspc = &conn->proto.rtspc;
+ struct rtsp_conn *rtspc;
struct RTSP *rtsp;
- (void)conn;
- if(!rtspc->initialised) {
- Curl_dyn_init(&rtspc->buf, MAX_RTP_BUFFERSIZE);
- rtspc->initialised = TRUE;
- }
+ rtspc = calloc(1, sizeof(*rtspc));
+ if(!rtspc)
+ return CURLE_OUT_OF_MEMORY;
+ curlx_dyn_init(&rtspc->buf, MAX_RTP_BUFFERSIZE);
+ if(Curl_conn_meta_set(conn, CURL_META_RTSP_CONN, rtspc, rtsp_conn_dtor))
+ return CURLE_OUT_OF_MEMORY;
- data->req.p.rtsp = rtsp = calloc(1, sizeof(struct RTSP));
- if(!rtsp)
+ rtsp = calloc(1, sizeof(struct RTSP));
+ if(!rtsp ||
+ Curl_meta_set(data, CURL_META_RTSP_EASY, rtsp, rtsp_easy_dtor))
return CURLE_OUT_OF_MEMORY;
return CURLE_OK;
@@ -169,8 +216,13 @@ static unsigned int rtsp_conncheck(struct Curl_easy *data,
static CURLcode rtsp_connect(struct Curl_easy *data, bool *done)
{
+ struct rtsp_conn *rtspc =
+ Curl_conn_meta_get(data->conn, CURL_META_RTSP_CONN);
CURLcode httpStatus;
+ if(!rtspc)
+ return CURLE_FAILED_INIT;
+
httpStatus = Curl_http_connect(data, done);
/* Initialize the CSeq if not already done */
@@ -179,38 +231,29 @@ static CURLcode rtsp_connect(struct Curl_easy *data, bool *done)
if(data->state.rtsp_next_server_CSeq == 0)
data->state.rtsp_next_server_CSeq = 1;
- data->conn->proto.rtspc.rtp_channel = -1;
+ rtspc->rtp_channel = -1;
return httpStatus;
}
-static CURLcode rtsp_disconnect(struct Curl_easy *data,
- struct connectdata *conn, bool dead)
-{
- struct rtsp_conn *rtspc = &conn->proto.rtspc;
- (void) dead;
- (void) data;
- if(rtspc->initialised) {
- Curl_dyn_free(&conn->proto.rtspc.buf);
- rtspc->initialised = FALSE;
- }
- return CURLE_OK;
-}
-
-
static CURLcode rtsp_done(struct Curl_easy *data,
CURLcode status, bool premature)
{
- struct RTSP *rtsp = data->req.p.rtsp;
+ struct rtsp_conn *rtspc =
+ Curl_conn_meta_get(data->conn, CURL_META_RTSP_CONN);
+ struct RTSP *rtsp = Curl_meta_get(data, CURL_META_RTSP_EASY);
CURLcode httpStatus;
+ if(!rtspc || !rtsp)
+ return CURLE_FAILED_INIT;
+
/* Bypass HTTP empty-reply checks on receive */
if(data->set.rtspreq == RTSPREQ_RECEIVE)
premature = TRUE;
httpStatus = Curl_http_done(data, status, premature);
- if(rtsp && !status && !httpStatus) {
+ if(!status && !httpStatus) {
/* Check the sequence numbers */
long CSeq_sent = rtsp->CSeq_sent;
long CSeq_recv = rtsp->CSeq_recv;
@@ -220,8 +263,7 @@ static CURLcode rtsp_done(struct Curl_easy *data,
CSeq_sent, CSeq_recv);
return CURLE_RTSP_CSEQ_ERROR;
}
- if(data->set.rtspreq == RTSPREQ_RECEIVE &&
- (data->conn->proto.rtspc.rtp_channel == -1)) {
+ if(data->set.rtspreq == RTSPREQ_RECEIVE && (rtspc->rtp_channel == -1)) {
infof(data, "Got an RTP Receive with a CSeq of %ld", CSeq_recv);
}
if(data->set.rtspreq == RTSPREQ_RECEIVE &&
@@ -239,7 +281,7 @@ static CURLcode rtsp_do(struct Curl_easy *data, bool *done)
struct connectdata *conn = data->conn;
CURLcode result = CURLE_OK;
Curl_RtspReq rtspreq = data->set.rtspreq;
- struct RTSP *rtsp = data->req.p.rtsp;
+ struct RTSP *rtsp = Curl_meta_get(data, CURL_META_RTSP_EASY);
struct dynbuf req_buffer;
unsigned char httpversion = 11; /* RTSP is close to HTTP/1.1, sort of... */
@@ -256,8 +298,11 @@ static CURLcode rtsp_do(struct Curl_easy *data, bool *done)
const char *p_userpwd = NULL;
*done = TRUE;
+ if(!rtsp)
+ return CURLE_FAILED_INIT;
+
/* Initialize a dynamic send buffer */
- Curl_dyn_init(&req_buffer, DYN_RTSP_REQ_HEADER);
+ curlx_dyn_init(&req_buffer, DYN_RTSP_REQ_HEADER);
rtsp->CSeq_sent = data->state.rtsp_next_client_CSeq;
rtsp->CSeq_recv = 0;
@@ -456,10 +501,10 @@ static CURLcode rtsp_do(struct Curl_easy *data, bool *done)
}
result =
- Curl_dyn_addf(&req_buffer,
- "%s %s RTSP/1.0\r\n" /* Request Stream-URI RTSP/1.0 */
- "CSeq: %ld\r\n", /* CSeq */
- p_request, p_stream_uri, rtsp->CSeq_sent);
+ curlx_dyn_addf(&req_buffer,
+ "%s %s RTSP/1.0\r\n" /* Request Stream-URI RTSP/1.0 */
+ "CSeq: %ld\r\n", /* CSeq */
+ p_request, p_stream_uri, rtsp->CSeq_sent);
if(result)
goto out;
@@ -468,7 +513,7 @@ static CURLcode rtsp_do(struct Curl_easy *data, bool *done)
* to make comparison easier
*/
if(p_session_id) {
- result = Curl_dyn_addf(&req_buffer, "Session: %s\r\n", p_session_id);
+ result = curlx_dyn_addf(&req_buffer, "Session: %s\r\n", p_session_id);
if(result)
goto out;
}
@@ -476,24 +521,24 @@ static CURLcode rtsp_do(struct Curl_easy *data, bool *done)
/*
* Shared HTTP-like options
*/
- result = Curl_dyn_addf(&req_buffer,
- "%s" /* transport */
- "%s" /* accept */
- "%s" /* accept-encoding */
- "%s" /* range */
- "%s" /* referrer */
- "%s" /* user-agent */
- "%s" /* proxyuserpwd */
- "%s" /* userpwd */
- ,
- p_transport ? p_transport : "",
- p_accept ? p_accept : "",
- p_accept_encoding ? p_accept_encoding : "",
- p_range ? p_range : "",
- p_referrer ? p_referrer : "",
- p_uagent ? p_uagent : "",
- p_proxyuserpwd ? p_proxyuserpwd : "",
- p_userpwd ? p_userpwd : "");
+ result = curlx_dyn_addf(&req_buffer,
+ "%s" /* transport */
+ "%s" /* accept */
+ "%s" /* accept-encoding */
+ "%s" /* range */
+ "%s" /* referrer */
+ "%s" /* user-agent */
+ "%s" /* proxyuserpwd */
+ "%s" /* userpwd */
+ ,
+ p_transport ? p_transport : "",
+ p_accept ? p_accept : "",
+ p_accept_encoding ? p_accept_encoding : "",
+ p_range ? p_range : "",
+ p_referrer ? p_referrer : "",
+ p_uagent ? p_uagent : "",
+ p_proxyuserpwd ? p_proxyuserpwd : "",
+ p_userpwd ? p_userpwd : "");
/*
* Free userpwd now --- cannot reuse this for Negotiate and possibly NTLM
@@ -549,8 +594,8 @@ static CURLcode rtsp_do(struct Curl_easy *data, bool *done)
* actually set a custom Content-Length in the headers */
if(!Curl_checkheaders(data, STRCONST("Content-Length"))) {
result =
- Curl_dyn_addf(&req_buffer, "Content-Length: %" FMT_OFF_T"\r\n",
- req_clen);
+ curlx_dyn_addf(&req_buffer, "Content-Length: %" FMT_OFF_T"\r\n",
+ req_clen);
if(result)
goto out;
}
@@ -558,9 +603,9 @@ static CURLcode rtsp_do(struct Curl_easy *data, bool *done)
if(rtspreq == RTSPREQ_SET_PARAMETER ||
rtspreq == RTSPREQ_GET_PARAMETER) {
if(!Curl_checkheaders(data, STRCONST("Content-Type"))) {
- result = Curl_dyn_addn(&req_buffer,
- STRCONST("Content-Type: "
- "text/parameters\r\n"));
+ result = curlx_dyn_addn(&req_buffer,
+ STRCONST("Content-Type: "
+ "text/parameters\r\n"));
if(result)
goto out;
}
@@ -568,9 +613,9 @@ static CURLcode rtsp_do(struct Curl_easy *data, bool *done)
if(rtspreq == RTSPREQ_ANNOUNCE) {
if(!Curl_checkheaders(data, STRCONST("Content-Type"))) {
- result = Curl_dyn_addn(&req_buffer,
- STRCONST("Content-Type: "
- "application/sdp\r\n"));
+ result = curlx_dyn_addn(&req_buffer,
+ STRCONST("Content-Type: "
+ "application/sdp\r\n"));
if(result)
goto out;
}
@@ -589,7 +634,7 @@ static CURLcode rtsp_do(struct Curl_easy *data, bool *done)
}
/* Finish the request buffer */
- result = Curl_dyn_addn(&req_buffer, STRCONST("\r\n"));
+ result = curlx_dyn_addn(&req_buffer, STRCONST("\r\n"));
if(result)
goto out;
@@ -613,7 +658,7 @@ static CURLcode rtsp_do(struct Curl_easy *data, bool *done)
result = CURLE_ABORTED_BY_CALLBACK;
}
out:
- Curl_dyn_free(&req_buffer);
+ curlx_dyn_free(&req_buffer);
return result;
}
@@ -621,10 +666,10 @@ out:
* write any BODY bytes missing to the client, ignore the rest.
*/
static CURLcode rtp_write_body_junk(struct Curl_easy *data,
+ struct rtsp_conn *rtspc,
const char *buf,
size_t blen)
{
- struct rtsp_conn *rtspc = &(data->conn->proto.rtspc);
curl_off_t body_remain;
bool in_body;
@@ -642,11 +687,11 @@ static CURLcode rtp_write_body_junk(struct Curl_easy *data,
}
static CURLcode rtsp_filter_rtp(struct Curl_easy *data,
- const char *buf,
- size_t blen,
- size_t *pconsumed)
+ struct rtsp_conn *rtspc,
+ const char *buf,
+ size_t blen,
+ size_t *pconsumed)
{
- struct rtsp_conn *rtspc = &(data->conn->proto.rtspc);
CURLcode result = CURLE_OK;
size_t skip_len = 0;
@@ -658,7 +703,7 @@ static CURLcode rtsp_filter_rtp(struct Curl_easy *data,
switch(rtspc->state) {
case RTP_PARSE_SKIP: {
- DEBUGASSERT(Curl_dyn_len(&rtspc->buf) == 0);
+ DEBUGASSERT(curlx_dyn_len(&rtspc->buf) == 0);
while(blen && buf[0] != '$') {
if(!in_body && buf[0] == 'R' &&
data->set.rtspreq != RTSPREQ_RECEIVE) {
@@ -683,12 +728,12 @@ static CURLcode rtsp_filter_rtp(struct Curl_easy *data,
/* possible start of an RTP message, buffer */
if(skip_len) {
/* end of junk/BODY bytes, flush */
- result = rtp_write_body_junk(data, buf - skip_len, skip_len);
+ result = rtp_write_body_junk(data, rtspc, buf - skip_len, skip_len);
skip_len = 0;
if(result)
goto out;
}
- if(Curl_dyn_addn(&rtspc->buf, buf, 1)) {
+ if(curlx_dyn_addn(&rtspc->buf, buf, 1)) {
result = CURLE_OUT_OF_MEMORY;
goto out;
}
@@ -703,7 +748,7 @@ static CURLcode rtsp_filter_rtp(struct Curl_easy *data,
case RTP_PARSE_CHANNEL: {
int idx = ((unsigned char)buf[0]) / 8;
int off = ((unsigned char)buf[0]) % 8;
- DEBUGASSERT(Curl_dyn_len(&rtspc->buf) == 1);
+ DEBUGASSERT(curlx_dyn_len(&rtspc->buf) == 1);
if(!(data->state.rtp_channel_mask[idx] & (1 << off))) {
/* invalid channel number, junk or BODY data */
rtspc->state = RTP_PARSE_SKIP;
@@ -714,7 +759,8 @@ static CURLcode rtsp_filter_rtp(struct Curl_easy *data,
/* We did not consume the initial '$' in our buffer, but had
* it from an earlier call. We cannot un-consume it and have
* to write it directly as BODY data */
- result = rtp_write_body_junk(data, Curl_dyn_ptr(&rtspc->buf), 1);
+ result = rtp_write_body_junk(data, rtspc,
+ curlx_dyn_ptr(&rtspc->buf), 1);
if(result)
goto out;
}
@@ -722,12 +768,12 @@ static CURLcode rtsp_filter_rtp(struct Curl_easy *data,
/* count the '$' as skip and continue */
skip_len = 1;
}
- Curl_dyn_free(&rtspc->buf);
+ curlx_dyn_free(&rtspc->buf);
break;
}
/* a valid channel, so we expect this to be a real RTP message */
rtspc->rtp_channel = (unsigned char)buf[0];
- if(Curl_dyn_addn(&rtspc->buf, buf, 1)) {
+ if(curlx_dyn_addn(&rtspc->buf, buf, 1)) {
result = CURLE_OUT_OF_MEMORY;
goto out;
}
@@ -739,10 +785,10 @@ static CURLcode rtsp_filter_rtp(struct Curl_easy *data,
}
case RTP_PARSE_LEN: {
- size_t rtp_len = Curl_dyn_len(&rtspc->buf);
+ size_t rtp_len = curlx_dyn_len(&rtspc->buf);
const char *rtp_buf;
DEBUGASSERT(rtp_len >= 2 && rtp_len < 4);
- if(Curl_dyn_addn(&rtspc->buf, buf, 1)) {
+ if(curlx_dyn_addn(&rtspc->buf, buf, 1)) {
result = CURLE_OUT_OF_MEMORY;
goto out;
}
@@ -751,19 +797,19 @@ static CURLcode rtsp_filter_rtp(struct Curl_easy *data,
--blen;
if(rtp_len == 2)
break;
- rtp_buf = Curl_dyn_ptr(&rtspc->buf);
+ rtp_buf = curlx_dyn_ptr(&rtspc->buf);
rtspc->rtp_len = RTP_PKT_LENGTH(rtp_buf) + 4;
rtspc->state = RTP_PARSE_DATA;
break;
}
case RTP_PARSE_DATA: {
- size_t rtp_len = Curl_dyn_len(&rtspc->buf);
+ size_t rtp_len = curlx_dyn_len(&rtspc->buf);
size_t needed;
DEBUGASSERT(rtp_len < rtspc->rtp_len);
needed = rtspc->rtp_len - rtp_len;
if(needed <= blen) {
- if(Curl_dyn_addn(&rtspc->buf, buf, needed)) {
+ if(curlx_dyn_addn(&rtspc->buf, buf, needed)) {
result = CURLE_OUT_OF_MEMORY;
goto out;
}
@@ -773,15 +819,15 @@ static CURLcode rtsp_filter_rtp(struct Curl_easy *data,
/* complete RTP message in buffer */
DEBUGF(infof(data, "RTP write channel %d rtp_len %zu",
rtspc->rtp_channel, rtspc->rtp_len));
- result = rtp_client_write(data, Curl_dyn_ptr(&rtspc->buf),
+ result = rtp_client_write(data, curlx_dyn_ptr(&rtspc->buf),
rtspc->rtp_len);
- Curl_dyn_free(&rtspc->buf);
+ curlx_dyn_free(&rtspc->buf);
rtspc->state = RTP_PARSE_SKIP;
if(result)
goto out;
}
else {
- if(Curl_dyn_addn(&rtspc->buf, buf, blen)) {
+ if(curlx_dyn_addn(&rtspc->buf, buf, blen)) {
result = CURLE_OUT_OF_MEMORY;
goto out;
}
@@ -799,7 +845,7 @@ static CURLcode rtsp_filter_rtp(struct Curl_easy *data,
}
out:
if(!result && skip_len)
- result = rtp_write_body_junk(data, buf - skip_len, skip_len);
+ result = rtp_write_body_junk(data, rtspc, buf - skip_len, skip_len);
return result;
}
@@ -808,10 +854,14 @@ static CURLcode rtsp_rtp_write_resp(struct Curl_easy *data,
size_t blen,
bool is_eos)
{
- struct rtsp_conn *rtspc = &(data->conn->proto.rtspc);
+ struct rtsp_conn *rtspc =
+ Curl_conn_meta_get(data->conn, CURL_META_RTSP_CONN);
CURLcode result = CURLE_OK;
size_t consumed = 0;
+ if(!rtspc)
+ return CURLE_FAILED_INIT;
+
if(!data->req.header)
rtspc->in_header = FALSE;
if(!blen) {
@@ -823,7 +873,7 @@ static CURLcode rtsp_rtp_write_resp(struct Curl_easy *data,
/* If header parsing is not ongoing, extract RTP messages */
if(!rtspc->in_header) {
- result = rtsp_filter_rtp(data, buf, blen, &consumed);
+ result = rtsp_filter_rtp(data, rtspc, buf, blen, &consumed);
if(result)
goto out;
buf += consumed;
@@ -855,7 +905,7 @@ static CURLcode rtsp_rtp_write_resp(struct Curl_easy *data,
data->req.size = 0;
data->req.download_done = TRUE;
}
- result = rtsp_filter_rtp(data, buf, blen, &consumed);
+ result = rtsp_filter_rtp(data, rtspc, buf, blen, &consumed);
if(result)
goto out;
blen -= consumed;
@@ -933,10 +983,12 @@ CURLcode Curl_rtsp_parseheader(struct Curl_easy *data, const char *header)
{
if(checkprefix("CSeq:", header)) {
curl_off_t CSeq = 0;
- struct RTSP *rtsp = data->req.p.rtsp;
+ struct RTSP *rtsp = Curl_meta_get(data, CURL_META_RTSP_EASY);
const char *p = &header[5];
- Curl_str_passblanks(&p);
- if(Curl_str_number(&p, &CSeq, LONG_MAX)) {
+ if(!rtsp)
+ return CURLE_FAILED_INIT;
+ curlx_str_passblanks(&p);
+ if(curlx_str_number(&p, &CSeq, LONG_MAX)) {
failf(data, "Unable to read the CSeq header: [%s]", header);
return CURLE_RTSP_CSEQ_ERROR;
}
@@ -949,7 +1001,7 @@ CURLcode Curl_rtsp_parseheader(struct Curl_easy *data, const char *header)
/* Find the first non-space letter */
start = header + 8;
- Curl_str_passblanks(&start);
+ curlx_str_passblanks(&start);
if(!*start) {
failf(data, "Got a blank Session ID");
@@ -1007,16 +1059,16 @@ CURLcode rtsp_parse_transport(struct Curl_easy *data, const char *transport)
const char *start, *end;
start = transport;
while(start && *start) {
- Curl_str_passblanks(&start);
+ curlx_str_passblanks(&start);
end = strchr(start, ';');
if(checkprefix("interleaved=", start)) {
curl_off_t chan1, chan2, chan;
const char *p = start + 12;
- if(!Curl_str_number(&p, &chan1, 255)) {
+ if(!curlx_str_number(&p, &chan1, 255)) {
unsigned char *rtp_channel_mask = data->state.rtp_channel_mask;
chan2 = chan1;
- if(!Curl_str_single(&p, '-')) {
- if(Curl_str_number(&p, &chan2, 255)) {
+ if(!curlx_str_single(&p, '-')) {
+ if(curlx_str_number(&p, &chan2, 255)) {
infof(data, "Unable to read the interleaved parameter from "
"Transport header: [%s]", transport);
chan2 = chan1;
diff --git a/libs/libcurl/src/rtsp.h b/libs/libcurl/src/rtsp.h
index 0aeaa45e9d..3209219d52 100644
--- a/libs/libcurl/src/rtsp.h
+++ b/libs/libcurl/src/rtsp.h
@@ -36,33 +36,4 @@ CURLcode Curl_rtsp_parseheader(struct Curl_easy *data, const char *header);
#endif /* CURL_DISABLE_RTSP */
-typedef enum {
- RTP_PARSE_SKIP,
- RTP_PARSE_CHANNEL,
- RTP_PARSE_LEN,
- RTP_PARSE_DATA
-} rtp_parse_st;
-/*
- * RTSP Connection data
- *
- * Currently, only used for tracking incomplete RTP data reads
- */
-struct rtsp_conn {
- struct dynbuf buf;
- int rtp_channel;
- size_t rtp_len;
- rtp_parse_st state;
- BIT(in_header);
- BIT(initialised);
-};
-
-/****************************************************************************
- * RTSP unique setup
- ***************************************************************************/
-struct RTSP {
- long CSeq_sent; /* CSeq of this request */
- long CSeq_recv; /* CSeq received */
-};
-
-
#endif /* HEADER_CURL_RTSP_H */
diff --git a/libs/libcurl/src/select.c b/libs/libcurl/src/select.c
index ba8c00153d..01bde7c0ee 100644
--- a/libs/libcurl/src/select.c
+++ b/libs/libcurl/src/select.c
@@ -45,8 +45,8 @@
#include "urldata.h"
#include "connect.h"
#include "select.h"
-#include "timediff.h"
-#include "warnless.h"
+#include "curlx/timediff.h"
+#include "curlx/warnless.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h"
@@ -197,7 +197,7 @@ int Curl_socket_check(curl_socket_t readfd0, /* two sockets to read from */
return Curl_wait_ms(timeout_ms);
}
- /* Avoid initial timestamp, avoid Curl_now() call, when elapsed
+ /* Avoid initial timestamp, avoid curlx_now() call, when elapsed
time in this function does not need to be measured. This happens
when function is called with a zero timeout or a negative timeout
value indicating a blocking call should be performed. */
@@ -292,7 +292,7 @@ int Curl_poll(struct pollfd ufds[], unsigned int nfds, timediff_t timeout_ms)
return Curl_wait_ms(timeout_ms);
}
- /* Avoid initial timestamp, avoid Curl_now() call, when elapsed
+ /* Avoid initial timestamp, avoid curlx_now() call, when elapsed
time in this function does not need to be measured. This happens
when function is called with a zero timeout or a negative timeout
value indicating a blocking call should be performed. */
diff --git a/libs/libcurl/src/sendf.c b/libs/libcurl/src/sendf.c
index c576febd1c..34fd0edce0 100644
--- a/libs/libcurl/src/sendf.c
+++ b/libs/libcurl/src/sendf.c
@@ -52,7 +52,7 @@
#include "strdup.h"
#include "http2.h"
#include "progress.h"
-#include "warnless.h"
+#include "curlx/warnless.h"
#include "ws.h"
/* The last 3 #include files should be in this order */
diff --git a/libs/libcurl/src/setopt.c b/libs/libcurl/src/setopt.c
index d853e3effa..6e0838b326 100644
--- a/libs/libcurl/src/setopt.c
+++ b/libs/libcurl/src/setopt.c
@@ -43,8 +43,9 @@
#include "strcase.h"
#include "share.h"
#include "vtls/vtls.h"
-#include "warnless.h"
+#include "curlx/warnless.h"
#include "sendf.h"
+#include "hostip.h"
#include "http2.h"
#include "setopt.h"
#include "multiif.h"
@@ -255,6 +256,157 @@ static CURLcode httpauth(struct Curl_easy *data, bool proxy,
return CURLE_OK;
}
+#ifndef CURL_DISABLE_HTTP
+static CURLcode setopt_HTTP_VERSION(struct Curl_easy *data, long arg)
+{
+ /*
+ * This sets a requested HTTP version to be used. The value is one of
+ * the listed enums in curl/curl.h.
+ */
+ switch(arg) {
+ case CURL_HTTP_VERSION_NONE:
+ /* accepted */
+ break;
+ case CURL_HTTP_VERSION_1_0:
+ case CURL_HTTP_VERSION_1_1:
+ /* accepted */
+ break;
+#ifdef USE_HTTP2
+ case CURL_HTTP_VERSION_2_0:
+ case CURL_HTTP_VERSION_2TLS:
+ case CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE:
+ /* accepted */
+ break;
+#endif
+#ifdef USE_HTTP3
+ case CURL_HTTP_VERSION_3:
+ case CURL_HTTP_VERSION_3ONLY:
+ /* accepted */
+ break;
+#endif
+ default:
+ /* not accepted */
+ if(arg < CURL_HTTP_VERSION_NONE)
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ return CURLE_UNSUPPORTED_PROTOCOL;
+ }
+ data->set.httpwant = (unsigned char)arg;
+ return CURLE_OK;
+}
+#endif /* ! CURL_DISABLE_HTTP */
+
+#ifdef USE_SSL
+static CURLcode setopt_SSLVERSION(struct Curl_easy *data, CURLoption option,
+ long arg)
+{
+ /*
+ * Set explicit SSL version to try to connect with, as some SSL
+ * implementations are lame.
+ */
+ {
+ long version, version_max;
+ struct ssl_primary_config *primary = &data->set.ssl.primary;
+#ifndef CURL_DISABLE_PROXY
+ if(option != CURLOPT_SSLVERSION)
+ primary = &data->set.proxy_ssl.primary;
+#else
+ if(option) {}
+#endif
+ version = C_SSLVERSION_VALUE(arg);
+ version_max = (long)C_SSLVERSION_MAX_VALUE(arg);
+
+ if(version < CURL_SSLVERSION_DEFAULT ||
+ version == CURL_SSLVERSION_SSLv2 ||
+ version == CURL_SSLVERSION_SSLv3 ||
+ version >= CURL_SSLVERSION_LAST ||
+ version_max < CURL_SSLVERSION_MAX_NONE ||
+ version_max >= CURL_SSLVERSION_MAX_LAST)
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+
+ primary->version = (unsigned char)version;
+ primary->version_max = (unsigned int)version_max;
+ }
+ return CURLE_OK;
+}
+#endif /* ! USE_SSL */
+
+#ifndef CURL_DISABLE_RTSP
+static CURLcode setopt_RTSP_REQUEST(struct Curl_easy *data, long arg)
+{
+ /*
+ * Set the RTSP request method (OPTIONS, SETUP, PLAY, etc...)
+ * Would this be better if the RTSPREQ_* were just moved into here?
+ */
+ Curl_RtspReq rtspreq = RTSPREQ_NONE;
+ switch(arg) {
+ case CURL_RTSPREQ_OPTIONS:
+ rtspreq = RTSPREQ_OPTIONS;
+ break;
+
+ case CURL_RTSPREQ_DESCRIBE:
+ rtspreq = RTSPREQ_DESCRIBE;
+ break;
+
+ case CURL_RTSPREQ_ANNOUNCE:
+ rtspreq = RTSPREQ_ANNOUNCE;
+ break;
+
+ case CURL_RTSPREQ_SETUP:
+ rtspreq = RTSPREQ_SETUP;
+ break;
+
+ case CURL_RTSPREQ_PLAY:
+ rtspreq = RTSPREQ_PLAY;
+ break;
+
+ case CURL_RTSPREQ_PAUSE:
+ rtspreq = RTSPREQ_PAUSE;
+ break;
+
+ case CURL_RTSPREQ_TEARDOWN:
+ rtspreq = RTSPREQ_TEARDOWN;
+ break;
+
+ case CURL_RTSPREQ_GET_PARAMETER:
+ rtspreq = RTSPREQ_GET_PARAMETER;
+ break;
+
+ case CURL_RTSPREQ_SET_PARAMETER:
+ rtspreq = RTSPREQ_SET_PARAMETER;
+ break;
+
+ case CURL_RTSPREQ_RECORD:
+ rtspreq = RTSPREQ_RECORD;
+ break;
+
+ case CURL_RTSPREQ_RECEIVE:
+ rtspreq = RTSPREQ_RECEIVE;
+ break;
+ default:
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ }
+
+ data->set.rtspreq = rtspreq;
+ return CURLE_OK;
+}
+#endif /* ! CURL_DISABLE_RTSP */
+
+#ifdef USE_SSL
+static void set_ssl_options(struct ssl_config_data *ssl,
+ struct ssl_primary_config *config,
+ long arg)
+{
+ config->ssl_options = (unsigned char)(arg & 0xff);
+ ssl->enable_beast = !!(arg & CURLSSLOPT_ALLOW_BEAST);
+ ssl->no_revoke = !!(arg & CURLSSLOPT_NO_REVOKE);
+ ssl->no_partialchain = !!(arg & CURLSSLOPT_NO_PARTIALCHAIN);
+ ssl->revoke_best_effort = !!(arg & CURLSSLOPT_REVOKE_BEST_EFFORT);
+ ssl->native_ca_store = !!(arg & CURLSSLOPT_NATIVE_CA);
+ ssl->auto_client_cert = !!(arg & CURLSSLOPT_AUTO_CLIENT_CERT);
+ ssl->earlydata = !!(arg & CURLSSLOPT_EARLYDATA);
+}
+#endif
+
static CURLcode setopt_long(struct Curl_easy *data, CURLoption option,
long arg)
{
@@ -290,7 +442,7 @@ static CURLcode setopt_long(struct Curl_easy *data, CURLoption option,
return CURLE_BAD_FUNCTION_ARGUMENT;
data->set.maxconnects = (unsigned int)uarg;
break;
- case CURLOPT_FORBID_REUSE:
+ case CURLOPT_FORBID_REUSE:
/*
* When this transfer is done, it must not be left to be reused by a
* subsequent transfer but shall be closed immediately.
@@ -321,11 +473,7 @@ static CURLcode setopt_long(struct Curl_easy *data, CURLoption option,
/*
* Shut off the internal supported progress meter
*/
- data->set.hide_progress = enabled;
- if(data->set.hide_progress)
- data->progress.flags |= PGRS_HIDE;
- else
- data->progress.flags &= ~PGRS_HIDE;
+ data->progress.hide = enabled;
break;
case CURLOPT_NOBODY:
/*
@@ -451,36 +599,12 @@ static CURLcode setopt_long(struct Curl_easy *data, CURLoption option,
#ifndef CURL_DISABLE_PROXY
case CURLOPT_PROXY_SSLVERSION:
#endif
- /*
- * Set explicit SSL version to try to connect with, as some SSL
- * implementations are lame.
- */
#ifdef USE_SSL
- {
- long version, version_max;
- struct ssl_primary_config *primary = &data->set.ssl.primary;
-#ifndef CURL_DISABLE_PROXY
- if(option != CURLOPT_SSLVERSION)
- primary = &data->set.proxy_ssl.primary;
-#endif
- version = C_SSLVERSION_VALUE(arg);
- version_max = (long)C_SSLVERSION_MAX_VALUE(arg);
-
- if(version < CURL_SSLVERSION_DEFAULT ||
- version == CURL_SSLVERSION_SSLv2 ||
- version == CURL_SSLVERSION_SSLv3 ||
- version >= CURL_SSLVERSION_LAST ||
- version_max < CURL_SSLVERSION_MAX_NONE ||
- version_max >= CURL_SSLVERSION_MAX_LAST)
- return CURLE_BAD_FUNCTION_ARGUMENT;
-
- primary->version = (unsigned char)version;
- primary->version_max = (unsigned int)version_max;
- }
- break;
+ return setopt_SSLVERSION(data, option, arg);
#else
return CURLE_NOT_BUILT_IN;
#endif
+
case CURLOPT_POSTFIELDSIZE:
/*
* The size of the POSTFIELD data to prevent libcurl to do strlen() to
@@ -596,39 +720,7 @@ static CURLcode setopt_long(struct Curl_easy *data, CURLoption option,
break;
case CURLOPT_HTTP_VERSION:
- /*
- * This sets a requested HTTP version to be used. The value is one of
- * the listed enums in curl/curl.h.
- */
- switch(arg) {
- case CURL_HTTP_VERSION_NONE:
- /* accepted */
- break;
- case CURL_HTTP_VERSION_1_0:
- case CURL_HTTP_VERSION_1_1:
- /* accepted */
- break;
-#ifdef USE_HTTP2
- case CURL_HTTP_VERSION_2_0:
- case CURL_HTTP_VERSION_2TLS:
- case CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE:
- /* accepted */
- break;
-#endif
-#ifdef USE_HTTP3
- case CURL_HTTP_VERSION_3:
- case CURL_HTTP_VERSION_3ONLY:
- /* accepted */
- break;
-#endif
- default:
- /* not accepted */
- if(arg < CURL_HTTP_VERSION_NONE)
- return CURLE_BAD_FUNCTION_ARGUMENT;
- return CURLE_UNSUPPORTED_PROTOCOL;
- }
- data->set.httpwant = (unsigned char)arg;
- break;
+ return setopt_HTTP_VERSION(data, arg);
case CURLOPT_EXPECT_100_TIMEOUT_MS:
/*
@@ -1051,29 +1143,12 @@ static CURLcode setopt_long(struct Curl_easy *data, CURLoption option,
data->set.use_ssl = (unsigned char)arg;
break;
case CURLOPT_SSL_OPTIONS:
- data->set.ssl.primary.ssl_options = (unsigned char)(arg & 0xff);
- data->set.ssl.enable_beast = !!(arg & CURLSSLOPT_ALLOW_BEAST);
- data->set.ssl.no_revoke = !!(arg & CURLSSLOPT_NO_REVOKE);
- data->set.ssl.no_partialchain = !!(arg & CURLSSLOPT_NO_PARTIALCHAIN);
- data->set.ssl.revoke_best_effort = !!(arg & CURLSSLOPT_REVOKE_BEST_EFFORT);
- data->set.ssl.native_ca_store = !!(arg & CURLSSLOPT_NATIVE_CA);
- data->set.ssl.auto_client_cert = !!(arg & CURLSSLOPT_AUTO_CLIENT_CERT);
- data->set.ssl.earlydata = !!(arg & CURLSSLOPT_EARLYDATA);
- /* If a setting is added here it should also be added in dohprobe()
- which sets its own CURLOPT_SSL_OPTIONS based on these settings. */
+ set_ssl_options(&data->set.ssl, &data->set.ssl.primary, arg);
break;
#ifndef CURL_DISABLE_PROXY
case CURLOPT_PROXY_SSL_OPTIONS:
- data->set.proxy_ssl.primary.ssl_options = (unsigned char)(arg & 0xff);
- data->set.proxy_ssl.enable_beast = !!(arg & CURLSSLOPT_ALLOW_BEAST);
- data->set.proxy_ssl.no_revoke = !!(arg & CURLSSLOPT_NO_REVOKE);
- data->set.proxy_ssl.no_partialchain = !!(arg & CURLSSLOPT_NO_PARTIALCHAIN);
- data->set.proxy_ssl.revoke_best_effort =
- !!(arg & CURLSSLOPT_REVOKE_BEST_EFFORT);
- data->set.proxy_ssl.native_ca_store = !!(arg & CURLSSLOPT_NATIVE_CA);
- data->set.proxy_ssl.auto_client_cert =
- !!(arg & CURLSSLOPT_AUTO_CLIENT_CERT);
+ set_ssl_options(&data->set.proxy_ssl, &data->set.proxy_ssl.primary, arg);
break;
#endif
@@ -1129,12 +1204,8 @@ static CURLcode setopt_long(struct Curl_easy *data, CURLoption option,
/*
* disable libcurl transfer encoding is used
*/
-#ifndef USE_HYPER
data->set.http_te_skip = !enabled; /* reversed */
break;
-#else
- return CURLE_NOT_BUILT_IN; /* hyper does not support */
-#endif
case CURLOPT_HTTP_CONTENT_DECODING:
/*
@@ -1204,63 +1275,7 @@ static CURLcode setopt_long(struct Curl_easy *data, CURLoption option,
break;
#ifndef CURL_DISABLE_RTSP
case CURLOPT_RTSP_REQUEST:
- {
- /*
- * Set the RTSP request method (OPTIONS, SETUP, PLAY, etc...)
- * Would this be better if the RTSPREQ_* were just moved into here?
- */
- Curl_RtspReq rtspreq = RTSPREQ_NONE;
- switch(arg) {
- case CURL_RTSPREQ_OPTIONS:
- rtspreq = RTSPREQ_OPTIONS;
- break;
-
- case CURL_RTSPREQ_DESCRIBE:
- rtspreq = RTSPREQ_DESCRIBE;
- break;
-
- case CURL_RTSPREQ_ANNOUNCE:
- rtspreq = RTSPREQ_ANNOUNCE;
- break;
-
- case CURL_RTSPREQ_SETUP:
- rtspreq = RTSPREQ_SETUP;
- break;
-
- case CURL_RTSPREQ_PLAY:
- rtspreq = RTSPREQ_PLAY;
- break;
-
- case CURL_RTSPREQ_PAUSE:
- rtspreq = RTSPREQ_PAUSE;
- break;
-
- case CURL_RTSPREQ_TEARDOWN:
- rtspreq = RTSPREQ_TEARDOWN;
- break;
-
- case CURL_RTSPREQ_GET_PARAMETER:
- rtspreq = RTSPREQ_GET_PARAMETER;
- break;
-
- case CURL_RTSPREQ_SET_PARAMETER:
- rtspreq = RTSPREQ_SET_PARAMETER;
- break;
-
- case CURL_RTSPREQ_RECORD:
- rtspreq = RTSPREQ_RECORD;
- break;
-
- case CURL_RTSPREQ_RECEIVE:
- rtspreq = RTSPREQ_RECEIVE;
- break;
- default:
- return CURLE_BAD_FUNCTION_ARGUMENT;
- }
-
- data->set.rtspreq = rtspreq;
- break;
- }
+ return setopt_RTSP_REQUEST(data, arg);
case CURLOPT_RTSP_CLIENT_CSEQ:
/*
* Set the CSEQ number to issue for the next RTSP request. Useful if the
@@ -1388,7 +1403,8 @@ static CURLcode setopt_long(struct Curl_easy *data, CURLoption option,
#endif /* ! CURL_DISABLE_ALTSVC */
#ifndef CURL_DISABLE_WEBSOCKETS
case CURLOPT_WS_OPTIONS:
- data->set.ws_raw_mode = (bool)(arg & CURLWS_RAW_MODE);
+ data->set.ws_raw_mode = (bool)(arg & CURLWS_RAW_MODE);
+ data->set.ws_no_auto_pong = (bool)(arg & CURLWS_NOAUTOPONG);
break;
#endif
case CURLOPT_QUICK_EXIT:
@@ -1569,11 +1585,6 @@ static CURLcode setopt_pointers(struct Curl_easy *data, CURLoption option,
if(data->share) {
Curl_share_lock(data, CURL_LOCK_DATA_SHARE, CURL_LOCK_ACCESS_SINGLE);
- if(data->dns.hostcachetype == HCACHE_SHARED) {
- data->dns.hostcache = NULL;
- data->dns.hostcachetype = HCACHE_NONE;
- }
-
#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
if(data->share->cookies == data->cookies)
data->cookies = NULL;
@@ -1587,6 +1598,10 @@ static CURLcode setopt_pointers(struct Curl_easy *data, CURLoption option,
if(data->psl == &data->share->psl)
data->psl = data->multi ? &data->multi->psl : NULL;
#endif
+ if(data->share->specifier & (1 << CURL_LOCK_DATA_DNS)) {
+ Curl_resolv_unlink(data, &data->state.dns[0]);
+ Curl_resolv_unlink(data, &data->state.dns[1]);
+ }
data->share->dirty--;
@@ -1603,11 +1618,6 @@ static CURLcode setopt_pointers(struct Curl_easy *data, CURLoption option,
data->share->dirty++;
- if(data->share->specifier & (1 << CURL_LOCK_DATA_DNS)) {
- /* use shared host cache */
- data->dns.hostcache = &data->share->hostcache;
- data->dns.hostcachetype = HCACHE_SHARED;
- }
#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
if(data->share->cookies) {
/* use shared cookie list, first free own one if any */
@@ -2406,6 +2416,15 @@ static CURLcode setopt_cptr(struct Curl_easy *data, CURLoption option,
*/
return Curl_setstropt(&data->set.str[STRING_SSL_EC_CURVES], ptr);
+ case CURLOPT_SSL_SIGNATURE_ALGORITHMS:
+ /*
+ * Set accepted signature algorithms.
+ * Specify colon-delimited list of signature scheme names.
+ */
+ if(Curl_ssl_supports(data, SSLSUPP_SIGNATURE_ALGORITHMS))
+ return Curl_setstropt(&data->set.str[STRING_SSL_SIGNATURE_ALGORITHMS],
+ ptr);
+ return CURLE_NOT_BUILT_IN;
#endif
#ifdef USE_SSH
case CURLOPT_SSH_PUBLIC_KEYFILE:
@@ -2548,30 +2567,30 @@ static CURLcode setopt_cptr(struct Curl_easy *data, CURLoption option,
break;
#endif
#endif
-#ifdef USE_ARES
+#ifdef CURLRES_ARES
case CURLOPT_DNS_SERVERS:
result = Curl_setstropt(&data->set.str[STRING_DNS_SERVERS], ptr);
if(result)
return result;
- return Curl_set_dns_servers(data, data->set.str[STRING_DNS_SERVERS]);
+ return Curl_async_ares_set_dns_servers(data);
case CURLOPT_DNS_INTERFACE:
result = Curl_setstropt(&data->set.str[STRING_DNS_INTERFACE], ptr);
if(result)
return result;
- return Curl_set_dns_interface(data, data->set.str[STRING_DNS_INTERFACE]);
+ return Curl_async_ares_set_dns_interface(data);
case CURLOPT_DNS_LOCAL_IP4:
result = Curl_setstropt(&data->set.str[STRING_DNS_LOCAL_IP4], ptr);
if(result)
return result;
- return Curl_set_dns_local_ip4(data, data->set.str[STRING_DNS_LOCAL_IP4]);
+ return Curl_async_ares_set_dns_local_ip4(data);
case CURLOPT_DNS_LOCAL_IP6:
result = Curl_setstropt(&data->set.str[STRING_DNS_LOCAL_IP6], ptr);
if(result)
return result;
- return Curl_set_dns_local_ip6(data, data->set.str[STRING_DNS_LOCAL_IP6]);
+ return Curl_async_ares_set_dns_local_ip6(data);
#endif
#ifdef USE_UNIX_SOCKETS
@@ -3074,9 +3093,7 @@ CURLcode curl_easy_setopt(CURL *d, CURLoption tag, ...)
result = Curl_vsetopt(data, tag, arg);
va_end(arg);
-#ifdef DEBUGBUILD
if(result == CURLE_BAD_FUNCTION_ARGUMENT)
- infof(data, "setopt arg 0x%x returned CURLE_BAD_FUNCTION_ARGUMENT", tag);
-#endif
+ failf(data, "setopt 0x%x got bad argument", tag);
return result;
}
diff --git a/libs/libcurl/src/sha256.c b/libs/libcurl/src/sha256.c
index e53d0c24d3..f762c195d8 100644
--- a/libs/libcurl/src/sha256.c
+++ b/libs/libcurl/src/sha256.c
@@ -28,7 +28,7 @@
#if !defined(CURL_DISABLE_AWS) || !defined(CURL_DISABLE_DIGEST_AUTH) \
|| defined(USE_LIBSSH2) || defined(USE_SSL)
-#include "warnless.h"
+#include "curlx/warnless.h"
#include "curl_sha256.h"
#include "curl_hmac.h"
diff --git a/libs/libcurl/src/share.c b/libs/libcurl/src/share.c
index 0dc2b146a6..d31b23f512 100644
--- a/libs/libcurl/src/share.c
+++ b/libs/libcurl/src/share.c
@@ -46,12 +46,14 @@ curl_share_init(void)
if(share) {
share->magic = CURL_GOOD_SHARE;
share->specifier |= (1 << CURL_LOCK_DATA_SHARE);
- Curl_init_dnscache(&share->hostcache, 23);
+ Curl_dnscache_init(&share->dnscache, 23);
share->admin = curl_easy_init();
if(!share->admin) {
free(share);
return NULL;
}
+ /* admin handles have mid 0 */
+ share->admin->mid = 0;
share->admin->state.internal = TRUE;
#ifdef DEBUGBUILD
if(getenv("CURL_DEBUG"))
@@ -136,8 +138,7 @@ curl_share_setopt(CURLSH *sh, CURLSHoption option, ...)
case CURL_LOCK_DATA_CONNECT:
/* It is safe to set this option several times on a share. */
if(!share->cpool.initialised) {
- if(Curl_cpool_init(&share->cpool, share->admin, share, 103))
- res = CURLSHE_NOMEM;
+ Curl_cpool_init(&share->cpool, share->admin, share, 103);
}
break;
@@ -248,7 +249,8 @@ curl_share_cleanup(CURLSH *sh)
if(share->specifier & (1 << CURL_LOCK_DATA_CONNECT)) {
Curl_cpool_destroy(&share->cpool);
}
- Curl_hash_destroy(&share->hostcache);
+
+ Curl_dnscache_destroy(&share->dnscache);
#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
Curl_cookie_cleanup(share->cookies);
diff --git a/libs/libcurl/src/share.h b/libs/libcurl/src/share.h
index 920a30af0a..6cc9db3ee3 100644
--- a/libs/libcurl/src/share.h
+++ b/libs/libcurl/src/share.h
@@ -51,7 +51,7 @@ struct Curl_share {
void *clientdata;
struct Curl_easy *admin;
struct cpool cpool;
- struct Curl_hash hostcache;
+ struct Curl_dnscache dnscache; /* DNS cache */
#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
struct CookieInfo *cookies;
#endif
diff --git a/libs/libcurl/src/sigpipe.h b/libs/libcurl/src/sigpipe.h
index c68a076b99..6ab1faab77 100644
--- a/libs/libcurl/src/sigpipe.h
+++ b/libs/libcurl/src/sigpipe.h
@@ -31,7 +31,7 @@
struct sigpipe_ignore {
struct sigaction old_pipe_act;
- bool no_signal;
+ BIT(no_signal);
};
#define SIGPIPE_VARIABLE(x) struct sigpipe_ignore x
diff --git a/libs/libcurl/src/smb.c b/libs/libcurl/src/smb.c
index 7f81f6ec80..2313eeff96 100644
--- a/libs/libcurl/src/smb.c
+++ b/libs/libcurl/src/smb.c
@@ -29,6 +29,7 @@
#include "smb.h"
#include "urldata.h"
+#include "url.h"
#include "sendf.h"
#include "multiif.h"
#include "cfilters.h"
@@ -45,6 +46,58 @@
#include "curl_memory.h"
#include "memdebug.h"
+
+/* meta key for storing protocol meta at easy handle */
+#define CURL_META_SMB_EASY "meta:proto:smb:easy"
+/* meta key for storing protocol meta at connection */
+#define CURL_META_SMB_CONN "meta:proto:smb:conn"
+
+enum smb_conn_state {
+ SMB_NOT_CONNECTED = 0,
+ SMB_CONNECTING,
+ SMB_NEGOTIATE,
+ SMB_SETUP,
+ SMB_CONNECTED
+};
+
+/* SMB connection data, kept at connection */
+struct smb_conn {
+ enum smb_conn_state state;
+ char *user;
+ char *domain;
+ char *share;
+ unsigned char challenge[8];
+ unsigned int session_key;
+ unsigned short uid;
+ char *recv_buf;
+ char *send_buf;
+ size_t upload_size;
+ size_t send_size;
+ size_t sent;
+ size_t got;
+};
+
+/* SMB request state */
+enum smb_req_state {
+ SMB_REQUESTING,
+ SMB_TREE_CONNECT,
+ SMB_OPEN,
+ SMB_DOWNLOAD,
+ SMB_UPLOAD,
+ SMB_CLOSE,
+ SMB_TREE_DISCONNECT,
+ SMB_DONE
+};
+
+/* SMB request data, kept at easy handle */
+struct smb_request {
+ enum smb_req_state state;
+ char *path;
+ unsigned short tid; /* Even if we connect to the same tree as another */
+ unsigned short fid; /* request, the tid will be different */
+ CURLcode result;
+};
+
/*
* Definitions for SMB protocol data structures
*/
@@ -245,12 +298,11 @@ static CURLcode smb_connect(struct Curl_easy *data, bool *done);
static CURLcode smb_connection_state(struct Curl_easy *data, bool *done);
static CURLcode smb_do(struct Curl_easy *data, bool *done);
static CURLcode smb_request_state(struct Curl_easy *data, bool *done);
-static CURLcode smb_disconnect(struct Curl_easy *data,
- struct connectdata *conn, bool dead);
static int smb_getsock(struct Curl_easy *data, struct connectdata *conn,
curl_socket_t *socks);
static CURLcode smb_parse_url_path(struct Curl_easy *data,
- struct connectdata *conn);
+ struct smb_conn *smbc,
+ struct smb_request *req);
/*
* SMB handler interface
@@ -268,7 +320,7 @@ const struct Curl_handler Curl_handler_smb = {
smb_getsock, /* doing_getsock */
ZERO_NULL, /* domore_getsock */
ZERO_NULL, /* perform_getsock */
- smb_disconnect, /* disconnect */
+ ZERO_NULL, /* disconnect */
ZERO_NULL, /* write_resp */
ZERO_NULL, /* write_resp_hd */
ZERO_NULL, /* connection_check */
@@ -297,7 +349,7 @@ const struct Curl_handler Curl_handler_smbs = {
smb_getsock, /* doing_getsock */
ZERO_NULL, /* domore_getsock */
ZERO_NULL, /* perform_getsock */
- smb_disconnect, /* disconnect */
+ ZERO_NULL, /* disconnect */
ZERO_NULL, /* write_resp */
ZERO_NULL, /* write_resp_hd */
ZERO_NULL, /* connection_check */
@@ -341,30 +393,9 @@ static curl_off_t smb_swap64(curl_off_t x)
# define smb_swap64(x) (x)
#endif
-/* SMB request state */
-enum smb_req_state {
- SMB_REQUESTING,
- SMB_TREE_CONNECT,
- SMB_OPEN,
- SMB_DOWNLOAD,
- SMB_UPLOAD,
- SMB_CLOSE,
- SMB_TREE_DISCONNECT,
- SMB_DONE
-};
-
-/* SMB request data */
-struct smb_request {
- enum smb_req_state state;
- char *path;
- unsigned short tid; /* Even if we connect to the same tree as another */
- unsigned short fid; /* request, the tid will be different */
- CURLcode result;
-};
-
-static void conn_state(struct Curl_easy *data, enum smb_conn_state newstate)
+static void conn_state(struct Curl_easy *data, struct smb_conn *smbc,
+ enum smb_conn_state newstate)
{
- struct smb_conn *smbc = &data->conn->proto.smbc;
#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
/* For debug purposes */
static const char * const names[] = {
@@ -380,34 +411,59 @@ static void conn_state(struct Curl_easy *data, enum smb_conn_state newstate)
infof(data, "SMB conn %p state change from %s to %s",
(void *)smbc, names[smbc->state], names[newstate]);
#endif
-
+ (void)data;
smbc->state = newstate;
}
static void request_state(struct Curl_easy *data,
enum smb_req_state newstate)
{
- struct smb_request *req = data->req.p.smb;
+ struct smb_request *req = Curl_meta_get(data, CURL_META_SMB_EASY);
+ if(req) {
#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
- /* For debug purposes */
- static const char * const names[] = {
- "SMB_REQUESTING",
- "SMB_TREE_CONNECT",
- "SMB_OPEN",
- "SMB_DOWNLOAD",
- "SMB_UPLOAD",
- "SMB_CLOSE",
- "SMB_TREE_DISCONNECT",
- "SMB_DONE",
- /* LAST */
- };
-
- if(req->state != newstate)
- infof(data, "SMB request %p state change from %s to %s",
- (void *)req, names[req->state], names[newstate]);
+ /* For debug purposes */
+ static const char * const names[] = {
+ "SMB_REQUESTING",
+ "SMB_TREE_CONNECT",
+ "SMB_OPEN",
+ "SMB_DOWNLOAD",
+ "SMB_UPLOAD",
+ "SMB_CLOSE",
+ "SMB_TREE_DISCONNECT",
+ "SMB_DONE",
+ /* LAST */
+ };
+
+ if(req->state != newstate)
+ infof(data, "SMB request %p state change from %s to %s",
+ (void *)req, names[req->state], names[newstate]);
#endif
- req->state = newstate;
+ req->state = newstate;
+ }
+}
+
+static void smb_easy_dtor(void *key, size_t klen, void *entry)
+{
+ struct smb_request *req = entry;
+ (void)key;
+ (void)klen;
+ /* `req->path` points to somewhere in `struct smb_conn` which is
+ * kept at the connection meta. If the connection is destroyed first,
+ * req->path points to free'd memory. */
+ free(req);
+}
+
+static void smb_conn_dtor(void *key, size_t klen, void *entry)
+{
+ struct smb_conn *smbc = entry;
+ (void)key;
+ (void)klen;
+ Curl_safefree(smbc->share);
+ Curl_safefree(smbc->domain);
+ Curl_safefree(smbc->recv_buf);
+ Curl_safefree(smbc->send_buf);
+ free(smbc);
}
/* this should setup things in the connection, not in the easy
@@ -415,24 +471,34 @@ static void request_state(struct Curl_easy *data,
static CURLcode smb_setup_connection(struct Curl_easy *data,
struct connectdata *conn)
{
+ struct smb_conn *smbc;
struct smb_request *req;
+ /* Initialize the connection state */
+ smbc = calloc(1, sizeof(*smbc));
+ if(!smbc ||
+ Curl_conn_meta_set(conn, CURL_META_SMB_CONN, smbc, smb_conn_dtor))
+ return CURLE_OUT_OF_MEMORY;
+
/* Initialize the request state */
- data->req.p.smb = req = calloc(1, sizeof(struct smb_request));
- if(!req)
+ req = calloc(1, sizeof(*req));
+ if(!req ||
+ Curl_meta_set(data, CURL_META_SMB_EASY, req, smb_easy_dtor))
return CURLE_OUT_OF_MEMORY;
/* Parse the URL path */
- return smb_parse_url_path(data, conn);
+ return smb_parse_url_path(data, smbc, req);
}
static CURLcode smb_connect(struct Curl_easy *data, bool *done)
{
struct connectdata *conn = data->conn;
- struct smb_conn *smbc = &conn->proto.smbc;
+ struct smb_conn *smbc = Curl_conn_meta_get(conn, CURL_META_SMB_CONN);
char *slash;
(void) done;
+ if(!smbc)
+ return CURLE_FAILED_INIT;
/* Check we have a username and password to authenticate with */
if(!data->state.aptr.user)
@@ -472,10 +538,10 @@ static CURLcode smb_connect(struct Curl_easy *data, bool *done)
return CURLE_OK;
}
-static CURLcode smb_recv_message(struct Curl_easy *data, void **msg)
+static CURLcode smb_recv_message(struct Curl_easy *data,
+ struct smb_conn *smbc,
+ void **msg)
{
- struct connectdata *conn = data->conn;
- struct smb_conn *smbc = &conn->proto.smbc;
char *buf = smbc->recv_buf;
ssize_t bytes_read;
size_t nbt_size;
@@ -520,20 +586,17 @@ static CURLcode smb_recv_message(struct Curl_easy *data, void **msg)
return CURLE_OK;
}
-static void smb_pop_message(struct connectdata *conn)
+static void smb_pop_message(struct smb_conn *smbc)
{
- struct smb_conn *smbc = &conn->proto.smbc;
-
smbc->got = 0;
}
-static void smb_format_message(struct Curl_easy *data, struct smb_header *h,
+static void smb_format_message(struct smb_conn *smbc,
+ struct smb_request *req,
+ struct smb_header *h,
unsigned char cmd, size_t len)
{
- struct connectdata *conn = data->conn;
- struct smb_conn *smbc = &conn->proto.smbc;
- struct smb_request *req = data->req.p.smb;
- unsigned int pid;
+ const unsigned int pid = 0xbad71d; /* made up */
memset(h, 0, sizeof(*h));
h->nbt_length = htons((unsigned short) (sizeof(*h) - sizeof(unsigned int) +
@@ -544,16 +607,13 @@ static void smb_format_message(struct Curl_easy *data, struct smb_header *h,
h->flags2 = smb_swap16(SMB_FLAGS2_IS_LONG_NAME | SMB_FLAGS2_KNOWS_LONG_NAME);
h->uid = smb_swap16(smbc->uid);
h->tid = smb_swap16(req->tid);
- pid = (unsigned int)curlx_getpid();
h->pid_high = smb_swap16((unsigned short)(pid >> 16));
h->pid = smb_swap16((unsigned short) pid);
}
-static CURLcode smb_send(struct Curl_easy *data, size_t len,
- size_t upload_size)
+static CURLcode smb_send(struct Curl_easy *data, struct smb_conn *smbc,
+ size_t len, size_t upload_size)
{
- struct connectdata *conn = data->conn;
- struct smb_conn *smbc = &conn->proto.smbc;
size_t bytes_written;
CURLcode result;
@@ -571,10 +631,8 @@ static CURLcode smb_send(struct Curl_easy *data, size_t len,
return CURLE_OK;
}
-static CURLcode smb_flush(struct Curl_easy *data)
+static CURLcode smb_flush(struct Curl_easy *data, struct smb_conn *smbc)
{
- struct connectdata *conn = data->conn;
- struct smb_conn *smbc = &conn->proto.smbc;
size_t bytes_written;
size_t len = smbc->send_size - smbc->sent;
CURLcode result;
@@ -595,39 +653,46 @@ static CURLcode smb_flush(struct Curl_easy *data)
return CURLE_OK;
}
-static CURLcode smb_send_message(struct Curl_easy *data, unsigned char cmd,
+static CURLcode smb_send_message(struct Curl_easy *data,
+ struct smb_conn *smbc,
+ struct smb_request *req,
+ unsigned char cmd,
const void *msg, size_t msg_len)
{
- struct connectdata *conn = data->conn;
- struct smb_conn *smbc = &conn->proto.smbc;
-
- smb_format_message(data, (struct smb_header *)smbc->send_buf,
+ smb_format_message(smbc, req, (struct smb_header *)smbc->send_buf,
cmd, msg_len);
DEBUGASSERT((sizeof(struct smb_header) + msg_len) <= MAX_MESSAGE_SIZE);
memcpy(smbc->send_buf + sizeof(struct smb_header), msg, msg_len);
- return smb_send(data, sizeof(struct smb_header) + msg_len, 0);
+ return smb_send(data, smbc, sizeof(struct smb_header) + msg_len, 0);
}
-static CURLcode smb_send_negotiate(struct Curl_easy *data)
+static CURLcode smb_send_negotiate(struct Curl_easy *data,
+ struct smb_conn *smbc,
+ struct smb_request *req)
{
const char *msg = "\x00\x0c\x00\x02NT LM 0.12";
- return smb_send_message(data, SMB_COM_NEGOTIATE, msg, 15);
+ return smb_send_message(data, smbc, req, SMB_COM_NEGOTIATE, msg, 15);
}
static CURLcode smb_send_setup(struct Curl_easy *data)
{
struct connectdata *conn = data->conn;
- struct smb_conn *smbc = &conn->proto.smbc;
+ struct smb_conn *smbc = Curl_conn_meta_get(conn, CURL_META_SMB_CONN);
+ struct smb_request *req = Curl_meta_get(data, CURL_META_SMB_EASY);
struct smb_setup msg;
char *p = msg.bytes;
unsigned char lm_hash[21];
unsigned char lm[24];
unsigned char nt_hash[21];
unsigned char nt[24];
+ size_t byte_count;
+
+ if(!smbc || !req)
+ return CURLE_FAILED_INIT;
- const size_t byte_count = sizeof(lm) + sizeof(nt) +
+ byte_count = sizeof(lm) + sizeof(nt) +
strlen(smbc->user) + strlen(smbc->domain) +
strlen(CURL_OS) + strlen(CLIENTNAME) + 4; /* 4 null chars */
if(byte_count > sizeof(msg.bytes))
@@ -662,19 +727,20 @@ static CURLcode smb_send_setup(struct Curl_easy *data)
DEBUGASSERT(byte_count == (size_t)(p - msg.bytes));
msg.byte_count = smb_swap16((unsigned short)byte_count);
- return smb_send_message(data, SMB_COM_SETUP_ANDX, &msg,
+ return smb_send_message(data, smbc, req, SMB_COM_SETUP_ANDX, &msg,
sizeof(msg) - sizeof(msg.bytes) + byte_count);
}
-static CURLcode smb_send_tree_connect(struct Curl_easy *data)
+static CURLcode smb_send_tree_connect(struct Curl_easy *data,
+ struct smb_conn *smbc,
+ struct smb_request *req)
{
struct smb_tree_connect msg;
struct connectdata *conn = data->conn;
- struct smb_conn *smbc = &conn->proto.smbc;
char *p = msg.bytes;
-
const size_t byte_count = strlen(conn->host.name) + strlen(smbc->share) +
strlen(SERVICENAME) + 5; /* 2 nulls and 3 backslashes */
+
if(byte_count > sizeof(msg.bytes))
return CURLE_FILESIZE_EXCEEDED;
@@ -692,13 +758,14 @@ static CURLcode smb_send_tree_connect(struct Curl_easy *data)
DEBUGASSERT(byte_count == (size_t)(p - msg.bytes));
msg.byte_count = smb_swap16((unsigned short)byte_count);
- return smb_send_message(data, SMB_COM_TREE_CONNECT_ANDX, &msg,
+ return smb_send_message(data, smbc, req, SMB_COM_TREE_CONNECT_ANDX, &msg,
sizeof(msg) - sizeof(msg.bytes) + byte_count);
}
-static CURLcode smb_send_open(struct Curl_easy *data)
+static CURLcode smb_send_open(struct Curl_easy *data,
+ struct smb_conn *smbc,
+ struct smb_request *req)
{
- struct smb_request *req = data->req.p.smb;
struct smb_nt_create msg;
const size_t byte_count = strlen(req->path) + 1;
@@ -721,34 +788,37 @@ static CURLcode smb_send_open(struct Curl_easy *data)
msg.byte_count = smb_swap16((unsigned short) byte_count);
strcpy(msg.bytes, req->path);
- return smb_send_message(data, SMB_COM_NT_CREATE_ANDX, &msg,
+ return smb_send_message(data, smbc, req, SMB_COM_NT_CREATE_ANDX, &msg,
sizeof(msg) - sizeof(msg.bytes) + byte_count);
}
-static CURLcode smb_send_close(struct Curl_easy *data)
+static CURLcode smb_send_close(struct Curl_easy *data,
+ struct smb_conn *smbc,
+ struct smb_request *req)
{
- struct smb_request *req = data->req.p.smb;
struct smb_close msg;
memset(&msg, 0, sizeof(msg));
msg.word_count = SMB_WC_CLOSE;
msg.fid = smb_swap16(req->fid);
- return smb_send_message(data, SMB_COM_CLOSE, &msg, sizeof(msg));
+ return smb_send_message(data, smbc, req, SMB_COM_CLOSE, &msg, sizeof(msg));
}
-static CURLcode smb_send_tree_disconnect(struct Curl_easy *data)
+static CURLcode smb_send_tree_disconnect(struct Curl_easy *data,
+ struct smb_conn *smbc,
+ struct smb_request *req)
{
struct smb_tree_disconnect msg;
-
memset(&msg, 0, sizeof(msg));
-
- return smb_send_message(data, SMB_COM_TREE_DISCONNECT, &msg, sizeof(msg));
+ return smb_send_message(data, smbc, req, SMB_COM_TREE_DISCONNECT,
+ &msg, sizeof(msg));
}
-static CURLcode smb_send_read(struct Curl_easy *data)
+static CURLcode smb_send_read(struct Curl_easy *data,
+ struct smb_conn *smbc,
+ struct smb_request *req)
{
- struct smb_request *req = data->req.p.smb;
curl_off_t offset = data->req.offset;
struct smb_read msg;
@@ -761,15 +831,15 @@ static CURLcode smb_send_read(struct Curl_easy *data)
msg.min_bytes = smb_swap16(MAX_PAYLOAD_SIZE);
msg.max_bytes = smb_swap16(MAX_PAYLOAD_SIZE);
- return smb_send_message(data, SMB_COM_READ_ANDX, &msg, sizeof(msg));
+ return smb_send_message(data, smbc, req, SMB_COM_READ_ANDX,
+ &msg, sizeof(msg));
}
-static CURLcode smb_send_write(struct Curl_easy *data)
+static CURLcode smb_send_write(struct Curl_easy *data,
+ struct smb_conn *smbc,
+ struct smb_request *req)
{
- struct connectdata *conn = data->conn;
- struct smb_conn *smbc = &conn->proto.smbc;
struct smb_write *msg;
- struct smb_request *req = data->req.p.smb;
curl_off_t offset = data->req.offset;
curl_off_t upload_size = data->req.size - data->req.bytecount;
@@ -787,16 +857,15 @@ static CURLcode smb_send_write(struct Curl_easy *data)
msg->data_offset = smb_swap16(sizeof(*msg) - sizeof(unsigned int));
msg->byte_count = smb_swap16((unsigned short) (upload_size + 1));
- smb_format_message(data, &msg->h, SMB_COM_WRITE_ANDX,
+ smb_format_message(smbc, req, &msg->h, SMB_COM_WRITE_ANDX,
sizeof(*msg) - sizeof(msg->h) + (size_t) upload_size);
- return smb_send(data, sizeof(*msg), (size_t) upload_size);
+ return smb_send(data, smbc, sizeof(*msg), (size_t) upload_size);
}
-static CURLcode smb_send_and_recv(struct Curl_easy *data, void **msg)
+static CURLcode smb_send_and_recv(struct Curl_easy *data,
+ struct smb_conn *smbc, void **msg)
{
- struct connectdata *conn = data->conn;
- struct smb_conn *smbc = &conn->proto.smbc;
CURLcode result;
*msg = NULL; /* if it returns early */
@@ -819,7 +888,7 @@ static CURLcode smb_send_and_recv(struct Curl_easy *data, void **msg)
/* Check if there is data to send */
if(smbc->send_size) {
- result = smb_flush(data);
+ result = smb_flush(data, smbc);
if(result)
return result;
}
@@ -828,18 +897,22 @@ static CURLcode smb_send_and_recv(struct Curl_easy *data, void **msg)
if(smbc->send_size || smbc->upload_size)
return CURLE_AGAIN;
- return smb_recv_message(data, msg);
+ return smb_recv_message(data, smbc, msg);
}
static CURLcode smb_connection_state(struct Curl_easy *data, bool *done)
{
struct connectdata *conn = data->conn;
- struct smb_conn *smbc = &conn->proto.smbc;
+ struct smb_conn *smbc = Curl_conn_meta_get(conn, CURL_META_SMB_CONN);
+ struct smb_request *req = Curl_meta_get(data, CURL_META_SMB_EASY);
struct smb_negotiate_response *nrsp;
struct smb_header *h;
CURLcode result;
void *msg = NULL;
+ if(!smbc || !req)
+ return CURLE_FAILED_INIT;
+
if(smbc->state == SMB_CONNECTING) {
#ifdef USE_SSL
if(Curl_conn_is_ssl(conn, FIRSTSOCKET)) {
@@ -852,17 +925,17 @@ static CURLcode smb_connection_state(struct Curl_easy *data, bool *done)
}
#endif
- result = smb_send_negotiate(data);
+ result = smb_send_negotiate(data, smbc, req);
if(result) {
connclose(conn, "SMB: failed to send negotiate message");
return result;
}
- conn_state(data, SMB_NEGOTIATE);
+ conn_state(data, smbc, SMB_NEGOTIATE);
}
/* Send the previous message and check for a response */
- result = smb_send_and_recv(data, &msg);
+ result = smb_send_and_recv(data, smbc, &msg);
if(result && result != CURLE_AGAIN) {
connclose(conn, "SMB: failed to communicate");
return result;
@@ -897,7 +970,7 @@ static CURLcode smb_connection_state(struct Curl_easy *data, bool *done)
connclose(conn, "SMB: failed to send setup message");
return result;
}
- conn_state(data, SMB_SETUP);
+ conn_state(data, smbc, SMB_SETUP);
break;
case SMB_SETUP:
@@ -906,16 +979,16 @@ static CURLcode smb_connection_state(struct Curl_easy *data, bool *done)
return CURLE_LOGIN_DENIED;
}
smbc->uid = smb_swap16(h->uid);
- conn_state(data, SMB_CONNECTED);
+ conn_state(data, smbc, SMB_CONNECTED);
*done = TRUE;
break;
default:
- smb_pop_message(conn);
+ smb_pop_message(smbc);
return CURLE_OK; /* ignore */
}
- smb_pop_message(conn);
+ smb_pop_message(smbc);
return CURLE_OK;
}
@@ -926,24 +999,28 @@ static CURLcode smb_connection_state(struct Curl_easy *data, bool *done)
*/
static void get_posix_time(time_t *out, curl_off_t timestamp)
{
- timestamp -= CURL_OFF_T_C(116444736000000000);
- timestamp /= 10000000;
+ if(timestamp >= CURL_OFF_T_C(116444736000000000)) {
+ timestamp -= CURL_OFF_T_C(116444736000000000);
+ timestamp /= 10000000;
#if SIZEOF_TIME_T < SIZEOF_CURL_OFF_T
- if(timestamp > TIME_T_MAX)
- *out = TIME_T_MAX;
- else if(timestamp < TIME_T_MIN)
- *out = TIME_T_MIN;
- else
+ if(timestamp > TIME_T_MAX)
+ *out = TIME_T_MAX;
+ else if(timestamp < TIME_T_MIN)
+ *out = TIME_T_MIN;
+ else
#endif
- *out = (time_t) timestamp;
+ *out = (time_t) timestamp;
+ }
+ else
+ *out = 0;
}
static CURLcode smb_request_state(struct Curl_easy *data, bool *done)
{
struct connectdata *conn = data->conn;
- struct smb_request *req = data->req.p.smb;
+ struct smb_conn *smbc = Curl_conn_meta_get(conn, CURL_META_SMB_CONN);
+ struct smb_request *req = Curl_meta_get(data, CURL_META_SMB_EASY);
struct smb_header *h;
- struct smb_conn *smbc = &conn->proto.smbc;
enum smb_req_state next_state = SMB_DONE;
unsigned short len;
unsigned short off;
@@ -951,6 +1028,9 @@ static CURLcode smb_request_state(struct Curl_easy *data, bool *done)
void *msg = NULL;
const struct smb_nt_create_response *smb_m;
+ if(!smbc || !req)
+ return CURLE_FAILED_INIT;
+
if(data->state.upload && (data->state.infilesize < 0)) {
failf(data, "SMB upload needs to know the size up front");
return CURLE_SEND_ERROR;
@@ -958,7 +1038,7 @@ static CURLcode smb_request_state(struct Curl_easy *data, bool *done)
/* Start the request */
if(req->state == SMB_REQUESTING) {
- result = smb_send_tree_connect(data);
+ result = smb_send_tree_connect(data, smbc, req);
if(result) {
connclose(conn, "SMB: failed to send tree connect message");
return result;
@@ -968,7 +1048,7 @@ static CURLcode smb_request_state(struct Curl_easy *data, bool *done)
}
/* Send the previous message and check for a response */
- result = smb_send_and_recv(data, &msg);
+ result = smb_send_and_recv(data, smbc, &msg);
if(result && result != CURLE_AGAIN) {
connclose(conn, "SMB: failed to communicate");
return result;
@@ -1078,31 +1158,31 @@ static CURLcode smb_request_state(struct Curl_easy *data, bool *done)
break;
default:
- smb_pop_message(conn);
+ smb_pop_message(smbc);
return CURLE_OK; /* ignore */
}
- smb_pop_message(conn);
+ smb_pop_message(smbc);
switch(next_state) {
case SMB_OPEN:
- result = smb_send_open(data);
+ result = smb_send_open(data, smbc, req);
break;
case SMB_DOWNLOAD:
- result = smb_send_read(data);
+ result = smb_send_read(data, smbc, req);
break;
case SMB_UPLOAD:
- result = smb_send_write(data);
+ result = smb_send_write(data, smbc, req);
break;
case SMB_CLOSE:
- result = smb_send_close(data);
+ result = smb_send_close(data, smbc, req);
break;
case SMB_TREE_DISCONNECT:
- result = smb_send_tree_disconnect(data);
+ result = smb_send_tree_disconnect(data, smbc, req);
break;
case SMB_DONE:
@@ -1124,19 +1204,6 @@ static CURLcode smb_request_state(struct Curl_easy *data, bool *done)
return CURLE_OK;
}
-static CURLcode smb_disconnect(struct Curl_easy *data,
- struct connectdata *conn, bool dead)
-{
- struct smb_conn *smbc = &conn->proto.smbc;
- (void) dead;
- (void) data;
- Curl_safefree(smbc->share);
- Curl_safefree(smbc->domain);
- Curl_safefree(smbc->recv_buf);
- Curl_safefree(smbc->send_buf);
- return CURLE_OK;
-}
-
static int smb_getsock(struct Curl_easy *data,
struct connectdata *conn, curl_socket_t *socks)
{
@@ -1148,26 +1215,26 @@ static int smb_getsock(struct Curl_easy *data,
static CURLcode smb_do(struct Curl_easy *data, bool *done)
{
struct connectdata *conn = data->conn;
- struct smb_conn *smbc = &conn->proto.smbc;
+ struct smb_conn *smbc = Curl_conn_meta_get(conn, CURL_META_SMB_CONN);
*done = FALSE;
- if(smbc->share) {
+ if(!smbc)
+ return CURLE_FAILED_INIT;
+ if(smbc->share)
return CURLE_OK;
- }
return CURLE_URL_MALFORMAT;
}
static CURLcode smb_parse_url_path(struct Curl_easy *data,
- struct connectdata *conn)
+ struct smb_conn *smbc,
+ struct smb_request *req)
{
- struct smb_request *req = data->req.p.smb;
- struct smb_conn *smbc = &conn->proto.smbc;
char *path;
char *slash;
+ CURLcode result;
/* URL decode the path */
- CURLcode result = Curl_urldecode(data->state.up.path, 0, &path, NULL,
- REJECT_CTRL);
+ result = Curl_urldecode(data->state.up.path, 0, &path, NULL, REJECT_CTRL);
if(result)
return result;
diff --git a/libs/libcurl/src/smb.h b/libs/libcurl/src/smb.h
index 09281a3adb..6fbdf01066 100644
--- a/libs/libcurl/src/smb.h
+++ b/libs/libcurl/src/smb.h
@@ -25,30 +25,6 @@
*
***************************************************************************/
-enum smb_conn_state {
- SMB_NOT_CONNECTED = 0,
- SMB_CONNECTING,
- SMB_NEGOTIATE,
- SMB_SETUP,
- SMB_CONNECTED
-};
-
-struct smb_conn {
- enum smb_conn_state state;
- char *user;
- char *domain;
- char *share;
- unsigned char challenge[8];
- unsigned int session_key;
- unsigned short uid;
- char *recv_buf;
- char *send_buf;
- size_t upload_size;
- size_t send_size;
- size_t sent;
- size_t got;
-};
-
#if !defined(CURL_DISABLE_SMB) && defined(USE_CURL_NTLM_CORE) && \
(SIZEOF_CURL_OFF_T > 4)
diff --git a/libs/libcurl/src/smtp.c b/libs/libcurl/src/smtp.c
index e35b22f4b1..b7c9ba8558 100644
--- a/libs/libcurl/src/smtp.c
+++ b/libs/libcurl/src/smtp.c
@@ -78,17 +78,79 @@
#include "curl_gethostname.h"
#include "bufref.h"
#include "curl_sasl.h"
-#include "warnless.h"
+#include "curlx/warnless.h"
#include "idn.h"
-#include "strparse.h"
+#include "curlx/strparse.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h"
#include "memdebug.h"
+/* meta key for storing protocol meta at easy handle */
+#define CURL_META_SMTP_EASY "meta:proto:smtp:easy"
+/* meta key for storing protocol meta at connection */
+#define CURL_META_SMTP_CONN "meta:proto:smtp:conn"
+
+/****************************************************************************
+ * SMTP unique setup
+ ***************************************************************************/
+typedef enum {
+ SMTP_STOP, /* do nothing state, stops the state machine */
+ SMTP_SERVERGREET, /* waiting for the initial greeting immediately after
+ a connect */
+ SMTP_EHLO,
+ SMTP_HELO,
+ SMTP_STARTTLS,
+ SMTP_UPGRADETLS, /* asynchronously upgrade the connection to SSL/TLS
+ (multi mode only) */
+ SMTP_AUTH,
+ SMTP_COMMAND, /* VRFY, EXPN, NOOP, RSET and HELP */
+ SMTP_MAIL, /* MAIL FROM */
+ SMTP_RCPT, /* RCPT TO */
+ SMTP_DATA,
+ SMTP_POSTDATA,
+ SMTP_QUIT,
+ SMTP_LAST /* never used */
+} smtpstate;
+
+/* smtp_conn is used for struct connection-oriented data in the connectdata
+ struct */
+struct smtp_conn {
+ struct pingpong pp;
+ struct SASL sasl; /* SASL-related storage */
+ smtpstate state; /* Always use smtp.c:state() to change state! */
+ char *domain; /* Client address/name to send in the EHLO */
+ BIT(ssldone); /* Is connect() over SSL done? */
+ BIT(tls_supported); /* StartTLS capability supported by server */
+ BIT(size_supported); /* If server supports SIZE extension according to
+ RFC 1870 */
+ BIT(utf8_supported); /* If server supports SMTPUTF8 extension according
+ to RFC 6531 */
+ BIT(auth_supported); /* AUTH capability supported by server */
+};
+
+/* This SMTP struct is used in the Curl_easy. All SMTP data that is
+ connection-oriented must be in smtp_conn to properly deal with the fact that
+ perhaps the Curl_easy is changed between the times the connection is
+ used. */
+struct SMTP {
+ curl_pp_transfer transfer;
+ char *custom; /* Custom Request */
+ struct curl_slist *rcpt; /* Recipient list */
+ int rcpt_last_error; /* The last error received for RCPT TO command */
+ size_t eob; /* Number of bytes of the EOB (End Of Body) that
+ have been received so far */
+ BIT(rcpt_had_ok); /* Whether any of RCPT TO commands (depends on
+ total number of recipients) succeeded so far */
+ BIT(trailing_crlf); /* Specifies if the trailing CRLF is present */
+};
+
/* Local API functions */
-static CURLcode smtp_regular_transfer(struct Curl_easy *data, bool *done);
+static CURLcode smtp_regular_transfer(struct Curl_easy *data,
+ struct smtp_conn *smtpc,
+ struct SMTP *smtp,
+ bool *done);
static CURLcode smtp_do(struct Curl_easy *data, bool *done);
static CURLcode smtp_done(struct Curl_easy *data, CURLcode status,
bool premature);
@@ -101,9 +163,12 @@ static int smtp_getsock(struct Curl_easy *data,
static CURLcode smtp_doing(struct Curl_easy *data, bool *dophase_done);
static CURLcode smtp_setup_connection(struct Curl_easy *data,
struct connectdata *conn);
-static CURLcode smtp_parse_url_options(struct connectdata *conn);
-static CURLcode smtp_parse_url_path(struct Curl_easy *data);
-static CURLcode smtp_parse_custom_request(struct Curl_easy *data);
+static CURLcode smtp_parse_url_options(struct connectdata *conn,
+ struct smtp_conn *smtpc);
+static CURLcode smtp_parse_url_path(struct Curl_easy *data,
+ struct smtp_conn *smtpc);
+static CURLcode smtp_parse_custom_request(struct Curl_easy *data,
+ struct SMTP *smtp);
static CURLcode smtp_parse_address(const char *fqma,
char **address, struct hostname *host);
static CURLcode smtp_perform_auth(struct Curl_easy *data, const char *mech,
@@ -201,10 +266,14 @@ static const struct SASLproto saslsmtp = {
static bool smtp_endofresp(struct Curl_easy *data, struct connectdata *conn,
const char *line, size_t len, int *resp)
{
- struct smtp_conn *smtpc = &conn->proto.smtpc;
+ struct smtp_conn *smtpc = Curl_conn_meta_get(conn, CURL_META_SMTP_CONN);
bool result = FALSE;
(void)data;
+ DEBUGASSERT(smtpc);
+ if(!smtpc)
+ return FALSE;
+
/* Nothing for us */
if(len < 4 || !ISDIGIT(line[0]) || !ISDIGIT(line[1]) || !ISDIGIT(line[2]))
return FALSE;
@@ -220,7 +289,7 @@ static bool smtp_endofresp(struct Curl_easy *data, struct connectdata *conn,
result = TRUE;
memcpy(tmpline, line, (len == 5 ? 5 : 3));
tmpline[len == 5 ? 5 : 3 ] = 0;
- if(Curl_str_number(&p, &code, len == 5 ? 99999 : 999))
+ if(curlx_str_number(&p, &code, len == 5 ? 99999 : 999))
return FALSE;
*resp = (int) code;
@@ -246,9 +315,16 @@ static bool smtp_endofresp(struct Curl_easy *data, struct connectdata *conn,
*/
static CURLcode smtp_get_message(struct Curl_easy *data, struct bufref *out)
{
- char *message = Curl_dyn_ptr(&data->conn->proto.smtpc.pp.recvbuf);
- size_t len = data->conn->proto.smtpc.pp.nfinal;
+ struct smtp_conn *smtpc =
+ Curl_conn_meta_get(data->conn, CURL_META_SMTP_CONN);
+ char *message;
+ size_t len;
+
+ if(!smtpc)
+ return CURLE_FAILED_INIT;
+ message = curlx_dyn_ptr(&smtpc->pp.recvbuf);
+ len = smtpc->pp.nfinal;
if(len > 4) {
/* Find the start of the message */
len -= 4;
@@ -278,9 +354,10 @@ static CURLcode smtp_get_message(struct Curl_easy *data, struct bufref *out)
*
* This is the ONLY way to change SMTP state!
*/
-static void smtp_state(struct Curl_easy *data, smtpstate newstate)
+static void smtp_state(struct Curl_easy *data,
+ struct smtp_conn *smtpc,
+ smtpstate newstate)
{
- struct smtp_conn *smtpc = &data->conn->proto.smtpc;
#if !defined(CURL_DISABLE_VERBOSE_STRINGS)
/* for debug purposes */
static const char * const names[] = {
@@ -315,11 +392,10 @@ static void smtp_state(struct Curl_easy *data, smtpstate newstate)
* Sends the EHLO command to not only initialise communication with the ESMTP
* server but to also obtain a list of server side supported capabilities.
*/
-static CURLcode smtp_perform_ehlo(struct Curl_easy *data)
+static CURLcode smtp_perform_ehlo(struct Curl_easy *data,
+ struct smtp_conn *smtpc)
{
CURLcode result = CURLE_OK;
- struct connectdata *conn = data->conn;
- struct smtp_conn *smtpc = &conn->proto.smtpc;
smtpc->sasl.authmechs = SASL_AUTH_NONE; /* No known auth. mechanism yet */
smtpc->sasl.authused = SASL_AUTH_NONE; /* Clear the authentication mechanism
@@ -331,7 +407,7 @@ static CURLcode smtp_perform_ehlo(struct Curl_easy *data)
result = Curl_pp_sendf(data, &smtpc->pp, "EHLO %s", smtpc->domain);
if(!result)
- smtp_state(data, SMTP_EHLO);
+ smtp_state(data, smtpc, SMTP_EHLO);
return result;
}
@@ -343,10 +419,9 @@ static CURLcode smtp_perform_ehlo(struct Curl_easy *data)
* Sends the HELO command to initialise communication with the SMTP server.
*/
static CURLcode smtp_perform_helo(struct Curl_easy *data,
- struct connectdata *conn)
+ struct smtp_conn *smtpc)
{
CURLcode result = CURLE_OK;
- struct smtp_conn *smtpc = &conn->proto.smtpc;
smtpc->sasl.authused = SASL_AUTH_NONE; /* No authentication mechanism used
in smtp connections */
@@ -355,7 +430,7 @@ static CURLcode smtp_perform_helo(struct Curl_easy *data,
result = Curl_pp_sendf(data, &smtpc->pp, "HELO %s", smtpc->domain);
if(!result)
- smtp_state(data, SMTP_HELO);
+ smtp_state(data, smtpc, SMTP_HELO);
return result;
}
@@ -367,14 +442,13 @@ static CURLcode smtp_perform_helo(struct Curl_easy *data,
* Sends the STLS command to start the upgrade to TLS.
*/
static CURLcode smtp_perform_starttls(struct Curl_easy *data,
- struct connectdata *conn)
+ struct smtp_conn *smtpc)
{
/* Send the STARTTLS command */
- CURLcode result = Curl_pp_sendf(data, &conn->proto.smtpc.pp,
- "%s", "STARTTLS");
+ CURLcode result = Curl_pp_sendf(data, &smtpc->pp, "%s", "STARTTLS");
if(!result)
- smtp_state(data, SMTP_STARTTLS);
+ smtp_state(data, smtpc, SMTP_STARTTLS);
return result;
}
@@ -385,12 +459,12 @@ static CURLcode smtp_perform_starttls(struct Curl_easy *data,
*
* Performs the upgrade to TLS.
*/
-static CURLcode smtp_perform_upgrade_tls(struct Curl_easy *data)
+static CURLcode smtp_perform_upgrade_tls(struct Curl_easy *data,
+ struct smtp_conn *smtpc)
{
#ifdef USE_SSL
/* Start the SSL connection */
struct connectdata *conn = data->conn;
- struct smtp_conn *smtpc = &conn->proto.smtpc;
CURLcode result;
bool ssldone = FALSE;
@@ -410,12 +484,13 @@ static CURLcode smtp_perform_upgrade_tls(struct Curl_easy *data)
if(!result && ssldone) {
smtpc->ssldone = ssldone;
/* perform EHLO now, changes smpt->state out of SMTP_UPGRADETLS */
- result = smtp_perform_ehlo(data);
+ result = smtp_perform_ehlo(data, smtpc);
}
out:
return result;
#else
(void)data;
+ (void)smtpc;
return CURLE_NOT_BUILT_IN;
#endif
}
@@ -432,9 +507,13 @@ static CURLcode smtp_perform_auth(struct Curl_easy *data,
const struct bufref *initresp)
{
CURLcode result = CURLE_OK;
- struct smtp_conn *smtpc = &data->conn->proto.smtpc;
+ struct smtp_conn *smtpc =
+ Curl_conn_meta_get(data->conn, CURL_META_SMTP_CONN);
const char *ir = (const char *) Curl_bufref_ptr(initresp);
+ if(!smtpc)
+ return CURLE_FAILED_INIT;
+
if(ir) { /* AUTH <mech> ...<crlf> */
/* Send the AUTH command with the initial response */
result = Curl_pp_sendf(data, &smtpc->pp, "AUTH %s %s", mech, ir);
@@ -457,10 +536,12 @@ static CURLcode smtp_continue_auth(struct Curl_easy *data,
const char *mech,
const struct bufref *resp)
{
- struct smtp_conn *smtpc = &data->conn->proto.smtpc;
+ struct smtp_conn *smtpc =
+ Curl_conn_meta_get(data->conn, CURL_META_SMTP_CONN);
(void)mech;
-
+ if(!smtpc)
+ return CURLE_FAILED_INIT;
return Curl_pp_sendf(data, &smtpc->pp,
"%s", (const char *) Curl_bufref_ptr(resp));
}
@@ -473,10 +554,12 @@ static CURLcode smtp_continue_auth(struct Curl_easy *data,
*/
static CURLcode smtp_cancel_auth(struct Curl_easy *data, const char *mech)
{
- struct smtp_conn *smtpc = &data->conn->proto.smtpc;
+ struct smtp_conn *smtpc =
+ Curl_conn_meta_get(data->conn, CURL_META_SMTP_CONN);
(void)mech;
-
+ if(!smtpc)
+ return CURLE_FAILED_INIT;
return Curl_pp_sendf(data, &smtpc->pp, "*");
}
@@ -487,18 +570,17 @@ static CURLcode smtp_cancel_auth(struct Curl_easy *data, const char *mech)
* Initiates the authentication sequence, with the appropriate SASL
* authentication mechanism.
*/
-static CURLcode smtp_perform_authentication(struct Curl_easy *data)
+static CURLcode smtp_perform_authentication(struct Curl_easy *data,
+ struct smtp_conn *smtpc)
{
CURLcode result = CURLE_OK;
- struct connectdata *conn = data->conn;
- struct smtp_conn *smtpc = &conn->proto.smtpc;
saslprogress progress;
/* Check we have enough data to authenticate with, and the
server supports authentication, and end the connect phase if not */
if(!smtpc->auth_supported ||
!Curl_sasl_can_authenticate(&smtpc->sasl, data)) {
- smtp_state(data, SMTP_STOP);
+ smtp_state(data, smtpc, SMTP_STOP);
return result;
}
@@ -507,12 +589,9 @@ static CURLcode smtp_perform_authentication(struct Curl_easy *data)
if(!result) {
if(progress == SASL_INPROGRESS)
- smtp_state(data, SMTP_AUTH);
- else {
- /* Other mechanisms not supported */
- infof(data, "No known authentication mechanisms supported");
- result = CURLE_LOGIN_DENIED;
- }
+ smtp_state(data, smtpc, SMTP_AUTH);
+ else
+ result = Curl_sasl_is_blocked(&smtpc->sasl, data);
}
return result;
@@ -524,11 +603,11 @@ static CURLcode smtp_perform_authentication(struct Curl_easy *data)
*
* Sends a SMTP based command.
*/
-static CURLcode smtp_perform_command(struct Curl_easy *data)
+static CURLcode smtp_perform_command(struct Curl_easy *data,
+ struct smtp_conn *smtpc,
+ struct SMTP *smtp)
{
CURLcode result = CURLE_OK;
- struct connectdata *conn = data->conn;
- struct SMTP *smtp = data->req.p.smtp;
if(smtp->rcpt) {
/* We notify the server we are sending UTF-8 data if a) it supports the
@@ -550,13 +629,13 @@ static CURLcode smtp_perform_command(struct Curl_easy *data)
/* Establish whether we should report SMTPUTF8 to the server for this
mailbox as per RFC-6531 sect. 3.1 point 6 */
- utf8 = (conn->proto.smtpc.utf8_supported) &&
+ utf8 = (smtpc->utf8_supported) &&
((host.encalloc) || (!Curl_is_ASCII_name(address)) ||
(!Curl_is_ASCII_name(host.name)));
/* Send the VRFY command (Note: The hostname part may be absent when the
host is a local system) */
- result = Curl_pp_sendf(data, &conn->proto.smtpc.pp, "VRFY %s%s%s%s",
+ result = Curl_pp_sendf(data, &smtpc->pp, "VRFY %s%s%s%s",
address,
host.name ? "@" : "",
host.name ? host.name : "",
@@ -568,11 +647,10 @@ static CURLcode smtp_perform_command(struct Curl_easy *data)
else {
/* Establish whether we should report that we support SMTPUTF8 for EXPN
commands to the server as per RFC-6531 sect. 3.1 point 6 */
- utf8 = (conn->proto.smtpc.utf8_supported) &&
- (!strcmp(smtp->custom, "EXPN"));
+ utf8 = (smtpc->utf8_supported) && (!strcmp(smtp->custom, "EXPN"));
/* Send the custom recipient based command such as the EXPN command */
- result = Curl_pp_sendf(data, &conn->proto.smtpc.pp,
+ result = Curl_pp_sendf(data, &smtpc->pp,
"%s %s%s", smtp->custom,
smtp->rcpt->data,
utf8 ? " SMTPUTF8" : "");
@@ -580,12 +658,12 @@ static CURLcode smtp_perform_command(struct Curl_easy *data)
}
else
/* Send the non-recipient based command such as HELP */
- result = Curl_pp_sendf(data, &conn->proto.smtpc.pp, "%s",
+ result = Curl_pp_sendf(data, &smtpc->pp, "%s",
smtp->custom && smtp->custom[0] != '\0' ?
smtp->custom : "HELP");
if(!result)
- smtp_state(data, SMTP_COMMAND);
+ smtp_state(data, smtpc, SMTP_COMMAND);
return result;
}
@@ -596,13 +674,14 @@ static CURLcode smtp_perform_command(struct Curl_easy *data)
*
* Sends an MAIL command to initiate the upload of a message.
*/
-static CURLcode smtp_perform_mail(struct Curl_easy *data)
+static CURLcode smtp_perform_mail(struct Curl_easy *data,
+ struct smtp_conn *smtpc,
+ struct SMTP *smtp)
{
char *from = NULL;
char *auth = NULL;
char *size = NULL;
CURLcode result = CURLE_OK;
- struct connectdata *conn = data->conn;
/* We notify the server we are sending UTF-8 data if a) it supports the
SMTPUTF8 extension and b) The mailbox contains UTF-8 characters, in
@@ -624,7 +703,7 @@ static CURLcode smtp_perform_mail(struct Curl_easy *data)
/* Establish whether we should report SMTPUTF8 to the server for this
mailbox as per RFC-6531 sect. 3.1 point 4 and sect. 3.4 */
- utf8 = (conn->proto.smtpc.utf8_supported) &&
+ utf8 = (smtpc->utf8_supported) &&
((host.encalloc) || (!Curl_is_ASCII_name(address)) ||
(!Curl_is_ASCII_name(host.name)));
@@ -650,7 +729,7 @@ static CURLcode smtp_perform_mail(struct Curl_easy *data)
}
/* Calculate the optional AUTH parameter */
- if(data->set.str[STRING_MAIL_AUTH] && conn->proto.smtpc.sasl.authused) {
+ if(data->set.str[STRING_MAIL_AUTH] && smtpc->sasl.authused) {
if(data->set.str[STRING_MAIL_AUTH][0] != '\0') {
char *address = NULL;
struct hostname host = { NULL, NULL, NULL, NULL };
@@ -664,7 +743,7 @@ static CURLcode smtp_perform_mail(struct Curl_easy *data)
/* Establish whether we should report SMTPUTF8 to the server for this
mailbox as per RFC-6531 sect. 3.1 point 4 and sect. 3.4 */
- if((!utf8) && (conn->proto.smtpc.utf8_supported) &&
+ if((!utf8) && (smtpc->utf8_supported) &&
((host.encalloc) || (!Curl_is_ASCII_name(address)) ||
(!Curl_is_ASCII_name(host.name))))
utf8 = TRUE;
@@ -721,7 +800,7 @@ static CURLcode smtp_perform_mail(struct Curl_easy *data)
}
/* Calculate the optional SIZE parameter */
- if(conn->proto.smtpc.size_supported && data->state.infilesize > 0) {
+ if(smtpc->size_supported && data->state.infilesize > 0) {
size = aprintf("%" FMT_OFF_T, data->state.infilesize);
if(!size) {
@@ -734,8 +813,7 @@ static CURLcode smtp_perform_mail(struct Curl_easy *data)
based address then quickly scan through the recipient list and check if
any there do, as we need to correctly identify our support for SMTPUTF8
in the envelope, as per RFC-6531 sect. 3.4 */
- if(conn->proto.smtpc.utf8_supported && !utf8) {
- struct SMTP *smtp = data->req.p.smtp;
+ if(smtpc->utf8_supported && !utf8) {
struct curl_slist *rcpt = smtp->rcpt;
while(rcpt && !utf8) {
@@ -753,7 +831,7 @@ static CURLcode smtp_perform_mail(struct Curl_easy *data)
goto out;
/* Send the MAIL command */
- result = Curl_pp_sendf(data, &conn->proto.smtpc.pp,
+ result = Curl_pp_sendf(data, &smtpc->pp,
"MAIL FROM:%s%s%s%s%s%s",
from, /* Mandatory */
auth ? " AUTH=" : "", /* Optional on AUTH support */
@@ -769,7 +847,7 @@ out:
free(size);
if(!result)
- smtp_state(data, SMTP_MAIL);
+ smtp_state(data, smtpc, SMTP_MAIL);
return result;
}
@@ -781,11 +859,11 @@ out:
* Sends a RCPT TO command for a given recipient as part of the message upload
* process.
*/
-static CURLcode smtp_perform_rcpt_to(struct Curl_easy *data)
+static CURLcode smtp_perform_rcpt_to(struct Curl_easy *data,
+ struct smtp_conn *smtpc,
+ struct SMTP *smtp)
{
CURLcode result = CURLE_OK;
- struct connectdata *conn = data->conn;
- struct SMTP *smtp = data->req.p.smtp;
char *address = NULL;
struct hostname host = { NULL, NULL, NULL, NULL };
@@ -798,19 +876,18 @@ static CURLcode smtp_perform_rcpt_to(struct Curl_easy *data)
/* Send the RCPT TO command */
if(host.name)
- result = Curl_pp_sendf(data, &conn->proto.smtpc.pp, "RCPT TO:<%s@%s>",
+ result = Curl_pp_sendf(data, &smtpc->pp, "RCPT TO:<%s@%s>",
address, host.name);
else
/* An invalid mailbox was provided but we will simply let the server worry
about that and reply with a 501 error */
- result = Curl_pp_sendf(data, &conn->proto.smtpc.pp, "RCPT TO:<%s>",
- address);
+ result = Curl_pp_sendf(data, &smtpc->pp, "RCPT TO:<%s>", address);
Curl_free_idnconverted_hostname(&host);
free(address);
if(!result)
- smtp_state(data, SMTP_RCPT);
+ smtp_state(data, smtpc, SMTP_RCPT);
return result;
}
@@ -822,19 +899,20 @@ static CURLcode smtp_perform_rcpt_to(struct Curl_easy *data)
* Performs the quit action prior to sclose() being called.
*/
static CURLcode smtp_perform_quit(struct Curl_easy *data,
- struct connectdata *conn)
+ struct smtp_conn *smtpc)
{
/* Send the QUIT command */
- CURLcode result = Curl_pp_sendf(data, &conn->proto.smtpc.pp, "%s", "QUIT");
+ CURLcode result = Curl_pp_sendf(data, &smtpc->pp, "%s", "QUIT");
if(!result)
- smtp_state(data, SMTP_QUIT);
+ smtp_state(data, smtpc, SMTP_QUIT);
return result;
}
/* For the initial server greeting */
static CURLcode smtp_state_servergreet_resp(struct Curl_easy *data,
+ struct smtp_conn *smtpc,
int smtpcode,
smtpstate instate)
{
@@ -846,13 +924,14 @@ static CURLcode smtp_state_servergreet_resp(struct Curl_easy *data,
result = CURLE_WEIRD_SERVER_REPLY;
}
else
- result = smtp_perform_ehlo(data);
+ result = smtp_perform_ehlo(data, smtpc);
return result;
}
/* For STARTTLS responses */
static CURLcode smtp_state_starttls_resp(struct Curl_easy *data,
+ struct smtp_conn *smtpc,
int smtpcode,
smtpstate instate)
{
@@ -860,7 +939,7 @@ static CURLcode smtp_state_starttls_resp(struct Curl_easy *data,
(void)instate; /* no use for this yet */
/* Pipelining in response is forbidden. */
- if(data->conn->proto.smtpc.pp.overflow)
+ if(smtpc->pp.overflow)
return CURLE_WEIRD_SERVER_REPLY;
if(smtpcode != 220) {
@@ -869,30 +948,30 @@ static CURLcode smtp_state_starttls_resp(struct Curl_easy *data,
result = CURLE_USE_SSL_FAILED;
}
else
- result = smtp_perform_authentication(data);
+ result = smtp_perform_authentication(data, smtpc);
}
else
- smtp_state(data, SMTP_UPGRADETLS);
+ smtp_state(data, smtpc, SMTP_UPGRADETLS);
return result;
}
/* For EHLO responses */
static CURLcode smtp_state_ehlo_resp(struct Curl_easy *data,
- struct connectdata *conn, int smtpcode,
+ struct smtp_conn *smtpc,
+ int smtpcode,
smtpstate instate)
{
CURLcode result = CURLE_OK;
- struct smtp_conn *smtpc = &conn->proto.smtpc;
- const char *line = Curl_dyn_ptr(&smtpc->pp.recvbuf);
+ const char *line = curlx_dyn_ptr(&smtpc->pp.recvbuf);
size_t len = smtpc->pp.nfinal;
(void)instate; /* no use for this yet */
if(smtpcode/100 != 2 && smtpcode != 1) {
if(data->set.use_ssl <= CURLUSESSL_TRY
- || Curl_conn_is_ssl(conn, FIRSTSOCKET))
- result = smtp_perform_helo(data, conn);
+ || Curl_conn_is_ssl(data->conn, FIRSTSOCKET))
+ result = smtp_perform_helo(data, smtpc);
else {
failf(data, "Remote access denied: %d", smtpcode);
result = CURLE_REMOTE_ACCESS_DENIED;
@@ -956,21 +1035,21 @@ static CURLcode smtp_state_ehlo_resp(struct Curl_easy *data,
}
if(smtpcode != 1) {
- if(data->set.use_ssl && !Curl_conn_is_ssl(conn, FIRSTSOCKET)) {
+ if(data->set.use_ssl && !Curl_conn_is_ssl(data->conn, FIRSTSOCKET)) {
/* We do not have a SSL/TLS connection yet, but SSL is requested */
if(smtpc->tls_supported)
/* Switch to TLS connection now */
- result = smtp_perform_starttls(data, conn);
+ result = smtp_perform_starttls(data, smtpc);
else if(data->set.use_ssl == CURLUSESSL_TRY)
/* Fallback and carry on with authentication */
- result = smtp_perform_authentication(data);
+ result = smtp_perform_authentication(data, smtpc);
else {
failf(data, "STARTTLS not supported.");
result = CURLE_USE_SSL_FAILED;
}
}
else
- result = smtp_perform_authentication(data);
+ result = smtp_perform_authentication(data, smtpc);
}
}
else {
@@ -982,7 +1061,9 @@ static CURLcode smtp_state_ehlo_resp(struct Curl_easy *data,
}
/* For HELO responses */
-static CURLcode smtp_state_helo_resp(struct Curl_easy *data, int smtpcode,
+static CURLcode smtp_state_helo_resp(struct Curl_easy *data,
+ struct smtp_conn *smtpc,
+ int smtpcode,
smtpstate instate)
{
CURLcode result = CURLE_OK;
@@ -994,19 +1075,18 @@ static CURLcode smtp_state_helo_resp(struct Curl_easy *data, int smtpcode,
}
else
/* End of connect phase */
- smtp_state(data, SMTP_STOP);
+ smtp_state(data, smtpc, SMTP_STOP);
return result;
}
/* For SASL authentication responses */
static CURLcode smtp_state_auth_resp(struct Curl_easy *data,
+ struct smtp_conn *smtpc,
int smtpcode,
smtpstate instate)
{
CURLcode result = CURLE_OK;
- struct connectdata *conn = data->conn;
- struct smtp_conn *smtpc = &conn->proto.smtpc;
saslprogress progress;
(void)instate; /* no use for this yet */
@@ -1015,7 +1095,7 @@ static CURLcode smtp_state_auth_resp(struct Curl_easy *data,
if(!result)
switch(progress) {
case SASL_DONE:
- smtp_state(data, SMTP_STOP); /* Authenticated */
+ smtp_state(data, smtpc, SMTP_STOP); /* Authenticated */
break;
case SASL_IDLE: /* No mechanism left after cancellation */
failf(data, "Authentication cancelled");
@@ -1029,13 +1109,15 @@ static CURLcode smtp_state_auth_resp(struct Curl_easy *data,
}
/* For command responses */
-static CURLcode smtp_state_command_resp(struct Curl_easy *data, int smtpcode,
+static CURLcode smtp_state_command_resp(struct Curl_easy *data,
+ struct smtp_conn *smtpc,
+ struct SMTP *smtp,
+ int smtpcode,
smtpstate instate)
{
CURLcode result = CURLE_OK;
- struct SMTP *smtp = data->req.p.smtp;
- char *line = Curl_dyn_ptr(&data->conn->proto.smtpc.pp.recvbuf);
- size_t len = data->conn->proto.smtpc.pp.nfinal;
+ char *line = curlx_dyn_ptr(&smtpc->pp.recvbuf);
+ size_t len = smtpc->pp.nfinal;
(void)instate; /* no use for this yet */
@@ -1054,15 +1136,15 @@ static CURLcode smtp_state_command_resp(struct Curl_easy *data, int smtpcode,
if(smtp->rcpt) {
/* Send the next command */
- result = smtp_perform_command(data);
+ result = smtp_perform_command(data, smtpc, smtp);
}
else
/* End of DO phase */
- smtp_state(data, SMTP_STOP);
+ smtp_state(data, smtpc, SMTP_STOP);
}
else
/* End of DO phase */
- smtp_state(data, SMTP_STOP);
+ smtp_state(data, smtpc, SMTP_STOP);
}
}
@@ -1070,7 +1152,10 @@ static CURLcode smtp_state_command_resp(struct Curl_easy *data, int smtpcode,
}
/* For MAIL responses */
-static CURLcode smtp_state_mail_resp(struct Curl_easy *data, int smtpcode,
+static CURLcode smtp_state_mail_resp(struct Curl_easy *data,
+ struct smtp_conn *smtpc,
+ struct SMTP *smtp,
+ int smtpcode,
smtpstate instate)
{
CURLcode result = CURLE_OK;
@@ -1082,18 +1167,19 @@ static CURLcode smtp_state_mail_resp(struct Curl_easy *data, int smtpcode,
}
else
/* Start the RCPT TO command */
- result = smtp_perform_rcpt_to(data);
+ result = smtp_perform_rcpt_to(data, smtpc, smtp);
return result;
}
/* For RCPT responses */
static CURLcode smtp_state_rcpt_resp(struct Curl_easy *data,
- struct connectdata *conn, int smtpcode,
+ struct smtp_conn *smtpc,
+ struct SMTP *smtp,
+ int smtpcode,
smtpstate instate)
{
CURLcode result = CURLE_OK;
- struct SMTP *smtp = data->req.p.smtp;
bool is_smtp_err = FALSE;
bool is_smtp_blocking_err = FALSE;
@@ -1125,7 +1211,7 @@ static CURLcode smtp_state_rcpt_resp(struct Curl_easy *data,
if(smtp->rcpt)
/* Send the next RCPT TO command */
- result = smtp_perform_rcpt_to(data);
+ result = smtp_perform_rcpt_to(data, smtpc, smtp);
else {
/* We were not able to issue a successful RCPT TO command while going
over recipients (potentially multiple). Sending back last error. */
@@ -1135,10 +1221,10 @@ static CURLcode smtp_state_rcpt_resp(struct Curl_easy *data,
}
else {
/* Send the DATA command */
- result = Curl_pp_sendf(data, &conn->proto.smtpc.pp, "%s", "DATA");
+ result = Curl_pp_sendf(data, &smtpc->pp, "%s", "DATA");
if(!result)
- smtp_state(data, SMTP_DATA);
+ smtp_state(data, smtpc, SMTP_DATA);
}
}
}
@@ -1147,7 +1233,9 @@ static CURLcode smtp_state_rcpt_resp(struct Curl_easy *data,
}
/* For DATA response */
-static CURLcode smtp_state_data_resp(struct Curl_easy *data, int smtpcode,
+static CURLcode smtp_state_data_resp(struct Curl_easy *data,
+ struct smtp_conn *smtpc,
+ int smtpcode,
smtpstate instate)
{
CURLcode result = CURLE_OK;
@@ -1165,7 +1253,7 @@ static CURLcode smtp_state_data_resp(struct Curl_easy *data, int smtpcode,
Curl_xfer_setup1(data, CURL_XFER_SEND, -1, FALSE);
/* End of DO phase */
- smtp_state(data, SMTP_STOP);
+ smtp_state(data, smtpc, SMTP_STOP);
}
return result;
@@ -1174,6 +1262,7 @@ static CURLcode smtp_state_data_resp(struct Curl_easy *data, int smtpcode,
/* For POSTDATA responses, which are received after the entire DATA
part has been sent to the server */
static CURLcode smtp_state_postdata_resp(struct Curl_easy *data,
+ struct smtp_conn *smtpc,
int smtpcode,
smtpstate instate)
{
@@ -1185,35 +1274,39 @@ static CURLcode smtp_state_postdata_resp(struct Curl_easy *data,
result = CURLE_WEIRD_SERVER_REPLY;
/* End of DONE phase */
- smtp_state(data, SMTP_STOP);
+ smtp_state(data, smtpc, SMTP_STOP);
return result;
}
-static CURLcode smtp_statemachine(struct Curl_easy *data,
- struct connectdata *conn)
+static CURLcode smtp_pp_statemachine(struct Curl_easy *data,
+ struct connectdata *conn)
{
CURLcode result = CURLE_OK;
int smtpcode;
- struct smtp_conn *smtpc = &conn->proto.smtpc;
- struct pingpong *pp = &smtpc->pp;
+ struct smtp_conn *smtpc = Curl_conn_meta_get(conn, CURL_META_SMTP_CONN);
+ struct SMTP *smtp = Curl_meta_get(data, CURL_META_SMTP_EASY);
size_t nread = 0;
+ if(!smtpc || !smtp)
+ return CURLE_FAILED_INIT;
+
/* Busy upgrading the connection; right now all I/O is SSL/TLS, not SMTP */
upgrade_tls:
if(smtpc->state == SMTP_UPGRADETLS) {
- result = smtp_perform_upgrade_tls(data);
+ result = smtp_perform_upgrade_tls(data, smtpc);
if(result || (smtpc->state == SMTP_UPGRADETLS))
return result;
}
/* Flush any data that needs to be sent */
- if(pp->sendleft)
- return Curl_pp_flushsend(data, pp);
+ if(smtpc->pp.sendleft)
+ return Curl_pp_flushsend(data, &smtpc->pp);
do {
/* Read the response from the server */
- result = Curl_pp_readresp(data, FIRSTSOCKET, pp, &smtpcode, &nread);
+ result = Curl_pp_readresp(data, FIRSTSOCKET, &smtpc->pp,
+ &smtpcode, &nread);
if(result)
return result;
@@ -1227,19 +1320,20 @@ upgrade_tls:
/* We have now received a full SMTP server response */
switch(smtpc->state) {
case SMTP_SERVERGREET:
- result = smtp_state_servergreet_resp(data, smtpcode, smtpc->state);
+ result = smtp_state_servergreet_resp(data, smtpc,
+ smtpcode, smtpc->state);
break;
case SMTP_EHLO:
- result = smtp_state_ehlo_resp(data, conn, smtpcode, smtpc->state);
+ result = smtp_state_ehlo_resp(data, smtpc, smtpcode, smtpc->state);
break;
case SMTP_HELO:
- result = smtp_state_helo_resp(data, smtpcode, smtpc->state);
+ result = smtp_state_helo_resp(data, smtpc, smtpcode, smtpc->state);
break;
case SMTP_STARTTLS:
- result = smtp_state_starttls_resp(data, smtpcode, smtpc->state);
+ result = smtp_state_starttls_resp(data, smtpc, smtpcode, smtpc->state);
/* During UPGRADETLS, leave the read loop as we need to connect
* (e.g. TLS handshake) before we continue sending/receiving. */
if(!result && (smtpc->state == SMTP_UPGRADETLS))
@@ -1247,36 +1341,38 @@ upgrade_tls:
break;
case SMTP_AUTH:
- result = smtp_state_auth_resp(data, smtpcode, smtpc->state);
+ result = smtp_state_auth_resp(data, smtpc, smtpcode, smtpc->state);
break;
case SMTP_COMMAND:
- result = smtp_state_command_resp(data, smtpcode, smtpc->state);
+ result = smtp_state_command_resp(data, smtpc, smtp,
+ smtpcode, smtpc->state);
break;
case SMTP_MAIL:
- result = smtp_state_mail_resp(data, smtpcode, smtpc->state);
+ result = smtp_state_mail_resp(data, smtpc, smtp, smtpcode, smtpc->state);
break;
case SMTP_RCPT:
- result = smtp_state_rcpt_resp(data, conn, smtpcode, smtpc->state);
+ result = smtp_state_rcpt_resp(data, smtpc, smtp, smtpcode, smtpc->state);
break;
case SMTP_DATA:
- result = smtp_state_data_resp(data, smtpcode, smtpc->state);
+ result = smtp_state_data_resp(data, smtpc, smtpcode, smtpc->state);
break;
case SMTP_POSTDATA:
- result = smtp_state_postdata_resp(data, smtpcode, smtpc->state);
+ result = smtp_state_postdata_resp(data, smtpc, smtpcode, smtpc->state);
break;
case SMTP_QUIT:
default:
/* internal error */
- smtp_state(data, SMTP_STOP);
+ smtp_state(data, smtpc, SMTP_STOP);
break;
}
- } while(!result && smtpc->state != SMTP_STOP && Curl_pp_moredata(pp));
+ } while(!result && smtpc->state != SMTP_STOP &&
+ Curl_pp_moredata(&smtpc->pp));
return result;
}
@@ -1285,21 +1381,23 @@ upgrade_tls:
static CURLcode smtp_multi_statemach(struct Curl_easy *data, bool *done)
{
CURLcode result = CURLE_OK;
- struct connectdata *conn = data->conn;
- struct smtp_conn *smtpc = &conn->proto.smtpc;
+ struct smtp_conn *smtpc =
+ Curl_conn_meta_get(data->conn, CURL_META_SMTP_CONN);
+
+ *done = FALSE;
+ if(!smtpc)
+ return CURLE_FAILED_INIT;
result = Curl_pp_statemach(data, &smtpc->pp, FALSE, FALSE);
*done = (smtpc->state == SMTP_STOP);
-
return result;
}
static CURLcode smtp_block_statemach(struct Curl_easy *data,
- struct connectdata *conn,
+ struct smtp_conn *smtpc,
bool disconnecting)
{
CURLcode result = CURLE_OK;
- struct smtp_conn *smtpc = &conn->proto.smtpc;
while(smtpc->state != SMTP_STOP && !result)
result = Curl_pp_statemach(data, &smtpc->pp, TRUE, disconnecting);
@@ -1307,25 +1405,13 @@ static CURLcode smtp_block_statemach(struct Curl_easy *data,
return result;
}
-/* Allocate and initialize the SMTP struct for the current Curl_easy if
- required */
-static CURLcode smtp_init(struct Curl_easy *data)
-{
- CURLcode result = CURLE_OK;
- struct SMTP *smtp;
-
- smtp = data->req.p.smtp = calloc(1, sizeof(struct SMTP));
- if(!smtp)
- result = CURLE_OUT_OF_MEMORY;
-
- return result;
-}
-
/* For the SMTP "protocol connect" and "doing" phases only */
static int smtp_getsock(struct Curl_easy *data,
struct connectdata *conn, curl_socket_t *socks)
{
- return Curl_pp_getsock(data, &conn->proto.smtpc.pp, socks);
+ struct smtp_conn *smtpc = Curl_conn_meta_get(conn, CURL_META_SMTP_CONN);
+ return smtpc ?
+ Curl_pp_getsock(data, &smtpc->pp, socks) : GETSOCK_BLANK;
}
/***********************************************************************
@@ -1340,36 +1426,37 @@ static int smtp_getsock(struct Curl_easy *data,
*/
static CURLcode smtp_connect(struct Curl_easy *data, bool *done)
{
+ struct smtp_conn *smtpc =
+ Curl_conn_meta_get(data->conn, CURL_META_SMTP_CONN);
CURLcode result = CURLE_OK;
- struct connectdata *conn = data->conn;
- struct smtp_conn *smtpc = &conn->proto.smtpc;
- struct pingpong *pp = &smtpc->pp;
*done = FALSE; /* default to not done yet */
+ if(!smtpc)
+ return CURLE_FAILED_INIT;
/* We always support persistent connections in SMTP */
- connkeep(conn, "SMTP default");
+ connkeep(data->conn, "SMTP default");
- PINGPONG_SETUP(pp, smtp_statemachine, smtp_endofresp);
+ PINGPONG_SETUP(&smtpc->pp, smtp_pp_statemachine, smtp_endofresp);
/* Initialize the SASL storage */
Curl_sasl_init(&smtpc->sasl, data, &saslsmtp);
/* Initialise the pingpong layer */
- Curl_pp_init(pp);
+ Curl_pp_init(&smtpc->pp);
/* Parse the URL options */
- result = smtp_parse_url_options(conn);
+ result = smtp_parse_url_options(data->conn, smtpc);
if(result)
return result;
/* Parse the URL path */
- result = smtp_parse_url_path(data);
+ result = smtp_parse_url_path(data, smtpc);
if(result)
return result;
/* Start off waiting for the server greeting response */
- smtp_state(data, SMTP_SERVERGREET);
+ smtp_state(data, smtpc, SMTP_SERVERGREET);
result = smtp_multi_statemach(data, done);
@@ -1388,12 +1475,16 @@ static CURLcode smtp_connect(struct Curl_easy *data, bool *done)
static CURLcode smtp_done(struct Curl_easy *data, CURLcode status,
bool premature)
{
+ struct smtp_conn *smtpc =
+ Curl_conn_meta_get(data->conn, CURL_META_SMTP_CONN);
CURLcode result = CURLE_OK;
struct connectdata *conn = data->conn;
- struct SMTP *smtp = data->req.p.smtp;
+ struct SMTP *smtp = Curl_meta_get(data, CURL_META_SMTP_EASY);
(void)premature;
+ if(!smtpc)
+ return CURLE_FAILED_INIT;
if(!smtp)
return CURLE_OK;
@@ -1407,10 +1498,10 @@ static CURLcode smtp_done(struct Curl_easy *data, CURLcode status,
else if(!data->set.connect_only && data->set.mail_rcpt &&
(data->state.upload || IS_MIME_POST(data))) {
- smtp_state(data, SMTP_POSTDATA);
+ smtp_state(data, smtpc, SMTP_POSTDATA);
/* Run the state-machine */
- result = smtp_block_statemach(data, conn, FALSE);
+ result = smtp_block_statemach(data, smtpc, FALSE);
}
/* Clear the transfer mode for the next request */
@@ -1427,12 +1518,14 @@ static CURLcode smtp_done(struct Curl_easy *data, CURLcode status,
* This is the actual DO function for SMTP. Transfer a mail, send a command
* or get some data according to the options previously setup.
*/
-static CURLcode smtp_perform(struct Curl_easy *data, bool *connected,
+static CURLcode smtp_perform(struct Curl_easy *data,
+ struct smtp_conn *smtpc,
+ struct SMTP *smtp,
+ bool *connected,
bool *dophase_done)
{
/* This is SMTP and no proxy */
CURLcode result = CURLE_OK;
- struct SMTP *smtp = data->req.p.smtp;
CURL_TRC_SMTP(data, "smtp_perform(), start");
@@ -1460,10 +1553,10 @@ static CURLcode smtp_perform(struct Curl_easy *data, bool *connected,
/* Start the first command in the DO phase */
if((data->state.upload || IS_MIME_POST(data)) && data->set.mail_rcpt)
/* MAIL transfer */
- result = smtp_perform_mail(data);
+ result = smtp_perform_mail(data, smtpc, smtp);
else
/* SMTP based command (VRFY, EXPN, NOOP, RSET or HELP) */
- result = smtp_perform_command(data);
+ result = smtp_perform_command(data, smtpc, smtp);
if(result)
goto out;
@@ -1490,17 +1583,23 @@ out:
*/
static CURLcode smtp_do(struct Curl_easy *data, bool *done)
{
+ struct smtp_conn *smtpc =
+ Curl_conn_meta_get(data->conn, CURL_META_SMTP_CONN);
+ struct SMTP *smtp = Curl_meta_get(data, CURL_META_SMTP_EASY);
CURLcode result = CURLE_OK;
+
DEBUGASSERT(data);
DEBUGASSERT(data->conn);
*done = FALSE; /* default to false */
+ if(!smtpc || !smtp)
+ return CURLE_FAILED_INIT;
/* Parse the custom request */
- result = smtp_parse_custom_request(data);
+ result = smtp_parse_custom_request(data, smtp);
if(result)
return result;
- result = smtp_regular_transfer(data, done);
+ result = smtp_regular_transfer(data, smtpc, smtp, done);
CURL_TRC_SMTP(data, "smtp_do() -> %d, done=%d", result, *done);
return result;
}
@@ -1516,36 +1615,32 @@ static CURLcode smtp_disconnect(struct Curl_easy *data,
struct connectdata *conn,
bool dead_connection)
{
- struct smtp_conn *smtpc = &conn->proto.smtpc;
+ struct smtp_conn *smtpc = Curl_conn_meta_get(conn, CURL_META_SMTP_CONN);
+
(void)data;
+ if(!smtpc)
+ return CURLE_FAILED_INIT;
/* We cannot send quit unconditionally. If this connection is stale or
bad in any way, sending quit and waiting around here will make the
disconnect wait in vain and cause more problems than we need to. */
if(!dead_connection && conn->bits.protoconnstart) {
- if(!smtp_perform_quit(data, conn))
- (void)smtp_block_statemach(data, conn, TRUE); /* ignore errors on QUIT */
+ if(!smtp_perform_quit(data, smtpc))
+ (void)smtp_block_statemach(data, smtpc, TRUE); /* ignore on QUIT */
}
- /* Disconnect from the server */
- Curl_pp_disconnect(&smtpc->pp);
-
/* Cleanup the SASL module */
Curl_sasl_cleanup(conn, smtpc->sasl.authused);
-
- /* Cleanup our connection based variables */
- Curl_safefree(smtpc->domain);
CURL_TRC_SMTP(data, "smtp_disconnect(), finished");
-
return CURLE_OK;
}
/* Call this when the DO phase has completed */
-static CURLcode smtp_dophase_done(struct Curl_easy *data, bool connected)
+static CURLcode smtp_dophase_done(struct Curl_easy *data,
+ struct SMTP *smtp,
+ bool connected)
{
- struct SMTP *smtp = data->req.p.smtp;
-
(void)connected;
if(smtp->transfer != PPTRANSFER_BODY)
@@ -1558,12 +1653,16 @@ static CURLcode smtp_dophase_done(struct Curl_easy *data, bool connected)
/* Called from multi.c while DOing */
static CURLcode smtp_doing(struct Curl_easy *data, bool *dophase_done)
{
- CURLcode result = smtp_multi_statemach(data, dophase_done);
+ struct SMTP *smtp = Curl_meta_get(data, CURL_META_SMTP_EASY);
+ CURLcode result;
+ if(!smtp)
+ return CURLE_FAILED_INIT;
+ result = smtp_multi_statemach(data, dophase_done);
if(result)
DEBUGF(infof(data, "DO phase failed"));
else if(*dophase_done) {
- result = smtp_dophase_done(data, FALSE /* not connected */);
+ result = smtp_dophase_done(data, smtp, FALSE /* not connected */);
DEBUGF(infof(data, "DO phase is complete"));
}
@@ -1582,6 +1681,8 @@ static CURLcode smtp_doing(struct Curl_easy *data, bool *dophase_done)
* remote host.
*/
static CURLcode smtp_regular_transfer(struct Curl_easy *data,
+ struct smtp_conn *smtpc,
+ struct SMTP *smtp,
bool *dophase_done)
{
CURLcode result = CURLE_OK;
@@ -1597,25 +1698,56 @@ static CURLcode smtp_regular_transfer(struct Curl_easy *data,
Curl_pgrsSetDownloadSize(data, -1);
/* Carry out the perform */
- result = smtp_perform(data, &connected, dophase_done);
+ result = smtp_perform(data, smtpc, smtp, &connected, dophase_done);
/* Perform post DO phase operations if necessary */
if(!result && *dophase_done)
- result = smtp_dophase_done(data, connected);
+ result = smtp_dophase_done(data, smtp, connected);
CURL_TRC_SMTP(data, "smtp_regular_transfer() -> %d, done=%d",
result, *dophase_done);
return result;
}
+
+static void smtp_easy_dtor(void *key, size_t klen, void *entry)
+{
+ struct SMTP *smtp = entry;
+ (void)key;
+ (void)klen;
+ free(smtp);
+}
+
+static void smtp_conn_dtor(void *key, size_t klen, void *entry)
+{
+ struct smtp_conn *smtpc = entry;
+ (void)key;
+ (void)klen;
+ Curl_pp_disconnect(&smtpc->pp);
+ Curl_safefree(smtpc->domain);
+ free(smtpc);
+}
+
static CURLcode smtp_setup_connection(struct Curl_easy *data,
struct connectdata *conn)
{
- CURLcode result;
+ struct smtp_conn *smtpc;
+ struct SMTP *smtp;
+ CURLcode result = CURLE_OK;
+
+ smtpc = calloc(1, sizeof(*smtpc));
+ if(!smtpc ||
+ Curl_conn_meta_set(conn, CURL_META_SMTP_CONN, smtpc, smtp_conn_dtor)) {
+ result = CURLE_OUT_OF_MEMORY;
+ goto out;
+ }
- /* Initialise the SMTP layer */
- (void)conn;
- result = smtp_init(data);
+ smtp = calloc(1, sizeof(*smtp));
+ if(!smtp ||
+ Curl_meta_set(data, CURL_META_SMTP_EASY, smtp, smtp_easy_dtor))
+ result = CURLE_OUT_OF_MEMORY;
+
+out:
CURL_TRC_SMTP(data, "smtp_setup_connection() -> %d", result);
return result;
}
@@ -1626,10 +1758,10 @@ static CURLcode smtp_setup_connection(struct Curl_easy *data,
*
* Parse the URL login options.
*/
-static CURLcode smtp_parse_url_options(struct connectdata *conn)
+static CURLcode smtp_parse_url_options(struct connectdata *conn,
+ struct smtp_conn *smtpc)
{
CURLcode result = CURLE_OK;
- struct smtp_conn *smtpc = &conn->proto.smtpc;
const char *ptr = conn->options;
while(!result && ptr && *ptr) {
@@ -1663,11 +1795,10 @@ static CURLcode smtp_parse_url_options(struct connectdata *conn)
*
* Parse the URL path into separate path components.
*/
-static CURLcode smtp_parse_url_path(struct Curl_easy *data)
+static CURLcode smtp_parse_url_path(struct Curl_easy *data,
+ struct smtp_conn *smtpc)
{
/* The SMTP struct is already initialised in smtp_connect() */
- struct connectdata *conn = data->conn;
- struct smtp_conn *smtpc = &conn->proto.smtpc;
const char *path = &data->state.up.path[1]; /* skip leading path */
char localhost[HOSTNAME_MAX + 1];
@@ -1689,10 +1820,10 @@ static CURLcode smtp_parse_url_path(struct Curl_easy *data)
*
* Parse the custom request.
*/
-static CURLcode smtp_parse_custom_request(struct Curl_easy *data)
+static CURLcode smtp_parse_custom_request(struct Curl_easy *data,
+ struct SMTP *smtp)
{
CURLcode result = CURLE_OK;
- struct SMTP *smtp = data->req.p.smtp;
const char *custom = data->set.str[STRING_CUSTOMREQUEST];
/* URL decode the custom request */
diff --git a/libs/libcurl/src/smtp.h b/libs/libcurl/src/smtp.h
index c6b33515b7..ef0f0ed8a5 100644
--- a/libs/libcurl/src/smtp.h
+++ b/libs/libcurl/src/smtp.h
@@ -27,60 +27,6 @@
#include "pingpong.h"
#include "curl_sasl.h"
-/****************************************************************************
- * SMTP unique setup
- ***************************************************************************/
-typedef enum {
- SMTP_STOP, /* do nothing state, stops the state machine */
- SMTP_SERVERGREET, /* waiting for the initial greeting immediately after
- a connect */
- SMTP_EHLO,
- SMTP_HELO,
- SMTP_STARTTLS,
- SMTP_UPGRADETLS, /* asynchronously upgrade the connection to SSL/TLS
- (multi mode only) */
- SMTP_AUTH,
- SMTP_COMMAND, /* VRFY, EXPN, NOOP, RSET and HELP */
- SMTP_MAIL, /* MAIL FROM */
- SMTP_RCPT, /* RCPT TO */
- SMTP_DATA,
- SMTP_POSTDATA,
- SMTP_QUIT,
- SMTP_LAST /* never used */
-} smtpstate;
-
-/* This SMTP struct is used in the Curl_easy. All SMTP data that is
- connection-oriented must be in smtp_conn to properly deal with the fact that
- perhaps the Curl_easy is changed between the times the connection is
- used. */
-struct SMTP {
- curl_pp_transfer transfer;
- char *custom; /* Custom Request */
- struct curl_slist *rcpt; /* Recipient list */
- int rcpt_last_error; /* The last error received for RCPT TO command */
- size_t eob; /* Number of bytes of the EOB (End Of Body) that
- have been received so far */
- BIT(rcpt_had_ok); /* Whether any of RCPT TO commands (depends on
- total number of recipients) succeeded so far */
- BIT(trailing_crlf); /* Specifies if the trailing CRLF is present */
-};
-
-/* smtp_conn is used for struct connection-oriented data in the connectdata
- struct */
-struct smtp_conn {
- struct pingpong pp;
- struct SASL sasl; /* SASL-related storage */
- smtpstate state; /* Always use smtp.c:state() to change state! */
- char *domain; /* Client address/name to send in the EHLO */
- BIT(ssldone); /* Is connect() over SSL done? */
- BIT(tls_supported); /* StartTLS capability supported by server */
- BIT(size_supported); /* If server supports SIZE extension according to
- RFC 1870 */
- BIT(utf8_supported); /* If server supports SMTPUTF8 extension according
- to RFC 6531 */
- BIT(auth_supported); /* AUTH capability supported by server */
-};
-
extern const struct Curl_handler Curl_handler_smtp;
extern const struct Curl_handler Curl_handler_smtps;
diff --git a/libs/libcurl/src/socketpair.c b/libs/libcurl/src/socketpair.c
index a7cf171a97..b194831312 100644
--- a/libs/libcurl/src/socketpair.c
+++ b/libs/libcurl/src/socketpair.c
@@ -27,10 +27,9 @@
#include "urldata.h"
#include "rand.h"
-#ifdef HAVE_EVENTFD
-#ifdef HAVE_SYS_EVENTFD_H
+#ifdef USE_EVENTFD
+
#include <sys/eventfd.h>
-#endif
int Curl_eventfd(curl_socket_t socks[2], bool nonblocking)
{
@@ -42,13 +41,20 @@ int Curl_eventfd(curl_socket_t socks[2], bool nonblocking)
socks[0] = socks[1] = efd;
return 0;
}
+
#elif defined(HAVE_PIPE)
+
#ifdef HAVE_FCNTL
#include <fcntl.h>
#endif
int Curl_pipe(curl_socket_t socks[2], bool nonblocking)
{
+#ifdef HAVE_PIPE2
+ int flags = nonblocking ? O_NONBLOCK | O_CLOEXEC : O_CLOEXEC;
+ if(pipe2(socks, flags))
+ return -1;
+#else
if(pipe(socks))
return -1;
#ifdef HAVE_FCNTL
@@ -69,11 +75,12 @@ int Curl_pipe(curl_socket_t socks[2], bool nonblocking)
return -1;
}
}
+#endif
return 0;
}
-#endif
+#endif /* USE_EVENTFD */
#ifndef CURL_DISABLE_SOCKETPAIR
#ifdef HAVE_SOCKETPAIR
@@ -121,8 +128,8 @@ int Curl_socketpair(int domain, int type, int protocol,
#endif /* !INADDR_LOOPBACK */
#endif /* !_WIN32 */
-#include "nonblock.h" /* for curlx_nonblock */
-#include "timeval.h" /* needed before select.h */
+#include "curlx/nonblock.h" /* for curlx_nonblock */
+#include "curlx/timeval.h" /* needed before select.h */
#include "select.h" /* for Curl_poll */
/* The last 3 #include files should be in this order */
@@ -196,7 +203,7 @@ int Curl_socketpair(int domain, int type, int protocol,
if(socks[1] == CURL_SOCKET_BAD)
goto error;
else {
- struct curltime start = Curl_now();
+ struct curltime start = curlx_now();
char rnd[9];
char check[sizeof(rnd)];
char *p = &check[0];
@@ -220,7 +227,7 @@ int Curl_socketpair(int domain, int type, int protocol,
if(nread == -1) {
int sockerr = SOCKERRNO;
/* Do not block forever */
- if(Curl_timediff(Curl_now(), start) > (60 * 1000))
+ if(curlx_timediff(curlx_now(), start) > (60 * 1000))
goto error;
if(
#ifdef USE_WINSOCK
diff --git a/libs/libcurl/src/socketpair.h b/libs/libcurl/src/socketpair.h
index 68dfa5288b..a68a52f3fe 100644
--- a/libs/libcurl/src/socketpair.h
+++ b/libs/libcurl/src/socketpair.h
@@ -26,7 +26,7 @@
#include "curl_setup.h"
-#ifdef HAVE_EVENTFD
+#ifdef USE_EVENTFD
#define wakeup_write write
#define wakeup_read read
@@ -46,7 +46,7 @@ int Curl_eventfd(curl_socket_t socks[2], bool nonblocking);
#include <curl/curl.h>
int Curl_pipe(curl_socket_t socks[2], bool nonblocking);
-#else /* !HAVE_EVENTFD && !HAVE_PIPE */
+#else /* !USE_EVENTFD && !HAVE_PIPE */
#define wakeup_write swrite
#define wakeup_read sread
@@ -69,7 +69,7 @@ int Curl_pipe(curl_socket_t socks[2], bool nonblocking);
#define wakeup_create(p,nb)\
Curl_socketpair(SOCKETPAIR_FAMILY, SOCKETPAIR_TYPE, 0, p, nb)
-#endif /* HAVE_EVENTFD */
+#endif /* USE_EVENTFD */
#ifndef CURL_DISABLE_SOCKETPAIR
#include <curl/curl.h>
diff --git a/libs/libcurl/src/socks.c b/libs/libcurl/src/socks.c
index c586b158b6..794f4296ff 100644
--- a/libs/libcurl/src/socks.c
+++ b/libs/libcurl/src/socks.c
@@ -38,10 +38,10 @@
#include "select.h"
#include "cfilters.h"
#include "connect.h"
-#include "timeval.h"
+#include "curlx/timeval.h"
#include "socks.h"
#include "multiif.h" /* for getsock macros */
-#include "inet_pton.h"
+#include "curlx/inet_pton.h"
#include "url.h"
/* The last 3 #include files should be in this order */
@@ -321,16 +321,16 @@ static CURLproxycode do_SOCKS4(struct Curl_cfilter *cf,
/* DNS resolve only for SOCKS4, not SOCKS4a */
if(!protocol4a) {
- enum resolve_t rc =
- Curl_resolv(data, sx->hostname, sx->remote_port, TRUE, &dns);
+ result = Curl_resolv(data, sx->hostname, sx->remote_port,
+ cf->conn->ip_version, TRUE, &dns);
- if(rc == CURLRESOLV_ERROR)
- return CURLPX_RESOLVE_HOST;
- else if(rc == CURLRESOLV_PENDING) {
+ if(result == CURLE_AGAIN) {
sxstate(sx, data, CONNECT_RESOLVING);
infof(data, "SOCKS4 non-blocking resolve of %s", sx->hostname);
return CURLPX_OK;
}
+ else if(result)
+ return CURLPX_RESOLVE_HOST;
sxstate(sx, data, CONNECT_RESOLVED);
goto CONNECT_RESOLVED;
}
@@ -341,23 +341,11 @@ static CURLproxycode do_SOCKS4(struct Curl_cfilter *cf,
case CONNECT_RESOLVING:
/* check if we have the name resolved by now */
- dns = Curl_fetch_addr(data, sx->hostname, conn->primary.remote_port);
-
- if(dns) {
-#ifdef USE_CURL_ASYNC
- data->state.async.dns = dns;
- data->state.async.done = TRUE;
-#endif
- infof(data, "Hostname '%s' was found", sx->hostname);
- sxstate(sx, data, CONNECT_RESOLVED);
- }
- else {
- result = Curl_resolv_check(data, &dns);
- if(!dns) {
- if(result)
- return CURLPX_RESOLVE_HOST;
- return CURLPX_OK;
- }
+ result = Curl_resolv_check(data, &dns);
+ if(!dns) {
+ if(result)
+ return CURLPX_RESOLVE_HOST;
+ return CURLPX_OK;
}
FALLTHROUGH();
case CONNECT_RESOLVED:
@@ -794,16 +782,15 @@ CONNECT_AUTH_INIT:
case CONNECT_REQ_INIT:
CONNECT_REQ_INIT:
if(socks5_resolve_local) {
- enum resolve_t rc = Curl_resolv(data, sx->hostname, sx->remote_port,
- TRUE, &dns);
+ result = Curl_resolv(data, sx->hostname, sx->remote_port,
+ cf->conn->ip_version, TRUE, &dns);
- if(rc == CURLRESOLV_ERROR)
- return CURLPX_RESOLVE_HOST;
-
- if(rc == CURLRESOLV_PENDING) {
+ if(result == CURLE_AGAIN) {
sxstate(sx, data, CONNECT_RESOLVING);
return CURLPX_OK;
}
+ else if(result)
+ return CURLPX_RESOLVE_HOST;
sxstate(sx, data, CONNECT_RESOLVED);
goto CONNECT_RESOLVED;
}
@@ -811,23 +798,11 @@ CONNECT_REQ_INIT:
case CONNECT_RESOLVING:
/* check if we have the name resolved by now */
- dns = Curl_fetch_addr(data, sx->hostname, sx->remote_port);
-
- if(dns) {
-#ifdef USE_CURL_ASYNC
- data->state.async.dns = dns;
- data->state.async.done = TRUE;
-#endif
- infof(data, "SOCKS5: hostname '%s' found", sx->hostname);
- }
-
+ result = Curl_resolv_check(data, &dns);
if(!dns) {
- result = Curl_resolv_check(data, &dns);
- if(!dns) {
- if(result)
- return CURLPX_RESOLVE_HOST;
- return CURLPX_OK;
- }
+ if(result)
+ return CURLPX_RESOLVE_HOST;
+ return CURLPX_OK;
}
FALLTHROUGH();
case CONNECT_RESOLVED:
diff --git a/libs/libcurl/src/socks_gssapi.c b/libs/libcurl/src/socks_gssapi.c
index bab7957e91..e12ebfc03a 100644
--- a/libs/libcurl/src/socks_gssapi.c
+++ b/libs/libcurl/src/socks_gssapi.c
@@ -32,9 +32,9 @@
#include "sendf.h"
#include "cfilters.h"
#include "connect.h"
-#include "timeval.h"
+#include "curlx/timeval.h"
#include "socks.h"
-#include "warnless.h"
+#include "curlx/warnless.h"
#include "strdup.h"
/* The last 3 #include files should be in this order */
@@ -65,7 +65,7 @@ static int check_gss_err(struct Curl_easy *data,
gss_buffer_desc status_string = GSS_C_EMPTY_BUFFER;
struct dynbuf dbuf;
- Curl_dyn_init(&dbuf, MAX_GSS_LEN);
+ curlx_dyn_init(&dbuf, MAX_GSS_LEN);
msg_ctx = 0;
while(!msg_ctx) {
/* convert major status code (GSS-API error) to text */
@@ -74,7 +74,7 @@ static int check_gss_err(struct Curl_easy *data,
GSS_C_NULL_OID,
&msg_ctx, &status_string);
if(maj_stat == GSS_S_COMPLETE) {
- if(Curl_dyn_addn(&dbuf, status_string.value,
+ if(curlx_dyn_addn(&dbuf, status_string.value,
status_string.length))
return 1; /* error */
gss_release_buffer(&min_stat, &status_string);
@@ -82,7 +82,7 @@ static int check_gss_err(struct Curl_easy *data,
}
gss_release_buffer(&min_stat, &status_string);
}
- if(Curl_dyn_addn(&dbuf, ".\n", 2))
+ if(curlx_dyn_addn(&dbuf, ".\n", 2))
return 1; /* error */
msg_ctx = 0;
while(!msg_ctx) {
@@ -92,7 +92,7 @@ static int check_gss_err(struct Curl_easy *data,
GSS_C_NULL_OID,
&msg_ctx, &status_string);
if(maj_stat == GSS_S_COMPLETE) {
- if(Curl_dyn_addn(&dbuf, status_string.value,
+ if(curlx_dyn_addn(&dbuf, status_string.value,
status_string.length))
return 1; /* error */
gss_release_buffer(&min_stat, &status_string);
@@ -100,8 +100,9 @@ static int check_gss_err(struct Curl_easy *data,
}
gss_release_buffer(&min_stat, &status_string);
}
- failf(data, "GSS-API error: %s failed: %s", function, Curl_dyn_ptr(&dbuf));
- Curl_dyn_free(&dbuf);
+ failf(data, "GSS-API error: %s failed: %s", function,
+ curlx_dyn_ptr(&dbuf));
+ curlx_dyn_free(&dbuf);
return 1;
}
diff --git a/libs/libcurl/src/socks_sspi.c b/libs/libcurl/src/socks_sspi.c
index 5c0254d490..d417ba5188 100644
--- a/libs/libcurl/src/socks_sspi.c
+++ b/libs/libcurl/src/socks_sspi.c
@@ -32,11 +32,11 @@
#include "cfilters.h"
#include "connect.h"
#include "strerror.h"
-#include "timeval.h"
+#include "curlx/timeval.h"
#include "socks.h"
#include "curl_sspi.h"
-#include "curl_multibyte.h"
-#include "warnless.h"
+#include "curlx/multibyte.h"
+#include "curlx/warnless.h"
#include "strdup.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
diff --git a/libs/libcurl/src/speedcheck.c b/libs/libcurl/src/speedcheck.c
index fd1eaa73dc..6c9bdf2d50 100644
--- a/libs/libcurl/src/speedcheck.c
+++ b/libs/libcurl/src/speedcheck.c
@@ -52,7 +52,7 @@ CURLcode Curl_speedcheck(struct Curl_easy *data,
data->state.keeps_speed = now;
else {
/* how long has it been under the limit */
- timediff_t howlong = Curl_timediff(now, data->state.keeps_speed);
+ timediff_t howlong = curlx_timediff(now, data->state.keeps_speed);
if(howlong >= data->set.low_speed_time * 1000) {
/* too long */
diff --git a/libs/libcurl/src/speedcheck.h b/libs/libcurl/src/speedcheck.h
index d09ec743b5..ea39e3db4b 100644
--- a/libs/libcurl/src/speedcheck.h
+++ b/libs/libcurl/src/speedcheck.h
@@ -26,7 +26,7 @@
#include "curl_setup.h"
-#include "timeval.h"
+#include "curlx/timeval.h"
struct Curl_easy;
void Curl_speedinit(struct Curl_easy *data);
CURLcode Curl_speedcheck(struct Curl_easy *data,
diff --git a/libs/libcurl/src/splay.c b/libs/libcurl/src/splay.c
index e5031a70ef..4cd049e51d 100644
--- a/libs/libcurl/src/splay.c
+++ b/libs/libcurl/src/splay.c
@@ -24,7 +24,7 @@
#include "curl_setup.h"
-#include "timeval.h"
+#include "curlx/timeval.h"
#include "splay.h"
/*
@@ -34,7 +34,7 @@
* zero : when i is equal to j
* positive when : when i is larger than j
*/
-#define compare(i,j) Curl_timediff_us(i,j)
+#define compare(i,j) curlx_timediff_us(i,j)
/*
* Splay using the key i (which may or may not be in the tree.) The starting
diff --git a/libs/libcurl/src/splay.h b/libs/libcurl/src/splay.h
index 4816ac7a66..84d4b93967 100644
--- a/libs/libcurl/src/splay.h
+++ b/libs/libcurl/src/splay.h
@@ -24,7 +24,7 @@
*
***************************************************************************/
#include "curl_setup.h"
-#include "timeval.h"
+#include "curlx/timeval.h"
/* only use function calls to access this struct */
struct Curl_tree {
diff --git a/libs/libcurl/src/strerror.c b/libs/libcurl/src/strerror.c
index b9f29ea096..a48ab988aa 100644
--- a/libs/libcurl/src/strerror.c
+++ b/libs/libcurl/src/strerror.c
@@ -42,16 +42,13 @@
#include "curl_sspi.h"
#endif
+#include "curlx/winapi.h"
#include "strerror.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h"
#include "memdebug.h"
-#ifdef _WIN32
-#define PRESERVE_WINDOWS_ERROR_CODE
-#endif
-
const char *
curl_easy_strerror(CURLcode error)
{
@@ -782,50 +779,6 @@ get_winsock_error(int err, char *buf, size_t len)
}
#endif /* USE_WINSOCK */
-#ifdef _WIN32
-/* This is a helper function for Curl_strerror that converts Windows API error
- * codes (GetLastError) to error messages.
- * Returns NULL if no error message was found for error code.
- */
-static const char *
-get_winapi_error(int err, char *buf, size_t buflen)
-{
- char *p;
- wchar_t wbuf[256];
-
- if(!buflen)
- return NULL;
-
- *buf = '\0';
- *wbuf = L'\0';
-
- /* We return the local codepage version of the error string because if it is
- output to the user's terminal it will likely be with functions which
- expect the local codepage (eg fprintf, failf, infof).
- FormatMessageW -> wcstombs is used for Windows CE compatibility. */
- if(FormatMessageW((FORMAT_MESSAGE_FROM_SYSTEM |
- FORMAT_MESSAGE_IGNORE_INSERTS), NULL, (DWORD)err,
- LANG_NEUTRAL, wbuf, CURL_ARRAYSIZE(wbuf), NULL)) {
- size_t written = wcstombs(buf, wbuf, buflen - 1);
- if(written != (size_t)-1)
- buf[written] = '\0';
- else
- *buf = '\0';
- }
-
- /* Truncate multiple lines */
- p = strchr(buf, '\n');
- if(p) {
- if(p > buf && *(p-1) == '\r')
- *(p-1) = '\0';
- else
- *p = '\0';
- }
-
- return *buf ? buf : NULL;
-}
-#endif /* _WIN32 */
-
/*
* Our thread-safe and smart strerror() replacement.
*
@@ -847,7 +800,7 @@ get_winapi_error(int err, char *buf, size_t buflen)
*/
const char *Curl_strerror(int err, char *buf, size_t buflen)
{
-#ifdef PRESERVE_WINDOWS_ERROR_CODE
+#ifdef _WIN32
DWORD old_win_err = GetLastError();
#endif
int old_errno = errno;
@@ -866,16 +819,16 @@ const char *Curl_strerror(int err, char *buf, size_t buflen)
#ifndef UNDER_CE
/* 'sys_nerr' is the maximum errno number, it is not widely portable */
if(err >= 0 && err < sys_nerr)
- msnprintf(buf, buflen, "%s", sys_errlist[err]);
+ curl_msnprintf(buf, buflen, "%s", sys_errlist[err]);
else
#endif
{
if(
#ifdef USE_WINSOCK
- !get_winsock_error(err, buf, buflen) &&
+ !get_winsock_error(err, buf, buflen) &&
#endif
- !get_winapi_error(err, buf, buflen))
- msnprintf(buf, buflen, "Unknown error %d (%#x)", err, err);
+ !curlx_get_winapi_error(err, buf, buflen))
+ curl_msnprintf(buf, buflen, "Unknown error %d (%#x)", err, err);
}
#else /* not Windows coming up */
@@ -887,7 +840,7 @@ const char *Curl_strerror(int err, char *buf, size_t buflen)
*/
if(0 != strerror_r(err, buf, buflen)) {
if('\0' == buf[0])
- msnprintf(buf, buflen, "Unknown error %d", err);
+ curl_msnprintf(buf, buflen, "Unknown error %d", err);
}
#elif defined(HAVE_STRERROR_R) && defined(HAVE_GLIBC_STRERROR_R)
/*
@@ -899,18 +852,18 @@ const char *Curl_strerror(int err, char *buf, size_t buflen)
char buffer[256];
char *msg = strerror_r(err, buffer, sizeof(buffer));
if(msg)
- msnprintf(buf, buflen, "%s", msg);
+ curl_msnprintf(buf, buflen, "%s", msg);
else
- msnprintf(buf, buflen, "Unknown error %d", err);
+ curl_msnprintf(buf, buflen, "Unknown error %d", err);
}
#else
{
/* !checksrc! disable BANNEDFUNC 1 */
const char *msg = strerror(err);
if(msg)
- msnprintf(buf, buflen, "%s", msg);
+ curl_msnprintf(buf, buflen, "%s", msg);
else
- msnprintf(buf, buflen, "Unknown error %d", err);
+ curl_msnprintf(buf, buflen, "Unknown error %d", err);
}
#endif
@@ -927,54 +880,13 @@ const char *Curl_strerror(int err, char *buf, size_t buflen)
if(errno != old_errno)
CURL_SETERRNO(old_errno);
-#ifdef PRESERVE_WINDOWS_ERROR_CODE
- if(old_win_err != GetLastError())
- SetLastError(old_win_err);
-#endif
-
- return buf;
-}
-
-/*
- * curlx_winapi_strerror:
- * Variant of Curl_strerror if the error code is definitely Windows API.
- */
#ifdef _WIN32
-const char *curlx_winapi_strerror(DWORD err, char *buf, size_t buflen)
-{
-#ifdef PRESERVE_WINDOWS_ERROR_CODE
- DWORD old_win_err = GetLastError();
-#endif
- int old_errno = errno;
-
- if(!buflen)
- return NULL;
-
- *buf = '\0';
-
-#ifndef CURL_DISABLE_VERBOSE_STRINGS
- if(!get_winapi_error((int)err, buf, buflen)) {
- msnprintf(buf, buflen, "Unknown error %lu (0x%08lX)", err, err);
- }
-#else
- {
- const char *txt = (err == ERROR_SUCCESS) ? "No error" : "Error";
- if(strlen(txt) < buflen)
- strcpy(buf, txt);
- }
-#endif
-
- if(errno != old_errno)
- CURL_SETERRNO(old_errno);
-
-#ifdef PRESERVE_WINDOWS_ERROR_CODE
if(old_win_err != GetLastError())
SetLastError(old_win_err);
#endif
return buf;
}
-#endif /* _WIN32 */
#ifdef USE_WINDOWS_SSPI
/*
@@ -983,7 +895,7 @@ const char *curlx_winapi_strerror(DWORD err, char *buf, size_t buflen)
*/
const char *Curl_sspi_strerror(int err, char *buf, size_t buflen)
{
-#ifdef PRESERVE_WINDOWS_ERROR_CODE
+#ifdef _WIN32
DWORD old_win_err = GetLastError();
#endif
int old_errno = errno;
@@ -1090,18 +1002,18 @@ const char *Curl_sspi_strerror(int err, char *buf, size_t buflen)
}
if(err == SEC_E_ILLEGAL_MESSAGE) {
- msnprintf(buf, buflen,
- "SEC_E_ILLEGAL_MESSAGE (0x%08X) - This error usually occurs "
- "when a fatal SSL/TLS alert is received (e.g. handshake failed)."
- " More detail may be available in the Windows System event log.",
- err);
+ curl_msnprintf(buf, buflen,
+ "SEC_E_ILLEGAL_MESSAGE (0x%08X) - This error usually "
+ "occurs when a fatal SSL/TLS alert is received (e.g. "
+ "handshake failed). More detail may be available in "
+ "the Windows System event log.", err);
}
else {
char msgbuf[256];
- if(get_winapi_error(err, msgbuf, sizeof(msgbuf)))
- msnprintf(buf, buflen, "%s (0x%08X) - %s", txt, err, msgbuf);
+ if(curlx_get_winapi_error(err, msgbuf, sizeof(msgbuf)))
+ curl_msnprintf(buf, buflen, "%s (0x%08X) - %s", txt, err, msgbuf);
else
- msnprintf(buf, buflen, "%s (0x%08X)", txt, err);
+ curl_msnprintf(buf, buflen, "%s (0x%08X)", txt, err);
}
#else
@@ -1116,7 +1028,7 @@ const char *Curl_sspi_strerror(int err, char *buf, size_t buflen)
if(errno != old_errno)
CURL_SETERRNO(old_errno);
-#ifdef PRESERVE_WINDOWS_ERROR_CODE
+#ifdef _WIN32
if(old_win_err != GetLastError())
SetLastError(old_win_err);
#endif
diff --git a/libs/libcurl/src/strerror.h b/libs/libcurl/src/strerror.h
index 6b9b8e358a..130c4647fe 100644
--- a/libs/libcurl/src/strerror.h
+++ b/libs/libcurl/src/strerror.h
@@ -29,9 +29,6 @@
#define STRERROR_LEN 256 /* a suitable length */
const char *Curl_strerror(int err, char *buf, size_t buflen);
-#ifdef _WIN32
-const char *curlx_winapi_strerror(DWORD err, char *buf, size_t buflen);
-#endif
#ifdef USE_WINDOWS_SSPI
const char *Curl_sspi_strerror(int err, char *buf, size_t buflen);
#endif
diff --git a/libs/libcurl/src/system_win32.c b/libs/libcurl/src/system_win32.c
index 1a3744001c..0e96998ad9 100644
--- a/libs/libcurl/src/system_win32.c
+++ b/libs/libcurl/src/system_win32.c
@@ -28,17 +28,14 @@
#include <curl/curl.h>
#include "system_win32.h"
-#include "version_win32.h"
+#include "curlx/version_win32.h"
#include "curl_sspi.h"
-#include "warnless.h"
+#include "curlx/warnless.h"
/* The last #include files should be: */
#include "curl_memory.h"
#include "memdebug.h"
-LARGE_INTEGER Curl_freq;
-bool Curl_isVistaOrGreater;
-
/* Handle of iphlpapp.dll */
static HMODULE s_hIpHlpApiDll = NULL;
diff --git a/libs/libcurl/src/telnet.c b/libs/libcurl/src/telnet.c
index fa475fc4e2..b5d4380263 100644
--- a/libs/libcurl/src/telnet.c
+++ b/libs/libcurl/src/telnet.c
@@ -47,6 +47,7 @@
#endif
#include "urldata.h"
+#include "url.h"
#include <curl/curl.h>
#include "transfer.h"
#include "sendf.h"
@@ -57,8 +58,8 @@
#include "arpa_telnet.h"
#include "select.h"
#include "strcase.h"
-#include "warnless.h"
-#include "strparse.h"
+#include "curlx/warnless.h"
+#include "curlx/strparse.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
@@ -90,36 +91,6 @@
#define printoption(a,b,c,d) Curl_nop_stmt
#endif
-static
-CURLcode telrcv(struct Curl_easy *data,
- const unsigned char *inbuf, /* Data received from socket */
- ssize_t count); /* Number of bytes received */
-
-#ifndef CURL_DISABLE_VERBOSE_STRINGS
-static void printoption(struct Curl_easy *data,
- const char *direction,
- int cmd, int option);
-#endif
-
-static void negotiate(struct Curl_easy *data);
-static void send_negotiation(struct Curl_easy *data, int cmd, int option);
-static void set_local_option(struct Curl_easy *data,
- int option, int newstate);
-static void set_remote_option(struct Curl_easy *data,
- int option, int newstate);
-
-static void printsub(struct Curl_easy *data,
- int direction, unsigned char *pointer,
- size_t length);
-static void suboption(struct Curl_easy *data);
-static void sendsuboption(struct Curl_easy *data, int option);
-
-static CURLcode telnet_do(struct Curl_easy *data, bool *done);
-static CURLcode telnet_done(struct Curl_easy *data,
- CURLcode, bool premature);
-static CURLcode send_telnet_data(struct Curl_easy *data,
- char *buffer, ssize_t nread);
-
/* For negotiation compliant to RFC 1143 */
#define CURL_NO 0
#define CURL_YES 1
@@ -129,6 +100,10 @@ static CURLcode send_telnet_data(struct Curl_easy *data,
#define CURL_EMPTY 0
#define CURL_OPPOSITE 1
+
+/* meta key for storing protocol meta at easy handle */
+#define CURL_META_TELNET_EASY "meta:proto:telnet:easy"
+
/*
* Telnet receiver states for fsm
*/
@@ -169,6 +144,38 @@ struct TELNET {
};
+static
+CURLcode telrcv(struct Curl_easy *data,
+ struct TELNET *tn,
+ const unsigned char *inbuf, /* Data received from socket */
+ ssize_t count); /* Number of bytes received */
+
+#ifndef CURL_DISABLE_VERBOSE_STRINGS
+static void printoption(struct Curl_easy *data,
+ const char *direction,
+ int cmd, int option);
+#endif
+
+static void send_negotiation(struct Curl_easy *data, int cmd, int option);
+static void set_local_option(struct Curl_easy *data, struct TELNET *tn,
+ int option, int newstate);
+static void set_remote_option(struct Curl_easy *data, struct TELNET *tn,
+ int option, int newstate);
+
+static void printsub(struct Curl_easy *data,
+ int direction, unsigned char *pointer,
+ size_t length);
+static void suboption(struct Curl_easy *data, struct TELNET *tn);
+static void sendsuboption(struct Curl_easy *data,
+ struct TELNET *tn, int option);
+
+static CURLcode telnet_do(struct Curl_easy *data, bool *done);
+static CURLcode telnet_done(struct Curl_easy *data,
+ CURLcode, bool premature);
+static CURLcode send_telnet_data(struct Curl_easy *data,
+ struct TELNET *tn,
+ char *buffer, ssize_t nread);
+
/*
* TELNET protocol handler.
*/
@@ -199,6 +206,16 @@ const struct Curl_handler Curl_handler_telnet = {
};
+static void telnet_easy_dtor(void *key, size_t klen, void *entry)
+{
+ struct TELNET *tn = entry;
+ (void)key;
+ (void)klen;
+ curl_slist_free_all(tn->telnet_vars);
+ curlx_dyn_free(&tn->out);
+ free(tn);
+}
+
static
CURLcode init_telnet(struct Curl_easy *data)
{
@@ -208,8 +225,7 @@ CURLcode init_telnet(struct Curl_easy *data)
if(!tn)
return CURLE_OUT_OF_MEMORY;
- Curl_dyn_init(&tn->out, 0xffff);
- data->req.p.telnet = tn; /* make us known */
+ curlx_dyn_init(&tn->out, 0xffff);
tn->telrcv_state = CURL_TS_DATA;
@@ -248,23 +264,23 @@ CURLcode init_telnet(struct Curl_easy *data)
based upon the terminal type information that may have been sent
using the TERMINAL TYPE Telnet option). */
tn->subnegotiation[CURL_TELOPT_NAWS] = CURL_YES;
- return CURLE_OK;
+
+ return Curl_meta_set(data, CURL_META_TELNET_EASY, tn, telnet_easy_dtor);
}
-static void negotiate(struct Curl_easy *data)
+static void telnet_negotiate(struct Curl_easy *data, struct TELNET *tn)
{
int i;
- struct TELNET *tn = data->req.p.telnet;
for(i = 0; i < CURL_NTELOPTS; i++) {
if(i == CURL_TELOPT_ECHO)
continue;
if(tn->us_preferred[i] == CURL_YES)
- set_local_option(data, i, CURL_YES);
+ set_local_option(data, tn, i, CURL_YES);
if(tn->him_preferred[i] == CURL_YES)
- set_remote_option(data, i, CURL_YES);
+ set_remote_option(data, tn, i, CURL_YES);
}
}
@@ -325,9 +341,9 @@ static void send_negotiation(struct Curl_easy *data, int cmd, int option)
}
static
-void set_remote_option(struct Curl_easy *data, int option, int newstate)
+void set_remote_option(struct Curl_easy *data, struct TELNET *tn,
+ int option, int newstate)
{
- struct TELNET *tn = data->req.p.telnet;
if(newstate == CURL_YES) {
switch(tn->him[option]) {
case CURL_NO:
@@ -399,9 +415,8 @@ void set_remote_option(struct Curl_easy *data, int option, int newstate)
}
static
-void rec_will(struct Curl_easy *data, int option)
+void rec_will(struct Curl_easy *data, struct TELNET *tn, int option)
{
- struct TELNET *tn = data->req.p.telnet;
switch(tn->him[option]) {
case CURL_NO:
if(tn->him_preferred[option] == CURL_YES) {
@@ -447,9 +462,8 @@ void rec_will(struct Curl_easy *data, int option)
}
static
-void rec_wont(struct Curl_easy *data, int option)
+void rec_wont(struct Curl_easy *data, struct TELNET *tn, int option)
{
- struct TELNET *tn = data->req.p.telnet;
switch(tn->him[option]) {
case CURL_NO:
/* Already disabled */
@@ -489,9 +503,9 @@ void rec_wont(struct Curl_easy *data, int option)
}
static void
-set_local_option(struct Curl_easy *data, int option, int newstate)
+set_local_option(struct Curl_easy *data, struct TELNET *tn,
+ int option, int newstate)
{
- struct TELNET *tn = data->req.p.telnet;
if(newstate == CURL_YES) {
switch(tn->us[option]) {
case CURL_NO:
@@ -563,9 +577,8 @@ set_local_option(struct Curl_easy *data, int option, int newstate)
}
static
-void rec_do(struct Curl_easy *data, int option)
+void rec_do(struct Curl_easy *data, struct TELNET *tn, int option)
{
- struct TELNET *tn = data->req.p.telnet;
switch(tn->us[option]) {
case CURL_NO:
if(tn->us_preferred[option] == CURL_YES) {
@@ -573,13 +586,13 @@ void rec_do(struct Curl_easy *data, int option)
send_negotiation(data, CURL_WILL, option);
if(tn->subnegotiation[option] == CURL_YES)
/* transmission of data option */
- sendsuboption(data, option);
+ sendsuboption(data, tn, option);
}
else if(tn->subnegotiation[option] == CURL_YES) {
/* send information to achieve this option */
tn->us[option] = CURL_YES;
send_negotiation(data, CURL_WILL, option);
- sendsuboption(data, option);
+ sendsuboption(data, tn, option);
}
else
send_negotiation(data, CURL_WONT, option);
@@ -609,7 +622,7 @@ void rec_do(struct Curl_easy *data, int option)
tn->us[option] = CURL_YES;
if(tn->subnegotiation[option] == CURL_YES) {
/* transmission of data option */
- sendsuboption(data, option);
+ sendsuboption(data, tn, option);
}
break;
case CURL_OPPOSITE:
@@ -623,9 +636,8 @@ void rec_do(struct Curl_easy *data, int option)
}
static
-void rec_dont(struct Curl_easy *data, int option)
+void rec_dont(struct Curl_easy *data, struct TELNET *tn, int option)
{
- struct TELNET *tn = data->req.p.telnet;
switch(tn->us[option]) {
case CURL_NO:
/* Already disabled */
@@ -788,11 +800,11 @@ static bool str_is_nonascii(const char *str)
return FALSE;
}
-static CURLcode check_telnet_options(struct Curl_easy *data)
+static CURLcode check_telnet_options(struct Curl_easy *data,
+ struct TELNET *tn)
{
struct curl_slist *head;
struct curl_slist *beg;
- struct TELNET *tn = data->req.p.telnet;
CURLcode result = CURLE_OK;
/* Add the username as an environment variable if it
@@ -866,9 +878,9 @@ static CURLcode check_telnet_options(struct Curl_easy *data)
const char *p = arg;
curl_off_t x = 0;
curl_off_t y = 0;
- if(Curl_str_number(&p, &x, 0xffff) ||
- Curl_str_single(&p, 'x') ||
- Curl_str_number(&p, &y, 0xffff)) {
+ if(curlx_str_number(&p, &x, 0xffff) ||
+ curlx_str_single(&p, 'x') ||
+ curlx_str_number(&p, &y, 0xffff)) {
failf(data, "Syntax error in telnet option: %s", head->data);
result = CURLE_SETOPT_OPTION_SYNTAX;
}
@@ -921,14 +933,13 @@ static CURLcode check_telnet_options(struct Curl_easy *data)
* side.
*/
-static void suboption(struct Curl_easy *data)
+static void suboption(struct Curl_easy *data, struct TELNET *tn)
{
struct curl_slist *v;
unsigned char temp[2048];
ssize_t bytes_written;
size_t len;
int err;
- struct TELNET *tn = data->req.p.telnet;
struct connectdata *conn = data->conn;
printsub(data, '<', (unsigned char *)tn->subbuffer, CURL_SB_LEN(tn) + 2);
@@ -1000,13 +1011,13 @@ static void suboption(struct Curl_easy *data)
* Send suboption information to the server side.
*/
-static void sendsuboption(struct Curl_easy *data, int option)
+static void sendsuboption(struct Curl_easy *data,
+ struct TELNET *tn, int option)
{
ssize_t bytes_written;
int err;
unsigned short x, y;
unsigned char *uc1, *uc2;
- struct TELNET *tn = data->req.p.telnet;
struct connectdata *conn = data->conn;
switch(option) {
@@ -1043,7 +1054,7 @@ static void sendsuboption(struct Curl_easy *data, int option)
}
/* ... then the window size with the send_telnet_data() function
to deal with 0xFF cases ... */
- send_telnet_data(data, (char *)tn->subbuffer + 3, 4);
+ send_telnet_data(data, tn, (char *)tn->subbuffer + 3, 4);
/* ... and the footer */
bytes_written = swrite(conn->sock[FIRSTSOCKET], tn->subbuffer + 7, 2);
if(bytes_written < 0) {
@@ -1057,6 +1068,7 @@ static void sendsuboption(struct Curl_easy *data, int option)
static
CURLcode telrcv(struct Curl_easy *data,
+ struct TELNET *tn,
const unsigned char *inbuf, /* Data received from socket */
ssize_t count) /* Number of bytes received */
{
@@ -1064,7 +1076,6 @@ CURLcode telrcv(struct Curl_easy *data,
CURLcode result;
int in = 0;
int startwrite = -1;
- struct TELNET *tn = data->req.p.telnet;
#define startskipping() \
if(startwrite >= 0) { \
@@ -1144,28 +1155,28 @@ process_iac:
case CURL_TS_WILL:
printoption(data, "RCVD", CURL_WILL, c);
tn->please_negotiate = 1;
- rec_will(data, c);
+ rec_will(data, tn, c);
tn->telrcv_state = CURL_TS_DATA;
break;
case CURL_TS_WONT:
printoption(data, "RCVD", CURL_WONT, c);
tn->please_negotiate = 1;
- rec_wont(data, c);
+ rec_wont(data, tn, c);
tn->telrcv_state = CURL_TS_DATA;
break;
case CURL_TS_DO:
printoption(data, "RCVD", CURL_DO, c);
tn->please_negotiate = 1;
- rec_do(data, c);
+ rec_do(data, tn, c);
tn->telrcv_state = CURL_TS_DATA;
break;
case CURL_TS_DONT:
printoption(data, "RCVD", CURL_DONT, c);
tn->please_negotiate = 1;
- rec_dont(data, c);
+ rec_dont(data, tn, c);
tn->telrcv_state = CURL_TS_DATA;
break;
@@ -1194,7 +1205,7 @@ process_iac:
CURL_SB_TERM(tn);
printoption(data, "In SUBOPTION processing, RCVD", CURL_IAC, c);
- suboption(data); /* handle sub-option */
+ suboption(data, tn); /* handle sub-option */
tn->telrcv_state = CURL_TS_IAC;
goto process_iac;
}
@@ -1206,7 +1217,7 @@ process_iac:
CURL_SB_ACCUM(tn, CURL_SE);
tn->subpointer -= 2;
CURL_SB_TERM(tn);
- suboption(data); /* handle sub-option */
+ suboption(data, tn); /* handle sub-option */
tn->telrcv_state = CURL_TS_DATA;
}
break;
@@ -1219,6 +1230,7 @@ process_iac:
/* Escape and send a telnet data block */
static CURLcode send_telnet_data(struct Curl_easy *data,
+ struct TELNET *tn,
char *buffer, ssize_t nread)
{
size_t i, outlen;
@@ -1227,7 +1239,6 @@ static CURLcode send_telnet_data(struct Curl_easy *data,
size_t bytes_written;
size_t total_written = 0;
struct connectdata *conn = data->conn;
- struct TELNET *tn = data->req.p.telnet;
DEBUGASSERT(tn);
DEBUGASSERT(nread > 0);
@@ -1236,17 +1247,17 @@ static CURLcode send_telnet_data(struct Curl_easy *data,
if(memchr(buffer, CURL_IAC, nread)) {
/* only use the escape buffer when necessary */
- Curl_dyn_reset(&tn->out);
+ curlx_dyn_reset(&tn->out);
for(i = 0; i < (size_t)nread && !result; i++) {
- result = Curl_dyn_addn(&tn->out, &buffer[i], 1);
+ result = curlx_dyn_addn(&tn->out, &buffer[i], 1);
if(!result && ((unsigned char)buffer[i] == CURL_IAC))
/* IAC is FF in hex */
- result = Curl_dyn_addn(&tn->out, "\xff", 1);
+ result = curlx_dyn_addn(&tn->out, "\xff", 1);
}
- outlen = Curl_dyn_len(&tn->out);
- outbuf = Curl_dyn_uptr(&tn->out);
+ outlen = curlx_dyn_len(&tn->out);
+ outbuf = curlx_dyn_uptr(&tn->out);
}
else {
outlen = (size_t)nread;
@@ -1277,16 +1288,9 @@ static CURLcode send_telnet_data(struct Curl_easy *data,
static CURLcode telnet_done(struct Curl_easy *data,
CURLcode status, bool premature)
{
- struct TELNET *tn = data->req.p.telnet;
(void)status; /* unused */
(void)premature; /* not used */
-
- if(!tn)
- return CURLE_OK;
-
- curl_slist_free_all(tn->telnet_vars);
- tn->telnet_vars = NULL;
- Curl_dyn_free(&tn->out);
+ Curl_meta_remove(data, CURL_META_TELNET_EASY);
return CURLE_OK;
}
@@ -1323,9 +1327,11 @@ static CURLcode telnet_do(struct Curl_easy *data, bool *done)
if(result)
return result;
- tn = data->req.p.telnet;
+ tn = Curl_meta_get(data, CURL_META_TELNET_EASY);
+ if(!tn)
+ return CURLE_FAILED_INIT;
- result = check_telnet_options(data);
+ result = check_telnet_options(data, tn);
if(result)
return result;
@@ -1418,7 +1424,7 @@ static CURLcode telnet_do(struct Curl_easy *data, bool *done)
}
}
- result = send_telnet_data(data, buffer, readfile_read);
+ result = send_telnet_data(data, tn, buffer, readfile_read);
if(result) {
keepon = FALSE;
break;
@@ -1436,7 +1442,7 @@ static CURLcode telnet_do(struct Curl_easy *data, bool *done)
break;
}
- result = send_telnet_data(data, buffer, readfile_read);
+ result = send_telnet_data(data, tn, buffer, readfile_read);
if(result) {
keepon = FALSE;
break;
@@ -1474,7 +1480,7 @@ static CURLcode telnet_do(struct Curl_easy *data, bool *done)
break;
}
- result = telrcv(data, (unsigned char *) buffer, nread);
+ result = telrcv(data, tn, (unsigned char *) buffer, nread);
if(result) {
keepon = FALSE;
break;
@@ -1484,7 +1490,7 @@ static CURLcode telnet_do(struct Curl_easy *data, bool *done)
otherwise do not. We do not want to speak telnet with
non-telnet servers, like POP or SMTP. */
if(tn->please_negotiate && !tn->already_negotiated) {
- negotiate(data);
+ telnet_negotiate(data, tn);
tn->already_negotiated = 1;
}
}
@@ -1497,8 +1503,8 @@ static CURLcode telnet_do(struct Curl_easy *data, bool *done)
}
if(data->set.timeout) {
- now = Curl_now();
- if(Curl_timediff(now, conn->created) >= data->set.timeout) {
+ now = curlx_now();
+ if(curlx_timediff(now, conn->created) >= data->set.timeout) {
failf(data, "Time-out");
result = CURLE_OPERATION_TIMEDOUT;
keepon = FALSE;
@@ -1569,7 +1575,7 @@ static CURLcode telnet_do(struct Curl_easy *data, bool *done)
total_dl += nread;
result = Curl_pgrsSetDownloadCounter(data, total_dl);
if(!result)
- result = telrcv(data, (unsigned char *)buffer, nread);
+ result = telrcv(data, tn, (unsigned char *)buffer, nread);
if(result) {
keepon = FALSE;
break;
@@ -1579,7 +1585,7 @@ static CURLcode telnet_do(struct Curl_easy *data, bool *done)
otherwise do not. We do not want to speak telnet with
non-telnet servers, like POP or SMTP. */
if(tn->please_negotiate && !tn->already_negotiated) {
- negotiate(data);
+ telnet_negotiate(data, tn);
tn->already_negotiated = 1;
}
}
@@ -1603,7 +1609,7 @@ static CURLcode telnet_do(struct Curl_easy *data, bool *done)
}
if(nread > 0) {
- result = send_telnet_data(data, buffer, nread);
+ result = send_telnet_data(data, tn, buffer, nread);
if(result) {
keepon = FALSE;
break;
@@ -1618,8 +1624,8 @@ static CURLcode telnet_do(struct Curl_easy *data, bool *done)
} /* poll switch statement */
if(data->set.timeout) {
- now = Curl_now();
- if(Curl_timediff(now, conn->created) >= data->set.timeout) {
+ now = curlx_now();
+ if(curlx_timediff(now, conn->created) >= data->set.timeout) {
failf(data, "Time-out");
result = CURLE_OPERATION_TIMEDOUT;
keepon = FALSE;
diff --git a/libs/libcurl/src/tftp.c b/libs/libcurl/src/tftp.c
index c1a25d7092..f6ba609797 100644
--- a/libs/libcurl/src/tftp.c
+++ b/libs/libcurl/src/tftp.c
@@ -62,7 +62,7 @@
#include "speedcheck.h"
#include "select.h"
#include "escape.h"
-#include "strparse.h"
+#include "curlx/strparse.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
@@ -121,7 +121,10 @@ struct tftp_packet {
unsigned char *data;
};
-struct tftp_state_data {
+/* meta key for storing protocol meta at connection */
+#define CURL_META_TFTP_CONN "meta:proto:tftp:conn"
+
+struct tftp_conn {
tftp_state_t state;
tftp_mode_t mode;
tftp_error_t error;
@@ -146,12 +149,9 @@ struct tftp_state_data {
/* Forward declarations */
-static CURLcode tftp_rx(struct tftp_state_data *state, tftp_event_t event);
-static CURLcode tftp_tx(struct tftp_state_data *state, tftp_event_t event);
+static CURLcode tftp_rx(struct tftp_conn *state, tftp_event_t event);
+static CURLcode tftp_tx(struct tftp_conn *state, tftp_event_t event);
static CURLcode tftp_connect(struct Curl_easy *data, bool *done);
-static CURLcode tftp_disconnect(struct Curl_easy *data,
- struct connectdata *conn,
- bool dead_connection);
static CURLcode tftp_do(struct Curl_easy *data, bool *done);
static CURLcode tftp_done(struct Curl_easy *data,
CURLcode, bool premature);
@@ -181,7 +181,7 @@ const struct Curl_handler Curl_handler_tftp = {
tftp_getsock, /* doing_getsock */
ZERO_NULL, /* domore_getsock */
ZERO_NULL, /* perform_getsock */
- tftp_disconnect, /* disconnect */
+ ZERO_NULL, /* disconnect */
ZERO_NULL, /* write_resp */
ZERO_NULL, /* write_resp_hd */
ZERO_NULL, /* connection_check */
@@ -203,7 +203,7 @@ const struct Curl_handler Curl_handler_tftp = {
*
*
**********************************************************/
-static CURLcode tftp_set_timeouts(struct tftp_state_data *state)
+static CURLcode tftp_set_timeouts(struct tftp_conn *state)
{
time_t maxtime, timeout;
timediff_t timeout_ms;
@@ -310,7 +310,7 @@ static const char *tftp_option_get(const char *buf, size_t len,
return &buf[loc];
}
-static CURLcode tftp_parse_option_ack(struct tftp_state_data *state,
+static CURLcode tftp_parse_option_ack(struct tftp_conn *state,
const char *ptr, int len)
{
const char *tmp = ptr;
@@ -332,7 +332,7 @@ static CURLcode tftp_parse_option_ack(struct tftp_state_data *state,
if(checkprefix(TFTP_OPTION_BLKSIZE, option)) {
curl_off_t blksize;
- if(Curl_str_number(&value, &blksize, TFTP_BLKSIZE_MAX)) {
+ if(curlx_str_number(&value, &blksize, TFTP_BLKSIZE_MAX)) {
failf(data, "%s (%d)", "blksize is larger than max supported",
TFTP_BLKSIZE_MAX);
return CURLE_TFTP_ILLEGAL;
@@ -364,7 +364,7 @@ static CURLcode tftp_parse_option_ack(struct tftp_state_data *state,
/* tsize should be ignored on upload: Who cares about the size of the
remote file? */
if(!data->state.upload &&
- !Curl_str_number(&value, &tsize, CURL_OFF_T_MAX)) {
+ !curlx_str_number(&value, &tsize, CURL_OFF_T_MAX)) {
if(!tsize) {
failf(data, "invalid tsize -:%s:- value in OACK packet", value);
return CURLE_TFTP_ILLEGAL;
@@ -379,7 +379,7 @@ static CURLcode tftp_parse_option_ack(struct tftp_state_data *state,
return CURLE_OK;
}
-static CURLcode tftp_option_add(struct tftp_state_data *state, size_t *csize,
+static CURLcode tftp_option_add(struct tftp_conn *state, size_t *csize,
char *buf, const char *option)
{
if(( strlen(option) + *csize + 1) > (size_t)state->blksize)
@@ -389,7 +389,7 @@ static CURLcode tftp_option_add(struct tftp_state_data *state, size_t *csize,
return CURLE_OK;
}
-static CURLcode tftp_connect_for_tx(struct tftp_state_data *state,
+static CURLcode tftp_connect_for_tx(struct tftp_conn *state,
tftp_event_t event)
{
CURLcode result;
@@ -405,7 +405,7 @@ static CURLcode tftp_connect_for_tx(struct tftp_state_data *state,
return tftp_tx(state, event);
}
-static CURLcode tftp_connect_for_rx(struct tftp_state_data *state,
+static CURLcode tftp_connect_for_rx(struct tftp_conn *state,
tftp_event_t event)
{
CURLcode result;
@@ -421,7 +421,7 @@ static CURLcode tftp_connect_for_rx(struct tftp_state_data *state,
return tftp_rx(state, event);
}
-static CURLcode tftp_send_first(struct tftp_state_data *state,
+static CURLcode tftp_send_first(struct tftp_conn *state,
tftp_event_t event)
{
size_t sbytes;
@@ -576,8 +576,7 @@ static CURLcode tftp_send_first(struct tftp_state_data *state,
* Event handler for the RX state
*
**********************************************************/
-static CURLcode tftp_rx(struct tftp_state_data *state,
- tftp_event_t event)
+static CURLcode tftp_rx(struct tftp_conn *state, tftp_event_t event)
{
ssize_t sbytes;
int rblock;
@@ -699,7 +698,7 @@ static CURLcode tftp_rx(struct tftp_state_data *state,
* Event handler for the TX state
*
**********************************************************/
-static CURLcode tftp_tx(struct tftp_state_data *state, tftp_event_t event)
+static CURLcode tftp_tx(struct tftp_conn *state, tftp_event_t event)
{
struct Curl_easy *data = state->data;
ssize_t sbytes;
@@ -901,7 +900,7 @@ static CURLcode tftp_translate_code(tftp_error_t error)
* The tftp state machine event dispatcher
*
**********************************************************/
-static CURLcode tftp_state_machine(struct tftp_state_data *state,
+static CURLcode tftp_state_machine(struct tftp_conn *state,
tftp_event_t event)
{
CURLcode result = CURLE_OK;
@@ -933,28 +932,14 @@ static CURLcode tftp_state_machine(struct tftp_state_data *state,
return result;
}
-/**********************************************************
- *
- * tftp_disconnect
- *
- * The disconnect callback
- *
- **********************************************************/
-static CURLcode tftp_disconnect(struct Curl_easy *data,
- struct connectdata *conn, bool dead_connection)
+static void tftp_conn_dtor(void *key, size_t klen, void *entry)
{
- struct tftp_state_data *state = conn->proto.tftpc;
- (void) data;
- (void) dead_connection;
-
- /* done, free dynamically allocated pkt buffers */
- if(state) {
- Curl_safefree(state->rpacket.data);
- Curl_safefree(state->spacket.data);
- free(state);
- }
-
- return CURLE_OK;
+ struct tftp_conn *state = entry;
+ (void)key;
+ (void)klen;
+ Curl_safefree(state->rpacket.data);
+ Curl_safefree(state->spacket.data);
+ free(state);
}
/**********************************************************
@@ -966,15 +951,16 @@ static CURLcode tftp_disconnect(struct Curl_easy *data,
**********************************************************/
static CURLcode tftp_connect(struct Curl_easy *data, bool *done)
{
- struct tftp_state_data *state;
+ struct tftp_conn *state;
int blksize;
int need_blksize;
struct connectdata *conn = data->conn;
blksize = TFTP_BLKSIZE_DEFAULT;
- state = conn->proto.tftpc = calloc(1, sizeof(struct tftp_state_data));
- if(!state)
+ state = calloc(1, sizeof(*state));
+ if(!state ||
+ Curl_conn_meta_set(conn, CURL_META_TFTP_CONN, state, tftp_conn_dtor))
return CURLE_OUT_OF_MEMORY;
/* alloc pkt buffers based on specified blksize */
@@ -1061,7 +1047,7 @@ static CURLcode tftp_done(struct Curl_easy *data, CURLcode status,
{
CURLcode result = CURLE_OK;
struct connectdata *conn = data->conn;
- struct tftp_state_data *state = conn->proto.tftpc;
+ struct tftp_conn *state = Curl_conn_meta_get(conn, CURL_META_TFTP_CONN);
(void)status; /* unused */
(void)premature; /* not used */
@@ -1098,12 +1084,11 @@ static int tftp_getsock(struct Curl_easy *data,
* Called once select fires and data is ready on the socket
*
**********************************************************/
-static CURLcode tftp_receive_packet(struct Curl_easy *data)
+static CURLcode tftp_receive_packet(struct Curl_easy *data,
+ struct tftp_conn *state)
{
curl_socklen_t fromlen;
CURLcode result = CURLE_OK;
- struct connectdata *conn = data->conn;
- struct tftp_state_data *state = conn->proto.tftpc;
/* Receive the packet */
fromlen = sizeof(state->remote_addr);
@@ -1182,12 +1167,10 @@ static CURLcode tftp_receive_packet(struct Curl_easy *data)
* Check if timeouts have been reached
*
**********************************************************/
-static timediff_t tftp_state_timeout(struct Curl_easy *data,
+static timediff_t tftp_state_timeout(struct tftp_conn *state,
tftp_event_t *event)
{
time_t current;
- struct connectdata *conn = data->conn;
- struct tftp_state_data *state = conn->proto.tftpc;
timediff_t timeout_ms;
if(event)
@@ -1222,11 +1205,14 @@ static CURLcode tftp_multi_statemach(struct Curl_easy *data, bool *done)
tftp_event_t event;
CURLcode result = CURLE_OK;
struct connectdata *conn = data->conn;
- struct tftp_state_data *state = conn->proto.tftpc;
- timediff_t timeout_ms = tftp_state_timeout(data, &event);
+ struct tftp_conn *state = Curl_conn_meta_get(conn, CURL_META_TFTP_CONN);
+ timediff_t timeout_ms;
*done = FALSE;
+ if(!state)
+ return CURLE_FAILED_INIT;
+ timeout_ms = tftp_state_timeout(state, &event);
if(timeout_ms < 0) {
failf(data, "TFTP response timeout");
return CURLE_OPERATION_TIMEDOUT;
@@ -1252,7 +1238,7 @@ static CURLcode tftp_multi_statemach(struct Curl_easy *data, bool *done)
state->event = TFTP_EVENT_ERROR;
}
else if(rc) {
- result = tftp_receive_packet(data);
+ result = tftp_receive_packet(data, state);
if(result)
return result;
result = tftp_state_machine(state, state->event);
@@ -1291,7 +1277,7 @@ static CURLcode tftp_doing(struct Curl_easy *data, bool *dophase_done)
if(Curl_pgrsUpdate(data))
result = CURLE_ABORTED_BY_CALLBACK;
else
- result = Curl_speedcheck(data, Curl_now());
+ result = Curl_speedcheck(data, curlx_now());
}
return result;
}
@@ -1307,9 +1293,11 @@ static CURLcode tftp_perform(struct Curl_easy *data, bool *dophase_done)
{
CURLcode result = CURLE_OK;
struct connectdata *conn = data->conn;
- struct tftp_state_data *state = conn->proto.tftpc;
+ struct tftp_conn *state = Curl_conn_meta_get(conn, CURL_META_TFTP_CONN);
*dophase_done = FALSE;
+ if(!state)
+ return CURLE_FAILED_INIT;
result = tftp_state_machine(state, TFTP_EVENT_INIT);
@@ -1337,21 +1325,21 @@ static CURLcode tftp_perform(struct Curl_easy *data, bool *dophase_done)
static CURLcode tftp_do(struct Curl_easy *data, bool *done)
{
- struct tftp_state_data *state;
- CURLcode result;
struct connectdata *conn = data->conn;
+ struct tftp_conn *state = Curl_conn_meta_get(conn, CURL_META_TFTP_CONN);
+ CURLcode result;
*done = FALSE;
- if(!conn->proto.tftpc) {
+ if(!state) {
result = tftp_connect(data, done);
if(result)
return result;
- }
- state = conn->proto.tftpc;
- if(!state)
- return CURLE_TFTP_ILLEGAL;
+ state = Curl_conn_meta_get(conn, CURL_META_TFTP_CONN);
+ if(!state)
+ return CURLE_TFTP_ILLEGAL;
+ }
result = tftp_perform(data, done);
diff --git a/libs/libcurl/src/transfer.c b/libs/libcurl/src/transfer.c
index c8434592df..e39fd04d30 100644
--- a/libs/libcurl/src/transfer.c
+++ b/libs/libcurl/src/transfer.c
@@ -470,13 +470,13 @@ CURLcode Curl_sendrecv(struct Curl_easy *data, struct curltime *nowp)
failf(data, "Operation timed out after %" FMT_TIMEDIFF_T
" milliseconds with %" FMT_OFF_T " out of %"
FMT_OFF_T " bytes received",
- Curl_timediff(*nowp, data->progress.t_startsingle),
+ curlx_timediff(*nowp, data->progress.t_startsingle),
k->bytecount, k->size);
}
else {
failf(data, "Operation timed out after %" FMT_TIMEDIFF_T
" milliseconds with %" FMT_OFF_T " bytes received",
- Curl_timediff(*nowp, data->progress.t_startsingle),
+ curlx_timediff(*nowp, data->progress.t_startsingle),
k->bytecount);
}
result = CURLE_OPERATION_TIMEDOUT;
diff --git a/libs/libcurl/src/uint-bset.c b/libs/libcurl/src/uint-bset.c
new file mode 100644
index 0000000000..5103aab010
--- /dev/null
+++ b/libs/libcurl/src/uint-bset.c
@@ -0,0 +1,238 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+#include "uint-bset.h"
+
+/* The last 3 #include files should be in this order */
+#include "curl_printf.h"
+#include "curl_memory.h"
+#include "memdebug.h"
+
+#ifdef DEBUGBUILD
+#define CURL_UINT_BSET_MAGIC 0x62757473
+#endif
+
+void Curl_uint_bset_init(struct uint_bset *bset)
+{
+ memset(bset, 0, sizeof(*bset));
+#ifdef DEBUGBUILD
+ bset->init = CURL_UINT_BSET_MAGIC;
+#endif
+}
+
+
+CURLcode Curl_uint_bset_resize(struct uint_bset *bset, unsigned int nmax)
+{
+ unsigned int nslots = (nmax + 63) / 64;
+
+ DEBUGASSERT(bset->init == CURL_UINT_BSET_MAGIC);
+ if(nslots != bset->nslots) {
+ curl_uint64_t *slots = calloc(nslots, sizeof(curl_uint64_t));
+ if(!slots)
+ return CURLE_OUT_OF_MEMORY;
+
+ if(bset->slots) {
+ memcpy(slots, bset->slots,
+ (CURLMIN(nslots, bset->nslots) * sizeof(curl_uint64_t)));
+ free(bset->slots);
+ }
+ bset->slots = slots;
+ bset->nslots = nslots;
+ }
+ return CURLE_OK;
+}
+
+
+void Curl_uint_bset_destroy(struct uint_bset *bset)
+{
+ DEBUGASSERT(bset->init == CURL_UINT_BSET_MAGIC);
+ free(bset->slots);
+ memset(bset, 0, sizeof(*bset));
+}
+
+
+unsigned int Curl_uint_bset_capacity(struct uint_bset *bset)
+{
+ return bset->nslots * 64;
+}
+
+
+unsigned int Curl_uint_bset_count(struct uint_bset *bset)
+{
+ unsigned int i;
+ unsigned int n = 0;
+ for(i = 0; i < bset->nslots; ++i) {
+ if(bset->slots[i])
+ n += CURL_POPCOUNT64(bset->slots[i]);
+ }
+ return n;
+}
+
+
+bool Curl_uint_bset_empty(struct uint_bset *bset)
+{
+ unsigned int i;
+ for(i = 0; i < bset->nslots; ++i) {
+ if(bset->slots[i])
+ return FALSE;
+ }
+ return TRUE;
+}
+
+
+void Curl_uint_bset_clear(struct uint_bset *bset)
+{
+ if(bset->nslots)
+ memset(bset->slots, 0, bset->nslots * sizeof(curl_uint64_t));
+}
+
+
+bool Curl_uint_bset_add(struct uint_bset *bset, unsigned int i)
+{
+ unsigned int islot = i / 64;
+ if(islot >= bset->nslots)
+ return FALSE;
+ bset->slots[islot] |= ((curl_uint64_t)1 << (i % 64));
+ return TRUE;
+}
+
+
+void Curl_uint_bset_remove(struct uint_bset *bset, unsigned int i)
+{
+ size_t islot = i / 64;
+ if(islot < bset->nslots)
+ bset->slots[islot] &= ~((curl_uint64_t)1 << (i % 64));
+}
+
+
+bool Curl_uint_bset_contains(struct uint_bset *bset, unsigned int i)
+{
+ unsigned int islot = i / 64;
+ if(islot >= bset->nslots)
+ return FALSE;
+ return (bset->slots[islot] & ((curl_uint64_t)1 << (i % 64))) != 0;
+}
+
+
+bool Curl_uint_bset_first(struct uint_bset *bset, unsigned int *pfirst)
+{
+ unsigned int i;
+ for(i = 0; i < bset->nslots; ++i) {
+ if(bset->slots[i]) {
+ *pfirst = (i * 64) + CURL_CTZ64(bset->slots[i]);
+ return TRUE;
+ }
+ }
+ *pfirst = UINT_MAX; /* a value we cannot store */
+ return FALSE;
+}
+
+bool Curl_uint_bset_next(struct uint_bset *bset, unsigned int last,
+ unsigned int *pnext)
+{
+ unsigned int islot;
+ curl_uint64_t x;
+
+ ++last; /* look for number one higher than last */
+ islot = last / 64; /* the slot this would be in */
+ if(islot < bset->nslots) {
+ /* shift away the bits we already iterated in this slot */
+ x = (bset->slots[islot] >> (last % 64));
+ if(x) {
+ /* more bits set, next is `last` + trailing0s of the shifted slot */
+ *pnext = last + CURL_CTZ64(x);
+ return TRUE;
+ }
+ /* no more bits set in the last slot, scan forward */
+ for(islot = islot + 1; islot < bset->nslots; ++islot) {
+ if(bset->slots[islot]) {
+ *pnext = (islot * 64) + CURL_CTZ64(bset->slots[islot]);
+ return TRUE;
+ }
+ }
+ }
+ *pnext = UINT_MAX; /* a value we cannot store */
+ return FALSE;
+}
+
+#ifdef CURL_POPCOUNT64_IMPLEMENT
+unsigned int Curl_popcount64(curl_uint64_t x)
+{
+ /* Compute the "Hamming Distance" between 'x' and 0,
+ * which is the number of set bits in 'x'.
+ * See: https://en.wikipedia.org/wiki/Hamming_weight */
+ const curl_uint64_t m1 = CURL_OFF_TU_C(0x5555555555555555); /* 0101+ */
+ const curl_uint64_t m2 = CURL_OFF_TU_C(0x3333333333333333); /* 00110011+ */
+ const curl_uint64_t m4 = CURL_OFF_TU_C(0x0f0f0f0f0f0f0f0f); /* 00001111+ */
+ /* 1 + 256^1 + 256^2 + 256^3 + ... + 256^7 */
+ const curl_uint64_t h01 = CURL_OFF_TU_C(0x0101010101010101);
+ x -= (x >> 1) & m1; /* replace every 2 bits with bits present */
+ x = (x & m2) + ((x >> 2) & m2); /* replace every nibble with bits present */
+ x = (x + (x >> 4)) & m4; /* replace every byte with bits present */
+ /* top 8 bits of x + (x<<8) + (x<<16) + (x<<24) + ... which makes the
+ * top byte the sum of all individual 8 bytes, throw away the rest */
+ return (unsigned int)((x * h01) >> 56);
+}
+#endif /* CURL_POPCOUNT64_IMPLEMENT */
+
+
+#ifdef CURL_CTZ64_IMPLEMENT
+unsigned int Curl_ctz64(curl_uint64_t x)
+{
+ /* count trailing zeros in a curl_uint64_t.
+ * divide and conquer to find the number of lower 0 bits */
+ const curl_uint64_t ml32 = CURL_OFF_TU_C(0xFFFFFFFF); /* lower 32 bits */
+ const curl_uint64_t ml16 = CURL_OFF_TU_C(0x0000FFFF); /* lower 16 bits */
+ const curl_uint64_t ml8 = CURL_OFF_TU_C(0x000000FF); /* lower 8 bits */
+ const curl_uint64_t ml4 = CURL_OFF_TU_C(0x0000000F); /* lower 4 bits */
+ const curl_uint64_t ml2 = CURL_OFF_TU_C(0x00000003); /* lower 2 bits */
+ unsigned int n;
+
+ if(!x)
+ return 64;
+ n = 1;
+ if(!(x & ml32)) {
+ n = n + 32;
+ x = x >> 32;
+ }
+ if(!(x & ml16)) {
+ n = n + 16;
+ x = x >> 16;
+ }
+ if(!(x & ml8)) {
+ n = n + 8;
+ x = x >> 8;
+ }
+ if(!(x & ml4)) {
+ n = n + 4;
+ x = x >> 4;
+ }
+ if(!(x & ml2)) {
+ n = n + 2;
+ x = x >> 2;
+ }
+ return n - (unsigned int)(x & 1);
+}
+#endif /* CURL_CTZ64_IMPLEMENT */
diff --git a/libs/libcurl/src/uint-bset.h b/libs/libcurl/src/uint-bset.h
new file mode 100644
index 0000000000..7eab4f44bf
--- /dev/null
+++ b/libs/libcurl/src/uint-bset.h
@@ -0,0 +1,114 @@
+#ifndef HEADER_CURL_UINT_BSET_H
+#define HEADER_CURL_UINT_BSET_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "curl_setup.h"
+
+#include <curl/curl.h>
+
+/* A bitset for unsigned int values.
+ * It can hold the numbers from 0 - (nmax - 1),
+ * rounded to the next 64 multiple.
+ *
+ * Optimized for high efficiency in adding/removing numbers.
+ * Efficient storage when the set is (often) relatively full.
+ *
+ * If the set's cardinality is only expected to be a fraction of nmax,
+ * uint_spbset offers a "sparse" variant with more memory efficiency at
+ * the price of slightly slower operations.
+ */
+
+struct uint_bset {
+ curl_uint64_t *slots;
+ unsigned int nslots;
+#ifdef DEBUGBUILD
+ int init;
+#endif
+};
+
+/* Initialize the bitset with capacity 0. */
+void Curl_uint_bset_init(struct uint_bset *bset);
+
+/* Resize the bitset capacity to hold numbers from 0 to `nmax`,
+ * which rounds up `nmax` to the next multiple of 64. */
+CURLcode Curl_uint_bset_resize(struct uint_bset *bset, unsigned int nmax);
+
+/* Destroy the bitset, freeing all resources. */
+void Curl_uint_bset_destroy(struct uint_bset *bset);
+
+/* Get the bitset capacity, e.g. can hold numbers from 0 to capacity - 1. */
+unsigned int Curl_uint_bset_capacity(struct uint_bset *bset);
+
+/* Get the cardinality of the bitset, e.g. numbers present in the set. */
+unsigned int Curl_uint_bset_count(struct uint_bset *bset);
+
+/* TRUE of bitset is empty */
+bool Curl_uint_bset_empty(struct uint_bset *bset);
+
+/* Clear the bitset, making it empty. */
+void Curl_uint_bset_clear(struct uint_bset *bset);
+
+/* Add the number `i` to the bitset. Return FALSE if the number is
+ * outside the set's capacity.
+ * Numbers can be added more than once, without making a difference. */
+bool Curl_uint_bset_add(struct uint_bset *bset, unsigned int i);
+
+/* Remove the number `i` from the bitset. */
+void Curl_uint_bset_remove(struct uint_bset *bset, unsigned int i);
+
+/* Return TRUE if the bitset contains number `i`. */
+bool Curl_uint_bset_contains(struct uint_bset *bset, unsigned int i);
+
+/* Get the first number in the bitset, e.g. the smallest.
+ * Returns FALSE when the bitset is empty. */
+bool Curl_uint_bset_first(struct uint_bset *bset, unsigned int *pfirst);
+
+/* Get the next number in the bitset, following `last` in natural order.
+ * Put another way, this is the smallest number greater than `last` in
+ * the bitset. `last` does not have to be present in the set.
+ *
+ * Returns FALSE when no such number is in the set.
+ *
+ * This allows to iterate the set while being modified:
+ * - added numbers higher than 'last' will be picked up by the iteration.
+ * - added numbers lower than 'last' will not show up.
+ * - removed numbers lower or equal to 'last' will not show up.
+ * - removed numbers higher than 'last' will not be visited. */
+bool Curl_uint_bset_next(struct uint_bset *bset, unsigned int last,
+ unsigned int *pnext);
+
+
+#ifndef CURL_POPCOUNT64
+#define CURL_POPCOUNT64(x) Curl_popcount64(x)
+#define CURL_POPCOUNT64_IMPLEMENT
+unsigned int Curl_popcount64(curl_uint64_t x);
+#endif /* !CURL_POPCOUNT64 */
+
+#ifndef CURL_CTZ64
+#define CURL_CTZ64(x) Curl_ctz64(x)
+#define CURL_CTZ64_IMPLEMENT
+unsigned int Curl_ctz64(curl_uint64_t x);
+#endif /* !CURL_CTZ64 */
+
+#endif /* HEADER_CURL_UINT_BSET_H */
diff --git a/libs/libcurl/src/hash_offt.c b/libs/libcurl/src/uint-hash.c
index 96ff500307..8257813bd2 100644
--- a/libs/libcurl/src/hash_offt.c
+++ b/libs/libcurl/src/uint-hash.c
@@ -26,7 +26,7 @@
#include <curl/curl.h>
-#include "hash_offt.h"
+#include "uint-hash.h"
#include "curl_memory.h"
/* The last #include file should be: */
@@ -34,23 +34,24 @@
/* random patterns for API verification */
#ifdef DEBUGBUILD
-#define CURL_HASHOFFTINIT 0x7117e781
+#define CURL_UINTHASHINIT 0x7117e779
#endif
-static size_t hash_offt_hash(curl_off_t id, size_t slots)
+static unsigned int uint_hash_hash(unsigned int id, unsigned int slots)
{
- return (size_t)((id >= 0) ? (id % slots) : (-id % slots));
+ return (id % slots);
}
-struct Curl_hash_offt_entry {
- curl_off_t id;
- struct Curl_hash_offt_entry *next;
+
+struct uint_hash_entry {
+ struct uint_hash_entry *next;
void *value;
+ unsigned int id;
};
-void Curl_hash_offt_init(struct Curl_hash_offt *h,
- size_t slots,
- Curl_hash_offt_dtor *dtor)
+void Curl_uint_hash_init(struct uint_hash *h,
+ unsigned int slots,
+ Curl_uint_hash_dtor *dtor)
{
DEBUGASSERT(h);
DEBUGASSERT(slots);
@@ -60,14 +61,13 @@ void Curl_hash_offt_init(struct Curl_hash_offt *h,
h->size = 0;
h->slots = slots;
#ifdef DEBUGBUILD
- h->init = CURL_HASHOFFTINIT;
+ h->init = CURL_UINTHASHINIT;
#endif
}
-static struct Curl_hash_offt_entry *
-hash_offt_mk_entry(curl_off_t id, void *value)
+static struct uint_hash_entry *uint_hash_mk_entry(unsigned int id, void *value)
{
- struct Curl_hash_offt_entry *e;
+ struct uint_hash_entry *e;
/* allocate the struct for the hash entry */
e = malloc(sizeof(*e));
@@ -79,8 +79,8 @@ hash_offt_mk_entry(curl_off_t id, void *value)
return e;
}
-static void hash_offt_entry_clear(struct Curl_hash_offt *h,
- struct Curl_hash_offt_entry *e)
+static void uint_hash_entry_clear(struct uint_hash *h,
+ struct uint_hash_entry *e)
{
DEBUGASSERT(h);
DEBUGASSERT(e);
@@ -91,78 +91,78 @@ static void hash_offt_entry_clear(struct Curl_hash_offt *h,
}
}
-static void hash_offt_entry_destroy(struct Curl_hash_offt *h,
- struct Curl_hash_offt_entry *e)
+static void uint_hash_entry_destroy(struct uint_hash *h,
+ struct uint_hash_entry *e)
{
- hash_offt_entry_clear(h, e);
+ uint_hash_entry_clear(h, e);
free(e);
}
-static void hash_offt_entry_unlink(struct Curl_hash_offt *h,
- struct Curl_hash_offt_entry **he_anchor,
- struct Curl_hash_offt_entry *he)
+static void uint_hash_entry_unlink(struct uint_hash *h,
+ struct uint_hash_entry **he_anchor,
+ struct uint_hash_entry *he)
{
*he_anchor = he->next;
--h->size;
}
-static void hash_offtr_elem_link(struct Curl_hash_offt *h,
- struct Curl_hash_offt_entry **he_anchor,
- struct Curl_hash_offt_entry *he)
+static void uint_hash_elem_link(struct uint_hash *h,
+ struct uint_hash_entry **he_anchor,
+ struct uint_hash_entry *he)
{
he->next = *he_anchor;
*he_anchor = he;
++h->size;
}
-#define CURL_HASH_OFFT_SLOT(h,id) h->table[hash_offt_hash(id, h->slots)]
-#define CURL_HASH_OFFT_SLOT_ADDR(h,id) &CURL_HASH_OFFT_SLOT(h,id)
+#define CURL_UINT_HASH_SLOT(h,id) h->table[uint_hash_hash(id, h->slots)]
+#define CURL_UINT_HASH_SLOT_ADDR(h,id) &CURL_UINT_HASH_SLOT(h,id)
-bool Curl_hash_offt_set(struct Curl_hash_offt *h, curl_off_t id, void *value)
+bool Curl_uint_hash_set(struct uint_hash *h, unsigned int id, void *value)
{
- struct Curl_hash_offt_entry *he, **slot;
+ struct uint_hash_entry *he, **slot;
DEBUGASSERT(h);
DEBUGASSERT(h->slots);
- DEBUGASSERT(h->init == CURL_HASHOFFTINIT);
+ DEBUGASSERT(h->init == CURL_UINTHASHINIT);
if(!h->table) {
h->table = calloc(h->slots, sizeof(*he));
if(!h->table)
return FALSE; /* OOM */
}
- slot = CURL_HASH_OFFT_SLOT_ADDR(h, id);
+ slot = CURL_UINT_HASH_SLOT_ADDR(h, id);
for(he = *slot; he; he = he->next) {
if(he->id == id) {
/* existing key entry, overwrite by clearing old pointer */
- hash_offt_entry_clear(h, he);
+ uint_hash_entry_clear(h, he);
he->value = value;
return TRUE;
}
}
- he = hash_offt_mk_entry(id, value);
+ he = uint_hash_mk_entry(id, value);
if(!he)
return FALSE; /* OOM */
- hash_offtr_elem_link(h, slot, he);
+ uint_hash_elem_link(h, slot, he);
return TRUE;
}
-bool Curl_hash_offt_remove(struct Curl_hash_offt *h, curl_off_t id)
+bool Curl_uint_hash_remove(struct uint_hash *h, unsigned int id)
{
DEBUGASSERT(h);
DEBUGASSERT(h->slots);
- DEBUGASSERT(h->init == CURL_HASHOFFTINIT);
+ DEBUGASSERT(h->init == CURL_UINTHASHINIT);
if(h->table) {
- struct Curl_hash_offt_entry *he, **he_anchor;
+ struct uint_hash_entry *he, **he_anchor;
- he_anchor = CURL_HASH_OFFT_SLOT_ADDR(h, id);
+ he_anchor = CURL_UINT_HASH_SLOT_ADDR(h, id);
while(*he_anchor) {
he = *he_anchor;
if(id == he->id) {
- hash_offt_entry_unlink(h, he_anchor, he);
- hash_offt_entry_destroy(h, he);
+ uint_hash_entry_unlink(h, he_anchor, he);
+ uint_hash_entry_destroy(h, he);
return TRUE;
}
he_anchor = &he->next;
@@ -171,14 +171,14 @@ bool Curl_hash_offt_remove(struct Curl_hash_offt *h, curl_off_t id)
return FALSE;
}
-void *Curl_hash_offt_get(struct Curl_hash_offt *h, curl_off_t id)
+void *Curl_uint_hash_get(struct uint_hash *h, unsigned int id)
{
DEBUGASSERT(h);
- DEBUGASSERT(h->init == CURL_HASHOFFTINIT);
+ DEBUGASSERT(h->init == CURL_UINTHASHINIT);
if(h->table) {
- struct Curl_hash_offt_entry *he;
+ struct uint_hash_entry *he;
DEBUGASSERT(h->slots);
- he = CURL_HASH_OFFT_SLOT(h, id);
+ he = CURL_UINT_HASH_SLOT(h, id);
while(he) {
if(id == he->id) {
return he->value;
@@ -189,49 +189,53 @@ void *Curl_hash_offt_get(struct Curl_hash_offt *h, curl_off_t id)
return NULL;
}
-void Curl_hash_offt_clear(struct Curl_hash_offt *h)
+static void uint_hash_clear(struct uint_hash *h)
{
if(h && h->table) {
- struct Curl_hash_offt_entry *he, **he_anchor;
+ struct uint_hash_entry *he, **he_anchor;
size_t i;
- DEBUGASSERT(h->init == CURL_HASHOFFTINIT);
+ DEBUGASSERT(h->init == CURL_UINTHASHINIT);
for(i = 0; i < h->slots; ++i) {
he_anchor = &h->table[i];
while(*he_anchor) {
he = *he_anchor;
- hash_offt_entry_unlink(h, he_anchor, he);
- hash_offt_entry_destroy(h, he);
+ uint_hash_entry_unlink(h, he_anchor, he);
+ uint_hash_entry_destroy(h, he);
}
}
}
}
-void
-Curl_hash_offt_destroy(struct Curl_hash_offt *h)
+void Curl_uint_hash_clear(struct uint_hash *h)
+{
+ uint_hash_clear(h);
+}
+
+void Curl_uint_hash_destroy(struct uint_hash *h)
{
- DEBUGASSERT(h->init == CURL_HASHOFFTINIT);
+ DEBUGASSERT(h->init == CURL_UINTHASHINIT);
if(h->table) {
- Curl_hash_offt_clear(h);
+ uint_hash_clear(h);
Curl_safefree(h->table);
}
DEBUGASSERT(h->size == 0);
h->slots = 0;
}
-size_t Curl_hash_offt_count(struct Curl_hash_offt *h)
+unsigned int Curl_uint_hash_count(struct uint_hash *h)
{
- DEBUGASSERT(h->init == CURL_HASHOFFTINIT);
+ DEBUGASSERT(h->init == CURL_UINTHASHINIT);
return h->size;
}
-void Curl_hash_offt_visit(struct Curl_hash_offt *h,
- Curl_hash_offt_visit_cb *cb,
+void Curl_uint_hash_visit(struct uint_hash *h,
+ Curl_uint_hash_visit_cb *cb,
void *user_data)
{
if(h && h->table && cb) {
- struct Curl_hash_offt_entry *he;
+ struct uint_hash_entry *he;
size_t i;
- DEBUGASSERT(h->init == CURL_HASHOFFTINIT);
+ DEBUGASSERT(h->init == CURL_UINTHASHINIT);
for(i = 0; i < h->slots; ++i) {
for(he = h->table[i]; he; he = he->next) {
if(!cb(he->id, he->value, user_data))
diff --git a/libs/libcurl/src/hash_offt.h b/libs/libcurl/src/uint-hash.h
index 66eb703b11..d2e60c5faf 100644
--- a/libs/libcurl/src/hash_offt.h
+++ b/libs/libcurl/src/uint-hash.h
@@ -1,5 +1,5 @@
-#ifndef HEADER_CURL_HASH_OFFT_H
-#define HEADER_CURL_HASH_OFFT_H
+#ifndef HEADER_CURL_UINT_HASH_H
+#define HEADER_CURL_UINT_HASH_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
@@ -30,38 +30,39 @@
#include "llist.h"
-struct Curl_hash_offt_entry;
-typedef void Curl_hash_offt_dtor(curl_off_t id, void *value);
+/* A version with unsigned int as key */
+typedef void Curl_uint_hash_dtor(unsigned int id, void *value);
+struct uint_hash_entry;
-/* Hash for `curl_off_t` as key */
-struct Curl_hash_offt {
- struct Curl_hash_offt_entry **table;
- Curl_hash_offt_dtor *dtor;
- size_t slots;
- size_t size;
+/* Hash for `unsigned int` as key */
+struct uint_hash {
+ struct uint_hash_entry **table;
+ Curl_uint_hash_dtor *dtor;
+ unsigned int slots;
+ unsigned int size;
#ifdef DEBUGBUILD
int init;
#endif
};
-void Curl_hash_offt_init(struct Curl_hash_offt *h,
- size_t slots,
- Curl_hash_offt_dtor *dtor);
-void Curl_hash_offt_destroy(struct Curl_hash_offt *h);
-bool Curl_hash_offt_set(struct Curl_hash_offt *h, curl_off_t id, void *value);
-bool Curl_hash_offt_remove(struct Curl_hash_offt *h, curl_off_t id);
-void *Curl_hash_offt_get(struct Curl_hash_offt *h, curl_off_t id);
-void Curl_hash_offt_clear(struct Curl_hash_offt *h);
-size_t Curl_hash_offt_count(struct Curl_hash_offt *h);
+void Curl_uint_hash_init(struct uint_hash *h,
+ unsigned int slots,
+ Curl_uint_hash_dtor *dtor);
+void Curl_uint_hash_destroy(struct uint_hash *h);
+void Curl_uint_hash_clear(struct uint_hash *h);
+bool Curl_uint_hash_set(struct uint_hash *h, unsigned int id, void *value);
+bool Curl_uint_hash_remove(struct uint_hash *h, unsigned int id);
+void *Curl_uint_hash_get(struct uint_hash *h, unsigned int id);
+unsigned int Curl_uint_hash_count(struct uint_hash *h);
-typedef bool Curl_hash_offt_visit_cb(curl_off_t id, void *value,
+
+typedef bool Curl_uint_hash_visit_cb(unsigned int id, void *value,
void *user_data);
-void Curl_hash_offt_visit(struct Curl_hash_offt *h,
- Curl_hash_offt_visit_cb *cb,
+void Curl_uint_hash_visit(struct uint_hash *h,
+ Curl_uint_hash_visit_cb *cb,
void *user_data);
-
-#endif /* HEADER_CURL_HASH_OFFT_H */
+#endif /* HEADER_CURL_UINT_HASH_H */
diff --git a/libs/libcurl/src/uint-spbset.c b/libs/libcurl/src/uint-spbset.c
new file mode 100644
index 0000000000..cd367f2799
--- /dev/null
+++ b/libs/libcurl/src/uint-spbset.c
@@ -0,0 +1,273 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+#include "uint-bset.h"
+#include "uint-spbset.h"
+
+/* The last 3 #include files should be in this order */
+#include "curl_printf.h"
+#include "curl_memory.h"
+#include "memdebug.h"
+
+#ifdef DEBUGBUILD
+#define CURL_UINT_SPBSET_MAGIC 0x70737362
+#endif
+
+void Curl_uint_spbset_init(struct uint_spbset *bset)
+{
+ memset(bset, 0, sizeof(*bset));
+#ifdef DEBUGBUILD
+ bset->init = CURL_UINT_SPBSET_MAGIC;
+#endif
+}
+
+void Curl_uint_spbset_destroy(struct uint_spbset *bset)
+{
+ DEBUGASSERT(bset->init == CURL_UINT_SPBSET_MAGIC);
+ Curl_uint_spbset_clear(bset);
+}
+
+unsigned int Curl_uint_spbset_count(struct uint_spbset *bset)
+{
+ struct uint_spbset_chunk *chunk;
+ unsigned int i, n = 0;
+
+ for(chunk = &bset->head; chunk; chunk = chunk->next) {
+ for(i = 0; i < CURL_UINT_SPBSET_CH_SLOTS; ++i) {
+ if(chunk->slots[i])
+ n += CURL_POPCOUNT64(chunk->slots[i]);
+ }
+ }
+ return n;
+}
+
+bool Curl_uint_spbset_empty(struct uint_spbset *bset)
+{
+ struct uint_spbset_chunk *chunk;
+ unsigned int i;
+
+ for(chunk = &bset->head; chunk; chunk = chunk->next) {
+ for(i = 0; i < CURL_UINT_SPBSET_CH_SLOTS; ++i) {
+ if(chunk->slots[i])
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
+void Curl_uint_spbset_clear(struct uint_spbset *bset)
+{
+ struct uint_spbset_chunk *next, *chunk;
+
+ for(chunk = bset->head.next; chunk; chunk = next) {
+ next = chunk->next;
+ free(chunk);
+ }
+ memset(&bset->head, 0, sizeof(bset->head));
+}
+
+
+static struct uint_spbset_chunk *
+uint_spbset_get_chunk(struct uint_spbset *bset, unsigned int i, bool grow)
+{
+ struct uint_spbset_chunk *chunk, **panchor = NULL;
+ unsigned int i_offset = (i & ~CURL_UINT_SPBSET_CH_MASK);
+
+ if(!bset)
+ return NULL;
+
+ for(chunk = &bset->head; chunk;
+ panchor = &chunk->next, chunk = chunk->next) {
+ if(chunk->offset == i_offset) {
+ return chunk;
+ }
+ else if(chunk->offset > i_offset) {
+ /* need new chunk here */
+ chunk = NULL;
+ break;
+ }
+ }
+
+ if(!grow)
+ return NULL;
+
+ /* need a new one */
+ chunk = calloc(1, sizeof(*chunk));
+ if(!chunk)
+ return NULL;
+
+ if(panchor) { /* insert between panchor and *panchor */
+ chunk->next = *panchor;
+ *panchor = chunk;
+ }
+ else { /* prepend to head, switching places */
+ memcpy(chunk, &bset->head, sizeof(*chunk));
+ memset(&bset->head, 0, sizeof(bset->head));
+ bset->head.next = chunk;
+ }
+ chunk->offset = i_offset;
+ return chunk;
+}
+
+
+bool Curl_uint_spbset_add(struct uint_spbset *bset, unsigned int i)
+{
+ struct uint_spbset_chunk *chunk;
+ unsigned int i_chunk;
+
+ chunk = uint_spbset_get_chunk(bset, i, TRUE);
+ if(!chunk)
+ return FALSE;
+
+ DEBUGASSERT(i >= chunk->offset);
+ i_chunk = (i - chunk->offset);
+ DEBUGASSERT((i_chunk / 64) < CURL_UINT_SPBSET_CH_SLOTS);
+ chunk->slots[(i_chunk / 64)] |= ((curl_uint64_t)1 << (i_chunk % 64));
+ return TRUE;
+}
+
+
+void Curl_uint_spbset_remove(struct uint_spbset *bset, unsigned int i)
+{
+ struct uint_spbset_chunk *chunk;
+ unsigned int i_chunk;
+
+ chunk = uint_spbset_get_chunk(bset, i, FALSE);
+ if(chunk) {
+ DEBUGASSERT(i >= chunk->offset);
+ i_chunk = (i - chunk->offset);
+ DEBUGASSERT((i_chunk / 64) < CURL_UINT_SPBSET_CH_SLOTS);
+ chunk->slots[(i_chunk / 64)] &= ~((curl_uint64_t)1 << (i_chunk % 64));
+ }
+}
+
+
+bool Curl_uint_spbset_contains(struct uint_spbset *bset, unsigned int i)
+{
+ struct uint_spbset_chunk *chunk;
+ unsigned int i_chunk;
+
+ chunk = uint_spbset_get_chunk(bset, i, FALSE);
+ if(chunk) {
+ DEBUGASSERT(i >= chunk->offset);
+ i_chunk = (i - chunk->offset);
+ DEBUGASSERT((i_chunk / 64) < CURL_UINT_SPBSET_CH_SLOTS);
+ return (chunk->slots[i_chunk / 64] &
+ ((curl_uint64_t)1 << (i_chunk % 64))) != 0;
+ }
+ return FALSE;
+}
+
+bool Curl_uint_spbset_first(struct uint_spbset *bset, unsigned int *pfirst)
+{
+ struct uint_spbset_chunk *chunk;
+ unsigned int i;
+
+ for(chunk = &bset->head; chunk; chunk = chunk->next) {
+ for(i = 0; i < CURL_UINT_SPBSET_CH_SLOTS; ++i) {
+ if(chunk->slots[i]) {
+ *pfirst = chunk->offset + ((i * 64) + CURL_CTZ64(chunk->slots[i]));
+ return TRUE;
+ }
+ }
+ }
+ *pfirst = 0; /* give it a defined value even if it should not be used */
+ return FALSE;
+}
+
+
+static bool uint_spbset_chunk_first(struct uint_spbset_chunk *chunk,
+ unsigned int *pfirst)
+{
+ unsigned int i;
+ for(i = 0; i < CURL_UINT_SPBSET_CH_SLOTS; ++i) {
+ if(chunk->slots[i]) {
+ *pfirst = chunk->offset + ((i * 64) + CURL_CTZ64(chunk->slots[i]));
+ return TRUE;
+ }
+ }
+ *pfirst = UINT_MAX; /* a value we cannot store */
+ return FALSE;
+}
+
+
+static bool uint_spbset_chunk_next(struct uint_spbset_chunk *chunk,
+ unsigned int last,
+ unsigned int *pnext)
+{
+ if(chunk->offset <= last) {
+ curl_uint64_t x;
+ unsigned int i = ((last - chunk->offset) / 64);
+ if(i < CURL_UINT_SPBSET_CH_SLOTS) {
+ x = (chunk->slots[i] >> (last % 64));
+ if(x) {
+ /* more bits set, next is `last` + trailing0s of the shifted slot */
+ *pnext = last + CURL_CTZ64(x);
+ return TRUE;
+ }
+ /* no more bits set in the last slot, scan forward */
+ for(i = i + 1; i < CURL_UINT_SPBSET_CH_SLOTS; ++i) {
+ if(chunk->slots[i]) {
+ *pnext = chunk->offset + ((i * 64) + CURL_CTZ64(chunk->slots[i]));
+ return TRUE;
+ }
+ }
+ }
+ }
+ *pnext = UINT_MAX;
+ return FALSE;
+}
+
+bool Curl_uint_spbset_next(struct uint_spbset *bset, unsigned int last,
+ unsigned int *pnext)
+{
+ struct uint_spbset_chunk *chunk;
+ unsigned int last_offset;
+
+ ++last; /* look for the next higher number */
+ last_offset = (last & ~CURL_UINT_SPBSET_CH_MASK);
+
+ for(chunk = &bset->head; chunk; chunk = chunk->next) {
+ if(chunk->offset >= last_offset) {
+ break;
+ }
+ }
+
+ if(chunk && (chunk->offset == last_offset)) {
+ /* is there a number higher than last in this chunk? */
+ if(uint_spbset_chunk_next(chunk, last, pnext))
+ return TRUE;
+ /* not in this chunk */
+ chunk = chunk->next;
+ }
+ /* look for the first in the "higher" chunks, if there are any. */
+ while(chunk) {
+ if(uint_spbset_chunk_first(chunk, pnext))
+ return TRUE;
+ chunk = chunk->next;
+ }
+ *pnext = UINT_MAX;
+ return FALSE;
+}
diff --git a/libs/libcurl/src/uint-spbset.h b/libs/libcurl/src/uint-spbset.h
new file mode 100644
index 0000000000..060a0e6c0f
--- /dev/null
+++ b/libs/libcurl/src/uint-spbset.h
@@ -0,0 +1,99 @@
+#ifndef HEADER_CURL_UINT_SPBSET_H
+#define HEADER_CURL_UINT_SPBSET_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "curl_setup.h"
+
+#include <curl/curl.h>
+
+/* A "sparse" bitset for unsigned int values.
+ * It can hold any unsigned int value.
+ *
+ * Optimized for the case where only a small set of numbers need
+ * to be kept, especially when "close" together. Then storage space
+ * is most efficient, deteriorating when many number are far apart.
+ */
+
+/* 4 slots = 256 bits, keep this a 2^n value. */
+#define CURL_UINT_SPBSET_CH_SLOTS 4
+#define CURL_UINT_SPBSET_CH_MASK ((CURL_UINT_SPBSET_CH_SLOTS * 64) - 1)
+
+/* store the uint value from offset to
+ * (offset + (CURL_UINT_SPBSET_CHUNK_SLOTS * 64) - 1 */
+struct uint_spbset_chunk {
+ struct uint_spbset_chunk *next;
+ curl_uint64_t slots[CURL_UINT_SPBSET_CH_SLOTS];
+ unsigned int offset;
+};
+
+struct uint_spbset {
+ struct uint_spbset_chunk head;
+#ifdef DEBUGBUILD
+ int init;
+#endif
+};
+
+void Curl_uint_spbset_init(struct uint_spbset *bset);
+
+void Curl_uint_spbset_destroy(struct uint_spbset *bset);
+
+/* Get the cardinality of the bitset, e.g. numbers present in the set. */
+unsigned int Curl_uint_spbset_count(struct uint_spbset *bset);
+
+/* TRUE of bitset is empty */
+bool Curl_uint_spbset_empty(struct uint_spbset *bset);
+
+/* Clear the bitset, making it empty. */
+void Curl_uint_spbset_clear(struct uint_spbset *bset);
+
+/* Add the number `i` to the bitset.
+ * Numbers can be added more than once, without making a difference.
+ * Returns FALSE if allocations failed. */
+bool Curl_uint_spbset_add(struct uint_spbset *bset, unsigned int i);
+
+/* Remove the number `i` from the bitset. */
+void Curl_uint_spbset_remove(struct uint_spbset *bset, unsigned int i);
+
+/* Return TRUE if the bitset contains number `i`. */
+bool Curl_uint_spbset_contains(struct uint_spbset *bset, unsigned int i);
+
+/* Get the first number in the bitset, e.g. the smallest.
+ * Returns FALSE when the bitset is empty. */
+bool Curl_uint_spbset_first(struct uint_spbset *bset, unsigned int *pfirst);
+
+/* Get the next number in the bitset, following `last` in natural order.
+ * Put another way, this is the smallest number greater than `last` in
+ * the bitset. `last` does not have to be present in the set.
+ *
+ * Returns FALSE when no such number is in the set.
+ *
+ * This allows to iterate the set while being modified:
+ * - added numbers higher than 'last' will be picked up by the iteration.
+ * - added numbers lower than 'last' will not show up.
+ * - removed numbers lower or equal to 'last' will not show up.
+ * - removed numbers higher than 'last' will not be visited. */
+bool Curl_uint_spbset_next(struct uint_spbset *bset, unsigned int last,
+ unsigned int *pnext);
+
+#endif /* HEADER_CURL_UINT_SPBSET_H */
diff --git a/libs/libcurl/src/uint-table.c b/libs/libcurl/src/uint-table.c
new file mode 100644
index 0000000000..c40d538348
--- /dev/null
+++ b/libs/libcurl/src/uint-table.c
@@ -0,0 +1,214 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+#include "uint-table.h"
+
+/* The last 3 #include files should be in this order */
+#include "curl_printf.h"
+#include "curl_memory.h"
+#include "memdebug.h"
+
+#ifdef DEBUGBUILD
+#define CURL_UINT_TBL_MAGIC 0x62757473
+#endif
+
+void Curl_uint_tbl_init(struct uint_tbl *tbl,
+ Curl_uint_tbl_entry_dtor *entry_dtor)
+{
+ memset(tbl, 0, sizeof(*tbl));
+ tbl->entry_dtor = entry_dtor;
+ tbl->last_key_added = UINT_MAX;
+#ifdef DEBUGBUILD
+ tbl->init = CURL_UINT_TBL_MAGIC;
+#endif
+}
+
+
+static void uint_tbl_clear_rows(struct uint_tbl *tbl,
+ unsigned int from,
+ unsigned int upto_excluding)
+{
+ unsigned int i, end;
+
+ end = CURLMIN(upto_excluding, tbl->nrows);
+ for(i = from; i < end; ++i) {
+ if(tbl->rows[i]) {
+ if(tbl->entry_dtor)
+ tbl->entry_dtor(i, tbl->rows[i]);
+ tbl->rows[i] = NULL;
+ tbl->nentries--;
+ }
+ }
+}
+
+
+CURLcode Curl_uint_tbl_resize(struct uint_tbl *tbl, unsigned int nrows)
+{
+ /* we use `tbl->nrows + 1` during iteration, want that to work */
+ DEBUGASSERT(tbl->init == CURL_UINT_TBL_MAGIC);
+ if(!nrows || (nrows == UINT_MAX))
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ if(nrows != tbl->nrows) {
+ void **rows = calloc(nrows, sizeof(void *));
+ if(!rows)
+ return CURLE_OUT_OF_MEMORY;
+ if(tbl->rows) {
+ memcpy(rows, tbl->rows, (CURLMIN(nrows, tbl->nrows) * sizeof(void *)));
+ if(nrows < tbl->nrows)
+ uint_tbl_clear_rows(tbl, nrows, tbl->nrows);
+ free(tbl->rows);
+ }
+ tbl->rows = rows;
+ tbl->nrows = nrows;
+ }
+ return CURLE_OK;
+}
+
+
+void Curl_uint_tbl_destroy(struct uint_tbl *tbl)
+{
+ DEBUGASSERT(tbl->init == CURL_UINT_TBL_MAGIC);
+ Curl_uint_tbl_clear(tbl);
+ free(tbl->rows);
+ memset(tbl, 0, sizeof(*tbl));
+}
+
+
+void Curl_uint_tbl_clear(struct uint_tbl *tbl)
+{
+ DEBUGASSERT(tbl->init == CURL_UINT_TBL_MAGIC);
+ uint_tbl_clear_rows(tbl, 0, tbl->nrows);
+ DEBUGASSERT(!tbl->nentries);
+ tbl->last_key_added = UINT_MAX;
+}
+
+
+unsigned int Curl_uint_tbl_capacity(struct uint_tbl *tbl)
+{
+ return tbl->nrows;
+}
+
+
+unsigned int Curl_uint_tbl_count(struct uint_tbl *tbl)
+{
+ return tbl->nentries;
+}
+
+
+void *Curl_uint_tbl_get(struct uint_tbl *tbl, unsigned int key)
+{
+ return (key < tbl->nrows) ? tbl->rows[key] : NULL;
+}
+
+
+bool Curl_uint_tbl_add(struct uint_tbl *tbl, void *entry, unsigned int *pkey)
+{
+ unsigned int key, start_pos;
+
+ DEBUGASSERT(tbl->init == CURL_UINT_TBL_MAGIC);
+ if(!entry || !pkey)
+ return FALSE;
+ *pkey = UINT_MAX; /* always invalid */
+ if(tbl->nentries == tbl->nrows) /* full */
+ return FALSE;
+
+ start_pos = CURLMIN(tbl->last_key_added, tbl->nrows) + 1;
+ for(key = start_pos; key < tbl->nrows; ++key) {
+ if(!tbl->rows[key]) {
+ tbl->rows[key] = entry;
+ tbl->nentries++;
+ tbl->last_key_added = key;
+ *pkey = key;
+ return TRUE;
+ }
+ }
+ /* no free entry at or above tbl->maybe_next_key, wrap around */
+ for(key = 0; key < start_pos; ++key) {
+ if(!tbl->rows[key]) {
+ tbl->rows[key] = entry;
+ tbl->nentries++;
+ tbl->last_key_added = key;
+ *pkey = key;
+ return TRUE;
+ }
+ }
+ /* Did not find any free row? Should not happen */
+ DEBUGASSERT(0);
+ return FALSE;
+}
+
+
+void Curl_uint_tbl_remove(struct uint_tbl *tbl, unsigned int key)
+{
+ uint_tbl_clear_rows(tbl, key, key + 1);
+}
+
+
+bool Curl_uint_tbl_contains(struct uint_tbl *tbl, unsigned int key)
+{
+ return (key < tbl->nrows) ? !!tbl->rows[key] : FALSE;
+}
+
+
+static bool uint_tbl_next_at(struct uint_tbl *tbl, unsigned int key,
+ unsigned int *pkey, void **pentry)
+{
+ for(; key < tbl->nrows; ++key) {
+ if(tbl->rows[key]) {
+ *pkey = key;
+ *pentry = tbl->rows[key];
+ return TRUE;
+ }
+ }
+ *pkey = UINT_MAX; /* always invalid */
+ *pentry = NULL;
+ return FALSE;
+}
+
+bool Curl_uint_tbl_first(struct uint_tbl *tbl,
+ unsigned int *pkey, void **pentry)
+{
+ if(!pkey || !pentry)
+ return FALSE;
+ if(tbl->nentries && uint_tbl_next_at(tbl, 0, pkey, pentry))
+ return TRUE;
+ DEBUGASSERT(!tbl->nentries);
+ *pkey = UINT_MAX; /* always invalid */
+ *pentry = NULL;
+ return FALSE;
+}
+
+
+bool Curl_uint_tbl_next(struct uint_tbl *tbl, unsigned int last_key,
+ unsigned int *pkey, void **pentry)
+{
+ if(!pkey || !pentry)
+ return FALSE;
+ if(uint_tbl_next_at(tbl, last_key + 1, pkey, pentry))
+ return TRUE;
+ *pkey = UINT_MAX; /* always invalid */
+ *pentry = NULL;
+ return FALSE;
+}
diff --git a/libs/libcurl/src/uint-table.h b/libs/libcurl/src/uint-table.h
new file mode 100644
index 0000000000..cf265f1113
--- /dev/null
+++ b/libs/libcurl/src/uint-table.h
@@ -0,0 +1,101 @@
+#ifndef HEADER_CURL_UINT_TABLE_H
+#define HEADER_CURL_UINT_TABLE_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "curl_setup.h"
+
+#include <curl/curl.h>
+
+/* Destructor for a single table entry */
+typedef void Curl_uint_tbl_entry_dtor(unsigned int key, void *entry);
+
+struct uint_tbl {
+ void **rows; /* array of void* holding entries */
+ Curl_uint_tbl_entry_dtor *entry_dtor;
+ unsigned int nrows; /* length of `rows` array */
+ unsigned int nentries; /* entris in table */
+ unsigned int last_key_added; /* UINT_MAX or last key added */
+#ifdef DEBUGBUILD
+ int init;
+#endif
+};
+
+/* Initialize the table with 0 capacity.
+ * The optional `entry_dtor` is called when a table entry is removed,
+ * Passing NULL means no action is taken on removal. */
+void Curl_uint_tbl_init(struct uint_tbl *tbl,
+ Curl_uint_tbl_entry_dtor *entry_dtor);
+
+/* Resize the table to change capacity `nmax`. When `nmax` is reduced,
+ * all present entries with key equal or larger to `nmax` are removed. */
+CURLcode Curl_uint_tbl_resize(struct uint_tbl *tbl, unsigned int nmax);
+
+/* Destroy the table, freeing all entries. */
+void Curl_uint_tbl_destroy(struct uint_tbl *tbl);
+
+/* Get the table capacity. */
+unsigned int Curl_uint_tbl_capacity(struct uint_tbl *tbl);
+
+/* Get the number of entries in the table. */
+unsigned int Curl_uint_tbl_count(struct uint_tbl *tbl);
+
+/* Clear the table, making it empty. */
+void Curl_uint_tbl_clear(struct uint_tbl *tbl);
+
+/* Get the entry for key or NULL if not present */
+void *Curl_uint_tbl_get(struct uint_tbl *tbl, unsigned int key);
+
+/* Add a new entry to the table and assign it a free key.
+ * Returns FALSE if the table is full.
+ *
+ * Keys are assigned in a round-robin manner.
+ * No matter the capacity, UINT_MAX is never assigned. */
+bool Curl_uint_tbl_add(struct uint_tbl *tbl, void *entry, unsigned int *pkey);
+
+/* Remove the entry with `key`. */
+void Curl_uint_tbl_remove(struct uint_tbl *tbl, unsigned int key);
+
+/* Return TRUE if the table contains an tryn with that keys. */
+bool Curl_uint_tbl_contains(struct uint_tbl *tbl, unsigned int key);
+
+/* Get the first entry in the table (with the smallest `key`).
+ * Returns FALSE if the table is empty. */
+bool Curl_uint_tbl_first(struct uint_tbl *tbl,
+ unsigned int *pkey, void **pentry);
+
+/* Get the next key in the table, following `last_key` in natural order.
+ * Put another way, this is the smallest key greater than `last_key` in
+ * the table. `last_key` does not have to be present in the table.
+ *
+ * Returns FALSE when no such entry is in the table.
+ *
+ * This allows to iterate the table while being modified:
+ * - added keys higher than 'last_key' will be picked up by the iteration.
+ * - added keys lower than 'last_key' will not show up.
+ * - removed keys lower or equal to 'last_key' will not show up.
+ * - removed keys higher than 'last_key' will not be visited. */
+bool Curl_uint_tbl_next(struct uint_tbl *tbl, unsigned int last_key,
+ unsigned int *pkey, void **pentry);
+
+#endif /* HEADER_CURL_UINT_TABLE_H */
diff --git a/libs/libcurl/src/url.c b/libs/libcurl/src/url.c
index dcd4b25d38..0e462be922 100644
--- a/libs/libcurl/src/url.c
+++ b/libs/libcurl/src/url.c
@@ -83,8 +83,9 @@
#include "multiif.h"
#include "easyif.h"
#include "speedcheck.h"
-#include "warnless.h"
+#include "curlx/warnless.h"
#include "getinfo.h"
+#include "pop3.h"
#include "urlapi-int.h"
#include "system_win32.h"
#include "hsts.h"
@@ -117,9 +118,9 @@
#include "strdup.h"
#include "setopt.h"
#include "altsvc.h"
-#include "dynbuf.h"
+#include "curlx/dynbuf.h"
#include "headers.h"
-#include "strparse.h"
+#include "curlx/strparse.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h"
@@ -271,7 +272,7 @@ CURLcode Curl_close(struct Curl_easy **datap)
data->state.referer = NULL;
up_free(data);
- Curl_dyn_free(&data->state.headerb);
+ curlx_dyn_free(&data->state.headerb);
Curl_flush_cookies(data, TRUE);
#ifndef CURL_DISABLE_ALTSVC
Curl_altsvc_save(data, data->asi, data->set.str[STRING_ALTSVC]);
@@ -290,9 +291,10 @@ CURLcode Curl_close(struct Curl_easy **datap)
Curl_safefree(data->info.contenttype);
Curl_safefree(data->info.wouldredirect);
- /* this destroys the channel and we cannot use it anymore after this */
- Curl_resolver_cancel(data);
- Curl_resolver_cleanup(data->state.async.resolver);
+ /* release any resolve information this transfer kept */
+ Curl_async_destroy(data);
+ Curl_resolv_unlink(data, &data->state.dns[0]); /* done with this */
+ Curl_resolv_unlink(data, &data->state.dns[1]);
data_priority_cleanup(data);
@@ -303,6 +305,7 @@ CURLcode Curl_close(struct Curl_easy **datap)
Curl_share_unlock(data, CURL_LOCK_DATA_SHARE);
}
+ Curl_hash_destroy(&data->meta_hash);
#ifndef CURL_DISABLE_PROXY
Curl_safefree(data->state.aptr.proxyuserpwd);
#endif
@@ -392,9 +395,6 @@ CURLcode Curl_init_userdefined(struct Curl_easy *data)
set->socks5auth = CURLAUTH_BASIC | CURLAUTH_GSSAPI;
#endif
- /* make libcurl quiet by default: */
- set->hide_progress = TRUE; /* CURLOPT_NOPROGRESS changes these */
-
Curl_mime_initpart(&set->mimepost);
Curl_ssl_easy_config_init(data);
@@ -481,9 +481,25 @@ CURLcode Curl_init_userdefined(struct Curl_easy *data)
memset(&set->priority, 0, sizeof(set->priority));
#endif
set->quick_exit = 0L;
+#ifndef CURL_DISABLE_WEBSOCKETS
+ set->ws_raw_mode = FALSE;
+ set->ws_no_auto_pong = FALSE;
+#endif
+
return result;
}
+/* easy->meta_hash destructor. Should never be called as elements
+ * MUST be added with their own destructor */
+static void easy_meta_freeentry(void *p)
+{
+ (void)p;
+ /* Will always be FALSE. Cannot use a 0 assert here since compilers
+ * are not in agreement if they then want a NORETURN attribute or
+ * not. *sigh* */
+ DEBUGASSERT(p == NULL);
+}
+
/**
* Curl_open()
*
@@ -506,8 +522,19 @@ CURLcode Curl_open(struct Curl_easy **curl)
}
data->magic = CURLEASY_MAGIC_NUMBER;
+ /* 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->mid = UINT_MAX;
+ data->master_mid = UINT_MAX;
+ data->progress.hide = TRUE;
+ data->state.current_speed = -1; /* init to negative == impossible */
- Curl_dyn_init(&data->state.headerb, CURL_MAX_HTTP_HEADER);
+ Curl_hash_init(&data->meta_hash, 23,
+ Curl_hash_str, curlx_str_key_compare, easy_meta_freeentry);
+ curlx_dyn_init(&data->state.headerb, CURL_MAX_HTTP_HEADER);
Curl_req_init(&data->req);
Curl_initinfo(data);
#ifndef CURL_DISABLE_HTTP
@@ -515,35 +542,14 @@ CURLcode Curl_open(struct Curl_easy **curl)
#endif
Curl_netrc_init(&data->state.netrc);
- result = Curl_resolver_init(data, &data->state.async.resolver);
- if(result) {
- DEBUGF(fprintf(stderr, "Error: resolver_init failed\n"));
- goto out;
- }
-
result = Curl_init_userdefined(data);
- if(result)
- goto out;
-
- /* 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->mid = -1;
-#ifndef CURL_DISABLE_DOH
- data->set.dohfor_mid = -1;
-#endif
-
- data->progress.flags |= PGRS_HIDE;
- data->state.current_speed = -1; /* init to negative == impossible */
-out:
if(result) {
- Curl_resolver_cleanup(data->state.async.resolver);
- Curl_dyn_free(&data->state.headerb);
+ curlx_dyn_free(&data->state.headerb);
Curl_freeset(data);
Curl_req_free(&data->req, data);
+ Curl_hash_destroy(&data->meta_hash);
+ data->magic = 0;
free(data);
data = NULL;
}
@@ -595,6 +601,8 @@ void Curl_conn_free(struct Curl_easy *data, struct connectdata *conn)
Curl_safefree(conn->unix_domain_socket);
#endif
Curl_safefree(conn->destination);
+ Curl_uint_spbset_destroy(&conn->xfers_attached);
+ Curl_hash_destroy(&conn->meta_hash);
free(conn); /* free all the connection oriented data */
}
@@ -672,7 +680,7 @@ static bool conn_maxage(struct Curl_easy *data,
{
timediff_t idletime, lifetime;
- idletime = Curl_timediff(now, conn->lastused);
+ idletime = curlx_timediff(now, conn->lastused);
idletime /= 1000; /* integer seconds is fine */
if(idletime > data->set.maxage_conn) {
@@ -681,7 +689,7 @@ static bool conn_maxage(struct Curl_easy *data,
return TRUE;
}
- lifetime = Curl_timediff(now, conn->created);
+ lifetime = curlx_timediff(now, conn->created);
lifetime /= 1000; /* integer seconds is fine */
if(data->set.maxlifetime_conn && lifetime > data->set.maxlifetime_conn) {
@@ -709,7 +717,7 @@ bool Curl_conn_seems_dead(struct connectdata *conn,
bool dead;
struct curltime now;
if(!pnow) {
- now = Curl_now();
+ now = curlx_now();
pnow = &now;
}
@@ -767,7 +775,7 @@ CURLcode Curl_conn_upkeep(struct Curl_easy *data,
struct curltime *now)
{
CURLcode result = CURLE_OK;
- if(Curl_timediff(*now, conn->keepalive) <= data->set.upkeep_interval_ms)
+ if(curlx_timediff(*now, conn->keepalive) <= data->set.upkeep_interval_ms)
return result;
/* briefly attach for action */
@@ -793,8 +801,12 @@ CURLcode Curl_conn_upkeep(struct Curl_easy *data,
static bool ssh_config_matches(struct connectdata *one,
struct connectdata *two)
{
- return Curl_safecmp(one->proto.sshc.rsa, two->proto.sshc.rsa) &&
- Curl_safecmp(one->proto.sshc.rsa_pub, two->proto.sshc.rsa_pub);
+ struct ssh_conn *sshc1, *sshc2;
+
+ sshc1 = Curl_conn_meta_get(one, CURL_META_SSH_CONN);
+ sshc2 = Curl_conn_meta_get(two, CURL_META_SSH_CONN);
+ return (sshc1 && sshc2 && Curl_safecmp(sshc1->rsa, sshc2->rsa) &&
+ Curl_safecmp(sshc1->rsa_pub, sshc2->rsa_pub));
}
#endif
@@ -813,25 +825,19 @@ struct url_conn_match {
BIT(seen_multiplex_conn);
};
-static bool url_match_conn(struct connectdata *conn, void *userdata)
+static bool url_match_connect_config(struct connectdata *conn,
+ struct url_conn_match *m)
{
- struct url_conn_match *match = userdata;
- struct Curl_easy *data = match->data;
- struct connectdata *needle = match->needle;
-
- /* Check if `conn` can be used for transfer `data` */
-
+ /* connect-only or to-be-closed connections will not be reused */
if(conn->connect_only || conn->bits.close)
- /* connect-only or to-be-closed connections will not be reused */
return FALSE;
- if(data->set.ipver != CURL_IPRESOLVE_WHATEVER
- && data->set.ipver != conn->ip_version) {
- /* skip because the connection is not via the requested IP version */
+ /* ip_version must match */
+ if(m->data->set.ipver != CURL_IPRESOLVE_WHATEVER
+ && m->data->set.ipver != conn->ip_version)
return FALSE;
- }
- if(needle->localdev || needle->localport) {
+ if(m->needle->localdev || m->needle->localport) {
/* If we are bound to a specific local end (IP+port), we must not reuse a
random other one, although if we did not ask for a particular one we
can reuse one that was bound.
@@ -843,74 +849,115 @@ static bool url_match_conn(struct connectdata *conn, void *userdata)
likely also reuse the exact same binding parameters and missing out a
few edge cases should not hurt anyone much.
*/
- if((conn->localport != needle->localport) ||
- (conn->localportrange != needle->localportrange) ||
- (needle->localdev &&
- (!conn->localdev || strcmp(conn->localdev, needle->localdev))))
+ if((conn->localport != m->needle->localport) ||
+ (conn->localportrange != m->needle->localportrange) ||
+ (m->needle->localdev &&
+ (!conn->localdev || strcmp(conn->localdev, m->needle->localdev))))
return FALSE;
}
- if(needle->bits.conn_to_host != conn->bits.conn_to_host)
+ if(m->needle->bits.conn_to_host != conn->bits.conn_to_host)
/* do not mix connections that use the "connect to host" feature and
* connections that do not use this feature */
return FALSE;
- if(needle->bits.conn_to_port != conn->bits.conn_to_port)
+ if(m->needle->bits.conn_to_port != conn->bits.conn_to_port)
/* do not mix connections that use the "connect to port" feature and
* connections that do not use this feature */
return FALSE;
+ /* Does `conn` use the correct protocol? */
+#ifdef USE_UNIX_SOCKETS
+ if(m->needle->unix_domain_socket) {
+ if(!conn->unix_domain_socket)
+ return FALSE;
+ if(strcmp(m->needle->unix_domain_socket, conn->unix_domain_socket))
+ return FALSE;
+ if(m->needle->bits.abstract_unix_socket != conn->bits.abstract_unix_socket)
+ return FALSE;
+ }
+ else if(conn->unix_domain_socket)
+ return FALSE;
+#endif
+
+ return TRUE;
+}
+
+static bool url_match_fully_connected(struct connectdata *conn,
+ struct url_conn_match *m)
+{
if(!Curl_conn_is_connected(conn, FIRSTSOCKET) ||
conn->bits.asks_multiplex) {
/* Not yet connected, or not yet decided if it multiplexes. The later
* happens for HTTP/2 Upgrade: requests that need a response. */
- if(match->may_multiplex) {
- match->seen_pending_conn = TRUE;
+ if(m->may_multiplex) {
+ m->seen_pending_conn = TRUE;
/* Do not pick a connection that has not connected yet */
- infof(data, "Connection #%" FMT_OFF_T
+ infof(m->data, "Connection #%" FMT_OFF_T
" is not open enough, cannot reuse", conn->connection_id);
}
/* Do not pick a connection that has not connected yet */
return FALSE;
}
- /* `conn` is connected. If it has transfers, can we add ours to it? */
+ return TRUE;
+}
+static bool url_match_multi(struct connectdata *conn,
+ struct url_conn_match *m)
+{
+ if(CONN_INUSE(conn)) {
+ DEBUGASSERT(conn->attached_multi);
+ if(conn->attached_multi != m->data->multi)
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static bool url_match_multiplex_needs(struct connectdata *conn,
+ struct url_conn_match *m)
+{
if(CONN_INUSE(conn)) {
if(!conn->bits.multiplex) {
/* conn busy and conn cannot take more transfers */
- match->seen_single_use_conn = TRUE;
+ m->seen_single_use_conn = TRUE;
return FALSE;
}
- match->seen_multiplex_conn = TRUE;
- if(!match->may_multiplex)
+ m->seen_multiplex_conn = TRUE;
+ if(!m->may_multiplex || !url_match_multi(conn, m))
/* conn busy and transfer cannot be multiplexed */
return FALSE;
- else {
- /* transfer and conn multiplex. Are they on the same multi? */
- struct Curl_llist_node *e = Curl_llist_head(&conn->easyq);
- struct Curl_easy *entry = Curl_node_elem(e);
- if(entry->multi != data->multi)
- return FALSE;
- }
}
- /* `conn` is connected and we could add the transfer to it, if
- * all the other criteria do match. */
+ return TRUE;
+}
- /* Does `conn` use the correct protocol? */
-#ifdef USE_UNIX_SOCKETS
- if(needle->unix_domain_socket) {
- if(!conn->unix_domain_socket)
- return FALSE;
- if(strcmp(needle->unix_domain_socket, conn->unix_domain_socket))
+static bool url_match_multiplex_limits(struct connectdata *conn,
+ struct url_conn_match *m)
+{
+ if(CONN_INUSE(conn) && m->may_multiplex) {
+ DEBUGASSERT(conn->bits.multiplex);
+ /* If multiplexed, make sure we do not go over concurrency limit */
+ if(CONN_ATTACHED(conn) >=
+ Curl_multi_max_concurrent_streams(m->data->multi)) {
+ infof(m->data, "client side MAX_CONCURRENT_STREAMS reached"
+ ", skip (%u)", CONN_ATTACHED(conn));
return FALSE;
- if(needle->bits.abstract_unix_socket != conn->bits.abstract_unix_socket)
+ }
+ if(CONN_ATTACHED(conn) >=
+ Curl_conn_get_max_concurrent(m->data, conn, FIRSTSOCKET)) {
+ infof(m->data, "MAX_CONCURRENT_STREAMS reached, skip (%u)",
+ CONN_ATTACHED(conn));
return FALSE;
+ }
+ /* When not multiplexed, we have a match here! */
+ infof(m->data, "Multiplexed connection found");
}
- else if(conn->unix_domain_socket)
- return FALSE;
-#endif
+ return TRUE;
+}
- if(needle->handler->flags&PROTOPT_SSL) {
+static bool url_match_ssl_use(struct connectdata *conn,
+ struct url_conn_match *m)
+{
+ if(m->needle->handler->flags&PROTOPT_SSL) {
/* We are looking for SSL, if `conn` does not do it, not a match. */
if(!Curl_conn_is_ssl(conn, FIRSTSOCKET))
return FALSE;
@@ -918,34 +965,39 @@ static bool url_match_conn(struct connectdata *conn, void *userdata)
else if(Curl_conn_is_ssl(conn, FIRSTSOCKET)) {
/* We are not *requiring* SSL, however `conn` has it. If the
* protocol *family* is not the same, not a match. */
- if(get_protocol_family(conn->handler) != needle->handler->protocol)
+ if(get_protocol_family(conn->handler) != m->needle->handler->protocol)
return FALSE;
}
+ return TRUE;
+}
#ifndef CURL_DISABLE_PROXY
- if(needle->bits.httpproxy != conn->bits.httpproxy ||
- needle->bits.socksproxy != conn->bits.socksproxy)
+static bool url_match_proxy_use(struct connectdata *conn,
+ struct url_conn_match *m)
+{
+ if(m->needle->bits.httpproxy != conn->bits.httpproxy ||
+ m->needle->bits.socksproxy != conn->bits.socksproxy)
return FALSE;
- if(needle->bits.socksproxy &&
- !socks_proxy_info_matches(&needle->socks_proxy,
+ if(m->needle->bits.socksproxy &&
+ !socks_proxy_info_matches(&m->needle->socks_proxy,
&conn->socks_proxy))
return FALSE;
- if(needle->bits.httpproxy) {
- if(needle->bits.tunnel_proxy != conn->bits.tunnel_proxy)
+ if(m->needle->bits.httpproxy) {
+ if(m->needle->bits.tunnel_proxy != conn->bits.tunnel_proxy)
return FALSE;
- if(!proxy_info_matches(&needle->http_proxy, &conn->http_proxy))
+ if(!proxy_info_matches(&m->needle->http_proxy, &conn->http_proxy))
return FALSE;
- if(IS_HTTPS_PROXY(needle->http_proxy.proxytype)) {
+ if(IS_HTTPS_PROXY(m->needle->http_proxy.proxytype)) {
/* https proxies come in different types, http/1.1, h2, ... */
- if(needle->http_proxy.proxytype != conn->http_proxy.proxytype)
+ if(m->needle->http_proxy.proxytype != conn->http_proxy.proxytype)
return FALSE;
/* match SSL config to proxy */
- if(!Curl_ssl_conn_config_match(data, conn, TRUE)) {
- DEBUGF(infof(data,
+ if(!Curl_ssl_conn_config_match(m->data, conn, TRUE)) {
+ DEBUGF(infof(m->data,
"Connection #%" FMT_OFF_T
" has different SSL proxy parameters, cannot reuse",
conn->connection_id));
@@ -955,109 +1007,134 @@ static bool url_match_conn(struct connectdata *conn, void *userdata)
* further below */
}
}
+ return TRUE;
+}
+#else
+#define url_match_proxy_use(c,m) ((void)c, (void)m, TRUE)
#endif
#ifndef CURL_DISABLE_HTTP
- if(match->may_multiplex &&
- (data->state.http_neg.allowed & (CURL_HTTP_V2x|CURL_HTTP_V3x)) &&
- (needle->handler->protocol & CURLPROTO_HTTP) &&
+static bool url_match_http_multiplex(struct connectdata *conn,
+ struct url_conn_match *m)
+{
+ if(m->may_multiplex &&
+ (m->data->state.http_neg.allowed & (CURL_HTTP_V2x|CURL_HTTP_V3x)) &&
+ (m->needle->handler->protocol & CURLPROTO_HTTP) &&
!conn->httpversion_seen) {
- if(data->set.pipewait) {
- infof(data, "Server upgrade does not support multiplex yet, wait");
- match->found = NULL;
- match->wait_pipe = TRUE;
+ if(m->data->set.pipewait) {
+ infof(m->data, "Server upgrade does not support multiplex yet, wait");
+ m->found = NULL;
+ m->wait_pipe = TRUE;
return TRUE; /* stop searching, we want to wait */
}
- infof(data, "Server upgrade cannot be used");
+ infof(m->data, "Server upgrade cannot be used");
return FALSE;
}
-#endif
-
- if(!(needle->handler->flags & PROTOPT_CREDSPERREQUEST)) {
- /* This protocol requires credentials per connection,
- so verify that we are using the same name and password as well */
- if(Curl_timestrcmp(needle->user, conn->user) ||
- Curl_timestrcmp(needle->passwd, conn->passwd) ||
- Curl_timestrcmp(needle->sasl_authzid, conn->sasl_authzid) ||
- Curl_timestrcmp(needle->oauth_bearer, conn->oauth_bearer)) {
- /* one of them was different */
- return FALSE;
- }
- }
-
-#ifdef HAVE_GSSAPI
- /* GSS delegation differences do not actually affect every connection
- and auth method, but this check takes precaution before efficiency */
- if(needle->gssapi_delegation != conn->gssapi_delegation)
- return FALSE;
-#endif
+ return TRUE;
+}
-#ifndef CURL_DISABLE_HTTP
+static bool url_match_http_version(struct connectdata *conn,
+ struct url_conn_match *m)
+{
/* If looking for HTTP and the HTTP versions allowed do not include
* the HTTP version of conn, continue looking. */
- if((needle->handler->protocol & PROTO_FAMILY_HTTP)) {
- switch(Curl_conn_http_version(data, conn)) {
+ if((m->needle->handler->protocol & PROTO_FAMILY_HTTP)) {
+ switch(Curl_conn_http_version(m->data, conn)) {
case 30:
- if(!(data->state.http_neg.allowed & CURL_HTTP_V3x)) {
- DEBUGF(infof(data, "not reusing conn #%" CURL_FORMAT_CURL_OFF_T
+ if(!(m->data->state.http_neg.allowed & CURL_HTTP_V3x)) {
+ DEBUGF(infof(m->data, "not reusing conn #%" CURL_FORMAT_CURL_OFF_T
", we do not want h3", conn->connection_id));
return FALSE;
}
break;
case 20:
- if(!(data->state.http_neg.allowed & CURL_HTTP_V2x)) {
- DEBUGF(infof(data, "not reusing conn #%" CURL_FORMAT_CURL_OFF_T
+ if(!(m->data->state.http_neg.allowed & CURL_HTTP_V2x)) {
+ DEBUGF(infof(m->data, "not reusing conn #%" CURL_FORMAT_CURL_OFF_T
", we do not want h2", conn->connection_id));
return FALSE;
}
break;
default:
- if(!(data->state.http_neg.allowed & CURL_HTTP_V1x)) {
- DEBUGF(infof(data, "not reusing conn #%" CURL_FORMAT_CURL_OFF_T
+ if(!(m->data->state.http_neg.allowed & CURL_HTTP_V1x)) {
+ DEBUGF(infof(m->data, "not reusing conn #%" CURL_FORMAT_CURL_OFF_T
", we do not want h1", conn->connection_id));
return FALSE;
}
break;
}
}
+ return TRUE;
+}
+#else
+#define url_match_http_multiplex(c,m) ((void)c, (void)m, TRUE)
+#define url_match_http_version(c,m) ((void)c, (void)m, TRUE)
#endif
+static bool url_match_proto_config(struct connectdata *conn,
+ struct url_conn_match *m)
+{
+ if(!url_match_http_version(conn, m))
+ return FALSE;
+
#ifdef USE_SSH
- else if(get_protocol_family(needle->handler) & PROTO_FAMILY_SSH) {
- if(!ssh_config_matches(needle, conn))
+ if(get_protocol_family(m->needle->handler) & PROTO_FAMILY_SSH) {
+ if(!ssh_config_matches(m->needle, conn))
return FALSE;
}
#endif
#ifndef CURL_DISABLE_FTP
- else if(get_protocol_family(needle->handler) & PROTO_FAMILY_FTP) {
- /* Also match ACCOUNT, ALTERNATIVE-TO-USER, USE_SSL and CCC options */
- if(Curl_timestrcmp(needle->proto.ftpc.account,
- conn->proto.ftpc.account) ||
- Curl_timestrcmp(needle->proto.ftpc.alternative_to_user,
- conn->proto.ftpc.alternative_to_user) ||
- (needle->proto.ftpc.use_ssl != conn->proto.ftpc.use_ssl) ||
- (needle->proto.ftpc.ccc != conn->proto.ftpc.ccc))
+ else if(get_protocol_family(m->needle->handler) & PROTO_FAMILY_FTP) {
+ if(!ftp_conns_match(m->needle, conn))
return FALSE;
}
#endif
+ return TRUE;
+}
+static bool url_match_auth(struct connectdata *conn,
+ struct url_conn_match *m)
+{
+ if(!(m->needle->handler->flags & PROTOPT_CREDSPERREQUEST)) {
+ /* This protocol requires credentials per connection,
+ so verify that we are using the same name and password as well */
+ if(Curl_timestrcmp(m->needle->user, conn->user) ||
+ Curl_timestrcmp(m->needle->passwd, conn->passwd) ||
+ Curl_timestrcmp(m->needle->sasl_authzid, conn->sasl_authzid) ||
+ Curl_timestrcmp(m->needle->oauth_bearer, conn->oauth_bearer)) {
+ /* one of them was different */
+ return FALSE;
+ }
+ }
+#ifdef HAVE_GSSAPI
+ /* GSS delegation differences do not actually affect every connection
+ and auth method, but this check takes precaution before efficiency */
+ if(m->needle->gssapi_delegation != conn->gssapi_delegation)
+ return FALSE;
+#endif
+
+ return TRUE;
+}
+
+static bool url_match_destination(struct connectdata *conn,
+ struct url_conn_match *m)
+{
/* Additional match requirements if talking TLS OR
* not talking to an HTTP proxy OR using a tunnel through a proxy */
- if((needle->handler->flags&PROTOPT_SSL)
+ if((m->needle->handler->flags&PROTOPT_SSL)
#ifndef CURL_DISABLE_PROXY
- || !needle->bits.httpproxy || needle->bits.tunnel_proxy
+ || !m->needle->bits.httpproxy || m->needle->bits.tunnel_proxy
#endif
) {
- if(!strcasecompare(needle->handler->scheme, conn->handler->scheme)) {
+ if(!strcasecompare(m->needle->handler->scheme, conn->handler->scheme)) {
/* `needle` and `conn` do not have the same scheme... */
- if(get_protocol_family(conn->handler) != needle->handler->protocol) {
+ if(get_protocol_family(conn->handler) != m->needle->handler->protocol) {
/* and `conn`s protocol family is not the protocol `needle` wants.
* IMAPS would work for IMAP, but no vice versa. */
return FALSE;
}
/* We are in an IMAPS vs IMAP like case. We expect `conn` to have SSL */
if(!Curl_conn_is_ssl(conn, FIRSTSOCKET)) {
- DEBUGF(infof(data,
+ DEBUGF(infof(m->data,
"Connection #%" FMT_OFF_T " has compatible protocol famiy, "
"but no SSL, no match", conn->connection_id));
return FALSE;
@@ -1065,42 +1142,52 @@ static bool url_match_conn(struct connectdata *conn, void *userdata)
}
/* If needle has "conn_to_*" set, conn must match this */
- if((needle->bits.conn_to_host && !strcasecompare(
- needle->conn_to_host.name, conn->conn_to_host.name)) ||
- (needle->bits.conn_to_port &&
- needle->conn_to_port != conn->conn_to_port))
+ if((m->needle->bits.conn_to_host && !strcasecompare(
+ m->needle->conn_to_host.name, conn->conn_to_host.name)) ||
+ (m->needle->bits.conn_to_port &&
+ m->needle->conn_to_port != conn->conn_to_port))
return FALSE;
/* hostname and port must match */
- if(!strcasecompare(needle->host.name, conn->host.name) ||
- needle->remote_port != conn->remote_port)
+ if(!strcasecompare(m->needle->host.name, conn->host.name) ||
+ m->needle->remote_port != conn->remote_port)
return FALSE;
+ }
+ return TRUE;
+}
- /* If talking TLS, conn needs to use the same SSL options. */
- if((needle->handler->flags & PROTOPT_SSL) &&
- !Curl_ssl_conn_config_match(data, conn, FALSE)) {
- DEBUGF(infof(data,
- "Connection #%" FMT_OFF_T
- " has different SSL parameters, cannot reuse",
- conn->connection_id));
- return FALSE;
- }
+static bool url_match_ssl_config(struct connectdata *conn,
+ struct url_conn_match *m)
+{
+ /* If talking TLS, conn needs to use the same SSL options. */
+ if((m->needle->handler->flags & PROTOPT_SSL) &&
+ !Curl_ssl_conn_config_match(m->data, conn, FALSE)) {
+ DEBUGF(infof(m->data,
+ "Connection #%" FMT_OFF_T
+ " has different SSL parameters, cannot reuse",
+ conn->connection_id));
+ return FALSE;
}
+ return TRUE;
+}
#ifdef USE_NTLM
+static bool url_match_auth_ntlm(struct connectdata *conn,
+ struct url_conn_match *m)
+{
/* If we are looking for an HTTP+NTLM connection, check if this is
already authenticating with the right credentials. If not, keep
looking so that we can reuse NTLM connections if
possible. (Especially we must not reuse the same connection if
partway through a handshake!) */
- if(match->want_ntlm_http) {
- if(Curl_timestrcmp(needle->user, conn->user) ||
- Curl_timestrcmp(needle->passwd, conn->passwd)) {
+ if(m->want_ntlm_http) {
+ if(Curl_timestrcmp(m->needle->user, conn->user) ||
+ Curl_timestrcmp(m->needle->passwd, conn->passwd)) {
/* we prefer a credential match, but this is at least a connection
that can be reused and "upgraded" to NTLM */
if(conn->http_ntlm_state == NTLMSTATE_NONE)
- match->found = conn;
+ m->found = conn;
return FALSE;
}
}
@@ -1111,15 +1198,15 @@ static bool url_match_conn(struct connectdata *conn, void *userdata)
#ifndef CURL_DISABLE_PROXY
/* Same for Proxy NTLM authentication */
- if(match->want_proxy_ntlm_http) {
+ if(m->want_proxy_ntlm_http) {
/* Both conn->http_proxy.user and conn->http_proxy.passwd can be
* NULL */
if(!conn->http_proxy.user || !conn->http_proxy.passwd)
return FALSE;
- if(Curl_timestrcmp(needle->http_proxy.user,
+ if(Curl_timestrcmp(m->needle->http_proxy.user,
conn->http_proxy.user) ||
- Curl_timestrcmp(needle->http_proxy.passwd,
+ Curl_timestrcmp(m->needle->http_proxy.passwd,
conn->http_proxy.passwd))
return FALSE;
}
@@ -1128,53 +1215,83 @@ static bool url_match_conn(struct connectdata *conn, void *userdata)
return FALSE;
}
#endif
- if(match->want_ntlm_http || match->want_proxy_ntlm_http) {
+ if(m->want_ntlm_http || m->want_proxy_ntlm_http) {
/* Credentials are already checked, we may use this connection.
* With NTLM being weird as it is, we MUST use a
* connection where it has already been fully negotiated.
* If it has not, we keep on looking for a better one. */
- match->found = conn;
+ m->found = conn;
- if((match->want_ntlm_http &&
+ if((m->want_ntlm_http &&
(conn->http_ntlm_state != NTLMSTATE_NONE)) ||
- (match->want_proxy_ntlm_http &&
+ (m->want_proxy_ntlm_http &&
(conn->proxy_ntlm_state != NTLMSTATE_NONE))) {
/* We must use this connection, no other */
- match->force_reuse = TRUE;
+ m->force_reuse = TRUE;
return TRUE;
}
/* Continue look up for a better connection */
return FALSE;
}
+ return TRUE;
+}
+#else
+#define url_match_auth_ntlm(c,m) ((void)c, (void)m, TRUE)
#endif
- if(CONN_INUSE(conn)) {
- DEBUGASSERT(match->may_multiplex);
- DEBUGASSERT(conn->bits.multiplex);
- /* If multiplexed, make sure we do not go over concurrency limit */
- if(CONN_INUSE(conn) >=
- Curl_multi_max_concurrent_streams(data->multi)) {
- infof(data, "client side MAX_CONCURRENT_STREAMS reached"
- ", skip (%zu)", CONN_INUSE(conn));
- return FALSE;
- }
- if(CONN_INUSE(conn) >=
- Curl_conn_get_max_concurrent(data, conn, FIRSTSOCKET)) {
- infof(data, "MAX_CONCURRENT_STREAMS reached, skip (%zu)",
- CONN_INUSE(conn));
- return FALSE;
- }
- /* When not multiplexed, we have a match here! */
- infof(data, "Multiplexed connection found");
- }
- else if(Curl_conn_seems_dead(conn, data, NULL)) {
- /* removed and disconnect. Do not treat as aborted. */
- Curl_conn_terminate(data, conn, FALSE);
+static bool url_match_conn(struct connectdata *conn, void *userdata)
+{
+ struct url_conn_match *m = userdata;
+ /* Check if `conn` can be used for transfer `m->data` */
+
+ /* general connect config setting match? */
+ if(!url_match_connect_config(conn, m))
+ return FALSE;
+
+ if(!url_match_destination(conn, m))
+ return FALSE;
+
+ if(!url_match_fully_connected(conn, m))
+ return FALSE;
+
+ if(!url_match_multiplex_needs(conn, m))
+ return FALSE;
+
+ if(!url_match_ssl_use(conn, m))
+ return FALSE;
+ if(!url_match_proxy_use(conn, m))
+ return FALSE;
+ if(!url_match_ssl_config(conn, m))
+ return FALSE;
+
+ if(!url_match_http_multiplex(conn, m))
+ return FALSE;
+ else if(m->wait_pipe)
+ /* we decided to wait on PIPELINING */
+ return TRUE;
+
+ if(!url_match_auth(conn, m))
+ return FALSE;
+
+ if(!url_match_proto_config(conn, m))
+ return FALSE;
+
+ if(!url_match_auth_ntlm(conn, m))
+ return FALSE;
+ else if(m->force_reuse)
+ return TRUE;
+
+ if(!url_match_multiplex_limits(conn, m))
+ return FALSE;
+
+ if(!CONN_INUSE(conn) && Curl_conn_seems_dead(conn, m->data, NULL)) {
+ /* remove and disconnect. */
+ Curl_conn_terminate(m->data, conn, FALSE);
return FALSE;
}
- /* We have found a connection. Let's stop searching. */
- match->found = conn;
+ /* conn matches our needs. */
+ m->found = conn;
return TRUE;
}
@@ -1310,7 +1427,7 @@ static struct connectdata *allocate_conn(struct Curl_easy *data)
connclose(conn, "Default to force-close");
/* Store creation time to help future close decision making */
- conn->created = Curl_now();
+ conn->created = curlx_now();
/* Store current time to give a baseline to keepalive connection times. */
conn->keepalive = conn->created;
@@ -1346,8 +1463,8 @@ static struct connectdata *allocate_conn(struct Curl_easy *data)
conn->connect_only = data->set.connect_only;
conn->transport = TRNSPRT_TCP; /* most of them are TCP streams */
- /* Initialize the easy handle list */
- Curl_llist_init(&conn->easyq, NULL);
+ /* Initialize the attached xfers bitset */
+ Curl_uint_spbset_init(&conn->xfers_attached);
#ifdef HAVE_GSSAPI
conn->data_prot = PROT_CLEAR;
@@ -1666,7 +1783,7 @@ static void zonefrom_url(CURLU *uh, struct Curl_easy *data,
if(!uc && zoneid) {
const char *p = zoneid;
curl_off_t scope;
- if(!Curl_str_number(&p, &scope, UINT_MAX))
+ if(!curlx_str_number(&p, &scope, UINT_MAX))
/* A plain number, use it directly as a scope id. */
conn->scope_id = (unsigned int)scope;
#ifdef HAVE_IF_NAMETOINDEX
@@ -1909,7 +2026,7 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data,
port = data->set.use_port;
else {
const char *p = data->state.up.port;
- if(Curl_str_number(&p, &port, 0xffff))
+ if(curlx_str_number(&p, &port, 0xffff))
valid = FALSE;
}
if(valid)
@@ -2243,7 +2360,7 @@ static CURLcode parse_proxy(struct Curl_easy *data,
if(portptr) {
curl_off_t num;
const char *p = portptr;
- if(!Curl_str_number(&p, &num, 0xffff))
+ if(!curlx_str_number(&p, &num, 0xffff))
port = (int)num;
free(portptr);
}
@@ -2887,7 +3004,7 @@ static CURLcode parse_connect_to_host_port(struct Curl_easy *data,
if(*host_portno) {
curl_off_t portparse;
const char *p = host_portno;
- if(Curl_str_number(&p, &portparse, 0xffff)) {
+ if(curlx_str_number(&p, &portparse, 0xffff)) {
failf(data, "No valid port number in connect to host string (%s)",
host_portno);
result = CURLE_SETOPT_OPTION_SYNTAX;
@@ -2965,7 +3082,7 @@ static CURLcode parse_connect_to_string(struct Curl_easy *data,
char *ptr_next = strchr(ptr, ':');
if(ptr_next) {
curl_off_t port_to_match;
- if(!Curl_str_number(&ptr, &port_to_match, 0xffff) &&
+ if(!curlx_str_number(&ptr, &port_to_match, 0xffff) &&
(port_to_match == (curl_off_t)conn->remote_port))
port_match = TRUE;
ptr = ptr_next + 1;
@@ -3045,10 +3162,14 @@ static CURLcode parse_connect_to_slist(struct Curl_easy *data,
DEBUGF(infof(data, "Alt-svc check wanted=%x, allowed=%x",
neg->wanted, neg->allowed));
+#ifdef USE_HTTP3
if(neg->allowed & CURL_HTTP_V3x)
allowed_alpns |= ALPN_h3;
+#endif
+#ifdef USE_HTTP2
if(neg->allowed & CURL_HTTP_V2x)
allowed_alpns |= ALPN_h2;
+#endif
if(neg->allowed & CURL_HTTP_V1x)
allowed_alpns |= ALPN_h1;
allowed_alpns &= (int)data->asi->flags;
@@ -3124,13 +3245,14 @@ static CURLcode parse_connect_to_slist(struct Curl_easy *data,
#ifdef USE_UNIX_SOCKETS
static CURLcode resolve_unix(struct Curl_easy *data,
struct connectdata *conn,
- char *unix_path)
+ char *unix_path,
+ struct Curl_dns_entry **pdns)
{
- struct Curl_dns_entry *hostaddr = NULL;
+ struct Curl_dns_entry *hostaddr;
bool longpath = FALSE;
DEBUGASSERT(unix_path);
- DEBUGASSERT(conn->dns_entry == NULL);
+ *pdns = NULL;
/* Unix domain sockets are local. The host gets ignored, just use the
* specified domain socket address. Do not cache "DNS entries". There is
@@ -3150,7 +3272,7 @@ static CURLcode resolve_unix(struct Curl_easy *data,
}
hostaddr->refcount = 1; /* connection is the only one holding this */
- conn->dns_entry = hostaddr;
+ *pdns = hostaddr;
return CURLE_OK;
}
#endif
@@ -3160,31 +3282,35 @@ static CURLcode resolve_unix(struct Curl_easy *data,
*************************************************************/
static CURLcode resolve_server(struct Curl_easy *data,
struct connectdata *conn,
- bool *async)
+ bool *async,
+ struct Curl_dns_entry **pdns)
{
struct hostname *ehost;
timediff_t timeout_ms = Curl_timeleft(data, NULL, TRUE);
const char *peertype = "host";
- int rc;
+ CURLcode result;
+
+ *pdns = NULL;
+
#ifdef USE_UNIX_SOCKETS
- char *unix_path = conn->unix_domain_socket;
+ {
+ char *unix_path = conn->unix_domain_socket;
#ifndef CURL_DISABLE_PROXY
- if(!unix_path && CONN_IS_PROXIED(conn) && conn->socks_proxy.host.name &&
- !strncmp(UNIX_SOCKET_PREFIX"/",
- conn->socks_proxy.host.name, sizeof(UNIX_SOCKET_PREFIX)))
- unix_path = conn->socks_proxy.host.name + sizeof(UNIX_SOCKET_PREFIX) - 1;
+ if(!unix_path && CONN_IS_PROXIED(conn) && conn->socks_proxy.host.name &&
+ !strncmp(UNIX_SOCKET_PREFIX"/",
+ conn->socks_proxy.host.name, sizeof(UNIX_SOCKET_PREFIX)))
+ unix_path = conn->socks_proxy.host.name + sizeof(UNIX_SOCKET_PREFIX) - 1;
#endif
- if(unix_path) {
- /* This only works if previous transport is TRNSPRT_TCP. Check it? */
- conn->transport = TRNSPRT_UNIX;
- return resolve_unix(data, conn, unix_path);
+ if(unix_path) {
+ /* This only works if previous transport is TRNSPRT_TCP. Check it? */
+ conn->transport = TRNSPRT_UNIX;
+ return resolve_unix(data, conn, unix_path, pdns);
+ }
}
#endif
- DEBUGASSERT(conn->dns_entry == NULL);
-
#ifndef CURL_DISABLE_PROXY
if(CONN_IS_PROXIED(conn)) {
ehost = conn->bits.socksproxy ? &conn->socks_proxy.host :
@@ -3206,22 +3332,25 @@ static CURLcode resolve_server(struct Curl_easy *data,
if(!conn->hostname_resolve)
return CURLE_OUT_OF_MEMORY;
- rc = Curl_resolv_timeout(data, conn->hostname_resolve,
- conn->primary.remote_port,
- &conn->dns_entry, timeout_ms);
- if(rc == CURLRESOLV_PENDING)
+ result = Curl_resolv_timeout(data, conn->hostname_resolve,
+ conn->primary.remote_port, conn->ip_version,
+ pdns, timeout_ms);
+ DEBUGASSERT(!result || !*pdns);
+ if(result == CURLE_AGAIN) {
*async = TRUE;
- else if(rc == CURLRESOLV_TIMEDOUT) {
+ return CURLE_OK;
+ }
+ else if(result == CURLE_OPERATION_TIMEDOUT) {
failf(data, "Failed to resolve %s '%s' with timeout after %"
FMT_TIMEDIFF_T " ms", peertype, ehost->dispname,
- Curl_timediff(Curl_now(), data->progress.t_startsingle));
+ curlx_timediff(curlx_now(), data->progress.t_startsingle));
return CURLE_OPERATION_TIMEDOUT;
}
- else if(!conn->dns_entry) {
+ else if(result) {
failf(data, "Could not resolve %s: %s", peertype, ehost->dispname);
- return CURLE_COULDNT_RESOLVE_HOST;
+ return result;
}
-
+ DEBUGASSERT(*pdns);
return CURLE_OK;
}
@@ -3300,6 +3429,15 @@ static void reuse_conn(struct Curl_easy *data,
Curl_conn_free(data, temp);
}
+static void conn_meta_freeentry(void *p)
+{
+ (void)p;
+ /* Will always be FALSE. Cannot use a 0 assert here since compilers
+ * are not in agreement if they then want a NORETURN attribute or
+ * not. *sigh* */
+ DEBUGASSERT(p == NULL);
+}
+
/**
* create_conn() sets up a new connectdata struct, or reuses an already
* existing one, and resolves hostname.
@@ -3310,14 +3448,14 @@ static void reuse_conn(struct Curl_easy *data,
*
* @param data The sessionhandle pointer
* @param in_connect is set to the next connection data pointer
- * @param async is set TRUE when an async DNS resolution is pending
+ * @param reusedp is set to to TRUE if connection was reused
* @see Curl_setup_conn()
*
*/
static CURLcode create_conn(struct Curl_easy *data,
struct connectdata **in_connect,
- bool *async)
+ bool *reusedp)
{
CURLcode result = CURLE_OK;
struct connectdata *conn;
@@ -3327,7 +3465,7 @@ static CURLcode create_conn(struct Curl_easy *data,
bool force_reuse = FALSE;
bool waitpipe = FALSE;
- *async = FALSE;
+ *reusedp = FALSE;
*in_connect = NULL;
/*************************************************************
@@ -3355,6 +3493,9 @@ static CURLcode create_conn(struct Curl_easy *data,
*in_connect = conn;
/* Do the unfailable inits first, before checks that may early return */
+ Curl_hash_init(&conn->meta_hash, 23,
+ Curl_hash_str, curlx_str_key_compare, conn_meta_freeentry);
+
/* GSSAPI related inits */
Curl_sec_conn_init(conn);
@@ -3498,28 +3639,26 @@ static CURLcode create_conn(struct Curl_easy *data,
/* conn_protocol can only provide "old" protocols */
data->info.conn_protocol = (conn->handler->protocol) & CURLPROTO_MASK;
result = conn->handler->connect_it(data, &done);
+ if(result)
+ goto out;
/* Setup a "faked" transfer that will do nothing */
+ Curl_attach_connection(data, conn);
+ result = Curl_cpool_add(data, conn);
if(!result) {
- Curl_attach_connection(data, conn);
- result = Curl_cpool_add(data, conn);
+ /* Setup whatever necessary for a resumed transfer */
+ result = setup_range(data);
if(!result) {
- /* Setup whatever necessary for a resumed transfer */
- result = setup_range(data);
+ Curl_xfer_setup_nop(data);
+ result = Curl_init_do(data, conn);
}
-
- if(result) {
- DEBUGASSERT(conn->handler->done);
- /* we ignore the return code for the protocol-specific DONE */
- (void)conn->handler->done(data, result, FALSE);
- goto out;
- }
- Curl_xfer_setup_nop(data);
}
- /* since we skip do_init() */
- Curl_init_do(data, conn);
-
+ if(result) {
+ DEBUGASSERT(conn->handler->done);
+ /* we ignore the return code for the protocol-specific DONE */
+ (void)conn->handler->done(data, result, FALSE);
+ }
goto out;
}
#endif
@@ -3597,10 +3736,12 @@ static CURLcode create_conn(struct Curl_easy *data,
conn->bits.tls_enable_alpn = TRUE;
}
- if(waitpipe)
+ if(waitpipe) {
/* There is a connection that *might* become usable for multiplexing
"soon", and we wait for that */
+ infof(data, "Waiting on connection to negotiate possible multiplexing.");
connections_available = FALSE;
+ }
else {
switch(Curl_cpool_check_limits(data, conn)) {
case CPOOL_LIMIT_DEST:
@@ -3608,13 +3749,12 @@ static CURLcode create_conn(struct Curl_easy *data,
connections_available = FALSE;
break;
case CPOOL_LIMIT_TOTAL:
-#ifndef CURL_DISABLE_DOH
- if(data->set.dohfor_mid >= 0)
- infof(data, "Allowing DoH to override max connection limit");
- else
-#endif
- {
- infof(data, "No connections available in cache");
+ if(data->master_mid != UINT_MAX)
+ CURL_TRC_M(data, "Allowing sub-requests (like DoH) to override "
+ "max connection limit");
+ else {
+ infof(data, "No connections available, total of %ld reached.",
+ data->multi->max_total_connections);
connections_available = FALSE;
}
break;
@@ -3624,8 +3764,6 @@ static CURLcode create_conn(struct Curl_easy *data,
}
if(!connections_available) {
- infof(data, "No connections available.");
-
Curl_conn_free(data, conn);
*in_connect = NULL;
@@ -3670,7 +3808,9 @@ static CURLcode create_conn(struct Curl_easy *data,
}
/* Setup and init stuff before DO starts, in preparing for the transfer. */
- Curl_init_do(data, conn);
+ result = Curl_init_do(data, conn);
+ if(result)
+ goto out;
/*
* Setup whatever necessary for a resumed transfer
@@ -3685,15 +3825,7 @@ static CURLcode create_conn(struct Curl_easy *data,
/* We are reusing the connection - no need to resolve anything, and
idnconvert_hostname() was called already in create_conn() for the reuse
case. */
- *async = FALSE;
- }
- else {
- /*************************************************************
- * Resolve the address of the server or proxy
- *************************************************************/
- result = resolve_server(data, conn, async);
- if(result)
- goto out;
+ *reusedp = TRUE;
}
/* persist the scheme and handler the transfer is using */
@@ -3722,21 +3854,17 @@ out:
* Curl_setup_conn() also handles reused connections
*/
CURLcode Curl_setup_conn(struct Curl_easy *data,
+ struct Curl_dns_entry *dns,
bool *protocol_done)
{
CURLcode result = CURLE_OK;
struct connectdata *conn = data->conn;
+ DEBUGASSERT(dns);
Curl_pgrsTime(data, TIMER_NAMELOOKUP);
- if(conn->handler->flags & PROTOPT_NONETWORK) {
- /* nothing to setup when not using a network */
- *protocol_done = TRUE;
- return result;
- }
-
if(!conn->bits.reuse)
- result = Curl_conn_setup(data, conn, FIRSTSOCKET, conn->dns_entry,
+ result = Curl_conn_setup(data, conn, FIRSTSOCKET, dns,
CURL_CF_SSL_DEFAULT);
if(!result)
result = Curl_headers_init(data);
@@ -3752,31 +3880,52 @@ CURLcode Curl_connect(struct Curl_easy *data,
{
CURLcode result;
struct connectdata *conn;
+ bool reused = FALSE;
*asyncp = FALSE; /* assume synchronous resolves by default */
+ *protocol_done = FALSE;
/* Set the request to virgin state based on transfer settings */
Curl_req_hard_reset(&data->req, data);
/* call the stuff that needs to be called */
- result = create_conn(data, &conn, asyncp);
+ result = create_conn(data, &conn, &reused);
+
+ if(result == CURLE_NO_CONNECTION_AVAILABLE) {
+ DEBUGASSERT(!conn);
+ return result;
+ }
if(!result) {
- if(CONN_INUSE(conn) > 1)
- /* multiplexed */
+ DEBUGASSERT(conn);
+ if(reused) {
+ if(CONN_ATTACHED(conn) > 1)
+ /* multiplexed */
+ *protocol_done = TRUE;
+ }
+ else if(conn->handler->flags & PROTOPT_NONETWORK) {
+ *asyncp = FALSE;
+ Curl_pgrsTime(data, TIMER_NAMELOOKUP);
*protocol_done = TRUE;
- else if(!*asyncp) {
- /* DNS resolution is done: that is either because this is a reused
- connection, in which case DNS was unnecessary, or because DNS
- really did finish already (synch resolver/fast async resolve) */
- result = Curl_setup_conn(data, protocol_done);
+ }
+ else {
+ /*************************************************************
+ * Resolve the address of the server or proxy
+ *************************************************************/
+ struct Curl_dns_entry *dns;
+ result = resolve_server(data, conn, asyncp, &dns);
+ if(!result) {
+ *asyncp = !dns;
+ if(dns)
+ /* DNS resolution is done: that is either because this is a reused
+ connection, in which case DNS was unnecessary, or because DNS
+ really did finish already (synch resolver/fast async resolve) */
+ result = Curl_setup_conn(data, dns, protocol_done);
+ }
}
}
- if(result == CURLE_NO_CONNECTION_AVAILABLE) {
- return result;
- }
- else if(result && conn) {
+ if(result && conn) {
/* We are not allowed to return failure with memory left allocated in the
connectdata struct, free those here */
Curl_detach_connection(data);
@@ -3923,3 +4072,25 @@ void Curl_data_priority_clear_state(struct Curl_easy *data)
}
#endif /* defined(USE_HTTP2) || defined(USE_HTTP3) */
+
+
+CURLcode Curl_conn_meta_set(struct connectdata *conn, const char *key,
+ void *meta_data, Curl_meta_dtor *meta_dtor)
+{
+ if(!Curl_hash_add2(&conn->meta_hash, CURL_UNCONST(key), strlen(key) + 1,
+ meta_data, meta_dtor)) {
+ meta_dtor(CURL_UNCONST(key), strlen(key) + 1, meta_data);
+ return CURLE_OUT_OF_MEMORY;
+ }
+ return CURLE_OK;
+}
+
+void Curl_conn_meta_remove(struct connectdata *conn, const char *key)
+{
+ Curl_hash_delete(&conn->meta_hash, CURL_UNCONST(key), strlen(key) + 1);
+}
+
+void *Curl_conn_meta_get(struct connectdata *conn, const char *key)
+{
+ return Curl_hash_pick(&conn->meta_hash, CURL_UNCONST(key), strlen(key) + 1);
+}
diff --git a/libs/libcurl/src/url.h b/libs/libcurl/src/url.h
index 30db5c78b5..3ab21dd8b5 100644
--- a/libs/libcurl/src/url.h
+++ b/libs/libcurl/src/url.h
@@ -38,12 +38,35 @@ CURLcode Curl_uc_to_curlcode(CURLUcode uc);
CURLcode Curl_close(struct Curl_easy **datap); /* opposite of curl_open() */
CURLcode Curl_connect(struct Curl_easy *, bool *async, bool *protocol_connect);
CURLcode Curl_setup_conn(struct Curl_easy *data,
+ struct Curl_dns_entry *dns,
bool *protocol_done);
void Curl_conn_free(struct Curl_easy *data, struct connectdata *conn);
CURLcode Curl_parse_login_details(const char *login, const size_t len,
char **userptr, char **passwdptr,
char **optionsptr);
+/* Attach/Clear/Get meta data for an easy handle. Needs to provide
+ * a destructor, will be automatically called when the easy handle
+ * is reset or closed. */
+typedef void Curl_meta_dtor(void *key, size_t key_len, void *meta_data);
+
+/* Set the transfer meta data for the key. Any existing entry for that
+ * key will be destroyed.
+ * Takes ownership of `meta_data` and destroys it when the call fails. */
+CURLcode Curl_meta_set(struct Curl_easy *data, const char *key,
+ void *meta_data, Curl_meta_dtor *meta_dtor);
+void Curl_meta_remove(struct Curl_easy *data, const char *key);
+void *Curl_meta_get(struct Curl_easy *data, const char *key);
+void Curl_meta_reset(struct Curl_easy *data);
+
+/* Set connection meta data for the key. Any existing entry for that
+ * key will be destroyed.
+ * Takes ownership of `meta_data` and destroys it when the call fails. */
+CURLcode Curl_conn_meta_set(struct connectdata *conn, const char *key,
+ void *meta_data, Curl_meta_dtor *meta_dtor);
+void Curl_conn_meta_remove(struct connectdata *conn, const char *key);
+void *Curl_conn_meta_get(struct connectdata *conn, const char *key);
+
/* Get protocol handler for a URI scheme
* @param scheme URI scheme, case-insensitive
* @return NULL of handler not found
diff --git a/libs/libcurl/src/urlapi-int.h b/libs/libcurl/src/urlapi-int.h
index 890e3285d9..a6d2b16be1 100644
--- a/libs/libcurl/src/urlapi-int.h
+++ b/libs/libcurl/src/urlapi-int.h
@@ -30,6 +30,8 @@ size_t Curl_is_absolute_url(const char *url, char *buf, size_t buflen,
CURLUcode Curl_url_set_authority(CURLU *u, const char *authority);
+CURLUcode Curl_junkscan(const char *url, size_t *urllen, bool allowspace);
+
#ifdef UNITTESTS
UNITTEST CURLUcode Curl_parse_port(struct Curl_URL *u, struct dynbuf *host,
bool has_scheme);
diff --git a/libs/libcurl/src/urlapi.c b/libs/libcurl/src/urlapi.c
index cd00a9f0f8..f0ea831c29 100644
--- a/libs/libcurl/src/urlapi.c
+++ b/libs/libcurl/src/urlapi.c
@@ -30,11 +30,11 @@
#include "url.h"
#include "escape.h"
#include "curl_ctype.h"
-#include "inet_pton.h"
+#include "curlx/inet_pton.h"
#include "inet_ntop.h"
#include "strdup.h"
#include "idn.h"
-#include "strparse.h"
+#include "curlx/strparse.h"
#include "curl_memrchr.h"
/* The last 3 #include files should be in this order */
@@ -129,7 +129,6 @@ static const char *find_host_sep(const char *url)
#define cc2cu(x) ((x) == CURLE_TOO_LARGE ? CURLUE_TOO_LARGE : \
CURLUE_OUT_OF_MEMORY)
-static const char hexdigits[] = "0123456789abcdef";
/* urlencode_str() writes data into an output dynbuf and URL-encodes the
* spaces in the source URL accordingly.
*
@@ -152,25 +151,24 @@ static CURLUcode urlencode_str(struct dynbuf *o, const char *url,
/* output the first piece as-is */
n = (const char *)host_sep - url;
- result = Curl_dyn_addn(o, url, n);
+ result = curlx_dyn_addn(o, url, n);
len -= n;
}
for(iptr = host_sep; len && !result; iptr++, len--) {
if(*iptr == ' ') {
if(left)
- result = Curl_dyn_addn(o, "%20", 3);
+ result = curlx_dyn_addn(o, "%20", 3);
else
- result = Curl_dyn_addn(o, "+", 1);
+ result = curlx_dyn_addn(o, "+", 1);
}
else if((*iptr < ' ') || (*iptr >= 0x7f)) {
- char out[3]={'%'};
- out[1] = hexdigits[*iptr >> 4];
- out[2] = hexdigits[*iptr & 0xf];
- result = Curl_dyn_addn(o, out, 3);
+ unsigned char out[3]={'%'};
+ Curl_hexbyte(&out[1], *iptr, TRUE);
+ result = curlx_dyn_addn(o, out, 3);
}
else {
- result = Curl_dyn_addn(o, iptr, 1);
+ result = curlx_dyn_addn(o, iptr, 1);
if(*iptr == '?')
left = FALSE;
}
@@ -290,22 +288,22 @@ static CURLUcode redirect_url(const char *base, const char *relurl,
prelen = cutoff ? (size_t)(cutoff - base) : strlen(base);
/* build new URL */
- Curl_dyn_init(&urlbuf, CURL_MAX_INPUT_LENGTH);
+ curlx_dyn_init(&urlbuf, CURL_MAX_INPUT_LENGTH);
- if(!Curl_dyn_addn(&urlbuf, base, prelen) &&
+ if(!curlx_dyn_addn(&urlbuf, base, prelen) &&
!urlencode_str(&urlbuf, useurl, strlen(useurl), !host_changed, FALSE)) {
- uc = parseurl_and_replace(Curl_dyn_ptr(&urlbuf), u,
+ uc = parseurl_and_replace(curlx_dyn_ptr(&urlbuf), u,
flags & ~CURLU_PATH_AS_IS);
}
else
uc = CURLUE_OUT_OF_MEMORY;
- Curl_dyn_free(&urlbuf);
+ curlx_dyn_free(&urlbuf);
return uc;
}
/* scan for byte values <= 31, 127 and sometimes space */
-static CURLUcode junkscan(const char *url, size_t *urllen, bool allowspace)
+CURLUcode Curl_junkscan(const char *url, size_t *urllen, bool allowspace)
{
size_t n = strlen(url);
size_t i;
@@ -419,7 +417,7 @@ UNITTEST CURLUcode Curl_parse_port(struct Curl_URL *u, struct dynbuf *host,
bool has_scheme)
{
const char *portptr;
- char *hostname = Curl_dyn_ptr(host);
+ char *hostname = curlx_dyn_ptr(host);
/*
* Find the end of an IPv6 address on the ']' ending bracket.
*/
@@ -450,12 +448,12 @@ UNITTEST CURLUcode Curl_parse_port(struct Curl_URL *u, struct dynbuf *host,
Do not do it if the URL has no scheme, to make something that looks like
a scheme not work!
*/
- Curl_dyn_setlen(host, keep);
+ curlx_dyn_setlen(host, keep);
portptr++;
if(!*portptr)
return has_scheme ? CURLUE_OK : CURLUE_BAD_PORT_NUMBER;
- if(Curl_str_number(&portptr, &port, 0xffff) || *portptr)
+ if(curlx_str_number(&portptr, &port, 0xffff) || *portptr)
return CURLUE_BAD_PORT_NUMBER;
u->portnum = (unsigned short) port;
@@ -515,7 +513,7 @@ static CURLUcode ipv6_parse(struct Curl_URL *u, char *hostname,
hostname[hlen] = 0; /* end the address there */
if(1 != curlx_inet_pton(AF_INET6, hostname, dest))
return CURLUE_BAD_IPV6;
- if(curlx_inet_ntop(AF_INET6, dest, hostname, hlen)) {
+ if(Curl_inet_ntop(AF_INET6, dest, hostname, hlen)) {
hlen = strlen(hostname); /* might be shorter now */
hostname[hlen + 1] = 0;
}
@@ -567,7 +565,7 @@ static int ipv4_normalize(struct dynbuf *host)
{
bool done = FALSE;
int n = 0;
- const char *c = Curl_dyn_ptr(host);
+ const char *c = curlx_dyn_ptr(host);
unsigned int parts[4] = {0, 0, 0, 0};
CURLcode result = CURLE_OK;
@@ -580,13 +578,13 @@ static int ipv4_normalize(struct dynbuf *host)
if(*c == '0') {
if(c[1] == 'x') {
c += 2; /* skip the prefix */
- rc = Curl_str_hex(&c, &l, UINT_MAX);
+ rc = curlx_str_hex(&c, &l, UINT_MAX);
}
else
- rc = Curl_str_octal(&c, &l, UINT_MAX);
+ rc = curlx_str_octal(&c, &l, UINT_MAX);
}
else
- rc = Curl_str_number(&c, &l, UINT_MAX);
+ rc = curlx_str_number(&c, &l, UINT_MAX);
if(rc)
return HOST_NAME;
@@ -612,44 +610,44 @@ static int ipv4_normalize(struct dynbuf *host)
switch(n) {
case 0: /* a -- 32 bits */
- Curl_dyn_reset(host);
+ curlx_dyn_reset(host);
- result = Curl_dyn_addf(host, "%u.%u.%u.%u",
- (parts[0] >> 24),
- ((parts[0] >> 16) & 0xff),
- ((parts[0] >> 8) & 0xff),
- (parts[0] & 0xff));
+ result = curlx_dyn_addf(host, "%u.%u.%u.%u",
+ (parts[0] >> 24),
+ ((parts[0] >> 16) & 0xff),
+ ((parts[0] >> 8) & 0xff),
+ (parts[0] & 0xff));
break;
case 1: /* a.b -- 8.24 bits */
if((parts[0] > 0xff) || (parts[1] > 0xffffff))
return HOST_NAME;
- Curl_dyn_reset(host);
- result = Curl_dyn_addf(host, "%u.%u.%u.%u",
- (parts[0]),
- ((parts[1] >> 16) & 0xff),
- ((parts[1] >> 8) & 0xff),
- (parts[1] & 0xff));
+ curlx_dyn_reset(host);
+ result = curlx_dyn_addf(host, "%u.%u.%u.%u",
+ (parts[0]),
+ ((parts[1] >> 16) & 0xff),
+ ((parts[1] >> 8) & 0xff),
+ (parts[1] & 0xff));
break;
case 2: /* a.b.c -- 8.8.16 bits */
if((parts[0] > 0xff) || (parts[1] > 0xff) || (parts[2] > 0xffff))
return HOST_NAME;
- Curl_dyn_reset(host);
- result = Curl_dyn_addf(host, "%u.%u.%u.%u",
- (parts[0]),
- (parts[1]),
- ((parts[2] >> 8) & 0xff),
- (parts[2] & 0xff));
+ curlx_dyn_reset(host);
+ result = curlx_dyn_addf(host, "%u.%u.%u.%u",
+ (parts[0]),
+ (parts[1]),
+ ((parts[2] >> 8) & 0xff),
+ (parts[2] & 0xff));
break;
case 3: /* a.b.c.d -- 8.8.8.8 bits */
if((parts[0] > 0xff) || (parts[1] > 0xff) || (parts[2] > 0xff) ||
(parts[3] > 0xff))
return HOST_NAME;
- Curl_dyn_reset(host);
- result = Curl_dyn_addf(host, "%u.%u.%u.%u",
- (parts[0]),
- (parts[1]),
- (parts[2]),
- (parts[3]));
+ curlx_dyn_reset(host);
+ result = curlx_dyn_addf(host, "%u.%u.%u.%u",
+ (parts[0]),
+ (parts[1]),
+ (parts[2]),
+ (parts[3]));
break;
}
if(result)
@@ -661,7 +659,7 @@ static int ipv4_normalize(struct dynbuf *host)
static CURLUcode urldecode_host(struct dynbuf *host)
{
char *per = NULL;
- const char *hostname = Curl_dyn_ptr(host);
+ const char *hostname = curlx_dyn_ptr(host);
per = strchr(hostname, '%');
if(!per)
/* nothing to decode */
@@ -674,8 +672,8 @@ static CURLUcode urldecode_host(struct dynbuf *host)
REJECT_CTRL);
if(result)
return CURLUE_BAD_HOSTNAME;
- Curl_dyn_reset(host);
- result = Curl_dyn_addn(host, decoded, dlen);
+ curlx_dyn_reset(host);
+ result = curlx_dyn_addn(host, decoded, dlen);
free(decoded);
if(result)
return cc2cu(result);
@@ -701,7 +699,7 @@ static CURLUcode parse_authority(struct Curl_URL *u,
if(uc)
goto out;
- result = Curl_dyn_addn(host, auth + offset, authlen - offset);
+ result = curlx_dyn_addn(host, auth + offset, authlen - offset);
if(result) {
uc = cc2cu(result);
goto out;
@@ -711,19 +709,19 @@ static CURLUcode parse_authority(struct Curl_URL *u,
if(uc)
goto out;
- if(!Curl_dyn_len(host))
+ if(!curlx_dyn_len(host))
return CURLUE_NO_HOST;
switch(ipv4_normalize(host)) {
case HOST_IPV4:
break;
case HOST_IPV6:
- uc = ipv6_parse(u, Curl_dyn_ptr(host), Curl_dyn_len(host));
+ uc = ipv6_parse(u, curlx_dyn_ptr(host), curlx_dyn_len(host));
break;
case HOST_NAME:
uc = urldecode_host(host);
if(!uc)
- uc = hostname_check(u, Curl_dyn_ptr(host), Curl_dyn_len(host));
+ uc = hostname_check(u, curlx_dyn_ptr(host), curlx_dyn_len(host));
break;
case HOST_ERROR:
uc = CURLUE_OUT_OF_MEMORY;
@@ -744,15 +742,15 @@ CURLUcode Curl_url_set_authority(CURLU *u, const char *authority)
struct dynbuf host;
DEBUGASSERT(authority);
- Curl_dyn_init(&host, CURL_MAX_INPUT_LENGTH);
+ curlx_dyn_init(&host, CURL_MAX_INPUT_LENGTH);
result = parse_authority(u, authority, strlen(authority),
CURLU_DISALLOW_USER, &host, !!u->scheme);
if(result)
- Curl_dyn_free(&host);
+ curlx_dyn_free(&host);
else {
free(u->host);
- u->host = Curl_dyn_ptr(&host);
+ u->host = curlx_dyn_ptr(&host);
}
return result;
}
@@ -806,7 +804,7 @@ UNITTEST int dedotdotify(const char *input, size_t clen, char **outp)
if(clen < 2)
return 0;
- Curl_dyn_init(&out, clen + 1);
+ curlx_dyn_init(&out, clen + 1);
/* A. If the input buffer begins with a prefix of "../" or "./", then
remove that prefix from the input buffer; otherwise, */
@@ -846,7 +844,7 @@ UNITTEST int dedotdotify(const char *input, size_t clen, char **outp)
the input buffer; otherwise, */
if(is_dot(&p, &blen)) {
if(!blen) { /* /. */
- result = Curl_dyn_addn(&out, "/", 1);
+ result = curlx_dyn_addn(&out, "/", 1);
break;
}
else if(ISSLASH(*p)) { /* /./ */
@@ -861,13 +859,13 @@ UNITTEST int dedotdotify(const char *input, size_t clen, char **outp)
preceding "/" (if any) from the output buffer; otherwise, */
else if(is_dot(&p, &blen) && (ISSLASH(*p) || !blen)) {
/* remove the last segment from the output buffer */
- size_t len = Curl_dyn_len(&out);
+ size_t len = curlx_dyn_len(&out);
if(len) {
- char *ptr = Curl_dyn_ptr(&out);
+ char *ptr = curlx_dyn_ptr(&out);
char *last = memrchr(ptr, '/', len);
if(last)
/* trim the output at the slash */
- Curl_dyn_setlen(&out, last - ptr);
+ curlx_dyn_setlen(&out, last - ptr);
}
if(blen) { /* /../ */
@@ -875,7 +873,7 @@ UNITTEST int dedotdotify(const char *input, size_t clen, char **outp)
clen = blen;
continue;
}
- result = Curl_dyn_addn(&out, "/", 1);
+ result = curlx_dyn_addn(&out, "/", 1);
break;
}
}
@@ -886,14 +884,14 @@ UNITTEST int dedotdotify(const char *input, size_t clen, char **outp)
any subsequent characters up to, but not including, the next "/"
character or the end of the input buffer. */
- result = Curl_dyn_addn(&out, input, 1);
+ result = curlx_dyn_addn(&out, input, 1);
input++;
clen--;
}
end:
if(!result) {
- if(Curl_dyn_len(&out))
- *outp = Curl_dyn_ptr(&out);
+ if(curlx_dyn_len(&out))
+ *outp = curlx_dyn_ptr(&out);
else {
*outp = strdup("");
if(!*outp)
@@ -918,9 +916,9 @@ static CURLUcode parseurl(const char *url, CURLU *u, unsigned int flags)
DEBUGASSERT(url);
- Curl_dyn_init(&host, CURL_MAX_INPUT_LENGTH);
+ curlx_dyn_init(&host, CURL_MAX_INPUT_LENGTH);
- result = junkscan(url, &urllen, !!(flags & CURLU_ALLOW_SPACE));
+ result = Curl_junkscan(url, &urllen, !!(flags & CURLU_ALLOW_SPACE));
if(result)
goto fail;
@@ -998,7 +996,7 @@ static CURLUcode parseurl(const char *url, CURLU *u, unsigned int flags)
len = path - ptr;
if(len) {
- CURLcode code = Curl_dyn_addn(&host, ptr, len);
+ CURLcode code = curlx_dyn_addn(&host, ptr, len);
if(code) {
result = cc2cu(code);
goto fail;
@@ -1022,7 +1020,7 @@ static CURLUcode parseurl(const char *url, CURLU *u, unsigned int flags)
if(!uncpath)
/* no host for file: URLs by default */
- Curl_dyn_reset(&host);
+ curlx_dyn_reset(&host);
#if !defined(_WIN32) && !defined(MSDOS) && !defined(__CYGWIN__)
/* Do not allow Windows drive letters when not in Windows.
@@ -1108,7 +1106,7 @@ static CURLUcode parseurl(const char *url, CURLU *u, unsigned int flags)
goto fail;
if((flags & CURLU_GUESS_SCHEME) && !schemep) {
- const char *hostname = Curl_dyn_ptr(&host);
+ const char *hostname = curlx_dyn_ptr(&host);
/* legacy curl-style guess based on hostname */
if(checkprefix("ftp.", hostname))
schemep = "ftp";
@@ -1135,7 +1133,7 @@ static CURLUcode parseurl(const char *url, CURLU *u, unsigned int flags)
}
else if(flags & CURLU_NO_AUTHORITY) {
/* allowed to be empty. */
- if(Curl_dyn_add(&host, "")) {
+ if(curlx_dyn_add(&host, "")) {
result = CURLUE_OUT_OF_MEMORY;
goto fail;
}
@@ -1154,11 +1152,11 @@ static CURLUcode parseurl(const char *url, CURLU *u, unsigned int flags)
/* skip the leading '#' in the copy but include the terminating null */
if(flags & CURLU_URLENCODE) {
struct dynbuf enc;
- Curl_dyn_init(&enc, CURL_MAX_INPUT_LENGTH);
+ curlx_dyn_init(&enc, CURL_MAX_INPUT_LENGTH);
result = urlencode_str(&enc, fragment + 1, fraglen - 1, TRUE, FALSE);
if(result)
goto fail;
- u->fragment = Curl_dyn_ptr(&enc);
+ u->fragment = curlx_dyn_ptr(&enc);
}
else {
u->fragment = Curl_memdup0(fragment + 1, fraglen - 1);
@@ -1181,12 +1179,12 @@ static CURLUcode parseurl(const char *url, CURLU *u, unsigned int flags)
if(qlen > 1) {
if(flags & CURLU_URLENCODE) {
struct dynbuf enc;
- Curl_dyn_init(&enc, CURL_MAX_INPUT_LENGTH);
+ curlx_dyn_init(&enc, CURL_MAX_INPUT_LENGTH);
/* skip the leading question mark */
result = urlencode_str(&enc, query + 1, qlen - 1, TRUE, TRUE);
if(result)
goto fail;
- u->query = Curl_dyn_ptr(&enc);
+ u->query = curlx_dyn_ptr(&enc);
}
else {
u->query = Curl_memdup0(query + 1, qlen - 1);
@@ -1208,12 +1206,12 @@ static CURLUcode parseurl(const char *url, CURLU *u, unsigned int flags)
if(pathlen && (flags & CURLU_URLENCODE)) {
struct dynbuf enc;
- Curl_dyn_init(&enc, CURL_MAX_INPUT_LENGTH);
+ curlx_dyn_init(&enc, CURL_MAX_INPUT_LENGTH);
result = urlencode_str(&enc, path, pathlen, TRUE, FALSE);
if(result)
goto fail;
- pathlen = Curl_dyn_len(&enc);
- path = u->path = Curl_dyn_ptr(&enc);
+ pathlen = curlx_dyn_len(&enc);
+ path = u->path = curlx_dyn_ptr(&enc);
}
if(pathlen <= 1) {
@@ -1248,11 +1246,11 @@ static CURLUcode parseurl(const char *url, CURLU *u, unsigned int flags)
}
}
- u->host = Curl_dyn_ptr(&host);
+ u->host = curlx_dyn_ptr(&host);
return result;
fail:
- Curl_dyn_free(&host);
+ curlx_dyn_free(&host);
free_urlhandle(u);
return result;
}
@@ -1470,11 +1468,11 @@ CURLUcode curl_url_get(const CURLU *u, CURLUPart what,
/* make it '[ host %25 zoneid ]' */
struct dynbuf enc;
size_t hostlen = strlen(u->host);
- Curl_dyn_init(&enc, CURL_MAX_INPUT_LENGTH);
- if(Curl_dyn_addf(&enc, "%.*s%%25%s]", (int)hostlen - 1, u->host,
- u->zoneid))
+ curlx_dyn_init(&enc, CURL_MAX_INPUT_LENGTH);
+ if(curlx_dyn_addf(&enc, "%.*s%%25%s]", (int)hostlen - 1, u->host,
+ u->zoneid))
return CURLUE_OUT_OF_MEMORY;
- allochost = Curl_dyn_ptr(&enc);
+ allochost = curlx_dyn_ptr(&enc);
}
}
else if(urlencode) {
@@ -1495,7 +1493,7 @@ CURLUcode curl_url_get(const CURLU *u, CURLUPart what,
}
}
else if(depunyfy) {
- if(Curl_is_ASCII_name(u->host) && !strncmp("xn--", u->host, 4)) {
+ if(Curl_is_ASCII_name(u->host)) {
#ifndef USE_IDN
return CURLUE_LACKS_IDN;
#else
@@ -1571,12 +1569,12 @@ CURLUcode curl_url_get(const CURLU *u, CURLUPart what,
if(urlencode) {
struct dynbuf enc;
CURLUcode uc;
- Curl_dyn_init(&enc, CURL_MAX_INPUT_LENGTH);
+ curlx_dyn_init(&enc, CURL_MAX_INPUT_LENGTH);
uc = urlencode_str(&enc, *part, partlen, TRUE, what == CURLUPART_QUERY);
if(uc)
return uc;
free(*part);
- *part = Curl_dyn_ptr(&enc);
+ *part = curlx_dyn_ptr(&enc);
}
else if(punycode) {
if(!Curl_is_ASCII_name(u->host)) {
@@ -1594,7 +1592,7 @@ CURLUcode curl_url_get(const CURLU *u, CURLUPart what,
}
}
else if(depunyfy) {
- if(Curl_is_ASCII_name(u->host) && !strncmp("xn--", u->host, 4)) {
+ if(Curl_is_ASCII_name(u->host)) {
#ifndef USE_IDN
return CURLUE_LACKS_IDN;
#else
@@ -1615,6 +1613,89 @@ CURLUcode curl_url_get(const CURLU *u, CURLUPart what,
return ifmissing;
}
+static CURLUcode set_url_scheme(CURLU *u, const char *scheme,
+ unsigned int flags)
+{
+ size_t plen = strlen(scheme);
+ const char *s = scheme;
+ if((plen > MAX_SCHEME_LEN) || (plen < 1))
+ /* too long or too short */
+ return CURLUE_BAD_SCHEME;
+ /* verify that it is a fine scheme */
+ if(!(flags & CURLU_NON_SUPPORT_SCHEME) && !Curl_get_scheme_handler(scheme))
+ return CURLUE_UNSUPPORTED_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;
+ u->guessed_scheme = FALSE;
+ return CURLUE_OK;
+}
+
+static CURLUcode set_url_port(CURLU *u, const char *provided_port)
+{
+ char *tmp;
+ curl_off_t port;
+ if(!ISDIGIT(provided_port[0]))
+ /* not a number */
+ return CURLUE_BAD_PORT_NUMBER;
+ if(curlx_str_number(&provided_port, &port, 0xffff) || *provided_port)
+ /* weirdly provided number, not good! */
+ return CURLUE_BAD_PORT_NUMBER;
+ tmp = aprintf("%" CURL_FORMAT_CURL_OFF_T, port);
+ if(!tmp)
+ return CURLUE_OUT_OF_MEMORY;
+ free(u->port);
+ u->port = tmp;
+ u->portnum = (unsigned short)port;
+ return CURLUE_OK;
+}
+
+static CURLUcode set_url(CURLU *u, const char *url, size_t part_size,
+ unsigned int flags)
+{
+ /*
+ * Allow a new URL to replace the existing (if any) contents.
+ *
+ * If the existing contents is enough for a URL, allow a relative URL to
+ * replace it.
+ */
+ CURLUcode uc;
+ char *oldurl = NULL;
+
+ if(!part_size) {
+ /* a blank URL is not a valid URL unless we already have a complete one
+ and this is a redirect */
+ if(!curl_url_get(u, CURLUPART_URL, &oldurl, flags)) {
+ /* success, meaning the "" is a fine relative URL, but nothing
+ changes */
+ free(oldurl);
+ return CURLUE_OK;
+ }
+ return CURLUE_MALFORMED_INPUT;
+ }
+
+ /* if the new thing is absolute or the old one is not (we could not get an
+ * absolute URL in 'oldurl'), then replace the existing with the new. */
+ if(Curl_is_absolute_url(url, NULL, 0,
+ flags & (CURLU_GUESS_SCHEME|CURLU_DEFAULT_SCHEME))
+ || curl_url_get(u, CURLUPART_URL, &oldurl, flags)) {
+ return parseurl_and_replace(url, u, flags);
+ }
+ DEBUGASSERT(oldurl); /* it is set here */
+ /* apply the relative part to create a new URL */
+ uc = redirect_url(oldurl, url, u, flags);
+ free(oldurl);
+ return uc;
+}
+
CURLUcode curl_url_set(CURLU *u, CURLUPart what,
const char *part, unsigned int flags)
{
@@ -1688,28 +1769,11 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what,
switch(what) {
case CURLUPART_SCHEME: {
- size_t plen = strlen(part);
- const char *s = part;
- if((plen > MAX_SCHEME_LEN) || (plen < 1))
- /* too long or too short */
- return CURLUE_BAD_SCHEME;
- /* verify that it is a fine scheme */
- if(!(flags & CURLU_NON_SUPPORT_SCHEME) && !Curl_get_scheme_handler(part))
- return CURLUE_UNSUPPORTED_SCHEME;
+ CURLUcode status = set_url_scheme(u, part, flags);
+ if(status)
+ return status;
storep = &u->scheme;
urlencode = FALSE; /* never */
- 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;
- u->guessed_scheme = FALSE;
break;
}
case CURLUPART_USER:
@@ -1729,23 +1793,7 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what,
storep = &u->zoneid;
break;
case CURLUPART_PORT:
- if(!ISDIGIT(part[0]))
- /* not a number */
- return CURLUE_BAD_PORT_NUMBER;
- else {
- char *tmp;
- curl_off_t port;
- if(Curl_str_number(&part, &port, 0xffff) || *part)
- /* weirdly provided number, not good! */
- return CURLUE_BAD_PORT_NUMBER;
- tmp = aprintf("%" CURL_FORMAT_CURL_OFF_T, port);
- if(!tmp)
- return CURLUE_OUT_OF_MEMORY;
- free(u->port);
- u->port = tmp;
- u->portnum = (unsigned short)port;
- return CURLUE_OK;
- }
+ return set_url_port(u, part);
case CURLUPART_PATH:
urlskipslash = TRUE;
leadingslash = TRUE; /* enforce */
@@ -1763,31 +1811,7 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what,
u->fragment_present = TRUE;
break;
case CURLUPART_URL: {
- /*
- * Allow a new URL to replace the existing (if any) contents.
- *
- * If the existing contents is enough for a URL, allow a relative URL to
- * replace it.
- */
- CURLUcode uc;
- char *oldurl;
-
- if(!nalloc)
- /* a blank URL is not a valid URL */
- return CURLUE_MALFORMED_INPUT;
-
- /* if the new thing is absolute or the old one is not (we could not get an
- * absolute URL in 'oldurl'), then replace the existing with the new. */
- if(Curl_is_absolute_url(part, NULL, 0,
- flags & (CURLU_GUESS_SCHEME|CURLU_DEFAULT_SCHEME))
- || curl_url_get(u, CURLUPART_URL, &oldurl, flags)) {
- return parseurl_and_replace(part, u, flags);
- }
- DEBUGASSERT(oldurl); /* it is set here */
- /* apply the relative part to create a new URL */
- uc = redirect_url(oldurl, part, u, flags);
- free(oldurl);
- return uc;
+ return set_url(u, part, nalloc, flags);
}
default:
return CURLUE_UNKNOWN_PART;
@@ -1796,10 +1820,10 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what,
{
const char *newp;
struct dynbuf enc;
- Curl_dyn_init(&enc, nalloc * 3 + 1 + leadingslash);
+ curlx_dyn_init(&enc, nalloc * 3 + 1 + leadingslash);
if(leadingslash && (part[0] != '/')) {
- CURLcode result = Curl_dyn_addn(&enc, "/", 1);
+ CURLcode result = curlx_dyn_addn(&enc, "/", 1);
if(result)
return cc2cu(result);
}
@@ -1809,7 +1833,7 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what,
for(i = (const unsigned char *)part; *i; i++) {
CURLcode result;
if((*i == ' ') && plusencode) {
- result = Curl_dyn_addn(&enc, "+", 1);
+ result = curlx_dyn_addn(&enc, "+", 1);
if(result)
return CURLUE_OUT_OF_MEMORY;
}
@@ -1819,15 +1843,14 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what,
if((*i == '=') && equalsencode)
/* only skip the first equals sign */
equalsencode = FALSE;
- result = Curl_dyn_addn(&enc, i, 1);
+ result = curlx_dyn_addn(&enc, i, 1);
if(result)
return cc2cu(result);
}
else {
- char out[3]={'%'};
- out[1] = hexdigits[*i >> 4];
- out[2] = hexdigits[*i & 0xf];
- result = Curl_dyn_addn(&enc, out, 3);
+ unsigned char out[3]={'%'};
+ Curl_hexbyte(&out[1], *i, TRUE);
+ result = curlx_dyn_addn(&enc, out, 3);
if(result)
return cc2cu(result);
}
@@ -1835,10 +1858,10 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what,
}
else {
char *p;
- CURLcode result = Curl_dyn_add(&enc, part);
+ CURLcode result = curlx_dyn_add(&enc, part);
if(result)
return cc2cu(result);
- p = Curl_dyn_ptr(&enc);
+ p = curlx_dyn_ptr(&enc);
while(*p) {
/* make sure percent encoded are lower case */
if((*p == '%') && ISXDIGIT(p[1]) && ISXDIGIT(p[2]) &&
@@ -1851,7 +1874,7 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what,
p++;
}
}
- newp = Curl_dyn_ptr(&enc);
+ newp = curlx_dyn_ptr(&enc);
if(appendquery && newp) {
/* Append the 'newp' string onto the old query. Add a '&' separator if
@@ -1861,29 +1884,29 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what,
bool addamperand = querylen && (u->query[querylen -1] != '&');
if(querylen) {
struct dynbuf qbuf;
- Curl_dyn_init(&qbuf, CURL_MAX_INPUT_LENGTH);
+ curlx_dyn_init(&qbuf, CURL_MAX_INPUT_LENGTH);
- if(Curl_dyn_addn(&qbuf, u->query, querylen)) /* add original query */
+ if(curlx_dyn_addn(&qbuf, u->query, querylen)) /* add original query */
goto nomem;
if(addamperand) {
- if(Curl_dyn_addn(&qbuf, "&", 1))
+ if(curlx_dyn_addn(&qbuf, "&", 1))
goto nomem;
}
- if(Curl_dyn_add(&qbuf, newp))
+ if(curlx_dyn_add(&qbuf, newp))
goto nomem;
- Curl_dyn_free(&enc);
+ curlx_dyn_free(&enc);
free(*storep);
- *storep = Curl_dyn_ptr(&qbuf);
+ *storep = curlx_dyn_ptr(&qbuf);
return CURLUE_OK;
nomem:
- Curl_dyn_free(&enc);
+ curlx_dyn_free(&enc);
return CURLUE_OUT_OF_MEMORY;
}
}
else if(what == CURLUPART_HOST) {
- size_t n = Curl_dyn_len(&enc);
+ size_t n = curlx_dyn_len(&enc);
if(!n && (flags & CURLU_NO_AUTHORITY)) {
/* Skip hostname check, it is allowed to be empty. */
}
@@ -1905,7 +1928,7 @@ nomem:
else if(hostname_check(u, (char *)CURL_UNCONST(newp), n))
bad = TRUE;
if(bad) {
- Curl_dyn_free(&enc);
+ curlx_dyn_free(&enc);
return CURLUE_BAD_HOSTNAME;
}
}
diff --git a/libs/libcurl/src/urldata.h b/libs/libcurl/src/urldata.h
index f986d76046..f30e97774f 100644
--- a/libs/libcurl/src/urldata.h
+++ b/libs/libcurl/src/urldata.h
@@ -95,13 +95,6 @@ typedef unsigned int curl_prot_t;
in the API */
#define CURLPROTO_MASK (0x3ffffff)
-#define DICT_MATCH "/MATCH:"
-#define DICT_MATCH2 "/M:"
-#define DICT_MATCH3 "/FIND:"
-#define DICT_DEFINE "/DEFINE:"
-#define DICT_DEFINE2 "/D:"
-#define DICT_DEFINE3 "/LOOKUP:"
-
#define CURL_DEFAULT_USER "anonymous"
#define CURL_DEFAULT_PASSWORD "ftp@example.com"
@@ -152,16 +145,15 @@ typedef unsigned int curl_prot_t;
#include <netinet/in6.h>
#endif
-#include "timeval.h"
+#include "curlx/timeval.h"
#include <curl/curl.h>
#include "http_chunks.h" /* for the structs and enum stuff */
#include "hostip.h"
#include "hash.h"
-#include "hash_offt.h"
#include "splay.h"
-#include "dynbuf.h"
+#include "curlx/dynbuf.h"
#include "dynhds.h"
#include "request.h"
#include "netrc.h"
@@ -183,7 +175,6 @@ typedef ssize_t (Curl_recv)(struct Curl_easy *data, /* transfer */
#include "mime.h"
#include "imap.h"
-#include "pop3.h"
#include "smtp.h"
#include "ftp.h"
#include "file.h"
@@ -273,6 +264,7 @@ struct ssl_primary_config {
char *clientcert;
char *cipher_list; /* list of ciphers to use */
char *cipher_list13; /* list of TLS 1.3 cipher suites to use */
+ char *signature_algorithms; /* list of signature algorithms to use */
char *pinned_key;
char *CRLfile; /* CRL to check certificate revocation */
struct curl_blob *cert_blob;
@@ -283,8 +275,8 @@ struct ssl_primary_config {
char *password; /* TLS password (for, e.g., SRP) */
#endif
char *curves; /* list of curves to use */
- unsigned char ssl_options; /* the CURLOPT_SSL_OPTIONS bitmask */
unsigned int version_max; /* max supported version the client wants to use */
+ unsigned char ssl_options; /* the CURLOPT_SSL_OPTIONS bitmask */
unsigned char version; /* what version the client wants to use */
BIT(verifypeer); /* set TRUE if this is desired */
BIT(verifyhost); /* set TRUE if CN/SAN must match hostname */
@@ -563,21 +555,6 @@ struct hostname {
#define CURL_WANT_RECV(data) \
(((data)->req.keepon & KEEP_RECVBITS) == KEEP_RECV)
-#if defined(CURLRES_ASYNCH) || !defined(CURL_DISABLE_DOH)
-#define USE_CURL_ASYNC
-struct Curl_async {
- struct Curl_dns_entry *dns;
-#ifdef CURLRES_ASYNCH
- struct thread_data thdata;
- void *resolver; /* resolver state, if it is used in the URL state -
- ares_channel e.g. */
-#endif
- int port;
- BIT(done); /* set TRUE when the lookup is complete */
-};
-
-#endif
-
#define FIRSTSOCKET 0
#define SECONDARYSOCKET 1
@@ -742,8 +719,6 @@ struct proxy_info {
char *passwd; /* proxy password string, allocated */
};
-struct ldapconninfo;
-
#define TRNSPRT_TCP 3
#define TRNSPRT_UDP 4
#define TRNSPRT_QUIC 5
@@ -764,18 +739,19 @@ struct connectdata {
handle is still used by one or more easy handles and can only used by any
other easy handle without careful consideration (== only for
multiplexing) and it cannot be used by another multi handle! */
-#define CONN_INUSE(c) Curl_llist_count(&(c)->easyq)
+#define CONN_INUSE(c) (!Curl_uint_spbset_empty(&(c)->xfers_attached))
+#define CONN_ATTACHED(c) Curl_uint_spbset_count(&(c)->xfers_attached)
/**** Fields set when inited and not modified again */
curl_off_t connection_id; /* Contains a unique number to make it easier to
track the connections in the log output */
char *destination; /* string carrying normalized hostname+port+scope */
- /* '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
- multi_done(). This entry will be NULL if the connection is reused as then
- there is no name resolve done. */
- struct Curl_dns_entry *dns_entry;
+ /* `meta_hash` is a general key-value store for implementations
+ * with the lifetime of the connection.
+ * Elements need to be added with their own destructor to be invoked when
+ * the connection is cleaned up (see Curl_hash_add2()).*/
+ struct Curl_hash meta_hash;
/* 'remote_addr' is the particular IP we connected to. it is owned, set
* and NULLed by the connected socket filter (if there is one). */
@@ -851,7 +827,14 @@ struct connectdata {
struct kerberos5data krb5; /* variables into the structure definition, */
#endif /* however, some of them are ftp specific. */
- struct Curl_llist easyq; /* List of easy handles using this connection */
+ struct uint_spbset xfers_attached; /* mids of attached transfers */
+ /* A connection cache from a SHARE might be used in several multi handles.
+ * We MUST not reuse connections that are running in another multi,
+ * for concurrency reasons. That multi might run in another thread.
+ * `attached_multi` is set by the first transfer attached and cleared
+ * when the last one is detached.
+ * NEVER call anything on this multi, just check for equality. */
+ struct Curl_multi *attached_multi;
/*************** Request - specific items ************/
#if defined(USE_WINDOWS_SSPI) && defined(SECPKG_ATTR_ENDPOINT_BINDINGS)
@@ -880,46 +863,6 @@ struct connectdata {
struct negotiatedata proxyneg; /* state data for proxy Negotiate auth */
#endif
- union {
-#ifndef CURL_DISABLE_FTP
- struct ftp_conn ftpc;
-#endif
-#ifdef USE_SSH
- struct ssh_conn sshc;
-#endif
-#ifndef CURL_DISABLE_TFTP
- struct tftp_state_data *tftpc;
-#endif
-#ifndef CURL_DISABLE_IMAP
- struct imap_conn imapc;
-#endif
-#ifndef CURL_DISABLE_POP3
- struct pop3_conn pop3c;
-#endif
-#ifndef CURL_DISABLE_SMTP
- struct smtp_conn smtpc;
-#endif
-#ifndef CURL_DISABLE_RTSP
- struct rtsp_conn rtspc;
-#endif
-#ifndef CURL_DISABLE_SMB
- struct smb_conn smbc;
-#endif
-#ifdef USE_LIBRTMP
- void *rtmp;
-#endif
-#ifdef USE_OPENLDAP
- struct ldapconninfo *ldapc;
-#endif
-#ifndef CURL_DISABLE_MQTT
- struct mqtt_conn mqtt;
-#endif
-#ifndef CURL_DISABLE_WEBSOCKETS
- struct websocket *ws;
-#endif
- unsigned int unused:1; /* avoids empty union */
- } proto;
-
#ifdef USE_UNIX_SOCKETS
char *unix_domain_socket;
#endif
@@ -1035,9 +978,6 @@ struct Progress {
curl_off_t current_speed; /* uses the currently fastest transfer */
curl_off_t earlydata_sent;
- int width; /* screen width at download start */
- int flags; /* see progress.h */
-
timediff_t timespent;
timediff_t t_postqueue;
@@ -1059,7 +999,11 @@ struct Progress {
curl_off_t speeder[ CURR_TIME ];
struct curltime speeder_time[ CURR_TIME ];
- int speeder_c;
+ unsigned char speeder_c;
+ BIT(hide);
+ BIT(ul_size_known);
+ BIT(dl_size_known);
+ BIT(headers_out); /* when the headers have been written */
BIT(callback); /* set when progress callback is used */
BIT(is_t_startransfer_set);
};
@@ -1208,6 +1152,8 @@ struct UrlState {
#endif
struct auth authhost; /* auth details for host */
struct auth authproxy; /* auth details for proxy */
+
+ struct Curl_dns_entry *dns[2]; /* DNS to connect FIRST/SECONDARY */
#ifdef USE_CURL_ASYNC
struct Curl_async async; /* asynchronous name resolver data */
#endif
@@ -1215,10 +1161,13 @@ struct UrlState {
#if defined(USE_OPENSSL)
/* void instead of ENGINE to avoid bleeding OpenSSL into this header */
void *engine;
- /* this is just a flag -- we do not need to reference the provider in any
- * way as OpenSSL takes care of that */
- BIT(provider);
- BIT(provider_failed);
+ /* void instead of OSSL_PROVIDER */
+ void *provider;
+ void *baseprov;
+ void *libctx;
+ char *propq; /* for a provider */
+
+ BIT(provider_loaded);
#endif /* USE_OPENSSL */
struct curltime expiretime; /* set this with Curl_expire() only */
struct Curl_tree timenode; /* for the splay stuff */
@@ -1493,6 +1442,7 @@ enum dupstring {
#endif
STRING_ECH_CONFIG, /* CURLOPT_ECH_CONFIG */
STRING_ECH_PUBLIC, /* CURLOPT_ECH_PUBLIC */
+ STRING_SSL_SIGNATURE_ALGORITHMS, /* CURLOPT_SSL_SIGNATURE_ALGORITHMS */
/* -- end of null-terminated strings -- */
@@ -1519,10 +1469,6 @@ enum dupblob {
BLOB_LAST
};
-/* callback that gets called when this easy handle is completed within a multi
- handle. Only used for internally created transfers, like for example
- DoH. */
-typedef int (*multidone_func)(struct Curl_easy *easy, CURLcode result);
struct UserDefined {
FILE *err; /* the stderr user data goes here */
@@ -1678,10 +1624,6 @@ struct UserDefined {
before resolver start */
void *resolver_start_client; /* pointer to pass to resolver start callback */
long upkeep_interval_ms; /* Time between calls for connection upkeep. */
- multidone_func fmultidone;
-#ifndef CURL_DISABLE_DOH
- curl_off_t dohfor_mid; /* this is a DoH request for that transfer */
-#endif
CURLU *uh; /* URL handle for the current parsed URL */
#ifndef CURL_DISABLE_HTTP
void *trailer_data; /* pointer to pass to trailer data callback */
@@ -1776,7 +1718,6 @@ struct UserDefined {
us */
BIT(wildcard_enabled); /* enable wildcard matching */
#endif
- BIT(hide_progress); /* do not use the progress meter */
BIT(http_fail_on_error); /* fail on HTTP error codes >= 400 */
BIT(http_keep_sending_on_error); /* for HTTP status codes >= 300 */
BIT(http_transfer_encoding); /* request compressed HTTP transfer-encoding */
@@ -1831,6 +1772,7 @@ struct UserDefined {
BIT(http09_allowed); /* allow HTTP/0.9 responses */
#ifndef CURL_DISABLE_WEBSOCKETS
BIT(ws_raw_mode);
+ BIT(ws_no_auto_pong);
#endif
};
@@ -1840,14 +1782,11 @@ struct UserDefined {
#define IS_MIME_POST(a) FALSE
#endif
-struct Names {
- struct Curl_hash *hostcache;
- enum {
- HCACHE_NONE, /* not pointing to anything */
- HCACHE_MULTI, /* points to a shared one in the multi handle */
- HCACHE_SHARED /* points to a shared one in a shared object */
- } hostcachetype;
-};
+/* callback that gets called when a sub easy (data->master_mid set) is
+ DONE. Called on the master easy. */
+typedef void multi_sub_xfer_done_cb(struct Curl_easy *master_easy,
+ struct Curl_easy *sub_easy,
+ CURLcode result);
/*
* The 'connectdata' struct MUST have all the connection oriented stuff as we
@@ -1873,18 +1812,17 @@ struct Curl_easy {
/* once an easy handle is added to a multi, either explicitly by the
* libcurl application or implicitly during `curl_easy_perform()`,
* a unique identifier inside this one multi instance. */
- curl_off_t mid;
+ unsigned int mid;
+ unsigned int master_mid; /* if set, this transfer belongs to a master */
+ multi_sub_xfer_done_cb *sub_xfer_done;
struct connectdata *conn;
- struct Curl_llist_node multi_queue; /* for multihandle list management */
- struct Curl_llist_node conn_queue; /* list per connectdata */
CURLMstate mstate; /* the handle's state */
CURLcode result; /* previous result */
struct Curl_message msg; /* A single posted message. */
- struct Names dns;
struct Curl_multi *multi; /* if non-NULL, points to the multi handle
struct to which this "belongs" when used by
the multi interface */
@@ -1892,6 +1830,13 @@ struct Curl_easy {
struct to which this "belongs" when used
by the easy interface */
struct Curl_share *share; /* Share, handles global variable mutexing */
+
+ /* `meta_hash` is a general key-value store for implementations
+ * with the lifetime of the easy handle.
+ * Elements need to be added with their own destructor to be invoked when
+ * the easy handle is cleaned up (see Curl_hash_add2()).*/
+ struct Curl_hash meta_hash;
+
#ifdef USE_LIBPSL
struct PslCache *psl; /* The associated PSL cache. */
#endif
diff --git a/libs/libcurl/src/vauth/cleartext.c b/libs/libcurl/src/vauth/cleartext.c
index 93d6340bf2..5833316aaa 100644
--- a/libs/libcurl/src/vauth/cleartext.c
+++ b/libs/libcurl/src/vauth/cleartext.c
@@ -25,23 +25,23 @@
*
***************************************************************************/
-#include "curl_setup.h"
+#include "../curl_setup.h"
#if !defined(CURL_DISABLE_IMAP) || !defined(CURL_DISABLE_SMTP) || \
!defined(CURL_DISABLE_POP3) || \
(!defined(CURL_DISABLE_LDAP) && defined(USE_OPENLDAP))
#include <curl/curl.h>
-#include "urldata.h"
+#include "../urldata.h"
-#include "vauth/vauth.h"
-#include "warnless.h"
-#include "sendf.h"
-#include "curl_printf.h"
+#include "vauth.h"
+#include "../curlx/warnless.h"
+#include "../sendf.h"
+#include "../curl_printf.h"
/* The last #include files should be: */
-#include "curl_memory.h"
-#include "memdebug.h"
+#include "../curl_memory.h"
+#include "../memdebug.h"
/*
* Curl_auth_create_plain_message()
diff --git a/libs/libcurl/src/vauth/cram.c b/libs/libcurl/src/vauth/cram.c
index 5457135d42..4dea9c48bc 100644
--- a/libs/libcurl/src/vauth/cram.c
+++ b/libs/libcurl/src/vauth/cram.c
@@ -24,22 +24,22 @@
*
***************************************************************************/
-#include "curl_setup.h"
+#include "../curl_setup.h"
#ifndef CURL_DISABLE_DIGEST_AUTH
#include <curl/curl.h>
-#include "urldata.h"
+#include "../urldata.h"
-#include "vauth/vauth.h"
-#include "curl_hmac.h"
-#include "curl_md5.h"
-#include "warnless.h"
-#include "curl_printf.h"
+#include "vauth.h"
+#include "../curl_hmac.h"
+#include "../curl_md5.h"
+#include "../curlx/warnless.h"
+#include "../curl_printf.h"
/* The last #include files should be: */
-#include "curl_memory.h"
-#include "memdebug.h"
+#include "../curl_memory.h"
+#include "../memdebug.h"
/*
diff --git a/libs/libcurl/src/vauth/digest.c b/libs/libcurl/src/vauth/digest.c
index 98d0c04dca..d7d6562185 100644
--- a/libs/libcurl/src/vauth/digest.c
+++ b/libs/libcurl/src/vauth/digest.c
@@ -25,30 +25,30 @@
*
***************************************************************************/
-#include "curl_setup.h"
+#include "../curl_setup.h"
#ifndef CURL_DISABLE_DIGEST_AUTH
#include <curl/curl.h>
-#include "vauth/vauth.h"
-#include "vauth/digest.h"
-#include "urldata.h"
-#include "curl_base64.h"
-#include "curl_hmac.h"
-#include "curl_md5.h"
-#include "curl_sha256.h"
-#include "curl_sha512_256.h"
-#include "vtls/vtls.h"
-#include "warnless.h"
-#include "strparse.h"
-#include "strcase.h"
-#include "curl_printf.h"
-#include "rand.h"
+#include "vauth.h"
+#include "digest.h"
+#include "../urldata.h"
+#include "../curlx/base64.h"
+#include "../curl_hmac.h"
+#include "../curl_md5.h"
+#include "../curl_sha256.h"
+#include "../curl_sha512_256.h"
+#include "../vtls/vtls.h"
+#include "../curlx/warnless.h"
+#include "../curlx/strparse.h"
+#include "../strcase.h"
+#include "../curl_printf.h"
+#include "../rand.h"
/* The last #include files should be: */
-#include "curl_memory.h"
-#include "memdebug.h"
+#include "../curl_memory.h"
+#include "../memdebug.h"
#ifndef USE_WINDOWS_SSPI
#define SESSION_ALGO 1 /* for algos with this bit set */
@@ -223,14 +223,14 @@ static CURLcode auth_digest_get_qop_values(const char *options, int *value)
/* Initialise the output */
*value = 0;
- while(!Curl_str_until(&options, &out, 32, ',')) {
- if(Curl_str_casecompare(&out, DIGEST_QOP_VALUE_STRING_AUTH))
+ while(!curlx_str_until(&options, &out, 32, ',')) {
+ if(curlx_str_casecompare(&out, DIGEST_QOP_VALUE_STRING_AUTH))
*value |= DIGEST_QOP_VALUE_AUTH;
- else if(Curl_str_casecompare(&out, DIGEST_QOP_VALUE_STRING_AUTH_INT))
+ else if(curlx_str_casecompare(&out, DIGEST_QOP_VALUE_STRING_AUTH_INT))
*value |= DIGEST_QOP_VALUE_AUTH_INT;
- else if(Curl_str_casecompare(&out, DIGEST_QOP_VALUE_STRING_AUTH_CONF))
+ else if(curlx_str_casecompare(&out, DIGEST_QOP_VALUE_STRING_AUTH_CONF))
*value |= DIGEST_QOP_VALUE_AUTH_CONF;
- if(Curl_str_single(&options, ','))
+ if(curlx_str_single(&options, ','))
break;
}
@@ -542,13 +542,13 @@ CURLcode Curl_auth_decode_digest_http_message(const char *chlg,
/* Pass leading spaces */
while(*token && ISBLANK(*token))
token++;
- while(!Curl_str_until(&token, &out, 32, ',')) {
- if(Curl_str_casecompare(&out, DIGEST_QOP_VALUE_STRING_AUTH))
+ while(!curlx_str_until(&token, &out, 32, ',')) {
+ if(curlx_str_casecompare(&out, DIGEST_QOP_VALUE_STRING_AUTH))
foundAuth = TRUE;
- else if(Curl_str_casecompare(&out,
+ else if(curlx_str_casecompare(&out,
DIGEST_QOP_VALUE_STRING_AUTH_INT))
foundAuthInt = TRUE;
- if(Curl_str_single(&token, ','))
+ if(curlx_str_single(&token, ','))
break;
while(*token && ISBLANK(*token))
token++;
@@ -699,8 +699,8 @@ static CURLcode auth_create_digest_http_message(
if(result)
return result;
- result = Curl_base64_encode(cnoncebuf, sizeof(cnoncebuf),
- &cnonce, &cnonce_sz);
+ result = curlx_base64_encode(cnoncebuf, sizeof(cnoncebuf),
+ &cnonce, &cnonce_sz);
if(result)
return result;
diff --git a/libs/libcurl/src/vauth/digest_sspi.c b/libs/libcurl/src/vauth/digest_sspi.c
index 3210e8ad0e..9bf4c796c6 100644
--- a/libs/libcurl/src/vauth/digest_sspi.c
+++ b/libs/libcurl/src/vauth/digest_sspi.c
@@ -25,25 +25,25 @@
*
***************************************************************************/
-#include "curl_setup.h"
+#include "../curl_setup.h"
#if defined(USE_WINDOWS_SSPI) && !defined(CURL_DISABLE_DIGEST_AUTH)
#include <curl/curl.h>
-#include "vauth/vauth.h"
-#include "vauth/digest.h"
-#include "urldata.h"
-#include "warnless.h"
-#include "curl_multibyte.h"
-#include "sendf.h"
-#include "strdup.h"
-#include "strcase.h"
-#include "strerror.h"
+#include "vauth.h"
+#include "digest.h"
+#include "../urldata.h"
+#include "../curlx/warnless.h"
+#include "../curlx/multibyte.h"
+#include "../sendf.h"
+#include "../strdup.h"
+#include "../strcase.h"
+#include "../strerror.h"
/* The last #include files should be: */
-#include "curl_memory.h"
-#include "memdebug.h"
+#include "../curl_memory.h"
+#include "../memdebug.h"
/*
* Curl_auth_is_digest_supported()
diff --git a/libs/libcurl/src/vauth/gsasl.c b/libs/libcurl/src/vauth/gsasl.c
index d88f9ea77a..8897c84f92 100644
--- a/libs/libcurl/src/vauth/gsasl.c
+++ b/libs/libcurl/src/vauth/gsasl.c
@@ -24,22 +24,22 @@
*
***************************************************************************/
-#include "curl_setup.h"
+#include "../curl_setup.h"
#ifdef USE_GSASL
#include <curl/curl.h>
-#include "vauth/vauth.h"
-#include "urldata.h"
-#include "sendf.h"
+#include "vauth.h"
+#include "../urldata.h"
+#include "../sendf.h"
#include <gsasl.h>
/* The last 3 #include files should be in this order */
-#include "curl_printf.h"
-#include "curl_memory.h"
-#include "memdebug.h"
+#include "../curl_printf.h"
+#include "../curl_memory.h"
+#include "../memdebug.h"
bool Curl_auth_gsasl_is_supported(struct Curl_easy *data,
const char *mech,
diff --git a/libs/libcurl/src/vauth/krb5_gssapi.c b/libs/libcurl/src/vauth/krb5_gssapi.c
index fde838b3ce..96d717fbaa 100644
--- a/libs/libcurl/src/vauth/krb5_gssapi.c
+++ b/libs/libcurl/src/vauth/krb5_gssapi.c
@@ -25,22 +25,22 @@
*
***************************************************************************/
-#include "curl_setup.h"
+#include "../curl_setup.h"
#if defined(HAVE_GSSAPI) && defined(USE_KERBEROS5)
#include <curl/curl.h>
-#include "vauth/vauth.h"
-#include "curl_sasl.h"
-#include "urldata.h"
-#include "curl_gssapi.h"
-#include "sendf.h"
-#include "curl_printf.h"
+#include "vauth.h"
+#include "../curl_sasl.h"
+#include "../urldata.h"
+#include "../curl_gssapi.h"
+#include "../sendf.h"
+#include "../curl_printf.h"
/* The last #include files should be: */
-#include "curl_memory.h"
-#include "memdebug.h"
+#include "../curl_memory.h"
+#include "../memdebug.h"
#if defined(__GNUC__) && defined(__APPLE__)
#pragma GCC diagnostic push
diff --git a/libs/libcurl/src/vauth/krb5_sspi.c b/libs/libcurl/src/vauth/krb5_sspi.c
index eadeb3d046..6cac791bdc 100644
--- a/libs/libcurl/src/vauth/krb5_sspi.c
+++ b/libs/libcurl/src/vauth/krb5_sspi.c
@@ -24,21 +24,21 @@
*
***************************************************************************/
-#include "curl_setup.h"
+#include "../curl_setup.h"
#if defined(USE_WINDOWS_SSPI) && defined(USE_KERBEROS5)
#include <curl/curl.h>
-#include "vauth/vauth.h"
-#include "urldata.h"
-#include "warnless.h"
-#include "curl_multibyte.h"
-#include "sendf.h"
+#include "vauth.h"
+#include "../urldata.h"
+#include "../curlx/warnless.h"
+#include "../curlx/multibyte.h"
+#include "../sendf.h"
/* The last #include files should be: */
-#include "curl_memory.h"
-#include "memdebug.h"
+#include "../curl_memory.h"
+#include "../memdebug.h"
/*
* Curl_auth_is_gssapi_supported()
diff --git a/libs/libcurl/src/vauth/ntlm.c b/libs/libcurl/src/vauth/ntlm.c
index e8230e6b83..1d474689d3 100644
--- a/libs/libcurl/src/vauth/ntlm.c
+++ b/libs/libcurl/src/vauth/ntlm.c
@@ -22,7 +22,7 @@
*
***************************************************************************/
-#include "curl_setup.h"
+#include "../curl_setup.h"
#if defined(USE_NTLM) && !defined(USE_WINDOWS_SSPI)
@@ -35,24 +35,24 @@
#define DEBUG_ME 0
-#include "urldata.h"
-#include "sendf.h"
-#include "curl_ntlm_core.h"
-#include "curl_gethostname.h"
-#include "curl_multibyte.h"
-#include "curl_md5.h"
-#include "warnless.h"
-#include "rand.h"
-#include "vtls/vtls.h"
-#include "strdup.h"
-
-#include "vauth/vauth.h"
-#include "curl_endian.h"
-#include "curl_printf.h"
+#include "../urldata.h"
+#include "../sendf.h"
+#include "../curl_ntlm_core.h"
+#include "../curl_gethostname.h"
+#include "../curlx/multibyte.h"
+#include "../curl_md5.h"
+#include "../curlx/warnless.h"
+#include "../rand.h"
+#include "../vtls/vtls.h"
+#include "../strdup.h"
+
+#include "vauth.h"
+#include "../curl_endian.h"
+#include "../curl_printf.h"
/* The last #include files should be: */
-#include "curl_memory.h"
-#include "memdebug.h"
+#include "../curl_memory.h"
+#include "../memdebug.h"
/* NTLM buffer fixed size, large enough for long user + host + domain */
diff --git a/libs/libcurl/src/vauth/ntlm_sspi.c b/libs/libcurl/src/vauth/ntlm_sspi.c
index 3d8d1e010e..7922177158 100644
--- a/libs/libcurl/src/vauth/ntlm_sspi.c
+++ b/libs/libcurl/src/vauth/ntlm_sspi.c
@@ -22,23 +22,23 @@
*
***************************************************************************/
-#include "curl_setup.h"
+#include "../curl_setup.h"
#if defined(USE_WINDOWS_SSPI) && defined(USE_NTLM)
#include <curl/curl.h>
-#include "vauth/vauth.h"
-#include "urldata.h"
-#include "curl_ntlm_core.h"
-#include "warnless.h"
-#include "curl_multibyte.h"
-#include "sendf.h"
-#include "strdup.h"
+#include "vauth.h"
+#include "../urldata.h"
+#include "../curl_ntlm_core.h"
+#include "../curlx/warnless.h"
+#include "../curlx/multibyte.h"
+#include "../sendf.h"
+#include "../strdup.h"
/* The last #include files should be: */
-#include "curl_memory.h"
-#include "memdebug.h"
+#include "../curl_memory.h"
+#include "../memdebug.h"
/*
* Curl_auth_is_ntlm_supported()
diff --git a/libs/libcurl/src/vauth/oauth2.c b/libs/libcurl/src/vauth/oauth2.c
index 00bb9867ec..d8fb109386 100644
--- a/libs/libcurl/src/vauth/oauth2.c
+++ b/libs/libcurl/src/vauth/oauth2.c
@@ -24,22 +24,22 @@
*
***************************************************************************/
-#include "curl_setup.h"
+#include "../curl_setup.h"
#if !defined(CURL_DISABLE_IMAP) || !defined(CURL_DISABLE_SMTP) || \
!defined(CURL_DISABLE_POP3) || \
(!defined(CURL_DISABLE_LDAP) && defined(USE_OPENLDAP))
#include <curl/curl.h>
-#include "urldata.h"
+#include "../urldata.h"
-#include "vauth/vauth.h"
-#include "warnless.h"
-#include "curl_printf.h"
+#include "vauth.h"
+#include "../curlx/warnless.h"
+#include "../curl_printf.h"
/* The last #include files should be: */
-#include "curl_memory.h"
-#include "memdebug.h"
+#include "../curl_memory.h"
+#include "../memdebug.h"
/*
* Curl_auth_create_oauth_bearer_message()
diff --git a/libs/libcurl/src/vauth/spnego_gssapi.c b/libs/libcurl/src/vauth/spnego_gssapi.c
index 7b7ec3ccfc..05169a81f8 100644
--- a/libs/libcurl/src/vauth/spnego_gssapi.c
+++ b/libs/libcurl/src/vauth/spnego_gssapi.c
@@ -24,23 +24,23 @@
*
***************************************************************************/
-#include "curl_setup.h"
+#include "../curl_setup.h"
#if defined(HAVE_GSSAPI) && defined(USE_SPNEGO)
#include <curl/curl.h>
-#include "vauth/vauth.h"
-#include "urldata.h"
-#include "curl_base64.h"
-#include "curl_gssapi.h"
-#include "warnless.h"
-#include "curl_multibyte.h"
-#include "sendf.h"
+#include "vauth.h"
+#include "../urldata.h"
+#include "../curlx/base64.h"
+#include "../curl_gssapi.h"
+#include "../curlx/warnless.h"
+#include "../curlx/multibyte.h"
+#include "../sendf.h"
/* The last #include files should be: */
-#include "curl_memory.h"
-#include "memdebug.h"
+#include "../curl_memory.h"
+#include "../memdebug.h"
#if defined(__GNUC__) && defined(__APPLE__)
#pragma GCC diagnostic push
@@ -139,7 +139,7 @@ CURLcode Curl_auth_decode_spnego_message(struct Curl_easy *data,
if(chlg64 && *chlg64) {
/* Decode the base-64 encoded challenge message */
if(*chlg64 != '=') {
- result = Curl_base64_decode(chlg64, &chlg, &chlglen);
+ result = curlx_base64_decode(chlg64, &chlg, &chlglen);
if(result)
return result;
}
@@ -156,10 +156,10 @@ CURLcode Curl_auth_decode_spnego_message(struct Curl_easy *data,
}
/* Set channel binding data if available */
- if(Curl_dyn_len(&nego->channel_binding_data)) {
+ if(curlx_dyn_len(&nego->channel_binding_data)) {
memset(&chan, 0, sizeof(struct gss_channel_bindings_struct));
- chan.application_data.length = Curl_dyn_len(&nego->channel_binding_data);
- chan.application_data.value = Curl_dyn_ptr(&nego->channel_binding_data);
+ chan.application_data.length = curlx_dyn_len(&nego->channel_binding_data);
+ chan.application_data.value = curlx_dyn_ptr(&nego->channel_binding_data);
chan_bindings = &chan;
}
@@ -228,9 +228,9 @@ CURLcode Curl_auth_create_spnego_message(struct negotiatedata *nego,
OM_uint32 minor_status;
/* Base64 encode the already generated response */
- result = Curl_base64_encode(nego->output_token.value,
- nego->output_token.length,
- outptr, outlen);
+ result = curlx_base64_encode(nego->output_token.value,
+ nego->output_token.length,
+ outptr, outlen);
if(result) {
gss_release_buffer(&minor_status, &nego->output_token);
diff --git a/libs/libcurl/src/vauth/spnego_sspi.c b/libs/libcurl/src/vauth/spnego_sspi.c
index c42c7f8f10..dead8c4f36 100644
--- a/libs/libcurl/src/vauth/spnego_sspi.c
+++ b/libs/libcurl/src/vauth/spnego_sspi.c
@@ -24,23 +24,23 @@
*
***************************************************************************/
-#include "curl_setup.h"
+#include "../curl_setup.h"
#if defined(USE_WINDOWS_SSPI) && defined(USE_SPNEGO)
#include <curl/curl.h>
-#include "vauth/vauth.h"
-#include "urldata.h"
-#include "curl_base64.h"
-#include "warnless.h"
-#include "curl_multibyte.h"
-#include "sendf.h"
-#include "strerror.h"
+#include "vauth.h"
+#include "../urldata.h"
+#include "../curlx/base64.h"
+#include "../curlx/warnless.h"
+#include "../curlx/multibyte.h"
+#include "../sendf.h"
+#include "../strerror.h"
/* The last #include files should be: */
-#include "curl_memory.h"
-#include "memdebug.h"
+#include "../curl_memory.h"
+#include "../memdebug.h"
/*
* Curl_auth_is_spnego_supported()
@@ -186,7 +186,7 @@ CURLcode Curl_auth_decode_spnego_message(struct Curl_easy *data,
if(chlg64 && *chlg64) {
/* Decode the base-64 encoded challenge message */
if(*chlg64 != '=') {
- result = Curl_base64_decode(chlg64, &chlg, &chlglen);
+ result = curlx_base64_decode(chlg64, &chlg, &chlglen);
if(result)
return result;
}
@@ -308,9 +308,9 @@ CURLcode Curl_auth_create_spnego_message(struct negotiatedata *nego,
char **outptr, size_t *outlen)
{
/* Base64 encode the already generated response */
- CURLcode result = Curl_base64_encode((const char *) nego->output_token,
- nego->output_token_length, outptr,
- outlen);
+ CURLcode result = curlx_base64_encode((const char *) nego->output_token,
+ nego->output_token_length, outptr,
+ outlen);
if(!result && (!*outptr || !*outlen)) {
free(*outptr);
result = CURLE_REMOTE_ACCESS_DENIED;
diff --git a/libs/libcurl/src/vauth/vauth.c b/libs/libcurl/src/vauth/vauth.c
index d61669c2b8..b98197bbdb 100644
--- a/libs/libcurl/src/vauth/vauth.c
+++ b/libs/libcurl/src/vauth/vauth.c
@@ -22,19 +22,19 @@
*
***************************************************************************/
-#include "curl_setup.h"
+#include "../curl_setup.h"
#include <curl/curl.h>
#include "vauth.h"
-#include "urldata.h"
-#include "strcase.h"
-#include "curl_multibyte.h"
-#include "curl_printf.h"
+#include "../urldata.h"
+#include "../strcase.h"
+#include "../curlx/multibyte.h"
+#include "../curl_printf.h"
/* The last #include files should be: */
-#include "curl_memory.h"
-#include "memdebug.h"
+#include "../curl_memory.h"
+#include "../memdebug.h"
/*
* Curl_auth_build_spn()
diff --git a/libs/libcurl/src/vauth/vauth.h b/libs/libcurl/src/vauth/vauth.h
index fb43bc5e02..933bb4e737 100644
--- a/libs/libcurl/src/vauth/vauth.h
+++ b/libs/libcurl/src/vauth/vauth.h
@@ -26,7 +26,7 @@
#include <curl/curl.h>
-#include "bufref.h"
+#include "../bufref.h"
struct Curl_easy;
@@ -167,6 +167,8 @@ CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data,
/* This is used to clean up the NTLM specific data */
void Curl_auth_cleanup_ntlm(struct ntlmdata *ntlm);
+#else
+#define Curl_auth_is_ntlm_supported() FALSE
#endif /* USE_NTLM */
/* This is used to generate a base64 encoded OAuth 2.0 message */
@@ -207,6 +209,8 @@ CURLcode Curl_auth_create_gssapi_security_message(struct Curl_easy *data,
/* This is used to clean up the GSSAPI specific data */
void Curl_auth_cleanup_gssapi(struct kerberos5data *krb5);
+#else
+#define Curl_auth_is_gssapi_supported() FALSE
#endif /* USE_KERBEROS5 */
#if defined(USE_SPNEGO)
diff --git a/libs/libcurl/src/vquic/curl_msh3.c b/libs/libcurl/src/vquic/curl_msh3.c
index c3f1375016..8f9590391f 100644
--- a/libs/libcurl/src/vquic/curl_msh3.c
+++ b/libs/libcurl/src/vquic/curl_msh3.c
@@ -22,31 +22,32 @@
*
***************************************************************************/
-#include "curl_setup.h"
+#include "../curl_setup.h"
#ifdef USE_MSH3
-#include "urldata.h"
-#include "hash.h"
-#include "hash_offt.h"
-#include "timeval.h"
-#include "multiif.h"
-#include "sendf.h"
-#include "curl_trc.h"
-#include "cfilters.h"
-#include "cf-socket.h"
-#include "connect.h"
-#include "progress.h"
-#include "http1.h"
+#include "../urldata.h"
+#include "../hash.h"
+#include "../uint-hash.h"
+#include "../curlx/timeval.h"
+#include "../multiif.h"
+#include "../sendf.h"
+#include "../curl_trc.h"
+#include "../cfilters.h"
+#include "../cf-socket.h"
+#include "../connect.h"
+#include "../progress.h"
+#include "../http1.h"
#include "curl_msh3.h"
-#include "socketpair.h"
-#include "vtls/vtls.h"
-#include "vquic/vquic.h"
+#include "../socketpair.h"
+#include "../vtls/vtls.h"
+#include "vquic.h"
+#include "vquic_int.h"
/* The last 3 #include files should be in this order */
-#include "curl_printf.h"
-#include "curl_memory.h"
-#include "memdebug.h"
+#include "../curl_printf.h"
+#include "../curl_memory.h"
+#include "../memdebug.h"
#ifdef CURL_DISABLE_SOCKETPAIR
#error "MSH3 cannot be build with CURL_DISABLE_SOCKETPAIR set"
@@ -120,18 +121,18 @@ struct cf_msh3_ctx {
struct cf_call_data call_data;
struct curltime connect_started; /* time the current attempt started */
struct curltime handshake_at; /* time connect handshake finished */
- struct Curl_hash_offt streams; /* hash `data->mid` to `stream_ctx` */
+ struct uint_hash streams; /* hash `data->mid` to `stream_ctx` */
/* Flags written by msh3/msquic thread */
- bool handshake_complete;
- bool handshake_succeeded;
- bool connected;
+ BIT(handshake_complete);
+ BIT(handshake_succeeded);
+ BIT(connected);
BIT(initialized);
/* Flags written by curl thread */
BIT(verbose);
BIT(active);
};
-static void h3_stream_hash_free(curl_off_t id, void *stream);
+static void h3_stream_hash_free(unsigned int id, void *stream);
static CURLcode cf_msh3_ctx_init(struct cf_msh3_ctx *ctx,
const struct Curl_addrinfo *ai)
@@ -139,7 +140,7 @@ static CURLcode cf_msh3_ctx_init(struct cf_msh3_ctx *ctx,
CURLcode result;
DEBUGASSERT(!ctx->initialized);
- Curl_hash_offt_init(&ctx->streams, 63, h3_stream_hash_free);
+ Curl_uint_hash_init(&ctx->streams, 63, h3_stream_hash_free);
result = Curl_sock_assign_addr(&ctx->addr, ai, TRNSPRT_QUIC);
if(result)
@@ -155,7 +156,7 @@ static CURLcode cf_msh3_ctx_init(struct cf_msh3_ctx *ctx,
static void cf_msh3_ctx_free(struct cf_msh3_ctx *ctx)
{
if(ctx && ctx->initialized) {
- Curl_hash_offt_destroy(&ctx->streams);
+ Curl_uint_hash_destroy(&ctx->streams);
}
free(ctx);
}
@@ -170,7 +171,7 @@ static struct cf_msh3_ctx *h3_get_msh3_ctx(struct Curl_easy *data);
/**
* All about the H3 internals of a stream
*/
-struct stream_ctx {
+struct h3_stream_ctx {
struct MSH3_REQUEST *req;
struct bufq recvbuf; /* h3 response */
#ifdef _WIN32
@@ -181,34 +182,31 @@ struct stream_ctx {
uint64_t error3; /* HTTP/3 stream error code */
int status_code; /* HTTP status code */
CURLcode recv_error;
- bool closed;
- bool reset;
- bool upload_done;
- bool firstheader; /* FALSE until headers arrive */
- bool recv_header_complete;
+ BIT(closed);
+ BIT(reset);
+ BIT(upload_done);
+ BIT(firstheader); /* FALSE until headers arrive */
+ BIT(recv_header_complete);
};
-#define H3_STREAM_CTX(ctx,data) ((struct stream_ctx *)((data && ctx)? \
- Curl_hash_offt_get(&(ctx)->streams, (data)->mid) : NULL))
-
-static void h3_stream_ctx_free(struct stream_ctx *stream)
+static void h3_stream_ctx_free(struct h3_stream_ctx *stream)
{
Curl_bufq_free(&stream->recvbuf);
free(stream);
}
-static void h3_stream_hash_free(curl_off_t id, void *stream)
+static void h3_stream_hash_free(unsigned int id, void *stream)
{
(void)id;
DEBUGASSERT(stream);
- h3_stream_ctx_free((struct stream_ctx *)stream);
+ h3_stream_ctx_free((struct h3_stream_ctx *)stream);
}
static CURLcode h3_data_setup(struct Curl_cfilter *cf,
struct Curl_easy *data)
{
struct cf_msh3_ctx *ctx = cf->ctx;
- struct stream_ctx *stream = H3_STREAM_CTX(ctx, data);
+ struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data);
if(stream)
return CURLE_OK;
@@ -223,7 +221,7 @@ static CURLcode h3_data_setup(struct Curl_cfilter *cf,
H3_STREAM_RECV_CHUNKS, BUFQ_OPT_SOFT_LIMIT);
CURL_TRC_CF(data, cf, "data setup");
- if(!Curl_hash_offt_set(&ctx->streams, data->mid, stream)) {
+ if(!Curl_uint_hash_set(&ctx->streams, data->mid, stream)) {
h3_stream_ctx_free(stream);
return CURLE_OUT_OF_MEMORY;
}
@@ -234,17 +232,17 @@ static CURLcode h3_data_setup(struct Curl_cfilter *cf,
static void h3_data_done(struct Curl_cfilter *cf, struct Curl_easy *data)
{
struct cf_msh3_ctx *ctx = cf->ctx;
- struct stream_ctx *stream = H3_STREAM_CTX(ctx, data);
+ struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data);
(void)cf;
if(stream) {
CURL_TRC_CF(data, cf, "easy handle is done");
- Curl_hash_offt_remove(&ctx->streams, data->mid);
+ Curl_uint_hash_remove(&ctx->streams, data->mid);
}
}
static void drain_stream_from_other_thread(struct Curl_easy *data,
- struct stream_ctx *stream)
+ struct h3_stream_ctx *stream)
{
unsigned char bits;
@@ -262,7 +260,7 @@ static void h3_drain_stream(struct Curl_cfilter *cf,
struct Curl_easy *data)
{
struct cf_msh3_ctx *ctx = cf->ctx;
- struct stream_ctx *stream = H3_STREAM_CTX(ctx, data);
+ struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data);
unsigned char bits;
(void)cf;
@@ -361,7 +359,7 @@ static CURLcode write_resp_raw(struct Curl_easy *data,
const void *mem, size_t memlen)
{
struct cf_msh3_ctx *ctx = h3_get_msh3_ctx(data);
- struct stream_ctx *stream = H3_STREAM_CTX(ctx, data);
+ struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data);
CURLcode result = CURLE_OK;
ssize_t nwritten;
@@ -388,7 +386,7 @@ static void MSH3_CALL msh3_header_received(MSH3_REQUEST *Request,
{
struct Curl_easy *data = userp;
struct cf_msh3_ctx *ctx = h3_get_msh3_ctx(data);
- struct stream_ctx *stream = H3_STREAM_CTX(ctx, data);
+ struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data);
CURLcode result;
(void)Request;
@@ -439,7 +437,7 @@ static bool MSH3_CALL msh3_data_received(MSH3_REQUEST *Request,
{
struct Curl_easy *data = IfContext;
struct cf_msh3_ctx *ctx = h3_get_msh3_ctx(data);
- struct stream_ctx *stream = H3_STREAM_CTX(ctx, data);
+ struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data);
CURLcode result;
bool rv = FALSE;
@@ -479,7 +477,7 @@ static void MSH3_CALL msh3_complete(MSH3_REQUEST *Request, void *IfContext,
{
struct Curl_easy *data = IfContext;
struct cf_msh3_ctx *ctx = h3_get_msh3_ctx(data);
- struct stream_ctx *stream = H3_STREAM_CTX(ctx, data);
+ struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data);
(void)Request;
if(!stream)
@@ -499,7 +497,7 @@ static void MSH3_CALL msh3_shutdown_complete(MSH3_REQUEST *Request,
{
struct Curl_easy *data = IfContext;
struct cf_msh3_ctx *ctx = h3_get_msh3_ctx(data);
- struct stream_ctx *stream = H3_STREAM_CTX(ctx, data);
+ struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data);
if(!stream)
return;
@@ -512,7 +510,7 @@ static void MSH3_CALL msh3_data_sent(MSH3_REQUEST *Request,
{
struct Curl_easy *data = IfContext;
struct cf_msh3_ctx *ctx = h3_get_msh3_ctx(data);
- struct stream_ctx *stream = H3_STREAM_CTX(ctx, data);
+ struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data);
if(!stream)
return;
(void)Request;
@@ -525,7 +523,7 @@ static ssize_t recv_closed_stream(struct Curl_cfilter *cf,
CURLcode *err)
{
struct cf_msh3_ctx *ctx = cf->ctx;
- struct stream_ctx *stream = H3_STREAM_CTX(ctx, data);
+ struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data);
ssize_t nread = -1;
if(!stream) {
@@ -559,7 +557,7 @@ out:
static void set_quic_expire(struct Curl_cfilter *cf, struct Curl_easy *data)
{
struct cf_msh3_ctx *ctx = cf->ctx;
- struct stream_ctx *stream = H3_STREAM_CTX(ctx, data);
+ struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data);
/* we have no indication from msh3 when it would be a good time
* to juggle the connection again. So, we compromise by calling
@@ -577,7 +575,7 @@ static ssize_t cf_msh3_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
char *buf, size_t len, CURLcode *err)
{
struct cf_msh3_ctx *ctx = cf->ctx;
- struct stream_ctx *stream = H3_STREAM_CTX(ctx, data);
+ struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data);
ssize_t nread = -1;
struct cf_call_data save;
@@ -629,7 +627,7 @@ static ssize_t cf_msh3_send(struct Curl_cfilter *cf, struct Curl_easy *data,
CURLcode *err)
{
struct cf_msh3_ctx *ctx = cf->ctx;
- struct stream_ctx *stream = H3_STREAM_CTX(ctx, data);
+ struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data);
struct h1_req_parser h1;
struct dynhds h2_headers;
MSH3_HEADER *nva = NULL;
@@ -725,7 +723,7 @@ static void cf_msh3_adjust_pollset(struct Curl_cfilter *cf,
struct easy_pollset *ps)
{
struct cf_msh3_ctx *ctx = cf->ctx;
- struct stream_ctx *stream = H3_STREAM_CTX(ctx, data);
+ struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data);
struct cf_call_data save;
CF_DATA_SAVE(save, cf, data);
@@ -745,7 +743,7 @@ static bool cf_msh3_data_pending(struct Curl_cfilter *cf,
const struct Curl_easy *data)
{
struct cf_msh3_ctx *ctx = cf->ctx;
- struct stream_ctx *stream = H3_STREAM_CTX(ctx, data);
+ struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data);
struct cf_call_data save;
bool pending = FALSE;
@@ -783,7 +781,7 @@ static CURLcode cf_msh3_data_event(struct Curl_cfilter *cf,
int event, int arg1, void *arg2)
{
struct cf_msh3_ctx *ctx = cf->ctx;
- struct stream_ctx *stream = H3_STREAM_CTX(ctx, data);
+ struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data);
struct cf_call_data save;
CURLcode result = CURLE_OK;
@@ -903,14 +901,14 @@ static CURLcode cf_msh3_connect(struct Curl_cfilter *cf,
*done = FALSE;
if(!ctx->qconn) {
- ctx->connect_started = Curl_now();
+ ctx->connect_started = curlx_now();
result = cf_connect_start(cf, data);
if(result)
goto out;
}
if(ctx->handshake_complete) {
- ctx->handshake_at = Curl_now();
+ ctx->handshake_at = curlx_now();
if(ctx->handshake_succeeded) {
CURL_TRC_CF(data, cf, "handshake succeeded");
cf->conn->bits.multiplex = TRUE; /* at least potentially multiplexed */
diff --git a/libs/libcurl/src/vquic/curl_msh3.h b/libs/libcurl/src/vquic/curl_msh3.h
index e3f40c2ab9..259011499b 100644
--- a/libs/libcurl/src/vquic/curl_msh3.h
+++ b/libs/libcurl/src/vquic/curl_msh3.h
@@ -24,7 +24,7 @@
*
***************************************************************************/
-#include "curl_setup.h"
+#include "../curl_setup.h"
#ifdef USE_MSH3
diff --git a/libs/libcurl/src/vquic/curl_ngtcp2.c b/libs/libcurl/src/vquic/curl_ngtcp2.c
index 7b3f0f9b7e..d5a9553677 100644
--- a/libs/libcurl/src/vquic/curl_ngtcp2.c
+++ b/libs/libcurl/src/vquic/curl_ngtcp2.c
@@ -22,7 +22,7 @@
*
***************************************************************************/
-#include "curl_setup.h"
+#include "../curl_setup.h"
#if defined(USE_NGTCP2) && defined(USE_NGHTTP3)
#include <ngtcp2/ngtcp2.h>
@@ -32,49 +32,51 @@
#include <openssl/err.h>
#if defined(OPENSSL_IS_BORINGSSL) || defined(OPENSSL_IS_AWSLC)
#include <ngtcp2/ngtcp2_crypto_boringssl.h>
+#elif defined(OPENSSL_QUIC_API2)
+#include <ngtcp2/ngtcp2_crypto_ossl.h>
#else
#include <ngtcp2/ngtcp2_crypto_quictls.h>
#endif
-#include "vtls/openssl.h"
+#include "../vtls/openssl.h"
#elif defined(USE_GNUTLS)
#include <ngtcp2/ngtcp2_crypto_gnutls.h>
-#include "vtls/gtls.h"
+#include "../vtls/gtls.h"
#elif defined(USE_WOLFSSL)
#include <ngtcp2/ngtcp2_crypto_wolfssl.h>
-#include "vtls/wolfssl.h"
+#include "../vtls/wolfssl.h"
#endif
-#include "urldata.h"
-#include "hash_offt.h"
-#include "sendf.h"
-#include "strdup.h"
-#include "rand.h"
-#include "multiif.h"
-#include "strcase.h"
-#include "cfilters.h"
-#include "cf-socket.h"
-#include "connect.h"
-#include "progress.h"
-#include "strerror.h"
-#include "dynbuf.h"
-#include "http1.h"
-#include "select.h"
-#include "inet_pton.h"
-#include "transfer.h"
+#include "../urldata.h"
+#include "../uint-hash.h"
+#include "../sendf.h"
+#include "../strdup.h"
+#include "../rand.h"
+#include "../multiif.h"
+#include "../strcase.h"
+#include "../cfilters.h"
+#include "../cf-socket.h"
+#include "../connect.h"
+#include "../progress.h"
+#include "../strerror.h"
+#include "../curlx/dynbuf.h"
+#include "../http1.h"
+#include "../select.h"
+#include "../curlx/inet_pton.h"
+#include "../transfer.h"
#include "vquic.h"
#include "vquic_int.h"
#include "vquic-tls.h"
-#include "vtls/keylog.h"
-#include "vtls/vtls.h"
-#include "vtls/vtls_scache.h"
+#include "../vtls/keylog.h"
+#include "../vtls/vtls.h"
+#include "../vtls/vtls_scache.h"
#include "curl_ngtcp2.h"
-#include "warnless.h"
+#include "../curlx/warnless.h"
/* The last 3 #include files should be in this order */
-#include "curl_printf.h"
-#include "curl_memory.h"
-#include "memdebug.h"
+#include "../curl_printf.h"
+#include "../curl_memory.h"
+#include "../memdebug.h"
#define QUIC_MAX_STREAMS (256*1024)
@@ -87,6 +89,10 @@
* Chunk size is large enough to take a full DATA frame */
#define H3_STREAM_WINDOW_SIZE (128 * 1024)
#define H3_STREAM_CHUNK_SIZE (16 * 1024)
+#if H3_STREAM_CHUNK_SIZE < NGTCP2_MAX_UDP_PAYLOAD_SIZE
+#error H3_STREAM_CHUNK_SIZE smaller than NGTCP2_MAX_UDP_PAYLOAD_SIZE
+#endif
+
/* The pool keeps spares around and half of a full stream windows
* seems good. More does not seem to improve performance.
* The benefit of the pool is that stream buffer to not keep
@@ -117,6 +123,9 @@ struct cf_ngtcp2_ctx {
struct cf_quic_ctx q;
struct ssl_peer peer;
struct curl_tls_ctx tls;
+#ifdef OPENSSL_QUIC_API2
+ ngtcp2_crypto_ossl_ctx *ossl_ctx;
+#endif
ngtcp2_path connected_path;
ngtcp2_conn *qconn;
ngtcp2_cid dcid;
@@ -133,9 +142,8 @@ struct cf_ngtcp2_ctx {
struct curltime handshake_at; /* time connect handshake finished */
struct bufc_pool stream_bufcp; /* chunk pool for streams */
struct dynbuf scratch; /* temp buffer for header construction */
- struct Curl_hash_offt streams; /* hash `data->mid` to `h3_stream_ctx` */
+ struct uint_hash streams; /* hash `data->mid` to `h3_stream_ctx` */
size_t max_stream_window; /* max flow window for one stream */
- uint64_t max_idle_ms; /* max idle time for QUIC connection */
uint64_t used_bidi_streams; /* bidi streams we have opened */
uint64_t max_bidi_streams; /* max bidi streams we can open */
size_t earlydata_max; /* max amount of early data supported by
@@ -156,7 +164,7 @@ struct cf_ngtcp2_ctx {
#define CF_CTX_CALL_DATA(cf) \
((struct cf_ngtcp2_ctx *)(cf)->ctx)->call_data
-static void h3_stream_hash_free(curl_off_t id, void *stream);
+static void h3_stream_hash_free(unsigned int id, void *stream);
static void cf_ngtcp2_ctx_init(struct cf_ngtcp2_ctx *ctx)
{
@@ -164,11 +172,10 @@ static void cf_ngtcp2_ctx_init(struct cf_ngtcp2_ctx *ctx)
ctx->qlogfd = -1;
ctx->version = NGTCP2_PROTO_VER_MAX;
ctx->max_stream_window = H3_STREAM_WINDOW_SIZE;
- ctx->max_idle_ms = CURL_QUIC_MAX_IDLE_MS;
Curl_bufcp_init(&ctx->stream_bufcp, H3_STREAM_CHUNK_SIZE,
H3_STREAM_POOL_SPARES);
- Curl_dyn_init(&ctx->scratch, CURL_MAX_HTTP_HEADER);
- Curl_hash_offt_init(&ctx->streams, 63, h3_stream_hash_free);
+ curlx_dyn_init(&ctx->scratch, CURL_MAX_HTTP_HEADER);
+ Curl_uint_hash_init(&ctx->streams, 63, h3_stream_hash_free);
ctx->initialized = TRUE;
}
@@ -178,13 +185,51 @@ static void cf_ngtcp2_ctx_free(struct cf_ngtcp2_ctx *ctx)
Curl_vquic_tls_cleanup(&ctx->tls);
vquic_ctx_free(&ctx->q);
Curl_bufcp_free(&ctx->stream_bufcp);
- Curl_dyn_free(&ctx->scratch);
- Curl_hash_offt_destroy(&ctx->streams);
+ curlx_dyn_free(&ctx->scratch);
+ Curl_uint_hash_destroy(&ctx->streams);
Curl_ssl_peer_cleanup(&ctx->peer);
}
free(ctx);
}
+static void cf_ngtcp2_setup_keep_alive(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
+{
+ struct cf_ngtcp2_ctx *ctx = cf->ctx;
+ const ngtcp2_transport_params *rp;
+ /* Peer should have sent us its transport parameters. If it
+ * announces a positive `max_idle_timeout` it will close the
+ * connection when it does not hear from us for that time.
+ *
+ * Some servers use this as a keep-alive timer at a rather low
+ * value. We are doing HTTP/3 here and waiting for the response
+ * to a request may take a considerable amount of time. We need
+ * to prevent the peer's QUIC stack from closing in this case.
+ */
+ if(!ctx->qconn)
+ return;
+
+ rp = ngtcp2_conn_get_remote_transport_params(ctx->qconn);
+ if(!rp || !rp->max_idle_timeout) {
+ ngtcp2_conn_set_keep_alive_timeout(ctx->qconn, UINT64_MAX);
+ CURL_TRC_CF(data, cf, "no peer idle timeout, unset keep-alive");
+ }
+ else if(!Curl_uint_hash_count(&ctx->streams)) {
+ ngtcp2_conn_set_keep_alive_timeout(ctx->qconn, UINT64_MAX);
+ CURL_TRC_CF(data, cf, "no active streams, unset keep-alive");
+ }
+ else {
+ ngtcp2_duration keep_ns;
+ keep_ns = (rp->max_idle_timeout > 1) ? (rp->max_idle_timeout / 2) : 1;
+ ngtcp2_conn_set_keep_alive_timeout(ctx->qconn, keep_ns);
+ CURL_TRC_CF(data, cf, "peer idle timeout is %" FMT_PRIu64 "ms, "
+ "set keep-alive to %" FMT_PRIu64 " ms.",
+ (curl_uint64_t)(rp->max_idle_timeout / NGTCP2_MILLISECONDS),
+ (curl_uint64_t)(keep_ns / NGTCP2_MILLISECONDS));
+ }
+}
+
+
struct pkt_io_ctx;
static CURLcode cf_progress_ingress(struct Curl_cfilter *cf,
struct Curl_easy *data,
@@ -205,18 +250,13 @@ struct h3_stream_ctx {
curl_off_t upload_left; /* number of request bytes left to upload */
int status_code; /* HTTP status code */
CURLcode xfer_result; /* result from xfer_resp_write(_hd) */
- bool resp_hds_complete; /* we have a complete, final response */
- bool closed; /* TRUE on stream close */
- bool reset; /* TRUE on stream reset */
- bool send_closed; /* stream is local closed */
+ BIT(resp_hds_complete); /* we have a complete, final response */
+ BIT(closed); /* TRUE on stream close */
+ BIT(reset); /* TRUE on stream reset */
+ BIT(send_closed); /* stream is local closed */
BIT(quic_flow_blocked); /* stream is blocked by QUIC flow control */
};
-#define H3_STREAM_CTX(ctx,data) ((struct h3_stream_ctx *)(\
- data? Curl_hash_offt_get(&(ctx)->streams, (data)->mid) : NULL))
-#define H3_STREAM_CTX_ID(ctx,id) ((struct h3_stream_ctx *)(\
- Curl_hash_offt_get(&(ctx)->streams, (id))))
-
static void h3_stream_ctx_free(struct h3_stream_ctx *stream)
{
Curl_bufq_free(&stream->sendbuf);
@@ -224,7 +264,7 @@ static void h3_stream_ctx_free(struct h3_stream_ctx *stream)
free(stream);
}
-static void h3_stream_hash_free(curl_off_t id, void *stream)
+static void h3_stream_hash_free(unsigned int id, void *stream)
{
(void)id;
DEBUGASSERT(stream);
@@ -254,11 +294,14 @@ static CURLcode h3_data_setup(struct Curl_cfilter *cf,
stream->sendbuf_len_in_flight = 0;
Curl_h1_req_parse_init(&stream->h1, H1_PARSE_DEFAULT_MAX_LINE_LEN);
- if(!Curl_hash_offt_set(&ctx->streams, data->mid, stream)) {
+ if(!Curl_uint_hash_set(&ctx->streams, data->mid, stream)) {
h3_stream_ctx_free(stream);
return CURLE_OUT_OF_MEMORY;
}
+ if(Curl_uint_hash_count(&ctx->streams) == 1)
+ cf_ngtcp2_setup_keep_alive(cf, data);
+
return CURLE_OK;
}
@@ -293,7 +336,9 @@ static void h3_data_done(struct Curl_cfilter *cf, struct Curl_easy *data)
CURL_TRC_CF(data, cf, "[%" FMT_PRId64 "] easy handle is done",
stream->id);
cf_ngtcp2_stream_close(cf, data, stream);
- Curl_hash_offt_remove(&ctx->streams, data->mid);
+ Curl_uint_hash_remove(&ctx->streams, data->mid);
+ if(!Curl_uint_hash_count(&ctx->streams))
+ cf_ngtcp2_setup_keep_alive(cf, data);
}
}
@@ -415,7 +460,7 @@ static void quic_settings(struct cf_ngtcp2_ctx *ctx,
t->initial_max_stream_data_uni = ctx->max_stream_window;
t->initial_max_streams_bidi = QUIC_MAX_STREAMS;
t->initial_max_streams_uni = QUIC_MAX_STREAMS;
- t->max_idle_timeout = (ctx->max_idle_ms * NGTCP2_MILLISECONDS);
+ t->max_idle_timeout = 0; /* no idle timeout from our side */
if(ctx->qlogfd != -1) {
s->qlog_write = qlog_callback;
}
@@ -437,14 +482,14 @@ static int cf_ngtcp2_handshake_completed(ngtcp2_conn *tconn, void *user_data)
if(!ctx || !data)
return NGHTTP3_ERR_CALLBACK_FAILURE;
- ctx->handshake_at = Curl_now();
+ ctx->handshake_at = curlx_now();
ctx->tls_handshake_complete = TRUE;
cf->conn->bits.multiplex = TRUE; /* at least potentially multiplexed */
ctx->tls_vrfy_result = Curl_vquic_tls_verify_peer(&ctx->tls, cf,
data, &ctx->peer);
CURL_TRC_CF(data, cf, "handshake complete after %dms",
- (int)Curl_timediff(ctx->handshake_at, ctx->started_at));
+ (int)curlx_timediff(ctx->handshake_at, ctx->started_at));
/* In case of earlydata, where we simulate being connected, update
* the handshake time when we really did connect */
if(ctx->use_earlydata)
@@ -546,7 +591,7 @@ static int cb_recv_stream_data(ngtcp2_conn *tconn, uint32_t flags,
CURL_TRC_CF(data, cf, "[%" FMT_PRId64 "] read_stream(len=%zu) -> %zd",
stream_id, buflen, nconsumed);
if(nconsumed < 0) {
- struct h3_stream_ctx *stream = H3_STREAM_CTX_ID(ctx, stream_id);
+ struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data);
if(data && stream) {
CURL_TRC_CF(data, cf, "[%" FMT_PRId64 "] error on known stream, "
"reset=%d, closed=%d",
@@ -1060,18 +1105,18 @@ static int cb_h3_recv_header(nghttp3_conn *conn, int64_t sid,
(const char *)h3val.base, h3val.len);
if(result)
return -1;
- Curl_dyn_reset(&ctx->scratch);
- result = Curl_dyn_addn(&ctx->scratch, STRCONST("HTTP/3 "));
+ curlx_dyn_reset(&ctx->scratch);
+ result = curlx_dyn_addn(&ctx->scratch, STRCONST("HTTP/3 "));
if(!result)
- result = Curl_dyn_addn(&ctx->scratch,
- (const char *)h3val.base, h3val.len);
+ result = curlx_dyn_addn(&ctx->scratch,
+ (const char *)h3val.base, h3val.len);
if(!result)
- result = Curl_dyn_addn(&ctx->scratch, STRCONST(" \r\n"));
+ result = curlx_dyn_addn(&ctx->scratch, STRCONST(" \r\n"));
if(!result)
- h3_xfer_write_resp_hd(cf, data, stream, Curl_dyn_ptr(&ctx->scratch),
- Curl_dyn_len(&ctx->scratch), FALSE);
+ h3_xfer_write_resp_hd(cf, data, stream, curlx_dyn_ptr(&ctx->scratch),
+ curlx_dyn_len(&ctx->scratch), FALSE);
CURL_TRC_CF(data, cf, "[%" FMT_PRId64 "] status: %s",
- stream_id, Curl_dyn_ptr(&ctx->scratch));
+ stream_id, curlx_dyn_ptr(&ctx->scratch));
if(result) {
return -1;
}
@@ -1081,19 +1126,19 @@ static int cb_h3_recv_header(nghttp3_conn *conn, int64_t sid,
CURL_TRC_CF(data, cf, "[%" FMT_PRId64 "] header: %.*s: %.*s",
stream_id, (int)h3name.len, h3name.base,
(int)h3val.len, h3val.base);
- Curl_dyn_reset(&ctx->scratch);
- result = Curl_dyn_addn(&ctx->scratch,
- (const char *)h3name.base, h3name.len);
+ curlx_dyn_reset(&ctx->scratch);
+ result = curlx_dyn_addn(&ctx->scratch,
+ (const char *)h3name.base, h3name.len);
if(!result)
- result = Curl_dyn_addn(&ctx->scratch, STRCONST(": "));
+ result = curlx_dyn_addn(&ctx->scratch, STRCONST(": "));
if(!result)
- result = Curl_dyn_addn(&ctx->scratch,
- (const char *)h3val.base, h3val.len);
+ result = curlx_dyn_addn(&ctx->scratch,
+ (const char *)h3val.base, h3val.len);
if(!result)
- result = Curl_dyn_addn(&ctx->scratch, STRCONST("\r\n"));
+ result = curlx_dyn_addn(&ctx->scratch, STRCONST("\r\n"));
if(!result)
- h3_xfer_write_resp_hd(cf, data, stream, Curl_dyn_ptr(&ctx->scratch),
- Curl_dyn_len(&ctx->scratch), FALSE);
+ h3_xfer_write_resp_hd(cf, data, stream, curlx_dyn_ptr(&ctx->scratch),
+ curlx_dyn_len(&ctx->scratch), FALSE);
}
return 0;
}
@@ -2014,10 +2059,20 @@ static void cf_ngtcp2_ctx_close(struct cf_ngtcp2_ctx *ctx)
ctx->qlogfd = -1;
Curl_vquic_tls_cleanup(&ctx->tls);
vquic_ctx_free(&ctx->q);
- if(ctx->h3conn)
+ if(ctx->h3conn) {
nghttp3_conn_del(ctx->h3conn);
- if(ctx->qconn)
+ ctx->h3conn = NULL;
+ }
+ if(ctx->qconn) {
ngtcp2_conn_del(ctx->qconn);
+ ctx->qconn = NULL;
+ }
+#ifdef OPENSSL_QUIC_API2
+ if(ctx->ossl_ctx) {
+ ngtcp2_crypto_ossl_ctx_del(ctx->ossl_ctx);
+ ctx->ossl_ctx = NULL;
+ }
+#endif
ctx->call_data = save;
}
@@ -2057,6 +2112,7 @@ static CURLcode cf_ngtcp2_shutdown(struct Curl_cfilter *cf,
}
}
+ DEBUGASSERT(Curl_bufq_is_empty(&ctx->q.sendbuf));
ctx->shutdown_started = TRUE;
nwritten = ngtcp2_conn_write_connection_close(
ctx->qconn, NULL, /* path */
@@ -2066,14 +2122,21 @@ static CURLcode cf_ngtcp2_shutdown(struct Curl_cfilter *cf,
CURL_TRC_CF(data, cf, "start shutdown(err_type=%d, err_code=%"
FMT_PRIu64 ") -> %d", ctx->last_error.type,
(curl_uint64_t)ctx->last_error.error_code, (int)nwritten);
+ /* there are cases listed in ngtcp2 documentation where this call
+ * may fail. Since we are doing a connection shutdown as graceful
+ * as we can, such an error is ignored here. */
if(nwritten > 0) {
- Curl_bufq_write(&ctx->q.sendbuf, (const unsigned char *)buffer,
- (size_t)nwritten, &result);
+ /* Ignore amount written. sendbuf was empty and has always room for
+ * NGTCP2_MAX_UDP_PAYLOAD_SIZE. It can only completely fail, in which
+ * case `result` is set non zero. */
+ (void)Curl_bufq_write(&ctx->q.sendbuf, (const unsigned char *)buffer,
+ (size_t)nwritten, &result);
if(result) {
CURL_TRC_CF(data, cf, "error %d adding shutdown packets to sendbuf, "
"aborting shutdown", result);
goto out;
}
+
ctx->q.no_gso = TRUE;
ctx->q.gsolen = (size_t)nwritten;
ctx->q.split_len = 0;
@@ -2133,6 +2196,7 @@ static void cf_ngtcp2_destroy(struct Curl_cfilter *cf, struct Curl_easy *data)
{
CURL_TRC_CF(data, cf, "destroy");
if(cf->ctx) {
+ cf_ngtcp2_close(cf, data);
cf_ngtcp2_ctx_free(cf->ctx);
cf->ctx = NULL;
}
@@ -2291,6 +2355,8 @@ static CURLcode cf_ngtcp2_tls_ctx_setup(struct Curl_cfilter *cf,
failf(data, "ngtcp2_crypto_boringssl_configure_client_context failed");
return CURLE_FAILED_INIT;
}
+#elif defined(OPENSSL_QUIC_API2)
+ /* nothing to do */
#else
if(ngtcp2_crypto_quictls_configure_client_context(ctx->ossl.ssl_ctx) != 0) {
failf(data, "ngtcp2_crypto_quictls_configure_client_context failed");
@@ -2453,6 +2519,9 @@ static const struct alpn_spec ALPN_SPEC_H3 = {
if(rc)
return CURLE_QUIC_CONNECT_ERROR;
+ ctx->conn_ref.get_conn = get_conn;
+ ctx->conn_ref.user_data = cf;
+
result = Curl_vquic_tls_init(&ctx->tls, cf, data, &ctx->peer, &ALPN_SPEC_H3,
cf_ngtcp2_tls_ctx_setup, &ctx->tls,
&ctx->conn_ref,
@@ -2460,7 +2529,17 @@ static const struct alpn_spec ALPN_SPEC_H3 = {
if(result)
return result;
-#ifdef USE_OPENSSL
+#if defined(USE_OPENSSL) && defined(OPENSSL_QUIC_API2)
+ if(ngtcp2_crypto_ossl_ctx_new(&ctx->ossl_ctx, ctx->tls.ossl.ssl) != 0) {
+ failf(data, "ngtcp2_crypto_ossl_ctx_new failed");
+ return CURLE_FAILED_INIT;
+ }
+ ngtcp2_conn_set_tls_native_handle(ctx->qconn, ctx->ossl_ctx);
+ if(ngtcp2_crypto_ossl_configure_client_session(ctx->tls.ossl.ssl) != 0) {
+ failf(data, "ngtcp2_crypto_ossl_configure_client_session failed");
+ return CURLE_FAILED_INIT;
+ }
+#elif defined(USE_OPENSSL)
SSL_set_quic_use_legacy_codepoint(ctx->tls.ossl.ssl, 0);
ngtcp2_conn_set_tls_native_handle(ctx->qconn, ctx->tls.ossl.ssl);
#elif defined(USE_GNUTLS)
@@ -2473,9 +2552,6 @@ static const struct alpn_spec ALPN_SPEC_H3 = {
ngtcp2_ccerr_default(&ctx->last_error);
- ctx->conn_ref.get_conn = get_conn;
- ctx->conn_ref.user_data = cf;
-
return CURLE_OK;
}
@@ -2502,7 +2578,7 @@ static CURLcode cf_ngtcp2_connect(struct Curl_cfilter *cf,
}
*done = FALSE;
- now = Curl_now();
+ now = curlx_now();
pktx_init(&pktx, cf, data);
CF_DATA_SAVE(save, cf, data);
@@ -2589,7 +2665,7 @@ static CURLcode cf_ngtcp2_query(struct Curl_cfilter *cf,
}
else if(ctx->max_bidi_streams) {
uint64_t avail_bidi_streams = 0;
- uint64_t max_streams = CONN_INUSE(cf->conn);
+ uint64_t max_streams = CONN_ATTACHED(cf->conn);
if(ctx->max_bidi_streams > ctx->used_bidi_streams)
avail_bidi_streams = ctx->max_bidi_streams - ctx->used_bidi_streams;
max_streams += avail_bidi_streams;
@@ -2598,14 +2674,14 @@ static CURLcode cf_ngtcp2_query(struct Curl_cfilter *cf,
else /* transport params not arrived yet? take our default. */
*pres1 = (int)Curl_multi_max_concurrent_streams(data->multi);
CURL_TRC_CF(data, cf, "query conn[%" FMT_OFF_T "]: "
- "MAX_CONCURRENT -> %d (%zu in use)",
- cf->conn->connection_id, *pres1, CONN_INUSE(cf->conn));
+ "MAX_CONCURRENT -> %d (%u in use)",
+ cf->conn->connection_id, *pres1, CONN_ATTACHED(cf->conn));
CF_DATA_RESTORE(cf, save);
return CURLE_OK;
}
case CF_QUERY_CONNECT_REPLY_MS:
if(ctx->q.got_first_byte) {
- timediff_t ms = Curl_timediff(ctx->q.first_byte_at, ctx->started_at);
+ timediff_t ms = curlx_timediff(ctx->q.first_byte_at, ctx->started_at);
*pres1 = (ms < INT_MAX) ? (int)ms : INT_MAX;
}
else
@@ -2648,21 +2724,12 @@ static bool cf_ngtcp2_conn_is_alive(struct Curl_cfilter *cf,
if(!ctx->qconn || ctx->shutdown_started)
goto out;
- /* Both sides of the QUIC connection announce they max idle times in
- * the transport parameters. Look at the minimum of both and if
- * we exceed this, regard the connection as dead. The other side
- * may have completely purged it and will no longer respond
- * to any packets from us. */
+ /* We do not announce a max idle timeout, but when the peer does
+ * it will close the connection when it expires. */
rp = ngtcp2_conn_get_remote_transport_params(ctx->qconn);
- if(rp) {
- timediff_t idletime;
- uint64_t idle_ms = ctx->max_idle_ms;
-
- if(rp->max_idle_timeout &&
- (rp->max_idle_timeout / NGTCP2_MILLISECONDS) < idle_ms)
- idle_ms = (rp->max_idle_timeout / NGTCP2_MILLISECONDS);
- idletime = Curl_timediff(Curl_now(), ctx->q.last_io);
- if(idletime > 0 && (uint64_t)idletime > idle_ms)
+ if(rp && rp->max_idle_timeout) {
+ timediff_t idletime = curlx_timediff(curlx_now(), ctx->q.last_io);
+ if(idletime > 0 && (uint64_t)idletime > rp->max_idle_timeout)
goto out;
}
diff --git a/libs/libcurl/src/vquic/curl_ngtcp2.h b/libs/libcurl/src/vquic/curl_ngtcp2.h
index 7b8a158b76..313d853644 100644
--- a/libs/libcurl/src/vquic/curl_ngtcp2.h
+++ b/libs/libcurl/src/vquic/curl_ngtcp2.h
@@ -24,7 +24,7 @@
*
***************************************************************************/
-#include "curl_setup.h"
+#include "../curl_setup.h"
#if defined(USE_NGTCP2) && defined(USE_NGHTTP3)
@@ -33,6 +33,9 @@
#endif
#include <ngtcp2/ngtcp2_crypto.h>
+#ifdef OPENSSL_QUIC_API2
+#include <ngtcp2/ngtcp2_crypto_ossl.h>
+#endif
#include <nghttp3/nghttp3.h>
#ifdef USE_OPENSSL
#include <openssl/ssl.h>
@@ -44,7 +47,7 @@
struct Curl_cfilter;
-#include "urldata.h"
+#include "../urldata.h"
void Curl_ngtcp2_ver(char *p, size_t len);
diff --git a/libs/libcurl/src/vquic/curl_osslq.c b/libs/libcurl/src/vquic/curl_osslq.c
index 7dbd0f13f3..3067ccfbda 100644
--- a/libs/libcurl/src/vquic/curl_osslq.c
+++ b/libs/libcurl/src/vquic/curl_osslq.c
@@ -22,7 +22,7 @@
*
***************************************************************************/
-#include "curl_setup.h"
+#include "../curl_setup.h"
#if defined(USE_OPENSSL_QUIC) && defined(USE_NGHTTP3)
@@ -31,36 +31,36 @@
#include <openssl/err.h>
#include <nghttp3/nghttp3.h>
-#include "urldata.h"
-#include "hash.h"
-#include "sendf.h"
-#include "strdup.h"
-#include "rand.h"
-#include "multiif.h"
-#include "strcase.h"
-#include "cfilters.h"
-#include "cf-socket.h"
-#include "connect.h"
-#include "progress.h"
-#include "strerror.h"
-#include "dynbuf.h"
-#include "http1.h"
-#include "select.h"
-#include "inet_pton.h"
+#include "../urldata.h"
+#include "../hash.h"
+#include "../sendf.h"
+#include "../strdup.h"
+#include "../rand.h"
+#include "../multiif.h"
+#include "../strcase.h"
+#include "../cfilters.h"
+#include "../cf-socket.h"
+#include "../connect.h"
+#include "../progress.h"
+#include "../strerror.h"
+#include "../curlx/dynbuf.h"
+#include "../http1.h"
+#include "../select.h"
+#include "../curlx/inet_pton.h"
+#include "../uint-hash.h"
#include "vquic.h"
#include "vquic_int.h"
#include "vquic-tls.h"
-#include "vtls/keylog.h"
-#include "vtls/vtls.h"
-#include "vtls/openssl.h"
+#include "../vtls/keylog.h"
+#include "../vtls/vtls.h"
+#include "../vtls/openssl.h"
#include "curl_osslq.h"
-
-#include "warnless.h"
+#include "../curlx/warnless.h"
/* The last 3 #include files should be in this order */
-#include "curl_printf.h"
-#include "curl_memory.h"
-#include "memdebug.h"
+#include "../curl_printf.h"
+#include "../curl_memory.h"
+#include "../memdebug.h"
/* A stream window is the maximum amount we need to buffer for
* each active transfer. We use HTTP/3 flow control and only ACK
@@ -285,7 +285,7 @@ struct cf_osslq_ctx {
struct curltime handshake_at; /* time connect handshake finished */
struct curltime first_byte_at; /* when first byte was recvd */
struct bufc_pool stream_bufcp; /* chunk pool for streams */
- struct Curl_hash_offt streams; /* hash `data->mid` to `h3_stream_ctx` */
+ struct uint_hash streams; /* hash `data->mid` to `h3_stream_ctx` */
size_t max_stream_window; /* max flow window for one stream */
uint64_t max_idle_ms; /* max idle time for QUIC connection */
SSL_POLL_ITEM *poll_items; /* Array for polling on writable state */
@@ -299,14 +299,14 @@ struct cf_osslq_ctx {
BIT(need_send); /* QUIC connection needs to send */
};
-static void h3_stream_hash_free(curl_off_t id, void *stream);
+static void h3_stream_hash_free(unsigned int id, void *stream);
static void cf_osslq_ctx_init(struct cf_osslq_ctx *ctx)
{
DEBUGASSERT(!ctx->initialized);
Curl_bufcp_init(&ctx->stream_bufcp, H3_STREAM_CHUNK_SIZE,
H3_STREAM_POOL_SPARES);
- Curl_hash_offt_init(&ctx->streams, 63, h3_stream_hash_free);
+ Curl_uint_hash_init(&ctx->streams, 63, h3_stream_hash_free);
ctx->poll_items = NULL;
ctx->curl_items = NULL;
ctx->items_max = 0;
@@ -317,7 +317,7 @@ static void cf_osslq_ctx_free(struct cf_osslq_ctx *ctx)
{
if(ctx && ctx->initialized) {
Curl_bufcp_free(&ctx->stream_bufcp);
- Curl_hash_offt_destroy(&ctx->streams);
+ Curl_uint_hash_destroy(&ctx->streams);
Curl_ssl_peer_cleanup(&ctx->peer);
free(ctx->poll_items);
free(ctx->curl_items);
@@ -583,16 +583,13 @@ struct h3_stream_ctx {
curl_off_t upload_left; /* number of request bytes left to upload */
curl_off_t download_recvd; /* number of response DATA bytes received */
int status_code; /* HTTP status code */
- bool resp_hds_complete; /* we have a complete, final response */
- bool closed; /* TRUE on stream close */
- bool reset; /* TRUE on stream reset */
- bool send_closed; /* stream is local closed */
+ BIT(resp_hds_complete); /* we have a complete, final response */
+ BIT(closed); /* TRUE on stream close */
+ BIT(reset); /* TRUE on stream reset */
+ BIT(send_closed); /* stream is local closed */
BIT(quic_flow_blocked); /* stream is blocked by QUIC flow control */
};
-#define H3_STREAM_CTX(ctx,data) ((struct h3_stream_ctx *)(\
- data? Curl_hash_offt_get(&(ctx)->streams, (data)->mid) : NULL))
-
static void h3_stream_ctx_free(struct h3_stream_ctx *stream)
{
cf_osslq_stream_cleanup(&stream->s);
@@ -602,7 +599,7 @@ static void h3_stream_ctx_free(struct h3_stream_ctx *stream)
free(stream);
}
-static void h3_stream_hash_free(curl_off_t id, void *stream)
+static void h3_stream_hash_free(unsigned int id, void *stream)
{
(void)id;
DEBUGASSERT(stream);
@@ -637,7 +634,7 @@ static CURLcode h3_data_setup(struct Curl_cfilter *cf,
stream->recv_buf_nonflow = 0;
Curl_h1_req_parse_init(&stream->h1, H1_PARSE_DEFAULT_MAX_LINE_LEN);
- if(!Curl_hash_offt_set(&ctx->streams, data->mid, stream)) {
+ if(!Curl_uint_hash_set(&ctx->streams, data->mid, stream)) {
h3_stream_ctx_free(stream);
return CURLE_OUT_OF_MEMORY;
}
@@ -654,7 +651,7 @@ static void h3_data_done(struct Curl_cfilter *cf, struct Curl_easy *data)
if(stream) {
CURL_TRC_CF(data, cf, "[%"FMT_PRId64"] easy handle is done",
stream->s.id);
- if(ctx->h3.conn && !stream->closed) {
+ if(ctx->h3.conn && (stream->s.id >= 0) && !stream->closed) {
nghttp3_conn_shutdown_stream_read(ctx->h3.conn, stream->s.id);
nghttp3_conn_close_stream(ctx->h3.conn, stream->s.id,
NGHTTP3_H3_REQUEST_CANCELLED);
@@ -662,7 +659,7 @@ static void h3_data_done(struct Curl_cfilter *cf, struct Curl_easy *data)
stream->closed = TRUE;
}
- Curl_hash_offt_remove(&ctx->streams, data->mid);
+ Curl_uint_hash_remove(&ctx->streams, data->mid);
}
}
@@ -671,7 +668,7 @@ struct cf_ossq_find_ctx {
struct h3_stream_ctx *stream;
};
-static bool cf_osslq_find_stream(curl_off_t mid, void *val, void *user_data)
+static bool cf_osslq_find_stream(unsigned int mid, void *val, void *user_data)
{
struct h3_stream_ctx *stream = val;
struct cf_ossq_find_ctx *fctx = user_data;
@@ -707,7 +704,7 @@ static struct cf_osslq_stream *cf_osslq_get_qstream(struct Curl_cfilter *cf,
struct cf_ossq_find_ctx fctx;
fctx.stream_id = stream_id;
fctx.stream = NULL;
- Curl_hash_offt_visit(&ctx->streams, cf_osslq_find_stream, &fctx);
+ Curl_uint_hash_visit(&ctx->streams, cf_osslq_find_stream, &fctx);
if(fctx.stream)
return &fctx.stream->s;
}
@@ -832,7 +829,7 @@ static int cb_h3_recv_data(nghttp3_conn *conn, int64_t stream3_id,
return NGHTTP3_ERR_CALLBACK_FAILURE;
}
stream->download_recvd += (curl_off_t)buflen;
- CURL_TRC_CF(data, cf, "[%" FMT_PRId64 "] DATA len=%zu, total=%zd",
+ CURL_TRC_CF(data, cf, "[%" FMT_PRId64 "] DATA len=%zu, total=%" FMT_OFF_T,
stream->s.id, buflen, stream->download_recvd);
h3_drain_stream(cf, data);
return 0;
@@ -1239,17 +1236,6 @@ static const struct alpn_spec ALPN_SPEC_H3 = {
goto out;
}
-#ifdef SSL_VALUE_QUIC_IDLE_TIMEOUT
- /* Added in OpenSSL v3.3.x */
- if(!SSL_set_feature_request_uint(ctx->tls.ossl.ssl,
- SSL_VALUE_QUIC_IDLE_TIMEOUT,
- CURL_QUIC_MAX_IDLE_MS)) {
- CURL_TRC_CF(data, cf, "error setting idle timeout, ");
- result = CURLE_FAILED_INIT;
- goto out;
- }
-#endif
-
SSL_set_bio(ctx->tls.ossl.ssl, bio, bio);
bio = NULL;
SSL_set_connect_state(ctx->tls.ossl.ssl);
@@ -1420,14 +1406,14 @@ struct cf_ossq_recv_ctx {
CURLcode result;
};
-static bool cf_osslq_iter_recv(curl_off_t mid, void *val, void *user_data)
+static bool cf_osslq_iter_recv(unsigned int mid, void *val, void *user_data)
{
struct h3_stream_ctx *stream = val;
struct cf_ossq_recv_ctx *rctx = user_data;
(void)mid;
if(stream && !stream->closed && !Curl_bufq_is_full(&stream->recvbuf)) {
- struct Curl_easy *sdata = Curl_multi_get_handle(rctx->multi, mid);
+ struct Curl_easy *sdata = Curl_multi_get_easy(rctx->multi, mid);
if(sdata) {
rctx->result = cf_osslq_stream_recv(&stream->s, rctx->cf, sdata);
if(rctx->result)
@@ -1479,7 +1465,7 @@ static CURLcode cf_progress_ingress(struct Curl_cfilter *cf,
rctx.cf = cf;
rctx.multi = data->multi;
rctx.result = CURLE_OK;
- Curl_hash_offt_visit(&ctx->streams, cf_osslq_iter_recv, &rctx);
+ Curl_uint_hash_visit(&ctx->streams, cf_osslq_iter_recv, &rctx);
result = rctx.result;
}
@@ -1494,7 +1480,7 @@ struct cf_ossq_fill_ctx {
size_t n;
};
-static bool cf_osslq_collect_block_send(curl_off_t mid, void *val,
+static bool cf_osslq_collect_block_send(unsigned int mid, void *val,
void *user_data)
{
struct h3_stream_ctx *stream = val;
@@ -1505,9 +1491,7 @@ static bool cf_osslq_collect_block_send(curl_off_t mid, void *val,
return FALSE;
if(stream && stream->s.ssl && stream->s.send_blocked) {
- struct Curl_easy *sdata = Curl_multi_get_handle(fctx->multi, mid);
- fprintf(stderr, "[OSSLQ] stream %" FMT_PRId64 " sdata=%p\n",
- stream->s.id, (void *)sdata);
+ struct Curl_easy *sdata = Curl_multi_get_easy(fctx->multi, mid);
if(sdata) {
ctx->poll_items[fctx->n].desc = SSL_as_poll_descriptor(stream->s.ssl);
ctx->poll_items[fctx->n].events = SSL_POLL_EVENT_W;
@@ -1534,8 +1518,8 @@ static CURLcode cf_osslq_check_and_unblock(struct Curl_cfilter *cf,
if(ctx->h3.conn) {
struct cf_ossq_fill_ctx fill_ctx;
- if(ctx->items_max < Curl_hash_offt_count(&ctx->streams)) {
- size_t nmax = Curl_hash_offt_count(&ctx->streams);
+ if(ctx->items_max < Curl_uint_hash_count(&ctx->streams)) {
+ size_t nmax = Curl_uint_hash_count(&ctx->streams);
ctx->items_max = 0;
tmpptr = realloc(ctx->poll_items, nmax * sizeof(SSL_POLL_ITEM));
if(!tmpptr) {
@@ -1560,7 +1544,7 @@ static CURLcode cf_osslq_check_and_unblock(struct Curl_cfilter *cf,
fill_ctx.ctx = ctx;
fill_ctx.multi = data->multi;
fill_ctx.n = 0;
- Curl_hash_offt_visit(&ctx->streams, cf_osslq_collect_block_send,
+ Curl_uint_hash_visit(&ctx->streams, cf_osslq_collect_block_send,
&fill_ctx);
poll_count = fill_ctx.n;
if(poll_count) {
@@ -1578,10 +1562,13 @@ static CURLcode cf_osslq_check_and_unblock(struct Curl_cfilter *cf,
idx_count++) {
if(ctx->poll_items[idx_count].revents & SSL_POLL_EVENT_W) {
stream = H3_STREAM_CTX(ctx, ctx->curl_items[idx_count]);
- nghttp3_conn_unblock_stream(ctx->h3.conn, stream->s.id);
- stream->s.send_blocked = FALSE;
- h3_drain_stream(cf, ctx->curl_items[idx_count]);
- CURL_TRC_CF(ctx->curl_items[idx_count], cf, "unblocked");
+ DEBUGASSERT(stream); /* should still exist */
+ if(stream) {
+ nghttp3_conn_unblock_stream(ctx->h3.conn, stream->s.id);
+ stream->s.send_blocked = FALSE;
+ h3_drain_stream(cf, ctx->curl_items[idx_count]);
+ CURL_TRC_CF(ctx->curl_items[idx_count], cf, "unblocked");
+ }
result_count--;
}
}
@@ -1677,7 +1664,7 @@ static CURLcode h3_send_streams(struct Curl_cfilter *cf,
if(acked_len > 0 || (eos && !s->send_blocked)) {
/* Since QUIC buffers the data written internally, we can tell
* nghttp3 that it can move forward on it */
- ctx->q.last_io = Curl_now();
+ ctx->q.last_io = curlx_now();
rv = nghttp3_conn_add_write_offset(ctx->h3.conn, s->id, acked_len);
if(rv && rv != NGHTTP3_ERR_STREAM_NOT_FOUND) {
failf(data, "nghttp3_conn_add_write_offset returned error: %s\n",
@@ -1791,7 +1778,7 @@ static CURLcode cf_osslq_connect(struct Curl_cfilter *cf,
}
*done = FALSE;
- now = Curl_now();
+ now = curlx_now();
CF_DATA_SAVE(save, cf, data);
if(!ctx->tls.ossl.ssl) {
@@ -1805,7 +1792,7 @@ static CURLcode cf_osslq_connect(struct Curl_cfilter *cf,
int readable = SOCKET_READABLE(ctx->q.sockfd, 0);
if(readable > 0 && (readable & CURL_CSELECT_IN)) {
ctx->got_first_byte = TRUE;
- ctx->first_byte_at = Curl_now();
+ ctx->first_byte_at = curlx_now();
}
}
@@ -1825,7 +1812,7 @@ static CURLcode cf_osslq_connect(struct Curl_cfilter *cf,
ctx->handshake_at = now;
ctx->q.last_io = now;
CURL_TRC_CF(data, cf, "handshake complete after %dms",
- (int)Curl_timediff(now, ctx->started_at));
+ (int)curlx_timediff(now, ctx->started_at));
result = cf_osslq_verify_peer(cf, data);
if(!result) {
CURL_TRC_CF(data, cf, "peer verified");
@@ -2301,7 +2288,7 @@ static bool cf_osslq_conn_is_alive(struct Curl_cfilter *cf,
goto out;
}
CURL_TRC_CF(data, cf, "negotiated idle timeout: %zums", (size_t)idle_ms);
- idletime = Curl_timediff(Curl_now(), ctx->q.last_io);
+ idletime = curlx_timediff(curlx_now(), ctx->q.last_io);
if(idletime > 0 && (uint64_t)idletime > idle_ms)
goto out;
}
@@ -2378,7 +2365,7 @@ static CURLcode cf_osslq_query(struct Curl_cfilter *cf,
return CURLE_HTTP3;
}
/* we report avail + in_use */
- v += CONN_INUSE(cf->conn);
+ v += CONN_ATTACHED(cf->conn);
*pres1 = (v > INT_MAX) ? INT_MAX : (int)v;
#else
*pres1 = 100;
@@ -2388,7 +2375,7 @@ static CURLcode cf_osslq_query(struct Curl_cfilter *cf,
}
case CF_QUERY_CONNECT_REPLY_MS:
if(ctx->got_first_byte) {
- timediff_t ms = Curl_timediff(ctx->first_byte_at, ctx->started_at);
+ timediff_t ms = curlx_timediff(ctx->first_byte_at, ctx->started_at);
*pres1 = (ms < INT_MAX) ? (int)ms : INT_MAX;
}
else
diff --git a/libs/libcurl/src/vquic/curl_osslq.h b/libs/libcurl/src/vquic/curl_osslq.h
index f34d84baf8..f0e670c106 100644
--- a/libs/libcurl/src/vquic/curl_osslq.h
+++ b/libs/libcurl/src/vquic/curl_osslq.h
@@ -24,7 +24,7 @@
*
***************************************************************************/
-#include "curl_setup.h"
+#include "../curl_setup.h"
#if defined(USE_OPENSSL_QUIC) && defined(USE_NGHTTP3)
@@ -34,7 +34,7 @@
struct Curl_cfilter;
-#include "urldata.h"
+#include "../urldata.h"
void Curl_osslq_ver(char *p, size_t len);
diff --git a/libs/libcurl/src/vquic/curl_quiche.c b/libs/libcurl/src/vquic/curl_quiche.c
index 5d565e31c1..d8bbbd72f6 100644
--- a/libs/libcurl/src/vquic/curl_quiche.c
+++ b/libs/libcurl/src/vquic/curl_quiche.c
@@ -22,40 +22,40 @@
*
***************************************************************************/
-#include "curl_setup.h"
+#include "../curl_setup.h"
#ifdef USE_QUICHE
#include <quiche.h>
#include <openssl/err.h>
#include <openssl/ssl.h>
-#include "bufq.h"
-#include "hash_offt.h"
-#include "urldata.h"
-#include "cfilters.h"
-#include "cf-socket.h"
-#include "sendf.h"
-#include "strdup.h"
-#include "rand.h"
-#include "strcase.h"
-#include "multiif.h"
-#include "connect.h"
-#include "progress.h"
-#include "strerror.h"
-#include "http1.h"
+#include "../bufq.h"
+#include "../uint-hash.h"
+#include "../urldata.h"
+#include "../cfilters.h"
+#include "../cf-socket.h"
+#include "../sendf.h"
+#include "../strdup.h"
+#include "../rand.h"
+#include "../strcase.h"
+#include "../multiif.h"
+#include "../connect.h"
+#include "../progress.h"
+#include "../strerror.h"
+#include "../http1.h"
#include "vquic.h"
#include "vquic_int.h"
#include "vquic-tls.h"
#include "curl_quiche.h"
-#include "transfer.h"
-#include "inet_pton.h"
-#include "vtls/openssl.h"
-#include "vtls/keylog.h"
-#include "vtls/vtls.h"
+#include "../transfer.h"
+#include "../curlx/inet_pton.h"
+#include "../vtls/openssl.h"
+#include "../vtls/keylog.h"
+#include "../vtls/vtls.h"
/* The last 3 #include files should be in this order */
-#include "curl_printf.h"
-#include "curl_memory.h"
-#include "memdebug.h"
+#include "../curl_printf.h"
+#include "../curl_memory.h"
+#include "../memdebug.h"
/* HTTP/3 error values defined in RFC 9114, ch. 8.1 */
#define CURL_H3_NO_ERROR (0x0100)
@@ -97,7 +97,7 @@ struct cf_quiche_ctx {
struct curltime started_at; /* time the current attempt started */
struct curltime handshake_at; /* time connect handshake finished */
struct bufc_pool stream_bufcp; /* chunk pool for streams */
- struct Curl_hash_offt streams; /* hash `data->mid` to `stream_ctx` */
+ struct uint_hash streams; /* hash `data->mid` to `stream_ctx` */
curl_off_t data_recvd;
BIT(initialized);
BIT(goaway); /* got GOAWAY from server */
@@ -115,7 +115,7 @@ static void quiche_debug_log(const char *line, void *argp)
}
#endif
-static void h3_stream_hash_free(curl_off_t id, void *stream);
+static void h3_stream_hash_free(unsigned int id, void *stream);
static void cf_quiche_ctx_init(struct cf_quiche_ctx *ctx)
{
@@ -128,7 +128,7 @@ static void cf_quiche_ctx_init(struct cf_quiche_ctx *ctx)
#endif
Curl_bufcp_init(&ctx->stream_bufcp, H3_STREAM_CHUNK_SIZE,
H3_STREAM_POOL_SPARES);
- Curl_hash_offt_init(&ctx->streams, 63, h3_stream_hash_free);
+ Curl_uint_hash_init(&ctx->streams, 63, h3_stream_hash_free);
ctx->data_recvd = 0;
ctx->initialized = TRUE;
}
@@ -142,7 +142,7 @@ static void cf_quiche_ctx_free(struct cf_quiche_ctx *ctx)
Curl_ssl_peer_cleanup(&ctx->peer);
vquic_ctx_free(&ctx->q);
Curl_bufcp_free(&ctx->stream_bufcp);
- Curl_hash_offt_destroy(&ctx->streams);
+ Curl_uint_hash_destroy(&ctx->streams);
}
free(ctx);
}
@@ -165,7 +165,7 @@ static CURLcode cf_flush_egress(struct Curl_cfilter *cf,
/**
* All about the H3 internals of a stream
*/
-struct stream_ctx {
+struct h3_stream_ctx {
curl_uint64_t id; /* HTTP/3 protocol stream identifier */
struct bufq recvbuf; /* h3 response */
struct h1_req_parser h1; /* h1 request parsing */
@@ -179,26 +179,23 @@ struct stream_ctx {
BIT(quic_flow_blocked); /* stream is blocked by QUIC flow control */
};
-#define H3_STREAM_CTX(ctx,data) ((struct stream_ctx *)(\
- data? Curl_hash_offt_get(&(ctx)->streams, (data)->mid) : NULL))
-
-static void h3_stream_ctx_free(struct stream_ctx *stream)
+static void h3_stream_ctx_free(struct h3_stream_ctx *stream)
{
Curl_bufq_free(&stream->recvbuf);
Curl_h1_req_parse_free(&stream->h1);
free(stream);
}
-static void h3_stream_hash_free(curl_off_t id, void *stream)
+static void h3_stream_hash_free(unsigned int id, void *stream)
{
(void)id;
DEBUGASSERT(stream);
- h3_stream_ctx_free((struct stream_ctx *)stream);
+ h3_stream_ctx_free((struct h3_stream_ctx *)stream);
}
typedef bool cf_quiche_svisit(struct Curl_cfilter *cf,
struct Curl_easy *sdata,
- struct stream_ctx *stream,
+ struct h3_stream_ctx *stream,
void *user_data);
struct cf_quiche_visit_ctx {
@@ -208,11 +205,11 @@ struct cf_quiche_visit_ctx {
void *user_data;
};
-static bool cf_quiche_stream_do(curl_off_t mid, void *val, void *user_data)
+static bool cf_quiche_stream_do(unsigned int mid, void *val, void *user_data)
{
struct cf_quiche_visit_ctx *vctx = user_data;
- struct stream_ctx *stream = val;
- struct Curl_easy *sdata = Curl_multi_get_handle(vctx->multi, mid);
+ struct h3_stream_ctx *stream = val;
+ struct Curl_easy *sdata = Curl_multi_get_easy(vctx->multi, mid);
if(sdata)
return vctx->cb(vctx->cf, sdata, stream, vctx->user_data);
return TRUE;
@@ -229,12 +226,12 @@ static void cf_quiche_for_all_streams(struct Curl_cfilter *cf,
vctx.multi = multi;
vctx.cb = do_cb;
vctx.user_data = user_data;
- Curl_hash_offt_visit(&ctx->streams, cf_quiche_stream_do, &vctx);
+ Curl_uint_hash_visit(&ctx->streams, cf_quiche_stream_do, &vctx);
}
static bool cf_quiche_do_resume(struct Curl_cfilter *cf,
struct Curl_easy *sdata,
- struct stream_ctx *stream,
+ struct h3_stream_ctx *stream,
void *user_data)
{
(void)user_data;
@@ -248,7 +245,7 @@ static bool cf_quiche_do_resume(struct Curl_cfilter *cf,
static bool cf_quiche_do_expire(struct Curl_cfilter *cf,
struct Curl_easy *sdata,
- struct stream_ctx *stream,
+ struct h3_stream_ctx *stream,
void *user_data)
{
(void)stream;
@@ -262,7 +259,7 @@ static CURLcode h3_data_setup(struct Curl_cfilter *cf,
struct Curl_easy *data)
{
struct cf_quiche_ctx *ctx = cf->ctx;
- struct stream_ctx *stream = H3_STREAM_CTX(ctx, data);
+ struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data);
if(stream)
return CURLE_OK;
@@ -276,7 +273,7 @@ static CURLcode h3_data_setup(struct Curl_cfilter *cf,
H3_STREAM_RECV_CHUNKS, BUFQ_OPT_SOFT_LIMIT);
Curl_h1_req_parse_init(&stream->h1, H1_PARSE_DEFAULT_MAX_LINE_LEN);
- if(!Curl_hash_offt_set(&ctx->streams, data->mid, stream)) {
+ if(!Curl_uint_hash_set(&ctx->streams, data->mid, stream)) {
h3_stream_ctx_free(stream);
return CURLE_OUT_OF_MEMORY;
}
@@ -287,7 +284,7 @@ static CURLcode h3_data_setup(struct Curl_cfilter *cf,
static void h3_data_done(struct Curl_cfilter *cf, struct Curl_easy *data)
{
struct cf_quiche_ctx *ctx = cf->ctx;
- struct stream_ctx *stream = H3_STREAM_CTX(ctx, data);
+ struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data);
CURLcode result;
(void)cf;
@@ -306,7 +303,7 @@ static void h3_data_done(struct Curl_cfilter *cf, struct Curl_easy *data)
if(result)
CURL_TRC_CF(data, cf, "data_done, flush egress -> %d", result);
}
- Curl_hash_offt_remove(&ctx->streams, data->mid);
+ Curl_uint_hash_remove(&ctx->streams, data->mid);
}
}
@@ -314,7 +311,7 @@ static void h3_drain_stream(struct Curl_cfilter *cf,
struct Curl_easy *data)
{
struct cf_quiche_ctx *ctx = cf->ctx;
- struct stream_ctx *stream = H3_STREAM_CTX(ctx, data);
+ struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data);
unsigned char bits;
(void)cf;
@@ -345,7 +342,7 @@ static CURLcode write_resp_raw(struct Curl_cfilter *cf,
const void *mem, size_t memlen)
{
struct cf_quiche_ctx *ctx = cf->ctx;
- struct stream_ctx *stream = H3_STREAM_CTX(ctx, data);
+ struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data);
CURLcode result = CURLE_OK;
ssize_t nwritten;
@@ -376,7 +373,7 @@ static int cb_each_header(uint8_t *name, size_t name_len,
{
struct cb_ctx *x = argp;
struct cf_quiche_ctx *ctx = x->cf->ctx;
- struct stream_ctx *stream = H3_STREAM_CTX(ctx, x->data);
+ struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, x->data);
CURLcode result;
if(!stream)
@@ -416,7 +413,7 @@ static ssize_t stream_resp_read(void *reader_ctx,
{
struct cb_ctx *x = reader_ctx;
struct cf_quiche_ctx *ctx = x->cf->ctx;
- struct stream_ctx *stream = H3_STREAM_CTX(ctx, x->data);
+ struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, x->data);
ssize_t nread;
if(!stream) {
@@ -440,7 +437,7 @@ static CURLcode cf_recv_body(struct Curl_cfilter *cf,
struct Curl_easy *data)
{
struct cf_quiche_ctx *ctx = cf->ctx;
- struct stream_ctx *stream = H3_STREAM_CTX(ctx, data);
+ struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data);
ssize_t nwritten;
struct cb_ctx cb_ctx;
CURLcode result = CURLE_OK;
@@ -498,7 +495,7 @@ static const char *cf_ev_name(quiche_h3_event *ev)
static CURLcode h3_process_event(struct Curl_cfilter *cf,
struct Curl_easy *data,
- struct stream_ctx *stream,
+ struct h3_stream_ctx *stream,
quiche_h3_event *ev)
{
struct cb_ctx cb_ctx;
@@ -561,7 +558,7 @@ static CURLcode h3_process_event(struct Curl_cfilter *cf,
static CURLcode cf_quiche_ev_process(struct Curl_cfilter *cf,
struct Curl_easy *data,
- struct stream_ctx *stream,
+ struct h3_stream_ctx *stream,
quiche_h3_event *ev)
{
CURLcode result = h3_process_event(cf, data, stream, ev);
@@ -581,13 +578,13 @@ struct cf_quich_disp_ctx {
CURLcode result;
};
-static bool cf_quiche_disp_event(curl_off_t mid, void *val, void *user_data)
+static bool cf_quiche_disp_event(unsigned int mid, void *val, void *user_data)
{
struct cf_quich_disp_ctx *dctx = user_data;
- struct stream_ctx *stream = val;
+ struct h3_stream_ctx *stream = val;
if(stream->id == dctx->stream_id) {
- struct Curl_easy *sdata = Curl_multi_get_handle(dctx->multi, mid);
+ struct Curl_easy *sdata = Curl_multi_get_easy(dctx->multi, mid);
if(sdata)
dctx->result = cf_quiche_ev_process(dctx->cf, sdata, stream, dctx->ev);
return FALSE; /* stop iterating */
@@ -599,7 +596,7 @@ static CURLcode cf_poll_events(struct Curl_cfilter *cf,
struct Curl_easy *data)
{
struct cf_quiche_ctx *ctx = cf->ctx;
- struct stream_ctx *stream = NULL;
+ struct h3_stream_ctx *stream = NULL;
quiche_h3_event *ev;
/* Take in the events and distribute them to the transfers. */
@@ -630,7 +627,7 @@ static CURLcode cf_poll_events(struct Curl_cfilter *cf,
else {
/* another transfer, do not return errors, as they are not for
* the calling transfer */
- Curl_hash_offt_visit(&ctx->streams, cf_quiche_disp_event, &dctx);
+ Curl_uint_hash_visit(&ctx->streams, cf_quiche_disp_event, &dctx);
quiche_h3_event_free(ev);
}
}
@@ -848,7 +845,7 @@ static ssize_t recv_closed_stream(struct Curl_cfilter *cf,
CURLcode *err)
{
struct cf_quiche_ctx *ctx = cf->ctx;
- struct stream_ctx *stream = H3_STREAM_CTX(ctx, data);
+ struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data);
ssize_t nread = -1;
DEBUGASSERT(stream);
@@ -880,7 +877,7 @@ static ssize_t cf_quiche_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
char *buf, size_t len, CURLcode *err)
{
struct cf_quiche_ctx *ctx = cf->ctx;
- struct stream_ctx *stream = H3_STREAM_CTX(ctx, data);
+ struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data);
ssize_t nread = -1;
CURLcode result;
@@ -953,7 +950,7 @@ out:
static ssize_t cf_quiche_send_body(struct Curl_cfilter *cf,
struct Curl_easy *data,
- struct stream_ctx *stream,
+ struct h3_stream_ctx *stream,
const void *buf, size_t len, bool eos,
CURLcode *err)
{
@@ -1012,7 +1009,7 @@ static ssize_t h3_open_stream(struct Curl_cfilter *cf,
CURLcode *err)
{
struct cf_quiche_ctx *ctx = cf->ctx;
- struct stream_ctx *stream = H3_STREAM_CTX(ctx, data);
+ struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data);
size_t nheader, i;
curl_int64_t stream3_id;
struct dynhds h2_headers;
@@ -1132,7 +1129,7 @@ static ssize_t cf_quiche_send(struct Curl_cfilter *cf, struct Curl_easy *data,
CURLcode *err)
{
struct cf_quiche_ctx *ctx = cf->ctx;
- struct stream_ctx *stream = H3_STREAM_CTX(ctx, data);
+ struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data);
CURLcode result;
ssize_t nwritten;
@@ -1191,7 +1188,7 @@ static bool stream_is_writeable(struct Curl_cfilter *cf,
struct Curl_easy *data)
{
struct cf_quiche_ctx *ctx = cf->ctx;
- struct stream_ctx *stream = H3_STREAM_CTX(ctx, data);
+ struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data);
return stream && (quiche_conn_stream_writable(
ctx->qconn, (curl_uint64_t)stream->id, 1) > 0);
@@ -1209,7 +1206,7 @@ static void cf_quiche_adjust_pollset(struct Curl_cfilter *cf,
Curl_pollset_check(data, ps, ctx->q.sockfd, &want_recv, &want_send);
if(want_recv || want_send) {
- struct stream_ctx *stream = H3_STREAM_CTX(ctx, data);
+ struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data);
bool c_exhaust, s_exhaust;
c_exhaust = FALSE; /* Have not found any call in quiche that tells
@@ -1232,7 +1229,7 @@ static bool cf_quiche_data_pending(struct Curl_cfilter *cf,
const struct Curl_easy *data)
{
struct cf_quiche_ctx *ctx = cf->ctx;
- const struct stream_ctx *stream = H3_STREAM_CTX(ctx, data);
+ const struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data);
(void)cf;
return stream && !Curl_bufq_is_empty(&stream->recvbuf);
}
@@ -1269,7 +1266,7 @@ static CURLcode cf_quiche_data_event(struct Curl_cfilter *cf,
h3_data_done(cf, data);
break;
case CF_CTRL_DATA_DONE_SEND: {
- struct stream_ctx *stream = H3_STREAM_CTX(ctx, data);
+ struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data);
if(stream && !stream->send_closed) {
unsigned char body[1];
ssize_t sent;
@@ -1283,7 +1280,7 @@ static CURLcode cf_quiche_data_event(struct Curl_cfilter *cf,
break;
}
case CF_CTRL_DATA_IDLE: {
- struct stream_ctx *stream = H3_STREAM_CTX(ctx, data);
+ struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data);
if(stream && !stream->closed) {
result = cf_flush_egress(cf, data);
if(result)
@@ -1321,7 +1318,6 @@ static const struct alpn_spec ALPN_SPEC_H3 = {
return CURLE_FAILED_INIT;
}
quiche_config_enable_pacing(ctx->cfg, FALSE);
- quiche_config_set_max_idle_timeout(ctx->cfg, CURL_QUIC_MAX_IDLE_MS);
quiche_config_set_initial_max_data(ctx->cfg, (1 * 1024 * 1024)
/* (QUIC_MAX_STREAMS/2) * H3_STREAM_WINDOW_SIZE */);
quiche_config_set_initial_max_streams_bidi(ctx->cfg, QUIC_MAX_STREAMS);
@@ -1456,7 +1452,7 @@ static CURLcode cf_quiche_connect(struct Curl_cfilter *cf,
if(quiche_conn_is_established(ctx->qconn)) {
ctx->handshake_at = ctx->q.last_op;
CURL_TRC_CF(data, cf, "handshake complete after %dms",
- (int)Curl_timediff(ctx->handshake_at, ctx->started_at));
+ (int)curlx_timediff(ctx->handshake_at, ctx->started_at));
result = cf_quiche_verify_peer(cf, data);
if(!result) {
CURL_TRC_CF(data, cf, "peer verified");
@@ -1572,19 +1568,19 @@ static CURLcode cf_quiche_query(struct Curl_cfilter *cf,
switch(query) {
case CF_QUERY_MAX_CONCURRENT: {
- curl_uint64_t max_streams = CONN_INUSE(cf->conn);
+ curl_uint64_t max_streams = CONN_ATTACHED(cf->conn);
if(!ctx->goaway) {
max_streams += quiche_conn_peer_streams_left_bidi(ctx->qconn);
}
*pres1 = (max_streams > INT_MAX) ? INT_MAX : (int)max_streams;
CURL_TRC_CF(data, cf, "query conn[%" FMT_OFF_T "]: "
- "MAX_CONCURRENT -> %d (%zu in use)",
- cf->conn->connection_id, *pres1, CONN_INUSE(cf->conn));
+ "MAX_CONCURRENT -> %d (%u in use)",
+ cf->conn->connection_id, *pres1, CONN_ATTACHED(cf->conn));
return CURLE_OK;
}
case CF_QUERY_CONNECT_REPLY_MS:
if(ctx->q.got_first_byte) {
- timediff_t ms = Curl_timediff(ctx->q.first_byte_at, ctx->started_at);
+ timediff_t ms = curlx_timediff(ctx->q.first_byte_at, ctx->started_at);
*pres1 = (ms < INT_MAX) ? (int)ms : INT_MAX;
}
else
diff --git a/libs/libcurl/src/vquic/curl_quiche.h b/libs/libcurl/src/vquic/curl_quiche.h
index 6af88dd479..caf21e0137 100644
--- a/libs/libcurl/src/vquic/curl_quiche.h
+++ b/libs/libcurl/src/vquic/curl_quiche.h
@@ -24,7 +24,7 @@
*
***************************************************************************/
-#include "curl_setup.h"
+#include "../curl_setup.h"
#ifdef USE_QUICHE
diff --git a/libs/libcurl/src/vquic/vquic-tls.c b/libs/libcurl/src/vquic/vquic-tls.c
index feae0f594a..7eb343538e 100644
--- a/libs/libcurl/src/vquic/vquic-tls.c
+++ b/libs/libcurl/src/vquic/vquic-tls.c
@@ -22,41 +22,41 @@
*
***************************************************************************/
-#include "curl_setup.h"
+#include "../curl_setup.h"
#if defined(USE_HTTP3) && \
(defined(USE_OPENSSL) || defined(USE_GNUTLS) || defined(USE_WOLFSSL))
#ifdef USE_OPENSSL
#include <openssl/err.h>
-#include "vtls/openssl.h"
+#include "../vtls/openssl.h"
#elif defined(USE_GNUTLS)
#include <gnutls/abstract.h>
#include <gnutls/gnutls.h>
#include <gnutls/x509.h>
#include <gnutls/crypto.h>
#include <nettle/sha2.h>
-#include "vtls/gtls.h"
+#include "../vtls/gtls.h"
#elif defined(USE_WOLFSSL)
#include <wolfssl/options.h>
#include <wolfssl/ssl.h>
#include <wolfssl/quic.h>
-#include "vtls/wolfssl.h"
+#include "../vtls/wolfssl.h"
#endif
-#include "urldata.h"
-#include "curl_trc.h"
-#include "cfilters.h"
-#include "multiif.h"
-#include "vtls/keylog.h"
-#include "vtls/vtls.h"
-#include "vtls/vtls_scache.h"
+#include "../urldata.h"
+#include "../curl_trc.h"
+#include "../cfilters.h"
+#include "../multiif.h"
+#include "../vtls/keylog.h"
+#include "../vtls/vtls.h"
+#include "../vtls/vtls_scache.h"
#include "vquic-tls.h"
/* The last 3 #include files should be in this order */
-#include "curl_printf.h"
-#include "curl_memory.h"
-#include "memdebug.h"
+#include "../curl_printf.h"
+#include "../curl_memory.h"
+#include "../memdebug.h"
CURLcode Curl_vquic_tls_init(struct curl_tls_ctx *ctx,
struct Curl_cfilter *cf,
@@ -179,16 +179,16 @@ CURLcode Curl_vquic_tls_verify_peer(struct curl_tls_ctx *ctx,
#elif defined(USE_WOLFSSL)
(void)data;
if(conn_config->verifyhost) {
- if(peer->sni) {
- WOLFSSL_X509* cert = wolfSSL_get_peer_certificate(ctx->wssl.ssl);
- if(wolfSSL_X509_check_host(cert, peer->sni, strlen(peer->sni), 0, NULL)
- == WOLFSSL_FAILURE) {
- result = CURLE_PEER_FAILED_VERIFICATION;
- }
- wolfSSL_X509_free(cert);
+ char *snihost = peer->sni ? peer->sni : peer->hostname;
+ WOLFSSL_X509* cert = wolfSSL_get_peer_certificate(ctx->wssl.ssl);
+ if(wolfSSL_X509_check_host(cert, snihost, strlen(snihost), 0, NULL)
+ == WOLFSSL_FAILURE) {
+ result = CURLE_PEER_FAILED_VERIFICATION;
}
-
+ wolfSSL_X509_free(cert);
}
+ if(!result)
+ result = Curl_wssl_verify_pinned(cf, data, &ctx->wssl);
#endif
/* on error, remove any session we might have in the pool */
if(result)
diff --git a/libs/libcurl/src/vquic/vquic-tls.h b/libs/libcurl/src/vquic/vquic-tls.h
index 7bc24819d8..0b9a1ec4f7 100644
--- a/libs/libcurl/src/vquic/vquic-tls.h
+++ b/libs/libcurl/src/vquic/vquic-tls.h
@@ -24,16 +24,16 @@
*
***************************************************************************/
-#include "curl_setup.h"
-#include "bufq.h"
-#include "vtls/vtls.h"
-#include "vtls/vtls_int.h"
-#include "vtls/openssl.h"
+#include "../curl_setup.h"
+#include "../bufq.h"
+#include "../vtls/vtls.h"
+#include "../vtls/vtls_int.h"
+#include "../vtls/openssl.h"
#if defined(USE_HTTP3) && \
(defined(USE_OPENSSL) || defined(USE_GNUTLS) || defined(USE_WOLFSSL))
-#include "vtls/wolfssl.h"
+#include "../vtls/wolfssl.h"
struct ssl_peer;
struct Curl_ssl_session;
diff --git a/libs/libcurl/src/vquic/vquic.c b/libs/libcurl/src/vquic/vquic.c
index f24c9dc799..4b7ab97c5b 100644
--- a/libs/libcurl/src/vquic/vquic.c
+++ b/libs/libcurl/src/vquic/vquic.c
@@ -22,7 +22,7 @@
*
***************************************************************************/
-#include "curl_setup.h"
+#include "../curl_setup.h"
#ifdef HAVE_NETINET_UDP_H
#include <netinet/udp.h>
@@ -30,26 +30,26 @@
#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#endif
-#include "urldata.h"
-#include "bufq.h"
-#include "dynbuf.h"
-#include "cfilters.h"
-#include "curl_trc.h"
+#include "../urldata.h"
+#include "../bufq.h"
+#include "../curlx/dynbuf.h"
+#include "../cfilters.h"
+#include "../curl_trc.h"
#include "curl_msh3.h"
#include "curl_ngtcp2.h"
#include "curl_osslq.h"
#include "curl_quiche.h"
-#include "multiif.h"
-#include "rand.h"
+#include "../multiif.h"
+#include "../rand.h"
#include "vquic.h"
#include "vquic_int.h"
-#include "strerror.h"
-#include "strparse.h"
+#include "../strerror.h"
+#include "../curlx/strparse.h"
/* The last 3 #include files should be in this order */
-#include "curl_printf.h"
-#include "curl_memory.h"
-#include "memdebug.h"
+#include "../curl_printf.h"
+#include "../curl_memory.h"
+#include "../memdebug.h"
#ifdef USE_HTTP3
@@ -58,6 +58,16 @@
#define NW_SEND_CHUNKS 2
+int Curl_vquic_init(void)
+{
+#if defined(USE_NGTCP2) && defined(OPENSSL_QUIC_API2)
+ if(ngtcp2_crypto_ossl_init())
+ return 0;
+#endif
+
+ return 1;
+}
+
void Curl_quic_ver(char *p, size_t len)
{
#if defined(USE_NGTCP2) && defined(USE_NGHTTP3)
@@ -85,7 +95,7 @@ CURLcode vquic_ctx_init(struct cf_quic_ctx *qctx)
const char *p = getenv("CURL_DBG_QUIC_WBLOCK");
if(p) {
curl_off_t l;
- if(!Curl_str_number(&p, &l, 100))
+ if(!curlx_str_number(&p, &l, 100))
qctx->wblock_percent = (int)l;
}
}
@@ -102,7 +112,7 @@ void vquic_ctx_free(struct cf_quic_ctx *qctx)
void vquic_ctx_update_time(struct cf_quic_ctx *qctx)
{
- qctx->last_op = Curl_now();
+ qctx->last_op = curlx_now();
}
static CURLcode send_packet_no_gso(struct Curl_cfilter *cf,
@@ -471,19 +481,20 @@ static CURLcode recvmsg_packets(struct Curl_cfilter *cf,
size_t pktlen;
size_t offset, to;
- msg_iov.iov_base = buf;
- msg_iov.iov_len = (int)sizeof(buf);
-
- memset(&msg, 0, sizeof(msg));
- msg.msg_iov = &msg_iov;
- msg.msg_iovlen = 1;
- msg.msg_control = msg_ctrl;
-
DEBUGASSERT(max_pkts > 0);
for(pkts = 0, total_nread = 0; pkts < max_pkts;) {
+ /* fully initialise this on each call to `recvmsg()`. There seem to
+ * operating systems out there that mess with `msg_iov.iov_len`. */
+ memset(&msg, 0, sizeof(msg));
+ msg_iov.iov_base = buf;
+ msg_iov.iov_len = (int)sizeof(buf);
+ msg.msg_iov = &msg_iov;
+ msg.msg_iovlen = 1;
+ msg.msg_control = msg_ctrl;
msg.msg_name = &remote_addr;
msg.msg_namelen = sizeof(remote_addr);
msg.msg_controllen = sizeof(msg_ctrl);
+
while((nread = recvmsg(qctx->sockfd, &msg, 0)) == -1 &&
SOCKERRNO == SOCKEINTR)
;
@@ -640,25 +651,25 @@ CURLcode Curl_qlogdir(struct Curl_easy *data,
struct dynbuf fname;
CURLcode result;
unsigned int i;
- Curl_dyn_init(&fname, DYN_QLOG_NAME);
- result = Curl_dyn_add(&fname, qlog_dir);
+ curlx_dyn_init(&fname, DYN_QLOG_NAME);
+ result = curlx_dyn_add(&fname, qlog_dir);
if(!result)
- result = Curl_dyn_add(&fname, "/");
+ result = curlx_dyn_add(&fname, "/");
for(i = 0; (i < scidlen) && !result; i++) {
char hex[3];
msnprintf(hex, 3, "%02x", scid[i]);
- result = Curl_dyn_add(&fname, hex);
+ result = curlx_dyn_add(&fname, hex);
}
if(!result)
- result = Curl_dyn_add(&fname, ".sqlog");
+ result = curlx_dyn_add(&fname, ".sqlog");
if(!result) {
- int qlogfd = open(Curl_dyn_ptr(&fname), O_WRONLY|O_CREAT|CURL_O_BINARY,
+ int qlogfd = open(curlx_dyn_ptr(&fname), O_WRONLY|O_CREAT|CURL_O_BINARY,
data->set.new_file_perms);
if(qlogfd != -1)
*qlogfdp = qlogfd;
}
- Curl_dyn_free(&fname);
+ curlx_dyn_free(&fname);
if(result)
return result;
}
diff --git a/libs/libcurl/src/vquic/vquic.h b/libs/libcurl/src/vquic/vquic.h
index 8d7474fbdc..0534d49286 100644
--- a/libs/libcurl/src/vquic/vquic.h
+++ b/libs/libcurl/src/vquic/vquic.h
@@ -24,7 +24,7 @@
*
***************************************************************************/
-#include "curl_setup.h"
+#include "../curl_setup.h"
#ifdef USE_HTTP3
struct Curl_cfilter;
@@ -33,6 +33,7 @@ struct connectdata;
struct Curl_addrinfo;
void Curl_quic_ver(char *p, size_t len);
+int Curl_vquic_init(void);
CURLcode Curl_qlogdir(struct Curl_easy *data,
unsigned char *scid,
@@ -48,6 +49,8 @@ CURLcode Curl_cf_quic_create(struct Curl_cfilter **pcf,
extern struct Curl_cftype Curl_cft_http3;
+#else
+#define Curl_vquic_init() 1
#endif /* !USE_HTTP3 */
CURLcode Curl_conn_may_http3(struct Curl_easy *data,
diff --git a/libs/libcurl/src/vquic/vquic_int.h b/libs/libcurl/src/vquic/vquic_int.h
index 52203735bf..75dfd33d26 100644
--- a/libs/libcurl/src/vquic/vquic_int.h
+++ b/libs/libcurl/src/vquic/vquic_int.h
@@ -24,15 +24,13 @@
*
***************************************************************************/
-#include "curl_setup.h"
-#include "bufq.h"
+#include "../curl_setup.h"
+#include "../bufq.h"
#ifdef USE_HTTP3
#define MAX_PKT_BURST 10
#define MAX_UDP_PAYLOAD_SIZE 1452
-/* Default QUIC connection timeout we announce from our side */
-#define CURL_QUIC_MAX_IDLE_MS (120 * 1000)
struct cf_quic_ctx {
curl_socket_t sockfd; /* connected UDP socket */
@@ -53,6 +51,9 @@ struct cf_quic_ctx {
BIT(no_gso); /* do not use gso on sending */
};
+#define H3_STREAM_CTX(ctx,data) \
+ (data ? Curl_uint_hash_get(&(ctx)->streams, (data)->mid) : NULL)
+
CURLcode vquic_ctx_init(struct cf_quic_ctx *qctx);
void vquic_ctx_free(struct cf_quic_ctx *qctx);
diff --git a/libs/libcurl/src/vssh/curl_path.c b/libs/libcurl/src/vssh/curl_path.c
index 7cf09022e0..f6837e7c9a 100644
--- a/libs/libcurl/src/vssh/curl_path.c
+++ b/libs/libcurl/src/vssh/curl_path.c
@@ -22,15 +22,15 @@
*
***************************************************************************/
-#include "curl_setup.h"
+#include "../curl_setup.h"
#if defined(USE_SSH)
#include "curl_path.h"
#include <curl/curl.h>
-#include "curl_memory.h"
-#include "escape.h"
-#include "memdebug.h"
+#include "../curl_memory.h"
+#include "../escape.h"
+#include "../memdebug.h"
#define MAX_SSHPATH_LEN 100000 /* arbitrary */
@@ -50,13 +50,13 @@ CURLcode Curl_getworkingpath(struct Curl_easy *data,
return result;
/* new path to switch to in case we need to */
- Curl_dyn_init(&npath, MAX_SSHPATH_LEN);
+ curlx_dyn_init(&npath, MAX_SSHPATH_LEN);
/* Check for /~/, indicating relative to the user's home directory */
if((data->conn->handler->protocol & CURLPROTO_SCP) &&
(working_path_len > 3) && (!memcmp(working_path, "/~/", 3))) {
/* It is referenced to the home directory, so strip the leading '/~/' */
- if(Curl_dyn_addn(&npath, &working_path[3], working_path_len - 3)) {
+ if(curlx_dyn_addn(&npath, &working_path[3], working_path_len - 3)) {
free(working_path);
return CURLE_OUT_OF_MEMORY;
}
@@ -64,7 +64,7 @@ CURLcode Curl_getworkingpath(struct Curl_easy *data,
else if((data->conn->handler->protocol & CURLPROTO_SFTP) &&
(!strcmp("/~", working_path) ||
((working_path_len > 2) && !memcmp(working_path, "/~/", 3)))) {
- if(Curl_dyn_add(&npath, homedir)) {
+ if(curlx_dyn_add(&npath, homedir)) {
free(working_path);
return CURLE_OUT_OF_MEMORY;
}
@@ -73,24 +73,24 @@ CURLcode Curl_getworkingpath(struct Curl_easy *data,
const char *p;
int copyfrom = 3;
/* Copy a separating '/' if homedir does not end with one */
- len = Curl_dyn_len(&npath);
- p = Curl_dyn_ptr(&npath);
+ len = curlx_dyn_len(&npath);
+ p = curlx_dyn_ptr(&npath);
if(len && (p[len-1] != '/'))
copyfrom = 2;
- if(Curl_dyn_addn(&npath,
- &working_path[copyfrom], working_path_len - copyfrom)) {
+ if(curlx_dyn_addn(&npath, &working_path[copyfrom],
+ working_path_len - copyfrom)) {
free(working_path);
return CURLE_OUT_OF_MEMORY;
}
}
}
- if(Curl_dyn_len(&npath)) {
+ if(curlx_dyn_len(&npath)) {
free(working_path);
/* store the pointer for the caller to receive */
- *path = Curl_dyn_ptr(&npath);
+ *path = curlx_dyn_ptr(&npath);
}
else
*path = working_path;
@@ -133,7 +133,7 @@ CURLcode Curl_get_pathname(const char **cpp, char **path, const char *homedir)
if(!*cp || !homedir)
return CURLE_QUOTE_ERROR;
- Curl_dyn_init(&out, MAX_PATHLENGTH);
+ curlx_dyn_init(&out, MAX_PATHLENGTH);
/* Ignore leading whitespace */
cp += strspn(cp, WHITESPACE);
@@ -158,12 +158,12 @@ CURLcode Curl_get_pathname(const char **cpp, char **path, const char *homedir)
goto fail;
}
}
- result = Curl_dyn_addn(&out, &cp[i], 1);
+ result = curlx_dyn_addn(&out, &cp[i], 1);
if(result)
return result;
}
- if(!Curl_dyn_len(&out))
+ if(!curlx_dyn_len(&out))
goto fail;
/* return pointer to second parameter if it exists */
@@ -180,23 +180,23 @@ CURLcode Curl_get_pathname(const char **cpp, char **path, const char *homedir)
/* Handling for relative path - prepend home directory */
if(cp[0] == '/' && cp[1] == '~' && cp[2] == '/') {
- result = Curl_dyn_add(&out, homedir);
+ result = curlx_dyn_add(&out, homedir);
if(!result)
- result = Curl_dyn_addn(&out, "/", 1);
+ result = curlx_dyn_addn(&out, "/", 1);
if(result)
return result;
cp += 3;
}
/* Copy path name up until first "whitespace" */
- result = Curl_dyn_addn(&out, cp, (end - cp));
+ result = curlx_dyn_addn(&out, cp, (end - cp));
if(result)
return result;
}
- *path = Curl_dyn_ptr(&out);
+ *path = curlx_dyn_ptr(&out);
return CURLE_OK;
fail:
- Curl_dyn_free(&out);
+ curlx_dyn_free(&out);
return CURLE_QUOTE_ERROR;
}
diff --git a/libs/libcurl/src/vssh/curl_path.h b/libs/libcurl/src/vssh/curl_path.h
index 4bac618e13..93c98bde95 100644
--- a/libs/libcurl/src/vssh/curl_path.h
+++ b/libs/libcurl/src/vssh/curl_path.h
@@ -24,9 +24,9 @@
*
***************************************************************************/
-#include "curl_setup.h"
+#include "../curl_setup.h"
#include <curl/curl.h>
-#include "urldata.h"
+#include "../urldata.h"
CURLcode Curl_getworkingpath(struct Curl_easy *data,
char *homedir,
diff --git a/libs/libcurl/src/vssh/libssh.c b/libs/libcurl/src/vssh/libssh.c
index cb98738fc3..569aa1a996 100644
--- a/libs/libcurl/src/vssh/libssh.c
+++ b/libs/libcurl/src/vssh/libssh.c
@@ -25,7 +25,7 @@
*
***************************************************************************/
-#include "curl_setup.h"
+#include "../curl_setup.h"
#ifdef USE_LIBSSH
@@ -46,29 +46,29 @@
#endif
#include <curl/curl.h>
-#include "urldata.h"
-#include "sendf.h"
-#include "hostip.h"
-#include "progress.h"
-#include "transfer.h"
-#include "escape.h"
-#include "http.h" /* for HTTP proxy tunnel stuff */
+#include "../urldata.h"
+#include "../sendf.h"
+#include "../hostip.h"
+#include "../progress.h"
+#include "../transfer.h"
+#include "../escape.h"
+#include "../http.h" /* for HTTP proxy tunnel stuff */
#include "ssh.h"
-#include "url.h"
-#include "speedcheck.h"
-#include "getinfo.h"
-#include "strdup.h"
-#include "strcase.h"
-#include "vtls/vtls.h"
-#include "cfilters.h"
-#include "connect.h"
-#include "inet_ntop.h"
-#include "parsedate.h" /* for the week day and month names */
-#include "sockaddr.h" /* required for Curl_sockaddr_storage */
-#include "strparse.h"
-#include "multiif.h"
-#include "select.h"
-#include "warnless.h"
+#include "../url.h"
+#include "../speedcheck.h"
+#include "../getinfo.h"
+#include "../strdup.h"
+#include "../strcase.h"
+#include "../vtls/vtls.h"
+#include "../cfilters.h"
+#include "../connect.h"
+#include "../inet_ntop.h"
+#include "../parsedate.h" /* for the week day and month names */
+#include "../sockaddr.h" /* required for Curl_sockaddr_storage */
+#include "../curlx/strparse.h"
+#include "../multiif.h"
+#include "../select.h"
+#include "../curlx/warnless.h"
#include "curl_path.h"
#ifdef HAVE_SYS_STAT_H
@@ -82,9 +82,9 @@
#endif
/* The last 3 #include files should be in this order */
-#include "curl_printf.h"
-#include "curl_memory.h"
-#include "memdebug.h"
+#include "../curl_printf.h"
+#include "../curl_memory.h"
+#include "../memdebug.h"
/* A recent macro provided by libssh. Or make our own. */
#ifndef SSH_STRING_FREE_CHAR
@@ -130,15 +130,19 @@ CURLcode sftp_perform(struct Curl_easy *data,
bool *connected,
bool *dophase_done);
-static void sftp_quote(struct Curl_easy *data);
-static void sftp_quote_stat(struct Curl_easy *data);
+static void sftp_quote(struct Curl_easy *data,
+ struct ssh_conn *sshc,
+ struct SSHPROTO *sshp);
+static void sftp_quote_stat(struct Curl_easy *data, struct ssh_conn *sshc);
static int myssh_getsock(struct Curl_easy *data,
struct connectdata *conn, curl_socket_t *sock);
-static void myssh_block2waitfor(struct connectdata *conn, bool block);
+static void myssh_block2waitfor(struct connectdata *conn,
+ struct ssh_conn *sshc,
+ bool block);
static CURLcode myssh_setup_connection(struct Curl_easy *data,
struct connectdata *conn);
-static void sshc_cleanup(struct ssh_conn *sshc, struct Curl_easy *data);
+static void sshc_cleanup(struct ssh_conn *sshc);
/*
* SCP protocol handler.
@@ -224,23 +228,23 @@ static CURLcode sftp_error_to_CURLE(int err)
}
#ifndef DEBUGBUILD
-#define state(x,y) mystate(x,y)
+#define myssh_state(x,y,z) myssh_set_state(x,y,z)
#else
-#define state(x,y) mystate(x,y, __LINE__)
+#define myssh_state(x,y,z) myssh_set_state(x,y,z, __LINE__)
#endif
/*
* SSH State machine related code
*/
/* This is the ONLY way to change SSH state! */
-static void mystate(struct Curl_easy *data, sshstate nowstate
+static void myssh_set_state(struct Curl_easy *data,
+ struct ssh_conn *sshc,
+ sshstate nowstate
#ifdef DEBUGBUILD
- , int lineno
+ , int lineno
#endif
)
{
- struct connectdata *conn = data->conn;
- struct ssh_conn *sshc = &conn->proto.sshc;
#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
/* for debug purposes */
static const char *const names[] = {
@@ -313,7 +317,7 @@ static void mystate(struct Curl_easy *data, sshstate nowstate
lineno);
}
#endif
-
+ (void)data;
sshc->state = nowstate;
}
@@ -327,11 +331,9 @@ static void mystate(struct Curl_easy *data, sshstate nowstate
*
* Returns SSH_OK or SSH_ERROR.
*/
-static int myssh_is_known(struct Curl_easy *data)
+static int myssh_is_known(struct Curl_easy *data, struct ssh_conn *sshc)
{
int rc;
- struct connectdata *conn = data->conn;
- struct ssh_conn *sshc = &conn->proto.sshc;
ssh_key pubkey;
size_t hlen;
unsigned char *hash = NULL;
@@ -517,14 +519,14 @@ cleanup:
return rc;
}
-#define MOVE_TO_ERROR_STATE(_r) do { \
- state(data, SSH_SESSION_DISCONNECT); \
- sshc->actualcode = _r; \
- rc = SSH_ERROR; \
+#define MOVE_TO_ERROR_STATE(_r) do { \
+ myssh_state(data, sshc, SSH_SESSION_DISCONNECT); \
+ sshc->actualcode = _r; \
+ rc = SSH_ERROR; \
} while(0)
#define MOVE_TO_SFTP_CLOSE_STATE() do { \
- state(data, SSH_SFTP_CLOSE); \
+ myssh_state(data, sshc, SSH_SFTP_CLOSE); \
sshc->actualcode = \
sftp_error_to_CURLE(sftp_get_error(sshc->sftp_session)); \
rc = SSH_ERROR; \
@@ -533,7 +535,7 @@ cleanup:
#define MOVE_TO_PASSWD_AUTH do { \
if(sshc->auth_methods & SSH_AUTH_METHOD_PASSWORD) { \
rc = SSH_OK; \
- state(data, SSH_AUTH_PASS_INIT); \
+ myssh_state(data, sshc, SSH_AUTH_PASS_INIT); \
} \
else { \
MOVE_TO_ERROR_STATE(CURLE_LOGIN_DENIED); \
@@ -543,7 +545,7 @@ cleanup:
#define MOVE_TO_KEY_AUTH do { \
if(sshc->auth_methods & SSH_AUTH_METHOD_INTERACTIVE) { \
rc = SSH_OK; \
- state(data, SSH_AUTH_KEY_INIT); \
+ myssh_state(data, sshc, SSH_AUTH_KEY_INIT); \
} \
else { \
MOVE_TO_PASSWD_AUTH; \
@@ -553,7 +555,7 @@ cleanup:
#define MOVE_TO_GSSAPI_AUTH do { \
if(sshc->auth_methods & SSH_AUTH_METHOD_GSSAPI_MIC) { \
rc = SSH_OK; \
- state(data, SSH_AUTH_GSSAPI); \
+ myssh_state(data, sshc, SSH_AUTH_GSSAPI); \
} \
else { \
MOVE_TO_KEY_AUTH; \
@@ -561,10 +563,10 @@ cleanup:
} while(0)
static
-int myssh_auth_interactive(struct connectdata *conn)
+int myssh_auth_interactive(struct connectdata *conn,
+ struct ssh_conn *sshc)
{
int rc;
- struct ssh_conn *sshc = &conn->proto.sshc;
int nprompts;
restart:
@@ -625,178 +627,493 @@ restart:
return rc;
}
-/*
- * ssh_statemach_act() runs the SSH state machine as far as it can without
- * blocking and without reaching the end. The data the pointer 'block' points
- * to will be set to TRUE if the libssh function returns SSH_AGAIN
- * meaning it wants to be called again when the socket is ready
- */
-static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
+static void myssh_state_init(struct Curl_easy *data,
+ struct ssh_conn *sshc)
{
- CURLcode result = CURLE_OK;
- struct connectdata *conn = data->conn;
- struct SSHPROTO *protop = data->req.p.ssh;
- struct ssh_conn *sshc = &conn->proto.sshc;
- curl_socket_t sock = conn->sock[FIRSTSOCKET];
- int rc = SSH_NO_ERROR, err;
- int seekerr = CURL_SEEKFUNC_OK;
- const char *err_msg;
- *block = 0; /* we are not blocking by default */
-
- do {
-
- switch(sshc->state) {
- case SSH_INIT:
- sshc->secondCreateDirs = 0;
- sshc->nextstate = SSH_NO_STATE;
- sshc->actualcode = CURLE_OK;
+ sshc->secondCreateDirs = 0;
+ sshc->nextstate = SSH_NO_STATE;
+ sshc->actualcode = CURLE_OK;
#if 0
- ssh_set_log_level(SSH_LOG_PROTOCOL);
+ ssh_set_log_level(SSH_LOG_PROTOCOL);
#endif
- /* Set libssh to non-blocking, since everything internally is
- non-blocking */
- ssh_set_blocking(sshc->ssh_session, 0);
+ /* Set libssh to non-blocking, since everything internally is
+ non-blocking */
+ ssh_set_blocking(sshc->ssh_session, 0);
- state(data, SSH_S_STARTUP);
- FALLTHROUGH();
+ myssh_state(data, sshc, SSH_S_STARTUP);
+}
- case SSH_S_STARTUP:
- rc = ssh_connect(sshc->ssh_session);
+static int myssh_state_startup(struct Curl_easy *data,
+ struct ssh_conn *sshc)
+{
+ struct connectdata *conn = data->conn;
+ int rc = ssh_connect(sshc->ssh_session);
- myssh_block2waitfor(conn, (rc == SSH_AGAIN));
- if(rc == SSH_AGAIN) {
- DEBUGF(infof(data, "ssh_connect -> EAGAIN"));
- break;
- }
+ myssh_block2waitfor(conn, sshc, (rc == SSH_AGAIN));
+ if(rc == SSH_AGAIN) {
+ DEBUGF(infof(data, "ssh_connect -> EAGAIN"));
+ }
+ else if(rc != SSH_OK) {
+ failf(data, "Failure establishing ssh session");
+ MOVE_TO_ERROR_STATE(CURLE_FAILED_INIT);
+ }
+ else
+ myssh_state(data, sshc, SSH_HOSTKEY);
- if(rc != SSH_OK) {
- failf(data, "Failure establishing ssh session");
- MOVE_TO_ERROR_STATE(CURLE_FAILED_INIT);
- break;
- }
+ return rc;
+}
- state(data, SSH_HOSTKEY);
+static int myssh_state_authlist(struct Curl_easy *data,
+ struct ssh_conn *sshc)
+{
+ int rc;
+ sshc->authed = FALSE;
- FALLTHROUGH();
- case SSH_HOSTKEY:
+ rc = ssh_userauth_none(sshc->ssh_session, NULL);
+ if(rc == SSH_AUTH_AGAIN)
+ return SSH_AGAIN;
+
+ if(rc == SSH_AUTH_SUCCESS) {
+ sshc->authed = TRUE;
+ infof(data, "Authenticated with none");
+ myssh_state(data, sshc, SSH_AUTH_DONE);
+ return rc;
+ }
+ else if(rc == SSH_AUTH_ERROR) {
+ MOVE_TO_ERROR_STATE(CURLE_LOGIN_DENIED);
+ return rc;
+ }
+
+ sshc->auth_methods =
+ (unsigned int)ssh_userauth_list(sshc->ssh_session, NULL);
+ if(sshc->auth_methods)
+ infof(data, "SSH authentication methods available: %s%s%s%s",
+ sshc->auth_methods & SSH_AUTH_METHOD_PUBLICKEY ?
+ "public key, ": "",
+ sshc->auth_methods & SSH_AUTH_METHOD_GSSAPI_MIC ?
+ "GSSAPI, " : "",
+ sshc->auth_methods & SSH_AUTH_METHOD_INTERACTIVE ?
+ "keyboard-interactive, " : "",
+ sshc->auth_methods & SSH_AUTH_METHOD_PASSWORD ?
+ "password": "");
+ if(sshc->auth_methods & SSH_AUTH_METHOD_PUBLICKEY) {
+ myssh_state(data, sshc, SSH_AUTH_PKEY_INIT);
+ infof(data, "Authentication using SSH public key file");
+ }
+ else if(sshc->auth_methods & SSH_AUTH_METHOD_GSSAPI_MIC) {
+ myssh_state(data, sshc, SSH_AUTH_GSSAPI);
+ }
+ else if(sshc->auth_methods & SSH_AUTH_METHOD_INTERACTIVE) {
+ myssh_state(data, sshc, SSH_AUTH_KEY_INIT);
+ }
+ else if(sshc->auth_methods & SSH_AUTH_METHOD_PASSWORD) {
+ myssh_state(data, sshc, SSH_AUTH_PASS_INIT);
+ }
+ else { /* unsupported authentication method */
+ MOVE_TO_ERROR_STATE(CURLE_LOGIN_DENIED);
+ }
+ return rc;
+}
+
+static int myssh_state_auth_pkey_init(struct Curl_easy *data,
+ struct ssh_conn *sshc)
+{
+ int rc;
+ if(!(data->set.ssh_auth_types & CURLSSH_AUTH_PUBLICKEY)) {
+ MOVE_TO_GSSAPI_AUTH;
+ return 0;
+ }
+
+ /* Two choices, (1) private key was given on CMD,
+ * (2) use the "default" keys. */
+ if(data->set.str[STRING_SSH_PRIVATE_KEY]) {
+ if(sshc->pubkey && !data->set.ssl.key_passwd) {
+ rc = ssh_userauth_try_publickey(sshc->ssh_session, NULL,
+ sshc->pubkey);
+ if(rc == SSH_AUTH_AGAIN)
+ return SSH_AGAIN;
- rc = myssh_is_known(data);
if(rc != SSH_OK) {
- MOVE_TO_ERROR_STATE(CURLE_PEER_FAILED_VERIFICATION);
- break;
+ MOVE_TO_GSSAPI_AUTH;
+ return rc;
}
+ }
- state(data, SSH_AUTHLIST);
- FALLTHROUGH();
- case SSH_AUTHLIST:{
- sshc->authed = FALSE;
+ rc = ssh_pki_import_privkey_file(data->
+ set.str[STRING_SSH_PRIVATE_KEY],
+ data->set.ssl.key_passwd, NULL,
+ NULL, &sshc->privkey);
+ if(rc != SSH_OK) {
+ failf(data, "Could not load private key file %s",
+ data->set.str[STRING_SSH_PRIVATE_KEY]);
+ MOVE_TO_ERROR_STATE(CURLE_LOGIN_DENIED);
+ return rc;
+ }
- rc = ssh_userauth_none(sshc->ssh_session, NULL);
- if(rc == SSH_AUTH_AGAIN) {
- rc = SSH_AGAIN;
- break;
- }
+ myssh_state(data, sshc, SSH_AUTH_PKEY);
+ }
+ else {
+ rc = ssh_userauth_publickey_auto(sshc->ssh_session, NULL,
+ data->set.ssl.key_passwd);
+ if(rc == SSH_AUTH_AGAIN)
+ return SSH_AGAIN;
+
+ if(rc == SSH_AUTH_SUCCESS) {
+ rc = SSH_OK;
+ sshc->authed = TRUE;
+ infof(data, "Completed public key authentication");
+ myssh_state(data, sshc, SSH_AUTH_DONE);
+ return rc;
+ }
- if(rc == SSH_AUTH_SUCCESS) {
- sshc->authed = TRUE;
- infof(data, "Authenticated with none");
- state(data, SSH_AUTH_DONE);
- break;
- }
- else if(rc == SSH_AUTH_ERROR) {
- MOVE_TO_ERROR_STATE(CURLE_LOGIN_DENIED);
- break;
- }
+ MOVE_TO_GSSAPI_AUTH;
+ }
+ return rc;
+}
- sshc->auth_methods =
- (unsigned int)ssh_userauth_list(sshc->ssh_session, NULL);
- if(sshc->auth_methods)
- infof(data, "SSH authentication methods available: %s%s%s%s",
- sshc->auth_methods & SSH_AUTH_METHOD_PUBLICKEY ?
- "public key, ": "",
- sshc->auth_methods & SSH_AUTH_METHOD_GSSAPI_MIC ?
- "GSSAPI, " : "",
- sshc->auth_methods & SSH_AUTH_METHOD_INTERACTIVE ?
- "keyboard-interactive, " : "",
- sshc->auth_methods & SSH_AUTH_METHOD_PASSWORD ?
- "password": "");
- if(sshc->auth_methods & SSH_AUTH_METHOD_PUBLICKEY) {
- state(data, SSH_AUTH_PKEY_INIT);
- infof(data, "Authentication using SSH public key file");
- }
- else if(sshc->auth_methods & SSH_AUTH_METHOD_GSSAPI_MIC) {
- state(data, SSH_AUTH_GSSAPI);
- }
- else if(sshc->auth_methods & SSH_AUTH_METHOD_INTERACTIVE) {
- state(data, SSH_AUTH_KEY_INIT);
- }
- else if(sshc->auth_methods & SSH_AUTH_METHOD_PASSWORD) {
- state(data, SSH_AUTH_PASS_INIT);
- }
- else { /* unsupported authentication method */
- MOVE_TO_ERROR_STATE(CURLE_LOGIN_DENIED);
- break;
+static int myssh_state_upload_init(struct Curl_easy *data,
+ struct ssh_conn *sshc,
+ struct SSHPROTO *sshp)
+{
+ int flags;
+ int rc = 0;
+
+ if(data->state.resume_from) {
+ sftp_attributes attrs;
+
+ if(data->state.resume_from < 0) {
+ attrs = sftp_stat(sshc->sftp_session, sshp->path);
+ if(attrs) {
+ curl_off_t size = attrs->size;
+ if(size < 0) {
+ failf(data, "Bad file size (%" FMT_OFF_T ")", size);
+ MOVE_TO_ERROR_STATE(CURLE_BAD_DOWNLOAD_RESUME);
+ return rc;
}
+ data->state.resume_from = attrs->size;
- break;
+ sftp_attributes_free(attrs);
}
- case SSH_AUTH_PKEY_INIT:
- if(!(data->set.ssh_auth_types & CURLSSH_AUTH_PUBLICKEY)) {
- MOVE_TO_GSSAPI_AUTH;
- break;
+ else {
+ data->state.resume_from = 0;
}
+ }
+ }
- /* Two choices, (1) private key was given on CMD,
- * (2) use the "default" keys. */
- if(data->set.str[STRING_SSH_PRIVATE_KEY]) {
- if(sshc->pubkey && !data->set.ssl.key_passwd) {
- rc = ssh_userauth_try_publickey(sshc->ssh_session, NULL,
- sshc->pubkey);
- if(rc == SSH_AUTH_AGAIN) {
- rc = SSH_AGAIN;
- break;
- }
+ if(data->set.remote_append)
+ /* Try to open for append, but create if nonexisting */
+ flags = O_WRONLY|O_CREAT|O_APPEND;
+ else if(data->state.resume_from > 0)
+ /* If we have restart position then open for append */
+ flags = O_WRONLY|O_APPEND;
+ else
+ /* Clear file before writing (normal behavior) */
+ flags = O_WRONLY|O_CREAT|O_TRUNC;
+
+ if(sshc->sftp_file)
+ sftp_close(sshc->sftp_file);
+ sshc->sftp_file =
+ sftp_open(sshc->sftp_session, sshp->path,
+ flags, (mode_t)data->set.new_file_perms);
+ if(!sshc->sftp_file) {
+ int err = sftp_get_error(sshc->sftp_session);
+
+ if(((err == SSH_FX_NO_SUCH_FILE || err == SSH_FX_FAILURE ||
+ err == SSH_FX_NO_SUCH_PATH)) &&
+ (data->set.ftp_create_missing_dirs &&
+ (strlen(sshp->path) > 1))) {
+ /* try to create the path remotely */
+ rc = 0;
+ sshc->secondCreateDirs = 1;
+ myssh_state(data, sshc, SSH_SFTP_CREATE_DIRS_INIT);
+ return rc;
+ }
+ else {
+ MOVE_TO_SFTP_CLOSE_STATE();
+ return rc;
+ }
+ }
- if(rc != SSH_OK) {
- MOVE_TO_GSSAPI_AUTH;
- break;
- }
- }
+ /* If we have a restart point then we need to seek to the correct
+ position. */
+ if(data->state.resume_from > 0) {
+ int seekerr = CURL_SEEKFUNC_OK;
+ /* Let's read off the proper amount of bytes from the input. */
+ if(data->set.seek_func) {
+ Curl_set_in_callback(data, TRUE);
+ seekerr = data->set.seek_func(data->set.seek_client,
+ data->state.resume_from, SEEK_SET);
+ Curl_set_in_callback(data, FALSE);
+ }
- rc = ssh_pki_import_privkey_file(data->
- set.str[STRING_SSH_PRIVATE_KEY],
- data->set.ssl.key_passwd, NULL,
- NULL, &sshc->privkey);
- if(rc != SSH_OK) {
- failf(data, "Could not load private key file %s",
- data->set.str[STRING_SSH_PRIVATE_KEY]);
- MOVE_TO_ERROR_STATE(CURLE_LOGIN_DENIED);
- break;
+ if(seekerr != CURL_SEEKFUNC_OK) {
+ curl_off_t passed = 0;
+
+ if(seekerr != CURL_SEEKFUNC_CANTSEEK) {
+ failf(data, "Could not seek stream");
+ MOVE_TO_ERROR_STATE(CURLE_FTP_COULDNT_USE_REST);
+ return rc;
+ }
+ /* seekerr == CURL_SEEKFUNC_CANTSEEK (cannot seek to offset) */
+ do {
+ char scratch[4*1024];
+ size_t readthisamountnow =
+ (data->state.resume_from - passed >
+ (curl_off_t)sizeof(scratch)) ?
+ sizeof(scratch) : curlx_sotouz(data->state.resume_from - passed);
+
+ size_t actuallyread =
+ data->state.fread_func(scratch, 1,
+ readthisamountnow, data->state.in);
+
+ passed += actuallyread;
+ if((actuallyread == 0) || (actuallyread > readthisamountnow)) {
+ /* this checks for greater-than only to make sure that the
+ CURL_READFUNC_ABORT return code still aborts */
+ failf(data, "Failed to read data");
+ MOVE_TO_ERROR_STATE(CURLE_FTP_COULDNT_USE_REST);
+ return rc;
}
+ } while(passed < data->state.resume_from);
+ }
- state(data, SSH_AUTH_PKEY);
- break;
+ /* now, decrease the size of the read */
+ if(data->state.infilesize > 0) {
+ data->state.infilesize -= data->state.resume_from;
+ data->req.size = data->state.infilesize;
+ Curl_pgrsSetUploadSize(data, data->state.infilesize);
+ }
+
+ rc = sftp_seek64(sshc->sftp_file, data->state.resume_from);
+ if(rc) {
+ MOVE_TO_SFTP_CLOSE_STATE();
+ return rc;
+ }
+ }
+ if(data->state.infilesize > 0) {
+ data->req.size = data->state.infilesize;
+ Curl_pgrsSetUploadSize(data, data->state.infilesize);
+ }
+ /* upload data */
+ Curl_xfer_setup1(data, CURL_XFER_SEND, -1, FALSE);
+
+ /* not set by Curl_xfer_setup to preserve keepon bits */
+ data->conn->sockfd = data->conn->writesockfd;
+
+ /* store this original bitmask setup to use later on if we cannot
+ figure out a "real" bitmask */
+ sshc->orig_waitfor = data->req.keepon;
+
+ /* we want to use the _sending_ function even when the socket turns
+ out readable as the underlying libssh sftp send function will deal
+ with both accordingly */
+ data->state.select_bits = CURL_CSELECT_OUT;
+
+ /* since we do not really wait for anything at this point, we want the
+ state machine to move on as soon as possible so we set a very short
+ timeout here */
+ Curl_expire(data, 0, EXPIRE_RUN_NOW);
+#if LIBSSH_VERSION_INT > SSH_VERSION_INT(0, 11, 0)
+ sshc->sftp_send_state = 0;
+#endif
+ myssh_state(data, sshc, SSH_STOP);
+ return rc;
+}
+static int myssh_state_sftp_dowload_stat(struct Curl_easy *data,
+ struct ssh_conn *sshc)
+{
+ curl_off_t size;
+ int rc = 0;
+ sftp_attributes attrs = sftp_fstat(sshc->sftp_file);
+ if(!attrs ||
+ !(attrs->flags & SSH_FILEXFER_ATTR_SIZE) ||
+ (attrs->size == 0)) {
+ /*
+ * sftp_fstat did not return an error, so maybe the server
+ * just does not support stat()
+ * OR the server does not return a file size with a stat()
+ * OR file size is 0
+ */
+ data->req.size = -1;
+ data->req.maxdownload = -1;
+ Curl_pgrsSetDownloadSize(data, -1);
+ size = 0;
+ if(attrs)
+ sftp_attributes_free(attrs);
+ }
+ else {
+ size = attrs->size;
+
+ sftp_attributes_free(attrs);
+
+ if(size < 0) {
+ failf(data, "Bad file size (%" FMT_OFF_T ")", size);
+ MOVE_TO_ERROR_STATE(CURLE_BAD_DOWNLOAD_RESUME);
+ return rc;
+ }
+ if(data->state.use_range) {
+ curl_off_t from, to;
+ const char *p = data->state.range;
+ int from_t, to_t;
+
+ from_t = curlx_str_number(&p, &from, CURL_OFF_T_MAX);
+ if(from_t == STRE_OVERFLOW) {
+ MOVE_TO_ERROR_STATE(CURLE_RANGE_ERROR);
+ return rc;
+ }
+ curlx_str_passblanks(&p);
+ (void)curlx_str_single(&p, '-');
+
+ to_t = curlx_str_numblanks(&p, &to);
+ if(to_t == STRE_OVERFLOW)
+ return CURLE_RANGE_ERROR;
+
+ if((to_t == STRE_NO_NUM) || (to >= size)) {
+ to = size - 1;
+ to_t = STRE_OK;
+ }
+
+ if(from_t == STRE_NO_NUM) {
+ /* from is relative to end of file */
+ from = size - to;
+ to = size - 1;
+ from_t = STRE_OK;
+ }
+ if(from > size) {
+ failf(data, "Offset (%" FMT_OFF_T ") was beyond file size (%"
+ FMT_OFF_T ")", from, size);
+ MOVE_TO_ERROR_STATE(CURLE_BAD_DOWNLOAD_RESUME);
+ return rc;
+ }
+ if(from > to) {
+ from = to;
+ size = 0;
}
else {
- rc = ssh_userauth_publickey_auto(sshc->ssh_session, NULL,
- data->set.ssl.key_passwd);
- if(rc == SSH_AUTH_AGAIN) {
- rc = SSH_AGAIN;
- break;
- }
- if(rc == SSH_AUTH_SUCCESS) {
- rc = SSH_OK;
- sshc->authed = TRUE;
- infof(data, "Completed public key authentication");
- state(data, SSH_AUTH_DONE);
- break;
+ if((to - from) == CURL_OFF_T_MAX) {
+ MOVE_TO_ERROR_STATE(CURLE_RANGE_ERROR);
+ return rc;
}
+ size = to - from + 1;
+ }
- MOVE_TO_GSSAPI_AUTH;
+ rc = sftp_seek64(sshc->sftp_file, from);
+ if(rc) {
+ MOVE_TO_SFTP_CLOSE_STATE();
+ return rc;
}
+ }
+ data->req.size = size;
+ data->req.maxdownload = size;
+ Curl_pgrsSetDownloadSize(data, size);
+ }
+
+ /* We can resume if we can seek to the resume position */
+ if(data->state.resume_from) {
+ if(data->state.resume_from < 0) {
+ /* We are supposed to download the last abs(from) bytes */
+ if((curl_off_t)size < -data->state.resume_from) {
+ failf(data, "Offset (%" FMT_OFF_T ") was beyond file size (%"
+ FMT_OFF_T ")", data->state.resume_from, size);
+ MOVE_TO_ERROR_STATE(CURLE_BAD_DOWNLOAD_RESUME);
+ return rc;
+ }
+ /* download from where? */
+ data->state.resume_from += size;
+ }
+ else {
+ if((curl_off_t)size < data->state.resume_from) {
+ failf(data, "Offset (%" FMT_OFF_T
+ ") was beyond file size (%" FMT_OFF_T ")",
+ data->state.resume_from, size);
+ MOVE_TO_ERROR_STATE(CURLE_BAD_DOWNLOAD_RESUME);
+ return rc;
+ }
+ }
+ /* Now store the number of bytes we are expected to download */
+ data->req.size = size - data->state.resume_from;
+ data->req.maxdownload = size - data->state.resume_from;
+ Curl_pgrsSetDownloadSize(data,
+ size - data->state.resume_from);
+
+ rc = sftp_seek64(sshc->sftp_file, data->state.resume_from);
+ if(rc) {
+ MOVE_TO_SFTP_CLOSE_STATE();
+ return rc;
+ }
+ }
+
+ /* Setup the actual download */
+ if(data->req.size == 0) {
+ /* no data to transfer */
+ Curl_xfer_setup_nop(data);
+ infof(data, "File already completely downloaded");
+ myssh_state(data, sshc, SSH_STOP);
+ return rc;
+ }
+ Curl_xfer_setup1(data, CURL_XFER_RECV, data->req.size, FALSE);
+
+ /* not set by Curl_xfer_setup to preserve keepon bits */
+ data->conn->writesockfd = data->conn->sockfd;
+
+ /* we want to use the _receiving_ function even when the socket turns
+ out writableable as the underlying libssh recv function will deal
+ with both accordingly */
+ data->state.select_bits = CURL_CSELECT_IN;
+
+ sshc->sftp_recv_state = 0;
+ myssh_state(data, sshc, SSH_STOP);
+
+ return rc;
+}
+
+/*
+ * ssh_statemach_act() runs the SSH state machine as far as it can without
+ * blocking and without reaching the end. The data the pointer 'block' points
+ * to will be set to TRUE if the libssh function returns SSH_AGAIN
+ * meaning it wants to be called again when the socket is ready
+ */
+static CURLcode myssh_statemach_act(struct Curl_easy *data,
+ struct ssh_conn *sshc,
+ struct SSHPROTO *sshp,
+ bool *block)
+{
+ CURLcode result = CURLE_OK;
+ struct connectdata *conn = data->conn;
+ curl_socket_t sock = conn->sock[FIRSTSOCKET];
+ int rc = SSH_NO_ERROR, err;
+ const char *err_msg;
+ *block = 0; /* we are not blocking by default */
+
+ do {
+
+ switch(sshc->state) {
+ case SSH_INIT:
+ myssh_state_init(data, sshc);
+ FALLTHROUGH();
+
+ case SSH_S_STARTUP:
+ rc = myssh_state_startup(data, sshc);
+ if(rc)
+ break;
+ FALLTHROUGH();
+ case SSH_HOSTKEY:
+ rc = myssh_is_known(data, sshc);
+ if(rc != SSH_OK) {
+ MOVE_TO_ERROR_STATE(CURLE_PEER_FAILED_VERIFICATION);
+ break;
+ }
+
+ myssh_state(data, sshc, SSH_AUTHLIST);
+ FALLTHROUGH();
+ case SSH_AUTHLIST:
+ rc = myssh_state_authlist(data, sshc);
+ break;
+ case SSH_AUTH_PKEY_INIT:
+ rc = myssh_state_auth_pkey_init(data, sshc);
break;
case SSH_AUTH_PKEY:
rc = ssh_userauth_publickey(sshc->ssh_session, NULL, sshc->privkey);
@@ -808,7 +1125,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
if(rc == SSH_AUTH_SUCCESS) {
sshc->authed = TRUE;
infof(data, "Completed public key authentication");
- state(data, SSH_AUTH_DONE);
+ myssh_state(data, sshc, SSH_AUTH_DONE);
break;
}
else {
@@ -833,7 +1150,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
rc = SSH_OK;
sshc->authed = TRUE;
infof(data, "Completed gssapi authentication");
- state(data, SSH_AUTH_DONE);
+ myssh_state(data, sshc, SSH_AUTH_DONE);
break;
}
@@ -842,7 +1159,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
case SSH_AUTH_KEY_INIT:
if(data->set.ssh_auth_types & CURLSSH_AUTH_KEYBOARD) {
- state(data, SSH_AUTH_KEY);
+ myssh_state(data, sshc, SSH_AUTH_KEY);
}
else {
MOVE_TO_PASSWD_AUTH;
@@ -851,14 +1168,14 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
case SSH_AUTH_KEY:
/* keyboard-interactive authentication */
- rc = myssh_auth_interactive(conn);
+ rc = myssh_auth_interactive(conn, sshc);
if(rc == SSH_AGAIN) {
break;
}
if(rc == SSH_OK) {
sshc->authed = TRUE;
infof(data, "completed keyboard interactive authentication");
- state(data, SSH_AUTH_DONE);
+ myssh_state(data, sshc, SSH_AUTH_DONE);
}
else {
MOVE_TO_PASSWD_AUTH;
@@ -870,7 +1187,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
MOVE_TO_ERROR_STATE(CURLE_LOGIN_DENIED);
break;
}
- state(data, SSH_AUTH_PASS);
+ myssh_state(data, sshc, SSH_AUTH_PASS);
FALLTHROUGH();
case SSH_AUTH_PASS:
@@ -883,7 +1200,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
if(rc == SSH_AUTH_SUCCESS) {
sshc->authed = TRUE;
infof(data, "Completed password authentication");
- state(data, SSH_AUTH_DONE);
+ myssh_state(data, sshc, SSH_AUTH_DONE);
}
else {
MOVE_TO_ERROR_STATE(CURLE_LOGIN_DENIED);
@@ -908,11 +1225,11 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
conn->writesockfd = CURL_SOCKET_BAD;
if(conn->handler->protocol == CURLPROTO_SFTP) {
- state(data, SSH_SFTP_INIT);
+ myssh_state(data, sshc, SSH_SFTP_INIT);
break;
}
infof(data, "SSH CONNECT phase done");
- state(data, SSH_STOP);
+ myssh_state(data, sshc, SSH_STOP);
break;
case SSH_SFTP_INIT:
@@ -933,7 +1250,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
MOVE_TO_ERROR_STATE(sftp_error_to_CURLE(SSH_FX_FAILURE));
break;
}
- state(data, SSH_SFTP_REALPATH);
+ myssh_state(data, sshc, SSH_SFTP_REALPATH);
FALLTHROUGH();
case SSH_SFTP_REALPATH:
/*
@@ -954,24 +1271,24 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
since the homedir will remain the same between request but the
working path will not. */
DEBUGF(infof(data, "SSH CONNECT phase done"));
- state(data, SSH_STOP);
+ myssh_state(data, sshc, SSH_STOP);
break;
case SSH_SFTP_QUOTE_INIT:
- result = Curl_getworkingpath(data, sshc->homedir, &protop->path);
+ result = Curl_getworkingpath(data, sshc->homedir, &sshp->path);
if(result) {
sshc->actualcode = result;
- state(data, SSH_STOP);
+ myssh_state(data, sshc, SSH_STOP);
break;
}
if(data->set.quote) {
infof(data, "Sending quote commands");
sshc->quote_item = data->set.quote;
- state(data, SSH_SFTP_QUOTE);
+ myssh_state(data, sshc, SSH_SFTP_QUOTE);
}
else {
- state(data, SSH_SFTP_GETINFO);
+ myssh_state(data, sshc, SSH_SFTP_GETINFO);
}
break;
@@ -979,16 +1296,16 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
if(data->set.postquote) {
infof(data, "Sending quote commands");
sshc->quote_item = data->set.postquote;
- state(data, SSH_SFTP_QUOTE);
+ myssh_state(data, sshc, SSH_SFTP_QUOTE);
}
else {
- state(data, SSH_STOP);
+ myssh_state(data, sshc, SSH_STOP);
}
break;
case SSH_SFTP_QUOTE:
/* Send any quote commands */
- sftp_quote(data);
+ sftp_quote(data, sshc, sshp);
break;
case SSH_SFTP_NEXT_QUOTE:
@@ -998,21 +1315,21 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
sshc->quote_item = sshc->quote_item->next;
if(sshc->quote_item) {
- state(data, SSH_SFTP_QUOTE);
+ myssh_state(data, sshc, SSH_SFTP_QUOTE);
}
else {
if(sshc->nextstate != SSH_NO_STATE) {
- state(data, sshc->nextstate);
+ myssh_state(data, sshc, sshc->nextstate);
sshc->nextstate = SSH_NO_STATE;
}
else {
- state(data, SSH_SFTP_GETINFO);
+ myssh_state(data, sshc, SSH_SFTP_GETINFO);
}
}
break;
case SSH_SFTP_QUOTE_STAT:
- sftp_quote_stat(data);
+ sftp_quote_stat(data, sshc);
break;
case SSH_SFTP_QUOTE_SETSTAT:
@@ -1023,7 +1340,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
Curl_safefree(sshc->quote_path2);
failf(data, "Attempt to set SFTP stats failed: %s",
ssh_get_error(sshc->ssh_session));
- state(data, SSH_SFTP_CLOSE);
+ myssh_state(data, sshc, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = CURLE_QUOTE_ERROR;
/* sshc->actualcode = sftp_error_to_CURLE(err);
@@ -1031,7 +1348,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
* the error the libssh2 backend is returning */
break;
}
- state(data, SSH_SFTP_NEXT_QUOTE);
+ myssh_state(data, sshc, SSH_SFTP_NEXT_QUOTE);
break;
case SSH_SFTP_QUOTE_SYMLINK:
@@ -1042,12 +1359,12 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
Curl_safefree(sshc->quote_path2);
failf(data, "symlink command failed: %s",
ssh_get_error(sshc->ssh_session));
- state(data, SSH_SFTP_CLOSE);
+ myssh_state(data, sshc, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = CURLE_QUOTE_ERROR;
break;
}
- state(data, SSH_SFTP_NEXT_QUOTE);
+ myssh_state(data, sshc, SSH_SFTP_NEXT_QUOTE);
break;
case SSH_SFTP_QUOTE_MKDIR:
@@ -1057,12 +1374,12 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
Curl_safefree(sshc->quote_path1);
failf(data, "mkdir command failed: %s",
ssh_get_error(sshc->ssh_session));
- state(data, SSH_SFTP_CLOSE);
+ myssh_state(data, sshc, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = CURLE_QUOTE_ERROR;
break;
}
- state(data, SSH_SFTP_NEXT_QUOTE);
+ myssh_state(data, sshc, SSH_SFTP_NEXT_QUOTE);
break;
case SSH_SFTP_QUOTE_RENAME:
@@ -1073,12 +1390,12 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
Curl_safefree(sshc->quote_path2);
failf(data, "rename command failed: %s",
ssh_get_error(sshc->ssh_session));
- state(data, SSH_SFTP_CLOSE);
+ myssh_state(data, sshc, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = CURLE_QUOTE_ERROR;
break;
}
- state(data, SSH_SFTP_NEXT_QUOTE);
+ myssh_state(data, sshc, SSH_SFTP_NEXT_QUOTE);
break;
case SSH_SFTP_QUOTE_RMDIR:
@@ -1087,12 +1404,12 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
Curl_safefree(sshc->quote_path1);
failf(data, "rmdir command failed: %s",
ssh_get_error(sshc->ssh_session));
- state(data, SSH_SFTP_CLOSE);
+ myssh_state(data, sshc, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = CURLE_QUOTE_ERROR;
break;
}
- state(data, SSH_SFTP_NEXT_QUOTE);
+ myssh_state(data, sshc, SSH_SFTP_NEXT_QUOTE);
break;
case SSH_SFTP_QUOTE_UNLINK:
@@ -1101,12 +1418,12 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
Curl_safefree(sshc->quote_path1);
failf(data, "rm command failed: %s",
ssh_get_error(sshc->ssh_session));
- state(data, SSH_SFTP_CLOSE);
+ myssh_state(data, sshc, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = CURLE_QUOTE_ERROR;
break;
}
- state(data, SSH_SFTP_NEXT_QUOTE);
+ myssh_state(data, sshc, SSH_SFTP_NEXT_QUOTE);
break;
case SSH_SFTP_QUOTE_STATVFS:
@@ -1118,7 +1435,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
Curl_safefree(sshc->quote_path1);
failf(data, "statvfs command failed: %s",
ssh_get_error(sshc->ssh_session));
- state(data, SSH_SFTP_CLOSE);
+ myssh_state(data, sshc, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = CURLE_QUOTE_ERROR;
break;
@@ -1151,7 +1468,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
if(!tmp) {
result = CURLE_OUT_OF_MEMORY;
- state(data, SSH_SFTP_CLOSE);
+ myssh_state(data, sshc, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
break;
}
@@ -1159,21 +1476,21 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
result = Curl_client_write(data, CLIENTWRITE_HEADER, tmp, strlen(tmp));
free(tmp);
if(result) {
- state(data, SSH_SFTP_CLOSE);
+ myssh_state(data, sshc, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = result;
}
}
- state(data, SSH_SFTP_NEXT_QUOTE);
+ myssh_state(data, sshc, SSH_SFTP_NEXT_QUOTE);
break;
}
case SSH_SFTP_GETINFO:
if(data->set.get_filetime) {
- state(data, SSH_SFTP_FILETIME);
+ myssh_state(data, sshc, SSH_SFTP_FILETIME);
}
else {
- state(data, SSH_SFTP_TRANS_INIT);
+ myssh_state(data, sshc, SSH_SFTP_TRANS_INIT);
}
break;
@@ -1181,180 +1498,38 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
{
sftp_attributes attrs;
- attrs = sftp_stat(sshc->sftp_session, protop->path);
+ attrs = sftp_stat(sshc->sftp_session, sshp->path);
if(attrs) {
data->info.filetime = attrs->mtime;
sftp_attributes_free(attrs);
}
- state(data, SSH_SFTP_TRANS_INIT);
+ myssh_state(data, sshc, SSH_SFTP_TRANS_INIT);
break;
}
case SSH_SFTP_TRANS_INIT:
if(data->state.upload)
- state(data, SSH_SFTP_UPLOAD_INIT);
+ myssh_state(data, sshc, SSH_SFTP_UPLOAD_INIT);
else {
- if(protop->path[strlen(protop->path)-1] == '/')
- state(data, SSH_SFTP_READDIR_INIT);
+ if(sshp->path[strlen(sshp->path)-1] == '/')
+ myssh_state(data, sshc, SSH_SFTP_READDIR_INIT);
else
- state(data, SSH_SFTP_DOWNLOAD_INIT);
+ myssh_state(data, sshc, SSH_SFTP_DOWNLOAD_INIT);
}
break;
case SSH_SFTP_UPLOAD_INIT:
- {
- int flags;
-
- if(data->state.resume_from) {
- sftp_attributes attrs;
-
- if(data->state.resume_from < 0) {
- attrs = sftp_stat(sshc->sftp_session, protop->path);
- if(attrs) {
- curl_off_t size = attrs->size;
- if(size < 0) {
- failf(data, "Bad file size (%" FMT_OFF_T ")", size);
- MOVE_TO_ERROR_STATE(CURLE_BAD_DOWNLOAD_RESUME);
- break;
- }
- data->state.resume_from = attrs->size;
-
- sftp_attributes_free(attrs);
- }
- else {
- data->state.resume_from = 0;
- }
- }
- }
-
- if(data->set.remote_append)
- /* Try to open for append, but create if nonexisting */
- flags = O_WRONLY|O_CREAT|O_APPEND;
- else if(data->state.resume_from > 0)
- /* If we have restart position then open for append */
- flags = O_WRONLY|O_APPEND;
- else
- /* Clear file before writing (normal behavior) */
- flags = O_WRONLY|O_CREAT|O_TRUNC;
-
- if(sshc->sftp_file)
- sftp_close(sshc->sftp_file);
- sshc->sftp_file =
- sftp_open(sshc->sftp_session, protop->path,
- flags, (mode_t)data->set.new_file_perms);
- if(!sshc->sftp_file) {
- err = sftp_get_error(sshc->sftp_session);
-
- if(((err == SSH_FX_NO_SUCH_FILE || err == SSH_FX_FAILURE ||
- err == SSH_FX_NO_SUCH_PATH)) &&
- (data->set.ftp_create_missing_dirs &&
- (strlen(protop->path) > 1))) {
- /* try to create the path remotely */
- rc = 0;
- sshc->secondCreateDirs = 1;
- state(data, SSH_SFTP_CREATE_DIRS_INIT);
- break;
- }
- else {
- MOVE_TO_SFTP_CLOSE_STATE();
- break;
- }
- }
-
- /* If we have a restart point then we need to seek to the correct
- position. */
- if(data->state.resume_from > 0) {
- /* Let's read off the proper amount of bytes from the input. */
- if(data->set.seek_func) {
- Curl_set_in_callback(data, TRUE);
- seekerr = data->set.seek_func(data->set.seek_client,
- data->state.resume_from, SEEK_SET);
- Curl_set_in_callback(data, FALSE);
- }
-
- if(seekerr != CURL_SEEKFUNC_OK) {
- curl_off_t passed = 0;
-
- if(seekerr != CURL_SEEKFUNC_CANTSEEK) {
- failf(data, "Could not seek stream");
- return CURLE_FTP_COULDNT_USE_REST;
- }
- /* seekerr == CURL_SEEKFUNC_CANTSEEK (cannot seek to offset) */
- do {
- char scratch[4*1024];
- size_t readthisamountnow =
- (data->state.resume_from - passed >
- (curl_off_t)sizeof(scratch)) ?
- sizeof(scratch) : curlx_sotouz(data->state.resume_from - passed);
-
- size_t actuallyread =
- data->state.fread_func(scratch, 1,
- readthisamountnow, data->state.in);
-
- passed += actuallyread;
- if((actuallyread == 0) || (actuallyread > readthisamountnow)) {
- /* this checks for greater-than only to make sure that the
- CURL_READFUNC_ABORT return code still aborts */
- failf(data, "Failed to read data");
- MOVE_TO_ERROR_STATE(CURLE_FTP_COULDNT_USE_REST);
- break;
- }
- } while(passed < data->state.resume_from);
- if(rc)
- break;
- }
-
- /* now, decrease the size of the read */
- if(data->state.infilesize > 0) {
- data->state.infilesize -= data->state.resume_from;
- data->req.size = data->state.infilesize;
- Curl_pgrsSetUploadSize(data, data->state.infilesize);
- }
-
- rc = sftp_seek64(sshc->sftp_file, data->state.resume_from);
- if(rc) {
- MOVE_TO_SFTP_CLOSE_STATE();
- break;
- }
- }
- if(data->state.infilesize > 0) {
- data->req.size = data->state.infilesize;
- Curl_pgrsSetUploadSize(data, data->state.infilesize);
- }
- /* upload data */
- Curl_xfer_setup1(data, CURL_XFER_SEND, -1, FALSE);
-
- /* not set by Curl_xfer_setup to preserve keepon bits */
- conn->sockfd = conn->writesockfd;
-
- /* store this original bitmask setup to use later on if we cannot
- figure out a "real" bitmask */
- sshc->orig_waitfor = data->req.keepon;
-
- /* we want to use the _sending_ function even when the socket turns
- out readable as the underlying libssh sftp send function will deal
- with both accordingly */
- data->state.select_bits = CURL_CSELECT_OUT;
-
- /* since we do not really wait for anything at this point, we want the
- state machine to move on as soon as possible so we set a very short
- timeout here */
- Curl_expire(data, 0, EXPIRE_RUN_NOW);
-#if LIBSSH_VERSION_INT > SSH_VERSION_INT(0, 11, 0)
- sshc->sftp_send_state = 0;
-#endif
- state(data, SSH_STOP);
+ rc = myssh_state_upload_init(data, sshc, sshp);
break;
- }
case SSH_SFTP_CREATE_DIRS_INIT:
- if(strlen(protop->path) > 1) {
- sshc->slash_pos = protop->path + 1; /* ignore the leading '/' */
- state(data, SSH_SFTP_CREATE_DIRS);
+ if(strlen(sshp->path) > 1) {
+ sshc->slash_pos = sshp->path + 1; /* ignore the leading '/' */
+ myssh_state(data, sshc, SSH_SFTP_CREATE_DIRS);
}
else {
- state(data, SSH_SFTP_UPLOAD_INIT);
+ myssh_state(data, sshc, SSH_SFTP_UPLOAD_INIT);
}
break;
@@ -1363,16 +1538,16 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
if(sshc->slash_pos) {
*sshc->slash_pos = 0;
- infof(data, "Creating directory '%s'", protop->path);
- state(data, SSH_SFTP_CREATE_DIRS_MKDIR);
+ infof(data, "Creating directory '%s'", sshp->path);
+ myssh_state(data, sshc, SSH_SFTP_CREATE_DIRS_MKDIR);
break;
}
- state(data, SSH_SFTP_UPLOAD_INIT);
+ myssh_state(data, sshc, SSH_SFTP_UPLOAD_INIT);
break;
case SSH_SFTP_CREATE_DIRS_MKDIR:
/* 'mode' - parameter is preliminary - default to 0644 */
- rc = sftp_mkdir(sshc->sftp_session, protop->path,
+ rc = sftp_mkdir(sshc->sftp_session, sshp->path,
(mode_t)data->set.new_directory_perms);
*sshc->slash_pos = '/';
++sshc->slash_pos;
@@ -1391,13 +1566,13 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
}
rc = 0; /* clear rc and continue */
}
- state(data, SSH_SFTP_CREATE_DIRS);
+ myssh_state(data, sshc, SSH_SFTP_CREATE_DIRS);
break;
case SSH_SFTP_READDIR_INIT:
Curl_pgrsSetDownloadSize(data, -1);
if(data->req.no_body) {
- state(data, SSH_STOP);
+ myssh_state(data, sshc, SSH_STOP);
break;
}
@@ -1406,18 +1581,18 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
* listing
*/
sshc->sftp_dir = sftp_opendir(sshc->sftp_session,
- protop->path);
+ sshp->path);
if(!sshc->sftp_dir) {
failf(data, "Could not open directory for reading: %s",
ssh_get_error(sshc->ssh_session));
MOVE_TO_SFTP_CLOSE_STATE();
break;
}
- state(data, SSH_SFTP_READDIR);
+ myssh_state(data, sshc, SSH_SFTP_READDIR);
break;
case SSH_SFTP_READDIR:
- Curl_dyn_reset(&sshc->readdir_buf);
+ curlx_dyn_reset(&sshc->readdir_buf);
if(sshc->readdir_attrs)
sftp_attributes_free(sshc->readdir_attrs);
@@ -1432,7 +1607,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
tmpLine = aprintf("%s\n", sshc->readdir_filename);
if(!tmpLine) {
- state(data, SSH_SFTP_CLOSE);
+ myssh_state(data, sshc, SSH_SFTP_CLOSE);
sshc->actualcode = CURLE_OUT_OF_MEMORY;
break;
}
@@ -1441,39 +1616,39 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
free(tmpLine);
if(result) {
- state(data, SSH_STOP);
+ myssh_state(data, sshc, SSH_STOP);
break;
}
}
else {
- if(Curl_dyn_add(&sshc->readdir_buf, sshc->readdir_longentry)) {
+ if(curlx_dyn_add(&sshc->readdir_buf, sshc->readdir_longentry)) {
sshc->actualcode = CURLE_OUT_OF_MEMORY;
- state(data, SSH_STOP);
+ myssh_state(data, sshc, SSH_STOP);
break;
}
if((sshc->readdir_attrs->flags & SSH_FILEXFER_ATTR_PERMISSIONS) &&
((sshc->readdir_attrs->permissions & SSH_S_IFMT) ==
SSH_S_IFLNK)) {
- sshc->readdir_linkPath = aprintf("%s%s", protop->path,
+ sshc->readdir_linkPath = aprintf("%s%s", sshp->path,
sshc->readdir_filename);
if(!sshc->readdir_linkPath) {
- state(data, SSH_SFTP_CLOSE);
+ myssh_state(data, sshc, SSH_SFTP_CLOSE);
sshc->actualcode = CURLE_OUT_OF_MEMORY;
break;
}
- state(data, SSH_SFTP_READDIR_LINK);
+ myssh_state(data, sshc, SSH_SFTP_READDIR_LINK);
break;
}
- state(data, SSH_SFTP_READDIR_BOTTOM);
+ myssh_state(data, sshc, SSH_SFTP_READDIR_BOTTOM);
break;
}
}
else if(sftp_dir_eof(sshc->sftp_dir)) {
- state(data, SSH_SFTP_READDIR_DONE);
+ myssh_state(data, sshc, SSH_SFTP_READDIR_DONE);
break;
}
else {
@@ -1515,8 +1690,8 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
Curl_safefree(sshc->readdir_linkPath);
- if(Curl_dyn_addf(&sshc->readdir_buf, " -> %s",
- sshc->readdir_filename)) {
+ if(curlx_dyn_addf(&sshc->readdir_buf, " -> %s",
+ sshc->readdir_filename)) {
sshc->actualcode = CURLE_OUT_OF_MEMORY;
break;
}
@@ -1526,24 +1701,24 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
sshc->readdir_filename = NULL;
sshc->readdir_longentry = NULL;
- state(data, SSH_SFTP_READDIR_BOTTOM);
+ myssh_state(data, sshc, SSH_SFTP_READDIR_BOTTOM);
FALLTHROUGH();
case SSH_SFTP_READDIR_BOTTOM:
- if(Curl_dyn_addn(&sshc->readdir_buf, "\n", 1))
+ if(curlx_dyn_addn(&sshc->readdir_buf, "\n", 1))
result = CURLE_OUT_OF_MEMORY;
else
result = Curl_client_write(data, CLIENTWRITE_BODY,
- Curl_dyn_ptr(&sshc->readdir_buf),
- Curl_dyn_len(&sshc->readdir_buf));
+ curlx_dyn_ptr(&sshc->readdir_buf),
+ curlx_dyn_len(&sshc->readdir_buf));
ssh_string_free_char(sshc->readdir_tmp);
sshc->readdir_tmp = NULL;
if(result) {
- state(data, SSH_STOP);
+ myssh_state(data, sshc, SSH_STOP);
}
else
- state(data, SSH_SFTP_READDIR);
+ myssh_state(data, sshc, SSH_SFTP_READDIR);
break;
case SSH_SFTP_READDIR_DONE:
@@ -1552,7 +1727,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
/* no data to transfer */
Curl_xfer_setup_nop(data);
- state(data, SSH_STOP);
+ myssh_state(data, sshc, SSH_STOP);
break;
case SSH_SFTP_DOWNLOAD_INIT:
@@ -1562,7 +1737,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
if(sshc->sftp_file)
sftp_close(sshc->sftp_file);
- sshc->sftp_file = sftp_open(sshc->sftp_session, protop->path,
+ sshc->sftp_file = sftp_open(sshc->sftp_session, sshp->path,
O_RDONLY, (mode_t)data->set.new_file_perms);
if(!sshc->sftp_file) {
failf(data, "Could not open remote file for reading: %s",
@@ -1572,160 +1747,19 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
break;
}
sftp_file_set_nonblocking(sshc->sftp_file);
- state(data, SSH_SFTP_DOWNLOAD_STAT);
+ myssh_state(data, sshc, SSH_SFTP_DOWNLOAD_STAT);
break;
case SSH_SFTP_DOWNLOAD_STAT:
- {
- sftp_attributes attrs;
- curl_off_t size;
-
- attrs = sftp_fstat(sshc->sftp_file);
- if(!attrs ||
- !(attrs->flags & SSH_FILEXFER_ATTR_SIZE) ||
- (attrs->size == 0)) {
- /*
- * sftp_fstat did not return an error, so maybe the server
- * just does not support stat()
- * OR the server does not return a file size with a stat()
- * OR file size is 0
- */
- data->req.size = -1;
- data->req.maxdownload = -1;
- Curl_pgrsSetDownloadSize(data, -1);
- size = 0;
- }
- else {
- size = attrs->size;
-
- sftp_attributes_free(attrs);
-
- if(size < 0) {
- failf(data, "Bad file size (%" FMT_OFF_T ")", size);
- return CURLE_BAD_DOWNLOAD_RESUME;
- }
- if(data->state.use_range) {
- curl_off_t from, to;
- const char *p = data->state.range;
- int from_t, to_t;
-
- from_t = Curl_str_number(&p, &from, CURL_OFF_T_MAX);
- if(from_t == STRE_OVERFLOW)
- return CURLE_RANGE_ERROR;
- Curl_str_passblanks(&p);
- (void)Curl_str_single(&p, '-');
-
- to_t = Curl_str_numblanks(&p, &to);
- if(to_t == STRE_OVERFLOW)
- return CURLE_RANGE_ERROR;
-
- if((to_t == STRE_NO_NUM) || (to >= size)) {
- to = size - 1;
- to_t = STRE_OK;
- }
-
- if(from_t == STRE_NO_NUM) {
- /* from is relative to end of file */
- from = size - to;
- to = size - 1;
- from_t = STRE_OK;
- }
- if(from > size) {
- failf(data, "Offset (%" FMT_OFF_T ") was beyond file size (%"
- FMT_OFF_T ")", from, size);
- return CURLE_BAD_DOWNLOAD_RESUME;
- }
- if(from > to) {
- from = to;
- size = 0;
- }
- else {
- if((to - from) == CURL_OFF_T_MAX)
- return CURLE_RANGE_ERROR;
- size = to - from + 1;
- }
-
- rc = sftp_seek64(sshc->sftp_file, from);
- if(rc) {
- MOVE_TO_SFTP_CLOSE_STATE();
- break;
- }
- }
- data->req.size = size;
- data->req.maxdownload = size;
- Curl_pgrsSetDownloadSize(data, size);
- }
-
- /* We can resume if we can seek to the resume position */
- if(data->state.resume_from) {
- if(data->state.resume_from < 0) {
- /* We are supposed to download the last abs(from) bytes */
- if((curl_off_t)size < -data->state.resume_from) {
- failf(data, "Offset (%" FMT_OFF_T ") was beyond file size (%"
- FMT_OFF_T ")", data->state.resume_from, size);
- return CURLE_BAD_DOWNLOAD_RESUME;
- }
- /* download from where? */
- data->state.resume_from += size;
- }
- else {
- if((curl_off_t)size < data->state.resume_from) {
- failf(data, "Offset (%" FMT_OFF_T
- ") was beyond file size (%" FMT_OFF_T ")",
- data->state.resume_from, size);
- return CURLE_BAD_DOWNLOAD_RESUME;
- }
- }
- /* Now store the number of bytes we are expected to download */
- data->req.size = size - data->state.resume_from;
- data->req.maxdownload = size - data->state.resume_from;
- Curl_pgrsSetDownloadSize(data,
- size - data->state.resume_from);
-
- rc = sftp_seek64(sshc->sftp_file, data->state.resume_from);
- if(rc) {
- MOVE_TO_SFTP_CLOSE_STATE();
- break;
- }
- }
- }
-
- /* Setup the actual download */
- if(data->req.size == 0) {
- /* no data to transfer */
- Curl_xfer_setup_nop(data);
- infof(data, "File already completely downloaded");
- state(data, SSH_STOP);
+ rc = myssh_state_sftp_dowload_stat(data, sshc);
break;
- }
- Curl_xfer_setup1(data, CURL_XFER_RECV, data->req.size, FALSE);
-
- /* not set by Curl_xfer_setup to preserve keepon bits */
- conn->writesockfd = conn->sockfd;
-
- /* we want to use the _receiving_ function even when the socket turns
- out writableable as the underlying libssh recv function will deal
- with both accordingly */
- data->state.select_bits = CURL_CSELECT_IN;
-
- if(result) {
- /* this should never occur; the close state should be entered
- at the time the error occurs */
- state(data, SSH_SFTP_CLOSE);
- sshc->actualcode = result;
- }
- else {
- sshc->sftp_recv_state = 0;
- state(data, SSH_STOP);
- }
- break;
case SSH_SFTP_CLOSE:
if(sshc->sftp_file) {
sftp_close(sshc->sftp_file);
sshc->sftp_file = NULL;
}
- Curl_safefree(protop->path);
+ Curl_safefree(sshp->path);
DEBUGF(infof(data, "SFTP DONE done"));
@@ -1734,11 +1768,11 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
SSH_SFTP_CLOSE to pass the correct result back */
if(sshc->nextstate != SSH_NO_STATE &&
sshc->nextstate != SSH_SFTP_CLOSE) {
- state(data, sshc->nextstate);
+ myssh_state(data, sshc, sshc->nextstate);
sshc->nextstate = SSH_SFTP_CLOSE;
}
else {
- state(data, SSH_STOP);
+ myssh_state(data, sshc, SSH_STOP);
result = sshc->actualcode;
}
break;
@@ -1767,14 +1801,14 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
SSH_STRING_FREE_CHAR(sshc->homedir);
- state(data, SSH_SESSION_DISCONNECT);
+ myssh_state(data, sshc, SSH_SESSION_DISCONNECT);
break;
case SSH_SCP_TRANS_INIT:
- result = Curl_getworkingpath(data, sshc->homedir, &protop->path);
+ result = Curl_getworkingpath(data, sshc->homedir, &sshp->path);
if(result) {
sshc->actualcode = result;
- state(data, SSH_STOP);
+ myssh_state(data, sshc, SSH_STOP);
break;
}
@@ -1790,13 +1824,13 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
}
sshc->scp_session =
- ssh_scp_new(sshc->ssh_session, SSH_SCP_WRITE, protop->path);
- state(data, SSH_SCP_UPLOAD_INIT);
+ ssh_scp_new(sshc->ssh_session, SSH_SCP_WRITE, sshp->path);
+ myssh_state(data, sshc, SSH_SCP_UPLOAD_INIT);
}
else {
sshc->scp_session =
- ssh_scp_new(sshc->ssh_session, SSH_SCP_READ, protop->path);
- state(data, SSH_SCP_DOWNLOAD_INIT);
+ ssh_scp_new(sshc->ssh_session, SSH_SCP_READ, sshp->path);
+ myssh_state(data, sshc, SSH_SCP_DOWNLOAD_INIT);
}
if(!sshc->scp_session) {
@@ -1817,7 +1851,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
break;
}
- rc = ssh_scp_push_file64(sshc->scp_session, protop->path,
+ rc = ssh_scp_push_file64(sshc->scp_session, sshp->path,
(uint64_t)data->state.infilesize,
(int)data->set.new_file_perms);
@@ -1843,7 +1877,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
with both accordingly */
data->state.select_bits = CURL_CSELECT_OUT;
- state(data, SSH_STOP);
+ myssh_state(data, sshc, SSH_STOP);
break;
@@ -1856,7 +1890,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
MOVE_TO_ERROR_STATE(CURLE_COULDNT_CONNECT);
break;
}
- state(data, SSH_SCP_DOWNLOAD);
+ myssh_state(data, sshc, SSH_SCP_DOWNLOAD);
FALLTHROUGH();
case SSH_SCP_DOWNLOAD:{
@@ -1883,14 +1917,14 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
with both accordingly */
data->state.select_bits = CURL_CSELECT_IN;
- state(data, SSH_STOP);
+ myssh_state(data, sshc, SSH_STOP);
break;
}
case SSH_SCP_DONE:
if(data->state.upload)
- state(data, SSH_SCP_SEND_EOF);
+ myssh_state(data, sshc, SSH_SCP_SEND_EOF);
else
- state(data, SSH_SCP_CHANNEL_FREE);
+ myssh_state(data, sshc, SSH_SCP_CHANNEL_FREE);
break;
case SSH_SCP_SEND_EOF:
@@ -1908,7 +1942,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
}
}
- state(data, SSH_SCP_CHANNEL_FREE);
+ myssh_state(data, sshc, SSH_SCP_CHANNEL_FREE);
break;
case SSH_SCP_CHANNEL_FREE:
@@ -1920,7 +1954,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
ssh_set_blocking(sshc->ssh_session, 0);
- state(data, SSH_SESSION_DISCONNECT);
+ myssh_state(data, sshc, SSH_SESSION_DISCONNECT);
FALLTHROUGH();
case SSH_SESSION_DISCONNECT:
@@ -1932,6 +1966,15 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
sshc->scp_session = NULL;
}
+ if(sshc->sftp_file) {
+ sftp_close(sshc->sftp_file);
+ sshc->sftp_file = NULL;
+ }
+ if(sshc->sftp_session) {
+ sftp_free(sshc->sftp_session);
+ sshc->sftp_session = NULL;
+ }
+
ssh_disconnect(sshc->ssh_session);
if(!ssh_version(SSH_VERSION_INT(0, 10, 0))) {
/* conn->sock[FIRSTSOCKET] is closed by ssh_disconnect behind our back,
@@ -1942,24 +1985,24 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
SSH_STRING_FREE_CHAR(sshc->homedir);
- state(data, SSH_SESSION_FREE);
+ myssh_state(data, sshc, SSH_SESSION_FREE);
FALLTHROUGH();
case SSH_SESSION_FREE:
- sshc_cleanup(sshc, data);
+ sshc_cleanup(sshc);
/* the code we are about to return */
result = sshc->actualcode;
memset(sshc, 0, sizeof(struct ssh_conn));
connclose(conn, "SSH session free");
sshc->state = SSH_SESSION_FREE; /* current */
sshc->nextstate = SSH_NO_STATE;
- state(data, SSH_STOP);
+ myssh_state(data, sshc, SSH_STOP);
break;
case SSH_QUIT:
default:
/* internal error */
sshc->nextstate = SSH_NO_STATE;
- state(data, SSH_STOP);
+ myssh_state(data, sshc, SSH_STOP);
break;
}
@@ -1999,10 +2042,10 @@ static int myssh_getsock(struct Curl_easy *data,
return bitmap;
}
-static void myssh_block2waitfor(struct connectdata *conn, bool block)
+static void myssh_block2waitfor(struct connectdata *conn,
+ struct ssh_conn *sshc,
+ bool block)
{
- struct ssh_conn *sshc = &conn->proto.sshc;
-
/* If it did not block, or nothing was returned by ssh_get_poll_flags
* have the original set */
conn->waitfor = sshc->orig_waitfor;
@@ -2023,30 +2066,35 @@ static CURLcode myssh_multi_statemach(struct Curl_easy *data,
bool *done)
{
struct connectdata *conn = data->conn;
- struct ssh_conn *sshc = &conn->proto.sshc;
+ struct ssh_conn *sshc = Curl_conn_meta_get(conn, CURL_META_SSH_CONN);
+ struct SSHPROTO *sshp = Curl_meta_get(data, CURL_META_SSH_EASY);
bool block; /* we store the status and use that to provide a ssh_getsock()
implementation */
- CURLcode result = myssh_statemach_act(data, &block);
+ CURLcode result;
+ if(!sshc || !sshp)
+ return CURLE_FAILED_INIT;
+ result = myssh_statemach_act(data, sshc, sshp, &block);
*done = (sshc->state == SSH_STOP);
- myssh_block2waitfor(conn, block);
+ myssh_block2waitfor(conn, sshc, block);
return result;
}
static CURLcode myssh_block_statemach(struct Curl_easy *data,
+ struct ssh_conn *sshc,
+ struct SSHPROTO *sshp,
bool disconnect)
{
struct connectdata *conn = data->conn;
- struct ssh_conn *sshc = &conn->proto.sshc;
CURLcode result = CURLE_OK;
while((sshc->state != SSH_STOP) && !result) {
bool block;
timediff_t left = 1000;
- struct curltime now = Curl_now();
+ struct curltime now = curlx_now();
- result = myssh_statemach_act(data, &block);
+ result = myssh_statemach_act(data, sshc, sshp, &block);
if(result)
break;
@@ -2077,22 +2125,45 @@ static CURLcode myssh_block_statemach(struct Curl_easy *data,
return result;
}
+static void myssh_easy_dtor(void *key, size_t klen, void *entry)
+{
+ struct SSHPROTO *sshp = entry;
+ (void)key;
+ (void)klen;
+ Curl_safefree(sshp->path);
+ free(sshp);
+}
+
+static void myssh_conn_dtor(void *key, size_t klen, void *entry)
+{
+ struct ssh_conn *sshc = entry;
+ (void)key;
+ (void)klen;
+ sshc_cleanup(sshc);
+ free(sshc);
+}
+
/*
* SSH setup connection
*/
static CURLcode myssh_setup_connection(struct Curl_easy *data,
struct connectdata *conn)
{
- struct SSHPROTO *ssh;
- struct ssh_conn *sshc = &conn->proto.sshc;
+ struct SSHPROTO *sshp;
+ struct ssh_conn *sshc;
- if(!sshc->initialised) {
- Curl_dyn_init(&sshc->readdir_buf, CURL_PATH_MAX * 2);
- sshc->initialised = TRUE;
- }
+ sshc = calloc(1, sizeof(*sshc));
+ if(!sshc)
+ return CURLE_OUT_OF_MEMORY;
- data->req.p.ssh = ssh = calloc(1, sizeof(struct SSHPROTO));
- if(!ssh)
+ curlx_dyn_init(&sshc->readdir_buf, CURL_PATH_MAX * 2);
+ sshc->initialised = TRUE;
+ if(Curl_conn_meta_set(conn, CURL_META_SSH_CONN, sshc, myssh_conn_dtor))
+ return CURLE_OUT_OF_MEMORY;
+
+ sshp = calloc(1, sizeof(*sshp));
+ if(!sshp ||
+ Curl_meta_set(data, CURL_META_SSH_EASY, sshp, myssh_easy_dtor))
return CURLE_OUT_OF_MEMORY;
return CURLE_OK;
@@ -2107,15 +2178,15 @@ static Curl_send scp_send, sftp_send;
*/
static CURLcode myssh_connect(struct Curl_easy *data, bool *done)
{
- struct ssh_conn *ssh;
CURLcode result;
struct connectdata *conn = data->conn;
+ struct ssh_conn *sshc = Curl_conn_meta_get(conn, CURL_META_SSH_CONN);
+ struct SSHPROTO *ssh = Curl_meta_get(data, CURL_META_SSH_EASY);
curl_socket_t sock = conn->sock[FIRSTSOCKET];
int rc;
- /* initialize per-handle data if not already */
- if(!data->req.p.ssh)
- myssh_setup_connection(data, conn);
+ if(!sshc || !ssh)
+ return CURLE_FAILED_INIT;
/* We default to persistent connections. We set this already in this connect
function to make the reuse checks properly be able to check this bit. */
@@ -2130,10 +2201,8 @@ static CURLcode myssh_connect(struct Curl_easy *data, bool *done)
conn->send[FIRSTSOCKET] = sftp_send;
}
- ssh = &conn->proto.sshc;
-
- ssh->ssh_session = ssh_new();
- if(!ssh->ssh_session) {
+ sshc->ssh_session = ssh_new();
+ if(!sshc->ssh_session) {
failf(data, "Failure initialising ssh session");
return CURLE_FAILED_INIT;
}
@@ -2141,23 +2210,23 @@ static CURLcode myssh_connect(struct Curl_easy *data, bool *done)
if(conn->bits.ipv6_ip) {
char ipv6[MAX_IPADR_LEN];
msnprintf(ipv6, sizeof(ipv6), "[%s]", conn->host.name);
- rc = ssh_options_set(ssh->ssh_session, SSH_OPTIONS_HOST, ipv6);
+ rc = ssh_options_set(sshc->ssh_session, SSH_OPTIONS_HOST, ipv6);
}
else
- rc = ssh_options_set(ssh->ssh_session, SSH_OPTIONS_HOST, conn->host.name);
+ rc = ssh_options_set(sshc->ssh_session, SSH_OPTIONS_HOST, conn->host.name);
if(rc != SSH_OK) {
failf(data, "Could not set remote host");
return CURLE_FAILED_INIT;
}
- rc = ssh_options_parse_config(ssh->ssh_session, NULL);
+ rc = ssh_options_parse_config(sshc->ssh_session, NULL);
if(rc != SSH_OK) {
infof(data, "Could not parse SSH configuration files");
/* ignore */
}
- rc = ssh_options_set(ssh->ssh_session, SSH_OPTIONS_FD, &sock);
+ rc = ssh_options_set(sshc->ssh_session, SSH_OPTIONS_FD, &sock);
if(rc != SSH_OK) {
failf(data, "Could not set socket");
return CURLE_FAILED_INIT;
@@ -2165,7 +2234,7 @@ static CURLcode myssh_connect(struct Curl_easy *data, bool *done)
if(conn->user && conn->user[0] != '\0') {
infof(data, "User: %s", conn->user);
- rc = ssh_options_set(ssh->ssh_session, SSH_OPTIONS_USER, conn->user);
+ rc = ssh_options_set(sshc->ssh_session, SSH_OPTIONS_USER, conn->user);
if(rc != SSH_OK) {
failf(data, "Could not set user");
return CURLE_FAILED_INIT;
@@ -2174,7 +2243,7 @@ static CURLcode myssh_connect(struct Curl_easy *data, bool *done)
if(data->set.str[STRING_SSH_KNOWNHOSTS]) {
infof(data, "Known hosts: %s", data->set.str[STRING_SSH_KNOWNHOSTS]);
- rc = ssh_options_set(ssh->ssh_session, SSH_OPTIONS_KNOWNHOSTS,
+ rc = ssh_options_set(sshc->ssh_session, SSH_OPTIONS_KNOWNHOSTS,
data->set.str[STRING_SSH_KNOWNHOSTS]);
if(rc != SSH_OK) {
failf(data, "Could not set known hosts file path");
@@ -2183,7 +2252,7 @@ static CURLcode myssh_connect(struct Curl_easy *data, bool *done)
}
if(conn->remote_port) {
- rc = ssh_options_set(ssh->ssh_session, SSH_OPTIONS_PORT,
+ rc = ssh_options_set(sshc->ssh_session, SSH_OPTIONS_PORT,
&conn->remote_port);
if(rc != SSH_OK) {
failf(data, "Could not set remote port");
@@ -2192,7 +2261,7 @@ static CURLcode myssh_connect(struct Curl_easy *data, bool *done)
}
if(data->set.ssh_compression) {
- rc = ssh_options_set(ssh->ssh_session, SSH_OPTIONS_COMPRESSION,
+ rc = ssh_options_set(sshc->ssh_session, SSH_OPTIONS_COMPRESSION,
"zlib,zlib@openssh.com,none");
if(rc != SSH_OK) {
failf(data, "Could not set compression");
@@ -2200,12 +2269,12 @@ static CURLcode myssh_connect(struct Curl_easy *data, bool *done)
}
}
- ssh->privkey = NULL;
- ssh->pubkey = NULL;
+ sshc->privkey = NULL;
+ sshc->pubkey = NULL;
if(data->set.str[STRING_SSH_PUBLIC_KEY]) {
rc = ssh_pki_import_pubkey_file(data->set.str[STRING_SSH_PUBLIC_KEY],
- &ssh->pubkey);
+ &sshc->pubkey);
if(rc != SSH_OK) {
failf(data, "Could not load public key file");
return CURLE_FAILED_INIT;
@@ -2215,7 +2284,7 @@ static CURLcode myssh_connect(struct Curl_easy *data, bool *done)
/* we do not verify here, we do it at the state machine,
* after connection */
- state(data, SSH_INIT);
+ myssh_state(data, sshc, SSH_INIT);
result = myssh_multi_statemach(data, done);
@@ -2249,13 +2318,16 @@ CURLcode scp_perform(struct Curl_easy *data,
bool *connected, bool *dophase_done)
{
CURLcode result = CURLE_OK;
+ struct ssh_conn *sshc = Curl_conn_meta_get(data->conn, CURL_META_SSH_CONN);
DEBUGF(infof(data, "DO phase starts"));
*dophase_done = FALSE; /* not done yet */
+ if(!sshc)
+ return CURLE_FAILED_INIT;
/* start the first command in the DO phase */
- state(data, SSH_SCP_TRANS_INIT);
+ myssh_state(data, sshc, SSH_SCP_TRANS_INIT);
result = myssh_multi_statemach(data, dophase_done);
@@ -2273,9 +2345,11 @@ static CURLcode myssh_do_it(struct Curl_easy *data, bool *done)
CURLcode result;
bool connected = FALSE;
struct connectdata *conn = data->conn;
- struct ssh_conn *sshc = &conn->proto.sshc;
+ struct ssh_conn *sshc = Curl_conn_meta_get(conn, CURL_META_SSH_CONN);
*done = FALSE; /* default to false */
+ if(!sshc)
+ return CURLE_FAILED_INIT;
data->req.size = -1; /* make sure this is unknown at this point */
@@ -2296,10 +2370,17 @@ static CURLcode myssh_do_it(struct Curl_easy *data, bool *done)
return result;
}
-static void sshc_cleanup(struct ssh_conn *sshc, struct Curl_easy *data)
+static void sshc_cleanup(struct ssh_conn *sshc)
{
- (void)data;
if(sshc->initialised) {
+ if(sshc->sftp_file) {
+ sftp_close(sshc->sftp_file);
+ sshc->sftp_file = NULL;
+ }
+ if(sshc->sftp_session) {
+ sftp_free(sshc->sftp_session);
+ sshc->sftp_session = NULL;
+ }
if(sshc->ssh_session) {
ssh_free(sshc->ssh_session);
sshc->ssh_session = NULL;
@@ -2338,7 +2419,7 @@ static void sshc_cleanup(struct ssh_conn *sshc, struct Curl_easy *data)
Curl_safefree(sshc->rsa);
Curl_safefree(sshc->quote_path1);
Curl_safefree(sshc->quote_path2);
- Curl_dyn_free(&sshc->readdir_buf);
+ curlx_dyn_free(&sshc->readdir_buf);
Curl_safefree(sshc->readdir_linkPath);
SSH_STRING_FREE_CHAR(sshc->homedir);
sshc->initialised = FALSE;
@@ -2353,37 +2434,37 @@ static CURLcode scp_disconnect(struct Curl_easy *data,
bool dead_connection)
{
CURLcode result = CURLE_OK;
- struct ssh_conn *sshc = &conn->proto.sshc;
+ struct ssh_conn *sshc = Curl_conn_meta_get(conn, CURL_META_SSH_CONN);
+ struct SSHPROTO *sshp = Curl_meta_get(data, CURL_META_SSH_EASY);
(void) dead_connection;
- if(sshc->ssh_session) {
+ if(sshc && sshc->ssh_session && sshp) {
/* only if there is a session still around to use! */
- state(data, SSH_SESSION_DISCONNECT);
+ myssh_state(data, sshc, SSH_SESSION_DISCONNECT);
- result = myssh_block_statemach(data, TRUE);
+ result = myssh_block_statemach(data, sshc, sshp, TRUE);
}
- sshc_cleanup(sshc, data);
return result;
}
/* generic done function for both SCP and SFTP called from their specific
done functions */
-static CURLcode myssh_done(struct Curl_easy *data, CURLcode status)
+static CURLcode myssh_done(struct Curl_easy *data,
+ struct ssh_conn *sshc,
+ CURLcode status)
{
CURLcode result = CURLE_OK;
- struct SSHPROTO *protop = data->req.p.ssh;
+ struct SSHPROTO *sshp = Curl_meta_get(data, CURL_META_SSH_EASY);
- if(!status) {
+ if(!status && sshp) {
/* run the state-machine */
- result = myssh_block_statemach(data, FALSE);
+ result = myssh_block_statemach(data, sshc, sshp, FALSE);
}
else
result = status;
- if(protop)
- Curl_safefree(protop->path);
if(Curl_pgrsDone(data))
return CURLE_ABORTED_BY_CALLBACK;
@@ -2395,13 +2476,15 @@ static CURLcode myssh_done(struct Curl_easy *data, CURLcode status)
static CURLcode scp_done(struct Curl_easy *data, CURLcode status,
bool premature)
{
+ struct ssh_conn *sshc = Curl_conn_meta_get(data->conn, CURL_META_SSH_CONN);
(void) premature; /* not used */
+ if(!sshc)
+ return CURLE_FAILED_INIT;
if(!status)
- state(data, SSH_SCP_DONE);
-
- return myssh_done(data, status);
+ myssh_state(data, sshc, SSH_SCP_DONE);
+ return myssh_done(data, sshc, status);
}
static ssize_t scp_send(struct Curl_easy *data, int sockindex,
@@ -2409,17 +2492,22 @@ static ssize_t scp_send(struct Curl_easy *data, int sockindex,
{
int rc;
struct connectdata *conn = data->conn;
+ struct ssh_conn *sshc = Curl_conn_meta_get(conn, CURL_META_SSH_CONN);
(void) sockindex; /* we only support SCP on the fixed known primary socket */
- (void) err;
(void)eos;
- rc = ssh_scp_write(conn->proto.sshc.scp_session, mem, len);
+ if(!sshc) {
+ *err = CURLE_FAILED_INIT;
+ return -1;
+ }
+
+ rc = ssh_scp_write(sshc->scp_session, mem, len);
#if 0
/* The following code is misleading, mostly added as wishful thinking
* that libssh at some point will implement non-blocking ssh_scp_write/read.
* Currently rc can only be number of bytes read or SSH_ERROR. */
- myssh_block2waitfor(conn, (rc == SSH_AGAIN));
+ myssh_block2waitfor(conn, sshc, (rc == SSH_AGAIN));
if(rc == SSH_AGAIN) {
*err = CURLE_AGAIN;
@@ -2440,18 +2528,22 @@ static ssize_t scp_recv(struct Curl_easy *data, int sockindex,
{
ssize_t nread;
struct connectdata *conn = data->conn;
- (void) err;
+ struct ssh_conn *sshc = Curl_conn_meta_get(conn, CURL_META_SSH_CONN);
(void) sockindex; /* we only support SCP on the fixed known primary socket */
+ if(!sshc) {
+ *err = CURLE_FAILED_INIT;
+ return -1;
+ }
/* libssh returns int */
- nread = ssh_scp_read(conn->proto.sshc.scp_session, mem, len);
+ nread = ssh_scp_read(sshc->scp_session, mem, len);
#if 0
/* The following code is misleading, mostly added as wishful thinking
* that libssh at some point will implement non-blocking ssh_scp_write/read.
* Currently rc can only be SSH_OK or SSH_ERROR. */
- myssh_block2waitfor(conn, (nread == SSH_AGAIN));
+ myssh_block2waitfor(conn, sshc, (nread == SSH_AGAIN));
if(nread == SSH_AGAIN) {
*err = CURLE_AGAIN;
nread = -1;
@@ -2479,14 +2571,17 @@ CURLcode sftp_perform(struct Curl_easy *data,
bool *connected,
bool *dophase_done)
{
+ struct ssh_conn *sshc = Curl_conn_meta_get(data->conn, CURL_META_SSH_CONN);
CURLcode result = CURLE_OK;
DEBUGF(infof(data, "DO phase starts"));
*dophase_done = FALSE; /* not done yet */
+ if(!sshc)
+ return CURLE_FAILED_INIT;
/* start the first command in the DO phase */
- state(data, SSH_SFTP_QUOTE_INIT);
+ myssh_state(data, sshc, SSH_SFTP_QUOTE_INIT);
/* run the state-machine */
result = myssh_multi_statemach(data, dophase_done);
@@ -2518,21 +2613,20 @@ static CURLcode sftp_disconnect(struct Curl_easy *data,
struct connectdata *conn,
bool dead_connection)
{
- struct ssh_conn *sshc = &conn->proto.sshc;
+ struct ssh_conn *sshc = Curl_conn_meta_get(conn, CURL_META_SSH_CONN);
+ struct SSHPROTO *sshp = Curl_meta_get(data, CURL_META_SSH_EASY);
CURLcode result = CURLE_OK;
(void) dead_connection;
DEBUGF(infof(data, "SSH DISCONNECT starts now"));
- if(conn->proto.sshc.ssh_session) {
+ if(sshc && sshc->ssh_session && sshp) {
/* only if there is a session still around to use! */
- state(data, SSH_SFTP_SHUTDOWN);
- result = myssh_block_statemach(data, TRUE);
+ myssh_state(data, sshc, SSH_SFTP_SHUTDOWN);
+ result = myssh_block_statemach(data, sshc, sshp, TRUE);
}
DEBUGF(infof(data, "SSH DISCONNECT is done"));
- sshc_cleanup(sshc, data);
-
return result;
}
@@ -2540,17 +2634,19 @@ static CURLcode sftp_done(struct Curl_easy *data, CURLcode status,
bool premature)
{
struct connectdata *conn = data->conn;
- struct ssh_conn *sshc = &conn->proto.sshc;
+ struct ssh_conn *sshc = Curl_conn_meta_get(conn, CURL_META_SSH_CONN);
+ if(!sshc)
+ return CURLE_FAILED_INIT;
if(!status) {
/* Post quote commands are executed after the SFTP_CLOSE state to avoid
errors that could happen due to open file handles during POSTQUOTE
operation */
if(!premature && data->set.postquote && !conn->bits.retry)
sshc->nextstate = SSH_SFTP_POSTQUOTE_INIT;
- state(data, SSH_SFTP_CLOSE);
+ myssh_state(data, sshc, SSH_SFTP_CLOSE);
}
- return myssh_done(data, status);
+ return myssh_done(data, sshc, status);
}
/* return number of sent bytes */
@@ -2560,28 +2656,33 @@ static ssize_t sftp_send(struct Curl_easy *data, int sockindex,
{
ssize_t nwrite;
struct connectdata *conn = data->conn;
+ struct ssh_conn *sshc = Curl_conn_meta_get(conn, CURL_META_SSH_CONN);
(void)sockindex;
(void)eos;
+ if(!sshc) {
+ *err = CURLE_FAILED_INIT;
+ return -1;
+ }
/* limit the writes to the maximum specified in Section 3 of
* https://datatracker.ietf.org/doc/html/draft-ietf-secsh-filexfer-02
*/
if(len > 32768)
len = 32768;
#if LIBSSH_VERSION_INT > SSH_VERSION_INT(0, 11, 0)
- switch(conn->proto.sshc.sftp_send_state) {
+ switch(sshc->sftp_send_state) {
case 0:
- sftp_file_set_nonblocking(conn->proto.sshc.sftp_file);
- if(sftp_aio_begin_write(conn->proto.sshc.sftp_file, mem, len,
- &conn->proto.sshc.sftp_aio) == SSH_ERROR) {
+ sftp_file_set_nonblocking(sshc->sftp_file);
+ if(sftp_aio_begin_write(sshc->sftp_file, mem, len,
+ &sshc->sftp_aio) == SSH_ERROR) {
*err = CURLE_SEND_ERROR;
return -1;
}
- conn->proto.sshc.sftp_send_state = 1;
+ sshc->sftp_send_state = 1;
FALLTHROUGH();
case 1:
- nwrite = sftp_aio_wait_write(&conn->proto.sshc.sftp_aio);
- myssh_block2waitfor(conn, (nwrite == SSH_AGAIN) ? TRUE : FALSE);
+ nwrite = sftp_aio_wait_write(&sshc->sftp_aio);
+ myssh_block2waitfor(conn, sshc, (nwrite == SSH_AGAIN) ? TRUE : FALSE);
if(nwrite == SSH_AGAIN) {
*err = CURLE_AGAIN;
return 0;
@@ -2590,20 +2691,20 @@ static ssize_t sftp_send(struct Curl_easy *data, int sockindex,
*err = CURLE_SEND_ERROR;
return -1;
}
- if(conn->proto.sshc.sftp_aio) {
- sftp_aio_free(conn->proto.sshc.sftp_aio);
- conn->proto.sshc.sftp_aio = NULL;
+ if(sshc->sftp_aio) {
+ sftp_aio_free(sshc->sftp_aio);
+ sshc->sftp_aio = NULL;
}
- conn->proto.sshc.sftp_send_state = 0;
+ sshc->sftp_send_state = 0;
return nwrite;
default:
/* we never reach here */
return -1;
}
#else
- nwrite = sftp_write(conn->proto.sshc.sftp_file, mem, len);
+ nwrite = sftp_write(sshc->sftp_file, mem, len);
- myssh_block2waitfor(conn, FALSE);
+ myssh_block2waitfor(conn, sshc, FALSE);
#if 0 /* not returned by libssh on write */
if(nwrite == SSH_AGAIN) {
@@ -2630,29 +2731,31 @@ static ssize_t sftp_recv(struct Curl_easy *data, int sockindex,
{
ssize_t nread;
struct connectdata *conn = data->conn;
+ struct ssh_conn *sshc = Curl_conn_meta_get(conn, CURL_META_SSH_CONN);
(void)sockindex;
DEBUGASSERT(len < CURL_MAX_READ_SIZE);
+ if(!sshc) {
+ *err = CURLE_FAILED_INIT;
+ return -1;
+ }
- switch(conn->proto.sshc.sftp_recv_state) {
+ switch(sshc->sftp_recv_state) {
case 0:
- conn->proto.sshc.sftp_file_index =
- sftp_async_read_begin(conn->proto.sshc.sftp_file,
- (uint32_t)len);
- if(conn->proto.sshc.sftp_file_index < 0) {
+ sshc->sftp_file_index =
+ sftp_async_read_begin(sshc->sftp_file, (uint32_t)len);
+ if(sshc->sftp_file_index < 0) {
*err = CURLE_RECV_ERROR;
return -1;
}
FALLTHROUGH();
case 1:
- conn->proto.sshc.sftp_recv_state = 1;
-
- nread = sftp_async_read(conn->proto.sshc.sftp_file,
- mem, (uint32_t)len,
- (uint32_t)conn->proto.sshc.sftp_file_index);
+ sshc->sftp_recv_state = 1;
+ nread = sftp_async_read(sshc->sftp_file, mem, (uint32_t)len,
+ (uint32_t)sshc->sftp_file_index);
- myssh_block2waitfor(conn, (nread == SSH_AGAIN));
+ myssh_block2waitfor(conn, sshc, (nread == SSH_AGAIN));
if(nread == SSH_AGAIN) {
*err = CURLE_AGAIN;
@@ -2663,7 +2766,7 @@ static ssize_t sftp_recv(struct Curl_easy *data, int sockindex,
return -1;
}
- conn->proto.sshc.sftp_recv_state = 0;
+ sshc->sftp_recv_state = 0;
return nread;
default:
@@ -2672,12 +2775,11 @@ static ssize_t sftp_recv(struct Curl_easy *data, int sockindex,
}
}
-static void sftp_quote(struct Curl_easy *data)
+static void sftp_quote(struct Curl_easy *data,
+ struct ssh_conn *sshc,
+ struct SSHPROTO *sshp)
{
const char *cp;
- struct connectdata *conn = data->conn;
- struct SSHPROTO *protop = data->req.p.ssh;
- struct ssh_conn *sshc = &conn->proto.sshc;
CURLcode result;
/*
@@ -2698,11 +2800,10 @@ static void sftp_quote(struct Curl_easy *data)
if(strcasecompare("pwd", cmd)) {
/* output debug output if that is requested */
- char *tmp = aprintf("257 \"%s\" is current directory.\n",
- protop->path);
+ char *tmp = aprintf("257 \"%s\" is current directory.\n", sshp->path);
if(!tmp) {
sshc->actualcode = CURLE_OUT_OF_MEMORY;
- state(data, SSH_SFTP_CLOSE);
+ myssh_state(data, sshc, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
return;
}
@@ -2715,12 +2816,12 @@ static void sftp_quote(struct Curl_easy *data)
result = Curl_client_write(data, CLIENTWRITE_HEADER, tmp, strlen(tmp));
free(tmp);
if(result) {
- state(data, SSH_SFTP_CLOSE);
+ myssh_state(data, sshc, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = result;
}
else
- state(data, SSH_SFTP_NEXT_QUOTE);
+ myssh_state(data, sshc, SSH_SFTP_NEXT_QUOTE);
return;
}
@@ -2731,7 +2832,7 @@ static void sftp_quote(struct Curl_easy *data)
cp = strchr(cmd, ' ');
if(!cp) {
failf(data, "Syntax error in SFTP command. Supply parameter(s)");
- state(data, SSH_SFTP_CLOSE);
+ myssh_state(data, sshc, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = CURLE_QUOTE_ERROR;
return;
@@ -2747,7 +2848,7 @@ static void sftp_quote(struct Curl_easy *data)
failf(data, "Out of memory");
else
failf(data, "Syntax error: Bad first parameter");
- state(data, SSH_SFTP_CLOSE);
+ myssh_state(data, sshc, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = result;
return;
@@ -2776,13 +2877,13 @@ static void sftp_quote(struct Curl_easy *data)
failf(data, "Syntax error in chgrp/chmod/chown/atime/mtime: "
"Bad second parameter");
Curl_safefree(sshc->quote_path1);
- state(data, SSH_SFTP_CLOSE);
+ myssh_state(data, sshc, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = result;
return;
}
sshc->quote_attrs = NULL;
- state(data, SSH_SFTP_QUOTE_STAT);
+ myssh_state(data, sshc, SSH_SFTP_QUOTE_STAT);
return;
}
if(!strncmp(cmd, "ln ", 3) ||
@@ -2797,17 +2898,17 @@ static void sftp_quote(struct Curl_easy *data)
else
failf(data, "Syntax error in ln/symlink: Bad second parameter");
Curl_safefree(sshc->quote_path1);
- state(data, SSH_SFTP_CLOSE);
+ myssh_state(data, sshc, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = result;
return;
}
- state(data, SSH_SFTP_QUOTE_SYMLINK);
+ myssh_state(data, sshc, SSH_SFTP_QUOTE_SYMLINK);
return;
}
else if(!strncmp(cmd, "mkdir ", 6)) {
/* create dir */
- state(data, SSH_SFTP_QUOTE_MKDIR);
+ myssh_state(data, sshc, SSH_SFTP_QUOTE_MKDIR);
return;
}
else if(!strncmp(cmd, "rename ", 7)) {
@@ -2821,26 +2922,26 @@ static void sftp_quote(struct Curl_easy *data)
else
failf(data, "Syntax error in rename: Bad second parameter");
Curl_safefree(sshc->quote_path1);
- state(data, SSH_SFTP_CLOSE);
+ myssh_state(data, sshc, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = result;
return;
}
- state(data, SSH_SFTP_QUOTE_RENAME);
+ myssh_state(data, sshc, SSH_SFTP_QUOTE_RENAME);
return;
}
else if(!strncmp(cmd, "rmdir ", 6)) {
/* delete dir */
- state(data, SSH_SFTP_QUOTE_RMDIR);
+ myssh_state(data, sshc, SSH_SFTP_QUOTE_RMDIR);
return;
}
else if(!strncmp(cmd, "rm ", 3)) {
- state(data, SSH_SFTP_QUOTE_UNLINK);
+ myssh_state(data, sshc, SSH_SFTP_QUOTE_UNLINK);
return;
}
#ifdef HAS_STATVFS_SUPPORT
else if(!strncmp(cmd, "statvfs ", 8)) {
- state(data, SSH_SFTP_QUOTE_STATVFS);
+ myssh_state(data, sshc, SSH_SFTP_QUOTE_STATVFS);
return;
}
#endif
@@ -2848,15 +2949,14 @@ static void sftp_quote(struct Curl_easy *data)
failf(data, "Unknown SFTP command");
Curl_safefree(sshc->quote_path1);
Curl_safefree(sshc->quote_path2);
- state(data, SSH_SFTP_CLOSE);
+ myssh_state(data, sshc, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = CURLE_QUOTE_ERROR;
}
-static void sftp_quote_stat(struct Curl_easy *data)
+static void sftp_quote_stat(struct Curl_easy *data,
+ struct ssh_conn *sshc)
{
- struct connectdata *conn = data->conn;
- struct ssh_conn *sshc = &conn->proto.sshc;
char *cmd = sshc->quote_item->data;
sshc->acceptfail = FALSE;
@@ -2883,7 +2983,7 @@ static void sftp_quote_stat(struct Curl_easy *data)
Curl_safefree(sshc->quote_path2);
failf(data, "Attempt to get SFTP stats failed: %d",
sftp_get_error(sshc->sftp_session));
- state(data, SSH_SFTP_CLOSE);
+ myssh_state(data, sshc, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = CURLE_QUOTE_ERROR;
return;
@@ -2893,14 +2993,14 @@ static void sftp_quote_stat(struct Curl_easy *data)
if(!strncmp(cmd, "chgrp", 5)) {
const char *p = sshc->quote_path1;
curl_off_t gid;
- (void)Curl_str_number(&p, &gid, UINT_MAX);
+ (void)curlx_str_number(&p, &gid, UINT_MAX);
sshc->quote_attrs->gid = (uint32_t)gid;
if(sshc->quote_attrs->gid == 0 && !ISDIGIT(sshc->quote_path1[0]) &&
!sshc->acceptfail) {
Curl_safefree(sshc->quote_path1);
Curl_safefree(sshc->quote_path2);
failf(data, "Syntax error: chgrp gid not a number");
- state(data, SSH_SFTP_CLOSE);
+ myssh_state(data, sshc, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = CURLE_QUOTE_ERROR;
return;
@@ -2910,11 +3010,11 @@ static void sftp_quote_stat(struct Curl_easy *data)
else if(!strncmp(cmd, "chmod", 5)) {
curl_off_t perms;
const char *p = sshc->quote_path1;
- if(Curl_str_octal(&p, &perms, 07777)) {
+ if(curlx_str_octal(&p, &perms, 07777)) {
Curl_safefree(sshc->quote_path1);
Curl_safefree(sshc->quote_path2);
failf(data, "Syntax error: chmod permissions not a number");
- state(data, SSH_SFTP_CLOSE);
+ myssh_state(data, sshc, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = CURLE_QUOTE_ERROR;
return;
@@ -2925,13 +3025,13 @@ static void sftp_quote_stat(struct Curl_easy *data)
else if(!strncmp(cmd, "chown", 5)) {
const char *p = sshc->quote_path1;
curl_off_t uid;
- (void)Curl_str_number(&p, &uid, UINT_MAX);
+ (void)curlx_str_number(&p, &uid, UINT_MAX);
if(sshc->quote_attrs->uid == 0 && !ISDIGIT(sshc->quote_path1[0]) &&
!sshc->acceptfail) {
Curl_safefree(sshc->quote_path1);
Curl_safefree(sshc->quote_path2);
failf(data, "Syntax error: chown uid not a number");
- state(data, SSH_SFTP_CLOSE);
+ myssh_state(data, sshc, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = CURLE_QUOTE_ERROR;
return;
@@ -2955,7 +3055,7 @@ static void sftp_quote_stat(struct Curl_easy *data)
if(fail) {
Curl_safefree(sshc->quote_path1);
Curl_safefree(sshc->quote_path2);
- state(data, SSH_SFTP_CLOSE);
+ myssh_state(data, sshc, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = CURLE_QUOTE_ERROR;
return;
@@ -2969,7 +3069,7 @@ static void sftp_quote_stat(struct Curl_easy *data)
}
/* Now send the completed structure... */
- state(data, SSH_SFTP_QUOTE_SETSTAT);
+ myssh_state(data, sshc, SSH_SFTP_QUOTE_SETSTAT);
return;
}
diff --git a/libs/libcurl/src/vssh/libssh2.c b/libs/libcurl/src/vssh/libssh2.c
index 4ecf198e17..7bf1ed9fb5 100644
--- a/libs/libcurl/src/vssh/libssh2.c
+++ b/libs/libcurl/src/vssh/libssh2.c
@@ -24,7 +24,7 @@
/* #define CURL_LIBSSH2_DEBUG */
-#include "curl_setup.h"
+#include "../curl_setup.h"
#ifdef USE_LIBSSH2
@@ -49,45 +49,45 @@
#endif
#include <curl/curl.h>
-#include "urldata.h"
-#include "sendf.h"
-#include "hostip.h"
-#include "progress.h"
-#include "transfer.h"
-#include "escape.h"
-#include "http.h" /* for HTTP proxy tunnel stuff */
+#include "../urldata.h"
+#include "../sendf.h"
+#include "../hostip.h"
+#include "../progress.h"
+#include "../transfer.h"
+#include "../escape.h"
+#include "../http.h" /* for HTTP proxy tunnel stuff */
#include "ssh.h"
-#include "url.h"
-#include "speedcheck.h"
-#include "getinfo.h"
-#include "strdup.h"
-#include "strcase.h"
-#include "vtls/vtls.h"
-#include "cfilters.h"
-#include "connect.h"
-#include "inet_ntop.h"
-#include "parsedate.h" /* for the week day and month names */
-#include "sockaddr.h" /* required for Curl_sockaddr_storage */
-#include "multiif.h"
-#include "select.h"
-#include "warnless.h"
+#include "../url.h"
+#include "../speedcheck.h"
+#include "../getinfo.h"
+#include "../strdup.h"
+#include "../strcase.h"
+#include "../vtls/vtls.h"
+#include "../cfilters.h"
+#include "../connect.h"
+#include "../inet_ntop.h"
+#include "../parsedate.h" /* for the week day and month names */
+#include "../sockaddr.h" /* required for Curl_sockaddr_storage */
+#include "../multiif.h"
+#include "../select.h"
+#include "../curlx/warnless.h"
#include "curl_path.h"
-#include "strparse.h"
-#include <curl_base64.h> /* for base64 encoding/decoding */
-#include <curl_sha256.h>
-
+#include "../curlx/strparse.h"
+#include "../curlx/base64.h" /* for base64 encoding/decoding */
+#include "../curl_sha256.h"
/* The last 3 #include files should be in this order */
-#include "curl_printf.h"
-#include "curl_memory.h"
-#include "memdebug.h"
+#include "../curl_printf.h"
+#include "../curl_memory.h"
+#include "../memdebug.h"
/* Local functions: */
static const char *sftp_libssh2_strerror(unsigned long err);
static LIBSSH2_ALLOC_FUNC(my_libssh2_malloc);
static LIBSSH2_REALLOC_FUNC(my_libssh2_realloc);
static LIBSSH2_FREE_FUNC(my_libssh2_free);
-static CURLcode ssh_force_knownhost_key_type(struct Curl_easy *data);
+static CURLcode ssh_force_knownhost_key_type(struct Curl_easy *data,
+ struct ssh_conn *sshc);
static CURLcode ssh_connect(struct Curl_easy *data, bool *done);
static CURLcode ssh_multi_statemach(struct Curl_easy *data, bool *done);
static CURLcode ssh_do(struct Curl_easy *data, bool *done);
@@ -106,8 +106,8 @@ static int ssh_getsock(struct Curl_easy *data, struct connectdata *conn,
static CURLcode ssh_setup_connection(struct Curl_easy *data,
struct connectdata *conn);
static void ssh_attach(struct Curl_easy *data, struct connectdata *conn);
-static int sshc_cleanup(struct ssh_conn *sshc, struct Curl_easy *data,
- bool block);
+static CURLcode sshc_cleanup(struct ssh_conn *sshc, struct Curl_easy *data,
+ bool block);
/*
* SCP protocol handler.
*/
@@ -299,10 +299,10 @@ static LIBSSH2_FREE_FUNC(my_libssh2_free)
* SSH State machine related code
*/
/* This is the ONLY way to change SSH state! */
-static void state(struct Curl_easy *data, sshstate nowstate)
+static void myssh_state(struct Curl_easy *data,
+ struct ssh_conn *sshc,
+ sshstate nowstate)
{
- struct connectdata *conn = data->conn;
- struct ssh_conn *sshc = &conn->proto.sshc;
#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
/* for debug purposes */
static const char * const names[] = {
@@ -376,7 +376,7 @@ static void state(struct Curl_easy *data, sshstate nowstate)
(void *)sshc, names[sshc->state], names[nowstate]);
}
#endif
-
+ (void)data;
sshc->state = nowstate;
}
@@ -429,7 +429,8 @@ static enum curl_khtype convert_ssh2_keytype(int sshkeytype)
return keytype;
}
-static CURLcode ssh_knownhost(struct Curl_easy *data)
+static CURLcode ssh_knownhost(struct Curl_easy *data,
+ struct ssh_conn *sshc)
{
int sshkeytype = 0;
size_t keylen = 0;
@@ -439,7 +440,6 @@ static CURLcode ssh_knownhost(struct Curl_easy *data)
if(data->set.str[STRING_SSH_KNOWNHOSTS]) {
/* we are asked to verify the host against a file */
struct connectdata *conn = data->conn;
- struct ssh_conn *sshc = &conn->proto.sshc;
struct libssh2_knownhost *host = NULL;
const char *remotekey = libssh2_session_hostkey(sshc->ssh_session,
&keylen, &sshkeytype);
@@ -544,11 +544,11 @@ static CURLcode ssh_knownhost(struct Curl_easy *data)
switch(rc) {
default: /* unknown return codes will equal reject */
case CURLKHSTAT_REJECT:
- state(data, SSH_SESSION_FREE);
+ myssh_state(data, sshc, SSH_SESSION_FREE);
FALLTHROUGH();
case CURLKHSTAT_DEFER:
/* DEFER means bail out but keep the SSH_HOSTKEY state */
- result = sshc->actualcode = CURLE_PEER_FAILED_VERIFICATION;
+ result = CURLE_PEER_FAILED_VERIFICATION;
break;
case CURLKHSTAT_FINE_REPLACE:
/* remove old host+key that does not match */
@@ -590,10 +590,9 @@ static CURLcode ssh_knownhost(struct Curl_easy *data)
return result;
}
-static CURLcode ssh_check_fingerprint(struct Curl_easy *data)
+static CURLcode ssh_check_fingerprint(struct Curl_easy *data,
+ struct ssh_conn *sshc)
{
- struct connectdata *conn = data->conn;
- struct ssh_conn *sshc = &conn->proto.sshc;
const char *pubkey_md5 = data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5];
const char *pubkey_sha256 = data->set.str[STRING_SSH_HOST_PUBLIC_KEY_SHA256];
@@ -629,25 +628,22 @@ static CURLcode ssh_check_fingerprint(struct Curl_easy *data)
failf(data,
"Denied establishing ssh session: sha256 fingerprint "
"not available");
- state(data, SSH_SESSION_FREE);
- sshc->actualcode = CURLE_PEER_FAILED_VERIFICATION;
- return sshc->actualcode;
+ myssh_state(data, sshc, SSH_SESSION_FREE);
+ return CURLE_PEER_FAILED_VERIFICATION;
}
/* The length of fingerprint is 32 bytes for SHA256.
* See libssh2_hostkey_hash documentation. */
- if(Curl_base64_encode(fingerprint, 32, &fingerprint_b64,
- &fingerprint_b64_len) != CURLE_OK) {
- state(data, SSH_SESSION_FREE);
- sshc->actualcode = CURLE_PEER_FAILED_VERIFICATION;
- return sshc->actualcode;
+ if(curlx_base64_encode(fingerprint, 32, &fingerprint_b64,
+ &fingerprint_b64_len) != CURLE_OK) {
+ myssh_state(data, sshc, SSH_SESSION_FREE);
+ return CURLE_PEER_FAILED_VERIFICATION;
}
if(!fingerprint_b64) {
failf(data, "sha256 fingerprint could not be encoded");
- state(data, SSH_SESSION_FREE);
- sshc->actualcode = CURLE_PEER_FAILED_VERIFICATION;
- return sshc->actualcode;
+ myssh_state(data, sshc, SSH_SESSION_FREE);
+ return CURLE_PEER_FAILED_VERIFICATION;
}
infof(data, "SSH SHA256 fingerprint: %s", fingerprint_b64);
@@ -672,9 +668,8 @@ static CURLcode ssh_check_fingerprint(struct Curl_easy *data)
"Denied establishing ssh session: mismatch sha256 fingerprint. "
"Remote %s is not equal to %s", fingerprint_b64, pubkey_sha256);
free(fingerprint_b64);
- state(data, SSH_SESSION_FREE);
- sshc->actualcode = CURLE_PEER_FAILED_VERIFICATION;
- return sshc->actualcode;
+ myssh_state(data, sshc, SSH_SESSION_FREE);
+ return CURLE_PEER_FAILED_VERIFICATION;
}
free(fingerprint_b64);
@@ -712,9 +707,8 @@ static CURLcode ssh_check_fingerprint(struct Curl_easy *data)
"Denied establishing ssh session: md5 fingerprint "
"not available");
}
- state(data, SSH_SESSION_FREE);
- sshc->actualcode = CURLE_PEER_FAILED_VERIFICATION;
- return sshc->actualcode;
+ myssh_state(data, sshc, SSH_SESSION_FREE);
+ return CURLE_PEER_FAILED_VERIFICATION;
}
infof(data, "MD5 checksum match");
}
@@ -734,20 +728,18 @@ static CURLcode ssh_check_fingerprint(struct Curl_easy *data)
(int)keytype, remotekey, keylen);
Curl_set_in_callback(data, FALSE);
if(rc!= CURLKHMATCH_OK) {
- state(data, SSH_SESSION_FREE);
- sshc->actualcode = CURLE_PEER_FAILED_VERIFICATION;
- return sshc->actualcode;
+ myssh_state(data, sshc, SSH_SESSION_FREE);
+ return CURLE_PEER_FAILED_VERIFICATION;
}
}
else {
- state(data, SSH_SESSION_FREE);
- sshc->actualcode = CURLE_PEER_FAILED_VERIFICATION;
- return sshc->actualcode;
+ myssh_state(data, sshc, SSH_SESSION_FREE);
+ return CURLE_PEER_FAILED_VERIFICATION;
}
return CURLE_OK;
}
else {
- return ssh_knownhost(data);
+ return ssh_knownhost(data, sshc);
}
}
else {
@@ -760,7 +752,8 @@ static CURLcode ssh_check_fingerprint(struct Curl_easy *data)
* ssh_force_knownhost_key_type() will check the known hosts file and try to
* force a specific public key type from the server if an entry is found.
*/
-static CURLcode ssh_force_knownhost_key_type(struct Curl_easy *data)
+static CURLcode ssh_force_knownhost_key_type(struct Curl_easy *data,
+ struct ssh_conn *sshc)
{
CURLcode result = CURLE_OK;
@@ -789,7 +782,6 @@ static CURLcode ssh_force_knownhost_key_type(struct Curl_easy *data)
const char *hostkey_method = NULL;
struct connectdata *conn = data->conn;
- struct ssh_conn *sshc = &conn->proto.sshc;
struct libssh2_knownhost* store = NULL;
const char *kh_name_end = NULL;
size_t kh_name_size = 0;
@@ -942,7 +934,7 @@ static CURLcode sftp_quote(struct Curl_easy *data,
result = Curl_client_write(data, CLIENTWRITE_HEADER, tmp, strlen(tmp));
free(tmp);
if(!result)
- state(data, SSH_SFTP_NEXT_QUOTE);
+ myssh_state(data, sshc, SSH_SFTP_NEXT_QUOTE);
return result;
}
@@ -989,7 +981,7 @@ static CURLcode sftp_quote(struct Curl_easy *data,
return result;
}
memset(&sshp->quote_attrs, 0, sizeof(LIBSSH2_SFTP_ATTRIBUTES));
- state(data, SSH_SFTP_QUOTE_STAT);
+ myssh_state(data, sshc, SSH_SFTP_QUOTE_STAT);
return result;
}
if(!strncmp(cmd, "ln ", 3) ||
@@ -1004,12 +996,12 @@ static CURLcode sftp_quote(struct Curl_easy *data,
Curl_safefree(sshc->quote_path1);
return result;
}
- state(data, SSH_SFTP_QUOTE_SYMLINK);
+ myssh_state(data, sshc, SSH_SFTP_QUOTE_SYMLINK);
return result;
}
else if(!strncmp(cmd, "mkdir ", 6)) {
/* create dir */
- state(data, SSH_SFTP_QUOTE_MKDIR);
+ myssh_state(data, sshc, SSH_SFTP_QUOTE_MKDIR);
return result;
}
else if(!strncmp(cmd, "rename ", 7)) {
@@ -1023,20 +1015,20 @@ static CURLcode sftp_quote(struct Curl_easy *data,
Curl_safefree(sshc->quote_path1);
return result;
}
- state(data, SSH_SFTP_QUOTE_RENAME);
+ myssh_state(data, sshc, SSH_SFTP_QUOTE_RENAME);
return result;
}
else if(!strncmp(cmd, "rmdir ", 6)) {
/* delete dir */
- state(data, SSH_SFTP_QUOTE_RMDIR);
+ myssh_state(data, sshc, SSH_SFTP_QUOTE_RMDIR);
return result;
}
else if(!strncmp(cmd, "rm ", 3)) {
- state(data, SSH_SFTP_QUOTE_UNLINK);
+ myssh_state(data, sshc, SSH_SFTP_QUOTE_UNLINK);
return result;
}
else if(!strncmp(cmd, "statvfs ", 8)) {
- state(data, SSH_SFTP_QUOTE_STATVFS);
+ myssh_state(data, sshc, SSH_SFTP_QUOTE_STATVFS);
return result;
}
@@ -1102,6 +1094,7 @@ sftp_upload_init(struct Curl_easy *data,
LIBSSH2_SFTP_OPENFILE);
if(!sshc->sftp_handle) {
+ CURLcode result;
unsigned long sftperr;
int rc = libssh2_session_last_errno(sshc->ssh_session);
@@ -1118,12 +1111,10 @@ sftp_upload_init(struct Curl_easy *data,
sftperr = LIBSSH2_FX_OK; /* not an sftp error at all */
if(sshc->secondCreateDirs) {
- state(data, SSH_SFTP_CLOSE);
- sshc->actualcode = sftperr != LIBSSH2_FX_OK ?
- sftp_libssh2_error_to_CURLE(sftperr) : CURLE_SSH;
+ myssh_state(data, sshc, SSH_SFTP_CLOSE);
failf(data, "Creating the dir/file failed: %s",
sftp_libssh2_strerror(sftperr));
- return CURLE_OK;
+ return sftp_libssh2_error_to_CURLE(sftperr);
}
if(((sftperr == LIBSSH2_FX_NO_SUCH_FILE) ||
(sftperr == LIBSSH2_FX_FAILURE) ||
@@ -1132,24 +1123,23 @@ sftp_upload_init(struct Curl_easy *data,
(strlen(sshp->path) > 1))) {
/* try to create the path remotely */
sshc->secondCreateDirs = 1;
- state(data, SSH_SFTP_CREATE_DIRS_INIT);
+ myssh_state(data, sshc, SSH_SFTP_CREATE_DIRS_INIT);
return CURLE_OK;
}
- state(data, SSH_SFTP_CLOSE);
- sshc->actualcode = sftperr != LIBSSH2_FX_OK ?
- sftp_libssh2_error_to_CURLE(sftperr) : CURLE_SSH;
- if(!sshc->actualcode) {
+ myssh_state(data, sshc, SSH_SFTP_CLOSE);
+ result = sftp_libssh2_error_to_CURLE(sftperr);
+ if(!result) {
/* Sometimes, for some reason libssh2_sftp_last_error() returns zero
even though libssh2_sftp_open() failed previously! We need to
work around that! */
- sshc->actualcode = CURLE_SSH;
+ result = CURLE_SSH;
sftperr = LIBSSH2_FX_OK;
}
failf(data, "Upload failed: %s (%lu/%d)",
sftperr != LIBSSH2_FX_OK ?
sftp_libssh2_strerror(sftperr) : "ssh error",
sftperr, rc);
- return sshc->actualcode;
+ return result;
}
/* If we have a restart point then we need to seek to the correct
@@ -1230,13 +1220,15 @@ sftp_upload_init(struct Curl_easy *data,
timeout here */
Curl_expire(data, 0, EXPIRE_RUN_NOW);
- state(data, SSH_STOP);
+ myssh_state(data, sshc, SSH_STOP);
return CURLE_OK;
}
-static CURLcode
-sftp_pkey_init(struct Curl_easy *data,
- struct ssh_conn *sshc)
+/* make sure that this does not collide with an actual libssh2 error code */
+#define ERROR_LIBBSH2 1
+
+static CURLcode ssh_state_pkey_init(struct Curl_easy *data,
+ struct ssh_conn *sshc)
{
/*
* Check the supported auth types in the order I feel is most secure
@@ -1307,8 +1299,7 @@ sftp_pkey_init(struct Curl_easy *data,
if(out_of_memory || !sshc->rsa) {
Curl_safefree(sshc->rsa);
Curl_safefree(sshc->rsa_pub);
- state(data, SSH_SESSION_FREE);
- sshc->actualcode = CURLE_OUT_OF_MEMORY;
+ myssh_state(data, sshc, SSH_SESSION_FREE);
return CURLE_OUT_OF_MEMORY;
}
@@ -1320,12 +1311,12 @@ sftp_pkey_init(struct Curl_easy *data,
infof(data, "Using SSH public key file '%s'", sshc->rsa_pub);
infof(data, "Using SSH private key file '%s'", sshc->rsa);
- state(data, SSH_AUTH_PKEY);
+ myssh_state(data, sshc, SSH_AUTH_PKEY);
}
else {
- state(data, SSH_AUTH_PASS_INIT);
+ myssh_state(data, sshc, SSH_AUTH_PASS_INIT);
}
- return CURLE_OK;
+ return 0;
}
static CURLcode
@@ -1372,7 +1363,7 @@ sftp_quote_stat(struct Curl_easy *data,
if(!strncmp(cmd, "chgrp", 5)) {
const char *p = sshc->quote_path1;
curl_off_t gid;
- (void)Curl_str_number(&p, &gid, ULONG_MAX);
+ (void)curlx_str_number(&p, &gid, ULONG_MAX);
sshp->quote_attrs.gid = (unsigned long)gid;
sshp->quote_attrs.flags = LIBSSH2_SFTP_ATTR_UIDGID;
if(sshp->quote_attrs.gid == 0 && !ISDIGIT(sshc->quote_path1[0]) &&
@@ -1385,7 +1376,7 @@ sftp_quote_stat(struct Curl_easy *data,
curl_off_t perms;
const char *p = sshc->quote_path1;
/* permissions are octal */
- if(Curl_str_octal(&p, &perms, 07777)) {
+ if(curlx_str_octal(&p, &perms, 07777)) {
failf(data, "Syntax error: chmod permissions not a number");
goto fail;
}
@@ -1396,7 +1387,7 @@ sftp_quote_stat(struct Curl_easy *data,
else if(!strncmp(cmd, "chown", 5)) {
const char *p = sshc->quote_path1;
curl_off_t uid;
- (void)Curl_str_number(&p, &uid, ULONG_MAX);
+ (void)curlx_str_number(&p, &uid, ULONG_MAX);
sshp->quote_attrs.uid = (unsigned long)uid;
sshp->quote_attrs.flags = LIBSSH2_SFTP_ATTR_UIDGID;
if(sshp->quote_attrs.uid == 0 && !ISDIGIT(sshc->quote_path1[0]) &&
@@ -1432,7 +1423,7 @@ sftp_quote_stat(struct Curl_easy *data,
}
/* Now send the completed structure... */
- state(data, SSH_SFTP_QUOTE_SETSTAT);
+ myssh_state(data, sshc, SSH_SFTP_QUOTE_SETSTAT);
return CURLE_OK;
fail:
Curl_safefree(sshc->quote_path1);
@@ -1479,13 +1470,13 @@ sftp_download_stat(struct Curl_easy *data,
const char *p = data->state.range;
int to_t, from_t;
- from_t = Curl_str_number(&p, &from, CURL_OFF_T_MAX);
+ from_t = curlx_str_number(&p, &from, CURL_OFF_T_MAX);
if(from_t == STRE_OVERFLOW)
return CURLE_RANGE_ERROR;
- Curl_str_passblanks(&p);
- (void)Curl_str_single(&p, '-');
+ curlx_str_passblanks(&p);
+ (void)curlx_str_single(&p, '-');
- to_t = Curl_str_numblanks(&p, &to);
+ to_t = curlx_str_numblanks(&p, &to);
if(to_t == STRE_OVERFLOW)
return CURLE_RANGE_ERROR;
if((to_t == STRE_NO_NUM) /* no "to" value given */
@@ -1554,7 +1545,7 @@ sftp_download_stat(struct Curl_easy *data,
/* no data to transfer */
Curl_xfer_setup_nop(data);
infof(data, "File already completely downloaded");
- state(data, SSH_STOP);
+ myssh_state(data, sshc, SSH_STOP);
return CURLE_OK;
}
Curl_xfer_setup1(data, CURL_XFER_RECV, data->req.size, FALSE);
@@ -1566,7 +1557,7 @@ sftp_download_stat(struct Curl_easy *data,
out writableable as the underlying libssh2 recv function will deal
with both accordingly */
data->state.select_bits = CURL_CSELECT_IN;
- state(data, SSH_STOP);
+ myssh_state(data, sshc, SSH_STOP);
return CURLE_OK;
}
@@ -1599,37 +1590,1102 @@ static CURLcode sftp_readdir(struct Curl_easy *data,
return result;
}
else {
- result = Curl_dyn_add(&sshp->readdir, sshp->readdir_longentry);
+ result = curlx_dyn_add(&sshp->readdir, sshp->readdir_longentry);
if(!result) {
if((sshp->readdir_attrs.flags & LIBSSH2_SFTP_ATTR_PERMISSIONS) &&
((sshp->readdir_attrs.permissions & LIBSSH2_SFTP_S_IFMT) ==
LIBSSH2_SFTP_S_IFLNK)) {
- result = Curl_dyn_addf(&sshp->readdir_link, "%s%s", sshp->path,
- sshp->readdir_filename);
- state(data, SSH_SFTP_READDIR_LINK);
+ result = curlx_dyn_addf(&sshp->readdir_link, "%s%s", sshp->path,
+ sshp->readdir_filename);
+ myssh_state(data, sshc, SSH_SFTP_READDIR_LINK);
}
else {
- state(data, SSH_SFTP_READDIR_BOTTOM);
+ myssh_state(data, sshc, SSH_SFTP_READDIR_BOTTOM);
}
}
return result;
}
}
else if(!rc) {
- state(data, SSH_SFTP_READDIR_DONE);
+ myssh_state(data, sshc, SSH_SFTP_READDIR_DONE);
}
else {
unsigned long sftperr = libssh2_sftp_last_error(sshc->sftp_session);
- result = sftp_libssh2_error_to_CURLE(sftperr);
- sshc->actualcode = result ? result : CURLE_SSH;
+ result = sftperr ? sftp_libssh2_error_to_CURLE(sftperr) : CURLE_SSH;
failf(data, "Could not open remote file for reading: %s :: %d",
sftp_libssh2_strerror(sftperr),
libssh2_session_last_errno(sshc->ssh_session));
- state(data, SSH_SFTP_CLOSE);
+ myssh_state(data, sshc, SSH_SFTP_CLOSE);
+ }
+ return result;
+}
+
+static CURLcode ssh_state_init(struct Curl_easy *data,
+ struct ssh_conn *sshc)
+{
+ CURLcode result;
+ sshc->secondCreateDirs = 0;
+ sshc->nextstate = SSH_NO_STATE;
+
+ /* Set libssh2 to non-blocking, since everything internally is
+ non-blocking */
+ libssh2_session_set_blocking(sshc->ssh_session, 0);
+
+ result = ssh_force_knownhost_key_type(data, sshc);
+ if(result)
+ myssh_state(data, sshc, SSH_SESSION_FREE);
+ else
+ myssh_state(data, sshc, SSH_S_STARTUP);
+ return result;
+}
+
+static CURLcode ssh_state_startup(struct Curl_easy *data,
+ struct ssh_conn *sshc)
+{
+ struct connectdata *conn = data->conn;
+ int rc = libssh2_session_handshake(sshc->ssh_session,
+ conn->sock[FIRSTSOCKET]);
+ if(rc == LIBSSH2_ERROR_EAGAIN)
+ return CURLE_AGAIN;
+
+ if(rc) {
+ char *err_msg = NULL;
+ (void)libssh2_session_last_error(sshc->ssh_session, &err_msg, NULL, 0);
+ failf(data, "Failure establishing ssh session: %d, %s", rc, err_msg);
+
+ myssh_state(data, sshc, SSH_SESSION_FREE);
+ return CURLE_FAILED_INIT;
+ }
+
+ myssh_state(data, sshc, SSH_HOSTKEY);
+ return CURLE_OK;
+}
+
+static CURLcode ssh_state_hostkey(struct Curl_easy *data,
+ struct ssh_conn *sshc)
+{
+ /*
+ * Before we authenticate we should check the hostkey's fingerprint
+ * against our known hosts. How that is handled (reading from file,
+ * whatever) is up to us.
+ */
+ CURLcode result = ssh_check_fingerprint(data, sshc);
+ if(!result)
+ myssh_state(data, sshc, SSH_AUTHLIST);
+ return result;
+}
+
+static CURLcode ssh_state_authlist(struct Curl_easy *data,
+ struct ssh_conn *sshc)
+{
+ /*
+ * Figure out authentication methods
+ * NB: As soon as we have provided a username to an openssh server we
+ * must never change it later. Thus, always specify the correct username
+ * here, even though the libssh2 docs kind of indicate that it should be
+ * possible to get a 'generic' list (not user-specific) of authentication
+ * methods, presumably with a blank username. That will not work in my
+ * experience.
+ * So always specify it here.
+ */
+ struct connectdata *conn = data->conn;
+ sshc->authlist = libssh2_userauth_list(sshc->ssh_session,
+ conn->user,
+ curlx_uztoui(strlen(conn->user)));
+
+ if(!sshc->authlist) {
+ int rc;
+ if(libssh2_userauth_authenticated(sshc->ssh_session)) {
+ sshc->authed = TRUE;
+ infof(data, "SSH user accepted with no authentication");
+ myssh_state(data, sshc, SSH_AUTH_DONE);
+ return CURLE_OK;
+ }
+ rc = libssh2_session_last_errno(sshc->ssh_session);
+ if(rc == LIBSSH2_ERROR_EAGAIN)
+ return CURLE_AGAIN;
+
+ myssh_state(data, sshc, SSH_SESSION_FREE);
+ return libssh2_session_error_to_CURLE(rc);
+ }
+ infof(data, "SSH authentication methods available: %s",
+ sshc->authlist);
+
+ myssh_state(data, sshc, SSH_AUTH_PKEY_INIT);
+ return CURLE_OK;
+}
+
+static CURLcode ssh_state_auth_pkey(struct Curl_easy *data,
+ struct ssh_conn *sshc)
+{
+ /* The function below checks if the files exists, no need to stat() here.
+ */
+ struct connectdata *conn = data->conn;
+ int rc =
+ libssh2_userauth_publickey_fromfile_ex(sshc->ssh_session,
+ conn->user,
+ curlx_uztoui(
+ strlen(conn->user)),
+ sshc->rsa_pub,
+ sshc->rsa, sshc->passphrase);
+ if(rc == LIBSSH2_ERROR_EAGAIN)
+ return CURLE_AGAIN;
+
+ Curl_safefree(sshc->rsa_pub);
+ Curl_safefree(sshc->rsa);
+
+ if(rc == 0) {
+ sshc->authed = TRUE;
+ infof(data, "Initialized SSH public key authentication");
+ myssh_state(data, sshc, SSH_AUTH_DONE);
+ }
+ else {
+ char *err_msg = NULL;
+ char unknown[] = "Reason unknown (-1)";
+ if(rc == -1) {
+ /* No error message has been set and the last set error message, if
+ any, is from a previous error so ignore it. #11837 */
+ err_msg = unknown;
+ }
+ else {
+ (void)libssh2_session_last_error(sshc->ssh_session,
+ &err_msg, NULL, 0);
+ }
+ infof(data, "SSH public key authentication failed: %s", err_msg);
+ myssh_state(data, sshc, SSH_AUTH_PASS_INIT);
+ }
+ return CURLE_OK;
+}
+
+static CURLcode ssh_state_auth_pass_init(struct Curl_easy *data,
+ struct ssh_conn *sshc)
+{
+ if((data->set.ssh_auth_types & CURLSSH_AUTH_PASSWORD) &&
+ (strstr(sshc->authlist, "password") != NULL)) {
+ myssh_state(data, sshc, SSH_AUTH_PASS);
+ }
+ else {
+ myssh_state(data, sshc, SSH_AUTH_HOST_INIT);
+ }
+ return CURLE_OK;
+}
+
+static CURLcode ssh_state_auth_pass(struct Curl_easy *data,
+ struct ssh_conn *sshc)
+{
+ struct connectdata *conn = data->conn;
+ int rc =
+ libssh2_userauth_password_ex(sshc->ssh_session, conn->user,
+ curlx_uztoui(strlen(conn->user)),
+ conn->passwd,
+ curlx_uztoui(strlen(conn->passwd)),
+ NULL);
+ if(rc == LIBSSH2_ERROR_EAGAIN) {
+ return CURLE_AGAIN;
+ }
+ if(rc == 0) {
+ sshc->authed = TRUE;
+ infof(data, "Initialized password authentication");
+ myssh_state(data, sshc, SSH_AUTH_DONE);
+ }
+ else {
+ myssh_state(data, sshc, SSH_AUTH_HOST_INIT);
+ }
+ return CURLE_OK;
+}
+
+static CURLcode ssh_state_auth_host_init(struct Curl_easy *data,
+ struct ssh_conn *sshc)
+{
+ if((data->set.ssh_auth_types & CURLSSH_AUTH_HOST) &&
+ (strstr(sshc->authlist, "hostbased") != NULL)) {
+ myssh_state(data, sshc, SSH_AUTH_HOST);
+ }
+ else {
+ myssh_state(data, sshc, SSH_AUTH_AGENT_INIT);
+ }
+ return CURLE_OK;
+}
+
+static CURLcode ssh_state_auth_agent_init(struct Curl_easy *data,
+ struct ssh_conn *sshc)
+{
+ int rc = 0;
+ if((data->set.ssh_auth_types & CURLSSH_AUTH_AGENT)
+ && (strstr(sshc->authlist, "publickey") != NULL)) {
+
+ /* Connect to the ssh-agent */
+ /* The agent could be shared by a curl thread i believe
+ but nothing obvious as keys can be added/removed at any time */
+ if(!sshc->ssh_agent) {
+ sshc->ssh_agent = libssh2_agent_init(sshc->ssh_session);
+ if(!sshc->ssh_agent) {
+ infof(data, "Could not create agent object");
+
+ myssh_state(data, sshc, SSH_AUTH_KEY_INIT);
+ return CURLE_OK;
+ }
+ }
+
+ rc = libssh2_agent_connect(sshc->ssh_agent);
+ if(rc == LIBSSH2_ERROR_EAGAIN)
+ return CURLE_AGAIN;
+ if(rc < 0) {
+ infof(data, "Failure connecting to agent");
+ myssh_state(data, sshc, SSH_AUTH_KEY_INIT);
+ }
+ else {
+ myssh_state(data, sshc, SSH_AUTH_AGENT_LIST);
+ }
+ }
+ else
+ myssh_state(data, sshc, SSH_AUTH_KEY_INIT);
+ return CURLE_OK;
+}
+
+static CURLcode ssh_state_auth_agent_list(struct Curl_easy *data,
+ struct ssh_conn *sshc)
+{
+ int rc = libssh2_agent_list_identities(sshc->ssh_agent);
+
+ if(rc == LIBSSH2_ERROR_EAGAIN)
+ return CURLE_AGAIN;
+ if(rc < 0) {
+ infof(data, "Failure requesting identities to agent");
+ myssh_state(data, sshc, SSH_AUTH_KEY_INIT);
+ }
+ else {
+ myssh_state(data, sshc, SSH_AUTH_AGENT);
+ sshc->sshagent_prev_identity = NULL;
+ }
+ return CURLE_OK;
+}
+
+static CURLcode ssh_state_auth_agent(struct Curl_easy *data,
+ struct ssh_conn *sshc)
+{
+ /* as prev_identity evolves only after an identity user auth finished we
+ can safely request it again as long as EAGAIN is returned here or by
+ libssh2_agent_userauth */
+ int rc = libssh2_agent_get_identity(sshc->ssh_agent,
+ &sshc->sshagent_identity,
+ sshc->sshagent_prev_identity);
+ if(rc == LIBSSH2_ERROR_EAGAIN)
+ return CURLE_AGAIN;
+
+ if(rc == 0) {
+ struct connectdata *conn = data->conn;
+ rc = libssh2_agent_userauth(sshc->ssh_agent, conn->user,
+ sshc->sshagent_identity);
+
+ if(rc < 0) {
+ if(rc != LIBSSH2_ERROR_EAGAIN) {
+ /* tried and failed? go to next identity */
+ sshc->sshagent_prev_identity = sshc->sshagent_identity;
+ }
+ return CURLE_OK;
+ }
+ }
+
+ if(rc < 0)
+ infof(data, "Failure requesting identities to agent");
+ else if(rc == 1)
+ infof(data, "No identity would match");
+
+ if(rc == LIBSSH2_ERROR_NONE) {
+ sshc->authed = TRUE;
+ infof(data, "Agent based authentication successful");
+ myssh_state(data, sshc, SSH_AUTH_DONE);
+ }
+ else {
+ myssh_state(data, sshc, SSH_AUTH_KEY_INIT);
+ }
+ return CURLE_OK;
+}
+
+static CURLcode ssh_state_auth_key_init(struct Curl_easy *data,
+ struct ssh_conn *sshc)
+{
+ if((data->set.ssh_auth_types & CURLSSH_AUTH_KEYBOARD)
+ && (strstr(sshc->authlist, "keyboard-interactive") != NULL)) {
+ myssh_state(data, sshc, SSH_AUTH_KEY);
+ }
+ else {
+ myssh_state(data, sshc, SSH_AUTH_DONE);
+ }
+ return CURLE_OK;
+}
+
+static CURLcode ssh_state_auth_key(struct Curl_easy *data,
+ struct ssh_conn *sshc)
+{
+ /* Authentication failed. Continue with keyboard-interactive now. */
+ struct connectdata *conn = data->conn;
+ int rc =
+ libssh2_userauth_keyboard_interactive_ex(sshc->ssh_session,
+ conn->user,
+ curlx_uztoui(
+ strlen(conn->user)),
+ &kbd_callback);
+ if(rc == LIBSSH2_ERROR_EAGAIN)
+ return CURLE_AGAIN;
+
+ if(rc == 0) {
+ sshc->authed = TRUE;
+ infof(data, "Initialized keyboard interactive authentication");
+ myssh_state(data, sshc, SSH_AUTH_DONE);
+ return CURLE_OK;
+ }
+ return CURLE_LOGIN_DENIED;
+}
+
+static CURLcode ssh_state_auth_done(struct Curl_easy *data,
+ struct ssh_conn *sshc)
+{
+ struct connectdata *conn = data->conn;
+ if(!sshc->authed) {
+ failf(data, "Authentication failure");
+ myssh_state(data, sshc, SSH_SESSION_FREE);
+ return CURLE_LOGIN_DENIED;
+ }
+
+ /*
+ * At this point we have an authenticated ssh session.
+ */
+ infof(data, "Authentication complete");
+
+ Curl_pgrsTime(data, TIMER_APPCONNECT); /* SSH is connected */
+
+ conn->sockfd = conn->sock[FIRSTSOCKET];
+ conn->writesockfd = CURL_SOCKET_BAD;
+
+ if(conn->handler->protocol == CURLPROTO_SFTP) {
+ myssh_state(data, sshc, SSH_SFTP_INIT);
+ return CURLE_OK;
+ }
+ infof(data, "SSH CONNECT phase done");
+ myssh_state(data, sshc, SSH_STOP);
+ return CURLE_OK;
+}
+
+static CURLcode ssh_state_sftp_init(struct Curl_easy *data,
+ struct ssh_conn *sshc)
+{
+ /*
+ * Start the libssh2 sftp session
+ */
+ sshc->sftp_session = libssh2_sftp_init(sshc->ssh_session);
+ if(!sshc->sftp_session) {
+ char *err_msg = NULL;
+ if(libssh2_session_last_errno(sshc->ssh_session) ==
+ LIBSSH2_ERROR_EAGAIN)
+ return CURLE_AGAIN;
+
+ (void)libssh2_session_last_error(sshc->ssh_session,
+ &err_msg, NULL, 0);
+ failf(data, "Failure initializing sftp session: %s", err_msg);
+ myssh_state(data, sshc, SSH_SESSION_FREE);
+ return CURLE_FAILED_INIT;
+ }
+ myssh_state(data, sshc, SSH_SFTP_REALPATH);
+ return CURLE_OK;
+}
+
+static CURLcode ssh_state_sftp_realpath(struct Curl_easy *data,
+ struct ssh_conn *sshc,
+ struct SSHPROTO *sshp)
+{
+ /*
+ * Get the "home" directory
+ */
+ int rc = libssh2_sftp_symlink_ex(sshc->sftp_session,
+ ".", curlx_uztoui(strlen(".")),
+ sshp->readdir_filename, CURL_PATH_MAX,
+ LIBSSH2_SFTP_REALPATH);
+ if(rc == LIBSSH2_ERROR_EAGAIN)
+ return CURLE_AGAIN;
+
+ if(rc > 0) {
+ /* It seems that this string is not always NULL terminated */
+ sshp->readdir_filename[rc] = '\0';
+ free(sshc->homedir);
+ sshc->homedir = strdup(sshp->readdir_filename);
+ if(!sshc->homedir) {
+ myssh_state(data, sshc, SSH_SFTP_CLOSE);
+ return CURLE_OUT_OF_MEMORY;
+ }
+ free(data->state.most_recent_ftp_entrypath);
+ data->state.most_recent_ftp_entrypath = strdup(sshc->homedir);
+ if(!data->state.most_recent_ftp_entrypath)
+ return CURLE_OUT_OF_MEMORY;
+ }
+ else {
+ /* Return the error type */
+ unsigned long sftperr = libssh2_sftp_last_error(sshc->sftp_session);
+ CURLcode result;
+ if(sftperr)
+ result = sftp_libssh2_error_to_CURLE(sftperr);
+ else
+ /* in this case, the error was not in the SFTP level but for example
+ a time-out or similar */
+ result = CURLE_SSH;
+ DEBUGF(infof(data, "error = %lu makes libcurl = %d",
+ sftperr, (int)result));
+ myssh_state(data, sshc, SSH_STOP);
+ return result;
+ }
+
+ /* This is the last step in the SFTP connect phase. Do note that while
+ we get the homedir here, we get the "workingpath" in the DO action
+ since the homedir will remain the same between request but the
+ working path will not. */
+ DEBUGF(infof(data, "SSH CONNECT phase done"));
+ myssh_state(data, sshc, SSH_STOP);
+ return CURLE_OK;
+}
+
+static CURLcode ssh_state_sftp_quote_init(struct Curl_easy *data,
+ struct ssh_conn *sshc,
+ struct SSHPROTO *sshp)
+{
+ CURLcode result = Curl_getworkingpath(data, sshc->homedir, &sshp->path);
+ if(result) {
+ myssh_state(data, sshc, SSH_STOP);
+ return result;
+ }
+
+ if(data->set.quote) {
+ infof(data, "Sending quote commands");
+ sshc->quote_item = data->set.quote;
+ myssh_state(data, sshc, SSH_SFTP_QUOTE);
+ }
+ else {
+ myssh_state(data, sshc, SSH_SFTP_GETINFO);
+ }
+ return CURLE_OK;
+}
+
+static CURLcode ssh_state_sftp_postquote_init(struct Curl_easy *data,
+ struct ssh_conn *sshc)
+{
+ if(data->set.postquote) {
+ infof(data, "Sending quote commands");
+ sshc->quote_item = data->set.postquote;
+ myssh_state(data, sshc, SSH_SFTP_QUOTE);
+ }
+ else {
+ myssh_state(data, sshc, SSH_STOP);
+ }
+ return CURLE_OK;
+}
+
+static CURLcode ssh_state_sftp_quote(struct Curl_easy *data,
+ struct ssh_conn *sshc,
+ struct SSHPROTO *sshp)
+{
+ /* Send quote commands */
+ CURLcode result = sftp_quote(data, sshc, sshp);
+ if(result) {
+ myssh_state(data, sshc, SSH_SFTP_CLOSE);
+ sshc->nextstate = SSH_NO_STATE;
+ }
+ return result;
+}
+
+static CURLcode ssh_state_sftp_next_quote(struct Curl_easy *data,
+ struct ssh_conn *sshc)
+{
+ Curl_safefree(sshc->quote_path1);
+ Curl_safefree(sshc->quote_path2);
+
+ sshc->quote_item = sshc->quote_item->next;
+
+ if(sshc->quote_item) {
+ myssh_state(data, sshc, SSH_SFTP_QUOTE);
+ }
+ else {
+ if(sshc->nextstate != SSH_NO_STATE) {
+ myssh_state(data, sshc, sshc->nextstate);
+ sshc->nextstate = SSH_NO_STATE;
+ }
+ else {
+ myssh_state(data, sshc, SSH_SFTP_GETINFO);
+ }
+ }
+ return CURLE_OK;
+}
+
+static CURLcode ssh_state_sftp_quote_stat(struct Curl_easy *data,
+ struct ssh_conn *sshc,
+ struct SSHPROTO *sshp,
+ bool *blockp)
+{
+ CURLcode result = sftp_quote_stat(data, sshc, sshp, blockp);
+ if(result) {
+ myssh_state(data, sshc, SSH_SFTP_CLOSE);
+ sshc->nextstate = SSH_NO_STATE;
}
return result;
}
+
+static CURLcode ssh_state_sftp_quote_setstat(struct Curl_easy *data,
+ struct ssh_conn *sshc,
+ struct SSHPROTO *sshp)
+{
+ int rc =
+ libssh2_sftp_stat_ex(sshc->sftp_session, sshc->quote_path2,
+ curlx_uztoui(strlen(sshc->quote_path2)),
+ LIBSSH2_SFTP_SETSTAT,
+ &sshp->quote_attrs);
+ if(rc == LIBSSH2_ERROR_EAGAIN)
+ return CURLE_AGAIN;
+
+ if(rc && !sshc->acceptfail) {
+ unsigned long sftperr = libssh2_sftp_last_error(sshc->sftp_session);
+ Curl_safefree(sshc->quote_path1);
+ Curl_safefree(sshc->quote_path2);
+ failf(data, "Attempt to set SFTP stats failed: %s",
+ sftp_libssh2_strerror(sftperr));
+ myssh_state(data, sshc, SSH_SFTP_CLOSE);
+ sshc->nextstate = SSH_NO_STATE;
+ return CURLE_QUOTE_ERROR;
+ }
+ myssh_state(data, sshc, SSH_SFTP_NEXT_QUOTE);
+ return CURLE_OK;
+}
+
+static CURLcode ssh_state_sftp_quote_symlink(struct Curl_easy *data,
+ struct ssh_conn *sshc)
+{
+ int rc =
+ libssh2_sftp_symlink_ex(sshc->sftp_session, sshc->quote_path1,
+ curlx_uztoui(strlen(sshc->quote_path1)),
+ sshc->quote_path2,
+ curlx_uztoui(strlen(sshc->quote_path2)),
+ LIBSSH2_SFTP_SYMLINK);
+ if(rc == LIBSSH2_ERROR_EAGAIN)
+ return CURLE_AGAIN;
+
+ if(rc && !sshc->acceptfail) {
+ unsigned long sftperr = libssh2_sftp_last_error(sshc->sftp_session);
+ Curl_safefree(sshc->quote_path1);
+ Curl_safefree(sshc->quote_path2);
+ failf(data, "symlink command failed: %s",
+ sftp_libssh2_strerror(sftperr));
+ myssh_state(data, sshc, SSH_SFTP_CLOSE);
+ sshc->nextstate = SSH_NO_STATE;
+ return CURLE_QUOTE_ERROR;
+ }
+ myssh_state(data, sshc, SSH_SFTP_NEXT_QUOTE);
+ return CURLE_OK;
+}
+
+static CURLcode ssh_state_sftp_quote_mkdir(struct Curl_easy *data,
+ struct ssh_conn *sshc)
+{
+ int rc = libssh2_sftp_mkdir_ex(sshc->sftp_session, sshc->quote_path1,
+ curlx_uztoui(strlen(sshc->quote_path1)),
+ (long)data->set.new_directory_perms);
+ if(rc == LIBSSH2_ERROR_EAGAIN)
+ return CURLE_AGAIN;
+
+ if(rc && !sshc->acceptfail) {
+ unsigned long sftperr = libssh2_sftp_last_error(sshc->sftp_session);
+ Curl_safefree(sshc->quote_path1);
+ failf(data, "mkdir command failed: %s",
+ sftp_libssh2_strerror(sftperr));
+ myssh_state(data, sshc, SSH_SFTP_CLOSE);
+ sshc->nextstate = SSH_NO_STATE;
+ return CURLE_QUOTE_ERROR;
+ }
+ myssh_state(data, sshc, SSH_SFTP_NEXT_QUOTE);
+ return CURLE_OK;
+}
+
+static CURLcode ssh_state_sftp_quote_rename(struct Curl_easy *data,
+ struct ssh_conn *sshc)
+{
+ int rc =
+ libssh2_sftp_rename_ex(sshc->sftp_session, sshc->quote_path1,
+ curlx_uztoui(strlen(sshc->quote_path1)),
+ sshc->quote_path2,
+ curlx_uztoui(strlen(sshc->quote_path2)),
+ LIBSSH2_SFTP_RENAME_OVERWRITE |
+ LIBSSH2_SFTP_RENAME_ATOMIC |
+ LIBSSH2_SFTP_RENAME_NATIVE);
+
+ if(rc == LIBSSH2_ERROR_EAGAIN)
+ return CURLE_AGAIN;
+
+ if(rc && !sshc->acceptfail) {
+ unsigned long sftperr = libssh2_sftp_last_error(sshc->sftp_session);
+ Curl_safefree(sshc->quote_path1);
+ Curl_safefree(sshc->quote_path2);
+ failf(data, "rename command failed: %s",
+ sftp_libssh2_strerror(sftperr));
+ myssh_state(data, sshc, SSH_SFTP_CLOSE);
+ sshc->nextstate = SSH_NO_STATE;
+ return CURLE_QUOTE_ERROR;
+ }
+ myssh_state(data, sshc, SSH_SFTP_NEXT_QUOTE);
+ return CURLE_OK;
+}
+
+static CURLcode ssh_state_sftp_quote_rmdir(struct Curl_easy *data,
+ struct ssh_conn *sshc)
+{
+ int rc = libssh2_sftp_rmdir_ex(sshc->sftp_session, sshc->quote_path1,
+ curlx_uztoui(strlen(sshc->quote_path1)));
+ if(rc == LIBSSH2_ERROR_EAGAIN)
+ return CURLE_AGAIN;
+
+ if(rc && !sshc->acceptfail) {
+ unsigned long sftperr = libssh2_sftp_last_error(sshc->sftp_session);
+ Curl_safefree(sshc->quote_path1);
+ failf(data, "rmdir command failed: %s",
+ sftp_libssh2_strerror(sftperr));
+ myssh_state(data, sshc, SSH_SFTP_CLOSE);
+ sshc->nextstate = SSH_NO_STATE;
+ return CURLE_QUOTE_ERROR;
+ }
+ myssh_state(data, sshc, SSH_SFTP_NEXT_QUOTE);
+ return CURLE_OK;
+}
+
+static CURLcode ssh_state_sftp_quote_unlink(struct Curl_easy *data,
+ struct ssh_conn *sshc)
+{
+ int rc = libssh2_sftp_unlink_ex(sshc->sftp_session, sshc->quote_path1,
+ curlx_uztoui(strlen(sshc->quote_path1)));
+ if(rc == LIBSSH2_ERROR_EAGAIN)
+ return CURLE_AGAIN;
+
+ if(rc && !sshc->acceptfail) {
+ unsigned long sftperr = libssh2_sftp_last_error(sshc->sftp_session);
+ Curl_safefree(sshc->quote_path1);
+ failf(data, "rm command failed: %s", sftp_libssh2_strerror(sftperr));
+ myssh_state(data, sshc, SSH_SFTP_CLOSE);
+ sshc->nextstate = SSH_NO_STATE;
+ return CURLE_QUOTE_ERROR;
+ }
+ myssh_state(data, sshc, SSH_SFTP_NEXT_QUOTE);
+ return CURLE_OK;
+}
+
+static CURLcode ssh_state_sftp_quote_statvfs(struct Curl_easy *data,
+ struct ssh_conn *sshc)
+{
+ LIBSSH2_SFTP_STATVFS statvfs;
+ int rc = libssh2_sftp_statvfs(sshc->sftp_session, sshc->quote_path1,
+ curlx_uztoui(strlen(sshc->quote_path1)),
+ &statvfs);
+
+ if(rc == LIBSSH2_ERROR_EAGAIN)
+ return CURLE_AGAIN;
+
+ if(rc && !sshc->acceptfail) {
+ unsigned long sftperr = libssh2_sftp_last_error(sshc->sftp_session);
+ Curl_safefree(sshc->quote_path1);
+ failf(data, "statvfs command failed: %s",
+ sftp_libssh2_strerror(sftperr));
+ myssh_state(data, sshc, SSH_SFTP_CLOSE);
+ sshc->nextstate = SSH_NO_STATE;
+ return CURLE_QUOTE_ERROR;
+ }
+ else if(rc == 0) {
+#ifdef _MSC_VER
+#define CURL_LIBSSH2_VFS_SIZE_MASK "I64u"
+#else
+#define CURL_LIBSSH2_VFS_SIZE_MASK "llu"
+#endif
+ CURLcode result;
+ char *tmp = aprintf("statvfs:\n"
+ "f_bsize: %" CURL_LIBSSH2_VFS_SIZE_MASK "\n"
+ "f_frsize: %" CURL_LIBSSH2_VFS_SIZE_MASK "\n"
+ "f_blocks: %" CURL_LIBSSH2_VFS_SIZE_MASK "\n"
+ "f_bfree: %" CURL_LIBSSH2_VFS_SIZE_MASK "\n"
+ "f_bavail: %" CURL_LIBSSH2_VFS_SIZE_MASK "\n"
+ "f_files: %" CURL_LIBSSH2_VFS_SIZE_MASK "\n"
+ "f_ffree: %" CURL_LIBSSH2_VFS_SIZE_MASK "\n"
+ "f_favail: %" CURL_LIBSSH2_VFS_SIZE_MASK "\n"
+ "f_fsid: %" CURL_LIBSSH2_VFS_SIZE_MASK "\n"
+ "f_flag: %" CURL_LIBSSH2_VFS_SIZE_MASK "\n"
+ "f_namemax: %" CURL_LIBSSH2_VFS_SIZE_MASK "\n",
+ statvfs.f_bsize, statvfs.f_frsize,
+ statvfs.f_blocks, statvfs.f_bfree,
+ statvfs.f_bavail, statvfs.f_files,
+ statvfs.f_ffree, statvfs.f_favail,
+ statvfs.f_fsid, statvfs.f_flag,
+ statvfs.f_namemax);
+ if(!tmp) {
+ myssh_state(data, sshc, SSH_SFTP_CLOSE);
+ sshc->nextstate = SSH_NO_STATE;
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ result = Curl_client_write(data, CLIENTWRITE_HEADER, tmp, strlen(tmp));
+ free(tmp);
+ if(result) {
+ myssh_state(data, sshc, SSH_SFTP_CLOSE);
+ sshc->nextstate = SSH_NO_STATE;
+ return result;
+ }
+ }
+ myssh_state(data, sshc, SSH_SFTP_NEXT_QUOTE);
+ return CURLE_OK;
+}
+
+static CURLcode ssh_state_sftp_create_dirs_mkdir(struct Curl_easy *data,
+ struct ssh_conn *sshc,
+ struct SSHPROTO *sshp)
+{
+ /* 'mode' - parameter is preliminary - default to 0644 */
+ int rc = libssh2_sftp_mkdir_ex(sshc->sftp_session, sshp->path,
+ curlx_uztoui(strlen(sshp->path)),
+ (long)data->set.new_directory_perms);
+ if(rc == LIBSSH2_ERROR_EAGAIN)
+ return CURLE_AGAIN;
+
+ *sshc->slash_pos = '/';
+ ++sshc->slash_pos;
+ if(rc < 0) {
+ /*
+ * Abort if failure was not that the dir already exists or the
+ * permission was denied (creation might succeed further down the
+ * path) - retry on unspecific FAILURE also
+ */
+ unsigned long sftperr = libssh2_sftp_last_error(sshc->sftp_session);
+ if((sftperr != LIBSSH2_FX_FILE_ALREADY_EXISTS) &&
+ (sftperr != LIBSSH2_FX_FAILURE) &&
+ (sftperr != LIBSSH2_FX_PERMISSION_DENIED)) {
+ myssh_state(data, sshc, SSH_SFTP_CLOSE);
+ return sftp_libssh2_error_to_CURLE(sftperr);
+ }
+ }
+ myssh_state(data, sshc, SSH_SFTP_CREATE_DIRS);
+ return CURLE_OK;
+}
+
+static CURLcode ssh_state_sftp_readdir_init(struct Curl_easy *data,
+ struct ssh_conn *sshc,
+ struct SSHPROTO *sshp)
+{
+ Curl_pgrsSetDownloadSize(data, -1);
+ if(data->req.no_body) {
+ myssh_state(data, sshc, SSH_STOP);
+ return CURLE_OK;
+ }
+
+ /*
+ * This is a directory that we are trying to get, so produce a directory
+ * listing
+ */
+ sshc->sftp_handle =
+ libssh2_sftp_open_ex(sshc->sftp_session, sshp->path,
+ curlx_uztoui(strlen(sshp->path)),
+ 0, 0, LIBSSH2_SFTP_OPENDIR);
+ if(!sshc->sftp_handle) {
+ unsigned long sftperr;
+ if(libssh2_session_last_errno(sshc->ssh_session) == LIBSSH2_ERROR_EAGAIN)
+ return CURLE_AGAIN;
+
+ sftperr = libssh2_sftp_last_error(sshc->sftp_session);
+ failf(data, "Could not open directory for reading: %s",
+ sftp_libssh2_strerror(sftperr));
+ myssh_state(data, sshc, SSH_SFTP_CLOSE);
+ return sftp_libssh2_error_to_CURLE(sftperr);
+ }
+ myssh_state(data, sshc, SSH_SFTP_READDIR);
+ return CURLE_OK;
+}
+
+static CURLcode ssh_state_sftp_readdir_link(struct Curl_easy *data,
+ struct ssh_conn *sshc,
+ struct SSHPROTO *sshp)
+{
+ CURLcode result;
+ int rc =
+ libssh2_sftp_symlink_ex(sshc->sftp_session,
+ curlx_dyn_ptr(&sshp->readdir_link),
+ (unsigned int)
+ curlx_dyn_len(&sshp->readdir_link),
+ sshp->readdir_filename,
+ CURL_PATH_MAX, LIBSSH2_SFTP_READLINK);
+ if(rc == LIBSSH2_ERROR_EAGAIN)
+ return CURLE_AGAIN;
+
+ curlx_dyn_free(&sshp->readdir_link);
+
+ /* append filename and extra output */
+ result = curlx_dyn_addf(&sshp->readdir, " -> %s", sshp->readdir_filename);
+ if(result)
+ myssh_state(data, sshc, SSH_SFTP_CLOSE);
+ else
+ myssh_state(data, sshc, SSH_SFTP_READDIR_BOTTOM);
+ return result;
+}
+
+static CURLcode ssh_state_scp_download_init(struct Curl_easy *data,
+ struct ssh_conn *sshc,
+ struct SSHPROTO *sshp)
+{
+ curl_off_t bytecount;
+
+ /*
+ * We must check the remote file; if it is a directory no values will
+ * be set in sb
+ */
+
+ /*
+ * If support for >2GB files exists, use it.
+ */
+
+ /* get a fresh new channel from the ssh layer */
+#if LIBSSH2_VERSION_NUM < 0x010700
+ struct stat sb;
+ memset(&sb, 0, sizeof(struct stat));
+ sshc->ssh_channel = libssh2_scp_recv(sshc->ssh_session,
+ sshp->path, &sb);
+#else
+ libssh2_struct_stat sb;
+ memset(&sb, 0, sizeof(libssh2_struct_stat));
+ sshc->ssh_channel = libssh2_scp_recv2(sshc->ssh_session,
+ sshp->path, &sb);
+#endif
+
+ if(!sshc->ssh_channel) {
+ int ssh_err;
+ char *err_msg = NULL;
+
+ if(libssh2_session_last_errno(sshc->ssh_session) ==
+ LIBSSH2_ERROR_EAGAIN)
+ return CURLE_AGAIN;
+
+ ssh_err = (int)(libssh2_session_last_error(sshc->ssh_session,
+ &err_msg, NULL, 0));
+ failf(data, "%s", err_msg);
+ myssh_state(data, sshc, SSH_SCP_CHANNEL_FREE);
+ return libssh2_session_error_to_CURLE(ssh_err);
+ }
+
+ /* download data */
+ bytecount = (curl_off_t)sb.st_size;
+ data->req.maxdownload = (curl_off_t)sb.st_size;
+ Curl_xfer_setup1(data, CURL_XFER_RECV, bytecount, FALSE);
+
+ /* not set by Curl_xfer_setup to preserve keepon bits */
+ data->conn->writesockfd = data->conn->sockfd;
+
+ /* we want to use the _receiving_ function even when the socket turns
+ out writableable as the underlying libssh2 recv function will deal
+ with both accordingly */
+ data->state.select_bits = CURL_CSELECT_IN;
+
+ myssh_state(data, sshc, SSH_STOP);
+ return CURLE_OK;
+}
+
+static CURLcode ssh_state_sftp_close(struct Curl_easy *data,
+ struct ssh_conn *sshc,
+ struct SSHPROTO *sshp)
+{
+ int rc = 0;
+ if(sshc->sftp_handle) {
+ rc = libssh2_sftp_close(sshc->sftp_handle);
+ if(rc == LIBSSH2_ERROR_EAGAIN)
+ return CURLE_AGAIN;
+
+ if(rc < 0) {
+ char *err_msg = NULL;
+ (void)libssh2_session_last_error(sshc->ssh_session,
+ &err_msg, NULL, 0);
+ infof(data, "Failed to close libssh2 file: %d %s", rc, err_msg);
+ }
+ sshc->sftp_handle = NULL;
+ }
+
+ Curl_safefree(sshp->path);
+
+ DEBUGF(infof(data, "SFTP DONE done"));
+
+ /* Check if nextstate is set and move .nextstate could be POSTQUOTE_INIT
+ After nextstate is executed, the control should come back to
+ SSH_SFTP_CLOSE to pass the correct result back */
+ if(sshc->nextstate != SSH_NO_STATE &&
+ sshc->nextstate != SSH_SFTP_CLOSE) {
+ myssh_state(data, sshc, sshc->nextstate);
+ sshc->nextstate = SSH_SFTP_CLOSE;
+ }
+ else
+ myssh_state(data, sshc, SSH_STOP);
+
+ return CURLE_OK;
+}
+
+static CURLcode ssh_state_sftp_shutdown(struct Curl_easy *data,
+ struct ssh_conn *sshc)
+{
+ /* during times we get here due to a broken transfer and then the
+ sftp_handle might not have been taken down so make sure that is done
+ before we proceed */
+ int rc = 0;
+ if(sshc->sftp_handle) {
+ rc = libssh2_sftp_close(sshc->sftp_handle);
+ if(rc == LIBSSH2_ERROR_EAGAIN)
+ return CURLE_AGAIN;
+
+ if(rc < 0) {
+ char *err_msg = NULL;
+ (void)libssh2_session_last_error(sshc->ssh_session, &err_msg,
+ NULL, 0);
+ infof(data, "Failed to close libssh2 file: %d %s", rc, err_msg);
+ }
+ sshc->sftp_handle = NULL;
+ }
+ if(sshc->sftp_session) {
+ rc = libssh2_sftp_shutdown(sshc->sftp_session);
+ if(rc == LIBSSH2_ERROR_EAGAIN)
+ return CURLE_AGAIN;
+
+ if(rc < 0) {
+ infof(data, "Failed to stop libssh2 sftp subsystem");
+ }
+ sshc->sftp_session = NULL;
+ }
+
+ Curl_safefree(sshc->homedir);
+
+ myssh_state(data, sshc, SSH_SESSION_DISCONNECT);
+ return CURLE_OK;
+}
+
+static CURLcode ssh_state_sftp_download_init(struct Curl_easy *data,
+ struct ssh_conn *sshc,
+ struct SSHPROTO *sshp)
+{
+ /*
+ * Work on getting the specified file
+ */
+ sshc->sftp_handle =
+ libssh2_sftp_open_ex(sshc->sftp_session, sshp->path,
+ curlx_uztoui(strlen(sshp->path)),
+ LIBSSH2_FXF_READ, (long)data->set.new_file_perms,
+ LIBSSH2_SFTP_OPENFILE);
+ if(!sshc->sftp_handle) {
+ unsigned long sftperr;
+ if(libssh2_session_last_errno(sshc->ssh_session) ==
+ LIBSSH2_ERROR_EAGAIN) {
+ return CURLE_AGAIN;
+ }
+ sftperr = libssh2_sftp_last_error(sshc->sftp_session);
+ failf(data, "Could not open remote file for reading: %s",
+ sftp_libssh2_strerror(sftperr));
+ myssh_state(data, sshc, SSH_SFTP_CLOSE);
+ return sftp_libssh2_error_to_CURLE(sftperr);
+ }
+ myssh_state(data, sshc, SSH_SFTP_DOWNLOAD_STAT);
+ return CURLE_OK;
+}
+
+static CURLcode ssh_state_scp_upload_init(struct Curl_easy *data,
+ struct ssh_conn *sshc,
+ struct SSHPROTO *sshp)
+{
+ /*
+ * libssh2 requires that the destination path is a full path that
+ * includes the destination file and name OR ends in a "/" . If this is
+ * not done the destination file will be named the same name as the last
+ * directory in the path.
+ */
+ sshc->ssh_channel =
+ libssh2_scp_send64(sshc->ssh_session, sshp->path,
+ (int)data->set.new_file_perms,
+ (libssh2_int64_t)data->state.infilesize, 0, 0);
+ if(!sshc->ssh_channel) {
+ int ssh_err;
+ char *err_msg = NULL;
+ CURLcode result;
+ if(libssh2_session_last_errno(sshc->ssh_session) ==
+ LIBSSH2_ERROR_EAGAIN)
+ return CURLE_AGAIN;
+
+ ssh_err = (int)(libssh2_session_last_error(sshc->ssh_session,
+ &err_msg, NULL, 0));
+ failf(data, "%s", err_msg);
+ myssh_state(data, sshc, SSH_SCP_CHANNEL_FREE);
+ result = libssh2_session_error_to_CURLE(ssh_err);
+
+ /* Map generic errors to upload failed */
+ if(result == CURLE_SSH ||
+ result == CURLE_REMOTE_FILE_NOT_FOUND)
+ result = CURLE_UPLOAD_FAILED;
+ return result;
+ }
+
+ /* upload data */
+ data->req.size = data->state.infilesize;
+ Curl_pgrsSetUploadSize(data, data->state.infilesize);
+ Curl_xfer_setup1(data, CURL_XFER_SEND, -1, FALSE);
+
+ /* not set by Curl_xfer_setup to preserve keepon bits */
+ data->conn->sockfd = data->conn->writesockfd;
+
+ /* store this original bitmask setup to use later on if we cannot
+ figure out a "real" bitmask */
+ sshc->orig_waitfor = data->req.keepon;
+
+ /* we want to use the _sending_ function even when the socket turns
+ out readable as the underlying libssh2 scp send function will deal
+ with both accordingly */
+ data->state.select_bits = CURL_CSELECT_OUT;
+
+ myssh_state(data, sshc, SSH_STOP);
+
+ return CURLE_OK;
+}
+
+static CURLcode ssh_state_session_disconnect(struct Curl_easy *data,
+ struct ssh_conn *sshc)
+{
+ /* during weird times when we have been prematurely aborted, the channel
+ is still alive when we reach this state and we MUST kill the channel
+ properly first */
+ int rc = 0;
+ if(sshc->ssh_channel) {
+ rc = libssh2_channel_free(sshc->ssh_channel);
+ if(rc == LIBSSH2_ERROR_EAGAIN)
+ return CURLE_OK;
+
+ if(rc < 0) {
+ char *err_msg = NULL;
+ (void)libssh2_session_last_error(sshc->ssh_session,
+ &err_msg, NULL, 0);
+ infof(data, "Failed to free libssh2 scp subsystem: %d %s",
+ rc, err_msg);
+ }
+ sshc->ssh_channel = NULL;
+ }
+
+ if(sshc->ssh_session) {
+ rc = libssh2_session_disconnect(sshc->ssh_session, "Shutdown");
+ if(rc == LIBSSH2_ERROR_EAGAIN)
+ return CURLE_AGAIN;
+
+ if(rc < 0) {
+ char *err_msg = NULL;
+ (void)libssh2_session_last_error(sshc->ssh_session,
+ &err_msg, NULL, 0);
+ infof(data, "Failed to disconnect libssh2 session: %d %s",
+ rc, err_msg);
+ }
+ }
+
+ Curl_safefree(sshc->homedir);
+
+ myssh_state(data, sshc, SSH_SESSION_FREE);
+ return CURLE_OK;
+}
/*
* ssh_statemachine() runs the SSH state machine as far as it can without
* blocking and without reaching the end. The data the pointer 'block' points
@@ -1637,673 +2693,147 @@ static CURLcode sftp_readdir(struct Curl_easy *data,
* meaning it wants to be called again when the socket is ready
*/
-static CURLcode ssh_statemachine(struct Curl_easy *data, bool *block)
+static CURLcode ssh_statemachine(struct Curl_easy *data,
+ struct ssh_conn *sshc,
+ struct SSHPROTO *sshp,
+ bool *block)
{
CURLcode result = CURLE_OK;
struct connectdata *conn = data->conn;
- struct SSHPROTO *sshp = data->req.p.ssh;
- struct ssh_conn *sshc = &conn->proto.sshc;
-
- int rc = LIBSSH2_ERROR_NONE;
*block = 0; /* we are not blocking by default */
do {
switch(sshc->state) {
case SSH_INIT:
- sshc->secondCreateDirs = 0;
- sshc->nextstate = SSH_NO_STATE;
- sshc->actualcode = CURLE_OK;
-
- /* Set libssh2 to non-blocking, since everything internally is
- non-blocking */
- libssh2_session_set_blocking(sshc->ssh_session, 0);
-
- result = ssh_force_knownhost_key_type(data);
- if(result) {
- state(data, SSH_SESSION_FREE);
- sshc->actualcode = result;
+ result = ssh_state_init(data, sshc);
+ if(result)
break;
- }
-
- state(data, SSH_S_STARTUP);
FALLTHROUGH();
case SSH_S_STARTUP:
- rc = libssh2_session_handshake(sshc->ssh_session,
- conn->sock[FIRSTSOCKET]);
- if(rc == LIBSSH2_ERROR_EAGAIN) {
- break;
- }
- if(rc) {
- char *err_msg = NULL;
- (void)libssh2_session_last_error(sshc->ssh_session, &err_msg, NULL, 0);
- failf(data, "Failure establishing ssh session: %d, %s", rc, err_msg);
-
- state(data, SSH_SESSION_FREE);
- sshc->actualcode = CURLE_FAILED_INIT;
+ result = ssh_state_startup(data, sshc);
+ if(result)
break;
- }
-
- state(data, SSH_HOSTKEY);
-
FALLTHROUGH();
+
case SSH_HOSTKEY:
- /*
- * Before we authenticate we should check the hostkey's fingerprint
- * against our known hosts. How that is handled (reading from file,
- * whatever) is up to us.
- */
- result = ssh_check_fingerprint(data);
- if(!result)
- state(data, SSH_AUTHLIST);
- /* ssh_check_fingerprint sets state appropriately on error */
+ result = ssh_state_hostkey(data, sshc);
break;
case SSH_AUTHLIST:
- /*
- * Figure out authentication methods
- * NB: As soon as we have provided a username to an openssh server we
- * must never change it later. Thus, always specify the correct username
- * here, even though the libssh2 docs kind of indicate that it should be
- * possible to get a 'generic' list (not user-specific) of authentication
- * methods, presumably with a blank username. That will not work in my
- * experience.
- * So always specify it here.
- */
- sshc->authlist = libssh2_userauth_list(sshc->ssh_session,
- conn->user,
- curlx_uztoui(strlen(conn->user)));
-
- if(!sshc->authlist) {
- if(libssh2_userauth_authenticated(sshc->ssh_session)) {
- sshc->authed = TRUE;
- infof(data, "SSH user accepted with no authentication");
- state(data, SSH_AUTH_DONE);
- break;
- }
- rc = libssh2_session_last_errno(sshc->ssh_session);
- if(rc == LIBSSH2_ERROR_EAGAIN)
- rc = LIBSSH2_ERROR_EAGAIN;
- else {
- state(data, SSH_SESSION_FREE);
- sshc->actualcode = libssh2_session_error_to_CURLE(rc);
- }
- break;
- }
- infof(data, "SSH authentication methods available: %s",
- sshc->authlist);
-
- state(data, SSH_AUTH_PKEY_INIT);
+ result = ssh_state_authlist(data, sshc);
break;
case SSH_AUTH_PKEY_INIT:
- result = sftp_pkey_init(data, sshc);
+ result = ssh_state_pkey_init(data, sshc);
break;
case SSH_AUTH_PKEY:
- /* The function below checks if the files exists, no need to stat() here.
- */
- rc = libssh2_userauth_publickey_fromfile_ex(sshc->ssh_session,
- conn->user,
- curlx_uztoui(
- strlen(conn->user)),
- sshc->rsa_pub,
- sshc->rsa, sshc->passphrase);
- if(rc == LIBSSH2_ERROR_EAGAIN) {
- break;
- }
-
- Curl_safefree(sshc->rsa_pub);
- Curl_safefree(sshc->rsa);
-
- if(rc == 0) {
- sshc->authed = TRUE;
- infof(data, "Initialized SSH public key authentication");
- state(data, SSH_AUTH_DONE);
- }
- else {
- char *err_msg = NULL;
- char unknown[] = "Reason unknown (-1)";
- if(rc == -1) {
- /* No error message has been set and the last set error message, if
- any, is from a previous error so ignore it. #11837 */
- err_msg = unknown;
- }
- else {
- (void)libssh2_session_last_error(sshc->ssh_session,
- &err_msg, NULL, 0);
- }
- infof(data, "SSH public key authentication failed: %s", err_msg);
- state(data, SSH_AUTH_PASS_INIT);
- rc = 0; /* clear rc and continue */
- }
+ result = ssh_state_auth_pkey(data, sshc);
break;
case SSH_AUTH_PASS_INIT:
- if((data->set.ssh_auth_types & CURLSSH_AUTH_PASSWORD) &&
- (strstr(sshc->authlist, "password") != NULL)) {
- state(data, SSH_AUTH_PASS);
- }
- else {
- state(data, SSH_AUTH_HOST_INIT);
- rc = 0; /* clear rc and continue */
- }
+ result = ssh_state_auth_pass_init(data, sshc);
break;
case SSH_AUTH_PASS:
- rc = libssh2_userauth_password_ex(sshc->ssh_session, conn->user,
- curlx_uztoui(strlen(conn->user)),
- conn->passwd,
- curlx_uztoui(strlen(conn->passwd)),
- NULL);
- if(rc == LIBSSH2_ERROR_EAGAIN) {
- break;
- }
- if(rc == 0) {
- sshc->authed = TRUE;
- infof(data, "Initialized password authentication");
- state(data, SSH_AUTH_DONE);
- }
- else {
- state(data, SSH_AUTH_HOST_INIT);
- rc = 0; /* clear rc and continue */
- }
+ result = ssh_state_auth_pass(data, sshc);
break;
case SSH_AUTH_HOST_INIT:
- if((data->set.ssh_auth_types & CURLSSH_AUTH_HOST) &&
- (strstr(sshc->authlist, "hostbased") != NULL)) {
- state(data, SSH_AUTH_HOST);
- }
- else {
- state(data, SSH_AUTH_AGENT_INIT);
- }
+ result = ssh_state_auth_host_init(data, sshc);
break;
case SSH_AUTH_HOST:
- state(data, SSH_AUTH_AGENT_INIT);
+ myssh_state(data, sshc, SSH_AUTH_AGENT_INIT);
break;
case SSH_AUTH_AGENT_INIT:
- if((data->set.ssh_auth_types & CURLSSH_AUTH_AGENT)
- && (strstr(sshc->authlist, "publickey") != NULL)) {
-
- /* Connect to the ssh-agent */
- /* The agent could be shared by a curl thread i believe
- but nothing obvious as keys can be added/removed at any time */
- if(!sshc->ssh_agent) {
- sshc->ssh_agent = libssh2_agent_init(sshc->ssh_session);
- if(!sshc->ssh_agent) {
- infof(data, "Could not create agent object");
-
- state(data, SSH_AUTH_KEY_INIT);
- break;
- }
- }
-
- rc = libssh2_agent_connect(sshc->ssh_agent);
- if(rc == LIBSSH2_ERROR_EAGAIN)
- break;
- if(rc < 0) {
- infof(data, "Failure connecting to agent");
- state(data, SSH_AUTH_KEY_INIT);
- rc = 0; /* clear rc and continue */
- }
- else {
- state(data, SSH_AUTH_AGENT_LIST);
- }
- }
- else
- state(data, SSH_AUTH_KEY_INIT);
+ result = ssh_state_auth_agent_init(data, sshc);
break;
case SSH_AUTH_AGENT_LIST:
- rc = libssh2_agent_list_identities(sshc->ssh_agent);
-
- if(rc == LIBSSH2_ERROR_EAGAIN)
- break;
- if(rc < 0) {
- infof(data, "Failure requesting identities to agent");
- state(data, SSH_AUTH_KEY_INIT);
- rc = 0; /* clear rc and continue */
- }
- else {
- state(data, SSH_AUTH_AGENT);
- sshc->sshagent_prev_identity = NULL;
- }
+ result = ssh_state_auth_agent_list(data, sshc);
break;
case SSH_AUTH_AGENT:
- /* as prev_identity evolves only after an identity user auth finished we
- can safely request it again as long as EAGAIN is returned here or by
- libssh2_agent_userauth */
- rc = libssh2_agent_get_identity(sshc->ssh_agent,
- &sshc->sshagent_identity,
- sshc->sshagent_prev_identity);
- if(rc == LIBSSH2_ERROR_EAGAIN)
- break;
-
- if(rc == 0) {
- rc = libssh2_agent_userauth(sshc->ssh_agent, conn->user,
- sshc->sshagent_identity);
-
- if(rc < 0) {
- if(rc != LIBSSH2_ERROR_EAGAIN) {
- /* tried and failed? go to next identity */
- sshc->sshagent_prev_identity = sshc->sshagent_identity;
- }
- break;
- }
- }
-
- if(rc < 0)
- infof(data, "Failure requesting identities to agent");
- else if(rc == 1)
- infof(data, "No identity would match");
-
- if(rc == LIBSSH2_ERROR_NONE) {
- sshc->authed = TRUE;
- infof(data, "Agent based authentication successful");
- state(data, SSH_AUTH_DONE);
- }
- else {
- state(data, SSH_AUTH_KEY_INIT);
- rc = 0; /* clear rc and continue */
- }
+ result = ssh_state_auth_agent(data, sshc);
break;
case SSH_AUTH_KEY_INIT:
- if((data->set.ssh_auth_types & CURLSSH_AUTH_KEYBOARD)
- && (strstr(sshc->authlist, "keyboard-interactive") != NULL)) {
- state(data, SSH_AUTH_KEY);
- }
- else {
- state(data, SSH_AUTH_DONE);
- }
+ result = ssh_state_auth_key_init(data, sshc);
break;
case SSH_AUTH_KEY:
- /* Authentication failed. Continue with keyboard-interactive now. */
- rc = libssh2_userauth_keyboard_interactive_ex(sshc->ssh_session,
- conn->user,
- curlx_uztoui(
- strlen(conn->user)),
- &kbd_callback);
- if(rc == LIBSSH2_ERROR_EAGAIN) {
- break;
- }
- if(rc == 0) {
- sshc->authed = TRUE;
- infof(data, "Initialized keyboard interactive authentication");
- }
- state(data, SSH_AUTH_DONE);
+ result = ssh_state_auth_key(data, sshc);
break;
case SSH_AUTH_DONE:
- if(!sshc->authed) {
- failf(data, "Authentication failure");
- state(data, SSH_SESSION_FREE);
- sshc->actualcode = CURLE_LOGIN_DENIED;
- break;
- }
-
- /*
- * At this point we have an authenticated ssh session.
- */
- infof(data, "Authentication complete");
-
- Curl_pgrsTime(data, TIMER_APPCONNECT); /* SSH is connected */
-
- conn->sockfd = conn->sock[FIRSTSOCKET];
- conn->writesockfd = CURL_SOCKET_BAD;
-
- if(conn->handler->protocol == CURLPROTO_SFTP) {
- state(data, SSH_SFTP_INIT);
- break;
- }
- infof(data, "SSH CONNECT phase done");
- state(data, SSH_STOP);
+ result = ssh_state_auth_done(data, sshc);
break;
case SSH_SFTP_INIT:
- /*
- * Start the libssh2 sftp session
- */
- sshc->sftp_session = libssh2_sftp_init(sshc->ssh_session);
- if(!sshc->sftp_session) {
- char *err_msg = NULL;
- if(libssh2_session_last_errno(sshc->ssh_session) ==
- LIBSSH2_ERROR_EAGAIN) {
- rc = LIBSSH2_ERROR_EAGAIN;
- break;
- }
-
- (void)libssh2_session_last_error(sshc->ssh_session,
- &err_msg, NULL, 0);
- failf(data, "Failure initializing sftp session: %s", err_msg);
- state(data, SSH_SESSION_FREE);
- sshc->actualcode = CURLE_FAILED_INIT;
- break;
- }
- state(data, SSH_SFTP_REALPATH);
+ result = ssh_state_sftp_init(data, sshc);
break;
case SSH_SFTP_REALPATH:
- /*
- * Get the "home" directory
- */
- rc = libssh2_sftp_symlink_ex(sshc->sftp_session,
- ".", curlx_uztoui(strlen(".")),
- sshp->readdir_filename, CURL_PATH_MAX,
- LIBSSH2_SFTP_REALPATH);
- if(rc == LIBSSH2_ERROR_EAGAIN) {
- break;
- }
- if(rc > 0) {
- /* It seems that this string is not always NULL terminated */
- sshp->readdir_filename[rc] = '\0';
- free(sshc->homedir);
- sshc->homedir = strdup(sshp->readdir_filename);
- if(!sshc->homedir) {
- state(data, SSH_SFTP_CLOSE);
- sshc->actualcode = CURLE_OUT_OF_MEMORY;
- break;
- }
- free(data->state.most_recent_ftp_entrypath);
- data->state.most_recent_ftp_entrypath = strdup(sshc->homedir);
- if(!data->state.most_recent_ftp_entrypath)
- return CURLE_OUT_OF_MEMORY;
- }
- else {
- /* Return the error type */
- unsigned long sftperr = libssh2_sftp_last_error(sshc->sftp_session);
- if(sftperr)
- result = sftp_libssh2_error_to_CURLE(sftperr);
- else
- /* in this case, the error was not in the SFTP level but for example
- a time-out or similar */
- result = CURLE_SSH;
- sshc->actualcode = result;
- DEBUGF(infof(data, "error = %lu makes libcurl = %d",
- sftperr, (int)result));
- state(data, SSH_STOP);
- break;
- }
-
- /* This is the last step in the SFTP connect phase. Do note that while
- we get the homedir here, we get the "workingpath" in the DO action
- since the homedir will remain the same between request but the
- working path will not. */
- DEBUGF(infof(data, "SSH CONNECT phase done"));
- state(data, SSH_STOP);
+ result = ssh_state_sftp_realpath(data, sshc, sshp);
break;
case SSH_SFTP_QUOTE_INIT:
-
- result = Curl_getworkingpath(data, sshc->homedir, &sshp->path);
- if(result) {
- sshc->actualcode = result;
- state(data, SSH_STOP);
- break;
- }
-
- if(data->set.quote) {
- infof(data, "Sending quote commands");
- sshc->quote_item = data->set.quote;
- state(data, SSH_SFTP_QUOTE);
- }
- else {
- state(data, SSH_SFTP_GETINFO);
- }
+ result = ssh_state_sftp_quote_init(data, sshc, sshp);
break;
case SSH_SFTP_POSTQUOTE_INIT:
- if(data->set.postquote) {
- infof(data, "Sending quote commands");
- sshc->quote_item = data->set.postquote;
- state(data, SSH_SFTP_QUOTE);
- }
- else {
- state(data, SSH_STOP);
- }
+ result = ssh_state_sftp_postquote_init(data, sshc);
break;
case SSH_SFTP_QUOTE:
- /* Send quote commands */
- result = sftp_quote(data, sshc, sshp);
- if(result) {
- state(data, SSH_SFTP_CLOSE);
- sshc->nextstate = SSH_NO_STATE;
- sshc->actualcode = result;
- }
+ result = ssh_state_sftp_quote(data, sshc, sshp);
break;
case SSH_SFTP_NEXT_QUOTE:
- Curl_safefree(sshc->quote_path1);
- Curl_safefree(sshc->quote_path2);
-
- sshc->quote_item = sshc->quote_item->next;
-
- if(sshc->quote_item) {
- state(data, SSH_SFTP_QUOTE);
- }
- else {
- if(sshc->nextstate != SSH_NO_STATE) {
- state(data, sshc->nextstate);
- sshc->nextstate = SSH_NO_STATE;
- }
- else {
- state(data, SSH_SFTP_GETINFO);
- }
- }
+ result = ssh_state_sftp_next_quote(data, sshc);
break;
case SSH_SFTP_QUOTE_STAT:
- result = sftp_quote_stat(data, sshc, sshp, block);
- if(result) {
- state(data, SSH_SFTP_CLOSE);
- sshc->nextstate = SSH_NO_STATE;
- sshc->actualcode = result;
- }
+ result = ssh_state_sftp_quote_stat(data, sshc, sshp, block);
break;
case SSH_SFTP_QUOTE_SETSTAT:
- rc = libssh2_sftp_stat_ex(sshc->sftp_session, sshc->quote_path2,
- curlx_uztoui(strlen(sshc->quote_path2)),
- LIBSSH2_SFTP_SETSTAT,
- &sshp->quote_attrs);
- if(rc == LIBSSH2_ERROR_EAGAIN) {
- break;
- }
- if(rc && !sshc->acceptfail) {
- unsigned long sftperr = libssh2_sftp_last_error(sshc->sftp_session);
- Curl_safefree(sshc->quote_path1);
- Curl_safefree(sshc->quote_path2);
- failf(data, "Attempt to set SFTP stats failed: %s",
- sftp_libssh2_strerror(sftperr));
- state(data, SSH_SFTP_CLOSE);
- sshc->nextstate = SSH_NO_STATE;
- sshc->actualcode = CURLE_QUOTE_ERROR;
- break;
- }
- state(data, SSH_SFTP_NEXT_QUOTE);
+ result = ssh_state_sftp_quote_setstat(data, sshc, sshp);
break;
case SSH_SFTP_QUOTE_SYMLINK:
- rc = libssh2_sftp_symlink_ex(sshc->sftp_session, sshc->quote_path1,
- curlx_uztoui(strlen(sshc->quote_path1)),
- sshc->quote_path2,
- curlx_uztoui(strlen(sshc->quote_path2)),
- LIBSSH2_SFTP_SYMLINK);
- if(rc == LIBSSH2_ERROR_EAGAIN) {
- break;
- }
- if(rc && !sshc->acceptfail) {
- unsigned long sftperr = libssh2_sftp_last_error(sshc->sftp_session);
- Curl_safefree(sshc->quote_path1);
- Curl_safefree(sshc->quote_path2);
- failf(data, "symlink command failed: %s",
- sftp_libssh2_strerror(sftperr));
- state(data, SSH_SFTP_CLOSE);
- sshc->nextstate = SSH_NO_STATE;
- sshc->actualcode = CURLE_QUOTE_ERROR;
- break;
- }
- state(data, SSH_SFTP_NEXT_QUOTE);
+ result = ssh_state_sftp_quote_symlink(data, sshc);
break;
case SSH_SFTP_QUOTE_MKDIR:
- rc = libssh2_sftp_mkdir_ex(sshc->sftp_session, sshc->quote_path1,
- curlx_uztoui(strlen(sshc->quote_path1)),
- (long)data->set.new_directory_perms);
- if(rc == LIBSSH2_ERROR_EAGAIN) {
- break;
- }
- if(rc && !sshc->acceptfail) {
- unsigned long sftperr = libssh2_sftp_last_error(sshc->sftp_session);
- Curl_safefree(sshc->quote_path1);
- failf(data, "mkdir command failed: %s",
- sftp_libssh2_strerror(sftperr));
- state(data, SSH_SFTP_CLOSE);
- sshc->nextstate = SSH_NO_STATE;
- sshc->actualcode = CURLE_QUOTE_ERROR;
- break;
- }
- state(data, SSH_SFTP_NEXT_QUOTE);
+ result = ssh_state_sftp_quote_mkdir(data, sshc);
break;
case SSH_SFTP_QUOTE_RENAME:
- rc = libssh2_sftp_rename_ex(sshc->sftp_session, sshc->quote_path1,
- curlx_uztoui(strlen(sshc->quote_path1)),
- sshc->quote_path2,
- curlx_uztoui(strlen(sshc->quote_path2)),
- LIBSSH2_SFTP_RENAME_OVERWRITE |
- LIBSSH2_SFTP_RENAME_ATOMIC |
- LIBSSH2_SFTP_RENAME_NATIVE);
-
- if(rc == LIBSSH2_ERROR_EAGAIN) {
- break;
- }
- if(rc && !sshc->acceptfail) {
- unsigned long sftperr = libssh2_sftp_last_error(sshc->sftp_session);
- Curl_safefree(sshc->quote_path1);
- Curl_safefree(sshc->quote_path2);
- failf(data, "rename command failed: %s",
- sftp_libssh2_strerror(sftperr));
- state(data, SSH_SFTP_CLOSE);
- sshc->nextstate = SSH_NO_STATE;
- sshc->actualcode = CURLE_QUOTE_ERROR;
- break;
- }
- state(data, SSH_SFTP_NEXT_QUOTE);
+ result = ssh_state_sftp_quote_rename(data, sshc);
break;
case SSH_SFTP_QUOTE_RMDIR:
- rc = libssh2_sftp_rmdir_ex(sshc->sftp_session, sshc->quote_path1,
- curlx_uztoui(strlen(sshc->quote_path1)));
- if(rc == LIBSSH2_ERROR_EAGAIN) {
- break;
- }
- if(rc && !sshc->acceptfail) {
- unsigned long sftperr = libssh2_sftp_last_error(sshc->sftp_session);
- Curl_safefree(sshc->quote_path1);
- failf(data, "rmdir command failed: %s",
- sftp_libssh2_strerror(sftperr));
- state(data, SSH_SFTP_CLOSE);
- sshc->nextstate = SSH_NO_STATE;
- sshc->actualcode = CURLE_QUOTE_ERROR;
- break;
- }
- state(data, SSH_SFTP_NEXT_QUOTE);
+ result = ssh_state_sftp_quote_rmdir(data, sshc);
break;
case SSH_SFTP_QUOTE_UNLINK:
- rc = libssh2_sftp_unlink_ex(sshc->sftp_session, sshc->quote_path1,
- curlx_uztoui(strlen(sshc->quote_path1)));
- if(rc == LIBSSH2_ERROR_EAGAIN) {
- break;
- }
- if(rc && !sshc->acceptfail) {
- unsigned long sftperr = libssh2_sftp_last_error(sshc->sftp_session);
- Curl_safefree(sshc->quote_path1);
- failf(data, "rm command failed: %s", sftp_libssh2_strerror(sftperr));
- state(data, SSH_SFTP_CLOSE);
- sshc->nextstate = SSH_NO_STATE;
- sshc->actualcode = CURLE_QUOTE_ERROR;
- break;
- }
- state(data, SSH_SFTP_NEXT_QUOTE);
+ result = ssh_state_sftp_quote_unlink(data, sshc);
break;
case SSH_SFTP_QUOTE_STATVFS:
- {
- LIBSSH2_SFTP_STATVFS statvfs;
- rc = libssh2_sftp_statvfs(sshc->sftp_session, sshc->quote_path1,
- curlx_uztoui(strlen(sshc->quote_path1)),
- &statvfs);
-
- if(rc == LIBSSH2_ERROR_EAGAIN) {
- break;
- }
- if(rc && !sshc->acceptfail) {
- unsigned long sftperr = libssh2_sftp_last_error(sshc->sftp_session);
- Curl_safefree(sshc->quote_path1);
- failf(data, "statvfs command failed: %s",
- sftp_libssh2_strerror(sftperr));
- state(data, SSH_SFTP_CLOSE);
- sshc->nextstate = SSH_NO_STATE;
- sshc->actualcode = CURLE_QUOTE_ERROR;
- break;
- }
- else if(rc == 0) {
-#ifdef _MSC_VER
-#define CURL_LIBSSH2_VFS_SIZE_MASK "I64u"
-#else
-#define CURL_LIBSSH2_VFS_SIZE_MASK "llu"
-#endif
- char *tmp = aprintf("statvfs:\n"
- "f_bsize: %" CURL_LIBSSH2_VFS_SIZE_MASK "\n"
- "f_frsize: %" CURL_LIBSSH2_VFS_SIZE_MASK "\n"
- "f_blocks: %" CURL_LIBSSH2_VFS_SIZE_MASK "\n"
- "f_bfree: %" CURL_LIBSSH2_VFS_SIZE_MASK "\n"
- "f_bavail: %" CURL_LIBSSH2_VFS_SIZE_MASK "\n"
- "f_files: %" CURL_LIBSSH2_VFS_SIZE_MASK "\n"
- "f_ffree: %" CURL_LIBSSH2_VFS_SIZE_MASK "\n"
- "f_favail: %" CURL_LIBSSH2_VFS_SIZE_MASK "\n"
- "f_fsid: %" CURL_LIBSSH2_VFS_SIZE_MASK "\n"
- "f_flag: %" CURL_LIBSSH2_VFS_SIZE_MASK "\n"
- "f_namemax: %" CURL_LIBSSH2_VFS_SIZE_MASK "\n",
- statvfs.f_bsize, statvfs.f_frsize,
- statvfs.f_blocks, statvfs.f_bfree,
- statvfs.f_bavail, statvfs.f_files,
- statvfs.f_ffree, statvfs.f_favail,
- statvfs.f_fsid, statvfs.f_flag,
- statvfs.f_namemax);
- if(!tmp) {
- result = CURLE_OUT_OF_MEMORY;
- state(data, SSH_SFTP_CLOSE);
- sshc->nextstate = SSH_NO_STATE;
- break;
- }
-
- result = Curl_client_write(data, CLIENTWRITE_HEADER, tmp, strlen(tmp));
- free(tmp);
- if(result) {
- state(data, SSH_SFTP_CLOSE);
- sshc->nextstate = SSH_NO_STATE;
- sshc->actualcode = result;
- }
- }
- state(data, SSH_SFTP_NEXT_QUOTE);
+ result = ssh_state_sftp_quote_statvfs(data, sshc);
break;
- }
case SSH_SFTP_GETINFO:
if(data->set.get_filetime) {
- state(data, SSH_SFTP_FILETIME);
+ myssh_state(data, sshc, SSH_SFTP_FILETIME);
}
else {
- state(data, SSH_SFTP_TRANS_INIT);
+ myssh_state(data, sshc, SSH_SFTP_TRANS_INIT);
}
break;
@@ -2311,47 +2841,47 @@ static CURLcode ssh_statemachine(struct Curl_easy *data, bool *block)
{
LIBSSH2_SFTP_ATTRIBUTES attrs;
- rc = libssh2_sftp_stat_ex(sshc->sftp_session, sshp->path,
- curlx_uztoui(strlen(sshp->path)),
- LIBSSH2_SFTP_STAT, &attrs);
+ int rc = libssh2_sftp_stat_ex(sshc->sftp_session, sshp->path,
+ curlx_uztoui(strlen(sshp->path)),
+ LIBSSH2_SFTP_STAT, &attrs);
if(rc == LIBSSH2_ERROR_EAGAIN) {
+ result = CURLE_AGAIN;
break;
}
if(rc == 0) {
data->info.filetime = (time_t)attrs.mtime;
}
- state(data, SSH_SFTP_TRANS_INIT);
+ myssh_state(data, sshc, SSH_SFTP_TRANS_INIT);
break;
}
case SSH_SFTP_TRANS_INIT:
if(data->state.upload)
- state(data, SSH_SFTP_UPLOAD_INIT);
+ myssh_state(data, sshc, SSH_SFTP_UPLOAD_INIT);
else {
if(sshp->path[strlen(sshp->path)-1] == '/')
- state(data, SSH_SFTP_READDIR_INIT);
+ myssh_state(data, sshc, SSH_SFTP_READDIR_INIT);
else
- state(data, SSH_SFTP_DOWNLOAD_INIT);
+ myssh_state(data, sshc, SSH_SFTP_DOWNLOAD_INIT);
}
break;
case SSH_SFTP_UPLOAD_INIT:
result = sftp_upload_init(data, sshc, sshp, block);
if(result) {
- state(data, SSH_SFTP_CLOSE);
+ myssh_state(data, sshc, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
- sshc->actualcode = result;
}
break;
case SSH_SFTP_CREATE_DIRS_INIT:
if(strlen(sshp->path) > 1) {
sshc->slash_pos = sshp->path + 1; /* ignore the leading '/' */
- state(data, SSH_SFTP_CREATE_DIRS);
+ myssh_state(data, sshc, SSH_SFTP_CREATE_DIRS);
}
else {
- state(data, SSH_SFTP_UPLOAD_INIT);
+ myssh_state(data, sshc, SSH_SFTP_UPLOAD_INIT);
}
break;
@@ -2361,400 +2891,121 @@ static CURLcode ssh_statemachine(struct Curl_easy *data, bool *block)
*sshc->slash_pos = 0;
infof(data, "Creating directory '%s'", sshp->path);
- state(data, SSH_SFTP_CREATE_DIRS_MKDIR);
+ myssh_state(data, sshc, SSH_SFTP_CREATE_DIRS_MKDIR);
break;
}
- state(data, SSH_SFTP_UPLOAD_INIT);
+ myssh_state(data, sshc, SSH_SFTP_UPLOAD_INIT);
break;
case SSH_SFTP_CREATE_DIRS_MKDIR:
- /* 'mode' - parameter is preliminary - default to 0644 */
- rc = libssh2_sftp_mkdir_ex(sshc->sftp_session, sshp->path,
- curlx_uztoui(strlen(sshp->path)),
- (long)data->set.new_directory_perms);
- if(rc == LIBSSH2_ERROR_EAGAIN) {
- break;
- }
- *sshc->slash_pos = '/';
- ++sshc->slash_pos;
- if(rc < 0) {
- /*
- * Abort if failure was not that the dir already exists or the
- * permission was denied (creation might succeed further down the
- * path) - retry on unspecific FAILURE also
- */
- unsigned long sftperr = libssh2_sftp_last_error(sshc->sftp_session);
- if((sftperr != LIBSSH2_FX_FILE_ALREADY_EXISTS) &&
- (sftperr != LIBSSH2_FX_FAILURE) &&
- (sftperr != LIBSSH2_FX_PERMISSION_DENIED)) {
- result = sftp_libssh2_error_to_CURLE(sftperr);
- state(data, SSH_SFTP_CLOSE);
- sshc->actualcode = result ? result : CURLE_SSH;
- break;
- }
- rc = 0; /* clear rc and continue */
- }
- state(data, SSH_SFTP_CREATE_DIRS);
+ result = ssh_state_sftp_create_dirs_mkdir(data, sshc, sshp);
break;
case SSH_SFTP_READDIR_INIT:
- Curl_pgrsSetDownloadSize(data, -1);
- if(data->req.no_body) {
- state(data, SSH_STOP);
- break;
- }
-
- /*
- * This is a directory that we are trying to get, so produce a directory
- * listing
- */
- sshc->sftp_handle =
- libssh2_sftp_open_ex(sshc->sftp_session, sshp->path,
- curlx_uztoui(strlen(sshp->path)),
- 0, 0, LIBSSH2_SFTP_OPENDIR);
- if(!sshc->sftp_handle) {
- unsigned long sftperr;
- if(libssh2_session_last_errno(sshc->ssh_session) ==
- LIBSSH2_ERROR_EAGAIN) {
- rc = LIBSSH2_ERROR_EAGAIN;
- break;
- }
- sftperr = libssh2_sftp_last_error(sshc->sftp_session);
- failf(data, "Could not open directory for reading: %s",
- sftp_libssh2_strerror(sftperr));
- state(data, SSH_SFTP_CLOSE);
- result = sftp_libssh2_error_to_CURLE(sftperr);
- sshc->actualcode = result ? result : CURLE_SSH;
- break;
- }
- state(data, SSH_SFTP_READDIR);
+ result = ssh_state_sftp_readdir_init(data, sshc, sshp);
break;
case SSH_SFTP_READDIR:
result = sftp_readdir(data, sshc, sshp, block);
if(result) {
- sshc->actualcode = result;
- state(data, SSH_SFTP_CLOSE);
+ myssh_state(data, sshc, SSH_SFTP_CLOSE);
}
break;
case SSH_SFTP_READDIR_LINK:
- rc =
- libssh2_sftp_symlink_ex(sshc->sftp_session,
- Curl_dyn_ptr(&sshp->readdir_link),
- (unsigned int)
- Curl_dyn_len(&sshp->readdir_link),
- sshp->readdir_filename,
- CURL_PATH_MAX, LIBSSH2_SFTP_READLINK);
- if(rc == LIBSSH2_ERROR_EAGAIN) {
- break;
- }
- Curl_dyn_free(&sshp->readdir_link);
-
- /* append filename and extra output */
- result = Curl_dyn_addf(&sshp->readdir, " -> %s", sshp->readdir_filename);
-
- if(result) {
- state(data, SSH_SFTP_CLOSE);
- sshc->actualcode = result;
- break;
- }
-
- state(data, SSH_SFTP_READDIR_BOTTOM);
+ result = ssh_state_sftp_readdir_link(data, sshc, sshp);
break;
case SSH_SFTP_READDIR_BOTTOM:
- result = Curl_dyn_addn(&sshp->readdir, "\n", 1);
+ result = curlx_dyn_addn(&sshp->readdir, "\n", 1);
if(!result)
result = Curl_client_write(data, CLIENTWRITE_BODY,
- Curl_dyn_ptr(&sshp->readdir),
- Curl_dyn_len(&sshp->readdir));
+ curlx_dyn_ptr(&sshp->readdir),
+ curlx_dyn_len(&sshp->readdir));
if(result) {
- Curl_dyn_free(&sshp->readdir);
- state(data, SSH_STOP);
+ curlx_dyn_free(&sshp->readdir);
+ myssh_state(data, sshc, SSH_STOP);
}
else {
- Curl_dyn_reset(&sshp->readdir);
- state(data, SSH_SFTP_READDIR);
+ curlx_dyn_reset(&sshp->readdir);
+ myssh_state(data, sshc, SSH_SFTP_READDIR);
}
break;
case SSH_SFTP_READDIR_DONE:
- if(libssh2_sftp_closedir(sshc->sftp_handle) ==
- LIBSSH2_ERROR_EAGAIN) {
- rc = LIBSSH2_ERROR_EAGAIN;
- break;
- }
- sshc->sftp_handle = NULL;
+ if(libssh2_sftp_closedir(sshc->sftp_handle) == LIBSSH2_ERROR_EAGAIN)
+ result = CURLE_AGAIN;
+ else {
+ sshc->sftp_handle = NULL;
- /* no data to transfer */
- Curl_xfer_setup_nop(data);
- state(data, SSH_STOP);
+ /* no data to transfer */
+ Curl_xfer_setup_nop(data);
+ myssh_state(data, sshc, SSH_STOP);
+ }
break;
case SSH_SFTP_DOWNLOAD_INIT:
- /*
- * Work on getting the specified file
- */
- sshc->sftp_handle =
- libssh2_sftp_open_ex(sshc->sftp_session, sshp->path,
- curlx_uztoui(strlen(sshp->path)),
- LIBSSH2_FXF_READ, (long)data->set.new_file_perms,
- LIBSSH2_SFTP_OPENFILE);
- if(!sshc->sftp_handle) {
- unsigned long sftperr;
- if(libssh2_session_last_errno(sshc->ssh_session) ==
- LIBSSH2_ERROR_EAGAIN) {
- rc = LIBSSH2_ERROR_EAGAIN;
- break;
- }
- sftperr = libssh2_sftp_last_error(sshc->sftp_session);
- failf(data, "Could not open remote file for reading: %s",
- sftp_libssh2_strerror(sftperr));
- state(data, SSH_SFTP_CLOSE);
- result = sftp_libssh2_error_to_CURLE(sftperr);
- sshc->actualcode = result ? result : CURLE_SSH;
- break;
- }
- state(data, SSH_SFTP_DOWNLOAD_STAT);
+ result = ssh_state_sftp_download_init(data, sshc, sshp);
break;
case SSH_SFTP_DOWNLOAD_STAT:
result = sftp_download_stat(data, sshc, sshp, block);
if(result) {
- state(data, SSH_SFTP_CLOSE);
+ myssh_state(data, sshc, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
- sshc->actualcode = result;
}
break;
case SSH_SFTP_CLOSE:
- if(sshc->sftp_handle) {
- rc = libssh2_sftp_close(sshc->sftp_handle);
- if(rc == LIBSSH2_ERROR_EAGAIN) {
- break;
- }
- if(rc < 0) {
- char *err_msg = NULL;
- (void)libssh2_session_last_error(sshc->ssh_session,
- &err_msg, NULL, 0);
- infof(data, "Failed to close libssh2 file: %d %s", rc, err_msg);
- }
- sshc->sftp_handle = NULL;
- }
-
- Curl_safefree(sshp->path);
-
- DEBUGF(infof(data, "SFTP DONE done"));
-
- /* Check if nextstate is set and move .nextstate could be POSTQUOTE_INIT
- After nextstate is executed, the control should come back to
- SSH_SFTP_CLOSE to pass the correct result back */
- if(sshc->nextstate != SSH_NO_STATE &&
- sshc->nextstate != SSH_SFTP_CLOSE) {
- state(data, sshc->nextstate);
- sshc->nextstate = SSH_SFTP_CLOSE;
- }
- else {
- state(data, SSH_STOP);
- result = sshc->actualcode;
- }
+ result = ssh_state_sftp_close(data, sshc, sshp);
break;
case SSH_SFTP_SHUTDOWN:
- /* during times we get here due to a broken transfer and then the
- sftp_handle might not have been taken down so make sure that is done
- before we proceed */
-
- if(sshc->sftp_handle) {
- rc = libssh2_sftp_close(sshc->sftp_handle);
- if(rc == LIBSSH2_ERROR_EAGAIN) {
- break;
- }
- if(rc < 0) {
- char *err_msg = NULL;
- (void)libssh2_session_last_error(sshc->ssh_session, &err_msg,
- NULL, 0);
- infof(data, "Failed to close libssh2 file: %d %s", rc, err_msg);
- }
- sshc->sftp_handle = NULL;
- }
- if(sshc->sftp_session) {
- rc = libssh2_sftp_shutdown(sshc->sftp_session);
- if(rc == LIBSSH2_ERROR_EAGAIN) {
- break;
- }
- if(rc < 0) {
- infof(data, "Failed to stop libssh2 sftp subsystem");
- }
- sshc->sftp_session = NULL;
- }
-
- Curl_safefree(sshc->homedir);
-
- state(data, SSH_SESSION_DISCONNECT);
+ result = ssh_state_sftp_shutdown(data, sshc);
break;
case SSH_SCP_TRANS_INIT:
result = Curl_getworkingpath(data, sshc->homedir, &sshp->path);
if(result) {
- sshc->actualcode = result;
- state(data, SSH_STOP);
+ myssh_state(data, sshc, SSH_STOP);
break;
}
if(data->state.upload) {
if(data->state.infilesize < 0) {
failf(data, "SCP requires a known file size for upload");
- sshc->actualcode = CURLE_UPLOAD_FAILED;
- state(data, SSH_SCP_CHANNEL_FREE);
+ result = CURLE_UPLOAD_FAILED;
+ myssh_state(data, sshc, SSH_SCP_CHANNEL_FREE);
break;
}
- state(data, SSH_SCP_UPLOAD_INIT);
+ myssh_state(data, sshc, SSH_SCP_UPLOAD_INIT);
}
else {
- state(data, SSH_SCP_DOWNLOAD_INIT);
+ myssh_state(data, sshc, SSH_SCP_DOWNLOAD_INIT);
}
break;
case SSH_SCP_UPLOAD_INIT:
- /*
- * libssh2 requires that the destination path is a full path that
- * includes the destination file and name OR ends in a "/" . If this is
- * not done the destination file will be named the same name as the last
- * directory in the path.
- */
- sshc->ssh_channel =
- libssh2_scp_send64(sshc->ssh_session, sshp->path,
- (int)data->set.new_file_perms,
- (libssh2_int64_t)data->state.infilesize, 0, 0);
- if(!sshc->ssh_channel) {
- int ssh_err;
- char *err_msg = NULL;
-
- if(libssh2_session_last_errno(sshc->ssh_session) ==
- LIBSSH2_ERROR_EAGAIN) {
- rc = LIBSSH2_ERROR_EAGAIN;
- break;
- }
-
- ssh_err = (int)(libssh2_session_last_error(sshc->ssh_session,
- &err_msg, NULL, 0));
- failf(data, "%s", err_msg);
- state(data, SSH_SCP_CHANNEL_FREE);
- sshc->actualcode = libssh2_session_error_to_CURLE(ssh_err);
- /* Map generic errors to upload failed */
- if(sshc->actualcode == CURLE_SSH ||
- sshc->actualcode == CURLE_REMOTE_FILE_NOT_FOUND)
- sshc->actualcode = CURLE_UPLOAD_FAILED;
- break;
- }
-
- /* upload data */
- data->req.size = data->state.infilesize;
- Curl_pgrsSetUploadSize(data, data->state.infilesize);
- Curl_xfer_setup1(data, CURL_XFER_SEND, -1, FALSE);
-
- /* not set by Curl_xfer_setup to preserve keepon bits */
- conn->sockfd = conn->writesockfd;
-
- if(result) {
- state(data, SSH_SCP_CHANNEL_FREE);
- sshc->actualcode = result;
- }
- else {
- /* store this original bitmask setup to use later on if we cannot
- figure out a "real" bitmask */
- sshc->orig_waitfor = data->req.keepon;
-
- /* we want to use the _sending_ function even when the socket turns
- out readable as the underlying libssh2 scp send function will deal
- with both accordingly */
- data->state.select_bits = CURL_CSELECT_OUT;
-
- state(data, SSH_STOP);
- }
+ result = ssh_state_scp_upload_init(data, sshc, sshp);
break;
case SSH_SCP_DOWNLOAD_INIT:
- {
- curl_off_t bytecount;
-
- /*
- * We must check the remote file; if it is a directory no values will
- * be set in sb
- */
-
- /*
- * If support for >2GB files exists, use it.
- */
-
- /* get a fresh new channel from the ssh layer */
-#if LIBSSH2_VERSION_NUM < 0x010700
- struct stat sb;
- memset(&sb, 0, sizeof(struct stat));
- sshc->ssh_channel = libssh2_scp_recv(sshc->ssh_session,
- sshp->path, &sb);
-#else
- libssh2_struct_stat sb;
- memset(&sb, 0, sizeof(libssh2_struct_stat));
- sshc->ssh_channel = libssh2_scp_recv2(sshc->ssh_session,
- sshp->path, &sb);
-#endif
-
- if(!sshc->ssh_channel) {
- int ssh_err;
- char *err_msg = NULL;
-
- if(libssh2_session_last_errno(sshc->ssh_session) ==
- LIBSSH2_ERROR_EAGAIN) {
- rc = LIBSSH2_ERROR_EAGAIN;
- break;
- }
-
-
- ssh_err = (int)(libssh2_session_last_error(sshc->ssh_session,
- &err_msg, NULL, 0));
- failf(data, "%s", err_msg);
- state(data, SSH_SCP_CHANNEL_FREE);
- sshc->actualcode = libssh2_session_error_to_CURLE(ssh_err);
- break;
- }
-
- /* download data */
- bytecount = (curl_off_t)sb.st_size;
- data->req.maxdownload = (curl_off_t)sb.st_size;
- Curl_xfer_setup1(data, CURL_XFER_RECV, bytecount, FALSE);
-
- /* not set by Curl_xfer_setup to preserve keepon bits */
- conn->writesockfd = conn->sockfd;
-
- /* we want to use the _receiving_ function even when the socket turns
- out writableable as the underlying libssh2 recv function will deal
- with both accordingly */
- data->state.select_bits = CURL_CSELECT_IN;
-
- if(result) {
- state(data, SSH_SCP_CHANNEL_FREE);
- sshc->actualcode = result;
- }
- else
- state(data, SSH_STOP);
- }
- break;
+ result = ssh_state_scp_download_init(data, sshc, sshp);
+ break;
case SSH_SCP_DONE:
if(data->state.upload)
- state(data, SSH_SCP_SEND_EOF);
+ myssh_state(data, sshc, SSH_SCP_SEND_EOF);
else
- state(data, SSH_SCP_CHANNEL_FREE);
+ myssh_state(data, sshc, SSH_SCP_CHANNEL_FREE);
break;
case SSH_SCP_SEND_EOF:
if(sshc->ssh_channel) {
- rc = libssh2_channel_send_eof(sshc->ssh_channel);
+ int rc = libssh2_channel_send_eof(sshc->ssh_channel);
if(rc == LIBSSH2_ERROR_EAGAIN) {
+ result = CURLE_AGAIN;
break;
}
if(rc) {
@@ -2765,13 +3016,14 @@ static CURLcode ssh_statemachine(struct Curl_easy *data, bool *block)
rc, err_msg);
}
}
- state(data, SSH_SCP_WAIT_EOF);
+ myssh_state(data, sshc, SSH_SCP_WAIT_EOF);
break;
case SSH_SCP_WAIT_EOF:
if(sshc->ssh_channel) {
- rc = libssh2_channel_wait_eof(sshc->ssh_channel);
+ int rc = libssh2_channel_wait_eof(sshc->ssh_channel);
if(rc == LIBSSH2_ERROR_EAGAIN) {
+ result = CURLE_AGAIN;
break;
}
if(rc) {
@@ -2781,13 +3033,14 @@ static CURLcode ssh_statemachine(struct Curl_easy *data, bool *block)
infof(data, "Failed to get channel EOF: %d %s", rc, err_msg);
}
}
- state(data, SSH_SCP_WAIT_CLOSE);
+ myssh_state(data, sshc, SSH_SCP_WAIT_CLOSE);
break;
case SSH_SCP_WAIT_CLOSE:
if(sshc->ssh_channel) {
- rc = libssh2_channel_wait_closed(sshc->ssh_channel);
+ int rc = libssh2_channel_wait_closed(sshc->ssh_channel);
if(rc == LIBSSH2_ERROR_EAGAIN) {
+ result = CURLE_AGAIN;
break;
}
if(rc) {
@@ -2797,13 +3050,14 @@ static CURLcode ssh_statemachine(struct Curl_easy *data, bool *block)
infof(data, "Channel failed to close: %d %s", rc, err_msg);
}
}
- state(data, SSH_SCP_CHANNEL_FREE);
+ myssh_state(data, sshc, SSH_SCP_CHANNEL_FREE);
break;
case SSH_SCP_CHANNEL_FREE:
if(sshc->ssh_channel) {
- rc = libssh2_channel_free(sshc->ssh_channel);
+ int rc = libssh2_channel_free(sshc->ssh_channel);
if(rc == LIBSSH2_ERROR_EAGAIN) {
+ result = CURLE_AGAIN;
break;
}
if(rc < 0) {
@@ -2816,78 +3070,38 @@ static CURLcode ssh_statemachine(struct Curl_easy *data, bool *block)
sshc->ssh_channel = NULL;
}
DEBUGF(infof(data, "SCP DONE phase complete"));
-#if 0 /* PREV */
- state(data, SSH_SESSION_DISCONNECT);
-#endif
- state(data, SSH_STOP);
- result = sshc->actualcode;
+ myssh_state(data, sshc, SSH_STOP);
break;
case SSH_SESSION_DISCONNECT:
- /* during weird times when we have been prematurely aborted, the channel
- is still alive when we reach this state and we MUST kill the channel
- properly first */
- if(sshc->ssh_channel) {
- rc = libssh2_channel_free(sshc->ssh_channel);
- if(rc == LIBSSH2_ERROR_EAGAIN) {
- break;
- }
- if(rc < 0) {
- char *err_msg = NULL;
- (void)libssh2_session_last_error(sshc->ssh_session,
- &err_msg, NULL, 0);
- infof(data, "Failed to free libssh2 scp subsystem: %d %s",
- rc, err_msg);
- }
- sshc->ssh_channel = NULL;
- }
-
- if(sshc->ssh_session) {
- rc = libssh2_session_disconnect(sshc->ssh_session, "Shutdown");
- if(rc == LIBSSH2_ERROR_EAGAIN) {
- break;
- }
- if(rc < 0) {
- char *err_msg = NULL;
- (void)libssh2_session_last_error(sshc->ssh_session,
- &err_msg, NULL, 0);
- infof(data, "Failed to disconnect libssh2 session: %d %s",
- rc, err_msg);
- }
- }
-
- Curl_safefree(sshc->homedir);
-
- state(data, SSH_SESSION_FREE);
+ result = ssh_state_session_disconnect(data, sshc);
break;
case SSH_SESSION_FREE:
- rc = sshc_cleanup(sshc, data, FALSE);
- if(rc == LIBSSH2_ERROR_EAGAIN)
+ result = sshc_cleanup(sshc, data, FALSE);
+ if(result)
break;
/* the code we are about to return */
- result = sshc->actualcode;
memset(sshc, 0, sizeof(struct ssh_conn));
connclose(conn, "SSH session free");
sshc->state = SSH_SESSION_FREE; /* current */
- sshc->nextstate = SSH_NO_STATE;
- state(data, SSH_STOP);
+ myssh_state(data, sshc, SSH_STOP);
break;
case SSH_QUIT:
default:
/* internal error */
- sshc->nextstate = SSH_NO_STATE;
- state(data, SSH_STOP);
+ myssh_state(data, sshc, SSH_STOP);
break;
}
- } while(!rc && (sshc->state != SSH_STOP));
+ } while(!result && (sshc->state != SSH_STOP));
- if(rc == LIBSSH2_ERROR_EAGAIN) {
+ if(result == CURLE_AGAIN) {
/* we would block, we need to wait for the socket to be ready (in the
right direction too)! */
*block = TRUE;
+ result = CURLE_OK;
}
return result;
@@ -2920,10 +3134,11 @@ static int ssh_getsock(struct Curl_easy *data,
* function in all cases so that when it _does not_ return EAGAIN we can
* restore the default wait bits.
*/
-static void ssh_block2waitfor(struct Curl_easy *data, bool block)
+static void ssh_block2waitfor(struct Curl_easy *data,
+ struct ssh_conn *sshc,
+ bool block)
{
struct connectdata *conn = data->conn;
- struct ssh_conn *sshc = &conn->proto.sshc;
int dir = 0;
if(block) {
dir = libssh2_session_block_directions(sshc->ssh_session);
@@ -2943,35 +3158,39 @@ static void ssh_block2waitfor(struct Curl_easy *data, bool block)
static CURLcode ssh_multi_statemach(struct Curl_easy *data, bool *done)
{
struct connectdata *conn = data->conn;
- struct ssh_conn *sshc = &conn->proto.sshc;
+ struct ssh_conn *sshc = Curl_conn_meta_get(conn, CURL_META_SSH_CONN);
+ struct SSHPROTO *sshp = Curl_meta_get(data, CURL_META_SSH_EASY);
CURLcode result = CURLE_OK;
bool block; /* we store the status and use that to provide a ssh_getsock()
implementation */
+ if(!sshc || !sshp)
+ return CURLE_FAILED_INIT;
+
do {
- result = ssh_statemachine(data, &block);
+ result = ssh_statemachine(data, sshc, sshp, &block);
*done = (sshc->state == SSH_STOP);
/* if there is no error, it is not done and it did not EWOULDBLOCK, then
try again */
} while(!result && !*done && !block);
- ssh_block2waitfor(data, block);
+ ssh_block2waitfor(data, sshc, block);
return result;
}
static CURLcode ssh_block_statemach(struct Curl_easy *data,
- struct connectdata *conn,
+ struct ssh_conn *sshc,
+ struct SSHPROTO *sshp,
bool disconnect)
{
- struct ssh_conn *sshc = &conn->proto.sshc;
CURLcode result = CURLE_OK;
- struct curltime dis = Curl_now();
+ struct curltime dis = curlx_now();
while((sshc->state != SSH_STOP) && !result) {
bool block;
timediff_t left = 1000;
- struct curltime now = Curl_now();
+ struct curltime now = curlx_now();
- result = ssh_statemachine(data, &block);
+ result = ssh_statemachine(data, sshc, sshp, &block);
if(result)
break;
@@ -2989,7 +3208,7 @@ static CURLcode ssh_block_statemach(struct Curl_easy *data,
return CURLE_OPERATION_TIMEDOUT;
}
}
- else if(Curl_timediff(now, dis) > 1000) {
+ else if(curlx_timediff(now, dis) > 1000) {
/* disconnect timeout */
failf(data, "Disconnect timed out");
result = CURLE_OK;
@@ -2998,7 +3217,7 @@ static CURLcode ssh_block_statemach(struct Curl_easy *data,
if(block) {
int dir = libssh2_session_block_directions(sshc->ssh_session);
- curl_socket_t sock = conn->sock[FIRSTSOCKET];
+ curl_socket_t sock = data->conn->sock[FIRSTSOCKET];
curl_socket_t fd_read = CURL_SOCKET_BAD;
curl_socket_t fd_write = CURL_SOCKET_BAD;
if(LIBSSH2_SESSION_BLOCK_INBOUND & dir)
@@ -3014,28 +3233,52 @@ static CURLcode ssh_block_statemach(struct Curl_easy *data,
return result;
}
+static void myssh_easy_dtor(void *key, size_t klen, void *entry)
+{
+ struct SSHPROTO *sshp = entry;
+ (void)key;
+ (void)klen;
+ Curl_safefree(sshp->path);
+ curlx_dyn_free(&sshp->readdir);
+ curlx_dyn_free(&sshp->readdir_link);
+ free(sshp);
+}
+
+static void myssh_conn_dtor(void *key, size_t klen, void *entry)
+{
+ struct ssh_conn *sshc = entry;
+ (void)key;
+ (void)klen;
+ sshc_cleanup(sshc, NULL, TRUE);
+ free(sshc);
+}
+
/*
* SSH setup and connection
*/
static CURLcode ssh_setup_connection(struct Curl_easy *data,
struct connectdata *conn)
{
- struct ssh_conn *sshc = &conn->proto.sshc;
- struct SSHPROTO *ssh;
+ struct ssh_conn *sshc;
+ struct SSHPROTO *sshp;
(void)conn;
- if(!sshc->initialised) {
- /* other ssh implementations do something here, let's keep
- * the initialised flag correct even if this implementation does not. */
- sshc->initialised = TRUE;
- }
+ sshc = calloc(1, sizeof(*sshc));
+ if(!sshc)
+ return CURLE_OUT_OF_MEMORY;
+
+ sshc->initialised = TRUE;
+ if(Curl_conn_meta_set(conn, CURL_META_SSH_CONN, sshc, myssh_conn_dtor))
+ return CURLE_OUT_OF_MEMORY;
- data->req.p.ssh = ssh = calloc(1, sizeof(struct SSHPROTO));
- if(!ssh)
+ sshp = calloc(1, sizeof(*sshp));
+ if(!sshp)
return CURLE_OUT_OF_MEMORY;
- Curl_dyn_init(&ssh->readdir, CURL_PATH_MAX * 2);
- Curl_dyn_init(&ssh->readdir_link, CURL_PATH_MAX);
+ curlx_dyn_init(&sshp->readdir, CURL_PATH_MAX * 2);
+ curlx_dyn_init(&sshp->readdir_link, CURL_PATH_MAX);
+ if(Curl_meta_set(data, CURL_META_SSH_EASY, sshp, myssh_easy_dtor))
+ return CURLE_OUT_OF_MEMORY;
return CURLE_OK;
}
@@ -3052,13 +3295,16 @@ static ssize_t ssh_tls_recv(libssh2_socket_t sock, void *buffer,
CURLcode result;
struct connectdata *conn = data->conn;
Curl_recv *backup = conn->recv[0];
- struct ssh_conn *ssh = &conn->proto.sshc;
+ struct ssh_conn *sshc = Curl_conn_meta_get(conn, CURL_META_SSH_CONN);
int socknum = Curl_conn_sockindex(data, sock);
(void)flags;
+ if(!sshc)
+ return -1;
+
/* swap in the TLS reader function for this call only, and then swap back
the SSH one again */
- conn->recv[0] = ssh->tls_recv;
+ conn->recv[0] = sshc->tls_recv;
result = Curl_conn_recv(data, socknum, buffer, length, &nread);
conn->recv[0] = backup;
if(result == CURLE_AGAIN)
@@ -3077,13 +3323,16 @@ static ssize_t ssh_tls_send(libssh2_socket_t sock, const void *buffer,
CURLcode result;
struct connectdata *conn = data->conn;
Curl_send *backup = conn->send[0];
- struct ssh_conn *ssh = &conn->proto.sshc;
+ struct ssh_conn *sshc = Curl_conn_meta_get(conn, CURL_META_SSH_CONN);
int socknum = Curl_conn_sockindex(data, sock);
(void)flags;
+ if(!sshc)
+ return -1;
+
/* swap in the TLS writer function for this call only, and then swap back
the SSH one again */
- conn->send[0] = ssh->tls_send;
+ conn->send[0] = sshc->tls_send;
result = Curl_conn_send(data, socknum, buffer, length, FALSE, &nwrite);
conn->send[0] = backup;
if(result == CURLE_AGAIN)
@@ -3104,9 +3353,9 @@ static CURLcode ssh_connect(struct Curl_easy *data, bool *done)
#ifdef CURL_LIBSSH2_DEBUG
curl_socket_t sock;
#endif
- struct ssh_conn *sshc;
- CURLcode result;
struct connectdata *conn = data->conn;
+ struct ssh_conn *sshc = Curl_conn_meta_get(conn, CURL_META_SSH_CONN);
+ CURLcode result;
#if LIBSSH2_VERSION_NUM >= 0x010b00
{
@@ -3136,19 +3385,13 @@ static CURLcode ssh_connect(struct Curl_easy *data, bool *done)
}
#endif
- /* initialize per-handle data if not already */
- if(!data->req.p.ssh) {
- result = ssh_setup_connection(data, conn);
- if(result)
- return result;
- }
+ if(!sshc)
+ return CURLE_FAILED_INIT;
/* We default to persistent connections. We set this already in this connect
function to make the reuse checks properly be able to check this bit. */
connkeep(conn, "SSH default");
- sshc = &conn->proto.sshc;
-
if(conn->user)
infof(data, "User: '%s'", conn->user);
else
@@ -3272,7 +3515,7 @@ static CURLcode ssh_connect(struct Curl_easy *data, bool *done)
infof(data, "SSH socket: %d", (int)sock);
#endif /* CURL_LIBSSH2_DEBUG */
- state(data, SSH_INIT);
+ myssh_state(data, sshc, SSH_INIT);
result = ssh_multi_statemach(data, done);
@@ -3293,14 +3536,17 @@ CURLcode scp_perform(struct Curl_easy *data,
bool *connected,
bool *dophase_done)
{
+ struct ssh_conn *sshc = Curl_conn_meta_get(data->conn, CURL_META_SSH_CONN);
CURLcode result = CURLE_OK;
DEBUGF(infof(data, "DO phase starts"));
*dophase_done = FALSE; /* not done yet */
+ if(!sshc)
+ return CURLE_FAILED_INIT;
/* start the first command in the DO phase */
- state(data, SSH_SCP_TRANS_INIT);
+ myssh_state(data, sshc, SSH_SCP_TRANS_INIT);
/* run the state-machine */
result = ssh_multi_statemach(data, dophase_done);
@@ -3337,13 +3583,13 @@ static CURLcode ssh_do(struct Curl_easy *data, bool *done)
CURLcode result;
bool connected = FALSE;
struct connectdata *conn = data->conn;
- struct ssh_conn *sshc = &conn->proto.sshc;
+ struct ssh_conn *sshc = Curl_conn_meta_get(conn, CURL_META_SSH_CONN);
*done = FALSE; /* default to false */
+ if(!sshc)
+ return CURLE_FAILED_INIT;
data->req.size = -1; /* make sure this is unknown at this point */
-
- sshc->actualcode = CURLE_OK; /* reset error code */
sshc->secondCreateDirs = 0; /* reset the create dir attempt state
variable */
@@ -3360,8 +3606,8 @@ static CURLcode ssh_do(struct Curl_easy *data, bool *done)
return result;
}
-static int sshc_cleanup(struct ssh_conn *sshc, struct Curl_easy *data,
- bool block)
+static CURLcode sshc_cleanup(struct ssh_conn *sshc, struct Curl_easy *data,
+ bool block)
{
int rc;
@@ -3373,10 +3619,10 @@ static int sshc_cleanup(struct ssh_conn *sshc, struct Curl_easy *data,
if(sshc->ssh_agent) {
rc = libssh2_agent_disconnect(sshc->ssh_agent);
- if(!block && (rc == LIBSSH2_ERROR_EAGAIN)) {
- return rc;
- }
- if(rc < 0) {
+ if(!block && (rc == LIBSSH2_ERROR_EAGAIN))
+ return CURLE_AGAIN;
+
+ if((rc < 0) && data) {
char *err_msg = NULL;
(void)libssh2_session_last_error(sshc->ssh_session,
&err_msg, NULL, 0);
@@ -3392,12 +3638,51 @@ static int sshc_cleanup(struct ssh_conn *sshc, struct Curl_easy *data,
sshc->sshagent_prev_identity = NULL;
}
+ if(sshc->sftp_handle) {
+ rc = libssh2_sftp_close(sshc->sftp_handle);
+ if(!block && (rc == LIBSSH2_ERROR_EAGAIN))
+ return CURLE_AGAIN;
+
+ if((rc < 0) && data) {
+ char *err_msg = NULL;
+ (void)libssh2_session_last_error(sshc->ssh_session, &err_msg,
+ NULL, 0);
+ infof(data, "Failed to close libssh2 file: %d %s", rc, err_msg);
+ }
+ sshc->sftp_handle = NULL;
+ }
+
+ if(sshc->ssh_channel) {
+ rc = libssh2_channel_free(sshc->ssh_channel);
+ if(!block && (rc == LIBSSH2_ERROR_EAGAIN))
+ return CURLE_AGAIN;
+
+ if((rc < 0) && data) {
+ char *err_msg = NULL;
+ (void)libssh2_session_last_error(sshc->ssh_session,
+ &err_msg, NULL, 0);
+ infof(data, "Failed to free libssh2 scp subsystem: %d %s",
+ rc, err_msg);
+ }
+ sshc->ssh_channel = NULL;
+ }
+
+ if(sshc->sftp_session) {
+ rc = libssh2_sftp_shutdown(sshc->sftp_session);
+ if(!block && (rc == LIBSSH2_ERROR_EAGAIN))
+ return CURLE_AGAIN;
+
+ if((rc < 0) && data)
+ infof(data, "Failed to stop libssh2 sftp subsystem");
+ sshc->sftp_session = NULL;
+ }
+
if(sshc->ssh_session) {
rc = libssh2_session_free(sshc->ssh_session);
- if(!block && (rc == LIBSSH2_ERROR_EAGAIN)) {
- return rc;
- }
- if(rc < 0) {
+ if(!block && (rc == LIBSSH2_ERROR_EAGAIN))
+ return CURLE_AGAIN;
+
+ if((rc < 0) && data) {
char *err_msg = NULL;
(void)libssh2_session_last_error(sshc->ssh_session,
&err_msg, NULL, 0);
@@ -3421,7 +3706,7 @@ static int sshc_cleanup(struct ssh_conn *sshc, struct Curl_easy *data,
Curl_safefree(sshc->homedir);
sshc->initialised = FALSE;
}
- return 0;
+ return CURLE_OK;
}
@@ -3433,16 +3718,18 @@ static CURLcode scp_disconnect(struct Curl_easy *data,
bool dead_connection)
{
CURLcode result = CURLE_OK;
- struct ssh_conn *sshc = &conn->proto.sshc;
+ struct ssh_conn *sshc = Curl_conn_meta_get(conn, CURL_META_SSH_CONN);
+ struct SSHPROTO *sshp = Curl_meta_get(data, CURL_META_SSH_EASY);
(void) dead_connection;
- if(sshc->ssh_session) {
+ if(sshc && sshc->ssh_session && sshp) {
/* only if there is a session still around to use! */
- state(data, SSH_SESSION_DISCONNECT);
- result = ssh_block_statemach(data, conn, TRUE);
+ myssh_state(data, sshc, SSH_SESSION_DISCONNECT);
+ result = ssh_block_statemach(data, sshc, sshp, TRUE);
}
- sshc_cleanup(sshc, data, TRUE);
+ if(sshc)
+ return sshc_cleanup(sshc, data, TRUE);
return result;
}
@@ -3450,20 +3737,19 @@ static CURLcode scp_disconnect(struct Curl_easy *data,
done functions */
static CURLcode ssh_done(struct Curl_easy *data, CURLcode status)
{
+ struct ssh_conn *sshc = Curl_conn_meta_get(data->conn, CURL_META_SSH_CONN);
+ struct SSHPROTO *sshp = Curl_meta_get(data, CURL_META_SSH_EASY);
CURLcode result = CURLE_OK;
- struct SSHPROTO *sshp = data->req.p.ssh;
- struct connectdata *conn = data->conn;
+
+ if(!sshc || !sshp)
+ return CURLE_FAILED_INIT;
if(!status)
/* run the state-machine */
- result = ssh_block_statemach(data, conn, FALSE);
+ result = ssh_block_statemach(data, sshc, sshp, FALSE);
else
result = status;
- Curl_safefree(sshp->path);
- Curl_dyn_free(&sshp->readdir);
- Curl_dyn_free(&sshp->readdir_link);
-
if(Curl_pgrsDone(data))
return CURLE_ABORTED_BY_CALLBACK;
@@ -3475,13 +3761,13 @@ static CURLcode ssh_done(struct Curl_easy *data, CURLcode status)
static CURLcode scp_done(struct Curl_easy *data, CURLcode status,
bool premature)
{
+ struct ssh_conn *sshc = Curl_conn_meta_get(data->conn, CURL_META_SSH_CONN);
(void)premature; /* not used */
- if(!status)
- state(data, SSH_SCP_DONE);
+ if(sshc && !status)
+ myssh_state(data, sshc, SSH_SCP_DONE);
return ssh_done(data, status);
-
}
static ssize_t scp_send(struct Curl_easy *data, int sockindex,
@@ -3489,14 +3775,18 @@ static ssize_t scp_send(struct Curl_easy *data, int sockindex,
{
ssize_t nwrite;
struct connectdata *conn = data->conn;
- struct ssh_conn *sshc = &conn->proto.sshc;
+ struct ssh_conn *sshc = Curl_conn_meta_get(conn, CURL_META_SSH_CONN);
(void)sockindex; /* we only support SCP on the fixed known primary socket */
(void)eos;
+ if(!sshc) {
+ *err = CURLE_FAILED_INIT;
+ return -1;
+ }
/* libssh2_channel_write() returns int! */
nwrite = (ssize_t) libssh2_channel_write(sshc->ssh_channel, mem, len);
- ssh_block2waitfor(data, (nwrite == LIBSSH2_ERROR_EAGAIN));
+ ssh_block2waitfor(data, sshc, (nwrite == LIBSSH2_ERROR_EAGAIN));
if(nwrite == LIBSSH2_ERROR_EAGAIN) {
*err = CURLE_AGAIN;
@@ -3515,13 +3805,17 @@ static ssize_t scp_recv(struct Curl_easy *data, int sockindex,
{
ssize_t nread;
struct connectdata *conn = data->conn;
- struct ssh_conn *sshc = &conn->proto.sshc;
+ struct ssh_conn *sshc = Curl_conn_meta_get(conn, CURL_META_SSH_CONN);
(void)sockindex; /* we only support SCP on the fixed known primary socket */
+ if(!sshc) {
+ *err = CURLE_FAILED_INIT;
+ return -1;
+ }
/* libssh2_channel_read() returns int */
nread = (ssize_t) libssh2_channel_read(sshc->ssh_channel, mem, len);
- ssh_block2waitfor(data, (nread == LIBSSH2_ERROR_EAGAIN));
+ ssh_block2waitfor(data, sshc, (nread == LIBSSH2_ERROR_EAGAIN));
if(nread == LIBSSH2_ERROR_EAGAIN) {
*err = CURLE_AGAIN;
nread = -1;
@@ -3548,14 +3842,17 @@ CURLcode sftp_perform(struct Curl_easy *data,
bool *connected,
bool *dophase_done)
{
+ struct ssh_conn *sshc = Curl_conn_meta_get(data->conn, CURL_META_SSH_CONN);
CURLcode result = CURLE_OK;
DEBUGF(infof(data, "DO phase starts"));
*dophase_done = FALSE; /* not done yet */
+ if(!sshc)
+ return CURLE_FAILED_INIT;
/* start the first command in the DO phase */
- state(data, SSH_SFTP_QUOTE_INIT);
+ myssh_state(data, sshc, SSH_SFTP_QUOTE_INIT);
/* run the state-machine */
result = ssh_multi_statemach(data, dophase_done);
@@ -3588,19 +3885,21 @@ static CURLcode sftp_disconnect(struct Curl_easy *data,
struct connectdata *conn, bool dead_connection)
{
CURLcode result = CURLE_OK;
- struct ssh_conn *sshc = &conn->proto.sshc;
+ struct ssh_conn *sshc = Curl_conn_meta_get(conn, CURL_META_SSH_CONN);
+ struct SSHPROTO *sshp = Curl_meta_get(data, CURL_META_SSH_EASY);
(void) dead_connection;
DEBUGF(infof(data, "SSH DISCONNECT starts now"));
- if(sshc->ssh_session) {
+ if(sshc && sshc->ssh_session && sshp) {
/* only if there is a session still around to use! */
- state(data, SSH_SFTP_SHUTDOWN);
- result = ssh_block_statemach(data, conn, TRUE);
+ myssh_state(data, sshc, SSH_SFTP_SHUTDOWN);
+ result = ssh_block_statemach(data, sshc, sshp, TRUE);
}
DEBUGF(infof(data, "SSH DISCONNECT is done"));
- sshc_cleanup(sshc, data, TRUE);
+ if(sshc)
+ sshc_cleanup(sshc, data, TRUE);
return result;
@@ -3610,7 +3909,10 @@ static CURLcode sftp_done(struct Curl_easy *data, CURLcode status,
bool premature)
{
struct connectdata *conn = data->conn;
- struct ssh_conn *sshc = &conn->proto.sshc;
+ struct ssh_conn *sshc = Curl_conn_meta_get(conn, CURL_META_SSH_CONN);
+
+ if(!sshc)
+ return CURLE_FAILED_INIT;
if(!status) {
/* Post quote commands are executed after the SFTP_CLOSE state to avoid
@@ -3618,7 +3920,7 @@ static CURLcode sftp_done(struct Curl_easy *data, CURLcode status,
operation */
if(!premature && data->set.postquote && !conn->bits.retry)
sshc->nextstate = SSH_SFTP_POSTQUOTE_INIT;
- state(data, SSH_SFTP_CLOSE);
+ myssh_state(data, sshc, SSH_SFTP_CLOSE);
}
return ssh_done(data, status);
}
@@ -3629,13 +3931,17 @@ static ssize_t sftp_send(struct Curl_easy *data, int sockindex,
{
ssize_t nwrite;
struct connectdata *conn = data->conn;
- struct ssh_conn *sshc = &conn->proto.sshc;
+ struct ssh_conn *sshc = Curl_conn_meta_get(conn, CURL_META_SSH_CONN);
(void)sockindex;
(void)eos;
+ if(!sshc) {
+ *err = CURLE_FAILED_INIT;
+ return -1;
+ }
nwrite = libssh2_sftp_write(sshc->sftp_handle, mem, len);
- ssh_block2waitfor(data, (nwrite == LIBSSH2_ERROR_EAGAIN));
+ ssh_block2waitfor(data, sshc, (nwrite == LIBSSH2_ERROR_EAGAIN));
if(nwrite == LIBSSH2_ERROR_EAGAIN) {
*err = CURLE_AGAIN;
@@ -3658,12 +3964,16 @@ static ssize_t sftp_recv(struct Curl_easy *data, int sockindex,
{
ssize_t nread;
struct connectdata *conn = data->conn;
- struct ssh_conn *sshc = &conn->proto.sshc;
+ struct ssh_conn *sshc = Curl_conn_meta_get(conn, CURL_META_SSH_CONN);
(void)sockindex;
+ if(!sshc) {
+ *err = CURLE_FAILED_INIT;
+ return -1;
+ }
nread = libssh2_sftp_read(sshc->sftp_handle, mem, len);
- ssh_block2waitfor(data, (nread == LIBSSH2_ERROR_EAGAIN));
+ ssh_block2waitfor(data, sshc, (nread == LIBSSH2_ERROR_EAGAIN));
if(nread == LIBSSH2_ERROR_EAGAIN) {
*err = CURLE_AGAIN;
@@ -3770,8 +4080,8 @@ static void ssh_attach(struct Curl_easy *data, struct connectdata *conn)
DEBUGASSERT(data);
DEBUGASSERT(conn);
if(conn->handler->protocol & PROTO_FAMILY_SSH) {
- struct ssh_conn *sshc = &conn->proto.sshc;
- if(sshc->ssh_session) {
+ struct ssh_conn *sshc = Curl_conn_meta_get(conn, CURL_META_SSH_CONN);
+ if(sshc && sshc->ssh_session) {
/* only re-attach if the session already exists */
void **abstract = libssh2_session_abstract(sshc->ssh_session);
*abstract = data;
diff --git a/libs/libcurl/src/vssh/ssh.h b/libs/libcurl/src/vssh/ssh.h
index 0ed3ffa84e..73aec97a97 100644
--- a/libs/libcurl/src/vssh/ssh.h
+++ b/libs/libcurl/src/vssh/ssh.h
@@ -24,7 +24,7 @@
*
***************************************************************************/
-#include "curl_setup.h"
+#include "../curl_setup.h"
#if defined(USE_LIBSSH2)
#include <libssh2.h>
@@ -41,6 +41,11 @@
#include "curl_path.h"
+/* meta key for storing protocol meta at easy handle */
+#define CURL_META_SSH_EASY "meta:proto:ssh:easy"
+/* meta key for storing protocol meta at connection */
+#define CURL_META_SSH_CONN "meta:proto:ssh:conn"
+
/****************************************************************************
* SSH unique setup
***************************************************************************/
@@ -141,12 +146,8 @@ struct ssh_conn {
const char *passphrase; /* pass-phrase to use */
char *rsa_pub; /* strdup'ed public key file */
char *rsa; /* strdup'ed private key file */
- bool authed; /* the connection has been authenticated fine */
- bool acceptfail; /* used by the SFTP_QUOTE (continue if
- quote command fails) */
sshstate state; /* always use ssh.c:state() to change state! */
sshstate nextstate; /* the state to goto after stopping */
- CURLcode actualcode; /* the actual error code */
struct curl_slist *quote_item; /* for the quote option */
char *quote_path1; /* two generic pointers for the QUOTE stuff */
char *quote_path2;
@@ -162,6 +163,7 @@ struct ssh_conn {
char *slash_pos; /* used by the SFTP_CREATE_DIRS state */
#if defined(USE_LIBSSH)
+ CURLcode actualcode; /* the actual error code */
char *readdir_linkPath;
size_t readdir_len;
struct dynbuf readdir_buf;
@@ -206,6 +208,7 @@ struct ssh_conn {
struct libssh2_agent_publickey *sshagent_prev_identity;
LIBSSH2_KNOWNHOSTS *kh;
#elif defined(USE_WOLFSSH)
+ CURLcode actualcode; /* the actual error code */
WOLFSSH *ssh_session;
WOLFSSH_CTX *ctx;
word32 handleSz;
@@ -213,6 +216,9 @@ struct ssh_conn {
curl_off_t offset;
#endif /* USE_LIBSSH */
BIT(initialised);
+ BIT(authed); /* the connection has been authenticated fine */
+ BIT(acceptfail); /* used by the SFTP_QUOTE (continue if
+ quote command fails) */
};
#ifdef USE_LIBSSH
diff --git a/libs/libcurl/src/vssh/wolfssh.c b/libs/libcurl/src/vssh/wolfssh.c
index 4b278ce62f..7bf3e8a90b 100644
--- a/libs/libcurl/src/vssh/wolfssh.c
+++ b/libs/libcurl/src/vssh/wolfssh.c
@@ -22,29 +22,30 @@
*
***************************************************************************/
-#include "curl_setup.h"
+#include "../curl_setup.h"
#ifdef USE_WOLFSSH
#include <limits.h>
-#include "urldata.h"
-#include "cfilters.h"
-#include "connect.h"
-#include "sendf.h"
-#include "progress.h"
+#include "../urldata.h"
+#include "../url.h"
+#include "../cfilters.h"
+#include "../connect.h"
+#include "../sendf.h"
+#include "../progress.h"
#include "curl_path.h"
-#include "transfer.h"
-#include "speedcheck.h"
-#include "select.h"
-#include "multiif.h"
-#include "warnless.h"
-#include "strdup.h"
+#include "../transfer.h"
+#include "../speedcheck.h"
+#include "../select.h"
+#include "../multiif.h"
+#include "../curlx/warnless.h"
+#include "../strdup.h"
/* The last 3 #include files should be in this order */
-#include "curl_printf.h"
-#include "curl_memory.h"
-#include "memdebug.h"
+#include "../curl_printf.h"
+#include "../curl_memory.h"
+#include "../memdebug.h"
static CURLcode wssh_connect(struct Curl_easy *data, bool *done);
static CURLcode wssh_multi_statemach(struct Curl_easy *data, bool *done);
@@ -70,7 +71,7 @@ static int wssh_getsock(struct Curl_easy *data,
curl_socket_t *sock);
static CURLcode wssh_setup_connection(struct Curl_easy *data,
struct connectdata *conn);
-static void wssh_sshc_cleanup(struct ssh_conn *sshc, struct Curl_easy *data);
+static void wssh_sshc_cleanup(struct ssh_conn *sshc);
#if 0
/*
@@ -138,10 +139,10 @@ const struct Curl_handler Curl_handler_sftp = {
* SSH State machine related code
*/
/* This is the ONLY way to change SSH state! */
-static void state(struct Curl_easy *data, sshstate nowstate)
+static void wssh_state(struct Curl_easy *data,
+ struct ssh_conn *sshc,
+ sshstate nowstate)
{
- struct connectdata *conn = data->conn;
- struct ssh_conn *sshc = &conn->proto.sshc;
#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
/* for debug purposes */
static const char * const names[] = {
@@ -215,7 +216,7 @@ static void state(struct Curl_easy *data, sshstate nowstate)
(void *)sshc, names[sshc->state], names[nowstate]);
}
#endif
-
+ (void)data;
sshc->state = nowstate;
}
@@ -252,12 +253,16 @@ static ssize_t wsftp_send(struct Curl_easy *data, int sockindex,
const void *mem, size_t len, bool eos, CURLcode *err)
{
struct connectdata *conn = data->conn;
- struct ssh_conn *sshc = &conn->proto.sshc;
+ struct ssh_conn *sshc = Curl_conn_meta_get(conn, CURL_META_SSH_CONN);
word32 offset[2];
int rc;
(void)sockindex;
(void)eos;
+ if(!sshc) {
+ *err = CURLE_FAILED_INIT;
+ return -1;
+ }
offset[0] = (word32)sshc->offset & 0xFFFFFFFF;
offset[1] = (word32)(sshc->offset >> 32) & 0xFFFFFFFF;
@@ -298,10 +303,14 @@ static ssize_t wsftp_recv(struct Curl_easy *data, int sockindex,
{
int rc;
struct connectdata *conn = data->conn;
- struct ssh_conn *sshc = &conn->proto.sshc;
+ struct ssh_conn *sshc = Curl_conn_meta_get(conn, CURL_META_SSH_CONN);
word32 offset[2];
(void)sockindex;
+ if(!sshc) {
+ *err = CURLE_FAILED_INIT;
+ return -1;
+ }
offset[0] = (word32)sshc->offset & 0xFFFFFFFF;
offset[1] = (word32)(sshc->offset >> 32) & 0xFFFFFFFF;
@@ -333,17 +342,45 @@ static ssize_t wsftp_recv(struct Curl_easy *data, int sockindex,
return (ssize_t)rc;
}
+static void wssh_easy_dtor(void *key, size_t klen, void *entry)
+{
+ struct SSHPROTO *sshp = entry;
+ (void)key;
+ (void)klen;
+ Curl_safefree(sshp->path);
+ free(sshp);
+}
+
+static void wssh_conn_dtor(void *key, size_t klen, void *entry)
+{
+ struct ssh_conn *sshc = entry;
+ (void)key;
+ (void)klen;
+ wssh_sshc_cleanup(sshc);
+ free(sshc);
+}
+
/*
* SSH setup and connection
*/
static CURLcode wssh_setup_connection(struct Curl_easy *data,
struct connectdata *conn)
{
- struct SSHPROTO *ssh;
+ struct ssh_conn *sshc;
+ struct SSHPROTO *sshp;
(void)conn;
- data->req.p.ssh = ssh = calloc(1, sizeof(struct SSHPROTO));
- if(!ssh)
+ sshc = calloc(1, sizeof(*sshc));
+ if(!sshc)
+ return CURLE_OUT_OF_MEMORY;
+
+ sshc->initialised = TRUE;
+ if(Curl_conn_meta_set(conn, CURL_META_SSH_CONN, sshc, wssh_conn_dtor))
+ return CURLE_OUT_OF_MEMORY;
+
+ sshp = calloc(1, sizeof(*sshp));
+ if(!sshp ||
+ Curl_meta_set(data, CURL_META_SSH_EASY, sshp, wssh_easy_dtor))
return CURLE_OUT_OF_MEMORY;
return CURLE_OK;
@@ -368,13 +405,13 @@ static int userauth(byte authtype,
static CURLcode wssh_connect(struct Curl_easy *data, bool *done)
{
struct connectdata *conn = data->conn;
- struct ssh_conn *sshc = &conn->proto.sshc;
+ struct ssh_conn *sshc = Curl_conn_meta_get(conn, CURL_META_SSH_CONN);
+ struct SSHPROTO *sshp = Curl_meta_get(data, CURL_META_SSH_EASY);
curl_socket_t sock = conn->sock[FIRSTSOCKET];
int rc;
- /* initialize per-handle data if not already */
- if(!data->req.p.ssh)
- wssh_setup_connection(data, conn);
+ if(!sshc || !sshp)
+ return CURLE_FAILED_INIT;
/* We default to persistent connections. We set this already in this connect
function to make the reuse checks properly be able to check this bit. */
@@ -422,13 +459,13 @@ static CURLcode wssh_connect(struct Curl_easy *data, bool *done)
*done = TRUE;
if(conn->handler->protocol & CURLPROTO_SCP)
- state(data, SSH_INIT);
+ wssh_state(data, sshc, SSH_INIT);
else
- state(data, SSH_SFTP_INIT);
+ wssh_state(data, sshc, SSH_SFTP_INIT);
return wssh_multi_statemach(data, done);
error:
- wssh_sshc_cleanup(sshc, data);
+ wssh_sshc_cleanup(sshc);
return CURLE_FAILED_INIT;
}
@@ -439,20 +476,24 @@ error:
* wants to be called again when the socket is ready
*/
-static CURLcode wssh_statemach_act(struct Curl_easy *data, bool *block)
+static CURLcode wssh_statemach_act(struct Curl_easy *data,
+ struct ssh_conn *sshc,
+ bool *block)
{
CURLcode result = CURLE_OK;
struct connectdata *conn = data->conn;
- struct ssh_conn *sshc = &conn->proto.sshc;
- struct SSHPROTO *sftp_scp = data->req.p.ssh;
+ struct SSHPROTO *sftp_scp = Curl_meta_get(data, CURL_META_SSH_EASY);
WS_SFTPNAME *name;
int rc = 0;
*block = FALSE; /* we are not blocking by default */
+ if(!sftp_scp)
+ return CURLE_FAILED_INIT;
+
do {
switch(sshc->state) {
case SSH_INIT:
- state(data, SSH_S_STARTUP);
+ wssh_state(data, sshc, SSH_S_STARTUP);
break;
case SSH_S_STARTUP:
@@ -470,11 +511,11 @@ static CURLcode wssh_statemach_act(struct Curl_easy *data, bool *block)
return CURLE_OK;
}
else if(rc != WS_SUCCESS) {
- state(data, SSH_STOP);
+ wssh_state(data, sshc, SSH_STOP);
return CURLE_SSH;
}
infof(data, "wolfssh connected");
- state(data, SSH_STOP);
+ wssh_state(data, sshc, SSH_STOP);
break;
case SSH_STOP:
break;
@@ -495,7 +536,7 @@ static CURLcode wssh_statemach_act(struct Curl_easy *data, bool *block)
}
else if(rc == WS_SUCCESS) {
infof(data, "wolfssh SFTP connected");
- state(data, SSH_SFTP_REALPATH);
+ wssh_state(data, sshc, SSH_SFTP_REALPATH);
}
else {
failf(data, "wolfssh SFTP connect error %d", rc);
@@ -521,7 +562,7 @@ static CURLcode wssh_statemach_act(struct Curl_easy *data, bool *block)
if(!sshc->homedir)
sshc->actualcode = CURLE_OUT_OF_MEMORY;
wolfSSH_SFTPNAME_list_free(name);
- state(data, SSH_STOP);
+ wssh_state(data, sshc, SSH_STOP);
return CURLE_OK;
}
failf(data, "wolfssh SFTP realpath %d", rc);
@@ -531,35 +572,35 @@ static CURLcode wssh_statemach_act(struct Curl_easy *data, bool *block)
result = Curl_getworkingpath(data, sshc->homedir, &sftp_scp->path);
if(result) {
sshc->actualcode = result;
- state(data, SSH_STOP);
+ wssh_state(data, sshc, SSH_STOP);
break;
}
if(data->set.quote) {
infof(data, "Sending quote commands");
sshc->quote_item = data->set.quote;
- state(data, SSH_SFTP_QUOTE);
+ wssh_state(data, sshc, SSH_SFTP_QUOTE);
}
else {
- state(data, SSH_SFTP_GETINFO);
+ wssh_state(data, sshc, SSH_SFTP_GETINFO);
}
break;
case SSH_SFTP_GETINFO:
if(data->set.get_filetime) {
- state(data, SSH_SFTP_FILETIME);
+ wssh_state(data, sshc, SSH_SFTP_FILETIME);
}
else {
- state(data, SSH_SFTP_TRANS_INIT);
+ wssh_state(data, sshc, SSH_SFTP_TRANS_INIT);
}
break;
case SSH_SFTP_TRANS_INIT:
if(data->state.upload)
- state(data, SSH_SFTP_UPLOAD_INIT);
+ wssh_state(data, sshc, SSH_SFTP_UPLOAD_INIT);
else {
if(sftp_scp->path[strlen(sftp_scp->path)-1] == '/')
- state(data, SSH_SFTP_READDIR_INIT);
+ wssh_state(data, sshc, SSH_SFTP_READDIR_INIT);
else
- state(data, SSH_SFTP_DOWNLOAD_INIT);
+ wssh_state(data, sshc, SSH_SFTP_DOWNLOAD_INIT);
}
break;
case SSH_SFTP_UPLOAD_INIT: {
@@ -622,7 +663,7 @@ static CURLcode wssh_statemach_act(struct Curl_easy *data, bool *block)
failf(data, "wolfssh SFTP upload open failed: %d", rc);
return CURLE_SSH;
}
- state(data, SSH_SFTP_DOWNLOAD_STAT);
+ wssh_state(data, sshc, SSH_SFTP_DOWNLOAD_STAT);
/* If we have a restart point then we need to seek to the correct
position. */
@@ -688,7 +729,7 @@ static CURLcode wssh_statemach_act(struct Curl_easy *data, bool *block)
conn->sockfd = conn->writesockfd;
if(result) {
- state(data, SSH_SFTP_CLOSE);
+ wssh_state(data, sshc, SSH_SFTP_CLOSE);
sshc->actualcode = result;
}
else {
@@ -706,7 +747,7 @@ static CURLcode wssh_statemach_act(struct Curl_easy *data, bool *block)
timeout here */
Curl_expire(data, 0, EXPIRE_RUN_NOW);
- state(data, SSH_STOP);
+ wssh_state(data, sshc, SSH_STOP);
}
break;
}
@@ -729,7 +770,7 @@ static CURLcode wssh_statemach_act(struct Curl_easy *data, bool *block)
}
else if(rc == WS_SUCCESS) {
infof(data, "wolfssh SFTP open succeeded");
- state(data, SSH_SFTP_DOWNLOAD_STAT);
+ wssh_state(data, sshc, SSH_SFTP_DOWNLOAD_STAT);
return CURLE_OK;
}
@@ -784,7 +825,7 @@ static CURLcode wssh_statemach_act(struct Curl_easy *data, bool *block)
/* no data to transfer */
Curl_xfer_setup_nop(data);
infof(data, "File already completely downloaded");
- state(data, SSH_STOP);
+ wssh_state(data, sshc, SSH_STOP);
break;
}
Curl_xfer_setup1(data, CURL_XFER_RECV, data->req.size, FALSE);
@@ -800,11 +841,11 @@ static CURLcode wssh_statemach_act(struct Curl_easy *data, bool *block)
if(result) {
/* this should never occur; the close state should be entered
at the time the error occurs */
- state(data, SSH_SFTP_CLOSE);
+ wssh_state(data, sshc, SSH_SFTP_CLOSE);
sshc->actualcode = result;
}
else {
- state(data, SSH_STOP);
+ wssh_state(data, sshc, SSH_STOP);
}
break;
}
@@ -829,7 +870,7 @@ static CURLcode wssh_statemach_act(struct Curl_easy *data, bool *block)
return CURLE_OK;
}
else if(rc == WS_SUCCESS) {
- state(data, SSH_STOP);
+ wssh_state(data, sshc, SSH_STOP);
return CURLE_OK;
}
@@ -839,10 +880,10 @@ static CURLcode wssh_statemach_act(struct Curl_easy *data, bool *block)
case SSH_SFTP_READDIR_INIT:
Curl_pgrsSetDownloadSize(data, -1);
if(data->req.no_body) {
- state(data, SSH_STOP);
+ wssh_state(data, sshc, SSH_STOP);
break;
}
- state(data, SSH_SFTP_READDIR);
+ wssh_state(data, sshc, SSH_SFTP_READDIR);
break;
case SSH_SFTP_READDIR:
@@ -870,7 +911,7 @@ static CURLcode wssh_statemach_act(struct Curl_easy *data, bool *block)
data->set.list_only ?
name->fName : name->lName);
if(!line) {
- state(data, SSH_SFTP_CLOSE);
+ wssh_state(data, sshc, SSH_SFTP_CLOSE);
sshc->actualcode = CURLE_OUT_OF_MEMORY;
break;
}
@@ -884,15 +925,15 @@ static CURLcode wssh_statemach_act(struct Curl_easy *data, bool *block)
name = name->next;
}
wolfSSH_SFTPNAME_list_free(origname);
- state(data, SSH_STOP);
+ wssh_state(data, sshc, SSH_STOP);
return result;
}
failf(data, "wolfssh SFTP ls failed: %d", rc);
return CURLE_SSH;
case SSH_SFTP_SHUTDOWN:
- wssh_sshc_cleanup(sshc, data);
- state(data, SSH_STOP);
+ wssh_sshc_cleanup(sshc);
+ wssh_state(data, sshc, SSH_STOP);
return CURLE_OK;
default:
break;
@@ -905,12 +946,15 @@ static CURLcode wssh_statemach_act(struct Curl_easy *data, bool *block)
static CURLcode wssh_multi_statemach(struct Curl_easy *data, bool *done)
{
struct connectdata *conn = data->conn;
- struct ssh_conn *sshc = &conn->proto.sshc;
+ struct ssh_conn *sshc = Curl_conn_meta_get(conn, CURL_META_SSH_CONN);
CURLcode result = CURLE_OK;
bool block; /* we store the status and use that to provide a ssh_getsock()
implementation */
+ if(!sshc)
+ return CURLE_FAILED_INIT;
+
do {
- result = wssh_statemach_act(data, &block);
+ result = wssh_statemach_act(data, sshc, &block);
*done = (sshc->state == SSH_STOP);
/* if there is no error, it is not done and it did not EWOULDBLOCK, then
try again */
@@ -935,6 +979,7 @@ CURLcode wscp_perform(struct Curl_easy *data,
static
CURLcode wsftp_perform(struct Curl_easy *data,
+ struct ssh_conn *sshc,
bool *connected,
bool *dophase_done)
{
@@ -945,7 +990,7 @@ CURLcode wsftp_perform(struct Curl_easy *data,
*dophase_done = FALSE; /* not done yet */
/* start the first command in the DO phase */
- state(data, SSH_SFTP_QUOTE_INIT);
+ wssh_state(data, sshc, SSH_SFTP_QUOTE_INIT);
/* run the state-machine */
result = wssh_multi_statemach(data, dophase_done);
@@ -967,9 +1012,12 @@ static CURLcode wssh_do(struct Curl_easy *data, bool *done)
CURLcode result;
bool connected = FALSE;
struct connectdata *conn = data->conn;
- struct ssh_conn *sshc = &conn->proto.sshc;
+ struct ssh_conn *sshc = Curl_conn_meta_get(conn, CURL_META_SSH_CONN);
*done = FALSE; /* default to false */
+ if(!sshc)
+ return CURLE_FAILED_INIT;
+
data->req.size = -1; /* make sure this is unknown at this point */
sshc->actualcode = CURLE_OK; /* reset error code */
sshc->secondCreateDirs = 0; /* reset the create dir attempt state
@@ -983,24 +1031,24 @@ static CURLcode wssh_do(struct Curl_easy *data, bool *done)
if(conn->handler->protocol & CURLPROTO_SCP)
result = wscp_perform(data, &connected, done);
else
- result = wsftp_perform(data, &connected, done);
+ result = wsftp_perform(data, sshc, &connected, done);
return result;
}
static CURLcode wssh_block_statemach(struct Curl_easy *data,
- bool disconnect)
+ struct ssh_conn *sshc,
+ bool disconnect)
{
struct connectdata *conn = data->conn;
- struct ssh_conn *sshc = &conn->proto.sshc;
CURLcode result = CURLE_OK;
while((sshc->state != SSH_STOP) && !result) {
bool block;
timediff_t left = 1000;
- struct curltime now = Curl_now();
+ struct curltime now = curlx_now();
- result = wssh_statemach_act(data, &block);
+ result = wssh_statemach_act(data, sshc, &block);
if(result)
break;
@@ -1040,20 +1088,19 @@ static CURLcode wssh_block_statemach(struct Curl_easy *data,
/* generic done function for both SCP and SFTP called from their specific
done functions */
-static CURLcode wssh_done(struct Curl_easy *data, CURLcode status)
+static CURLcode wssh_done(struct Curl_easy *data,
+ struct ssh_conn *sshc,
+ CURLcode status)
{
CURLcode result = CURLE_OK;
- struct SSHPROTO *sftp_scp = data->req.p.ssh;
if(!status) {
/* run the state-machine */
- result = wssh_block_statemach(data, FALSE);
+ result = wssh_block_statemach(data, sshc, FALSE);
}
else
result = status;
- if(sftp_scp)
- Curl_safefree(sftp_scp->path);
if(Curl_pgrsDone(data))
return CURLE_ABORTED_BY_CALLBACK;
@@ -1061,9 +1108,8 @@ static CURLcode wssh_done(struct Curl_easy *data, CURLcode status)
return result;
}
-static void wssh_sshc_cleanup(struct ssh_conn *sshc, struct Curl_easy *data)
+static void wssh_sshc_cleanup(struct ssh_conn *sshc)
{
- (void)data;
if(sshc->ssh_session) {
wolfSSH_free(sshc->ssh_session);
sshc->ssh_session = NULL;
@@ -1100,10 +1146,11 @@ static CURLcode wscp_doing(struct Curl_easy *data,
static CURLcode wscp_disconnect(struct Curl_easy *data,
struct connectdata *conn, bool dead_connection)
{
- struct ssh_conn *sshc = &conn->proto.sshc;
+ struct ssh_conn *sshc = Curl_conn_meta_get(conn, CURL_META_SSH_CONN);
CURLcode result = CURLE_OK;
(void)dead_connection;
- wssh_sshc_cleanup(sshc, data);
+ if(sshc)
+ wssh_sshc_cleanup(sshc);
return result;
}
#endif
@@ -1111,10 +1158,14 @@ static CURLcode wscp_disconnect(struct Curl_easy *data,
static CURLcode wsftp_done(struct Curl_easy *data,
CURLcode code, bool premature)
{
+ struct ssh_conn *sshc = Curl_conn_meta_get(data->conn, CURL_META_SSH_CONN);
(void)premature;
- state(data, SSH_SFTP_CLOSE);
+ if(!sshc)
+ return CURLE_FAILED_INIT;
+
+ wssh_state(data, sshc, SSH_SFTP_CLOSE);
- return wssh_done(data, code);
+ return wssh_done(data, sshc, code);
}
static CURLcode wsftp_doing(struct Curl_easy *data,
@@ -1132,19 +1183,20 @@ static CURLcode wsftp_disconnect(struct Curl_easy *data,
struct connectdata *conn,
bool dead)
{
- struct ssh_conn *sshc = &conn->proto.sshc;
+ struct ssh_conn *sshc = Curl_conn_meta_get(conn, CURL_META_SSH_CONN);
CURLcode result = CURLE_OK;
(void)dead;
DEBUGF(infof(data, "SSH DISCONNECT starts now"));
- if(conn->proto.sshc.ssh_session) {
+ if(sshc && sshc->ssh_session) {
/* only if there is a session still around to use! */
- state(data, SSH_SFTP_SHUTDOWN);
- result = wssh_block_statemach(data, TRUE);
+ wssh_state(data, sshc, SSH_SFTP_SHUTDOWN);
+ result = wssh_block_statemach(data, sshc, TRUE);
}
- wssh_sshc_cleanup(sshc, data);
+ if(sshc)
+ wssh_sshc_cleanup(sshc);
DEBUGF(infof(data, "SSH DISCONNECT is done"));
return result;
}
diff --git a/libs/libcurl/src/vtls/bearssl.c b/libs/libcurl/src/vtls/bearssl.c
index bf3f77e8be..4df187dc50 100644
--- a/libs/libcurl/src/vtls/bearssl.c
+++ b/libs/libcurl/src/vtls/bearssl.c
@@ -21,7 +21,7 @@
* SPDX-License-Identifier: curl
*
***************************************************************************/
-#include "curl_setup.h"
+#include "../curl_setup.h"
#ifdef USE_BEARSSL
@@ -29,20 +29,20 @@
#include "bearssl.h"
#include "cipher_suite.h"
-#include "urldata.h"
-#include "sendf.h"
-#include "inet_pton.h"
+#include "../urldata.h"
+#include "../sendf.h"
+#include "../curlx/inet_pton.h"
#include "vtls.h"
#include "vtls_int.h"
#include "vtls_scache.h"
-#include "connect.h"
-#include "select.h"
-#include "multiif.h"
-#include "curl_printf.h"
+#include "../connect.h"
+#include "../select.h"
+#include "../multiif.h"
+#include "../curl_printf.h"
/* The last #include files should be: */
-#include "curl_memory.h"
-#include "memdebug.h"
+#include "../curl_memory.h"
+#include "../memdebug.h"
struct x509_context {
const br_x509_class *vtable;
diff --git a/libs/libcurl/src/vtls/bearssl.h b/libs/libcurl/src/vtls/bearssl.h
index 76857f9419..aca1a7bd6a 100644
--- a/libs/libcurl/src/vtls/bearssl.h
+++ b/libs/libcurl/src/vtls/bearssl.h
@@ -24,7 +24,7 @@
*
***************************************************************************/
-#include "curl_setup.h"
+#include "../curl_setup.h"
#ifdef USE_BEARSSL
diff --git a/libs/libcurl/src/vtls/cipher_suite.c b/libs/libcurl/src/vtls/cipher_suite.c
index 202a1452b0..68bf3b6305 100644
--- a/libs/libcurl/src/vtls/cipher_suite.c
+++ b/libs/libcurl/src/vtls/cipher_suite.c
@@ -21,13 +21,13 @@
* SPDX-License-Identifier: curl
*
***************************************************************************/
-#include "curl_setup.h"
+#include "../curl_setup.h"
#if defined(USE_SECTRANSP) || defined(USE_MBEDTLS) || \
defined(USE_BEARSSL) || defined(USE_RUSTLS)
#include "cipher_suite.h"
-#include "curl_printf.h"
-#include "strcase.h"
+#include "../curl_printf.h"
+#include "../strcase.h"
#include <string.h>
/*
diff --git a/libs/libcurl/src/vtls/cipher_suite.h b/libs/libcurl/src/vtls/cipher_suite.h
index 8f3381d1b9..f25de29b52 100644
--- a/libs/libcurl/src/vtls/cipher_suite.h
+++ b/libs/libcurl/src/vtls/cipher_suite.h
@@ -24,7 +24,7 @@
*
***************************************************************************/
-#include "curl_setup.h"
+#include "../curl_setup.h"
#if defined(USE_SECTRANSP) || defined(USE_MBEDTLS) || \
defined(USE_BEARSSL) || defined(USE_RUSTLS)
diff --git a/libs/libcurl/src/vtls/gtls.c b/libs/libcurl/src/vtls/gtls.c
index 09b4e22352..1bd7793111 100644
--- a/libs/libcurl/src/vtls/gtls.c
+++ b/libs/libcurl/src/vtls/gtls.c
@@ -30,7 +30,7 @@
* since they were not present in 1.0.X.
*/
-#include "curl_setup.h"
+#include "../curl_setup.h"
#ifdef USE_GNUTLS
@@ -40,28 +40,28 @@
#include <gnutls/crypto.h>
#include <nettle/sha2.h>
-#include "urldata.h"
-#include "sendf.h"
-#include "inet_pton.h"
+#include "../urldata.h"
+#include "../sendf.h"
+#include "../curlx/inet_pton.h"
#include "keylog.h"
#include "gtls.h"
#include "vtls.h"
#include "vtls_int.h"
#include "vtls_scache.h"
-#include "vauth/vauth.h"
-#include "parsedate.h"
-#include "connect.h" /* for the connect timeout */
-#include "progress.h"
-#include "select.h"
-#include "strcase.h"
-#include "strdup.h"
-#include "warnless.h"
+#include "../vauth/vauth.h"
+#include "../parsedate.h"
+#include "../connect.h" /* for the connect timeout */
+#include "../progress.h"
+#include "../select.h"
+#include "../strcase.h"
+#include "../strdup.h"
+#include "../curlx/warnless.h"
#include "x509asn1.h"
-#include "multiif.h"
-#include "curl_printf.h"
-#include "curl_memory.h"
+#include "../multiif.h"
+#include "../curl_printf.h"
+#include "../curl_memory.h"
/* The last #include file should be: */
-#include "memdebug.h"
+#include "../memdebug.h"
/* Enable GnuTLS debugging by defining GTLSDEBUG */
/*#define GTLSDEBUG */
@@ -426,7 +426,7 @@ CURLcode Curl_gtls_shared_creds_create(struct Curl_easy *data,
}
shared->refcount = 1;
- shared->time = Curl_now();
+ shared->time = curlx_now();
*pcreds = shared;
return CURLE_OK;
}
@@ -540,8 +540,8 @@ static bool gtls_shared_creds_expired(const struct Curl_easy *data,
const struct gtls_shared_creds *sc)
{
const struct ssl_general_config *cfg = &data->set.general_ssl;
- struct curltime now = Curl_now();
- timediff_t elapsed_ms = Curl_timediff(now, sc->time);
+ struct curltime now = curlx_now();
+ timediff_t elapsed_ms = curlx_timediff(now, sc->time);
timediff_t timeout_ms = cfg->ca_cache_timeout * (timediff_t)1000;
if(timeout_ms < 0)
@@ -794,18 +794,18 @@ static CURLcode gtls_set_priority(struct Curl_cfilter *cf,
CURLcode result = CURLE_OK;
int rc;
- Curl_dyn_init(&buf, 4096);
+ curlx_dyn_init(&buf, 4096);
#ifdef USE_GNUTLS_SRP
if(conn_config->username) {
/* Only add SRP to the cipher list if SRP is requested. Otherwise
* GnuTLS will disable TLS 1.3 support. */
- result = Curl_dyn_add(&buf, priority);
+ result = curlx_dyn_add(&buf, priority);
if(!result)
- result = Curl_dyn_add(&buf, ":" GNUTLS_SRP);
+ result = curlx_dyn_add(&buf, ":" GNUTLS_SRP);
if(result)
goto out;
- priority = Curl_dyn_ptr(&buf);
+ priority = curlx_dyn_ptr(&buf);
}
#endif
@@ -814,15 +814,15 @@ static CURLcode gtls_set_priority(struct Curl_cfilter *cf,
(conn_config->cipher_list[0] == '-') ||
(conn_config->cipher_list[0] == '!')) {
/* add it to out own */
- if(!Curl_dyn_len(&buf)) { /* not added yet */
- result = Curl_dyn_add(&buf, priority);
+ if(!curlx_dyn_len(&buf)) { /* not added yet */
+ result = curlx_dyn_add(&buf, priority);
if(result)
goto out;
}
- result = Curl_dyn_addf(&buf, ":%s", conn_config->cipher_list);
+ result = curlx_dyn_addf(&buf, ":%s", conn_config->cipher_list);
if(result)
goto out;
- priority = Curl_dyn_ptr(&buf);
+ priority = curlx_dyn_ptr(&buf);
}
else /* replace our own completely */
priority = conn_config->cipher_list;
@@ -836,7 +836,7 @@ static CURLcode gtls_set_priority(struct Curl_cfilter *cf,
}
out:
- Curl_dyn_free(&buf);
+ curlx_dyn_free(&buf);
return result;
}
diff --git a/libs/libcurl/src/vtls/gtls.h b/libs/libcurl/src/vtls/gtls.h
index da1f57f8c8..dc8de777af 100644
--- a/libs/libcurl/src/vtls/gtls.h
+++ b/libs/libcurl/src/vtls/gtls.h
@@ -24,13 +24,13 @@
*
***************************************************************************/
-#include "curl_setup.h"
+#include "../curl_setup.h"
#include <curl/curl.h>
#ifdef USE_GNUTLS
#include <gnutls/gnutls.h>
-#include "timeval.h"
+#include "../curlx/timeval.h"
#ifdef HAVE_GNUTLS_SRP
/* the function exists */
diff --git a/libs/libcurl/src/vtls/hostcheck.c b/libs/libcurl/src/vtls/hostcheck.c
index 79ed869e87..482725cb87 100644
--- a/libs/libcurl/src/vtls/hostcheck.c
+++ b/libs/libcurl/src/vtls/hostcheck.c
@@ -22,7 +22,7 @@
*
***************************************************************************/
-#include "curl_setup.h"
+#include "../curl_setup.h"
#if defined(USE_OPENSSL) \
|| defined(USE_SCHANNEL)
@@ -34,15 +34,14 @@
#ifdef HAVE_NETINET_IN6_H
#include <netinet/in6.h>
#endif
-#include "curl_memrchr.h"
-
+#include "../curl_memrchr.h"
#include "hostcheck.h"
-#include "strcase.h"
-#include "hostip.h"
+#include "../strcase.h"
+#include "../hostip.h"
-#include "curl_memory.h"
+#include "../curl_memory.h"
/* The last #include file should be: */
-#include "memdebug.h"
+#include "../memdebug.h"
/* check the two input strings with given length, but do not
assume they end in nul-bytes */
diff --git a/libs/libcurl/src/vtls/keylog.c b/libs/libcurl/src/vtls/keylog.c
index c922879d05..77321c9f76 100644
--- a/libs/libcurl/src/vtls/keylog.c
+++ b/libs/libcurl/src/vtls/keylog.c
@@ -21,7 +21,7 @@
* SPDX-License-Identifier: curl
*
***************************************************************************/
-#include "curl_setup.h"
+#include "../curl_setup.h"
#if defined(USE_OPENSSL) || \
defined(USE_GNUTLS) || \
@@ -32,10 +32,11 @@
#include "keylog.h"
#include <curl/curl.h>
+#include "../escape.h"
/* The last #include files should be: */
-#include "curl_memory.h"
-#include "memdebug.h"
+#include "../curl_memory.h"
+#include "../memdebug.h"
/* The fp for the open SSLKEYLOGFILE, or NULL if not open */
static FILE *keylog_file_fp;
@@ -114,10 +115,9 @@ Curl_tls_keylog_write(const char *label,
const unsigned char client_random[CLIENT_RANDOM_SIZE],
const unsigned char *secret, size_t secretlen)
{
- const char *hex = "0123456789ABCDEF";
size_t pos, i;
- char line[KEYLOG_LABEL_MAXLEN + 1 + 2 * CLIENT_RANDOM_SIZE + 1 +
- 2 * SECRET_MAXLEN + 1 + 1];
+ unsigned char line[KEYLOG_LABEL_MAXLEN + 1 + 2 * CLIENT_RANDOM_SIZE + 1 +
+ 2 * SECRET_MAXLEN + 1 + 1];
if(!keylog_file_fp) {
return FALSE;
@@ -134,22 +134,22 @@ Curl_tls_keylog_write(const char *label,
/* Client Random */
for(i = 0; i < CLIENT_RANDOM_SIZE; i++) {
- line[pos++] = hex[client_random[i] >> 4];
- line[pos++] = hex[client_random[i] & 0xF];
+ Curl_hexbyte(&line[pos], client_random[i], FALSE);
+ pos += 2;
}
line[pos++] = ' ';
/* Secret */
for(i = 0; i < secretlen; i++) {
- line[pos++] = hex[secret[i] >> 4];
- line[pos++] = hex[secret[i] & 0xF];
+ Curl_hexbyte(&line[pos], secret[i], FALSE);
+ pos += 2;
}
line[pos++] = '\n';
line[pos] = '\0';
/* Using fputs here instead of fprintf since libcurl's fprintf replacement
may not be thread-safe. */
- fputs(line, keylog_file_fp);
+ fputs((char *)line, keylog_file_fp);
return TRUE;
}
diff --git a/libs/libcurl/src/vtls/keylog.h b/libs/libcurl/src/vtls/keylog.h
index 41e901db73..5b2df7fe8f 100644
--- a/libs/libcurl/src/vtls/keylog.h
+++ b/libs/libcurl/src/vtls/keylog.h
@@ -23,7 +23,7 @@
* SPDX-License-Identifier: curl
*
***************************************************************************/
-#include "curl_setup.h"
+#include "../curl_setup.h"
#define KEYLOG_LABEL_MAXLEN (sizeof("CLIENT_HANDSHAKE_TRAFFIC_SECRET") - 1)
diff --git a/libs/libcurl/src/vtls/mbedtls.c b/libs/libcurl/src/vtls/mbedtls.c
index 851802f147..0404c83407 100644
--- a/libs/libcurl/src/vtls/mbedtls.c
+++ b/libs/libcurl/src/vtls/mbedtls.c
@@ -29,7 +29,7 @@
*
*/
-#include "curl_setup.h"
+#include "../curl_setup.h"
#ifdef USE_MBEDTLS
@@ -57,26 +57,26 @@
#endif /* MBEDTLS_VERSION_MAJOR >= 2 */
#include "cipher_suite.h"
-#include "strcase.h"
-#include "urldata.h"
-#include "sendf.h"
-#include "inet_pton.h"
+#include "../strcase.h"
+#include "../urldata.h"
+#include "../sendf.h"
+#include "../curlx/inet_pton.h"
#include "mbedtls.h"
#include "vtls.h"
#include "vtls_int.h"
#include "vtls_scache.h"
#include "x509asn1.h"
-#include "parsedate.h"
-#include "connect.h" /* for the connect timeout */
-#include "select.h"
-#include "multiif.h"
+#include "../parsedate.h"
+#include "../connect.h" /* for the connect timeout */
+#include "../select.h"
+#include "../multiif.h"
#include "mbedtls_threadlock.h"
-#include "strdup.h"
+#include "../strdup.h"
/* The last 3 #include files should be in this order */
-#include "curl_printf.h"
-#include "curl_memory.h"
-#include "memdebug.h"
+#include "../curl_printf.h"
+#include "../curl_memory.h"
+#include "../memdebug.h"
/* ALPN for http2 */
#if defined(USE_HTTP2) && defined(MBEDTLS_SSL_ALPN)
@@ -273,7 +273,13 @@ mbed_set_ssl_version_min_max(struct Curl_easy *data,
#else
/* mbedTLS 3.2.0 (2022) introduced new methods for setting TLS version */
mbedtls_ssl_protocol_version ver_min = MBEDTLS_SSL_VERSION_TLS1_2;
- mbedtls_ssl_protocol_version ver_max = MBEDTLS_SSL_VERSION_TLS1_2;
+ mbedtls_ssl_protocol_version ver_max =
+#ifdef HAS_TLS13_SUPPORT
+ MBEDTLS_SSL_VERSION_TLS1_3
+#else
+ MBEDTLS_SSL_VERSION_TLS1_2
+#endif
+ ;
#endif
switch(conn_config->version) {
@@ -292,7 +298,11 @@ mbed_set_ssl_version_min_max(struct Curl_easy *data,
case CURL_SSLVERSION_TLSv1_1:
#endif
case CURL_SSLVERSION_TLSv1_2:
- /* ver_min = MBEDTLS_SSL_VERSION_TLS1_2; */
+#if MBEDTLS_VERSION_NUMBER < 0x03020000
+ ver_min = MBEDTLS_SSL_MINOR_VERSION_3; /* TLS 1.2 */
+#else
+ ver_min = MBEDTLS_SSL_VERSION_TLS1_2;
+#endif
break;
case CURL_SSLVERSION_TLSv1_3:
#ifdef HAS_TLS13_SUPPORT
@@ -314,7 +324,11 @@ mbed_set_ssl_version_min_max(struct Curl_easy *data,
break;
#endif
case CURL_SSLVERSION_MAX_TLSv1_2:
- /* ver_max = MBEDTLS_SSL_VERSION_TLS1_2; */
+#if MBEDTLS_VERSION_NUMBER < 0x03020000
+ ver_max = MBEDTLS_SSL_MINOR_VERSION_3; /* TLS 1.2 */
+#else
+ ver_max = MBEDTLS_SSL_VERSION_TLS1_2;
+#endif
break;
#if MBEDTLS_VERSION_NUMBER < 0x03000000
case CURL_SSLVERSION_MAX_TLSv1_1:
diff --git a/libs/libcurl/src/vtls/mbedtls.h b/libs/libcurl/src/vtls/mbedtls.h
index 91ede31e02..33ba492336 100644
--- a/libs/libcurl/src/vtls/mbedtls.h
+++ b/libs/libcurl/src/vtls/mbedtls.h
@@ -24,7 +24,7 @@
* SPDX-License-Identifier: curl
*
***************************************************************************/
-#include "curl_setup.h"
+#include "../curl_setup.h"
#ifdef USE_MBEDTLS
diff --git a/libs/libcurl/src/vtls/mbedtls_threadlock.c b/libs/libcurl/src/vtls/mbedtls_threadlock.c
index d6d20328a7..ed8531f9f1 100644
--- a/libs/libcurl/src/vtls/mbedtls_threadlock.c
+++ b/libs/libcurl/src/vtls/mbedtls_threadlock.c
@@ -22,7 +22,7 @@
* SPDX-License-Identifier: curl
*
***************************************************************************/
-#include "curl_setup.h"
+#include "../curl_setup.h"
#if defined(USE_MBEDTLS) && \
((defined(USE_THREADS_POSIX) && defined(HAVE_PTHREAD_H)) || \
@@ -36,10 +36,10 @@
#endif
#include "mbedtls_threadlock.h"
-#include "curl_printf.h"
-#include "curl_memory.h"
+#include "../curl_printf.h"
+#include "../curl_memory.h"
/* The last #include file should be: */
-#include "memdebug.h"
+#include "../memdebug.h"
/* number of thread locks */
#define NUMT 2
diff --git a/libs/libcurl/src/vtls/mbedtls_threadlock.h b/libs/libcurl/src/vtls/mbedtls_threadlock.h
index ae651c3866..e99b051cc0 100644
--- a/libs/libcurl/src/vtls/mbedtls_threadlock.h
+++ b/libs/libcurl/src/vtls/mbedtls_threadlock.h
@@ -24,7 +24,7 @@
* SPDX-License-Identifier: curl
*
***************************************************************************/
-#include "curl_setup.h"
+#include "../curl_setup.h"
#ifdef USE_MBEDTLS
diff --git a/libs/libcurl/src/vtls/openssl.c b/libs/libcurl/src/vtls/openssl.c
index 6044d4d073..b5ae754a96 100644
--- a/libs/libcurl/src/vtls/openssl.c
+++ b/libs/libcurl/src/vtls/openssl.c
@@ -27,7 +27,7 @@
* but vtls.c should ever call or use these functions.
*/
-#include "curl_setup.h"
+#include "../curl_setup.h"
#if defined(USE_QUICHE) || defined(USE_OPENSSL)
@@ -45,26 +45,27 @@
#undef OCSP_RESPONSE
#endif
-#include "urldata.h"
-#include "sendf.h"
-#include "formdata.h" /* for the boundary function */
-#include "url.h" /* for the ssl config check function */
-#include "inet_pton.h"
+#include "../urldata.h"
+#include "../sendf.h"
+#include "../formdata.h" /* for the boundary function */
+#include "../url.h" /* for the ssl config check function */
+#include "../curlx/inet_pton.h"
#include "openssl.h"
-#include "connect.h"
-#include "slist.h"
-#include "select.h"
+#include "../connect.h"
+#include "../slist.h"
+#include "../select.h"
#include "vtls.h"
#include "vtls_int.h"
#include "vtls_scache.h"
-#include "vauth/vauth.h"
+#include "../vauth/vauth.h"
#include "keylog.h"
-#include "strcase.h"
+#include "../strcase.h"
#include "hostcheck.h"
-#include "multiif.h"
-#include "strdup.h"
-#include "strerror.h"
-#include "curl_printf.h"
+#include "../multiif.h"
+#include "../curlx/strparse.h"
+#include "../strdup.h"
+#include "../strerror.h"
+#include "../curl_printf.h"
#include <openssl/ssl.h>
#include <openssl/rand.h>
@@ -117,13 +118,15 @@
#include <openssl/store.h>
/* this is used in the following conditions to make them easier to read */
#define OPENSSL_HAS_PROVIDERS
+
+static void ossl_provider_cleanup(struct Curl_easy *data);
#endif
-#include "warnless.h"
+#include "../curlx/warnless.h"
/* The last #include files should be: */
-#include "curl_memory.h"
-#include "memdebug.h"
+#include "../curl_memory.h"
+#include "../memdebug.h"
/* Uncomment the ALLOW_RENEG line to a real #define if you want to allow TLS
renegotiations when built with BoringSSL. Renegotiating is non-compliant
@@ -194,13 +197,24 @@
#endif
#endif
+/* Whether SSL_CTX_set1_sigalgs_list is available
+ * OpenSSL: supported since 1.0.2 (commit 0b362de5f575)
+ * BoringSSL: supported since 0.20240913.0 (commit 826ce15)
+ * LibreSSL: no
+ */
+#if (OPENSSL_VERSION_NUMBER >= 0x10002000L && \
+ !defined(LIBRESSL_VERSION_NUMBER))
+ #define HAVE_SSL_CTX_SET1_SIGALGS
+#endif
+
#ifdef LIBRESSL_VERSION_NUMBER
#define OSSL_PACKAGE "LibreSSL"
#elif defined(OPENSSL_IS_BORINGSSL)
#define OSSL_PACKAGE "BoringSSL"
#elif defined(OPENSSL_IS_AWSLC)
#define OSSL_PACKAGE "AWS-LC"
-#elif (defined(USE_NGTCP2) && defined(USE_NGHTTP3)) || defined(USE_MSH3)
+#elif (defined(USE_NGTCP2) && defined(USE_NGHTTP3) && \
+ !defined(OPENSSL_QUIC_API2)) || defined(USE_MSH3)
#define OSSL_PACKAGE "quictls"
#else
#define OSSL_PACKAGE "OpenSSL"
@@ -978,13 +992,13 @@ static CURLcode ossl_seed(struct Curl_easy *data)
size_t len = sizeof(randb);
size_t i, i_max;
for(i = 0, i_max = len / sizeof(struct curltime); i < i_max; ++i) {
- struct curltime tv = Curl_now();
+ struct curltime tv = curlx_now();
Curl_wait_ms(1);
tv.tv_sec *= (time_t)i + 1;
tv.tv_usec *= (int)i + 2;
- tv.tv_sec ^= ((Curl_now().tv_sec + (time_t)Curl_now().tv_usec) *
+ tv.tv_sec ^= ((curlx_now().tv_sec + (time_t)curlx_now().tv_usec) *
(time_t)(i + 3)) << 8;
- tv.tv_usec ^= (int) ((Curl_now().tv_sec + (time_t)Curl_now().tv_usec) *
+ tv.tv_usec ^= (int) ((curlx_now().tv_sec + (time_t)curlx_now().tv_usec) *
(time_t)(i + 4)) << 16;
memcpy(&randb[i * sizeof(struct curltime)], &tv,
sizeof(struct curltime));
@@ -1099,7 +1113,7 @@ static bool is_pkcs11_uri(const char *string)
#endif
static CURLcode ossl_set_engine(struct Curl_easy *data, const char *engine);
-#if !defined(USE_OPENSSL_ENGINE) && defined(OPENSSL_HAS_PROVIDERS)
+#if defined(OPENSSL_HAS_PROVIDERS)
static CURLcode ossl_set_provider(struct Curl_easy *data,
const char *provider);
#endif
@@ -1352,7 +1366,8 @@ int cert_stuff(struct Curl_easy *data,
}
}
break;
-#elif defined(OPENSSL_HAS_PROVIDERS)
+#endif
+#if defined(OPENSSL_HAS_PROVIDERS)
/* fall through to compatible provider */
case SSL_FILETYPE_PROVIDER:
{
@@ -1368,10 +1383,11 @@ int cert_stuff(struct Curl_easy *data,
if(data->state.provider) {
/* Load the certificate from the provider */
- OSSL_STORE_CTX *store = NULL;
OSSL_STORE_INFO *info = NULL;
X509 *cert = NULL;
- store = OSSL_STORE_open(cert_file, NULL, NULL, NULL, NULL);
+ OSSL_STORE_CTX *store =
+ OSSL_STORE_open_ex(cert_file, data->state.libctx,
+ NULL, NULL, NULL, NULL, NULL, NULL);
if(!store) {
failf(data, "Failed to open OpenSSL store: %s",
ossl_strerror(ERR_get_error(), error_buffer,
@@ -1384,22 +1400,13 @@ int cert_stuff(struct Curl_easy *data,
sizeof(error_buffer)));
}
- for(info = OSSL_STORE_load(store);
- info != NULL;
- info = OSSL_STORE_load(store)) {
+ info = OSSL_STORE_load(store);
+ if(info) {
int ossl_type = OSSL_STORE_INFO_get_type(info);
- if(ossl_type == OSSL_STORE_INFO_CERT) {
+ if(ossl_type == OSSL_STORE_INFO_CERT)
cert = OSSL_STORE_INFO_get1_CERT(info);
- }
- else {
- failf(data, "Ignoring object not matching our type: %d",
- ossl_type);
- OSSL_STORE_INFO_free(info);
- continue;
- }
OSSL_STORE_INFO_free(info);
- break;
}
OSSL_STORE_close(store);
if(!cert) {
@@ -1423,9 +1430,6 @@ int cert_stuff(struct Curl_easy *data,
}
}
break;
-#else
- failf(data, "file type ENG nor PROV for certificate not implemented");
- return 0;
#endif
case SSL_FILETYPE_PKCS12:
@@ -1615,7 +1619,8 @@ fail:
}
}
break;
-#elif defined(OPENSSL_HAS_PROVIDERS)
+#endif
+#if defined(OPENSSL_HAS_PROVIDERS)
/* fall through to compatible provider */
case SSL_FILETYPE_PROVIDER:
{
@@ -1646,7 +1651,9 @@ fail:
UI_method_set_reader(ui_method, ssl_ui_reader);
UI_method_set_writer(ui_method, ssl_ui_writer);
- store = OSSL_STORE_open(key_file, ui_method, NULL, NULL, NULL);
+ store = OSSL_STORE_open_ex(key_file, data->state.libctx,
+ data->state.propq, ui_method, NULL, NULL,
+ NULL, NULL);
if(!store) {
failf(data, "Failed to open OpenSSL store: %s",
ossl_strerror(ERR_get_error(), error_buffer,
@@ -1659,22 +1666,13 @@ fail:
sizeof(error_buffer)));
}
- for(info = OSSL_STORE_load(store);
- info != NULL;
- info = OSSL_STORE_load(store)) {
+ info = OSSL_STORE_load(store);
+ if(info) {
int ossl_type = OSSL_STORE_INFO_get_type(info);
- if(ossl_type == OSSL_STORE_INFO_PKEY) {
+ if(ossl_type == OSSL_STORE_INFO_PKEY)
priv_key = OSSL_STORE_INFO_get1_PKEY(info);
- }
- else {
- failf(data, "Ignoring object not matching our type: %d",
- ossl_type);
- OSSL_STORE_INFO_free(info);
- continue;
- }
OSSL_STORE_INFO_free(info);
- break;
}
OSSL_STORE_close(store);
UI_destroy_method(ui_method);
@@ -1700,9 +1698,6 @@ fail:
}
}
break;
-#else
- failf(data, "file type ENG nor PROV for private key not implemented");
- return 0;
#endif
case SSL_FILETYPE_PKCS12:
@@ -1779,11 +1774,11 @@ static CURLcode x509_name_oneline(X509_NAME *a, struct dynbuf *d)
CURLcode result = CURLE_OUT_OF_MEMORY;
if(bio_out) {
- Curl_dyn_reset(d);
+ curlx_dyn_reset(d);
rc = X509_NAME_print_ex(bio_out, a, 0, XN_FLAG_SEP_SPLUS_SPC);
if(rc != -1) {
BIO_get_mem_ptr(bio_out, &biomem);
- result = Curl_dyn_addn(d, biomem->data, biomem->length);
+ result = curlx_dyn_addn(d, biomem->data, biomem->length);
BIO_free(bio_out);
}
}
@@ -1877,36 +1872,39 @@ static void ossl_cleanup(void)
Curl_tls_keylog_close();
}
-/* Selects an OpenSSL crypto engine
+/* Selects an OpenSSL crypto engine or provider.
*/
-static CURLcode ossl_set_engine(struct Curl_easy *data, const char *engine)
+static CURLcode ossl_set_engine(struct Curl_easy *data, const char *name)
{
#ifdef USE_OPENSSL_ENGINE
- ENGINE *e = ENGINE_by_id(engine);
+ CURLcode result = CURLE_SSL_ENGINE_NOTFOUND;
+ ENGINE *e = ENGINE_by_id(name);
- if(!e) {
- failf(data, "SSL Engine '%s' not found", engine);
- return CURLE_SSL_ENGINE_NOTFOUND;
- }
+ if(e) {
- if(data->state.engine) {
- ENGINE_finish(data->state.engine);
- ENGINE_free(data->state.engine);
- data->state.engine = NULL;
- }
- if(!ENGINE_init(e)) {
- char buf[256];
-
- ENGINE_free(e);
- failf(data, "Failed to initialise SSL Engine '%s': %s",
- engine, ossl_strerror(ERR_get_error(), buf, sizeof(buf)));
- return CURLE_SSL_ENGINE_INITFAILED;
+ if(data->state.engine) {
+ ENGINE_finish(data->state.engine);
+ ENGINE_free(data->state.engine);
+ data->state.engine = NULL;
+ }
+ if(!ENGINE_init(e)) {
+ char buf[256];
+
+ ENGINE_free(e);
+ failf(data, "Failed to initialise SSL Engine '%s': %s",
+ name, ossl_strerror(ERR_get_error(), buf, sizeof(buf)));
+ result = CURLE_SSL_ENGINE_INITFAILED;
+ e = NULL;
+ }
+ data->state.engine = e;
+ return result;
}
- data->state.engine = e;
- return CURLE_OK;
+#endif
+#ifdef OPENSSL_HAS_PROVIDERS
+ return ossl_set_provider(data, name);
#else
- (void)engine;
- failf(data, "SSL Engine not supported");
+ (void)name;
+ failf(data, "OpenSSL engine not found");
return CURLE_SSL_ENGINE_NOTFOUND;
#endif
}
@@ -1955,33 +1953,97 @@ static struct curl_slist *ossl_engines_list(struct Curl_easy *data)
return list;
}
-#if !defined(USE_OPENSSL_ENGINE) && defined(OPENSSL_HAS_PROVIDERS)
-/* Selects an OpenSSL crypto provider
+#if defined(OPENSSL_HAS_PROVIDERS)
+
+static void ossl_provider_cleanup(struct Curl_easy *data)
+{
+ if(data->state.baseprov) {
+ OSSL_PROVIDER_unload(data->state.baseprov);
+ data->state.baseprov = NULL;
+ }
+ if(data->state.provider) {
+ OSSL_PROVIDER_unload(data->state.provider);
+ data->state.provider = NULL;
+ }
+ OSSL_LIB_CTX_free(data->state.libctx);
+ data->state.libctx = NULL;
+ Curl_safefree(data->state.propq);
+ data->state.provider_loaded = FALSE;
+}
+
+#define MAX_PROVIDER_LEN 128 /* reasonable */
+
+/* Selects an OpenSSL crypto provider.
+ *
+ * A provider might need an associated property, a string passed on to
+ * OpenSSL. Specify this as [PROVIDER][:PROPERTY]: separate the name and the
+ * property with a colon. No colon means no property is set.
+ *
+ * An example provider + property looks like "tpm2:?provider=tpm2".
*/
-static CURLcode ossl_set_provider(struct Curl_easy *data, const char *provider)
+static CURLcode ossl_set_provider(struct Curl_easy *data, const char *iname)
{
- OSSL_PROVIDER *pkcs11_provider = NULL;
- char error_buffer[256];
+ char name[MAX_PROVIDER_LEN + 1];
+ struct Curl_str prov;
+ const char *propq = NULL;
- if(OSSL_PROVIDER_available(NULL, provider)) {
- /* already loaded through the configuration - no action needed */
- data->state.provider = TRUE;
+ if(!iname) {
+ /* clear and cleanup provider use */
+ ossl_provider_cleanup(data);
return CURLE_OK;
}
- if(data->state.provider_failed) {
- return CURLE_SSL_ENGINE_NOTFOUND;
+ if(curlx_str_until(&iname, &prov, MAX_PROVIDER_LEN, ':'))
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+
+ if(!curlx_str_single(&iname, ':'))
+ /* there was a colon, get the propq until the end of string */
+ propq = iname;
+
+ /* we need the name in a buffer, null-terminated */
+ memcpy(name, curlx_str(&prov), curlx_strlen(&prov));
+ name[curlx_strlen(&prov)] = 0;
+
+ if(!data->state.libctx) {
+ OSSL_LIB_CTX *libctx = OSSL_LIB_CTX_new();
+ if(!libctx)
+ return CURLE_OUT_OF_MEMORY;
+ if(propq) {
+ data->state.propq = strdup(propq);
+ if(!data->state.propq) {
+ OSSL_LIB_CTX_free(libctx);
+ return CURLE_OUT_OF_MEMORY;
+ }
+ }
+ data->state.libctx = libctx;
}
- pkcs11_provider = OSSL_PROVIDER_try_load(NULL, provider, 1);
- if(!pkcs11_provider) {
+ if(OSSL_PROVIDER_available(data->state.libctx, name)) {
+ /* already loaded through the configuration - no action needed */
+ data->state.provider_loaded = TRUE;
+ return CURLE_OK;
+ }
+
+ data->state.provider =
+ OSSL_PROVIDER_try_load(data->state.libctx, name, 1);
+ if(!data->state.provider) {
+ char error_buffer[256];
failf(data, "Failed to initialize provider: %s",
ossl_strerror(ERR_get_error(), error_buffer,
sizeof(error_buffer)));
- /* Do not attempt to load it again */
- data->state.provider_failed = TRUE;
+ ossl_provider_cleanup(data);
+ return CURLE_SSL_ENGINE_NOTFOUND;
+ }
+
+ /* load the base provider as well */
+ data->state.baseprov =
+ OSSL_PROVIDER_try_load(data->state.libctx, "base", 1);
+ if(!data->state.baseprov) {
+ ossl_provider_cleanup(data);
+ failf(data, "Failed to load base");
return CURLE_SSL_ENGINE_NOTFOUND;
}
- data->state.provider = TRUE;
+ else
+ data->state.provider_loaded = TRUE;
return CURLE_OK;
}
#endif
@@ -2141,6 +2203,9 @@ static void ossl_close_all(struct Curl_easy *data)
#else
(void)data;
#endif
+#ifdef OPENSSL_HAS_PROVIDERS
+ ossl_provider_cleanup(data);
+#endif
#ifndef HAVE_ERR_REMOVE_THREAD_STATE_DEPRECATED
/* OpenSSL 1.0.1 and 1.0.2 build an error queue that is stored per-thread
so we need to clean it here in case the thread will be killed. All OpenSSL
@@ -3414,8 +3479,8 @@ ossl_cached_x509_store_expired(const struct Curl_easy *data,
if(cfg->ca_cache_timeout < 0)
return FALSE;
else {
- struct curltime now = Curl_now();
- timediff_t elapsed_ms = Curl_timediff(now, mb->time);
+ struct curltime now = curlx_now();
+ timediff_t elapsed_ms = curlx_timediff(now, mb->time);
timediff_t timeout_ms = cfg->ca_cache_timeout * (timediff_t)1000;
return elapsed_ms >= timeout_ms;
@@ -3497,7 +3562,7 @@ static void ossl_set_cached_x509_store(struct Curl_cfilter *cf,
free(share->CAfile);
}
- share->time = Curl_now();
+ share->time = curlx_now();
share->store = store;
share->CAfile = CAfile;
}
@@ -3549,43 +3614,299 @@ CURLcode Curl_ssl_setup_x509_store(struct Curl_cfilter *cf,
}
#endif /* HAVE_SSL_X509_STORE_SHARE */
-CURLcode Curl_ossl_ctx_init(struct ossl_ctx *octx,
+
+static CURLcode
+ossl_init_session_and_alpns(struct ossl_ctx *octx,
struct Curl_cfilter *cf,
struct Curl_easy *data,
struct ssl_peer *peer,
const struct alpn_spec *alpns_requested,
- Curl_ossl_ctx_setup_cb *cb_setup,
- void *cb_user_data,
- Curl_ossl_new_session_cb *cb_new_session,
- void *ssl_user_data,
Curl_ossl_init_session_reuse_cb *sess_reuse_cb)
{
- CURLcode result = CURLE_OK;
- const char *ciphers;
- const SSL_METHOD *req_method = NULL;
- ctx_option_t ctx_options = 0;
- 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);
- unsigned int ssl_version_min = conn_config->version;
- char * const ssl_cert = ssl_config->primary.clientcert;
- const struct curl_blob *ssl_cert_blob = ssl_config->primary.cert_blob;
- const char * const ssl_cert_type = ssl_config->cert_type;
- const bool verifypeer = conn_config->verifypeer;
- char error_buffer[256];
struct alpn_spec alpns;
-
- /* Make funny stuff to get random input */
- result = ossl_seed(data);
- if(result)
- return result;
+ char error_buffer[256];
+ CURLcode result;
Curl_alpn_copy(&alpns, alpns_requested);
- ssl_config->certverifyresult = !X509_V_OK;
+ octx->reused_session = FALSE;
+ if(ssl_config->primary.cache_session) {
+ struct Curl_ssl_session *scs = NULL;
+
+ result = Curl_ssl_scache_take(cf, data, peer->scache_key, &scs);
+ if(!result && scs && scs->sdata && scs->sdata_len) {
+ const unsigned char *der_sessionid = scs->sdata;
+ size_t der_sessionid_size = scs->sdata_len;
+ SSL_SESSION *ssl_session = NULL;
+
+ /* If OpenSSL does not accept the session from the cache, this
+ * is not an error. We just continue without it. */
+ ssl_session = d2i_SSL_SESSION(NULL, &der_sessionid,
+ (long)der_sessionid_size);
+ if(ssl_session) {
+ if(!SSL_set_session(octx->ssl, ssl_session)) {
+ infof(data, "SSL: SSL_set_session not accepted, "
+ "continuing without: %s",
+ ossl_strerror(ERR_get_error(), error_buffer,
+ sizeof(error_buffer)));
+ }
+ else {
+ infof(data, "SSL reusing session with ALPN '%s'",
+ scs->alpn ? scs->alpn : "-");
+ octx->reused_session = TRUE;
+#ifdef HAVE_OPENSSL_EARLYDATA
+ if(ssl_config->earlydata && scs->alpn &&
+ SSL_SESSION_get_max_early_data(ssl_session) &&
+ !cf->conn->connect_only &&
+ (SSL_version(octx->ssl) == TLS1_3_VERSION)) {
+ bool do_early_data = FALSE;
+ if(sess_reuse_cb) {
+ result = sess_reuse_cb(cf, data, &alpns, scs, &do_early_data);
+ if(result)
+ return result;
+ }
+ if(do_early_data) {
+ /* We only try the ALPN protocol the session used before,
+ * otherwise we might send early data for the wrong protocol */
+ Curl_alpn_restrict_to(&alpns, scs->alpn);
+ }
+ }
+#else
+ (void)sess_reuse_cb;
+#endif
+ }
+ SSL_SESSION_free(ssl_session);
+ }
+ else {
+ infof(data, "SSL session not accepted by OpenSSL, continuing without");
+ }
+ }
+ Curl_ssl_scache_return(cf, data, peer->scache_key, scs);
+ }
+
+#ifdef HAS_ALPN_OPENSSL
+ if(alpns.count) {
+ struct alpn_proto_buf proto;
+ memset(&proto, 0, sizeof(proto));
+ result = Curl_alpn_to_proto_buf(&proto, &alpns);
+ if(result) {
+ failf(data, "Error determining ALPN");
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ if(SSL_set_alpn_protos(octx->ssl, proto.data, (int)proto.len)) {
+ failf(data, "Error setting ALPN");
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ }
+#endif
+
+ return CURLE_OK;
+}
+
+#ifdef USE_ECH_OPENSSL
+static CURLcode ossl_init_ech(struct ossl_ctx *octx,
+ struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ struct ssl_peer *peer)
+{
+ unsigned char *ech_config = NULL;
+ size_t ech_config_len = 0;
+ char *outername = data->set.str[STRING_ECH_PUBLIC];
+ int trying_ech_now = 0;
+ CURLcode result;
+
+ if(!ECH_ENABLED(data))
+ return CURLE_OK;
+
+ if(data->set.tls_ech & CURLECH_GREASE) {
+ infof(data, "ECH: will GREASE ClientHello");
+# if defined(OPENSSL_IS_BORINGSSL) || defined(OPENSSL_IS_AWSLC)
+ SSL_set_enable_ech_grease(octx->ssl, 1);
+# else
+ SSL_set_options(octx->ssl, SSL_OP_ECH_GREASE);
+# endif
+ }
+ else if(data->set.tls_ech & CURLECH_CLA_CFG) {
+# if defined(OPENSSL_IS_BORINGSSL) || defined(OPENSSL_IS_AWSLC)
+ /* have to do base64 decode here for BoringSSL */
+ const char *b64 = data->set.str[STRING_ECH_CONFIG];
+
+ if(!b64) {
+ infof(data, "ECH: ECHConfig from command line empty");
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ ech_config_len = 2 * strlen(b64);
+ result = curlx_base64_decode(b64, &ech_config, &ech_config_len);
+ if(result || !ech_config) {
+ infof(data, "ECH: cannot base64 decode ECHConfig from command line");
+ if(data->set.tls_ech & CURLECH_HARD)
+ return result;
+ }
+ if(SSL_set1_ech_config_list(octx->ssl, ech_config,
+ ech_config_len) != 1) {
+ infof(data, "ECH: SSL_ECH_set1_ech_config_list failed");
+ if(data->set.tls_ech & CURLECH_HARD) {
+ free(ech_config);
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ }
+ free(ech_config);
+ trying_ech_now = 1;
+# else
+ ech_config = (unsigned char *) data->set.str[STRING_ECH_CONFIG];
+ if(!ech_config) {
+ infof(data, "ECH: ECHConfig from command line empty");
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ ech_config_len = strlen(data->set.str[STRING_ECH_CONFIG]);
+ if(SSL_set1_ech_config_list(octx->ssl, ech_config,
+ ech_config_len) != 1) {
+ infof(data, "ECH: SSL_ECH_set1_ech_config_list failed");
+ if(data->set.tls_ech & CURLECH_HARD)
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ else
+ trying_ech_now = 1;
+# endif
+ infof(data, "ECH: ECHConfig from command line");
+ }
+ else {
+ struct Curl_dns_entry *dns = NULL;
+
+ if(peer->hostname)
+ dns = Curl_dnscache_get(data, peer->hostname, peer->port,
+ cf->conn->ip_version);
+ if(!dns) {
+ infof(data, "ECH: requested but no DNS info available");
+ if(data->set.tls_ech & CURLECH_HARD)
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ else {
+ struct Curl_https_rrinfo *rinfo = NULL;
+
+ rinfo = dns->hinfo;
+ if(rinfo && rinfo->echconfiglist) {
+ unsigned char *ecl = rinfo->echconfiglist;
+ size_t elen = rinfo->echconfiglist_len;
+
+ infof(data, "ECH: ECHConfig from DoH HTTPS RR");
+ if(SSL_set1_ech_config_list(octx->ssl, ecl, elen) != 1) {
+ infof(data, "ECH: SSL_set1_ech_config_list failed");
+ if(data->set.tls_ech & CURLECH_HARD)
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ else {
+ trying_ech_now = 1;
+ infof(data, "ECH: imported ECHConfigList of length %zu", elen);
+ }
+ }
+ else {
+ infof(data, "ECH: requested but no ECHConfig available");
+ if(data->set.tls_ech & CURLECH_HARD)
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ Curl_resolv_unlink(data, &dns);
+ }
+ }
+# if defined(OPENSSL_IS_BORINGSSL) || defined(OPENSSL_IS_AWSLC)
+ if(trying_ech_now && outername) {
+ infof(data, "ECH: setting public_name not supported with BoringSSL");
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+# else
+ if(trying_ech_now && outername) {
+ infof(data, "ECH: inner: '%s', outer: '%s'",
+ peer->hostname ? peer->hostname : "NULL", outername);
+ result = SSL_ech_set1_server_names(octx->ssl,
+ peer->hostname, outername,
+ 0 /* do send outer */);
+ if(result != 1) {
+ infof(data, "ECH: rv failed to set server name(s) %d [ERROR]", result);
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ }
+# endif /* OPENSSL_IS_BORINGSSL || OPENSSL_IS_AWSLC */
+ if(trying_ech_now
+ && SSL_set_min_proto_version(octx->ssl, TLS1_3_VERSION) != 1) {
+ infof(data, "ECH: cannot force TLSv1.3 [ERROR]");
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+
+ return CURLE_OK;
+}
+#endif /* USE_ECH_OPENSSL */
+
+
+static CURLcode ossl_init_ssl(struct ossl_ctx *octx,
+ struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ struct ssl_peer *peer,
+ const struct alpn_spec *alpns_requested,
+ void *ssl_user_data,
+ Curl_ossl_init_session_reuse_cb *sess_reuse_cb)
+{
+ /* Let's make an SSL structure */
+ if(octx->ssl)
+ SSL_free(octx->ssl);
+ octx->ssl = SSL_new(octx->ssl_ctx);
+ if(!octx->ssl) {
+ failf(data, "SSL: could not create a context (handle)");
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ SSL_set_app_data(octx->ssl, ssl_user_data);
+
+#if !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_OCSP)
+ if(Curl_ssl_cf_get_primary_config(cf)->verifystatus)
+ SSL_set_tlsext_status_type(octx->ssl, TLSEXT_STATUSTYPE_ocsp);
+#endif
+
+#if (defined(OPENSSL_IS_BORINGSSL) || defined(OPENSSL_IS_AWSLC)) && \
+ defined(ALLOW_RENEG)
+ SSL_set_renegotiate_mode(octx->ssl, ssl_renegotiate_freely);
+#endif
+
+ SSL_set_connect_state(octx->ssl);
+
+ octx->server_cert = NULL;
+#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
+ if(peer->sni) {
+ if(!SSL_set_tlsext_host_name(octx->ssl, peer->sni)) {
+ failf(data, "Failed set SNI");
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ }
+
+#ifdef USE_ECH_OPENSSL
+ {
+ CURLcode result = ossl_init_ech(octx, cf, data, peer);
+ if(result)
+ return result;
+ }
+#endif /* USE_ECH_OPENSSL */
+
+#endif
+
+ return ossl_init_session_and_alpns(octx, cf, data, peer,
+ alpns_requested, sess_reuse_cb);
+}
+
+
+static CURLcode ossl_init_method(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ struct ssl_peer *peer,
+ const SSL_METHOD **pmethod,
+ unsigned int *pssl_version_min)
+{
+ struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
+
+ *pmethod = NULL;
+ *pssl_version_min = conn_config->version;
switch(peer->transport) {
case TRNSPRT_TCP:
/* check to see if we have been told to use an explicit SSL/TLS version */
- switch(ssl_version_min) {
+ switch(*pssl_version_min) {
case CURL_SSLVERSION_DEFAULT:
case CURL_SSLVERSION_TLSv1:
case CURL_SSLVERSION_TLSv1_0:
@@ -3594,9 +3915,9 @@ CURLcode Curl_ossl_ctx_init(struct ossl_ctx *octx,
case CURL_SSLVERSION_TLSv1_3:
/* it will be handled later with the context options */
#if (OPENSSL_VERSION_NUMBER >= 0x10100000L)
- req_method = TLS_client_method();
+ *pmethod = TLS_client_method();
#else
- req_method = SSLv23_client_method();
+ *pmethod = SSLv23_client_method();
#endif
break;
case CURL_SSLVERSION_SSLv2:
@@ -3611,7 +3932,7 @@ CURLcode Curl_ossl_ctx_init(struct ossl_ctx *octx,
}
break;
case TRNSPRT_QUIC:
- ssl_version_min = CURL_SSLVERSION_TLSv1_3;
+ *pssl_version_min = CURL_SSLVERSION_TLSv1_3;
if(conn_config->version_max &&
(conn_config->version_max != CURL_SSLVERSION_MAX_TLSv1_3)) {
failf(data, "QUIC needs at least TLS version 1.3");
@@ -3619,11 +3940,11 @@ CURLcode Curl_ossl_ctx_init(struct ossl_ctx *octx,
}
#ifdef USE_OPENSSL_QUIC
- req_method = OSSL_QUIC_client_method();
+ *pmethod = OSSL_QUIC_client_method();
#elif (OPENSSL_VERSION_NUMBER >= 0x10100000L)
- req_method = TLS_method();
+ *pmethod = TLS_method();
#else
- req_method = SSLv23_client_method();
+ *pmethod = SSLv23_client_method();
#endif
break;
default:
@@ -3631,9 +3952,53 @@ CURLcode Curl_ossl_ctx_init(struct ossl_ctx *octx,
return CURLE_SSL_CONNECT_ERROR;
}
+ return *pmethod ? CURLE_OK : CURLE_SSL_CONNECT_ERROR;
+}
+
+
+CURLcode Curl_ossl_ctx_init(struct ossl_ctx *octx,
+ struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ struct ssl_peer *peer,
+ const struct alpn_spec *alpns_requested,
+ Curl_ossl_ctx_setup_cb *cb_setup,
+ void *cb_user_data,
+ Curl_ossl_new_session_cb *cb_new_session,
+ void *ssl_user_data,
+ Curl_ossl_init_session_reuse_cb *sess_reuse_cb)
+{
+ CURLcode result = CURLE_OK;
+ const char *ciphers;
+ const SSL_METHOD *req_method = NULL;
+ ctx_option_t ctx_options = 0;
+ 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);
+ char * const ssl_cert = ssl_config->primary.clientcert;
+ const struct curl_blob *ssl_cert_blob = ssl_config->primary.cert_blob;
+ const char * const ssl_cert_type = ssl_config->cert_type;
+ const bool verifypeer = conn_config->verifypeer;
+ unsigned int ssl_version_min;
+ char error_buffer[256];
+
+ /* Make funny stuff to get random input */
+ result = ossl_seed(data);
+ if(result)
+ return result;
+
+ ssl_config->certverifyresult = !X509_V_OK;
+
+ result = ossl_init_method(cf, data, peer, &req_method, &ssl_version_min);
+ if(result)
+ return result;
+ DEBUGASSERT(req_method);
DEBUGASSERT(!octx->ssl_ctx);
- octx->ssl_ctx = SSL_CTX_new(req_method);
+ octx->ssl_ctx =
+#ifdef OPENSSL_HAS_PROVIDERS
+ data->state.libctx ?
+ SSL_CTX_new_ex(data->state.libctx, data->state.propq, req_method):
+#endif
+ SSL_CTX_new(req_method);
if(!octx->ssl_ctx) {
failf(data, "SSL: could not create a context: %s",
@@ -3751,18 +4116,6 @@ CURLcode Curl_ossl_ctx_init(struct ossl_ctx *octx,
SSL_CTX_set_mode(octx->ssl_ctx, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
#endif
- if(ssl_cert || ssl_cert_blob || ssl_cert_type) {
- if(!result &&
- !cert_stuff(data, octx->ssl_ctx,
- ssl_cert, ssl_cert_blob, ssl_cert_type,
- ssl_config->key, ssl_config->key_blob,
- ssl_config->key_type, ssl_config->key_passwd))
- result = CURLE_SSL_CERTPROBLEM;
- if(result)
- /* failf() is already done in cert_stuff() */
- return result;
- }
-
ciphers = conn_config->cipher_list;
if(!ciphers && (peer->transport != TRNSPRT_QUIC))
ciphers = DEFAULT_CIPHER_SELECTION;
@@ -3789,6 +4142,18 @@ CURLcode Curl_ossl_ctx_init(struct ossl_ctx *octx,
}
#endif
+ if(ssl_cert || ssl_cert_blob || ssl_cert_type) {
+ if(!result &&
+ !cert_stuff(data, octx->ssl_ctx,
+ ssl_cert, ssl_cert_blob, ssl_cert_type,
+ ssl_config->key, ssl_config->key_blob,
+ ssl_config->key_type, ssl_config->key_passwd))
+ result = CURLE_SSL_CERTPROBLEM;
+ if(result)
+ /* failf() is already done in cert_stuff() */
+ return result;
+ }
+
#ifdef HAVE_SSL_CTX_SET_POST_HANDSHAKE_AUTH
/* OpenSSL 1.1.1 requires clients to opt-in for PHA */
SSL_CTX_set_post_handshake_auth(octx->ssl_ctx, 1);
@@ -3809,6 +4174,21 @@ CURLcode Curl_ossl_ctx_init(struct ossl_ctx *octx,
}
}
+#ifdef HAVE_SSL_CTX_SET1_SIGALGS
+#define OSSL_SIGALG_CAST(x) OSSL_CURVE_CAST(x)
+ {
+ const char *signature_algorithms = conn_config->signature_algorithms;
+ if(signature_algorithms) {
+ if(!SSL_CTX_set1_sigalgs_list(octx->ssl_ctx,
+ OSSL_SIGALG_CAST(signature_algorithms))) {
+ failf(data, "failed setting signature algorithms: '%s'",
+ signature_algorithms);
+ return CURLE_SSL_CIPHER;
+ }
+ }
+ }
+#endif
+
#ifdef USE_OPENSSL_SRP
if(ssl_config->primary.username && Curl_auth_allowed_to_host(data)) {
char * const ssl_username = ssl_config->primary.username;
@@ -3880,234 +4260,8 @@ CURLcode Curl_ossl_ctx_init(struct ossl_ctx *octx,
}
}
- /* Let's make an SSL structure */
- if(octx->ssl)
- SSL_free(octx->ssl);
- octx->ssl = SSL_new(octx->ssl_ctx);
- if(!octx->ssl) {
- failf(data, "SSL: could not create a context (handle)");
- return CURLE_OUT_OF_MEMORY;
- }
-
- SSL_set_app_data(octx->ssl, ssl_user_data);
-
-#if !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_OCSP)
- if(conn_config->verifystatus)
- SSL_set_tlsext_status_type(octx->ssl, TLSEXT_STATUSTYPE_ocsp);
-#endif
-
-#if (defined(OPENSSL_IS_BORINGSSL) || defined(OPENSSL_IS_AWSLC)) && \
- defined(ALLOW_RENEG)
- SSL_set_renegotiate_mode(octx->ssl, ssl_renegotiate_freely);
-#endif
-
- SSL_set_connect_state(octx->ssl);
-
- octx->server_cert = 0x0;
-#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
- if(peer->sni) {
- if(!SSL_set_tlsext_host_name(octx->ssl, peer->sni)) {
- failf(data, "Failed set SNI");
- return CURLE_SSL_CONNECT_ERROR;
- }
- }
-
-#ifdef USE_ECH_OPENSSL
- if(ECH_ENABLED(data)) {
- unsigned char *ech_config = NULL;
- size_t ech_config_len = 0;
- char *outername = data->set.str[STRING_ECH_PUBLIC];
- int trying_ech_now = 0;
-
- if(data->set.tls_ech & CURLECH_GREASE) {
- infof(data, "ECH: will GREASE ClientHello");
-# if defined(OPENSSL_IS_BORINGSSL) || defined(OPENSSL_IS_AWSLC)
- SSL_set_enable_ech_grease(octx->ssl, 1);
-# else
- SSL_set_options(octx->ssl, SSL_OP_ECH_GREASE);
-# endif
- }
- else if(data->set.tls_ech & CURLECH_CLA_CFG) {
-# if defined(OPENSSL_IS_BORINGSSL) || defined(OPENSSL_IS_AWSLC)
- /* have to do base64 decode here for BoringSSL */
- const char *b64 = data->set.str[STRING_ECH_CONFIG];
-
- if(!b64) {
- infof(data, "ECH: ECHConfig from command line empty");
- return CURLE_SSL_CONNECT_ERROR;
- }
- ech_config_len = 2 * strlen(b64);
- result = Curl_base64_decode(b64, &ech_config, &ech_config_len);
- if(result || !ech_config) {
- infof(data, "ECH: cannot base64 decode ECHConfig from command line");
- if(data->set.tls_ech & CURLECH_HARD)
- return result;
- }
- if(SSL_set1_ech_config_list(octx->ssl, ech_config,
- ech_config_len) != 1) {
- infof(data, "ECH: SSL_ECH_set1_ech_config_list failed");
- if(data->set.tls_ech & CURLECH_HARD) {
- free(ech_config);
- return CURLE_SSL_CONNECT_ERROR;
- }
- }
- free(ech_config);
- trying_ech_now = 1;
-# else
- ech_config = (unsigned char *) data->set.str[STRING_ECH_CONFIG];
- if(!ech_config) {
- infof(data, "ECH: ECHConfig from command line empty");
- return CURLE_SSL_CONNECT_ERROR;
- }
- ech_config_len = strlen(data->set.str[STRING_ECH_CONFIG]);
- if(SSL_set1_ech_config_list(octx->ssl, ech_config,
- ech_config_len) != 1) {
- infof(data, "ECH: SSL_ECH_set1_ech_config_list failed");
- if(data->set.tls_ech & CURLECH_HARD)
- return CURLE_SSL_CONNECT_ERROR;
- }
- else
- trying_ech_now = 1;
-# endif
- infof(data, "ECH: ECHConfig from command line");
- }
- else {
- struct Curl_dns_entry *dns = NULL;
-
- if(peer->hostname)
- dns = Curl_fetch_addr(data, peer->hostname, peer->port);
- if(!dns) {
- infof(data, "ECH: requested but no DNS info available");
- if(data->set.tls_ech & CURLECH_HARD)
- return CURLE_SSL_CONNECT_ERROR;
- }
- else {
- struct Curl_https_rrinfo *rinfo = NULL;
-
- rinfo = dns->hinfo;
- if(rinfo && rinfo->echconfiglist) {
- unsigned char *ecl = rinfo->echconfiglist;
- size_t elen = rinfo->echconfiglist_len;
-
- infof(data, "ECH: ECHConfig from DoH HTTPS RR");
- if(SSL_set1_ech_config_list(octx->ssl, ecl, elen) != 1) {
- infof(data, "ECH: SSL_set1_ech_config_list failed");
- if(data->set.tls_ech & CURLECH_HARD)
- return CURLE_SSL_CONNECT_ERROR;
- }
- else {
- trying_ech_now = 1;
- infof(data, "ECH: imported ECHConfigList of length %zu", elen);
- }
- }
- else {
- infof(data, "ECH: requested but no ECHConfig available");
- if(data->set.tls_ech & CURLECH_HARD)
- return CURLE_SSL_CONNECT_ERROR;
- }
- Curl_resolv_unlink(data, &dns);
- }
- }
-# if defined(OPENSSL_IS_BORINGSSL) || defined(OPENSSL_IS_AWSLC)
- if(trying_ech_now && outername) {
- infof(data, "ECH: setting public_name not supported with BoringSSL");
- return CURLE_SSL_CONNECT_ERROR;
- }
-# else
- if(trying_ech_now && outername) {
- infof(data, "ECH: inner: '%s', outer: '%s'",
- peer->hostname ? peer->hostname : "NULL", outername);
- result = SSL_ech_set1_server_names(octx->ssl,
- peer->hostname, outername,
- 0 /* do send outer */);
- if(result != 1) {
- infof(data, "ECH: rv failed to set server name(s) %d [ERROR]", result);
- return CURLE_SSL_CONNECT_ERROR;
- }
- }
-# endif /* OPENSSL_IS_BORINGSSL || OPENSSL_IS_AWSLC */
- if(trying_ech_now
- && SSL_set_min_proto_version(octx->ssl, TLS1_3_VERSION) != 1) {
- infof(data, "ECH: cannot force TLSv1.3 [ERROR]");
- return CURLE_SSL_CONNECT_ERROR;
- }
- }
-#endif /* USE_ECH_OPENSSL */
-
-#endif
-
- octx->reused_session = FALSE;
- if(ssl_config->primary.cache_session) {
- struct Curl_ssl_session *scs = NULL;
-
- result = Curl_ssl_scache_take(cf, data, peer->scache_key, &scs);
- if(!result && scs && scs->sdata && scs->sdata_len) {
- const unsigned char *der_sessionid = scs->sdata;
- size_t der_sessionid_size = scs->sdata_len;
- SSL_SESSION *ssl_session = NULL;
-
- /* If OpenSSL does not accept the session from the cache, this
- * is not an error. We just continue without it. */
- ssl_session = d2i_SSL_SESSION(NULL, &der_sessionid,
- (long)der_sessionid_size);
- if(ssl_session) {
- if(!SSL_set_session(octx->ssl, ssl_session)) {
- infof(data, "SSL: SSL_set_session not accepted, "
- "continuing without: %s",
- ossl_strerror(ERR_get_error(), error_buffer,
- sizeof(error_buffer)));
- }
- else {
- infof(data, "SSL reusing session with ALPN '%s'",
- scs->alpn ? scs->alpn : "-");
- octx->reused_session = TRUE;
-#ifdef HAVE_OPENSSL_EARLYDATA
- if(ssl_config->earlydata && scs->alpn &&
- SSL_SESSION_get_max_early_data(ssl_session) &&
- !cf->conn->connect_only &&
- (SSL_version(octx->ssl) == TLS1_3_VERSION)) {
- bool do_early_data = FALSE;
- if(sess_reuse_cb) {
- result = sess_reuse_cb(cf, data, &alpns, scs, &do_early_data);
- if(result)
- return result;
- }
- if(do_early_data) {
- /* We only try the ALPN protocol the session used before,
- * otherwise we might send early data for the wrong protocol */
- Curl_alpn_restrict_to(&alpns, scs->alpn);
- }
- }
-#else
- (void)sess_reuse_cb;
-#endif
- }
- SSL_SESSION_free(ssl_session);
- }
- else {
- infof(data, "SSL session not accepted by OpenSSL, continuing without");
- }
- }
- Curl_ssl_scache_return(cf, data, peer->scache_key, scs);
- }
-
-#ifdef HAS_ALPN_OPENSSL
- if(alpns.count) {
- struct alpn_proto_buf proto;
- memset(&proto, 0, sizeof(proto));
- result = Curl_alpn_to_proto_buf(&proto, &alpns);
- if(result) {
- failf(data, "Error determining ALPN");
- return CURLE_SSL_CONNECT_ERROR;
- }
- if(SSL_set_alpn_protos(octx->ssl, proto.data, (int)proto.len)) {
- failf(data, "Error setting ALPN");
- return CURLE_SSL_CONNECT_ERROR;
- }
- }
-#endif
-
- return CURLE_OK;
+ return ossl_init_ssl(octx, cf, data, peer, alpns_requested,
+ ssl_user_data, sess_reuse_cb);
}
static CURLcode ossl_on_session_reuse(struct Curl_cfilter *cf,
@@ -4225,7 +4379,7 @@ static void ossl_trace_ech_retry_configs(struct Curl_easy *data, SSL* ssl,
char *b64str = NULL;
size_t blen = 0;
- result = Curl_base64_encode((const char *)rcs, rcl, &b64str, &blen);
+ result = curlx_base64_encode((const char *)rcs, rcl, &b64str, &blen);
if(!result && b64str) {
infof(data, "ECH: retry_configs %s", b64str);
free(b64str);
@@ -4656,7 +4810,7 @@ CURLcode Curl_oss_check_peer_cert(struct Curl_cfilter *cf,
DEBUGASSERT(octx);
- Curl_dyn_init(&dname, MAX_CERT_NAME_LENGTH);
+ curlx_dyn_init(&dname, MAX_CERT_NAME_LENGTH);
if(!mem) {
failf(data,
@@ -4686,7 +4840,7 @@ CURLcode Curl_oss_check_peer_cert(struct Curl_cfilter *cf,
result = x509_name_oneline(X509_get_subject_name(octx->server_cert),
&dname);
- infof(data, " subject: %s", result ? "[NONE]" : Curl_dyn_ptr(&dname));
+ infof(data, " subject: %s", result ? "[NONE]" : curlx_dyn_ptr(&dname));
#ifndef CURL_DISABLE_VERBOSE_STRINGS
{
@@ -4711,7 +4865,7 @@ CURLcode Curl_oss_check_peer_cert(struct Curl_cfilter *cf,
if(result) {
X509_free(octx->server_cert);
octx->server_cert = NULL;
- Curl_dyn_free(&dname);
+ curlx_dyn_free(&dname);
return result;
}
}
@@ -4724,8 +4878,8 @@ CURLcode Curl_oss_check_peer_cert(struct Curl_cfilter *cf,
result = CURLE_PEER_FAILED_VERIFICATION;
}
else {
- infof(data, " issuer: %s", Curl_dyn_ptr(&dname));
- Curl_dyn_free(&dname);
+ infof(data, " issuer: %s", curlx_dyn_ptr(&dname));
+ curlx_dyn_free(&dname);
/* We could do all sorts of certificate verification stuff here before
deallocating the certificate. */
@@ -5308,10 +5462,10 @@ static CURLcode ossl_get_channel_binding(struct Curl_easy *data, int sockindex,
}
/* Append "tls-server-end-point:" */
- if(Curl_dyn_addn(binding, prefix, sizeof(prefix) - 1) != CURLE_OK)
+ if(curlx_dyn_addn(binding, prefix, sizeof(prefix) - 1) != CURLE_OK)
return CURLE_OUT_OF_MEMORY;
/* Append digest */
- if(Curl_dyn_addn(binding, buf, length))
+ if(curlx_dyn_addn(binding, buf, length))
return CURLE_OUT_OF_MEMORY;
return CURLE_OK;
@@ -5462,6 +5616,9 @@ const struct Curl_ssl Curl_ssl_openssl = {
#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
SSLSUPP_TLS13_CIPHERSUITES |
#endif
+#ifdef HAVE_SSL_CTX_SET1_SIGALGS
+ SSLSUPP_SIGNATURE_ALGORITHMS |
+#endif
#ifdef USE_ECH_OPENSSL
SSLSUPP_ECH |
#endif
@@ -5483,7 +5640,7 @@ const struct Curl_ssl Curl_ssl_openssl = {
ossl_get_internals, /* get_internals */
ossl_close, /* close_one */
ossl_close_all, /* close_all */
- ossl_set_engine, /* set_engine */
+ ossl_set_engine, /* set_engine or provider */
ossl_set_engine_default, /* set_engine_default */
ossl_engines_list, /* engines_list */
NULL, /* false_start */
diff --git a/libs/libcurl/src/vtls/openssl.h b/libs/libcurl/src/vtls/openssl.h
index f72f6dea35..1ca175c942 100644
--- a/libs/libcurl/src/vtls/openssl.h
+++ b/libs/libcurl/src/vtls/openssl.h
@@ -24,7 +24,7 @@
*
***************************************************************************/
-#include "curl_setup.h"
+#include "../curl_setup.h"
#ifdef USE_OPENSSL
/*
@@ -35,7 +35,7 @@
#include <openssl/ossl_typ.h>
#include <openssl/ssl.h>
-#include "urldata.h"
+#include "../urldata.h"
/*
* Whether SSL_CTX_set_keylog_callback is available.
diff --git a/libs/libcurl/src/vtls/rustls.c b/libs/libcurl/src/vtls/rustls.c
index f8e668e17a..4876175212 100644
--- a/libs/libcurl/src/vtls/rustls.c
+++ b/libs/libcurl/src/vtls/rustls.c
@@ -24,22 +24,22 @@
* SPDX-License-Identifier: curl
*
***************************************************************************/
-#include "curl_setup.h"
+#include "../curl_setup.h"
#ifdef USE_RUSTLS
-#include "curl_printf.h"
+#include "../curl_printf.h"
#include <rustls.h>
-#include "inet_pton.h"
-#include "urldata.h"
-#include "sendf.h"
+#include "../curlx/inet_pton.h"
+#include "../urldata.h"
+#include "../sendf.h"
#include "vtls.h"
#include "vtls_int.h"
#include "rustls.h"
#include "keylog.h"
-#include "strerror.h"
+#include "../strerror.h"
#include "cipher_suite.h"
#include "x509asn1.h"
@@ -417,7 +417,7 @@ read_file_into(const char *filename,
uint8_t buf[256];
const size_t rr = fread(buf, 1, sizeof(buf), f);
if(rr == 0 ||
- CURLE_OK != Curl_dyn_addn(out, buf, rr)) {
+ CURLE_OK != curlx_dyn_addn(out, buf, rr)) {
fclose(f);
return 0;
}
@@ -692,7 +692,7 @@ init_config_builder_verifier_crl(
struct dynbuf crl_contents;
rustls_result rr;
- Curl_dyn_init(&crl_contents, DYN_CRLFILE_SIZE);
+ curlx_dyn_init(&crl_contents, DYN_CRLFILE_SIZE);
if(!read_file_into(conn_config->CRLfile, &crl_contents)) {
failf(data, "rustls: failed to read revocation list file");
result = CURLE_SSL_CRL_BADFILE;
@@ -701,8 +701,8 @@ init_config_builder_verifier_crl(
rr = rustls_web_pki_server_cert_verifier_builder_add_crl(
builder,
- Curl_dyn_uptr(&crl_contents),
- Curl_dyn_len(&crl_contents));
+ curlx_dyn_uptr(&crl_contents),
+ curlx_dyn_len(&crl_contents));
if(rr != RUSTLS_RESULT_OK) {
rustls_failf(data, rr, "failed to parse revocation list");
result = CURLE_SSL_CRL_BADFILE;
@@ -710,7 +710,7 @@ init_config_builder_verifier_crl(
}
cleanup:
- Curl_dyn_free(&crl_contents);
+ curlx_dyn_free(&crl_contents);
return result;
}
@@ -868,8 +868,8 @@ init_config_builder_client_auth(struct Curl_easy *data,
return CURLE_SSL_CERTPROBLEM;
}
- Curl_dyn_init(&cert_contents, SIZE_MAX);
- Curl_dyn_init(&key_contents, SIZE_MAX);
+ curlx_dyn_init(&cert_contents, DYN_CERTFILE_SIZE);
+ curlx_dyn_init(&key_contents, DYN_KEYFILE_SIZE);
if(!read_file_into(conn_config->clientcert, &cert_contents)) {
failf(data, "rustls: failed to read client certificate file: '%s'",
@@ -884,10 +884,10 @@ init_config_builder_client_auth(struct Curl_easy *data,
goto cleanup;
}
- rr = rustls_certified_key_build(Curl_dyn_uptr(&cert_contents),
- Curl_dyn_len(&cert_contents),
- Curl_dyn_uptr(&key_contents),
- Curl_dyn_len(&key_contents),
+ rr = rustls_certified_key_build(curlx_dyn_uptr(&cert_contents),
+ curlx_dyn_len(&cert_contents),
+ curlx_dyn_uptr(&key_contents),
+ curlx_dyn_len(&key_contents),
&certified_key);
if(rr != RUSTLS_RESULT_OK) {
rustls_failf(data, rr, "rustls: failed to build certified key");
@@ -915,8 +915,8 @@ init_config_builder_client_auth(struct Curl_easy *data,
}
cleanup:
- Curl_dyn_free(&cert_contents);
- Curl_dyn_free(&key_contents);
+ curlx_dyn_free(&cert_contents);
+ curlx_dyn_free(&key_contents);
if(certified_key) {
rustls_certified_key_free(certified_key);
}
@@ -961,8 +961,7 @@ init_config_builder_ech(struct Curl_easy *data,
return CURLE_OK;
}
- if(data->set.tls_ech & CURLECH_CLA_CFG
- && data->set.str[STRING_ECH_CONFIG]) {
+ if(data->set.tls_ech & CURLECH_CLA_CFG && data->set.str[STRING_ECH_CONFIG]) {
const char *b64 = data->set.str[STRING_ECH_CONFIG];
size_t decode_result;
if(!b64) {
@@ -971,7 +970,7 @@ init_config_builder_ech(struct Curl_easy *data,
goto cleanup;
}
/* rustls-ffi expects the raw TLS encoded ECHConfigList bytes */
- decode_result = Curl_base64_decode(b64, &ech_config, &ech_config_len);
+ decode_result = curlx_base64_decode(b64, &ech_config, &ech_config_len);
if(decode_result || !ech_config) {
infof(data, "rustls: cannot base64 decode ECHConfig from command line");
result = CURLE_SSL_CONNECT_ERROR;
@@ -980,10 +979,8 @@ init_config_builder_ech(struct Curl_easy *data,
}
else {
if(connssl->peer.hostname) {
- dns = Curl_fetch_addr(
- data,
- connssl->peer.hostname,
- connssl->peer.port);
+ dns = Curl_dnscache_get(data, connssl->peer.hostname,
+ connssl->peer.port, data->conn->ip_version);
}
if(!dns) {
failf(data, "rustls: ECH requested but no DNS info available");
@@ -1010,6 +1007,10 @@ init_config_builder_ech(struct Curl_easy *data,
goto cleanup;
}
cleanup:
+ /* if we base64 decoded, we can free now */
+ if(data->set.tls_ech & CURLECH_CLA_CFG && data->set.str[STRING_ECH_CONFIG]) {
+ free(ech_config);
+ }
if(dns) {
Curl_resolv_unlink(data, &dns);
}
diff --git a/libs/libcurl/src/vtls/rustls.h b/libs/libcurl/src/vtls/rustls.h
index d7c56de190..5e084eb785 100644
--- a/libs/libcurl/src/vtls/rustls.h
+++ b/libs/libcurl/src/vtls/rustls.h
@@ -25,7 +25,7 @@
#ifndef HEADER_CURL_RUSTLS_H
#define HEADER_CURL_RUSTLS_H
-#include "curl_setup.h"
+#include "../curl_setup.h"
#ifdef USE_RUSTLS
diff --git a/libs/libcurl/src/vtls/schannel.c b/libs/libcurl/src/vtls/schannel.c
index f685011aca..a8b12d65e9 100644
--- a/libs/libcurl/src/vtls/schannel.c
+++ b/libs/libcurl/src/vtls/schannel.c
@@ -29,7 +29,7 @@
* but vtls.c should ever call or use these functions.
*/
-#include "curl_setup.h"
+#include "../curl_setup.h"
#ifdef USE_SCHANNEL
@@ -42,25 +42,25 @@
#include "vtls.h"
#include "vtls_int.h"
#include "vtls_scache.h"
-#include "strcase.h"
-#include "sendf.h"
-#include "connect.h" /* for the connect timeout */
-#include "strerror.h"
-#include "select.h" /* for the socket readiness */
-#include "inet_pton.h" /* for IP addr SNI check */
-#include "curl_multibyte.h"
-#include "warnless.h"
+#include "../strcase.h"
+#include "../sendf.h"
+#include "../connect.h" /* for the connect timeout */
+#include "../strerror.h"
+#include "../select.h" /* for the socket readiness */
+#include "../curlx/inet_pton.h" /* for IP addr SNI check */
+#include "../curlx/multibyte.h"
+#include "../curlx/warnless.h"
#include "x509asn1.h"
-#include "curl_printf.h"
-#include "multiif.h"
-#include "system_win32.h"
-#include "version_win32.h"
-#include "rand.h"
-#include "strparse.h"
+#include "../curl_printf.h"
+#include "../multiif.h"
+#include "../system_win32.h"
+#include "../curlx/version_win32.h"
+#include "../rand.h"
+#include "../curlx/strparse.h"
/* The last #include file should be: */
-#include "curl_memory.h"
-#include "memdebug.h"
+#include "../curl_memory.h"
+#include "../memdebug.h"
/* Some verbose debug messages are wrapped by SCH_DEV() instead of DEBUGF()
* and only shown if CURL_SCHANNEL_DEV_DEBUG was defined at build time. These
@@ -151,6 +151,10 @@
#define PKCS12_NO_PERSIST_KEY 0x00008000
#endif
+#ifndef CERT_FIND_HAS_PRIVATE_KEY
+#define CERT_FIND_HAS_PRIVATE_KEY (21 << CERT_COMPARE_SHIFT)
+#endif
+
/* ALPN requires version 8.1 of the Windows SDK, which was
shipped with Visual Studio 2013, aka _MSC_VER 1800:
https://technet.microsoft.com/en-us/library/hh831771%28v=ws.11%29.aspx
@@ -377,7 +381,7 @@ set_ssl_ciphers(SCHANNEL_CRED *schannel_cred, char *ciphers,
int algCount = 0;
while(startCur && (0 != *startCur) && (algCount < NUM_CIPHERS)) {
curl_off_t alg;
- if(Curl_str_number(&startCur, &alg, INT_MAX) || !alg)
+ if(curlx_str_number(&startCur, &alg, INT_MAX) || !alg)
alg = get_alg_id_by_name(startCur);
if(alg)
@@ -611,6 +615,7 @@ schannel_acquire_credential_handle(struct Curl_cfilter *cf,
WCHAR* pszPassword;
size_t pwd_len = 0;
int str_w_len = 0;
+ int cert_find_flags;
const char *cert_showfilename_error = blob ?
"(memory blob)" : data->set.ssl.primary.clientcert;
curlx_unicodefree(cert_path);
@@ -682,9 +687,17 @@ schannel_acquire_credential_handle(struct Curl_cfilter *cf,
return CURLE_SSL_CERTPROBLEM;
}
+ /* CERT_FIND_HAS_PRIVATE_KEY is only available in Windows 8 / Server
+ 2012, (NT v6.2). For earlier versions we use CURL_FIND_ANY. */
+ if(curlx_verify_windows_version(6, 2, 0, PLATFORM_WINNT,
+ VERSION_GREATER_THAN_EQUAL))
+ cert_find_flags = CERT_FIND_HAS_PRIVATE_KEY;
+ else
+ cert_find_flags = CERT_FIND_ANY;
+
client_certs[0] = CertFindCertificateInStore(
cert_store, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0,
- CERT_FIND_ANY, NULL, NULL);
+ cert_find_flags, NULL, NULL);
if(!client_certs[0]) {
failf(data, "schannel: Failed to get certificate from file %s"
@@ -2619,8 +2632,8 @@ HCERTSTORE Curl_schannel_get_cached_cert_store(struct Curl_cfilter *cf,
negative timeout means retain forever. */
timeout_ms = cfg->ca_cache_timeout * (timediff_t)1000;
if(timeout_ms >= 0) {
- now = Curl_now();
- elapsed_ms = Curl_timediff(now, share->time);
+ now = curlx_now();
+ elapsed_ms = curlx_timediff(now, share->time);
if(elapsed_ms >= timeout_ms) {
return NULL;
}
@@ -2719,7 +2732,7 @@ bool Curl_schannel_set_cached_cert_store(struct Curl_cfilter *cf,
}
free(share->CAfile);
- share->time = Curl_now();
+ share->time = curlx_now();
share->cert_store = cert_store;
share->CAinfo_blob_size = CAinfo_blob_size;
share->CAfile = CAfile;
diff --git a/libs/libcurl/src/vtls/schannel.h b/libs/libcurl/src/vtls/schannel.h
index e901eacfbd..a0fb515aa7 100644
--- a/libs/libcurl/src/vtls/schannel.h
+++ b/libs/libcurl/src/vtls/schannel.h
@@ -24,7 +24,7 @@
* SPDX-License-Identifier: curl
*
***************************************************************************/
-#include "curl_setup.h"
+#include "../curl_setup.h"
#ifdef USE_SCHANNEL
@@ -50,10 +50,10 @@
#include <schnlsp.h>
#include <schannel.h>
-#include "curl_sspi.h"
+#include "../curl_sspi.h"
-#include "cfilters.h"
-#include "urldata.h"
+#include "../cfilters.h"
+#include "../urldata.h"
/* <wincrypt.h> has been included via the above <schnlsp.h>.
* Or in case of ldap.c, it was included via <winldap.h>.
diff --git a/libs/libcurl/src/vtls/schannel_int.h b/libs/libcurl/src/vtls/schannel_int.h
index 52d6fd5214..410a4808a2 100644
--- a/libs/libcurl/src/vtls/schannel_int.h
+++ b/libs/libcurl/src/vtls/schannel_int.h
@@ -24,7 +24,7 @@
* SPDX-License-Identifier: curl
*
***************************************************************************/
-#include "curl_setup.h"
+#include "../curl_setup.h"
#ifdef USE_SCHANNEL
@@ -150,17 +150,17 @@ struct schannel_ssl_backend_data {
cannot 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 */
+ BIT(recv_sspi_close_notify); /* true if connection closed by close_notify */
+ BIT(recv_connection_closed); /* true if connection closed, regardless how */
+ BIT(recv_renegotiating); /* true if recv is doing renegotiation */
+ BIT(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 */
+ BIT(use_manual_cred_validation); /* true if manual cred validation is used */
#endif
BIT(sent_shutdown);
+ BIT(encdata_is_incomplete);
};
/* key to use at `multi->proto_hash` */
diff --git a/libs/libcurl/src/vtls/schannel_verify.c b/libs/libcurl/src/vtls/schannel_verify.c
index 26b3805cc6..69d79182cf 100644
--- a/libs/libcurl/src/vtls/schannel_verify.c
+++ b/libs/libcurl/src/vtls/schannel_verify.c
@@ -29,7 +29,7 @@
* only be invoked by code in schannel.c.
*/
-#include "curl_setup.h"
+#include "../curl_setup.h"
#ifdef USE_SCHANNEL
#ifndef USE_WINDOWS_SSPI
@@ -39,19 +39,20 @@
#include "schannel.h"
#include "schannel_int.h"
-#include "inet_pton.h"
+#include "../curlx/inet_pton.h"
#include "vtls.h"
#include "vtls_int.h"
-#include "sendf.h"
-#include "strerror.h"
-#include "curl_multibyte.h"
-#include "curl_printf.h"
+#include "../sendf.h"
+#include "../strerror.h"
+#include "../curlx/winapi.h"
+#include "../curlx/multibyte.h"
+#include "../curl_printf.h"
#include "hostcheck.h"
-#include "version_win32.h"
+#include "../curlx/version_win32.h"
/* The last #include file should be: */
-#include "curl_memory.h"
-#include "memdebug.h"
+#include "../curl_memory.h"
+#include "../memdebug.h"
#define BACKEND ((struct schannel_ssl_backend_data *)connssl->backend)
@@ -174,7 +175,7 @@ static CURLcode add_certs_data_to_store(HCERTSTORE trust_store,
NULL,
NULL,
(const void **)&cert_context)) {
- char buffer[STRERROR_LEN];
+ char buffer[WINAPI_ERROR_LEN];
failf(data,
"schannel: failed to extract certificate from CA file "
"'%s': %s",
@@ -203,7 +204,7 @@ static CURLcode add_certs_data_to_store(HCERTSTORE trust_store,
NULL);
CertFreeCertificateContext(cert_context);
if(!add_cert_result) {
- char buffer[STRERROR_LEN];
+ char buffer[WINAPI_ERROR_LEN];
failf(data,
"schannel: failed to add certificate from CA file '%s' "
"to certificate store: %s",
@@ -251,7 +252,7 @@ static CURLcode add_certs_file_to_store(HCERTSTORE trust_store,
ca_file_tstr = curlx_convert_UTF8_to_tchar(ca_file);
if(!ca_file_tstr) {
- char buffer[STRERROR_LEN];
+ char buffer[WINAPI_ERROR_LEN];
failf(data,
"schannel: invalid path name for CA file '%s': %s",
ca_file,
@@ -273,7 +274,7 @@ static CURLcode add_certs_file_to_store(HCERTSTORE trust_store,
FILE_ATTRIBUTE_NORMAL,
NULL);
if(ca_file_handle == INVALID_HANDLE_VALUE) {
- char buffer[STRERROR_LEN];
+ char buffer[WINAPI_ERROR_LEN];
failf(data,
"schannel: failed to open CA file '%s': %s",
ca_file,
@@ -283,7 +284,7 @@ static CURLcode add_certs_file_to_store(HCERTSTORE trust_store,
}
if(!GetFileSizeEx(ca_file_handle, &file_size)) {
- char buffer[STRERROR_LEN];
+ char buffer[WINAPI_ERROR_LEN];
failf(data,
"schannel: failed to determine size of CA file '%s': %s",
ca_file,
@@ -313,7 +314,7 @@ static CURLcode add_certs_file_to_store(HCERTSTORE trust_store,
if(!ReadFile(ca_file_handle, ca_file_buffer + total_bytes_read,
bytes_to_read, &bytes_read, NULL)) {
- char buffer[STRERROR_LEN];
+ char buffer[WINAPI_ERROR_LEN];
failf(data,
"schannel: failed to read from CA file '%s': %s",
ca_file,
@@ -614,7 +615,7 @@ CURLcode Curl_verify_host(struct Curl_cfilter *cf,
&pCertContextServer);
if((sspi_status != SEC_E_OK) || !pCertContextServer) {
- char buffer[STRERROR_LEN];
+ char buffer[WINAPI_ERROR_LEN];
failf(data, "schannel: Failed to read remote certificate context: %s",
Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer)));
goto cleanup;
@@ -770,7 +771,7 @@ CURLcode Curl_verify_certificate(struct Curl_cfilter *cf,
&pCertContextServer);
if((sspi_status != SEC_E_OK) || !pCertContextServer) {
- char buffer[STRERROR_LEN];
+ char buffer[WINAPI_ERROR_LEN];
failf(data, "schannel: Failed to read remote certificate context: %s",
Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer)));
result = CURLE_PEER_FAILED_VERIFICATION;
@@ -806,7 +807,7 @@ CURLcode Curl_verify_certificate(struct Curl_cfilter *cf,
CERT_STORE_CREATE_NEW_FLAG,
NULL);
if(!trust_store) {
- char buffer[STRERROR_LEN];
+ char buffer[WINAPI_ERROR_LEN];
failf(data, "schannel: failed to create certificate store: %s",
curlx_winapi_strerror(GetLastError(), buffer, sizeof(buffer)));
result = CURLE_SSL_CACERT_BADFILE;
@@ -853,7 +854,7 @@ CURLcode Curl_verify_certificate(struct Curl_cfilter *cf,
CertCreateCertificateChainEngine(
(CERT_CHAIN_ENGINE_CONFIG *)&engine_config, &cert_chain_engine);
if(!create_engine_result) {
- char buffer[STRERROR_LEN];
+ char buffer[WINAPI_ERROR_LEN];
failf(data,
"schannel: failed to create certificate chain engine: %s",
curlx_winapi_strerror(GetLastError(), buffer, sizeof(buffer)));
@@ -878,7 +879,7 @@ CURLcode Curl_verify_certificate(struct Curl_cfilter *cf,
CERT_CHAIN_REVOCATION_CHECK_CHAIN),
NULL,
&pChainContext)) {
- char buffer[STRERROR_LEN];
+ char buffer[WINAPI_ERROR_LEN];
failf(data, "schannel: CertGetCertificateChain failed: %s",
curlx_winapi_strerror(GetLastError(), buffer, sizeof(buffer)));
pChainContext = NULL;
diff --git a/libs/libcurl/src/vtls/sectransp.c b/libs/libcurl/src/vtls/sectransp.c
index 9cb51f2c53..d05dd8a3f8 100644
--- a/libs/libcurl/src/vtls/sectransp.c
+++ b/libs/libcurl/src/vtls/sectransp.c
@@ -28,18 +28,18 @@
* TLS/SSL layer. No code but vtls.c should ever call or use these functions.
*/
-#include "curl_setup.h"
+#include "../curl_setup.h"
#ifdef USE_SECTRANSP
-#include "urldata.h" /* for the Curl_easy definition */
-#include "curl_base64.h"
-#include "strparse.h"
-#include "multiif.h"
-#include "strcase.h"
+#include "../urldata.h" /* for the Curl_easy definition */
+#include "../curlx/base64.h"
+#include "../curlx/strparse.h"
+#include "../multiif.h"
+#include "../strcase.h"
#include "x509asn1.h"
#include "vtls_scache.h"
-#include "strerror.h"
+#include "../strerror.h"
#include "cipher_suite.h"
#ifdef __clang__
@@ -134,19 +134,19 @@
#include <sys/sysctl.h>
#endif /* CURL_BUILD_MAC */
-#include "sendf.h"
-#include "inet_pton.h"
-#include "connect.h"
-#include "select.h"
+#include "../sendf.h"
+#include "../curlx/inet_pton.h"
+#include "../connect.h"
+#include "../select.h"
#include "vtls.h"
#include "vtls_int.h"
#include "sectransp.h"
-#include "curl_printf.h"
-#include "strdup.h"
+#include "../curl_printf.h"
+#include "../strdup.h"
-#include "curl_memory.h"
+#include "../curl_memory.h"
/* The last #include file should be: */
-#include "memdebug.h"
+#include "../memdebug.h"
/* From MacTypes.h (which we cannot include because it is not present in
@@ -352,9 +352,9 @@ CF_INLINE void GetDarwinVersionNumber(int *major, int *minor)
curl_off_t fnum;
curl_off_t snum;
/* Parse the version: */
- if(!Curl_str_number(&os, &fnum, INT_MAX) &&
- !Curl_str_single(&os, '.') &&
- !Curl_str_number(&os, &snum, INT_MAX)) {
+ if(!curlx_str_number(&os, &fnum, INT_MAX) &&
+ !curlx_str_single(&os, '.') &&
+ !curlx_str_number(&os, &snum, INT_MAX)) {
*major = (int)fnum;
*minor = (int)snum;
}
@@ -1092,8 +1092,8 @@ static CURLcode sectransp_connect_step1(struct Curl_cfilter *cf,
return result;
if(connssl->alpn) {
-#if (CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) && \
- defined(HAVE_BUILTIN_AVAILABLE)
+#if CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11
+#ifdef HAVE_BUILTIN_AVAILABLE
if(__builtin_available(macOS 10.13.4, iOS 11, tvOS 11, *)) {
#else
if(&SSLSetALPNProtocols && &SSLCopyALPNProtocols) {
@@ -1119,6 +1119,7 @@ static CURLcode sectransp_connect_step1(struct Curl_cfilter *cf,
Curl_alpn_to_proto_str(&proto, connssl->alpn);
infof(data, VTLS_INFOF_ALPN_OFFER_1STR, proto.data);
}
+#endif /* CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11 */
}
if(ssl_config->key) {
@@ -1434,7 +1435,7 @@ static long pem_to_der(const char *in, unsigned char **out, size_t *outlen)
}
b64[j] = '\0';
- err = Curl_base64_decode((const char *)b64, out, outlen);
+ err = curlx_base64_decode((const char *)b64, out, outlen);
free(b64);
if(err) {
free(*out);
@@ -1453,7 +1454,7 @@ static int read_cert(const char *file, unsigned char **out, size_t *outlen)
unsigned char buf[512];
struct dynbuf certs;
- Curl_dyn_init(&certs, MAX_CERTS_SIZE);
+ curlx_dyn_init(&certs, MAX_CERTS_SIZE);
fd = open(file, 0);
if(fd < 0)
@@ -1465,18 +1466,18 @@ static int read_cert(const char *file, unsigned char **out, size_t *outlen)
break;
if(n < 0) {
close(fd);
- Curl_dyn_free(&certs);
+ curlx_dyn_free(&certs);
return -1;
}
- if(Curl_dyn_addn(&certs, buf, n)) {
+ if(curlx_dyn_addn(&certs, buf, n)) {
close(fd);
return -1;
}
}
close(fd);
- *out = Curl_dyn_uptr(&certs);
- *outlen = Curl_dyn_len(&certs);
+ *out = curlx_dyn_uptr(&certs);
+ *outlen = curlx_dyn_len(&certs);
return 0;
}
@@ -2092,8 +2093,8 @@ check_handshake:
}
if(connssl->alpn) {
-#if (CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) && \
- defined(HAVE_BUILTIN_AVAILABLE)
+#if CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11
+#ifdef HAVE_BUILTIN_AVAILABLE
if(__builtin_available(macOS 10.13.4, iOS 11, tvOS 11, *)) {
#else
if(&SSLSetALPNProtocols && &SSLCopyALPNProtocols) {
@@ -2124,6 +2125,7 @@ check_handshake:
if(alpnArr)
CFRelease(alpnArr);
}
+#endif /* CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11 */
}
return CURLE_OK;
diff --git a/libs/libcurl/src/vtls/sectransp.h b/libs/libcurl/src/vtls/sectransp.h
index 3b79169ab3..9011f17508 100644
--- a/libs/libcurl/src/vtls/sectransp.h
+++ b/libs/libcurl/src/vtls/sectransp.h
@@ -24,7 +24,7 @@
* SPDX-License-Identifier: curl
*
***************************************************************************/
-#include "curl_setup.h"
+#include "../curl_setup.h"
#ifdef USE_SECTRANSP
diff --git a/libs/libcurl/src/vtls/vtls.c b/libs/libcurl/src/vtls/vtls.c
index 0247d77577..37aaea9358 100644
--- a/libs/libcurl/src/vtls/vtls.c
+++ b/libs/libcurl/src/vtls/vtls.c
@@ -38,7 +38,7 @@
https://httpd.apache.org/docs/2.0/ssl/ssl_intro.html
*/
-#include "curl_setup.h"
+#include "../curl_setup.h"
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
@@ -50,8 +50,8 @@
#include <fcntl.h>
#endif
-#include "urldata.h"
-#include "cfilters.h"
+#include "../urldata.h"
+#include "../cfilters.h"
#include "vtls.h" /* generic SSL protos etc */
#include "vtls_int.h"
@@ -66,28 +66,28 @@
#include "bearssl.h" /* BearSSL versions */
#include "rustls.h" /* Rustls versions */
-#include "slist.h"
-#include "sendf.h"
-#include "strcase.h"
-#include "url.h"
-#include "progress.h"
-#include "share.h"
-#include "multiif.h"
-#include "timeval.h"
-#include "curl_md5.h"
-#include "curl_sha256.h"
-#include "warnless.h"
-#include "curl_base64.h"
-#include "curl_printf.h"
-#include "inet_pton.h"
-#include "connect.h"
-#include "select.h"
-#include "strdup.h"
-#include "rand.h"
+#include "../slist.h"
+#include "../sendf.h"
+#include "../strcase.h"
+#include "../url.h"
+#include "../progress.h"
+#include "../share.h"
+#include "../multiif.h"
+#include "../curlx/timeval.h"
+#include "../curl_md5.h"
+#include "../curl_sha256.h"
+#include "../curlx/warnless.h"
+#include "../curlx/base64.h"
+#include "../curl_printf.h"
+#include "../curlx/inet_pton.h"
+#include "../connect.h"
+#include "../select.h"
+#include "../strdup.h"
+#include "../rand.h"
/* The last #include files should be: */
-#include "curl_memory.h"
-#include "memdebug.h"
+#include "../curl_memory.h"
+#include "../memdebug.h"
#define CLONE_STRING(var) \
@@ -215,6 +215,7 @@ match_ssl_primary_config(struct Curl_easy *data,
strcasecompare(c1->cipher_list, c2->cipher_list) &&
strcasecompare(c1->cipher_list13, c2->cipher_list13) &&
strcasecompare(c1->curves, c2->curves) &&
+ strcasecompare(c1->signature_algorithms, c2->signature_algorithms) &&
strcasecompare(c1->CRLfile, c2->CRLfile) &&
strcasecompare(c1->pinned_key, c2->pinned_key))
return TRUE;
@@ -259,6 +260,7 @@ static bool clone_ssl_primary_config(struct ssl_primary_config *source,
CLONE_STRING(cipher_list13);
CLONE_STRING(pinned_key);
CLONE_STRING(curves);
+ CLONE_STRING(signature_algorithms);
CLONE_STRING(CRLfile);
#ifdef USE_TLS_SRP
CLONE_STRING(username);
@@ -281,6 +283,7 @@ static void free_primary_ssl_config(struct ssl_primary_config *sslc)
Curl_safefree(sslc->ca_info_blob);
Curl_safefree(sslc->issuercert_blob);
Curl_safefree(sslc->curves);
+ Curl_safefree(sslc->signature_algorithms);
Curl_safefree(sslc->CRLfile);
#ifdef USE_TLS_SRP
Curl_safefree(sslc->username);
@@ -299,6 +302,8 @@ CURLcode Curl_ssl_easy_config_complete(struct Curl_easy *data)
data->set.str[STRING_SSL_CIPHER_LIST];
data->set.ssl.primary.cipher_list13 =
data->set.str[STRING_SSL_CIPHER13_LIST];
+ data->set.ssl.primary.signature_algorithms =
+ data->set.str[STRING_SSL_SIGNATURE_ALGORITHMS];
data->set.ssl.primary.pinned_key =
data->set.str[STRING_SSL_PINNEDPUBLICKEY];
data->set.ssl.primary.cert_blob = data->set.blobs[BLOB_CERT];
@@ -611,17 +616,17 @@ CURLcode Curl_ssl_push_certinfo_len(struct Curl_easy *data,
DEBUGASSERT(certnum < ci->num_of_certs);
- Curl_dyn_init(&build, CURL_X509_STR_MAX);
+ curlx_dyn_init(&build, CURL_X509_STR_MAX);
- if(Curl_dyn_add(&build, label) ||
- Curl_dyn_addn(&build, ":", 1) ||
- Curl_dyn_addn(&build, value, valuelen))
+ if(curlx_dyn_add(&build, label) ||
+ curlx_dyn_addn(&build, ":", 1) ||
+ curlx_dyn_addn(&build, value, valuelen))
return CURLE_OUT_OF_MEMORY;
nl = Curl_slist_append_nodup(ci->certinfo[certnum],
- Curl_dyn_ptr(&build));
+ curlx_dyn_ptr(&build));
if(!nl) {
- Curl_dyn_free(&build);
+ curlx_dyn_free(&build);
curl_slist_free_all(ci->certinfo[certnum]);
result = CURLE_OUT_OF_MEMORY;
}
@@ -658,7 +663,7 @@ static CURLcode pubkey_pem_to_der(const char *pem,
if(!pem)
return CURLE_BAD_CONTENT_ENCODING;
- Curl_dyn_init(&pbuf, MAX_PINNED_PUBKEY_SIZE);
+ curlx_dyn_init(&pbuf, MAX_PINNED_PUBKEY_SIZE);
begin_pos = strstr(pem, "-----BEGIN PUBLIC KEY-----");
if(!begin_pos)
@@ -686,16 +691,19 @@ static CURLcode pubkey_pem_to_der(const char *pem,
*/
while(pem_count < pem_len) {
if('\n' != pem[pem_count] && '\r' != pem[pem_count]) {
- result = Curl_dyn_addn(&pbuf, &pem[pem_count], 1);
+ result = curlx_dyn_addn(&pbuf, &pem[pem_count], 1);
if(result)
return result;
}
++pem_count;
}
- result = Curl_base64_decode(Curl_dyn_ptr(&pbuf), der, der_len);
-
- Curl_dyn_free(&pbuf);
+ if(curlx_dyn_len(&pbuf)) {
+ result = curlx_base64_decode(curlx_dyn_ptr(&pbuf), der, der_len);
+ curlx_dyn_free(&pbuf);
+ }
+ else
+ result = CURLE_BAD_CONTENT_ENCODING;
return result;
}
@@ -739,9 +747,9 @@ CURLcode Curl_pin_peer_pubkey(struct Curl_easy *data,
sha256sumdigest, CURL_SHA256_DIGEST_LENGTH);
if(!encode)
- encode = Curl_base64_encode((char *)sha256sumdigest,
- CURL_SHA256_DIGEST_LENGTH, &encoded,
- &encodedlen);
+ encode = curlx_base64_encode((char *)sha256sumdigest,
+ CURL_SHA256_DIGEST_LENGTH, &encoded,
+ &encodedlen);
Curl_safefree(sha256sumdigest);
if(encode)
@@ -796,7 +804,7 @@ CURLcode Curl_pin_peer_pubkey(struct Curl_easy *data,
if(!fp)
return result;
- Curl_dyn_init(&buf, MAX_PINNED_PUBKEY_SIZE);
+ curlx_dyn_init(&buf, MAX_PINNED_PUBKEY_SIZE);
/* Determine the file's size */
if(fseek(fp, 0, SEEK_END))
@@ -824,14 +832,14 @@ CURLcode Curl_pin_peer_pubkey(struct Curl_easy *data,
size_t want = left > sizeof(buffer) ? sizeof(buffer) : left;
if(want != fread(buffer, 1, want, fp))
goto end;
- if(Curl_dyn_addn(&buf, buffer, want))
+ if(curlx_dyn_addn(&buf, buffer, want))
goto end;
left -= want;
} while(left);
/* If the sizes are the same, it cannot be base64 encoded, must be der */
if(pubkeylen == size) {
- if(!memcmp(pubkey, Curl_dyn_ptr(&buf), pubkeylen))
+ if(!memcmp(pubkey, curlx_dyn_ptr(&buf), pubkeylen))
result = CURLE_OK;
goto end;
}
@@ -840,7 +848,7 @@ CURLcode Curl_pin_peer_pubkey(struct Curl_easy *data,
* Otherwise we will assume it is PEM and try to decode it
* after placing null terminator
*/
- pem_read = pubkey_pem_to_der(Curl_dyn_ptr(&buf), &pem_ptr, &pem_len);
+ pem_read = pubkey_pem_to_der(curlx_dyn_ptr(&buf), &pem_ptr, &pem_len);
/* if it was not read successfully, exit */
if(pem_read)
goto end;
@@ -852,7 +860,7 @@ CURLcode Curl_pin_peer_pubkey(struct Curl_easy *data,
if(pubkeylen == pem_len && !memcmp(pubkey, pem_ptr, pubkeylen))
result = CURLE_OK;
end:
- Curl_dyn_free(&buf);
+ curlx_dyn_free(&buf);
Curl_safefree(pem_ptr);
fclose(fp);
}
@@ -1346,7 +1354,7 @@ static CURLcode ssl_cf_connect(struct Curl_cfilter *cf,
if(!result && *done) {
cf->connected = TRUE;
if(connssl->state == ssl_connection_complete)
- connssl->handshake_done = Curl_now();
+ connssl->handshake_done = curlx_now();
/* Connection can be deferred when sending early data */
DEBUGASSERT(connssl->state == ssl_connection_complete ||
connssl->state == ssl_connection_deferred);
@@ -1661,8 +1669,14 @@ static CURLcode cf_ssl_create(struct Curl_cfilter **pcf,
DEBUGASSERT(data->conn);
+#ifdef CURL_DISABLE_HTTP
+ /* We only support ALPN for HTTP so far. */
+ DEBUGASSERT(!conn->bits.tls_enable_alpn);
+ ctx = cf_ctx_new(data, NULL);
+#else
ctx = cf_ctx_new(data, alpn_get_spec(data->state.http_neg.wanted,
conn->bits.tls_enable_alpn));
+#endif
if(!ctx) {
result = CURLE_OUT_OF_MEMORY;
goto out;
diff --git a/libs/libcurl/src/vtls/vtls.h b/libs/libcurl/src/vtls/vtls.h
index 3c438a2dba..0617758f92 100644
--- a/libs/libcurl/src/vtls/vtls.h
+++ b/libs/libcurl/src/vtls/vtls.h
@@ -23,7 +23,7 @@
* SPDX-License-Identifier: curl
*
***************************************************************************/
-#include "curl_setup.h"
+#include "../curl_setup.h"
struct connectdata;
struct ssl_config_data;
@@ -42,9 +42,10 @@ struct dynbuf;
#define SSLSUPP_ECH (1<<7)
#define SSLSUPP_CA_CACHE (1<<8)
#define SSLSUPP_CIPHER_LIST (1<<9) /* supports TLS 1.0-1.2 ciphersuites */
+#define SSLSUPP_SIGNATURE_ALGORITHMS (1<<10) /* supports TLS sigalgs */
#ifdef USE_ECH
-# include "curl_base64.h"
+# include "../curlx/base64.h"
# define ECH_ENABLED(__data__) \
(__data__->set.tls_ech && \
!(__data__->set.tls_ech & CURLECH_DISABLE)\
diff --git a/libs/libcurl/src/vtls/vtls_int.h b/libs/libcurl/src/vtls/vtls_int.h
index 59657883df..e4a9e35325 100644
--- a/libs/libcurl/src/vtls/vtls_int.h
+++ b/libs/libcurl/src/vtls/vtls_int.h
@@ -23,9 +23,9 @@
* SPDX-License-Identifier: curl
*
***************************************************************************/
-#include "curl_setup.h"
-#include "cfilters.h"
-#include "urldata.h"
+#include "../curl_setup.h"
+#include "../cfilters.h"
+#include "../urldata.h"
#include "vtls.h"
#ifdef USE_SSL
diff --git a/libs/libcurl/src/vtls/vtls_scache.c b/libs/libcurl/src/vtls/vtls_scache.c
index d06c6cf9f9..d2d2718e51 100644
--- a/libs/libcurl/src/vtls/vtls_scache.c
+++ b/libs/libcurl/src/vtls/vtls_scache.c
@@ -22,7 +22,7 @@
*
***************************************************************************/
-#include "curl_setup.h"
+#include "../curl_setup.h"
#ifdef USE_SSL
@@ -36,28 +36,28 @@
#include <fcntl.h>
#endif
-#include "urldata.h"
-#include "cfilters.h"
+#include "../urldata.h"
+#include "../cfilters.h"
#include "vtls.h" /* generic SSL protos etc */
#include "vtls_int.h"
#include "vtls_scache.h"
#include "vtls_spack.h"
-#include "strcase.h"
-#include "url.h"
-#include "llist.h"
-#include "share.h"
-#include "curl_trc.h"
-#include "curl_sha256.h"
-#include "rand.h"
-#include "warnless.h"
-#include "curl_printf.h"
-#include "strdup.h"
+#include "../strcase.h"
+#include "../url.h"
+#include "../llist.h"
+#include "../share.h"
+#include "../curl_trc.h"
+#include "../curl_sha256.h"
+#include "../rand.h"
+#include "../curlx/warnless.h"
+#include "../curl_printf.h"
+#include "../strdup.h"
/* The last #include files should be: */
-#include "curl_memory.h"
-#include "memdebug.h"
+#include "../curl_memory.h"
+#include "../memdebug.h"
static bool cf_ssl_peer_key_is_global(const char *peer_key);
@@ -387,24 +387,24 @@ static CURLcode cf_ssl_peer_key_add_path(struct dynbuf *buf,
* the path as is. */
#ifdef UNDER_CE
(void)is_local;
- return Curl_dyn_addf(buf, ":%s-%s", name, path);
+ return curlx_dyn_addf(buf, ":%s-%s", name, path);
#elif defined(_WIN32)
char abspath[_MAX_PATH];
if(_fullpath(abspath, path, _MAX_PATH))
- return Curl_dyn_addf(buf, ":%s-%s", name, abspath);
+ return curlx_dyn_addf(buf, ":%s-%s", name, abspath);
*is_local = TRUE;
#elif defined(HAVE_REALPATH)
if(path[0] != '/') {
char *abspath = realpath(path, NULL);
if(abspath) {
- CURLcode r = Curl_dyn_addf(buf, ":%s-%s", name, abspath);
+ CURLcode r = curlx_dyn_addf(buf, ":%s-%s", name, abspath);
(free)(abspath); /* allocated by libc, free without memdebug */
return r;
}
*is_local = TRUE;
}
#endif
- return Curl_dyn_addf(buf, ":%s-%s", name, path);
+ return curlx_dyn_addf(buf, ":%s-%s", name, path);
}
return CURLE_OK;
}
@@ -418,14 +418,14 @@ static CURLcode cf_ssl_peer_key_add_hash(struct dynbuf *buf,
unsigned char hash[CURL_SHA256_DIGEST_LENGTH];
size_t i;
- r = Curl_dyn_addf(buf, ":%s-", name);
+ r = curlx_dyn_addf(buf, ":%s-", name);
if(r)
goto out;
r = Curl_sha256it(hash, blob->data, blob->len);
if(r)
goto out;
for(i = 0; i < CURL_SHA256_DIGEST_LENGTH; ++i) {
- r = Curl_dyn_addf(buf, "%02x", hash[i]);
+ r = curlx_dyn_addf(buf, "%02x", hash[i]);
if(r)
goto out;
}
@@ -457,9 +457,9 @@ CURLcode Curl_ssl_peer_key_make(struct Curl_cfilter *cf,
CURLcode r;
*ppeer_key = NULL;
- Curl_dyn_init(&buf, 10 * 1024);
+ curlx_dyn_init(&buf, 10 * 1024);
- r = Curl_dyn_addf(&buf, "%s:%d", peer->hostname, peer->port);
+ r = curlx_dyn_addf(&buf, "%s:%d", peer->hostname, peer->port);
if(r)
goto out;
@@ -467,72 +467,72 @@ CURLcode Curl_ssl_peer_key_make(struct Curl_cfilter *cf,
case TRNSPRT_TCP:
break;
case TRNSPRT_UDP:
- r = Curl_dyn_add(&buf, ":UDP");
+ r = curlx_dyn_add(&buf, ":UDP");
break;
case TRNSPRT_QUIC:
- r = Curl_dyn_add(&buf, ":QUIC");
+ r = curlx_dyn_add(&buf, ":QUIC");
break;
case TRNSPRT_UNIX:
- r = Curl_dyn_add(&buf, ":UNIX");
+ r = curlx_dyn_add(&buf, ":UNIX");
break;
default:
- r = Curl_dyn_addf(&buf, ":TRNSPRT-%d", peer->transport);
+ r = curlx_dyn_addf(&buf, ":TRNSPRT-%d", peer->transport);
break;
}
if(r)
goto out;
if(!ssl->verifypeer) {
- r = Curl_dyn_add(&buf, ":NO-VRFY-PEER");
+ r = curlx_dyn_add(&buf, ":NO-VRFY-PEER");
if(r)
goto out;
}
if(!ssl->verifyhost) {
- r = Curl_dyn_add(&buf, ":NO-VRFY-HOST");
+ r = curlx_dyn_add(&buf, ":NO-VRFY-HOST");
if(r)
goto out;
}
if(ssl->verifystatus) {
- r = Curl_dyn_add(&buf, ":VRFY-STATUS");
+ r = curlx_dyn_add(&buf, ":VRFY-STATUS");
if(r)
goto out;
}
if(!ssl->verifypeer || !ssl->verifyhost) {
if(cf->conn->bits.conn_to_host) {
- r = Curl_dyn_addf(&buf, ":CHOST-%s", cf->conn->conn_to_host.name);
+ r = curlx_dyn_addf(&buf, ":CHOST-%s", cf->conn->conn_to_host.name);
if(r)
goto out;
}
if(cf->conn->bits.conn_to_port) {
- r = Curl_dyn_addf(&buf, ":CPORT-%d", cf->conn->conn_to_port);
+ r = curlx_dyn_addf(&buf, ":CPORT-%d", cf->conn->conn_to_port);
if(r)
goto out;
}
}
if(ssl->version || ssl->version_max) {
- r = Curl_dyn_addf(&buf, ":TLSVER-%d-%d", ssl->version,
+ r = curlx_dyn_addf(&buf, ":TLSVER-%d-%d", ssl->version,
(ssl->version_max >> 16));
if(r)
goto out;
}
if(ssl->ssl_options) {
- r = Curl_dyn_addf(&buf, ":TLSOPT-%x", ssl->ssl_options);
+ r = curlx_dyn_addf(&buf, ":TLSOPT-%x", ssl->ssl_options);
if(r)
goto out;
}
if(ssl->cipher_list) {
- r = Curl_dyn_addf(&buf, ":CIPHER-%s", ssl->cipher_list);
+ r = curlx_dyn_addf(&buf, ":CIPHER-%s", ssl->cipher_list);
if(r)
goto out;
}
if(ssl->cipher_list13) {
- r = Curl_dyn_addf(&buf, ":CIPHER13-%s", ssl->cipher_list13);
+ r = curlx_dyn_addf(&buf, ":CIPHER13-%s", ssl->cipher_list13);
if(r)
goto out;
}
if(ssl->curves) {
- r = Curl_dyn_addf(&buf, ":CURVES-%s", ssl->curves);
+ r = curlx_dyn_addf(&buf, ":CURVES-%s", ssl->curves);
if(r)
goto out;
}
@@ -566,19 +566,19 @@ CURLcode Curl_ssl_peer_key_make(struct Curl_cfilter *cf,
}
}
if(ssl->pinned_key && ssl->pinned_key[0]) {
- r = Curl_dyn_addf(&buf, ":Pinned-%s", ssl->pinned_key);
+ r = curlx_dyn_addf(&buf, ":Pinned-%s", ssl->pinned_key);
if(r)
goto out;
}
if(ssl->clientcert && ssl->clientcert[0]) {
- r = Curl_dyn_add(&buf, ":CCERT");
+ r = curlx_dyn_add(&buf, ":CCERT");
if(r)
goto out;
}
#ifdef USE_TLS_SRP
if(ssl->username || ssl->password) {
- r = Curl_dyn_add(&buf, ":SRP-AUTH");
+ r = curlx_dyn_add(&buf, ":SRP-AUTH");
if(r)
goto out;
}
@@ -588,22 +588,22 @@ CURLcode Curl_ssl_peer_key_make(struct Curl_cfilter *cf,
r = CURLE_FAILED_INIT;
goto out;
}
- r = Curl_dyn_addf(&buf, ":IMPL-%s", tls_id);
+ r = curlx_dyn_addf(&buf, ":IMPL-%s", tls_id);
if(r)
goto out;
- r = Curl_dyn_addf(&buf, is_local ?
- CURL_SSLS_LOCAL_SUFFIX : CURL_SSLS_GLOBAL_SUFFIX);
+ r = curlx_dyn_addf(&buf, is_local ?
+ CURL_SSLS_LOCAL_SUFFIX : CURL_SSLS_GLOBAL_SUFFIX);
if(r)
goto out;
- *ppeer_key = Curl_dyn_take(&buf, &key_len);
+ *ppeer_key = curlx_dyn_take(&buf, &key_len);
/* we just added printable char, and dynbuf always 0 terminates,
* no need to track length */
out:
- Curl_dyn_free(&buf);
+ curlx_dyn_free(&buf);
return r;
}
@@ -1173,8 +1173,8 @@ CURLcode Curl_ssl_session_export(struct Curl_easy *data,
Curl_ssl_scache_lock(data);
- Curl_dyn_init(&hbuf, (CURL_SHA256_DIGEST_LENGTH * 2) + 1);
- Curl_dyn_init(&sbuf, CURL_SSL_TICKET_MAX);
+ curlx_dyn_init(&hbuf, (CURL_SHA256_DIGEST_LENGTH * 2) + 1);
+ curlx_dyn_init(&sbuf, CURL_SSL_TICKET_MAX);
for(i = 0; scache && i < scache->peer_count; i++) {
peer = &scache->peers[i];
@@ -1183,7 +1183,7 @@ CURLcode Curl_ssl_session_export(struct Curl_easy *data,
if(!peer->exportable)
continue;
- Curl_dyn_reset(&hbuf);
+ curlx_dyn_reset(&hbuf);
cf_scache_peer_remove_expired(peer, now);
n = Curl_llist_head(&peer->sessions);
if(n)
@@ -1195,22 +1195,22 @@ CURLcode Curl_ssl_session_export(struct Curl_easy *data,
if(r)
goto out;
}
- if(!Curl_dyn_len(&hbuf)) {
- r = Curl_dyn_addn(&hbuf, peer->key_salt, sizeof(peer->key_salt));
+ if(!curlx_dyn_len(&hbuf)) {
+ r = curlx_dyn_addn(&hbuf, peer->key_salt, sizeof(peer->key_salt));
if(r)
goto out;
- r = Curl_dyn_addn(&hbuf, peer->key_hmac, sizeof(peer->key_hmac));
+ r = curlx_dyn_addn(&hbuf, peer->key_hmac, sizeof(peer->key_hmac));
if(r)
goto out;
}
- Curl_dyn_reset(&sbuf);
+ curlx_dyn_reset(&sbuf);
r = Curl_ssl_session_pack(data, s, &sbuf);
if(r)
goto out;
r = export_fn(data, userptr, peer->ssl_peer_key,
- Curl_dyn_uptr(&hbuf), Curl_dyn_len(&hbuf),
- Curl_dyn_uptr(&sbuf), Curl_dyn_len(&sbuf),
+ curlx_dyn_uptr(&hbuf), curlx_dyn_len(&hbuf),
+ curlx_dyn_uptr(&sbuf), curlx_dyn_len(&sbuf),
s->valid_until, s->ietf_tls_id,
s->alpn, s->earlydata_max);
if(r)
@@ -1226,8 +1226,8 @@ CURLcode Curl_ssl_session_export(struct Curl_easy *data,
out:
Curl_ssl_scache_unlock(data);
- Curl_dyn_free(&hbuf);
- Curl_dyn_free(&sbuf);
+ curlx_dyn_free(&hbuf);
+ curlx_dyn_free(&sbuf);
return r;
}
diff --git a/libs/libcurl/src/vtls/vtls_scache.h b/libs/libcurl/src/vtls/vtls_scache.h
index 3dea24024d..9bce4c36a5 100644
--- a/libs/libcurl/src/vtls/vtls_scache.h
+++ b/libs/libcurl/src/vtls/vtls_scache.h
@@ -23,9 +23,9 @@
* SPDX-License-Identifier: curl
*
***************************************************************************/
-#include "curl_setup.h"
-#include "cfilters.h"
-#include "urldata.h"
+#include "../curl_setup.h"
+#include "../cfilters.h"
+#include "../urldata.h"
#ifdef USE_SSL
diff --git a/libs/libcurl/src/vtls/vtls_spack.c b/libs/libcurl/src/vtls/vtls_spack.c
index b1bca85dbc..39555f226b 100644
--- a/libs/libcurl/src/vtls/vtls_spack.c
+++ b/libs/libcurl/src/vtls/vtls_spack.c
@@ -22,19 +22,19 @@
*
***************************************************************************/
-#include "curl_setup.h"
+#include "../curl_setup.h"
#ifdef USE_SSLS_EXPORT
-#include "urldata.h"
-#include "curl_trc.h"
+#include "../urldata.h"
+#include "../curl_trc.h"
#include "vtls_scache.h"
#include "vtls_spack.h"
-#include "strdup.h"
+#include "../strdup.h"
/* The last #include files should be: */
-#include "curl_memory.h"
-#include "memdebug.h"
+#include "../curl_memory.h"
+#include "../memdebug.h"
#ifdef _MSC_VER
#if _MSC_VER >= 1600
@@ -64,7 +64,7 @@ typedef unsigned __int64 uint64_t;
static CURLcode spack_enc8(struct dynbuf *buf, uint8_t b)
{
- return Curl_dyn_addn(buf, &b, 1);
+ return curlx_dyn_addn(buf, &b, 1);
}
static CURLcode
@@ -82,7 +82,7 @@ static CURLcode spack_enc16(struct dynbuf *buf, uint16_t val)
uint8_t nval[2];
nval[0] = (uint8_t)(val >> 8);
nval[1] = (uint8_t)val;
- return Curl_dyn_addn(buf, nval, sizeof(nval));
+ return curlx_dyn_addn(buf, nval, sizeof(nval));
}
static CURLcode
@@ -102,7 +102,7 @@ static CURLcode spack_enc32(struct dynbuf *buf, uint32_t val)
nval[1] = (uint8_t)(val >> 16);
nval[2] = (uint8_t)(val >> 8);
nval[3] = (uint8_t)val;
- return Curl_dyn_addn(buf, nval, sizeof(nval));
+ return curlx_dyn_addn(buf, nval, sizeof(nval));
}
static CURLcode
@@ -127,7 +127,7 @@ static CURLcode spack_enc64(struct dynbuf *buf, uint64_t val)
nval[5] = (uint8_t)(val >> 16);
nval[6] = (uint8_t)(val >> 8);
nval[7] = (uint8_t)val;
- return Curl_dyn_addn(buf, nval, sizeof(nval));
+ return curlx_dyn_addn(buf, nval, sizeof(nval));
}
static CURLcode
@@ -151,7 +151,7 @@ static CURLcode spack_encstr16(struct dynbuf *buf, const char *s)
return CURLE_BAD_FUNCTION_ARGUMENT;
r = spack_enc16(buf, (uint16_t)slen);
if(!r) {
- r = Curl_dyn_addn(buf, s, slen);
+ r = curlx_dyn_addn(buf, s, slen);
}
return r;
}
@@ -181,7 +181,7 @@ static CURLcode spack_encdata16(struct dynbuf *buf,
return CURLE_BAD_FUNCTION_ARGUMENT;
r = spack_enc16(buf, (uint16_t)data_len);
if(!r) {
- r = Curl_dyn_addn(buf, data, data_len);
+ r = curlx_dyn_addn(buf, data, data_len);
}
return r;
}
diff --git a/libs/libcurl/src/vtls/vtls_spack.h b/libs/libcurl/src/vtls/vtls_spack.h
index 62f9da6944..e1dfc18200 100644
--- a/libs/libcurl/src/vtls/vtls_spack.h
+++ b/libs/libcurl/src/vtls/vtls_spack.h
@@ -23,7 +23,7 @@
* SPDX-License-Identifier: curl
*
***************************************************************************/
-#include "curl_setup.h"
+#include "../curl_setup.h"
#ifdef USE_SSLS_EXPORT
diff --git a/libs/libcurl/src/vtls/wolfssl.c b/libs/libcurl/src/vtls/wolfssl.c
index 3cd67a2fe5..fad04a997f 100644
--- a/libs/libcurl/src/vtls/wolfssl.c
+++ b/libs/libcurl/src/vtls/wolfssl.c
@@ -28,7 +28,7 @@
*
*/
-#include "curl_setup.h"
+#include "../curl_setup.h"
#ifdef USE_WOLFSSL
@@ -56,30 +56,30 @@
#include <limits.h>
-#include "urldata.h"
-#include "sendf.h"
-#include "inet_pton.h"
+#include "../urldata.h"
+#include "../sendf.h"
+#include "../curlx/inet_pton.h"
#include "vtls.h"
#include "vtls_int.h"
#include "vtls_scache.h"
#include "keylog.h"
-#include "parsedate.h"
-#include "connect.h" /* for the connect timeout */
-#include "progress.h"
-#include "select.h"
-#include "strcase.h"
-#include "strdup.h"
+#include "../parsedate.h"
+#include "../connect.h" /* for the connect timeout */
+#include "../progress.h"
+#include "../select.h"
+#include "../strcase.h"
+#include "../strdup.h"
#include "x509asn1.h"
-#include "curl_printf.h"
-#include "multiif.h"
+#include "../curl_printf.h"
+#include "../multiif.h"
#include <wolfssl/ssl.h>
#include <wolfssl/error-ssl.h>
#include "wolfssl.h"
/* The last #include files should be: */
-#include "curl_memory.h"
-#include "memdebug.h"
+#include "../curl_memory.h"
+#include "../memdebug.h"
#ifdef HAVE_WOLFSSL_CTX_GENERATEECHCONFIG
#define USE_ECH_WOLFSSL
@@ -96,11 +96,11 @@
#endif
#endif
-#ifdef HAVE_WOLFSSL_BIO
+#ifdef HAVE_WOLFSSL_BIO_NEW
#define USE_BIO_CHAIN
-#ifdef HAVE_WOLFSSL_FULL_BIO
+#ifdef HAVE_WOLFSSL_BIO_SET_SHUTDOWN
#define USE_FULL_BIO
-#else /* HAVE_WOLFSSL_FULL_BIO */
+#else /* HAVE_WOLFSSL_BIO_SET_SHUTDOWN */
#undef USE_FULL_BIO
#endif
/* wolfSSL 5.7.4 and older do not have these symbols, but only the
@@ -114,7 +114,7 @@
#define wolfSSL_BIO_set_retry_read BIO_set_retry_read
#endif /* !WOLFSSL_BIO_CTRL_GET_CLOSE */
-#else /* HAVE_WOLFSSL_BIO */
+#else /* HAVE_WOLFSSL_BIO_NEW */
#undef USE_BIO_CHAIN
#endif
@@ -714,8 +714,8 @@ wssl_cached_x509_store_expired(const struct Curl_easy *data,
const struct wssl_x509_share *mb)
{
const struct ssl_general_config *cfg = &data->set.general_ssl;
- struct curltime now = Curl_now();
- timediff_t elapsed_ms = Curl_timediff(now, mb->time);
+ struct curltime now = curlx_now();
+ timediff_t elapsed_ms = curlx_timediff(now, mb->time);
timediff_t timeout_ms = cfg->ca_cache_timeout * (timediff_t)1000;
if(timeout_ms < 0)
@@ -799,7 +799,7 @@ static void wssl_set_cached_x509_store(struct Curl_cfilter *cf,
free(share->CAfile);
}
- share->time = Curl_now();
+ share->time = curlx_now();
share->store = store;
share->CAfile = CAfile;
}
@@ -871,14 +871,14 @@ wssl_add_default_ciphers(bool tls13, struct dynbuf *buf)
continue;
/* if there already is data in the string, add colon separator */
- if(Curl_dyn_len(buf)) {
- CURLcode result = Curl_dyn_addn(buf, ":", 1);
+ if(curlx_dyn_len(buf)) {
+ CURLcode result = curlx_dyn_addn(buf, ":", 1);
if(result)
return result;
}
n = strlen(str);
- if(Curl_dyn_addn(buf, str, n))
+ if(curlx_dyn_addn(buf, str, n))
return CURLE_OUT_OF_MEMORY;
}
@@ -1067,19 +1067,19 @@ CURLcode Curl_wssl_ctx_init(struct wssl_ctx *wctx,
const char *ciphers12 = conn_config->cipher_list;
const char *ciphers13 = conn_config->cipher_list13;
struct dynbuf c;
- Curl_dyn_init(&c, MAX_CIPHER_LEN);
+ curlx_dyn_init(&c, MAX_CIPHER_LEN);
if(ciphers13)
- result = Curl_dyn_add(&c, ciphers13);
+ result = curlx_dyn_add(&c, ciphers13);
else
result = wssl_add_default_ciphers(TRUE, &c);
if(!result) {
if(ciphers12) {
- if(Curl_dyn_len(&c))
- result = Curl_dyn_addn(&c, ":", 1);
+ if(curlx_dyn_len(&c))
+ result = curlx_dyn_addn(&c, ":", 1);
if(!result)
- result = Curl_dyn_add(&c, ciphers12);
+ result = curlx_dyn_add(&c, ciphers12);
}
else
result = wssl_add_default_ciphers(FALSE, &c);
@@ -1087,14 +1087,14 @@ CURLcode Curl_wssl_ctx_init(struct wssl_ctx *wctx,
if(result)
goto out;
- if(!wolfSSL_CTX_set_cipher_list(wctx->ssl_ctx, Curl_dyn_ptr(&c))) {
- failf(data, "failed setting cipher list: %s", Curl_dyn_ptr(&c));
- Curl_dyn_free(&c);
+ if(!wolfSSL_CTX_set_cipher_list(wctx->ssl_ctx, curlx_dyn_ptr(&c))) {
+ failf(data, "failed setting cipher list: %s", curlx_dyn_ptr(&c));
+ curlx_dyn_free(&c);
result = CURLE_SSL_CIPHER;
goto out;
}
- infof(data, "Cipher selection: %s", Curl_dyn_ptr(&c));
- Curl_dyn_free(&c);
+ infof(data, "Cipher selection: %s", curlx_dyn_ptr(&c));
+ curlx_dyn_free(&c);
}
#endif
@@ -1352,9 +1352,7 @@ CURLcode Curl_wssl_ctx_init(struct wssl_ctx *wctx,
goto out;
}
if(data->set.tls_ech == CURLECH_GREASE) {
- infof(data, "ECH: GREASE'd ECH not yet supported for wolfSSL");
- result = CURLE_SSL_CONNECT_ERROR;
- goto out;
+ infof(data, "ECH: GREASE is done by default by wolfSSL: no need to ask");
}
if(data->set.tls_ech & CURLECH_CLA_CFG
&& data->set.str[STRING_ECH_CONFIG]) {
@@ -1379,7 +1377,8 @@ CURLcode Curl_wssl_ctx_init(struct wssl_ctx *wctx,
struct ssl_connect_data *connssl = cf->ctx;
struct Curl_dns_entry *dns = NULL;
- dns = Curl_fetch_addr(data, connssl->peer.hostname, connssl->peer.port);
+ dns = Curl_dnscache_get(data, connssl->peer.hostname, connssl->peer.port,
+ cf->conn->ip_version);
if(!dns) {
infof(data, "ECH: requested but no DNS info available");
if(data->set.tls_ech & CURLECH_HARD) {
@@ -1467,7 +1466,7 @@ wssl_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
if(result)
return result;
-#ifdef HAS_ALPN
+#ifdef HAVE_ALPN
if(connssl->alpn && (connssl->state != ssl_connection_deferred)) {
struct alpn_proto_buf proto;
memset(&proto, 0, sizeof(proto));
@@ -1527,10 +1526,10 @@ static char *wssl_strerror(unsigned long error, char *buf,
return buf;
}
-static CURLcode wssl_verify_pinned(struct Curl_cfilter *cf,
- struct Curl_easy *data)
+CURLcode Curl_wssl_verify_pinned(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ struct wssl_ctx *wssl)
{
- struct ssl_connect_data *connssl = cf->ctx;
#ifndef CURL_DISABLE_PROXY
const char * const pinnedpubkey = Curl_ssl_cf_is_proxy(cf) ?
data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] :
@@ -1541,7 +1540,6 @@ static CURLcode wssl_verify_pinned(struct Curl_cfilter *cf,
if(pinnedpubkey) {
#ifdef KEEP_PEER_CERT
- struct wssl_ctx *wssl = (struct wssl_ctx *)connssl->backend;
WOLFSSL_X509 *x509;
const char *x509_der;
int x509_der_len;
@@ -1770,8 +1768,8 @@ static CURLcode wssl_handshake(struct Curl_cfilter *cf,
char *b64str = NULL;
size_t blen = 0;
- result = Curl_base64_encode((const char *)echConfigs, echConfigsLen,
- &b64str, &blen);
+ result = curlx_base64_encode((const char *)echConfigs, echConfigsLen,
+ &b64str, &blen);
if(!result && b64str)
infof(data, "ECH: (not yet) retry_configs %s", b64str);
free(b64str);
@@ -2139,7 +2137,7 @@ static CURLcode wssl_connect(struct Curl_cfilter *cf,
result = wssl->hs_result;
goto out;
}
- result = wssl_verify_pinned(cf, data);
+ result = Curl_wssl_verify_pinned(cf, data, wssl);
if(result) {
wssl->hs_result = result;
goto out;
diff --git a/libs/libcurl/src/vtls/wolfssl.h b/libs/libcurl/src/vtls/wolfssl.h
index cf4bff8e2c..f5f30b2018 100644
--- a/libs/libcurl/src/vtls/wolfssl.h
+++ b/libs/libcurl/src/vtls/wolfssl.h
@@ -23,11 +23,11 @@
* SPDX-License-Identifier: curl
*
***************************************************************************/
-#include "curl_setup.h"
+#include "../curl_setup.h"
#ifdef USE_WOLFSSL
-#include "urldata.h"
+#include "../urldata.h"
struct alpn_spec;
struct ssl_peer;
@@ -75,11 +75,6 @@ CURLcode Curl_wssl_setup_x509_store(struct Curl_cfilter *cf,
struct Curl_easy *data,
struct wssl_ctx *wssl);
-CURLcode Curl_wssl_setup_session(struct Curl_cfilter *cf,
- struct Curl_easy *data,
- struct wssl_ctx *wss,
- const char *ssl_peer_key);
-
CURLcode Curl_wssl_cache_session(struct Curl_cfilter *cf,
struct Curl_easy *data,
const char *ssl_peer_key,
@@ -89,6 +84,10 @@ CURLcode Curl_wssl_cache_session(struct Curl_cfilter *cf,
unsigned char *quic_tp,
size_t quic_tp_len);
+CURLcode Curl_wssl_verify_pinned(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ struct wssl_ctx *wssl);
+
#endif /* USE_WOLFSSL */
#endif /* HEADER_CURL_WOLFSSL_H */
diff --git a/libs/libcurl/src/vtls/x509asn1.c b/libs/libcurl/src/vtls/x509asn1.c
index 082b5191d9..d9c970d7d2 100644
--- a/libs/libcurl/src/vtls/x509asn1.c
+++ b/libs/libcurl/src/vtls/x509asn1.c
@@ -22,7 +22,7 @@
*
***************************************************************************/
-#include "curl_setup.h"
+#include "../curl_setup.h"
#if defined(USE_GNUTLS) || defined(USE_WOLFSSL) || \
defined(USE_SCHANNEL) || defined(USE_SECTRANSP) || \
@@ -39,22 +39,22 @@
#endif
#include <curl/curl.h>
-#include "urldata.h"
-#include "strcase.h"
-#include "curl_ctype.h"
+#include "../urldata.h"
+#include "../strcase.h"
+#include "../curl_ctype.h"
#include "hostcheck.h"
-#include "vtls/vtls.h"
-#include "vtls/vtls_int.h"
-#include "sendf.h"
-#include "inet_pton.h"
-#include "curl_base64.h"
+#include "vtls.h"
+#include "vtls_int.h"
+#include "../sendf.h"
+#include "../curlx/inet_pton.h"
+#include "../curlx/base64.h"
#include "x509asn1.h"
-#include "dynbuf.h"
+#include "../curlx/dynbuf.h"
/* The last 3 #include files should be in this order */
-#include "curl_printf.h"
-#include "curl_memory.h"
-#include "memdebug.h"
+#include "../curl_printf.h"
+#include "../curl_memory.h"
+#include "../memdebug.h"
/*
* Constants.
@@ -291,7 +291,7 @@ static CURLcode bool2str(struct dynbuf *store,
{
if(end - beg != 1)
return CURLE_BAD_FUNCTION_ARGUMENT;
- return Curl_dyn_add(store, *beg ? "TRUE": "FALSE");
+ return curlx_dyn_add(store, *beg ? "TRUE": "FALSE");
}
/*
@@ -305,7 +305,7 @@ static CURLcode octet2str(struct dynbuf *store,
CURLcode result = CURLE_OK;
while(!result && beg < end)
- result = Curl_dyn_addf(store, "%02x:", (unsigned char) *beg++);
+ result = curlx_dyn_addf(store, "%02x:", (unsigned char) *beg++);
return result;
}
@@ -344,7 +344,7 @@ static CURLcode int2str(struct dynbuf *store,
do
val = (val << 8) | *(const unsigned char *) beg++;
while(beg < end);
- return Curl_dyn_addf(store, "%s%x", val >= 10 ? "0x" : "", val);
+ return curlx_dyn_addf(store, "%s%x", val >= 10 ? "0x" : "", val);
}
/*
@@ -387,7 +387,7 @@ utf8asn1str(struct dynbuf *to, int type, const char *from, const char *end)
if(type == CURL_ASN1_UTF8_STRING) {
/* Just copy. */
if(inlength)
- result = Curl_dyn_addn(to, from, inlength);
+ result = curlx_dyn_addn(to, from, inlength);
}
else {
while(!result && (from < end)) {
@@ -426,7 +426,7 @@ utf8asn1str(struct dynbuf *to, int type, const char *from, const char *end)
charsize++;
}
buf[0] = (char) wc;
- result = Curl_dyn_addn(to, buf, charsize);
+ result = curlx_dyn_addn(to, buf, charsize);
}
}
return result;
@@ -449,7 +449,7 @@ static CURLcode encodeOID(struct dynbuf *store,
x = y / 40;
y -= x * 40;
- result = Curl_dyn_addf(store, "%u.%u", x, y);
+ result = curlx_dyn_addf(store, "%u.%u", x, y);
if(result)
return result;
@@ -462,7 +462,7 @@ static CURLcode encodeOID(struct dynbuf *store,
y = *(const unsigned char *) beg++;
x = (x << 7) | (y & 0x7F);
} while(y & 0x80);
- result = Curl_dyn_addf(store, ".%u", x);
+ result = curlx_dyn_addf(store, ".%u", x);
}
return result;
}
@@ -480,16 +480,16 @@ static CURLcode OID2str(struct dynbuf *store,
if(beg < end) {
if(symbolic) {
struct dynbuf buf;
- Curl_dyn_init(&buf, CURL_X509_STR_MAX);
+ curlx_dyn_init(&buf, CURL_X509_STR_MAX);
result = encodeOID(&buf, beg, end);
if(!result) {
- const struct Curl_OID *op = searchOID(Curl_dyn_ptr(&buf));
+ const struct Curl_OID *op = searchOID(curlx_dyn_ptr(&buf));
if(op)
- result = Curl_dyn_add(store, op->textoid);
+ result = curlx_dyn_add(store, op->textoid);
else
- result = Curl_dyn_add(store, Curl_dyn_ptr(&buf));
- Curl_dyn_free(&buf);
+ result = curlx_dyn_add(store, curlx_dyn_ptr(&buf));
+ curlx_dyn_free(&buf);
}
}
else
@@ -568,12 +568,12 @@ static CURLcode GTime2str(struct dynbuf *store,
tzl = end - tzp;
}
- return Curl_dyn_addf(store,
- "%.4s-%.2s-%.2s %.2s:%.2s:%c%c%s%.*s%s%.*s",
- beg, beg + 4, beg + 6,
- beg + 8, beg + 10, sec1, sec2,
- fracl ? ".": "", (int)fracl, fracp,
- sep, (int)tzl, tzp);
+ return curlx_dyn_addf(store,
+ "%.4s-%.2s-%.2s %.2s:%.2s:%c%c%s%.*s%s%.*s",
+ beg, beg + 4, beg + 6,
+ beg + 8, beg + 10, sec1, sec2,
+ fracl ? ".": "", (int)fracl, fracp,
+ sep, (int)tzl, tzp);
}
#ifdef UNITTESTS
@@ -622,10 +622,10 @@ static CURLcode UTime2str(struct dynbuf *store,
tzp++;
tzl = end - tzp;
- return Curl_dyn_addf(store, "%u%.2s-%.2s-%.2s %.2s:%.2s:%.2s %.*s",
- 20 - (*beg >= '5'), beg, beg + 2, beg + 4,
- beg + 6, beg + 8, sec,
- (int)tzl, tzp);
+ return curlx_dyn_addf(store, "%u%.2s-%.2s-%.2s %.2s:%.2s:%.2s %.*s",
+ 20 - (*beg >= '5'), beg, beg + 2, beg + 4,
+ beg + 6, beg + 8, sec,
+ (int)tzl, tzp);
}
/*
@@ -658,7 +658,7 @@ static CURLcode ASN1tostr(struct dynbuf *store,
result = octet2str(store, elem->beg, elem->end);
break;
case CURL_ASN1_NULL:
- result = Curl_dyn_addn(store, "", 1);
+ result = curlx_dyn_addn(store, "", 1);
break;
case CURL_ASN1_OBJECT_IDENTIFIER:
result = OID2str(store, elem->beg, elem->end, TRUE);
@@ -702,7 +702,7 @@ static CURLcode encodeDN(struct dynbuf *store, struct Curl_asn1Element *dn)
CURLcode result = CURLE_OK;
bool added = FALSE;
struct dynbuf temp;
- Curl_dyn_init(&temp, CURL_X509_STR_MAX);
+ curlx_dyn_init(&temp, CURL_X509_STR_MAX);
for(p1 = dn->beg; p1 < dn->end;) {
p1 = getASN1Element(&rdn, p1, dn->end);
@@ -725,12 +725,12 @@ static CURLcode encodeDN(struct dynbuf *store, struct Curl_asn1Element *dn)
result = CURLE_BAD_FUNCTION_ARGUMENT;
goto error;
}
- Curl_dyn_reset(&temp);
+ curlx_dyn_reset(&temp);
result = ASN1tostr(&temp, &oid, 0);
if(result)
goto error;
- str = Curl_dyn_ptr(&temp);
+ str = curlx_dyn_ptr(&temp);
if(!str) {
result = CURLE_BAD_FUNCTION_ARGUMENT;
@@ -743,20 +743,20 @@ static CURLcode encodeDN(struct dynbuf *store, struct Curl_asn1Element *dn)
;
if(added) {
if(p3 - str > 2)
- result = Curl_dyn_addn(store, "/", 1);
+ result = curlx_dyn_addn(store, "/", 1);
else
- result = Curl_dyn_addn(store, ", ", 2);
+ result = curlx_dyn_addn(store, ", ", 2);
if(result)
goto error;
}
/* Encode attribute name. */
- result = Curl_dyn_add(store, str);
+ result = curlx_dyn_add(store, str);
if(result)
goto error;
/* Generate equal sign. */
- result = Curl_dyn_addn(store, "=", 1);
+ result = curlx_dyn_addn(store, "=", 1);
if(result)
goto error;
@@ -764,12 +764,12 @@ static CURLcode encodeDN(struct dynbuf *store, struct Curl_asn1Element *dn)
result = ASN1tostr(store, &value, 0);
if(result)
goto error;
- Curl_dyn_reset(&temp);
+ curlx_dyn_reset(&temp);
added = TRUE; /* use separator for next */
}
}
error:
- Curl_dyn_free(&temp);
+ curlx_dyn_free(&temp);
return result;
}
@@ -947,8 +947,8 @@ static CURLcode ssl_push_certinfo_dyn(struct Curl_easy *data,
const char *label,
struct dynbuf *ptr)
{
- size_t valuelen = Curl_dyn_len(ptr);
- char *value = Curl_dyn_ptr(ptr);
+ size_t valuelen = curlx_dyn_len(ptr);
+ char *value = curlx_dyn_ptr(ptr);
CURLcode result = Curl_ssl_push_certinfo_len(data, certnum, label,
value, valuelen);
@@ -966,7 +966,7 @@ static CURLcode do_pubkey_field(struct Curl_easy *data, int certnum,
CURLcode result;
struct dynbuf out;
- Curl_dyn_init(&out, CURL_X509_STR_MAX);
+ curlx_dyn_init(&out, CURL_X509_STR_MAX);
/* Generate a certificate information record for the public key. */
@@ -974,7 +974,7 @@ static CURLcode do_pubkey_field(struct Curl_easy *data, int certnum,
if(!result) {
if(data->set.ssl.certinfo)
result = ssl_push_certinfo_dyn(data, certnum, label, &out);
- Curl_dyn_free(&out);
+ curlx_dyn_free(&out);
}
return result;
}
@@ -1110,7 +1110,7 @@ CURLcode Curl_extract_certinfo(struct Curl_easy *data,
if(certnum)
return CURLE_OK;
- Curl_dyn_init(&out, CURL_X509_STR_MAX);
+ curlx_dyn_init(&out, CURL_X509_STR_MAX);
/* Prepare the certificate information for curl_easy_getinfo(). */
/* Extract the certificate ASN.1 elements. */
@@ -1126,7 +1126,7 @@ CURLcode Curl_extract_certinfo(struct Curl_easy *data,
if(result)
goto done;
}
- Curl_dyn_reset(&out);
+ curlx_dyn_reset(&out);
/* Issuer. */
result = DNtostr(&out, &cert.issuer);
@@ -1137,20 +1137,20 @@ CURLcode Curl_extract_certinfo(struct Curl_easy *data,
if(result)
goto done;
}
- Curl_dyn_reset(&out);
+ curlx_dyn_reset(&out);
/* Version (always fits in less than 32 bits). */
version = 0;
for(ptr = cert.version.beg; ptr < cert.version.end; ptr++)
version = (version << 8) | *(const unsigned char *) ptr;
if(data->set.ssl.certinfo) {
- result = Curl_dyn_addf(&out, "%x", version);
+ result = curlx_dyn_addf(&out, "%x", version);
if(result)
goto done;
result = ssl_push_certinfo_dyn(data, certnum, "Version", &out);
if(result)
goto done;
- Curl_dyn_reset(&out);
+ curlx_dyn_reset(&out);
}
/* Serial number. */
@@ -1162,7 +1162,7 @@ CURLcode Curl_extract_certinfo(struct Curl_easy *data,
if(result)
goto done;
}
- Curl_dyn_reset(&out);
+ curlx_dyn_reset(&out);
/* Signature algorithm .*/
result = dumpAlgo(&out, &param, cert.signatureAlgorithm.beg,
@@ -1175,7 +1175,7 @@ CURLcode Curl_extract_certinfo(struct Curl_easy *data,
if(result)
goto done;
}
- Curl_dyn_reset(&out);
+ curlx_dyn_reset(&out);
/* Start Date. */
result = ASN1tostr(&out, &cert.notBefore, 0);
@@ -1186,7 +1186,7 @@ CURLcode Curl_extract_certinfo(struct Curl_easy *data,
if(result)
goto done;
}
- Curl_dyn_reset(&out);
+ curlx_dyn_reset(&out);
/* Expire Date. */
result = ASN1tostr(&out, &cert.notAfter, 0);
@@ -1197,7 +1197,7 @@ CURLcode Curl_extract_certinfo(struct Curl_easy *data,
if(result)
goto done;
}
- Curl_dyn_reset(&out);
+ curlx_dyn_reset(&out);
/* Public Key Algorithm. */
result = dumpAlgo(&out, &param, cert.subjectPublicKeyAlgorithm.beg,
@@ -1211,13 +1211,13 @@ CURLcode Curl_extract_certinfo(struct Curl_easy *data,
goto done;
}
- rc = do_pubkey(data, certnum, Curl_dyn_ptr(&out),
+ rc = do_pubkey(data, certnum, curlx_dyn_ptr(&out),
&param, &cert.subjectPublicKey);
if(rc) {
result = CURLE_OUT_OF_MEMORY; /* the most likely error */
goto done;
}
- Curl_dyn_reset(&out);
+ curlx_dyn_reset(&out);
/* Signature. */
result = ASN1tostr(&out, &cert.signature, 0);
@@ -1228,12 +1228,12 @@ CURLcode Curl_extract_certinfo(struct Curl_easy *data,
if(result)
goto done;
}
- Curl_dyn_reset(&out);
+ curlx_dyn_reset(&out);
/* Generate PEM certificate. */
- result = Curl_base64_encode(cert.certificate.beg,
- cert.certificate.end - cert.certificate.beg,
- &certptr, &clen);
+ result = curlx_base64_encode(cert.certificate.beg,
+ cert.certificate.end - cert.certificate.beg,
+ &certptr, &clen);
if(result)
goto done;
@@ -1246,22 +1246,22 @@ CURLcode Curl_extract_certinfo(struct Curl_easy *data,
-----END CERTIFICATE-----\n
*/
- Curl_dyn_reset(&out);
+ curlx_dyn_reset(&out);
/* Build the certificate string. */
- result = Curl_dyn_add(&out, "-----BEGIN CERTIFICATE-----\n");
+ result = curlx_dyn_add(&out, "-----BEGIN CERTIFICATE-----\n");
if(!result) {
size_t j = 0;
while(!result && (j < clen)) {
size_t chunksize = (clen - j) > 64 ? 64 : (clen - j);
- result = Curl_dyn_addn(&out, &certptr[j], chunksize);
+ result = curlx_dyn_addn(&out, &certptr[j], chunksize);
if(!result)
- result = Curl_dyn_addn(&out, "\n", 1);
+ result = curlx_dyn_addn(&out, "\n", 1);
j += chunksize;
}
if(!result)
- result = Curl_dyn_add(&out, "-----END CERTIFICATE-----\n");
+ result = curlx_dyn_add(&out, "-----END CERTIFICATE-----\n");
}
free(certptr);
if(!result)
@@ -1271,7 +1271,7 @@ CURLcode Curl_extract_certinfo(struct Curl_easy *data,
done:
if(result)
failf(data, "Failed extracting certificate chain");
- Curl_dyn_free(&out);
+ curlx_dyn_free(&out);
return result;
}
diff --git a/libs/libcurl/src/vtls/x509asn1.h b/libs/libcurl/src/vtls/x509asn1.h
index 34ba802d0f..3b933cb231 100644
--- a/libs/libcurl/src/vtls/x509asn1.h
+++ b/libs/libcurl/src/vtls/x509asn1.h
@@ -25,14 +25,14 @@
*
***************************************************************************/
-#include "curl_setup.h"
+#include "../curl_setup.h"
#if defined(USE_GNUTLS) || defined(USE_WOLFSSL) || \
defined(USE_SCHANNEL) || defined(USE_SECTRANSP) || \
defined(USE_MBEDTLS) || defined(USE_RUSTLS)
-#include "cfilters.h"
-#include "urldata.h"
+#include "../cfilters.h"
+#include "../urldata.h"
/*
* Types.
@@ -45,7 +45,7 @@ struct Curl_asn1Element {
const char *end; /* Pointer to 1st byte after element. */
unsigned char class; /* ASN.1 element class. */
unsigned char tag; /* ASN.1 element tag. */
- bool constructed; /* Element is constructed. */
+ BIT(constructed); /* Element is constructed. */
};
/* X509 certificate: RFC 5280. */
diff --git a/libs/libcurl/src/ws.c b/libs/libcurl/src/ws.c
index 1d641dfdb0..691710db06 100644
--- a/libs/libcurl/src/ws.c
+++ b/libs/libcurl/src/ws.c
@@ -27,10 +27,11 @@
#if !defined(CURL_DISABLE_WEBSOCKETS) && !defined(CURL_DISABLE_HTTP)
#include "urldata.h"
+#include "url.h"
#include "bufq.h"
-#include "dynbuf.h"
+#include "curlx/dynbuf.h"
#include "rand.h"
-#include "curl_base64.h"
+#include "curlx/base64.h"
#include "connect.h"
#include "sendf.h"
#include "multiif.h"
@@ -38,8 +39,8 @@
#include "easyif.h"
#include "transfer.h"
#include "select.h"
-#include "nonblock.h"
-#include "strparse.h"
+#include "curlx/nonblock.h"
+#include "curlx/strparse.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
@@ -76,6 +77,50 @@
#define WS_CHUNK_SIZE 65535
#define WS_CHUNK_COUNT 2
+
+/* a client-side WS frame decoder, parsing frame headers and
+ * payload, keeping track of current position and stats */
+enum ws_dec_state {
+ WS_DEC_INIT,
+ WS_DEC_HEAD,
+ WS_DEC_PAYLOAD
+};
+
+struct ws_decoder {
+ int frame_age; /* zero */
+ int frame_flags; /* See the CURLWS_* defines */
+ curl_off_t payload_offset; /* the offset parsing is at */
+ curl_off_t payload_len;
+ unsigned char head[10];
+ int head_len, head_total;
+ enum ws_dec_state state;
+ int cont_flags;
+};
+
+/* a client-side WS frame encoder, generating frame headers and
+ * converting payloads, tracking remaining data in current frame */
+struct ws_encoder {
+ curl_off_t payload_len; /* payload length of current frame */
+ curl_off_t payload_remain; /* remaining payload of current */
+ unsigned int xori; /* xor index */
+ unsigned char mask[4]; /* 32-bit mask for this connection */
+ unsigned char firstbyte; /* first byte of frame we encode */
+ BIT(contfragment); /* set TRUE if the previous fragment sent was not final */
+};
+
+/* A websocket connection with en- and decoder that treat frames
+ * and keep track of boundaries. */
+struct websocket {
+ struct Curl_easy *data; /* used for write callback handling */
+ struct ws_decoder dec; /* decode of we frames */
+ struct ws_encoder enc; /* decode of we frames */
+ struct bufq recvbuf; /* raw data from the server */
+ struct bufq sendbuf; /* raw data to be sent to the server */
+ struct curl_ws_frame frame; /* the current WS FRAME received */
+ size_t sendbuf_payload; /* number of payload bytes in sendbuf */
+};
+
+
static const char *ws_frame_name_of_op(unsigned char firstbyte)
{
switch(firstbyte & WSBIT_OPCODE_MASK) {
@@ -502,10 +547,12 @@ static ssize_t ws_cw_dec_next(const unsigned char *buf, size_t buflen,
struct ws_cw_dec_ctx *ctx = user_data;
struct Curl_easy *data = ctx->data;
struct websocket *ws = ctx->ws;
+ bool auto_pong = !data->set.ws_no_auto_pong;
curl_off_t remain = (payload_len - (payload_offset + buflen));
(void)frame_age;
- if((frame_flags & CURLWS_PING) && !remain) {
+
+ if(auto_pong && (frame_flags & CURLWS_PING) && !remain) {
/* auto-respond to PINGs, only works for single-frame payloads atm */
size_t bytes;
infof(data, "WS: auto-respond to PING with a PONG");
@@ -539,7 +586,7 @@ static CURLcode ws_cw_write(struct Curl_easy *data,
if(!(type & CLIENTWRITE_BODY) || data->set.ws_raw_mode)
return Curl_cwriter_write(data, writer->next, type, buf, nbytes);
- ws = data->conn->proto.ws;
+ ws = Curl_conn_meta_get(data->conn, CURL_META_PROTO_WS_CONN);
if(!ws) {
failf(data, "WS: not a websocket transfer");
return CURLE_FAILED_INIT;
@@ -776,18 +823,18 @@ CURLcode Curl_ws_request(struct Curl_easy *data, struct dynbuf *req)
{
/* The request MUST contain an |Upgrade| header field whose value
MUST include the "websocket" keyword. */
- "Upgrade:", "websocket"
+ "Upgrade", "websocket"
},
{
/* The request MUST contain a |Connection| header field whose value
MUST include the "Upgrade" token. */
- "Connection:", "Upgrade",
+ "Connection", "Upgrade",
},
{
/* The request MUST include a header field with the name
|Sec-WebSocket-Version|. The value of this header field MUST be
13. */
- "Sec-WebSocket-Version:", "13",
+ "Sec-WebSocket-Version", "13",
},
{
/* The request MUST include a header field with the name
@@ -795,7 +842,7 @@ CURLcode Curl_ws_request(struct Curl_easy *data, struct dynbuf *req)
consisting of a randomly selected 16-byte value that has been
base64-encoded (see Section 4 of [RFC4648]). The nonce MUST be
selected randomly for each connection. */
- "Sec-WebSocket-Key:", NULL,
+ "Sec-WebSocket-Key", NULL,
}
};
heads[3].val = &keyval[0];
@@ -804,7 +851,7 @@ CURLcode Curl_ws_request(struct Curl_easy *data, struct dynbuf *req)
result = Curl_rand(data, (unsigned char *)rand, sizeof(rand));
if(result)
return result;
- result = Curl_base64_encode((char *)rand, sizeof(rand), &randstr, &randlen);
+ result = curlx_base64_encode((char *)rand, sizeof(rand), &randstr, &randlen);
if(result)
return result;
DEBUGASSERT(randlen < sizeof(keyval));
@@ -815,15 +862,25 @@ CURLcode Curl_ws_request(struct Curl_easy *data, struct dynbuf *req)
strcpy(keyval, randstr);
free(randstr);
for(i = 0; !result && (i < CURL_ARRAYSIZE(heads)); i++) {
- if(!Curl_checkheaders(data, STRCONST(heads[i].name))) {
- result = Curl_dyn_addf(req, "%s %s\r\n", heads[i].name,
- heads[i].val);
+ if(!Curl_checkheaders(data, heads[i].name, strlen(heads[i].name))) {
+ result = curlx_dyn_addf(req, "%s: %s\r\n", heads[i].name,
+ heads[i].val);
}
}
k->upgr101 = UPGR101_WS;
return result;
}
+static void ws_conn_dtor(void *key, size_t klen, void *entry)
+{
+ struct websocket *ws = entry;
+ (void)key;
+ (void)klen;
+ Curl_bufq_free(&ws->recvbuf);
+ Curl_bufq_free(&ws->sendbuf);
+ free(ws);
+}
+
/*
* 'nread' is number of bytes of websocket data already in the buffer at
* 'mem'.
@@ -837,19 +894,18 @@ CURLcode Curl_ws_accept(struct Curl_easy *data,
CURLcode result;
DEBUGASSERT(data->conn);
- ws = data->conn->proto.ws;
+ ws = Curl_conn_meta_get(data->conn, CURL_META_PROTO_WS_CONN);
if(!ws) {
size_t chunk_size = WS_CHUNK_SIZE;
ws = calloc(1, sizeof(*ws));
if(!ws)
return CURLE_OUT_OF_MEMORY;
- data->conn->proto.ws = ws;
#ifdef DEBUGBUILD
{
const char *p = getenv("CURL_WS_CHUNK_SIZE");
if(p) {
curl_off_t l;
- if(!Curl_str_number(&p, &l, 1*1024*1024))
+ if(!curlx_str_number(&p, &l, 1*1024*1024))
chunk_size = (size_t)l;
}
}
@@ -861,6 +917,10 @@ CURLcode Curl_ws_accept(struct Curl_easy *data,
BUFQ_OPT_SOFT_LIMIT);
ws_dec_init(&ws->dec);
ws_enc_init(&ws->enc);
+ result = Curl_conn_meta_set(data->conn, CURL_META_PROTO_WS_CONN,
+ ws, ws_conn_dtor);
+ if(result)
+ return result;
}
else {
Curl_bufq_reset(&ws->recvbuf);
@@ -949,6 +1009,8 @@ static ssize_t ws_client_collect(const unsigned char *buf, size_t buflen,
CURLcode *err)
{
struct ws_collect *ctx = userp;
+ struct Curl_easy *data = ctx->data;
+ bool auto_pong = !data->set.ws_no_auto_pong;
size_t nwritten;
curl_off_t remain = (payload_len - (payload_offset + buflen));
@@ -960,7 +1022,7 @@ static ssize_t ws_client_collect(const unsigned char *buf, size_t buflen,
ctx->payload_len = payload_len;
}
- if((frame_flags & CURLWS_PING) && !remain) {
+ if(auto_pong && (frame_flags & CURLWS_PING) && !remain) {
/* auto-respond to PINGs, only works for single-frame payloads atm */
size_t bytes;
infof(ctx->data, "WS: auto-respond to PING with a PONG");
@@ -1027,7 +1089,7 @@ CURL_EXTERN CURLcode curl_ws_recv(CURL *d, void *buffer,
return CURLE_BAD_FUNCTION_ARGUMENT;
}
}
- ws = conn->proto.ws;
+ ws = Curl_conn_meta_get(conn, CURL_META_PROTO_WS_CONN);
if(!ws) {
failf(data, "connection is not setup for websocket");
return CURLE_BAD_FUNCTION_ARGUMENT;
@@ -1102,7 +1164,7 @@ static CURLcode ws_flush(struct Curl_easy *data, struct websocket *ws,
const char *p = getenv("CURL_WS_CHUNK_EAGAIN");
if(p) {
curl_off_t l;
- if(!Curl_str_number(&p, &l, 1*1024*1024))
+ if(!curlx_str_number(&p, &l, 1*1024*1024))
chunk_egain = (size_t)l;
}
#endif
@@ -1191,9 +1253,10 @@ static CURLcode ws_send_raw_blocking(CURL *d, struct websocket *ws,
static CURLcode ws_send_raw(struct Curl_easy *data, const void *buffer,
size_t buflen, size_t *pnwritten)
{
- struct websocket *ws = data->conn->proto.ws;
+ struct websocket *ws;
CURLcode result;
+ ws = Curl_conn_meta_get(data->conn, CURL_META_PROTO_WS_CONN);
if(!ws) {
failf(data, "Not a websocket transfer");
return CURLE_SEND_ERROR;
@@ -1249,12 +1312,12 @@ CURL_EXTERN CURLcode curl_ws_send(CURL *d, const void *buffer_arg,
result = CURLE_SEND_ERROR;
goto out;
}
- if(!data->conn->proto.ws) {
+ ws = Curl_conn_meta_get(data->conn, CURL_META_PROTO_WS_CONN);
+ if(!ws) {
failf(data, "Not a websocket transfer");
result = CURLE_SEND_ERROR;
goto out;
}
- ws = data->conn->proto.ws;
if(data->set.ws_raw_mode) {
/* In raw mode, we write directly to the connection */
@@ -1362,15 +1425,6 @@ out:
return result;
}
-static void ws_free(struct connectdata *conn)
-{
- if(conn && conn->proto.ws) {
- Curl_bufq_free(&conn->proto.ws->recvbuf);
- Curl_bufq_free(&conn->proto.ws->sendbuf);
- Curl_safefree(conn->proto.ws);
- }
-}
-
static CURLcode ws_setup_conn(struct Curl_easy *data,
struct connectdata *conn)
{
@@ -1383,24 +1437,19 @@ static CURLcode ws_setup_conn(struct Curl_easy *data,
}
-static CURLcode ws_disconnect(struct Curl_easy *data,
- struct connectdata *conn,
- bool dead_connection)
-{
- (void)data;
- (void)dead_connection;
- ws_free(conn);
- return CURLE_OK;
-}
-
CURL_EXTERN const struct curl_ws_frame *curl_ws_meta(CURL *d)
{
/* we only return something for websocket, called from within the callback
when not using raw mode */
struct Curl_easy *data = d;
- if(GOOD_EASY_HANDLE(data) && Curl_is_in_callback(data) && data->conn &&
- data->conn->proto.ws && !data->set.ws_raw_mode)
- return &data->conn->proto.ws->frame;
+ if(GOOD_EASY_HANDLE(data) && Curl_is_in_callback(data) &&
+ data->conn && !data->set.ws_raw_mode) {
+ struct websocket *ws;
+ ws = Curl_conn_meta_get(data->conn, CURL_META_PROTO_WS_CONN);
+ if(ws)
+ return &ws->frame;
+
+ }
return NULL;
}
@@ -1417,7 +1466,7 @@ const struct Curl_handler Curl_handler_ws = {
Curl_http_getsock_do, /* doing_getsock */
ZERO_NULL, /* domore_getsock */
ZERO_NULL, /* perform_getsock */
- ws_disconnect, /* disconnect */
+ ZERO_NULL, /* disconnect */
Curl_http_write_resp, /* write_resp */
Curl_http_write_resp_hd, /* write_resp_hd */
ZERO_NULL, /* connection_check */
@@ -1444,7 +1493,7 @@ const struct Curl_handler Curl_handler_wss = {
Curl_http_getsock_do, /* doing_getsock */
ZERO_NULL, /* domore_getsock */
ZERO_NULL, /* perform_getsock */
- ws_disconnect, /* disconnect */
+ ZERO_NULL, /* disconnect */
Curl_http_write_resp, /* write_resp */
Curl_http_write_resp_hd, /* write_resp_hd */
ZERO_NULL, /* connection_check */
diff --git a/libs/libcurl/src/ws.h b/libs/libcurl/src/ws.h
index f6aaa7936f..9b456ae4f9 100644
--- a/libs/libcurl/src/ws.h
+++ b/libs/libcurl/src/ws.h
@@ -27,47 +27,8 @@
#if !defined(CURL_DISABLE_WEBSOCKETS) && !defined(CURL_DISABLE_HTTP)
-/* a client-side WS frame decoder, parsing frame headers and
- * payload, keeping track of current position and stats */
-enum ws_dec_state {
- WS_DEC_INIT,
- WS_DEC_HEAD,
- WS_DEC_PAYLOAD
-};
-
-struct ws_decoder {
- int frame_age; /* zero */
- int frame_flags; /* See the CURLWS_* defines */
- curl_off_t payload_offset; /* the offset parsing is at */
- curl_off_t payload_len;
- unsigned char head[10];
- int head_len, head_total;
- enum ws_dec_state state;
- int cont_flags;
-};
-
-/* a client-side WS frame encoder, generating frame headers and
- * converting payloads, tracking remaining data in current frame */
-struct ws_encoder {
- curl_off_t payload_len; /* payload length of current frame */
- curl_off_t payload_remain; /* remaining payload of current */
- unsigned int xori; /* xor index */
- unsigned char mask[4]; /* 32-bit mask for this connection */
- unsigned char firstbyte; /* first byte of frame we encode */
- BIT(contfragment); /* set TRUE if the previous fragment sent was not final */
-};
-
-/* A websocket connection with en- and decoder that treat frames
- * and keep track of boundaries. */
-struct websocket {
- struct Curl_easy *data; /* used for write callback handling */
- struct ws_decoder dec; /* decode of we frames */
- struct ws_encoder enc; /* decode of we frames */
- struct bufq recvbuf; /* raw data from the server */
- struct bufq sendbuf; /* raw data to be sent to the server */
- struct curl_ws_frame frame; /* the current WS FRAME received */
- size_t sendbuf_payload; /* number of payload bytes in sendbuf */
-};
+/* meta key for storing protocol meta at connection */
+#define CURL_META_PROTO_WS_CONN "meta:proto:ws:conn"
CURLcode Curl_ws_request(struct Curl_easy *data, struct dynbuf *req);
CURLcode Curl_ws_accept(struct Curl_easy *data, const char *mem, size_t len);