summaryrefslogtreecommitdiff
path: root/Utilities
diff options
context:
space:
mode:
authorDongHun Kwak <dh0128.kwak@samsung.com>2021-10-08 09:20:44 +0900
committerDongHun Kwak <dh0128.kwak@samsung.com>2021-10-08 09:20:44 +0900
commit99a800848c2512f7c93504fc7b28e6182a6ceb93 (patch)
tree0236502664965e5284d0c950ed2c1bf294b1233b /Utilities
parentdf4ed7977a77409f899f6f05389960f6b73125a8 (diff)
downloadcmake-99a800848c2512f7c93504fc7b28e6182a6ceb93.tar.gz
cmake-99a800848c2512f7c93504fc7b28e6182a6ceb93.tar.bz2
cmake-99a800848c2512f7c93504fc7b28e6182a6ceb93.zip
Imported Upstream version 3.20.0upstream/3.20.0
Diffstat (limited to 'Utilities')
-rw-r--r--Utilities/Doxygen/CMakeLists.txt2
-rw-r--r--Utilities/Release/README.rst17
-rwxr-xr-xUtilities/Release/files-sign.bash5
-rw-r--r--Utilities/Release/files-v1.json.in106
-rw-r--r--Utilities/Release/files-v1.rst166
-rwxr-xr-xUtilities/Release/files.bash84
-rw-r--r--Utilities/Release/linux/aarch64/Dockerfile4
-rw-r--r--Utilities/Release/linux/aarch64/cache.txt2
-rw-r--r--Utilities/Release/linux/x86_64/Dockerfile4
-rw-r--r--Utilities/Release/linux/x86_64/cache.txt2
-rw-r--r--Utilities/Release/win/x86/cache-i386.txt2
-rw-r--r--Utilities/Release/win/x86/cache-x86_64.txt2
-rwxr-xr-xUtilities/Scripts/regenerate-parsers.bash7
-rwxr-xr-xUtilities/Scripts/update-curl.bash2
-rw-r--r--Utilities/Sphinx/CMakeLists.txt2
-rw-r--r--Utilities/Sphinx/cmake.py21
-rw-r--r--Utilities/Sphinx/conf.py.in1
-rwxr-xr-xUtilities/Sphinx/create_identifiers.py1
-rw-r--r--Utilities/Sphinx/static/cmake.css6
-rw-r--r--Utilities/cmbzip2/CMakeLists.txt2
-rw-r--r--Utilities/cmcurl/CMake/CMakeConfigurableFile.in2
-rw-r--r--Utilities/cmcurl/CMake/CurlSymbolHiding.cmake4
-rw-r--r--Utilities/cmcurl/CMake/CurlTests.c4
-rw-r--r--Utilities/cmcurl/CMake/FindBearSSL.cmake2
-rw-r--r--Utilities/cmcurl/CMake/FindBrotli.cmake2
-rw-r--r--Utilities/cmcurl/CMake/FindCARES.cmake2
-rw-r--r--Utilities/cmcurl/CMake/FindGSS.cmake2
-rw-r--r--Utilities/cmcurl/CMake/FindLibSSH2.cmake2
-rw-r--r--Utilities/cmcurl/CMake/FindMbedTLS.cmake2
-rw-r--r--Utilities/cmcurl/CMake/FindNGHTTP2.cmake2
-rw-r--r--Utilities/cmcurl/CMake/FindNGHTTP3.cmake2
-rw-r--r--Utilities/cmcurl/CMake/FindNGTCP2.cmake2
-rw-r--r--Utilities/cmcurl/CMake/FindNSS.cmake2
-rw-r--r--Utilities/cmcurl/CMake/FindQUICHE.cmake2
-rw-r--r--Utilities/cmcurl/CMake/FindWolfSSL.cmake2
-rw-r--r--Utilities/cmcurl/CMake/FindZstd.cmake2
-rw-r--r--Utilities/cmcurl/CMake/Macros.cmake13
-rw-r--r--Utilities/cmcurl/CMake/OtherTests.cmake2
-rw-r--r--Utilities/cmcurl/CMake/Platforms/WindowsCache.cmake2
-rw-r--r--Utilities/cmcurl/CMake/Utilities.cmake2
-rw-r--r--Utilities/cmcurl/CMake/cmake_uninstall.cmake.in2
-rw-r--r--Utilities/cmcurl/CMake/curl-config.cmake.in2
-rw-r--r--Utilities/cmcurl/CMakeLists.txt115
-rw-r--r--Utilities/cmcurl/COPYING2
-rw-r--r--Utilities/cmcurl/include/curl/curl.h207
-rw-r--r--Utilities/cmcurl/include/curl/curlver.h8
-rw-r--r--Utilities/cmcurl/include/curl/easy.h2
-rw-r--r--Utilities/cmcurl/include/curl/mprintf.h4
-rw-r--r--Utilities/cmcurl/include/curl/multi.h2
-rw-r--r--Utilities/cmcurl/include/curl/options.h68
-rw-r--r--Utilities/cmcurl/include/curl/stdcheaders.h4
-rw-r--r--Utilities/cmcurl/include/curl/system.h4
-rw-r--r--Utilities/cmcurl/include/curl/typecheck-gcc.h9
-rw-r--r--Utilities/cmcurl/include/curl/urlapi.h4
-rw-r--r--Utilities/cmcurl/lib/CMakeLists.txt13
-rw-r--r--Utilities/cmcurl/lib/Makefile.inc353
-rw-r--r--Utilities/cmcurl/lib/altsvc.c36
-rw-r--r--Utilities/cmcurl/lib/altsvc.h13
-rw-r--r--Utilities/cmcurl/lib/amigaos.c4
-rw-r--r--Utilities/cmcurl/lib/amigaos.h4
-rw-r--r--Utilities/cmcurl/lib/arpa_telnet.h4
-rw-r--r--Utilities/cmcurl/lib/asyn-ares.c167
-rw-r--r--Utilities/cmcurl/lib/asyn-thread.c160
-rw-r--r--Utilities/cmcurl/lib/asyn.h16
-rw-r--r--Utilities/cmcurl/lib/base64.c7
-rw-r--r--Utilities/cmcurl/lib/c-hyper.c908
-rw-r--r--Utilities/cmcurl/lib/c-hyper.h56
-rw-r--r--Utilities/cmcurl/lib/conncache.c79
-rw-r--r--Utilities/cmcurl/lib/conncache.h48
-rw-r--r--Utilities/cmcurl/lib/connect.c337
-rw-r--r--Utilities/cmcurl/lib/connect.h25
-rw-r--r--Utilities/cmcurl/lib/content_encoding.c178
-rw-r--r--Utilities/cmcurl/lib/content_encoding.h16
-rw-r--r--Utilities/cmcurl/lib/cookie.c13
-rw-r--r--Utilities/cmcurl/lib/cookie.h8
-rw-r--r--Utilities/cmcurl/lib/curl_addrinfo.c6
-rw-r--r--Utilities/cmcurl/lib/curl_addrinfo.h2
-rw-r--r--Utilities/cmcurl/lib/curl_base64.h4
-rw-r--r--Utilities/cmcurl/lib/curl_config.h.cmake26
-rw-r--r--Utilities/cmcurl/lib/curl_ctype.c4
-rw-r--r--Utilities/cmcurl/lib/curl_ctype.h4
-rw-r--r--Utilities/cmcurl/lib/curl_des.c4
-rw-r--r--Utilities/cmcurl/lib/curl_des.h4
-rw-r--r--Utilities/cmcurl/lib/curl_endian.c4
-rw-r--r--Utilities/cmcurl/lib/curl_endian.h4
-rw-r--r--Utilities/cmcurl/lib/curl_fnmatch.c4
-rw-r--r--Utilities/cmcurl/lib/curl_fnmatch.h4
-rw-r--r--Utilities/cmcurl/lib/curl_get_line.c9
-rw-r--r--Utilities/cmcurl/lib/curl_get_line.h4
-rw-r--r--Utilities/cmcurl/lib/curl_gethostname.c6
-rw-r--r--Utilities/cmcurl/lib/curl_gethostname.h6
-rw-r--r--Utilities/cmcurl/lib/curl_gssapi.c8
-rw-r--r--Utilities/cmcurl/lib/curl_gssapi.h4
-rw-r--r--Utilities/cmcurl/lib/curl_hmac.h2
-rw-r--r--Utilities/cmcurl/lib/curl_krb5.h (renamed from Utilities/cmcurl/lib/curl_sec.h)20
-rw-r--r--Utilities/cmcurl/lib/curl_ldap.h4
-rw-r--r--Utilities/cmcurl/lib/curl_md4.h2
-rw-r--r--Utilities/cmcurl/lib/curl_md5.h2
-rw-r--r--Utilities/cmcurl/lib/curl_memory.h4
-rw-r--r--Utilities/cmcurl/lib/curl_memrchr.c4
-rw-r--r--Utilities/cmcurl/lib/curl_memrchr.h4
-rw-r--r--Utilities/cmcurl/lib/curl_multibyte.c2
-rw-r--r--Utilities/cmcurl/lib/curl_multibyte.h2
-rw-r--r--Utilities/cmcurl/lib/curl_ntlm_core.c18
-rw-r--r--Utilities/cmcurl/lib/curl_ntlm_core.h10
-rw-r--r--Utilities/cmcurl/lib/curl_ntlm_wb.c31
-rw-r--r--Utilities/cmcurl/lib/curl_ntlm_wb.h10
-rw-r--r--Utilities/cmcurl/lib/curl_path.c15
-rw-r--r--Utilities/cmcurl/lib/curl_path.h6
-rw-r--r--Utilities/cmcurl/lib/curl_printf.h4
-rw-r--r--Utilities/cmcurl/lib/curl_range.c7
-rw-r--r--Utilities/cmcurl/lib/curl_range.h7
-rw-r--r--Utilities/cmcurl/lib/curl_rtmp.c56
-rw-r--r--Utilities/cmcurl/lib/curl_rtmp.h4
-rw-r--r--Utilities/cmcurl/lib/curl_sasl.c38
-rw-r--r--Utilities/cmcurl/lib/curl_sasl.h16
-rw-r--r--Utilities/cmcurl/lib/curl_setup.h36
-rw-r--r--Utilities/cmcurl/lib/curl_setup_once.h2
-rw-r--r--Utilities/cmcurl/lib/curl_sha256.h5
-rw-r--r--Utilities/cmcurl/lib/curl_sspi.c2
-rw-r--r--Utilities/cmcurl/lib/curl_sspi.h4
-rw-r--r--Utilities/cmcurl/lib/curl_threads.c8
-rw-r--r--Utilities/cmcurl/lib/curl_threads.h4
-rw-r--r--Utilities/cmcurl/lib/curlx.h2
-rw-r--r--Utilities/cmcurl/lib/dict.c104
-rw-r--r--Utilities/cmcurl/lib/dict.h4
-rw-r--r--Utilities/cmcurl/lib/doh.c107
-rw-r--r--Utilities/cmcurl/lib/doh.h8
-rw-r--r--Utilities/cmcurl/lib/dotdot.c2
-rw-r--r--Utilities/cmcurl/lib/dotdot.h4
-rw-r--r--Utilities/cmcurl/lib/dynbuf.c50
-rw-r--r--Utilities/cmcurl/lib/dynbuf.h27
-rw-r--r--Utilities/cmcurl/lib/easy.c92
-rw-r--r--Utilities/cmcurl/lib/easygetopt.c96
-rw-r--r--Utilities/cmcurl/lib/easyif.h2
-rw-r--r--Utilities/cmcurl/lib/easyoptions.c354
-rw-r--r--Utilities/cmcurl/lib/easyoptions.h35
-rw-r--r--Utilities/cmcurl/lib/escape.c4
-rw-r--r--Utilities/cmcurl/lib/escape.h2
-rw-r--r--Utilities/cmcurl/lib/file.c111
-rw-r--r--Utilities/cmcurl/lib/file.h4
-rw-r--r--Utilities/cmcurl/lib/fileinfo.c4
-rw-r--r--Utilities/cmcurl/lib/fileinfo.h6
-rw-r--r--Utilities/cmcurl/lib/formdata.c2
-rw-r--r--Utilities/cmcurl/lib/formdata.h12
-rw-r--r--Utilities/cmcurl/lib/ftp.c1404
-rw-r--r--Utilities/cmcurl/lib/ftp.h17
-rw-r--r--Utilities/cmcurl/lib/ftplistparser.c38
-rw-r--r--Utilities/cmcurl/lib/ftplistparser.h4
-rw-r--r--Utilities/cmcurl/lib/getenv.c2
-rw-r--r--Utilities/cmcurl/lib/getinfo.c7
-rw-r--r--Utilities/cmcurl/lib/getinfo.h4
-rw-r--r--Utilities/cmcurl/lib/gopher.c76
-rw-r--r--Utilities/cmcurl/lib/gopher.h7
-rw-r--r--Utilities/cmcurl/lib/hash.c86
-rw-r--r--Utilities/cmcurl/lib/hash.h50
-rw-r--r--Utilities/cmcurl/lib/hmac.c2
-rw-r--r--Utilities/cmcurl/lib/hostasyn.c22
-rw-r--r--Utilities/cmcurl/lib/hostcheck.c4
-rw-r--r--Utilities/cmcurl/lib/hostcheck.h4
-rw-r--r--Utilities/cmcurl/lib/hostip.c118
-rw-r--r--Utilities/cmcurl/lib/hostip.h35
-rw-r--r--Utilities/cmcurl/lib/hostip4.c13
-rw-r--r--Utilities/cmcurl/lib/hostip6.c32
-rw-r--r--Utilities/cmcurl/lib/hostsyn.c4
-rw-r--r--Utilities/cmcurl/lib/hsts.c522
-rw-r--r--Utilities/cmcurl/lib/hsts.h65
-rw-r--r--Utilities/cmcurl/lib/http.c2491
-rw-r--r--Utilities/cmcurl/lib/http.h90
-rw-r--r--Utilities/cmcurl/lib/http2.c367
-rw-r--r--Utilities/cmcurl/lib/http2.h17
-rw-r--r--Utilities/cmcurl/lib/http_aws_sigv4.c394
-rw-r--r--Utilities/cmcurl/lib/http_aws_sigv4.h29
-rw-r--r--Utilities/cmcurl/lib/http_chunks.c45
-rw-r--r--Utilities/cmcurl/lib/http_chunks.h23
-rw-r--r--Utilities/cmcurl/lib/http_digest.c12
-rw-r--r--Utilities/cmcurl/lib/http_digest.h9
-rw-r--r--Utilities/cmcurl/lib/http_negotiate.c25
-rw-r--r--Utilities/cmcurl/lib/http_negotiate.h11
-rw-r--r--Utilities/cmcurl/lib/http_ntlm.c36
-rw-r--r--Utilities/cmcurl/lib/http_ntlm.h8
-rw-r--r--Utilities/cmcurl/lib/http_proxy.c412
-rw-r--r--Utilities/cmcurl/lib/http_proxy.h8
-rw-r--r--Utilities/cmcurl/lib/idn_win32.c2
-rw-r--r--Utilities/cmcurl/lib/if2ip.c2
-rw-r--r--Utilities/cmcurl/lib/if2ip.h4
-rw-r--r--Utilities/cmcurl/lib/imap.c511
-rw-r--r--Utilities/cmcurl/lib/imap.h7
-rw-r--r--Utilities/cmcurl/lib/inet_ntop.h4
-rw-r--r--Utilities/cmcurl/lib/inet_pton.c4
-rw-r--r--Utilities/cmcurl/lib/inet_pton.h4
-rw-r--r--Utilities/cmcurl/lib/krb5.c607
-rw-r--r--Utilities/cmcurl/lib/ldap.c150
-rw-r--r--Utilities/cmcurl/lib/libcurl.rc8
-rw-r--r--Utilities/cmcurl/lib/llist.c14
-rw-r--r--Utilities/cmcurl/lib/llist.h30
-rw-r--r--Utilities/cmcurl/lib/md4.c2
-rw-r--r--Utilities/cmcurl/lib/md5.c2
-rw-r--r--Utilities/cmcurl/lib/memdebug.c53
-rw-r--r--Utilities/cmcurl/lib/memdebug.h2
-rw-r--r--Utilities/cmcurl/lib/mime.c5
-rw-r--r--Utilities/cmcurl/lib/mime.h6
-rw-r--r--Utilities/cmcurl/lib/mprintf.c57
-rw-r--r--Utilities/cmcurl/lib/mqtt.c189
-rw-r--r--Utilities/cmcurl/lib/mqtt.h4
-rw-r--r--Utilities/cmcurl/lib/multi.c311
-rw-r--r--Utilities/cmcurl/lib/multihandle.h24
-rw-r--r--Utilities/cmcurl/lib/multiif.h6
-rw-r--r--Utilities/cmcurl/lib/netrc.c4
-rw-r--r--Utilities/cmcurl/lib/netrc.h4
-rw-r--r--Utilities/cmcurl/lib/non-ascii.c4
-rw-r--r--Utilities/cmcurl/lib/non-ascii.h4
-rw-r--r--Utilities/cmcurl/lib/nonblock.c4
-rw-r--r--Utilities/cmcurl/lib/nonblock.h4
-rw-r--r--Utilities/cmcurl/lib/nwlib.c2
-rw-r--r--Utilities/cmcurl/lib/nwos.c4
-rw-r--r--Utilities/cmcurl/lib/openldap.c102
-rw-r--r--Utilities/cmcurl/lib/parsedate.c59
-rw-r--r--Utilities/cmcurl/lib/parsedate.h4
-rw-r--r--Utilities/cmcurl/lib/pingpong.c127
-rw-r--r--Utilities/cmcurl/lib/pingpong.h48
-rw-r--r--Utilities/cmcurl/lib/pop3.c374
-rw-r--r--Utilities/cmcurl/lib/pop3.h8
-rw-r--r--Utilities/cmcurl/lib/progress.c37
-rw-r--r--Utilities/cmcurl/lib/progress.h10
-rw-r--r--Utilities/cmcurl/lib/psl.c4
-rw-r--r--Utilities/cmcurl/lib/psl.h4
-rw-r--r--Utilities/cmcurl/lib/quic.h19
-rw-r--r--Utilities/cmcurl/lib/rand.c4
-rw-r--r--Utilities/cmcurl/lib/rand.h4
-rw-r--r--Utilities/cmcurl/lib/rename.c6
-rw-r--r--Utilities/cmcurl/lib/rename.h2
-rw-r--r--Utilities/cmcurl/lib/rtsp.c151
-rw-r--r--Utilities/cmcurl/lib/rtsp.h10
-rw-r--r--Utilities/cmcurl/lib/security.c579
-rw-r--r--Utilities/cmcurl/lib/select.c194
-rw-r--r--Utilities/cmcurl/lib/select.h25
-rw-r--r--Utilities/cmcurl/lib/sendf.c252
-rw-r--r--Utilities/cmcurl/lib/sendf.h19
-rw-r--r--Utilities/cmcurl/lib/setopt.c335
-rw-r--r--Utilities/cmcurl/lib/setopt.h2
-rw-r--r--Utilities/cmcurl/lib/setup-os400.h2
-rw-r--r--Utilities/cmcurl/lib/setup-vms.h2
-rw-r--r--Utilities/cmcurl/lib/setup-win32.h5
-rw-r--r--Utilities/cmcurl/lib/sha256.c35
-rw-r--r--Utilities/cmcurl/lib/share.c13
-rw-r--r--Utilities/cmcurl/lib/share.h12
-rw-r--r--Utilities/cmcurl/lib/sigpipe.h4
-rw-r--r--Utilities/cmcurl/lib/slist.c4
-rw-r--r--Utilities/cmcurl/lib/slist.h4
-rw-r--r--Utilities/cmcurl/lib/smb.c276
-rw-r--r--Utilities/cmcurl/lib/smb.h11
-rw-r--r--Utilities/cmcurl/lib/smtp.c416
-rw-r--r--Utilities/cmcurl/lib/smtp.h8
-rw-r--r--Utilities/cmcurl/lib/sockaddr.h4
-rw-r--r--Utilities/cmcurl/lib/socketpair.c6
-rw-r--r--Utilities/cmcurl/lib/socketpair.h4
-rw-r--r--Utilities/cmcurl/lib/socks.c295
-rw-r--r--Utilities/cmcurl/lib/socks.h34
-rw-r--r--Utilities/cmcurl/lib/socks_gssapi.c32
-rw-r--r--Utilities/cmcurl/lib/socks_sspi.c44
-rw-r--r--Utilities/cmcurl/lib/speedcheck.c8
-rw-r--r--Utilities/cmcurl/lib/speedcheck.h4
-rw-r--r--Utilities/cmcurl/lib/splay.c10
-rw-r--r--Utilities/cmcurl/lib/splay.h16
-rw-r--r--Utilities/cmcurl/lib/strcase.c2
-rw-r--r--Utilities/cmcurl/lib/strcase.h2
-rw-r--r--Utilities/cmcurl/lib/strdup.c2
-rw-r--r--Utilities/cmcurl/lib/strdup.h4
-rw-r--r--Utilities/cmcurl/lib/strerror.c48
-rw-r--r--Utilities/cmcurl/lib/strerror.h2
-rw-r--r--Utilities/cmcurl/lib/strtok.c2
-rw-r--r--Utilities/cmcurl/lib/strtok.h4
-rw-r--r--Utilities/cmcurl/lib/strtoofft.c4
-rw-r--r--Utilities/cmcurl/lib/strtoofft.h4
-rw-r--r--Utilities/cmcurl/lib/system_win32.c15
-rw-r--r--Utilities/cmcurl/lib/system_win32.h2
-rw-r--r--Utilities/cmcurl/lib/telnet.c342
-rw-r--r--Utilities/cmcurl/lib/telnet.h4
-rw-r--r--Utilities/cmcurl/lib/tftp.c158
-rw-r--r--Utilities/cmcurl/lib/tftp.h4
-rw-r--r--Utilities/cmcurl/lib/timeval.c2
-rw-r--r--Utilities/cmcurl/lib/timeval.h4
-rw-r--r--Utilities/cmcurl/lib/transfer.c240
-rw-r--r--Utilities/cmcurl/lib/transfer.h23
-rw-r--r--Utilities/cmcurl/lib/url.c499
-rw-r--r--Utilities/cmcurl/lib/url.h28
-rw-r--r--Utilities/cmcurl/lib/urlapi-int.h6
-rw-r--r--Utilities/cmcurl/lib/urlapi.c62
-rw-r--r--Utilities/cmcurl/lib/urldata.h294
-rw-r--r--Utilities/cmcurl/lib/vauth/cleartext.c2
-rw-r--r--Utilities/cmcurl/lib/vauth/cram.c2
-rw-r--r--Utilities/cmcurl/lib/vauth/digest.c16
-rw-r--r--Utilities/cmcurl/lib/vauth/digest.h4
-rw-r--r--Utilities/cmcurl/lib/vauth/digest_sspi.c17
-rw-r--r--Utilities/cmcurl/lib/vauth/krb5_gssapi.c4
-rw-r--r--Utilities/cmcurl/lib/vauth/krb5_sspi.c4
-rw-r--r--Utilities/cmcurl/lib/vauth/ntlm.c3
-rw-r--r--Utilities/cmcurl/lib/vauth/ntlm.h4
-rw-r--r--Utilities/cmcurl/lib/vauth/ntlm_sspi.c4
-rw-r--r--Utilities/cmcurl/lib/vauth/oauth2.c4
-rw-r--r--Utilities/cmcurl/lib/vauth/spnego_gssapi.c4
-rw-r--r--Utilities/cmcurl/lib/vauth/spnego_sspi.c4
-rw-r--r--Utilities/cmcurl/lib/vauth/vauth.c2
-rw-r--r--Utilities/cmcurl/lib/vauth/vauth.h4
-rw-r--r--Utilities/cmcurl/lib/version.c50
-rw-r--r--Utilities/cmcurl/lib/version_win32.c2
-rw-r--r--Utilities/cmcurl/lib/version_win32.h2
-rw-r--r--Utilities/cmcurl/lib/vquic/ngtcp2.c343
-rw-r--r--Utilities/cmcurl/lib/vquic/ngtcp2.h9
-rw-r--r--Utilities/cmcurl/lib/vquic/quiche.c148
-rw-r--r--Utilities/cmcurl/lib/vquic/quiche.h5
-rw-r--r--Utilities/cmcurl/lib/vquic/vquic.c2
-rw-r--r--Utilities/cmcurl/lib/vquic/vquic.h2
-rw-r--r--Utilities/cmcurl/lib/vssh/libssh.c558
-rw-r--r--Utilities/cmcurl/lib/vssh/libssh2.c1004
-rw-r--r--Utilities/cmcurl/lib/vssh/ssh.h37
-rw-r--r--Utilities/cmcurl/lib/vssh/wolfssh.c249
-rw-r--r--Utilities/cmcurl/lib/vssh/wolfssh.h2
-rw-r--r--Utilities/cmcurl/lib/vtls/bearssl.c140
-rw-r--r--Utilities/cmcurl/lib/vtls/bearssl.h4
-rw-r--r--Utilities/cmcurl/lib/vtls/gskit.c116
-rw-r--r--Utilities/cmcurl/lib/vtls/gskit.h4
-rw-r--r--Utilities/cmcurl/lib/vtls/gtls.c253
-rw-r--r--Utilities/cmcurl/lib/vtls/gtls.h4
-rw-r--r--Utilities/cmcurl/lib/vtls/keylog.c2
-rw-r--r--Utilities/cmcurl/lib/vtls/keylog.h2
-rw-r--r--Utilities/cmcurl/lib/vtls/mbedtls.c154
-rw-r--r--Utilities/cmcurl/lib/vtls/mbedtls.h4
-rw-r--r--Utilities/cmcurl/lib/vtls/mbedtls_threadlock.c2
-rw-r--r--Utilities/cmcurl/lib/vtls/mbedtls_threadlock.h2
-rw-r--r--Utilities/cmcurl/lib/vtls/mesalink.c139
-rw-r--r--Utilities/cmcurl/lib/vtls/mesalink.h6
-rw-r--r--Utilities/cmcurl/lib/vtls/nss.c303
-rw-r--r--Utilities/cmcurl/lib/vtls/nssg.h4
-rw-r--r--Utilities/cmcurl/lib/vtls/openssl.c556
-rw-r--r--Utilities/cmcurl/lib/vtls/openssl.h4
-rw-r--r--Utilities/cmcurl/lib/vtls/schannel.c291
-rw-r--r--Utilities/cmcurl/lib/vtls/schannel.h15
-rw-r--r--Utilities/cmcurl/lib/vtls/schannel_verify.c23
-rw-r--r--Utilities/cmcurl/lib/vtls/sectransp.c183
-rw-r--r--Utilities/cmcurl/lib/vtls/sectransp.h4
-rw-r--r--Utilities/cmcurl/lib/vtls/vtls.c202
-rw-r--r--Utilities/cmcurl/lib/vtls/vtls.h76
-rw-r--r--Utilities/cmcurl/lib/vtls/wolfssl.c179
-rw-r--r--Utilities/cmcurl/lib/vtls/wolfssl.h4
-rw-r--r--Utilities/cmcurl/lib/warnless.c23
-rw-r--r--Utilities/cmcurl/lib/warnless.h6
-rw-r--r--Utilities/cmcurl/lib/wildcard.c4
-rw-r--r--Utilities/cmcurl/lib/wildcard.h14
-rw-r--r--Utilities/cmcurl/lib/x509asn1.c10
-rw-r--r--Utilities/cmcurl/lib/x509asn1.h8
-rw-r--r--Utilities/cmexpat/CMakeLists.txt2
-rw-r--r--Utilities/cmjsoncpp/CMakeLists.txt2
-rw-r--r--Utilities/cmjsoncpp/src/lib_json/json_reader.cpp2027
-rw-r--r--Utilities/cmjsoncpp/src/lib_json/json_value.cpp1847
-rw-r--r--Utilities/cmjsoncpp/src/lib_json/json_writer.cpp1420
-rw-r--r--Utilities/cmlibarchive/CMakeLists.txt10
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_random.c8
-rw-r--r--Utilities/cmliblzma/CMakeLists.txt2
-rw-r--r--Utilities/cmlibrhash/CMakeLists.txt2
-rw-r--r--Utilities/cmlibuv/CMakeLists.txt2
-rw-r--r--Utilities/cmnghttp2/CMakeLists.txt2
-rw-r--r--Utilities/cmzlib/CMakeLists.txt2
-rw-r--r--Utilities/cmzstd/CMakeLists.txt2
-rw-r--r--Utilities/std/cm/optional56
366 files changed, 16589 insertions, 12782 deletions
diff --git a/Utilities/Doxygen/CMakeLists.txt b/Utilities/Doxygen/CMakeLists.txt
index 5bf13f3c9..a880f7a81 100644
--- a/Utilities/Doxygen/CMakeLists.txt
+++ b/Utilities/Doxygen/CMakeLists.txt
@@ -3,7 +3,7 @@
if(NOT CMake_SOURCE_DIR)
set(CMakeDeveloperReference_STANDALONE 1)
- cmake_minimum_required(VERSION 3.1...3.15 FATAL_ERROR)
+ cmake_minimum_required(VERSION 3.1...3.18 FATAL_ERROR)
get_filename_component(tmp "${CMAKE_CURRENT_SOURCE_DIR}" PATH)
get_filename_component(CMake_SOURCE_DIR "${tmp}" PATH)
include(${CMake_SOURCE_DIR}/Modules/CTestUseLaunchers.cmake)
diff --git a/Utilities/Release/README.rst b/Utilities/Release/README.rst
index 689268315..5d8e3181e 100644
--- a/Utilities/Release/README.rst
+++ b/Utilities/Release/README.rst
@@ -6,17 +6,6 @@ on ``cmake.org``. See also the `CMake Source Code Guide`_.
.. _`CMake Source Code Guide`: ../../Help/dev/source.rst
-File Table
-----------
-
-The set of package files distributed on ``cmake.org`` varies by CMake version.
-Clients providing automatic download functionality may query the set of
-package files available using a special file that lists them:
-
-* `File Table v1`_ Documentation
-
-.. _`File Table v1`: files-v1.rst
-
Docker
------
@@ -50,7 +39,7 @@ Each ``<os>/<arch>/`` directory contains the following:
-f cmake-src/Utilities/Release/linux/x86_64/Dockerfile cmake-src
$ docker container create --name cmake-build cmake:build
$ docker cp cmake-build:/out .
- $ ls out/cmake-*-Linux-x86_64.*
+ $ ls out/cmake-*-linux-x86_64.*
On Windows, the ``win/x86`` specifications support both the ``x86_64``
and ``i386`` architectures selected via ``--build-arg ARCH=...``.
@@ -69,8 +58,8 @@ Each ``<os>/<arch>/`` directory contains the following:
FROM cmake:test-base
COPY cmake-src /opt/cmake/src/cmake
- ADD out/cmake-<ver>-Linux-x86_64.tar.gz /opt/
- ENV PATH=/opt/cmake-<ver>-Linux-x86_64/bin:$PATH
+ ADD out/cmake-<ver>-linux-x86_64.tar.gz /opt/
+ ENV PATH=/opt/cmake-<ver>-linux-x86_64/bin:$PATH
Build the test image and run it to drive testing:
diff --git a/Utilities/Release/files-sign.bash b/Utilities/Release/files-sign.bash
deleted file mode 100755
index 414859dad..000000000
--- a/Utilities/Release/files-sign.bash
+++ /dev/null
@@ -1,5 +0,0 @@
-#!/usr/bin/env bash
-
-set -e
-
-gpg --armor --detach-sign cmake-*-SHA-256.txt
diff --git a/Utilities/Release/files-v1.json.in b/Utilities/Release/files-v1.json.in
deleted file mode 100644
index 6bafa694f..000000000
--- a/Utilities/Release/files-v1.json.in
+++ /dev/null
@@ -1,106 +0,0 @@
-{
- "version": {
- "major": @version_major@,
- "minor": @version_minor@,
- "patch": @version_patch@,
- @maybe_version_suffix@
- "string": "@version@"
- },
- "files": [
- {
- "os": ["linux", "Linux"],
- "architecture": ["aarch64"],
- "class": "installer",
- "name": "cmake-@version@-Linux-aarch64.sh"
- },
- {
- "os": ["linux", "Linux"],
- "architecture": ["aarch64"],
- "class": "archive",
- "name": "cmake-@version@-Linux-aarch64.tar.gz"
- },
- {
- "os": ["linux", "Linux"],
- "architecture": ["x86_64"],
- "class": "installer",
- "name": "cmake-@version@-Linux-x86_64.sh"
- },
- {
- "os": ["linux", "Linux"],
- "architecture": ["x86_64"],
- "class": "archive",
- "name": "cmake-@version@-Linux-x86_64.tar.gz"
- },
- {
- "os": ["macos", "macOS"],
- "architecture": ["arm64", "x86_64"],
- "class": "volume",
- "name": "cmake-@version@-macos-universal.dmg",
- "macOSmin": "10.13"
- },
- {
- "os": ["macos", "macOS"],
- "architecture": ["arm64", "x86_64"],
- "class": "archive",
- "name": "cmake-@version@-macos-universal.tar.gz",
- "macOSmin": "10.13"
- },
- {
- "os": ["macos10.10", "macOS10.10"],
- "architecture": ["arm64", "x86_64"],
- "class": "volume",
- "name": "cmake-@version@-macos10.10-universal.dmg",
- "macOSmin": "10.10"
- },
- {
- "os": ["macos10.10", "macOS10.10"],
- "architecture": ["arm64", "x86_64"],
- "class": "archive",
- "name": "cmake-@version@-macos10.10-universal.tar.gz",
- "macOSmin": "10.10"
- },
- {
- "os": ["windows", "Windows"],
- "architecture": ["i386"],
- "class": "installer",
- "name": "cmake-@version@-win32-x86.msi"
- },
- {
- "os": ["windows", "Windows"],
- "architecture": ["i386"],
- "class": "archive",
- "name": "cmake-@version@-win32-x86.zip"
- },
- {
- "os": ["windows", "Windows"],
- "architecture": ["x86_64"],
- "class": "installer",
- "name": "cmake-@version@-win64-x64.msi"
- },
- {
- "os": ["windows", "Windows"],
- "architecture": ["x86_64"],
- "class": "archive",
- "name": "cmake-@version@-win64-x64.zip"
- },
- {
- "os": ["source"],
- "architecture": [],
- "class": "archive",
- "name": "cmake-@version@.tar.gz"
- },
- {
- "os": ["source"],
- "architecture": [],
- "class": "archive",
- "name": "cmake-@version@.zip"
- }
- ],
- "hashFiles": [
- {
- "algorithm": ["sha256", "SHA-256"],
- "name": "cmake-@version@-SHA-256.txt",
- "signature": ["cmake-@version@-SHA-256.txt.asc"]
- }
- ]
-}
diff --git a/Utilities/Release/files-v1.rst b/Utilities/Release/files-v1.rst
deleted file mode 100644
index 3b916d432..000000000
--- a/Utilities/Release/files-v1.rst
+++ /dev/null
@@ -1,166 +0,0 @@
-File Table v1
-*************
-
-The set of package files distributed on ``cmake.org`` varies by CMake version.
-One file, named ``cmake-<ver>-files-v1.json``, contains a table of the package
-files available for a given version. Clients may use this to find other files.
-
-Format
-------
-
-The format is a JSON object:
-
-.. code-block:: json
-
- {
- "version": {
- "major": 3, "minor": 18, "patch": 6,
- "string": "3.18.6"
- },
- "files": [
- {
- "os": ["...", "..."],
- "architecture": ["...", "..."],
- "class": "...",
- "name": "..."
- }
- ],
- "hashFiles": [
- {
- "algorithm": ["...", "..."],
- "name": "cmake-<version>-<algo>.txt",
- "signature": ["cmake-<version>-<algo>.txt.asc"]
- }
- ]
- }
-
-The members are:
-
-``version``
- A JSON object specifying the version of CMake with members:
-
- ``major``, ``minor``, ``patch``
- Integer values specifying the major, minor, and patch version components.
-
- ``suffix``
- A string specifying the version suffix, if any, e.g. ``rc1``.
-
- ``string``
- A string specifying the full version in the format
- ``<major>.<minor>.<patch>[-<suffix>]``.
-
-``files``
- A JSON array of entries corresponding to available package files.
- Each entry is a JSON object containing members:
-
- ``os``
- A JSON array of strings naming the operating system for which the
- package file is built, possibly using multiple alternative spellings.
- Possible names include:
-
- ``source``
- Source packages.
-
- ``Linux``, ``linux``
- Linux packages.
-
- ``macOS``, ``macos``
- macOS packages.
-
- ``Windows``, ``windows``
- Windows packages.
-
- ``architecture``
- A JSON array of strings naming the architecture(s) for which the
- package file is built, possibly using multiple alternative spellings.
- Source packages have an empty list of architectures (``[]``).
- Binary packages have a non-empty list of architectures, with at least
- one name matching the output of ``uname -m`` on corresponding hosts.
- On Windows, architecture names include ``x86_64`` and ``i386``.
- On macOS, universal binary packages list all architectures,
- e.g. ``["arm64","x86_64"]``.
-
- ``class``
- A JSON string naming the class of package. The value is one of:
-
- ``archive``
- A tarball or zip archive.
- The extension, such as ``.tar.gz`` or ``.zip``, indicates the format.
- The rest of the file name matches the top-level directory in the archive.
-
- ``installer``
- An interactive installer.
-
- ``volume``
- A disk image (``.dmg`` on macOS).
-
- ``name``
- A JSON string specifying the name of the package file.
-
- ``macOSmin``
- Optional member that is present on package files for macOS.
- The value is a JSON string specifying the minimum version of macOS
- required to run the binary, e.g. ``"10.13"``.
-
-``hashFiles``
- A JSON array of entries corresponding to files containing cryptographic
- hashes of the package file contents. Each entry is a JSON object
- containing members:
-
- ``algorithm``
- A JSON array of strings naming a cryptographic hash algorithm, possibly
- using multiple alternative spellings, e.g. ``["sha256", "SHA-256"]``.
-
- ``name``
- A JSON string specifying the name of the file containing hashes,
- e.g. ``"cmake-<version>-SHA-256.txt"``.
-
- ``signature``
- A JSON array of strings naming files containing a cryptographic
- signature of the hash file specified by ``name``, e.g.
- ``["cmake-<version>-SHA-256.txt.asc"]``.
-
-The table and hash files are generated by `files.bash`_ from
-the `files-v1.json.in`_ template and the package files themselves.
-
-.. _`files.bash`: files.bash
-.. _`files-v1.json.in`: files-v1.json.in
-
-Queries
--------
-
-Clients may download the `File Table v1`_ file ``cmake-<ver>-files-v1.json``
-and query it to get the name(s) of specific package files adjacent to it.
-Make queries as specific as possible in order to account for additional
-alternative binaries in future CMake versions.
-
-For example, one may use ``jq`` queries:
-
-* To select a Windows binary archive supporting ``x86_64`` hosts::
-
- .files[] | select((.os[] | . == "windows") and
- (.architecture[] | . == "x86_64") and
- (.class == "archive")) | .name
-
-* To select a Linux binary archive supporting ``aarch64`` hosts::
-
- .files[] | select((.os[] | . == "linux") and
- (.architecture[] | . == "aarch64") and
- (.class == "archive")) | .name
-
-* To select a macOS binary archive supporting ``arm64`` hosts::
-
- .files[] | select((.os[] | . == "macos") and
- (.architecture[] | . == "arm64") and
- (.class == "archive")) | .name
-
-* To select a macOS binary archive supporting macOS 10.12 on ``x86_64`` hosts::
-
- .files[] | select((.os[] | contains("macOS")) and
- (.architecture[] | . == "x86_64") and
- ([.macOSmin] | inside(["10.10", "10.11", "10.12"]))
- ) | .name
-
-* To select a SHA-256 hash file::
-
- .hashFiles[] | select(.algorithm[] | . == "SHA-256") | .name
diff --git a/Utilities/Release/files.bash b/Utilities/Release/files.bash
deleted file mode 100755
index 28ca8f1b0..000000000
--- a/Utilities/Release/files.bash
+++ /dev/null
@@ -1,84 +0,0 @@
-#!/usr/bin/env bash
-
-set -e
-
-usage='usage: files.bash [<options>] [--]
-
-Options:
-
- --version <ver> CMake <major>.<minor> version number to push.
- Defaults to version of source tree.
-'
-
-die() {
- echo "$@" 1>&2; exit 1
-}
-
-readonly cmake_source_dir="${BASH_SOURCE%/*}/../.."
-
-cmake_version_component()
-{
- sed -n "
-/^set(CMake_VERSION_${1}/ {s/set(CMake_VERSION_${1} *\([0-9]*\))/\1/;p;}
-" "${cmake_source_dir}/Source/CMakeVersion.cmake"
-}
-
-
-version=''
-while test "$#" != 0; do
- case "$1" in
- --version) shift; version="$1" ;;
- --) shift ; break ;;
- -*) die "$usage" ;;
- *) break ;;
- esac
- shift
-done
-test "$#" = 0 || die "$usage"
-
-if test -z "$version"; then
- cmake_version_major="$(cmake_version_component MAJOR)"
- cmake_version_minor="$(cmake_version_component MINOR)"
- cmake_version_patch="$(cmake_version_component PATCH)"
- cmake_version_rc="$(cmake_version_component RC)"
- version="${cmake_version_major}.${cmake_version_minor}.${cmake_version_patch}"
- if test -n "$cmake_version_rc"; then
- version="$version-rc$cmake_version_rc"
- fi
-fi
-readonly version
-
-IFS='.-' read version_major version_minor version_patch version_suffix <<< "$version"
-readonly version_major
-readonly version_minor
-readonly version_patch
-readonly version_suffix
-
-if test -n "$version_suffix"; then
- maybe_version_suffix='"suffix": "'"$version_suffix"'",'
-else
- maybe_version_suffix=''
-fi
-readonly maybe_version_suffix
-
-readonly files_v1_in="${BASH_SOURCE%/*}/files-v1.json.in"
-sed "
- s/@version@/$version/g
- s/@version_major@/$version_major/g
- s/@version_minor@/$version_minor/g
- s/@version_patch@/$version_patch/g
- s/@maybe_version_suffix@/$maybe_version_suffix/g
-" "$files_v1_in" \
- | jq . \
- > "cmake-$version-files-v1.json"
-
-readonly algos='
- 256
-'
-for algo in $algos; do
- shasum -a $algo \
- "cmake-$version-files-v1.json" \
- $(jq -r '.files[].name' "cmake-$version-files-v1.json") \
- | LC_ALL=C sort -k 2 \
- > "cmake-$version-SHA-$algo.txt"
-done
diff --git a/Utilities/Release/linux/aarch64/Dockerfile b/Utilities/Release/linux/aarch64/Dockerfile
index 4077b79de..9abae2ab6 100644
--- a/Utilities/Release/linux/aarch64/Dockerfile
+++ b/Utilities/Release/linux/aarch64/Dockerfile
@@ -5,7 +5,7 @@
# Build using the CMake source directory as the build context.
# The resulting image will have an '/out' directory containing the package.
-# Keep this in sync with the `.gitlab-ci.yml` `release_linux` image.
+# Keep this in sync with the `.gitlab/os-linux.yml` `.linux_release_aarch64` image.
ARG FROM_IMAGE_NAME=kitware/cmake:build-linux-aarch64-deps-2020-12-21
ARG FROM_IMAGE_DIGEST=@sha256:0bd7dfe4e45593b04e39cd21e44011034610cfd376900558c5ef959bb1af15af
ARG FROM_IMAGE=$FROM_IMAGE_NAME$FROM_IMAGE_DIGEST
@@ -31,5 +31,5 @@ RUN : \
&& bin/cpack -G STGZ \
&& set +x \
&& mkdir /out \
- && mv cmake-*-Linux-aarch64.* /out \
+ && mv cmake-*-linux-aarch64.* /out \
&& :
diff --git a/Utilities/Release/linux/aarch64/cache.txt b/Utilities/Release/linux/aarch64/cache.txt
index 89050d1f1..0c2d9954f 100644
--- a/Utilities/Release/linux/aarch64/cache.txt
+++ b/Utilities/Release/linux/aarch64/cache.txt
@@ -41,4 +41,4 @@ CMAKE_SKIP_BOOTSTRAP_TEST:STRING=TRUE
CMake_TEST_Qt5:BOOL=FALSE
# CPack package file name component for this platform.
-CPACK_SYSTEM_NAME:STRING=Linux-aarch64
+CPACK_SYSTEM_NAME:STRING=linux-aarch64
diff --git a/Utilities/Release/linux/x86_64/Dockerfile b/Utilities/Release/linux/x86_64/Dockerfile
index 972913e3c..8c98d3e4b 100644
--- a/Utilities/Release/linux/x86_64/Dockerfile
+++ b/Utilities/Release/linux/x86_64/Dockerfile
@@ -5,7 +5,7 @@
# Build using the CMake source directory as the build context.
# The resulting image will have an '/out' directory containing the package.
-# Keep this in sync with the `.gitlab-ci.yml` `release_linux` image.
+# Keep this in sync with the `.gitlab/os-linux.yml` `.linux_release_x86_64` image.
ARG FROM_IMAGE_NAME=kitware/cmake:build-linux-x86_64-deps-2020-04-02
ARG FROM_IMAGE_DIGEST=@sha256:77e9ab183f34680990db9da5945473e288f0d6556bce79ecc1589670d656e157
ARG FROM_IMAGE=$FROM_IMAGE_NAME$FROM_IMAGE_DIGEST
@@ -32,5 +32,5 @@ RUN : \
&& bin/cpack -G STGZ \
&& set +x \
&& mkdir /out \
- && mv cmake-*-Linux-x86_64.* /out \
+ && mv cmake-*-linux-x86_64.* /out \
&& :
diff --git a/Utilities/Release/linux/x86_64/cache.txt b/Utilities/Release/linux/x86_64/cache.txt
index a2864e98b..e1f9fe337 100644
--- a/Utilities/Release/linux/x86_64/cache.txt
+++ b/Utilities/Release/linux/x86_64/cache.txt
@@ -41,4 +41,4 @@ CMAKE_SKIP_BOOTSTRAP_TEST:STRING=TRUE
CMake_TEST_Qt5:BOOL=FALSE
# CPack package file name component for this platform.
-CPACK_SYSTEM_NAME:STRING=Linux-x86_64
+CPACK_SYSTEM_NAME:STRING=linux-x86_64
diff --git a/Utilities/Release/win/x86/cache-i386.txt b/Utilities/Release/win/x86/cache-i386.txt
index 3c0ecc70e..54a45d8fc 100644
--- a/Utilities/Release/win/x86/cache-i386.txt
+++ b/Utilities/Release/win/x86/cache-i386.txt
@@ -42,4 +42,4 @@ CMAKE_Swift_COMPILER:FILEPATH=FALSE
CMake_TEST_Qt5:BOOL=FALSE
# CPack package file name component for this platform.
-CPACK_SYSTEM_NAME:STRING=win32-x86
+CPACK_SYSTEM_NAME:STRING=windows-i386
diff --git a/Utilities/Release/win/x86/cache-x86_64.txt b/Utilities/Release/win/x86/cache-x86_64.txt
index 2ccf93b5c..0b78c72b9 100644
--- a/Utilities/Release/win/x86/cache-x86_64.txt
+++ b/Utilities/Release/win/x86/cache-x86_64.txt
@@ -42,4 +42,4 @@ CMAKE_Swift_COMPILER:FILEPATH=FALSE
CMake_TEST_Qt5:BOOL=FALSE
# CPack package file name component for this platform.
-CPACK_SYSTEM_NAME:STRING=win64-x64
+CPACK_SYSTEM_NAME:STRING=windows-x86_64
diff --git a/Utilities/Scripts/regenerate-parsers.bash b/Utilities/Scripts/regenerate-parsers.bash
index 6fb35c028..33b59f730 100755
--- a/Utilities/Scripts/regenerate-parsers.bash
+++ b/Utilities/Scripts/regenerate-parsers.bash
@@ -22,12 +22,7 @@ do
if [[ (${in_file} -nt ${cxx_file}) || (${in_file} -nt ${h_file}) || (${forced} -gt 0) ]]; then
echo "Generating Parser ${parser}"
- bison --yacc --name-prefix=${prefix} --defines=${h_file} -o${cxx_file} ${in_file}
- sed -i '/\/\* Else will try to reuse/ i\
-#if 0
-/^yyerrlab1:/ a\
-#endif
-' ${cxx_file}
+ bison --name-prefix=${prefix} --defines=${h_file} -o${cxx_file} ${in_file}
else
echo "Skipped generating Parser ${parser}"
fi
diff --git a/Utilities/Scripts/update-curl.bash b/Utilities/Scripts/update-curl.bash
index 94a42e925..16cdd6575 100755
--- a/Utilities/Scripts/update-curl.bash
+++ b/Utilities/Scripts/update-curl.bash
@@ -8,7 +8,7 @@ readonly name="curl"
readonly ownership="Curl Upstream <curl-library@cool.haxx.se>"
readonly subtree="Utilities/cmcurl"
readonly repo="https://github.com/curl/curl.git"
-readonly tag="curl-7_72_0"
+readonly tag="curl-7_75_0"
readonly shortlog=false
readonly paths="
CMake/*
diff --git a/Utilities/Sphinx/CMakeLists.txt b/Utilities/Sphinx/CMakeLists.txt
index e5be43ad8..f989907b4 100644
--- a/Utilities/Sphinx/CMakeLists.txt
+++ b/Utilities/Sphinx/CMakeLists.txt
@@ -3,7 +3,7 @@
if(NOT CMake_SOURCE_DIR)
set(CMakeHelp_STANDALONE 1)
- cmake_minimum_required(VERSION 3.1...3.15 FATAL_ERROR)
+ cmake_minimum_required(VERSION 3.1...3.18 FATAL_ERROR)
get_filename_component(tmp "${CMAKE_CURRENT_SOURCE_DIR}" PATH)
get_filename_component(CMake_SOURCE_DIR "${tmp}" PATH)
include(${CMake_SOURCE_DIR}/Modules/CTestUseLaunchers.cmake)
diff --git a/Utilities/Sphinx/cmake.py b/Utilities/Sphinx/cmake.py
index e175d0df8..ece4bf56b 100644
--- a/Utilities/Sphinx/cmake.py
+++ b/Utilities/Sphinx/cmake.py
@@ -191,6 +191,7 @@ _cmake_index_objs = {
'cpack_gen': _cmake_index_entry('cpack generator'),
'envvar': _cmake_index_entry('envvar'),
'generator': _cmake_index_entry('generator'),
+ 'genex': _cmake_index_entry('genex'),
'guide': _cmake_index_entry('guide'),
'manual': _cmake_index_entry('manual'),
'module': _cmake_index_entry('module'),
@@ -224,7 +225,7 @@ class CMakeTransform(Transform):
self.titles = {}
def parse_title(self, docname):
- """Parse a document title as the first line starting in [A-Za-z0-9<]
+ """Parse a document title as the first line starting in [A-Za-z0-9<$]
or fall back to the document basename if no such line exists.
The cmake --help-*-list commands also depend on this convention.
Return the title or False if the document file does not exist.
@@ -239,7 +240,7 @@ class CMakeTransform(Transform):
title = False
else:
for line in f:
- if len(line) > 0 and (line[0].isalnum() or line[0] == '<'):
+ if len(line) > 0 and (line[0].isalnum() or line[0] == '<' or line[0] == '$'):
title = line.rstrip()
break
f.close()
@@ -260,6 +261,10 @@ class CMakeTransform(Transform):
if objtype == 'command':
targetname = title.lower()
else:
+ if objtype == 'genex':
+ m = CMakeXRefRole._re_genex.match(title)
+ if m:
+ title = m.group(1)
targetname = title
targetid = '%s:%s' % (objtype, targetname)
targetnode = nodes.target('', '', ids=[targetid])
@@ -277,6 +282,10 @@ class CMakeObject(ObjectDescription):
def handle_signature(self, sig, signode):
# called from sphinx.directives.ObjectDescription.run()
signode += addnodes.desc_name(sig, sig)
+ if self.objtype == 'genex':
+ m = CMakeXRefRole._re_genex.match(sig)
+ if m:
+ sig = m.group(1)
return sig
def add_target_and_index(self, name, sig, signode):
@@ -302,6 +311,7 @@ class CMakeXRefRole(XRefRole):
# See sphinx.util.nodes.explicit_title_re; \x00 escapes '<'.
_re = re.compile(r'^(.+?)(\s*)(?<!\x00)<(.*?)>$', re.DOTALL)
_re_sub = re.compile(r'^([^()\s]+)\s*\(([^()]*)\)$', re.DOTALL)
+ _re_genex = re.compile(r'^\$<([^<>:]+)(:[^<>]+)?>$', re.DOTALL)
def __call__(self, typ, rawtext, text, *args, **keys):
# Translate CMake command cross-references of the form:
@@ -312,6 +322,10 @@ class CMakeXRefRole(XRefRole):
m = CMakeXRefRole._re_sub.match(text)
if m:
text = '%s <%s>' % (text, m.group(1))
+ elif typ == 'cmake:genex':
+ m = CMakeXRefRole._re_genex.match(text)
+ if m:
+ text = '%s <%s>' % (text, m.group(1))
# CMake cross-reference targets frequently contain '<' so escape
# any explicit `<target>` with '<' not preceded by whitespace.
while True:
@@ -374,6 +388,7 @@ class CMakeDomain(Domain):
'cpack_gen': ObjType('cpack_gen', 'cpack_gen'),
'envvar': ObjType('envvar', 'envvar'),
'generator': ObjType('generator', 'generator'),
+ 'genex': ObjType('genex', 'genex'),
'guide': ObjType('guide', 'guide'),
'variable': ObjType('variable', 'variable'),
'module': ObjType('module', 'module'),
@@ -390,6 +405,7 @@ class CMakeDomain(Domain):
directives = {
'command': CMakeObject,
'envvar': CMakeObject,
+ 'genex': CMakeObject,
'variable': CMakeObject,
# Other object types cannot be created except by the CMakeTransform
# 'generator': CMakeObject,
@@ -409,6 +425,7 @@ class CMakeDomain(Domain):
'cpack_gen': CMakeXRefRole(),
'envvar': CMakeXRefRole(),
'generator': CMakeXRefRole(),
+ 'genex': CMakeXRefRole(),
'guide': CMakeXRefRole(),
'variable': CMakeXRefRole(),
'module': CMakeXRefRole(),
diff --git a/Utilities/Sphinx/conf.py.in b/Utilities/Sphinx/conf.py.in
index 42b095162..5def681dc 100644
--- a/Utilities/Sphinx/conf.py.in
+++ b/Utilities/Sphinx/conf.py.in
@@ -29,6 +29,7 @@ extensions = ['cmake']
templates_path = ['@conf_path@/templates']
nitpicky = True
+smartquotes = False
cmake_manuals = sorted(glob.glob(r'@conf_docs@/manual/*.rst'))
cmake_manual_description = re.compile('^\.\. cmake-manual-description:(.*)$')
diff --git a/Utilities/Sphinx/create_identifiers.py b/Utilities/Sphinx/create_identifiers.py
index e35f12770..0ff39a0c2 100755
--- a/Utilities/Sphinx/create_identifiers.py
+++ b/Utilities/Sphinx/create_identifiers.py
@@ -25,6 +25,7 @@ for line in lines:
("envvar", "envvar"),
("variable", "variable"),
("generator", "generator"),
+ ("genex", "genex"),
("guide", "guide"),
("target property", "prop_tgt"),
("test property", "prop_test"),
diff --git a/Utilities/Sphinx/static/cmake.css b/Utilities/Sphinx/static/cmake.css
index b082edec8..029eb1b2f 100644
--- a/Utilities/Sphinx/static/cmake.css
+++ b/Utilities/Sphinx/static/cmake.css
@@ -16,3 +16,9 @@ div.sphinxsidebarwrapper {
.literal-block a.reference.internal {
background-color: #dfdfdf;
}
+
+/* Remove unwanted margin in case list item contains a div-wrapping
+ directive like `.. versionadded` or `.. deprecated`. */
+dd > :first-child > p {
+ margin-top: 0px;
+}
diff --git a/Utilities/cmbzip2/CMakeLists.txt b/Utilities/cmbzip2/CMakeLists.txt
index cb4a038fa..9b53b0f12 100644
--- a/Utilities/cmbzip2/CMakeLists.txt
+++ b/Utilities/cmbzip2/CMakeLists.txt
@@ -2,7 +2,7 @@ project(bzip2)
# Disable warnings to avoid changing 3rd party code.
if(CMAKE_C_COMPILER_ID MATCHES
- "^(GNU|Clang|AppleClang|XLClang|XL|VisualAge|SunPro|HP|Intel)$")
+ "^(GNU|Clang|AppleClang|XLClang|XL|VisualAge|SunPro|HP|Intel|IntelLLVM)$")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -w")
elseif(CMAKE_C_COMPILER_ID STREQUAL "PathScale")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -woffall")
diff --git a/Utilities/cmcurl/CMake/CMakeConfigurableFile.in b/Utilities/cmcurl/CMake/CMakeConfigurableFile.in
index 2bafe2c10..8ccd016a6 100644
--- a/Utilities/cmcurl/CMake/CMakeConfigurableFile.in
+++ b/Utilities/cmcurl/CMake/CMakeConfigurableFile.in
@@ -9,7 +9,7 @@
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
-# are also available at https://curl.haxx.se/docs/copyright.html.
+# 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
diff --git a/Utilities/cmcurl/CMake/CurlSymbolHiding.cmake b/Utilities/cmcurl/CMake/CurlSymbolHiding.cmake
index aaac9fead..e99ea6f64 100644
--- a/Utilities/cmcurl/CMake/CurlSymbolHiding.cmake
+++ b/Utilities/cmcurl/CMake/CurlSymbolHiding.cmake
@@ -9,7 +9,7 @@
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
-# are also available at https://curl.haxx.se/docs/copyright.html.
+# 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
@@ -27,7 +27,7 @@ mark_as_advanced(CURL_HIDDEN_SYMBOLS)
if(CURL_HIDDEN_SYMBOLS)
set(SUPPORTS_SYMBOL_HIDING FALSE)
- if(CMAKE_C_COMPILER_ID MATCHES "Clang")
+ if(CMAKE_C_COMPILER_ID MATCHES "Clang" AND NOT MSVC)
set(SUPPORTS_SYMBOL_HIDING TRUE)
set(_SYMBOL_EXTERN "__attribute__ ((__visibility__ (\"default\")))")
set(_CFLAG_SYMBOLS_HIDE "-fvisibility=hidden")
diff --git a/Utilities/cmcurl/CMake/CurlTests.c b/Utilities/cmcurl/CMake/CurlTests.c
index 3ef35f025..949910d5e 100644
--- a/Utilities/cmcurl/CMake/CurlTests.c
+++ b/Utilities/cmcurl/CMake/CurlTests.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
diff --git a/Utilities/cmcurl/CMake/FindBearSSL.cmake b/Utilities/cmcurl/CMake/FindBearSSL.cmake
index a8f72c92d..9455f4ba3 100644
--- a/Utilities/cmcurl/CMake/FindBearSSL.cmake
+++ b/Utilities/cmcurl/CMake/FindBearSSL.cmake
@@ -9,7 +9,7 @@
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
-# are also available at https://curl.haxx.se/docs/copyright.html.
+# 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
diff --git a/Utilities/cmcurl/CMake/FindBrotli.cmake b/Utilities/cmcurl/CMake/FindBrotli.cmake
index c43172b64..0ed08550d 100644
--- a/Utilities/cmcurl/CMake/FindBrotli.cmake
+++ b/Utilities/cmcurl/CMake/FindBrotli.cmake
@@ -9,7 +9,7 @@
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
-# are also available at https://curl.haxx.se/docs/copyright.html.
+# 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
diff --git a/Utilities/cmcurl/CMake/FindCARES.cmake b/Utilities/cmcurl/CMake/FindCARES.cmake
index 9160ae5fd..71806823d 100644
--- a/Utilities/cmcurl/CMake/FindCARES.cmake
+++ b/Utilities/cmcurl/CMake/FindCARES.cmake
@@ -9,7 +9,7 @@
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
-# are also available at https://curl.haxx.se/docs/copyright.html.
+# 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
diff --git a/Utilities/cmcurl/CMake/FindGSS.cmake b/Utilities/cmcurl/CMake/FindGSS.cmake
index 02111a20f..4e4747d6c 100644
--- a/Utilities/cmcurl/CMake/FindGSS.cmake
+++ b/Utilities/cmcurl/CMake/FindGSS.cmake
@@ -9,7 +9,7 @@
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
-# are also available at https://curl.haxx.se/docs/copyright.html.
+# 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
diff --git a/Utilities/cmcurl/CMake/FindLibSSH2.cmake b/Utilities/cmcurl/CMake/FindLibSSH2.cmake
index 4cdf3e310..ce46a408b 100644
--- a/Utilities/cmcurl/CMake/FindLibSSH2.cmake
+++ b/Utilities/cmcurl/CMake/FindLibSSH2.cmake
@@ -9,7 +9,7 @@
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
-# are also available at https://curl.haxx.se/docs/copyright.html.
+# 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
diff --git a/Utilities/cmcurl/CMake/FindMbedTLS.cmake b/Utilities/cmcurl/CMake/FindMbedTLS.cmake
index 2ebe721a6..1746093df 100644
--- a/Utilities/cmcurl/CMake/FindMbedTLS.cmake
+++ b/Utilities/cmcurl/CMake/FindMbedTLS.cmake
@@ -9,7 +9,7 @@
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
-# are also available at https://curl.haxx.se/docs/copyright.html.
+# 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
diff --git a/Utilities/cmcurl/CMake/FindNGHTTP2.cmake b/Utilities/cmcurl/CMake/FindNGHTTP2.cmake
index e1eba0532..8614492b1 100644
--- a/Utilities/cmcurl/CMake/FindNGHTTP2.cmake
+++ b/Utilities/cmcurl/CMake/FindNGHTTP2.cmake
@@ -9,7 +9,7 @@
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
-# are also available at https://curl.haxx.se/docs/copyright.html.
+# 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
diff --git a/Utilities/cmcurl/CMake/FindNGHTTP3.cmake b/Utilities/cmcurl/CMake/FindNGHTTP3.cmake
index 73ce9e188..643b60097 100644
--- a/Utilities/cmcurl/CMake/FindNGHTTP3.cmake
+++ b/Utilities/cmcurl/CMake/FindNGHTTP3.cmake
@@ -9,7 +9,7 @@
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
-# are also available at https://curl.haxx.se/docs/copyright.html.
+# 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
diff --git a/Utilities/cmcurl/CMake/FindNGTCP2.cmake b/Utilities/cmcurl/CMake/FindNGTCP2.cmake
index a1ed8cd4b..5757009a5 100644
--- a/Utilities/cmcurl/CMake/FindNGTCP2.cmake
+++ b/Utilities/cmcurl/CMake/FindNGTCP2.cmake
@@ -9,7 +9,7 @@
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
-# are also available at https://curl.haxx.se/docs/copyright.html.
+# 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
diff --git a/Utilities/cmcurl/CMake/FindNSS.cmake b/Utilities/cmcurl/CMake/FindNSS.cmake
index 5fdb2b776..899c6b075 100644
--- a/Utilities/cmcurl/CMake/FindNSS.cmake
+++ b/Utilities/cmcurl/CMake/FindNSS.cmake
@@ -9,7 +9,7 @@
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
-# are also available at https://curl.haxx.se/docs/copyright.html.
+# 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
diff --git a/Utilities/cmcurl/CMake/FindQUICHE.cmake b/Utilities/cmcurl/CMake/FindQUICHE.cmake
index 01d17582b..0247364d4 100644
--- a/Utilities/cmcurl/CMake/FindQUICHE.cmake
+++ b/Utilities/cmcurl/CMake/FindQUICHE.cmake
@@ -9,7 +9,7 @@
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
-# are also available at https://curl.haxx.se/docs/copyright.html.
+# 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
diff --git a/Utilities/cmcurl/CMake/FindWolfSSL.cmake b/Utilities/cmcurl/CMake/FindWolfSSL.cmake
index 54df1a86c..42256b3cd 100644
--- a/Utilities/cmcurl/CMake/FindWolfSSL.cmake
+++ b/Utilities/cmcurl/CMake/FindWolfSSL.cmake
@@ -9,7 +9,7 @@
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
-# are also available at https://curl.haxx.se/docs/copyright.html.
+# 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
diff --git a/Utilities/cmcurl/CMake/FindZstd.cmake b/Utilities/cmcurl/CMake/FindZstd.cmake
index 44c741ae8..eaba39746 100644
--- a/Utilities/cmcurl/CMake/FindZstd.cmake
+++ b/Utilities/cmcurl/CMake/FindZstd.cmake
@@ -9,7 +9,7 @@
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
-# are also available at https://curl.haxx.se/docs/copyright.html.
+# 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
diff --git a/Utilities/cmcurl/CMake/Macros.cmake b/Utilities/cmcurl/CMake/Macros.cmake
index 65a41e484..d57dd6ad5 100644
--- a/Utilities/cmcurl/CMake/Macros.cmake
+++ b/Utilities/cmcurl/CMake/Macros.cmake
@@ -9,7 +9,7 @@
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
-# are also available at https://curl.haxx.se/docs/copyright.html.
+# 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
@@ -107,3 +107,14 @@ macro(curl_nroff_check)
message(WARNING "Found no *nroff program")
endif()
endmacro()
+
+macro(optional_dependency DEPENDENCY)
+ set(CURL_${DEPENDENCY} AUTO CACHE STRING "Build curl with ${DEPENDENCY} support (AUTO, ON or OFF)")
+ set_property(CACHE CURL_${DEPENDENCY} PROPERTY STRINGS AUTO ON OFF)
+
+ if(CURL_${DEPENDENCY} STREQUAL AUTO)
+ find_package(${DEPENDENCY})
+ elseif(CURL_${DEPENDENCY})
+ find_package(${DEPENDENCY} REQUIRED)
+ endif()
+endmacro()
diff --git a/Utilities/cmcurl/CMake/OtherTests.cmake b/Utilities/cmcurl/CMake/OtherTests.cmake
index 8c9a49194..bbd463250 100644
--- a/Utilities/cmcurl/CMake/OtherTests.cmake
+++ b/Utilities/cmcurl/CMake/OtherTests.cmake
@@ -9,7 +9,7 @@
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
-# are also available at https://curl.haxx.se/docs/copyright.html.
+# 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
diff --git a/Utilities/cmcurl/CMake/Platforms/WindowsCache.cmake b/Utilities/cmcurl/CMake/Platforms/WindowsCache.cmake
index 7c020bd49..9307381ef 100644
--- a/Utilities/cmcurl/CMake/Platforms/WindowsCache.cmake
+++ b/Utilities/cmcurl/CMake/Platforms/WindowsCache.cmake
@@ -9,7 +9,7 @@
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
-# are also available at https://curl.haxx.se/docs/copyright.html.
+# 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
diff --git a/Utilities/cmcurl/CMake/Utilities.cmake b/Utilities/cmcurl/CMake/Utilities.cmake
index 59b17d074..8f9b861ba 100644
--- a/Utilities/cmcurl/CMake/Utilities.cmake
+++ b/Utilities/cmcurl/CMake/Utilities.cmake
@@ -9,7 +9,7 @@
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
-# are also available at https://curl.haxx.se/docs/copyright.html.
+# 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
diff --git a/Utilities/cmcurl/CMake/cmake_uninstall.cmake.in b/Utilities/cmcurl/CMake/cmake_uninstall.cmake.in
index 74e56a29c..d9d9c4e3a 100644
--- a/Utilities/cmcurl/CMake/cmake_uninstall.cmake.in
+++ b/Utilities/cmcurl/CMake/cmake_uninstall.cmake.in
@@ -9,7 +9,7 @@
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
-# are also available at https://curl.haxx.se/docs/copyright.html.
+# 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
diff --git a/Utilities/cmcurl/CMake/curl-config.cmake.in b/Utilities/cmcurl/CMake/curl-config.cmake.in
index ae8cc30f1..957148ecc 100644
--- a/Utilities/cmcurl/CMake/curl-config.cmake.in
+++ b/Utilities/cmcurl/CMake/curl-config.cmake.in
@@ -9,7 +9,7 @@
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
-# are also available at https://curl.haxx.se/docs/copyright.html.
+# 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
diff --git a/Utilities/cmcurl/CMakeLists.txt b/Utilities/cmcurl/CMakeLists.txt
index 4821656af..4fb93615c 100644
--- a/Utilities/cmcurl/CMakeLists.txt
+++ b/Utilities/cmcurl/CMakeLists.txt
@@ -8,6 +8,7 @@ set(CMAKE_USE_LIBSSH2 OFF CACHE INTERNAL "Disable curl libssh2")
set(CMAKE_USE_LIBSSH OFF)
set(CMAKE_USE_OPENLDAP OFF CACHE INTERNAL "No curl OpenLDAP")
set(CURL_BROTLI OFF)
+set(CURL_DISABLE_ALTSVC ON)
set(CURL_DISABLE_COOKIES OFF CACHE INTERNAL "Do not disable curl cookie support")
set(CURL_DISABLE_CRYPTO_AUTH OFF CACHE INTERNAL "Do not disable curl crypto auth")
set(CURL_DISABLE_DICT ON CACHE INTERNAL "Disable curl dict protocol?")
@@ -18,6 +19,8 @@ set(CURL_DISABLE_HTTP OFF CACHE INTERNAL "Disable curl http protocol?")
set(CURL_DISABLE_IMAP ON CACHE INTERNAL "Disable curl imap protocol?")
set(CURL_DISABLE_LDAP ON CACHE INTERNAL "Disable curl ldap protocol?")
set(CURL_DISABLE_LDAPS ON CACHE INTERNAL "Disable curl ldaps protocol?")
+set(CURL_DISABLE_MQTT ON)
+set(CURL_DISABLE_OPENSSL_AUTO_LOAD_CONFIG OFF)
set(CURL_DISABLE_POP3 ON CACHE INTERNAL "Disable curl pop3 protocol?")
set(CURL_DISABLE_PROXY OFF CACHE INTERNAL "Do not disable curl proxy")
set(CURL_DISABLE_RTSP ON CACHE INTERNAL "Disable curl rtsp protocol?")
@@ -25,7 +28,6 @@ set(CURL_DISABLE_SMTP ON CACHE INTERNAL "Disable curl smtp protocol?")
set(CURL_DISABLE_TELNET ON CACHE INTERNAL "Disable curl telnet protocol?")
set(CURL_DISABLE_TFTP ON CACHE INTERNAL "Disable curl tftp protocol?")
set(CURL_DISABLE_VERBOSE_STRINGS OFF CACHE INTERNAL "Do not disable curl verbosity")
-set(CURL_ENABLE_MQTT OFF)
set(CURL_HIDDEN_SYMBOLS OFF CACHE INTERNAL "No curl hidden symbols")
set(CURL_LTO OFF CACHE INTERNAL "Turn on compiler Link Time Optimizations")
set(CURL_STATIC_CRT OFF CACHE INTERNAL "Set to ON to build libcurl with static CRT on Windows (/MT).")
@@ -40,9 +42,11 @@ set(ENABLE_INET_PTON OFF CACHE INTERNAL "Set to OFF to prevent usage of inet_pto
set(ENABLE_IPV6 ON CACHE INTERNAL "Enable curl IPv6 support detection")
set(ENABLE_MANUAL OFF CACHE INTERNAL "No curl built-in manual")
set(ENABLE_THREADED_RESOLVER OFF CACHE INTERNAL "No curl POSIX threaded DNS lookup")
+set(ENABLE_UNICODE OFF)
set(ENABLE_UNIX_SOCKETS OFF CACHE INTERNAL "No curl Unix domain sockets support")
set(HTTP_ONLY OFF CACHE INTERNAL "Curl is not http-only")
set(PICKY_COMPILER OFF CACHE INTERNAL "Enable picky compiler options")
+set(USE_LIBIDN2 ON)
set(USE_NGHTTP2 ON)
set(USE_NGTCP2 OFF)
set(USE_QUICHE OFF)
@@ -93,7 +97,7 @@ endif(APPLE)
# Disable warnings to avoid changing 3rd party code.
if(CMAKE_C_COMPILER_ID MATCHES
- "^(GNU|Clang|AppleClang|XLClang|XL|VisualAge|SunPro|HP|Intel)$")
+ "^(GNU|Clang|AppleClang|XLClang|XL|VisualAge|SunPro|HP|Intel|IntelLLVM)$")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -w")
elseif(CMAKE_C_COMPILER_ID STREQUAL "PathScale")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -woffall")
@@ -106,11 +110,11 @@ endif()
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
-# are also available at https://curl.haxx.se/docs/copyright.html.
+# 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
@@ -146,10 +150,6 @@ include(CheckCCompilerFlag)
project(CURL C)
-if(0) # This code not needed for building within CMake.
-message(WARNING "the curl cmake build system is poorly maintained. Be aware")
-endif()
-
file(STRINGS ${CURL_SOURCE_DIR}/include/curl/curlver.h CURL_VERSION_H_CONTENTS REGEX "#define LIBCURL_VERSION( |_NUM )")
string(REGEX MATCH "#define LIBCURL_VERSION \"[^\"]*"
CURL_VERSION ${CURL_VERSION_H_CONTENTS})
@@ -168,7 +168,7 @@ endif()
# SET(PACKAGE_NAME "curl")
# SET(PACKAGE_VERSION "-")
# SET(PACKAGE_STRING "curl-")
-# SET(PACKAGE_BUGREPORT "a suitable curl mailing list => https://curl.haxx.se/mail/")
+# SET(PACKAGE_BUGREPORT "a suitable curl mailing list => https://curl.se/mail/")
set(OPERATING_SYSTEM "${CMAKE_SYSTEM_NAME}")
set(OS "\"${CMAKE_SYSTEM_NAME}\"")
@@ -182,6 +182,7 @@ option(ENABLE_ARES "Set to ON to enable c-ares support" OFF)
if(WIN32)
option(CURL_STATIC_CRT "Set to ON to build libcurl with static CRT on Windows (/MT)." OFF)
option(ENABLE_INET_PTON "Set to OFF to prevent usage of inet_pton when building against modern SDKs while still requiring compatibility with older Windows versions, such as Windows XP, Windows Server 2003 etc." ON)
+ option(ENABLE_UNICODE "Set to ON to use the Unicode version of the Windows API functions" OFF)
if(0) # This code not needed for building within CMake.
set(CURL_TARGET_WINDOWS_VERSION "" CACHE STRING "Minimum target Windows version as hex string")
if(CURL_TARGET_WINDOWS_VERSION)
@@ -197,6 +198,12 @@ if(WIN32)
set(CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS} -D_WIN32_WINNT=0x0501")
endif()
endif()
+ if(ENABLE_UNICODE)
+ add_definitions(-DUNICODE -D_UNICODE)
+ if(MINGW)
+ add_compile_options(-municode)
+ endif()
+ endif()
endif()
option(CURL_LTO "Turn on compiler Link Time Optimizations" OFF)
@@ -294,28 +301,30 @@ option(CURL_DISABLE_SMTP "to disable SMTP" OFF)
mark_as_advanced(CURL_DISABLE_SMTP)
option(CURL_DISABLE_GOPHER "to disable Gopher" OFF)
mark_as_advanced(CURL_DISABLE_GOPHER)
-option(CURL_ENABLE_MQTT "to enable MQTT" OFF)
-mark_as_advanced(CURL_ENABLE_MQTT)
+option(CURL_DISABLE_MQTT "to disable MQTT" OFF)
+mark_as_advanced(CURL_DISABLE_MQTT)
if(HTTP_ONLY)
+ set(CURL_DISABLE_DICT ON)
+ set(CURL_DISABLE_FILE ON)
set(CURL_DISABLE_FTP ON)
+ set(CURL_DISABLE_GOPHER ON)
+ set(CURL_DISABLE_IMAP ON)
set(CURL_DISABLE_LDAP ON)
set(CURL_DISABLE_LDAPS ON)
- set(CURL_DISABLE_TELNET ON)
- set(CURL_DISABLE_DICT ON)
- set(CURL_DISABLE_FILE ON)
- set(CURL_DISABLE_TFTP ON)
- set(CURL_DISABLE_RTSP ON)
+ set(CURL_DISABLE_MQTT ON)
set(CURL_DISABLE_POP3 ON)
- set(CURL_DISABLE_IMAP ON)
+ set(CURL_DISABLE_RTSP ON)
set(CURL_DISABLE_SMB ON)
set(CURL_DISABLE_SMTP ON)
- set(CURL_DISABLE_GOPHER ON)
+ set(CURL_DISABLE_TELNET ON)
+ set(CURL_DISABLE_TFTP ON)
endif()
+option(CURL_DISABLE_ALTSVC "to disable alt-svc support" OFF)
+mark_as_advanced(CURL_DISABLE_ALTSVC)
option(CURL_DISABLE_COOKIES "to disable cookies support" OFF)
mark_as_advanced(CURL_DISABLE_COOKIES)
-
option(CURL_DISABLE_CRYPTO_AUTH "to disable cryptographic authentication" OFF)
mark_as_advanced(CURL_DISABLE_CRYPTO_AUTH)
option(CURL_DISABLE_VERBOSE_STRINGS "to disable verbose strings" OFF)
@@ -352,10 +361,6 @@ if(ENABLE_MANUAL)
endif()
endif()
-# We need ansi c-flags, especially on HP
-set(CMAKE_C_FLAGS "${CMAKE_ANSI_CFLAGS} ${CMAKE_C_FLAGS}")
-set(CMAKE_REQUIRED_FLAGS ${CMAKE_ANSI_CFLAGS})
-
if(CURL_STATIC_CRT)
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /MT")
@@ -454,6 +459,7 @@ set(openssl_default ON)
if(WIN32 OR CMAKE_USE_SECTRANSP OR CMAKE_USE_SCHANNEL OR CMAKE_USE_MBEDTLS OR CMAKE_USE_NSS OR CMAKE_USE_WOLFSSL)
set(openssl_default OFF)
endif()
+option(CURL_DISABLE_OPENSSL_AUTO_LOAD_CONFIG "Disable automatic loading of OpenSSL configuration" OFF)
count_true(enabled_ssl_options_count
CMAKE_USE_SCHANNEL
@@ -741,34 +747,35 @@ if(NOT CURL_DISABLE_LDAPS)
endif()
# Check for idn
-check_library_exists_concat("idn2" idn2_lookup_ul HAVE_LIBIDN2)
+option(USE_LIBIDN2 "Use libidn2 for IDN support" ON)
+set(HAVE_LIBIDN2 OFF)
+if(USE_LIBIDN2)
+ check_library_exists_concat("idn2" idn2_lookup_ul HAVE_LIBIDN2)
+endif()
# Check for symbol dlopen (same as HAVE_LIBDL)
check_library_exists("${CURL_LIBS}" dlopen "" HAVE_DLOPEN)
if(0) # This code not needed for building within CMake.
-option(CURL_ZLIB "Set to ON to enable building curl with zlib support." ON)
set(HAVE_LIBZ OFF)
set(HAVE_ZLIB_H OFF)
set(USE_ZLIB OFF)
-if(CURL_ZLIB)
- find_package(ZLIB QUIET)
- if(ZLIB_FOUND)
- set(HAVE_ZLIB_H ON)
- set(HAVE_LIBZ ON)
- set(USE_ZLIB ON)
-
- # Depend on ZLIB via imported targets if supported by the running
- # version of CMake. This allows our dependents to get our dependencies
- # transitively.
- if(NOT CMAKE_VERSION VERSION_LESS 3.4)
- list(APPEND CURL_LIBS ZLIB::ZLIB)
- else()
- list(APPEND CURL_LIBS ${ZLIB_LIBRARIES})
- include_directories(${ZLIB_INCLUDE_DIRS})
- endif()
- list(APPEND CMAKE_REQUIRED_INCLUDES ${ZLIB_INCLUDE_DIRS})
+optional_dependency(ZLIB)
+if(ZLIB_FOUND)
+ set(HAVE_ZLIB_H ON)
+ set(HAVE_LIBZ ON)
+ set(USE_ZLIB ON)
+
+ # Depend on ZLIB via imported targets if supported by the running
+ # version of CMake. This allows our dependents to get our dependencies
+ # transitively.
+ if(NOT CMAKE_VERSION VERSION_LESS 3.4)
+ list(APPEND CURL_LIBS ZLIB::ZLIB)
+ else()
+ list(APPEND CURL_LIBS ${ZLIB_LIBRARIES})
+ include_directories(${ZLIB_INCLUDE_DIRS})
endif()
+ list(APPEND CMAKE_REQUIRED_INCLUDES ${ZLIB_INCLUDE_DIRS})
endif()
endif()
@@ -911,6 +918,7 @@ if(CMAKE_USE_GSSAPI)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${GSS_COMPILER_FLAGS}")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${GSS_LINKER_FLAGS}")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${GSS_LINKER_FLAGS}")
+ set(CMAKE_STATIC_LINKER_FLAGS "${CMAKE_STATIC_LINKER_FLAGS} ${GSS_LINKER_FLAGS}")
list(APPEND CURL_LIBS ${GSS_LIBRARIES})
else()
@@ -926,8 +934,6 @@ else()
unset(USE_UNIX_SOCKETS CACHE)
endif()
-option(ENABLE_ALT_SVC "Enable alt-svc support" OFF)
-set(USE_ALTSVC ${ENABLE_ALT_SVC})
if(0) # This code not needed for building within CMake.
#
@@ -1055,6 +1061,7 @@ check_include_file_concat("net/if.h" HAVE_NET_IF_H)
check_include_file_concat("netdb.h" HAVE_NETDB_H)
check_include_file_concat("netinet/in.h" HAVE_NETINET_IN_H)
check_include_file_concat("netinet/tcp.h" HAVE_NETINET_TCP_H)
+check_include_file("linux/tcp.h" HAVE_LINUX_TCP_H)
check_include_file_concat("pem.h" HAVE_PEM_H)
check_include_file_concat("poll.h" HAVE_POLL_H)
@@ -1465,16 +1472,16 @@ install(FILES COPYING DESTINATION ${CMAKE_DOC_DIR}/cmcurl)
#-----------------------------------------------------------------------------
if(0) # This code not needed for building within CMake.
-option(BUILD_TESTING "Build tests" "${PERL_FOUND}")
-if(NOT PERL_FOUND)
- message(STATUS "Perl not found, testing disabled.")
-elseif(BUILD_TESTING)
+cmake_dependent_option(BUILD_TESTING "Build tests"
+ ON "PERL_FOUND;NOT CURL_DISABLE_TESTS"
+ OFF)
+if(BUILD_TESTING)
add_subdirectory(tests)
endif()
# NTLM support requires crypto function adaptions from various SSL libs
# TODO alternative SSL libs tests for SSP1, GNUTLS, NSS
-if(NOT CURL_DISABLE_CRYPTO_AUTH AND (USE_OPENSSL OR USE_WINDOWS_SSPI OR USE_DARWINSSL OR USE_MBEDTLS OR USE_WIN32_CRYPTO))
+if(NOT CURL_DISABLE_CRYPTO_AUTH AND (USE_OPENSSL OR USE_DARWINSSL OR USE_MBEDTLS OR USE_WIN32_CRYPTO))
set(use_ntlm ON)
else()
set(use_ntlm OFF)
@@ -1493,7 +1500,7 @@ endmacro()
set(_items)
_add_if("SSL" SSL_ENABLED)
_add_if("IPv6" ENABLE_IPV6)
-_add_if("unix-sockets" USE_UNIX_SOCKETS)
+_add_if("unixsockets" USE_UNIX_SOCKETS)
_add_if("libz" HAVE_LIBZ)
_add_if("brotli" HAVE_BROTLI)
_add_if("zstd" HAVE_ZSTD)
@@ -1504,7 +1511,7 @@ _add_if("Largefile" (CURL_SIZEOF_CURL_OFF_T GREATER 4) AND
# TODO SSP1 (Schannel) check is missing
_add_if("SSPI" USE_WINDOWS_SSPI)
_add_if("GSS-API" HAVE_GSSAPI)
-_add_if("alt-svc" ENABLE_ALT_SVC)
+_add_if("alt-svc" NOT CURL_DISABLE_ALTSVC)
# TODO SSP1 missing for SPNEGO
_add_if("SPNEGO" NOT CURL_DISABLE_CRYPTO_AUTH AND
(HAVE_GSSAPI OR USE_WINDOWS_SSPI))
@@ -1512,7 +1519,7 @@ _add_if("Kerberos" NOT CURL_DISABLE_CRYPTO_AUTH AND
(HAVE_GSSAPI OR USE_WINDOWS_SSPI))
# NTLM support requires crypto function adaptions from various SSL libs
# TODO alternative SSL libs tests for SSP1, GNUTLS, NSS
-_add_if("NTLM" use_ntlm)
+_add_if("NTLM" use_ntlm OR USE_WINDOWS_SSPI)
# TODO missing option (autoconf: --enable-ntlm-wb)
_add_if("NTLM_WB" use_ntlm AND NOT CURL_DISABLE_HTTP AND NTLM_WB_ENABLED)
# TODO missing option (--enable-tls-srp), depends on GNUTLS_SRP/OPENSSL_SRP
@@ -1522,6 +1529,7 @@ _add_if("HTTP2" USE_NGHTTP2)
_add_if("HTTP3" USE_NGTCP2 OR USE_QUICHE)
_add_if("MultiSSL" CURL_WITH_MULTI_SSL)
_add_if("HTTPS-proxy" SSL_ENABLED AND (USE_OPENSSL OR USE_GNUTLS OR USE_NSS))
+_add_if("unicode" ENABLE_UNICODE)
string(REPLACE ";" " " SUPPORT_FEATURES "${_items}")
message(STATUS "Enabled features: ${SUPPORT_FEATURES}")
@@ -1542,6 +1550,7 @@ _add_if("LDAPS" NOT CURL_DISABLE_LDAPS AND
_add_if("DICT" NOT CURL_DISABLE_DICT)
_add_if("TFTP" NOT CURL_DISABLE_TFTP)
_add_if("GOPHER" NOT CURL_DISABLE_GOPHER)
+_add_if("GOPHERS" NOT CURL_DISABLE_GOPHER AND SSL_ENABLED)
_add_if("POP3" NOT CURL_DISABLE_POP3)
_add_if("POP3S" NOT CURL_DISABLE_POP3 AND SSL_ENABLED)
_add_if("IMAP" NOT CURL_DISABLE_IMAP)
@@ -1554,7 +1563,7 @@ _add_if("SCP" USE_LIBSSH2 OR USE_LIBSSH)
_add_if("SFTP" USE_LIBSSH2 OR USE_LIBSSH)
_add_if("RTSP" NOT CURL_DISABLE_RTSP)
_add_if("RTMP" USE_LIBRTMP)
-_add_if("MQTT" CURL_ENABLE_MQTT)
+_add_if("MQTT" NOT CURL_DISABLE_MQTT)
if(_items)
list(SORT _items)
endif()
diff --git a/Utilities/cmcurl/COPYING b/Utilities/cmcurl/COPYING
index 9d9e4af8d..48f144758 100644
--- a/Utilities/cmcurl/COPYING
+++ b/Utilities/cmcurl/COPYING
@@ -1,6 +1,6 @@
COPYRIGHT AND PERMISSION NOTICE
-Copyright (c) 1996 - 2020, Daniel Stenberg, <daniel@haxx.se>, and many
+Copyright (c) 1996 - 2021, Daniel Stenberg, <daniel@haxx.se>, and many
contributors, see the THANKS file.
All rights reserved.
diff --git a/Utilities/cmcurl/include/curl/curl.h b/Utilities/cmcurl/include/curl/curl.h
index e8e3ed137..676dce38e 100644
--- a/Utilities/cmcurl/include/curl/curl.h
+++ b/Utilities/cmcurl/include/curl/curl.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -24,7 +24,7 @@
/*
* If you have libcurl problems, all docs and details are found here:
- * https://curl.haxx.se/libcurl/
+ * https://curl.se/libcurl/
*
* curl-library mailing list subscription and unsubscription web interface:
* https://cool.haxx.se/mailman/listinfo/curl-library/
@@ -74,7 +74,7 @@
#if defined(_AIX) || defined(__NOVELL_LIBC__) || defined(__NetBSD__) || \
defined(__minix) || defined(__SYMBIAN32__) || defined(__INTEGRITY) || \
defined(ANDROID) || defined(__ANDROID__) || defined(__OpenBSD__) || \
- defined(__CYGWIN__) || \
+ defined(__CYGWIN__) || defined(AMIGA) || \
(defined(__FreeBSD_version) && (__FreeBSD_version < 800000))
#include <sys/select.h>
#endif
@@ -610,6 +610,7 @@ typedef enum {
error */
CURLE_HTTP3, /* 95 - An HTTP/3 layer problem */
CURLE_QUIC_CONNECT_ERROR, /* 96 - QUIC connection error */
+ CURLE_PROXY, /* 97 - proxy handshake error */
CURL_LAST /* never use! */
} CURLcode;
@@ -689,6 +690,48 @@ typedef enum {
#endif /*!CURL_NO_OLDIES*/
+/*
+ * Proxy error codes. Returned in CURLINFO_PROXY_ERROR if CURLE_PROXY was
+ * return for the transfers.
+ */
+typedef enum {
+ CURLPX_OK,
+ CURLPX_BAD_ADDRESS_TYPE,
+ CURLPX_BAD_VERSION,
+ CURLPX_CLOSED,
+ CURLPX_GSSAPI,
+ CURLPX_GSSAPI_PERMSG,
+ CURLPX_GSSAPI_PROTECTION,
+ CURLPX_IDENTD,
+ CURLPX_IDENTD_DIFFER,
+ CURLPX_LONG_HOSTNAME,
+ CURLPX_LONG_PASSWD,
+ CURLPX_LONG_USER,
+ CURLPX_NO_AUTH,
+ CURLPX_RECV_ADDRESS,
+ CURLPX_RECV_AUTH,
+ CURLPX_RECV_CONNECT,
+ CURLPX_RECV_REQACK,
+ CURLPX_REPLY_ADDRESS_TYPE_NOT_SUPPORTED,
+ CURLPX_REPLY_COMMAND_NOT_SUPPORTED,
+ CURLPX_REPLY_CONNECTION_REFUSED,
+ CURLPX_REPLY_GENERAL_SERVER_FAILURE,
+ CURLPX_REPLY_HOST_UNREACHABLE,
+ CURLPX_REPLY_NETWORK_UNREACHABLE,
+ CURLPX_REPLY_NOT_ALLOWED,
+ CURLPX_REPLY_TTL_EXPIRED,
+ CURLPX_REPLY_UNASSIGNED,
+ CURLPX_REQUEST_FAILED,
+ CURLPX_RESOLVE_HOST,
+ CURLPX_SEND_AUTH,
+ CURLPX_SEND_CONNECT,
+ CURLPX_SEND_REQUEST,
+ CURLPX_UNKNOWN_FAIL,
+ CURLPX_UNKNOWN_MODE,
+ CURLPX_USER_REJECTED,
+ CURLPX_LAST /* never use */
+} CURLproxycode;
+
/* This prototype applies to all conversion callbacks */
typedef CURLcode (*curl_conv_callback)(char *buffer, size_t length);
@@ -744,6 +787,7 @@ typedef enum {
#define CURLAUTH_DIGEST_IE (((unsigned long)1)<<4)
#define CURLAUTH_NTLM_WB (((unsigned long)1)<<5)
#define CURLAUTH_BEARER (((unsigned long)1)<<6)
+#define CURLAUTH_AWS_SIGV4 (((unsigned long)1)<<7)
#define CURLAUTH_ONLY (((unsigned long)1)<<31)
#define CURLAUTH_ANY (~CURLAUTH_DIGEST_IE)
#define CURLAUTH_ANYSAFE (~(CURLAUTH_BASIC|CURLAUTH_DIGEST_IE))
@@ -789,6 +833,7 @@ enum curl_khstat {
CURLKHSTAT_DEFER, /* do not accept it, but we can't answer right now so
this causes a CURLE_DEFER error but otherwise the
connection will be left intact etc */
+ CURLKHSTAT_FINE_REPLACE, /* accept and replace the wrong key*/
CURLKHSTAT_LAST /* not for use, only a marker for last-in-list */
};
@@ -905,13 +950,42 @@ typedef enum {
#define CURLHEADER_SEPARATE (1<<0)
/* CURLALTSVC_* are bits for the CURLOPT_ALTSVC_CTRL option */
-#define CURLALTSVC_IMMEDIATELY (1<<0)
-
#define CURLALTSVC_READONLYFILE (1<<2)
#define CURLALTSVC_H1 (1<<3)
#define CURLALTSVC_H2 (1<<4)
#define CURLALTSVC_H3 (1<<5)
+
+struct curl_hstsentry {
+ char *name;
+ size_t namelen;
+ unsigned int includeSubDomains:1;
+ char expire[18]; /* YYYYMMDD HH:MM:SS [null-terminated] */
+};
+
+struct curl_index {
+ size_t index; /* the provided entry's "index" or count */
+ size_t total; /* total number of entries to save */
+};
+
+typedef enum {
+ CURLSTS_OK,
+ CURLSTS_DONE,
+ CURLSTS_FAIL
+} CURLSTScode;
+
+typedef CURLSTScode (*curl_hstsread_callback)(CURL *easy,
+ struct curl_hstsentry *e,
+ void *userp);
+typedef CURLSTScode (*curl_hstswrite_callback)(CURL *easy,
+ struct curl_hstsentry *e,
+ struct curl_index *i,
+ void *userp);
+
+/* CURLHSTS_* are bits for the CURLOPT_HSTS option */
+#define CURLHSTS_ENABLE (long)(1<<0)
+#define CURLHSTS_READONLYFILE (long)(1<<1)
+
/* CURLPROTO_ defines are for the CURLOPT_*PROTOCOLS options */
#define CURLPROTO_HTTP (1<<0)
#define CURLPROTO_HTTPS (1<<1)
@@ -942,6 +1016,7 @@ typedef enum {
#define CURLPROTO_SMB (1<<26)
#define CURLPROTO_SMBS (1<<27)
#define CURLPROTO_MQTT (1<<28)
+#define CURLPROTO_GOPHERS (1<<29)
#define CURLPROTO_ALL (~0) /* enable everything */
/* long may be 32 or 64 bits, but we should never depend on anything else
@@ -958,17 +1033,27 @@ typedef enum {
#define CURLOPT(na,t,nu) na = t + nu
-/* handy aliases that make no run-time difference */
-#define CURLOPTTYPE_STRINGPOINT CURLOPTTYPE_OBJECTPOINT
+/* CURLOPT aliases that make no run-time difference */
+
+/* 'char *' argument to a string with a trailing zero */
+#define CURLOPTTYPE_STRINGPOINT CURLOPTTYPE_OBJECTPOINT
+
+/* 'struct curl_slist *' argument */
#define CURLOPTTYPE_SLISTPOINT CURLOPTTYPE_OBJECTPOINT
+/* 'void *' argument passed untouched to callback */
+#define CURLOPTTYPE_CBPOINT CURLOPTTYPE_OBJECTPOINT
+
+/* 'long' argument with a set of values/bitmask */
+#define CURLOPTTYPE_VALUES CURLOPTTYPE_LONG
+
/*
* All CURLOPT_* values.
*/
typedef enum {
/* This is the FILE * or void * the regular output should be written to. */
- CURLOPT(CURLOPT_WRITEDATA, CURLOPTTYPE_OBJECTPOINT, 1),
+ CURLOPT(CURLOPT_WRITEDATA, CURLOPTTYPE_CBPOINT, 1),
/* The full URL to get/put */
CURLOPT(CURLOPT_URL, CURLOPTTYPE_STRINGPOINT, 2),
@@ -991,7 +1076,7 @@ typedef enum {
/* not used */
/* Specified file stream to upload from (use as input): */
- CURLOPT(CURLOPT_READDATA, CURLOPTTYPE_OBJECTPOINT, 9),
+ CURLOPT(CURLOPT_READDATA, CURLOPTTYPE_CBPOINT, 9),
/* Buffer to receive error messages in, must be at least CURL_ERROR_SIZE
* bytes big. */
@@ -1076,7 +1161,7 @@ typedef enum {
/* send FILE * or void * to store headers to, if you use a callback it
is simply passed to the callback unmodified */
- CURLOPT(CURLOPT_HEADERDATA, CURLOPTTYPE_OBJECTPOINT, 29),
+ CURLOPT(CURLOPT_HEADERDATA, CURLOPTTYPE_CBPOINT, 29),
/* point to a file to read the initial cookies from, also enables
"cookie awareness" */
@@ -1084,10 +1169,10 @@ typedef enum {
/* What version to specifically try to use.
See CURL_SSLVERSION defines below. */
- CURLOPT(CURLOPT_SSLVERSION, CURLOPTTYPE_LONG, 32),
+ CURLOPT(CURLOPT_SSLVERSION, CURLOPTTYPE_VALUES, 32),
/* What kind of HTTP time condition to use, see defines */
- CURLOPT(CURLOPT_TIMECONDITION, CURLOPTTYPE_LONG, 33),
+ CURLOPT(CURLOPT_TIMECONDITION, CURLOPTTYPE_VALUES, 33),
/* Time to use with the above condition. Specified in number of seconds
since 1 Jan 1970 */
@@ -1141,7 +1226,7 @@ typedef enum {
/* Specify whether to read the user+password from the .netrc or the URL.
* This must be one of the CURL_NETRC_* enums below. */
- CURLOPT(CURLOPT_NETRC, CURLOPTTYPE_LONG, 51),
+ CURLOPT(CURLOPT_NETRC, CURLOPTTYPE_VALUES, 51),
/* use Location: Luke! */
CURLOPT(CURLOPT_FOLLOWLOCATION, CURLOPTTYPE_LONG, 52),
@@ -1162,8 +1247,8 @@ typedef enum {
/* Data passed to the CURLOPT_PROGRESSFUNCTION and CURLOPT_XFERINFOFUNCTION
callbacks */
- CURLOPT(CURLOPT_PROGRESSDATA, CURLOPTTYPE_OBJECTPOINT, 57),
-#define CURLOPT_XFERINFODATA CURLOPT_PROGRESSDATA
+ CURLOPT(CURLOPT_XFERINFODATA, CURLOPTTYPE_CBPOINT, 57),
+#define CURLOPT_PROGRESSDATA CURLOPT_XFERINFODATA
/* We want the referrer field set automatically when following locations */
CURLOPT(CURLOPT_AUTOREFERER, CURLOPTTYPE_LONG, 58),
@@ -1258,7 +1343,7 @@ typedef enum {
/* Specify which HTTP version to use! This must be set to one of the
CURL_HTTP_VERSION* enums set below. */
- CURLOPT(CURLOPT_HTTP_VERSION, CURLOPTTYPE_LONG, 84),
+ CURLOPT(CURLOPT_HTTP_VERSION, CURLOPTTYPE_VALUES, 84),
/* Specifically switch on or off the FTP engine's use of the EPSV command. By
default, that one will always be attempted before the more traditional
@@ -1296,7 +1381,7 @@ typedef enum {
CURLOPT(CURLOPT_DEBUGFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 94),
/* set the data for the debug function */
- CURLOPT(CURLOPT_DEBUGDATA, CURLOPTTYPE_OBJECTPOINT, 95),
+ CURLOPT(CURLOPT_DEBUGDATA, CURLOPTTYPE_CBPOINT, 95),
/* mark this as start of a cookie session */
CURLOPT(CURLOPT_COOKIESESSION, CURLOPTTYPE_LONG, 96),
@@ -1319,7 +1404,7 @@ typedef enum {
/* indicates type of proxy. accepted values are CURLPROXY_HTTP (default),
CURLPROXY_HTTPS, CURLPROXY_SOCKS4, CURLPROXY_SOCKS4A and
CURLPROXY_SOCKS5. */
- CURLOPT(CURLOPT_PROXYTYPE, CURLOPTTYPE_LONG, 101),
+ CURLOPT(CURLOPT_PROXYTYPE, CURLOPTTYPE_VALUES, 101),
/* Set the Accept-Encoding string. Use this to tell a server you would like
the response to be compressed. Before 7.21.6, this was known as
@@ -1345,7 +1430,7 @@ typedef enum {
/* Set this to a bitmask value to enable the particular authentications
methods you like. Use this in combination with CURLOPT_USERPWD.
Note that setting multiple bits may cause extra network round-trips. */
- CURLOPT(CURLOPT_HTTPAUTH, CURLOPTTYPE_LONG, 107),
+ CURLOPT(CURLOPT_HTTPAUTH, CURLOPTTYPE_VALUES, 107),
/* Set the ssl context callback function, currently only for OpenSSL or
WolfSSL ssl_ctx, or mbedTLS mbedtls_ssl_config in the second argument.
@@ -1354,7 +1439,7 @@ typedef enum {
/* Set the userdata for the ssl context callback function's third
argument */
- CURLOPT(CURLOPT_SSL_CTX_DATA, CURLOPTTYPE_OBJECTPOINT, 109),
+ CURLOPT(CURLOPT_SSL_CTX_DATA, CURLOPTTYPE_CBPOINT, 109),
/* FTP Option that causes missing dirs to be created on the remote server.
In 7.19.4 we introduced the convenience enums for this option using the
@@ -1365,7 +1450,7 @@ typedef enum {
/* Set this to a bitmask value to enable the particular authentications
methods you like. Use this in combination with CURLOPT_PROXYUSERPWD.
Note that setting multiple bits may cause extra network round-trips. */
- CURLOPT(CURLOPT_PROXYAUTH, CURLOPTTYPE_LONG, 111),
+ CURLOPT(CURLOPT_PROXYAUTH, CURLOPTTYPE_VALUES, 111),
/* FTP option that changes the timeout, in seconds, associated with
getting a response. This is different from transfer timeout time and
@@ -1377,7 +1462,7 @@ typedef enum {
/* Set this option to one of the CURL_IPRESOLVE_* defines (see below) to
tell libcurl to resolve names to those IP versions only. This only has
affect on systems with support for more than one, i.e IPv4 _and_ IPv6. */
- CURLOPT(CURLOPT_IPRESOLVE, CURLOPTTYPE_LONG, 113),
+ CURLOPT(CURLOPT_IPRESOLVE, CURLOPTTYPE_VALUES, 113),
/* Set this option to limit the size of a file that will be downloaded from
an HTTP or FTP server.
@@ -1412,7 +1497,7 @@ typedef enum {
CURLUSESSL_CONTROL - SSL for the control connection or fail
CURLUSESSL_ALL - SSL for all communication or fail
*/
- CURLOPT(CURLOPT_USE_SSL, CURLOPTTYPE_LONG, 119),
+ CURLOPT(CURLOPT_USE_SSL, CURLOPTTYPE_VALUES, 119),
/* The _LARGE version of the standard POSTFIELDSIZE option */
CURLOPT(CURLOPT_POSTFIELDSIZE_LARGE, CURLOPTTYPE_OFF_T, 120),
@@ -1438,10 +1523,10 @@ typedef enum {
CURLFTPAUTH_SSL - try "AUTH SSL" first, then TLS
CURLFTPAUTH_TLS - try "AUTH TLS" first, then SSL
*/
- CURLOPT(CURLOPT_FTPSSLAUTH, CURLOPTTYPE_LONG, 129),
+ CURLOPT(CURLOPT_FTPSSLAUTH, CURLOPTTYPE_VALUES, 129),
CURLOPT(CURLOPT_IOCTLFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 130),
- CURLOPT(CURLOPT_IOCTLDATA, CURLOPTTYPE_OBJECTPOINT, 131),
+ CURLOPT(CURLOPT_IOCTLDATA, CURLOPTTYPE_CBPOINT, 131),
/* 132 OBSOLETE. Gone in 7.16.0 */
/* 133 OBSOLETE. Gone in 7.16.0 */
@@ -1464,7 +1549,7 @@ typedef enum {
/* Select "file method" to use when doing FTP, see the curl_ftpmethod
above. */
- CURLOPT(CURLOPT_FTP_FILEMETHOD, CURLOPTTYPE_LONG, 138),
+ CURLOPT(CURLOPT_FTP_FILEMETHOD, CURLOPTTYPE_VALUES, 138),
/* Local port number to bind the socket to */
CURLOPT(CURLOPT_LOCALPORT, CURLOPTTYPE_LONG, 139),
@@ -1501,14 +1586,14 @@ typedef enum {
/* callback function for setting socket options */
CURLOPT(CURLOPT_SOCKOPTFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 148),
- CURLOPT(CURLOPT_SOCKOPTDATA, CURLOPTTYPE_OBJECTPOINT, 149),
+ CURLOPT(CURLOPT_SOCKOPTDATA, CURLOPTTYPE_CBPOINT, 149),
/* set to 0 to disable session ID re-use for this transfer, default is
enabled (== 1) */
CURLOPT(CURLOPT_SSL_SESSIONID_CACHE, CURLOPTTYPE_LONG, 150),
/* allowed SSH authentication methods */
- CURLOPT(CURLOPT_SSH_AUTH_TYPES, CURLOPTTYPE_LONG, 151),
+ CURLOPT(CURLOPT_SSH_AUTH_TYPES, CURLOPTTYPE_VALUES, 151),
/* Used by scp/sftp to do public/private key authentication */
CURLOPT(CURLOPT_SSH_PUBLIC_KEYFILE, CURLOPTTYPE_STRINGPOINT, 152),
@@ -1531,9 +1616,9 @@ typedef enum {
CURLOPT(CURLOPT_NEW_FILE_PERMS, CURLOPTTYPE_LONG, 159),
CURLOPT(CURLOPT_NEW_DIRECTORY_PERMS, CURLOPTTYPE_LONG, 160),
- /* Set the behaviour of POST when redirecting. Values must be set to one
+ /* Set the behavior of POST when redirecting. Values must be set to one
of CURL_REDIR* defines below. This used to be called CURLOPT_POST301 */
- CURLOPT(CURLOPT_POSTREDIR, CURLOPTTYPE_LONG, 161),
+ CURLOPT(CURLOPT_POSTREDIR, CURLOPTTYPE_VALUES, 161),
/* used by scp/sftp to verify the host's public key */
CURLOPT(CURLOPT_SSH_HOST_PUBLIC_KEY_MD5, CURLOPTTYPE_STRINGPOINT, 162),
@@ -1543,7 +1628,7 @@ typedef enum {
CURL_SOCKET_BAD. The callback should have type
curl_opensocket_callback */
CURLOPT(CURLOPT_OPENSOCKETFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 163),
- CURLOPT(CURLOPT_OPENSOCKETDATA, CURLOPTTYPE_OBJECTPOINT, 164),
+ CURLOPT(CURLOPT_OPENSOCKETDATA, CURLOPTTYPE_CBPOINT, 164),
/* POST volatile input fields. */
CURLOPT(CURLOPT_COPYPOSTFIELDS, CURLOPTTYPE_OBJECTPOINT, 165),
@@ -1553,7 +1638,7 @@ typedef enum {
/* Callback function for seeking in the input stream */
CURLOPT(CURLOPT_SEEKFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 167),
- CURLOPT(CURLOPT_SEEKDATA, CURLOPTTYPE_OBJECTPOINT, 168),
+ CURLOPT(CURLOPT_SEEKDATA, CURLOPTTYPE_CBPOINT, 168),
/* CRL file */
CURLOPT(CURLOPT_CRLFILE, CURLOPTTYPE_STRINGPOINT, 169),
@@ -1614,7 +1699,7 @@ typedef enum {
CURLOPT(CURLOPT_SSH_KEYFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 184),
/* set the SSH host key callback custom pointer */
- CURLOPT(CURLOPT_SSH_KEYDATA, CURLOPTTYPE_OBJECTPOINT, 185),
+ CURLOPT(CURLOPT_SSH_KEYDATA, CURLOPTTYPE_CBPOINT, 185),
/* set the SMTP mail originator */
CURLOPT(CURLOPT_MAIL_FROM, CURLOPTTYPE_STRINGPOINT, 186),
@@ -1626,7 +1711,7 @@ typedef enum {
CURLOPT(CURLOPT_FTP_USE_PRET, CURLOPTTYPE_LONG, 188),
/* RTSP request method (OPTIONS, SETUP, PLAY, etc...) */
- CURLOPT(CURLOPT_RTSP_REQUEST, CURLOPTTYPE_LONG, 189),
+ CURLOPT(CURLOPT_RTSP_REQUEST, CURLOPTTYPE_VALUES, 189),
/* The RTSP session identifier */
CURLOPT(CURLOPT_RTSP_SESSION_ID, CURLOPTTYPE_STRINGPOINT, 190),
@@ -1644,7 +1729,7 @@ typedef enum {
CURLOPT(CURLOPT_RTSP_SERVER_CSEQ, CURLOPTTYPE_LONG, 194),
/* The stream to pass to INTERLEAVEFUNCTION. */
- CURLOPT(CURLOPT_INTERLEAVEDATA, CURLOPTTYPE_OBJECTPOINT, 195),
+ CURLOPT(CURLOPT_INTERLEAVEDATA, CURLOPTTYPE_CBPOINT, 195),
/* Let the application define a custom write method for RTP data */
CURLOPT(CURLOPT_INTERLEAVEFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 196),
@@ -1664,10 +1749,10 @@ typedef enum {
CURLOPT(CURLOPT_FNMATCH_FUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 200),
/* Let the application define custom chunk data pointer */
- CURLOPT(CURLOPT_CHUNK_DATA, CURLOPTTYPE_OBJECTPOINT, 201),
+ CURLOPT(CURLOPT_CHUNK_DATA, CURLOPTTYPE_CBPOINT, 201),
/* FNMATCH_FUNCTION user pointer */
- CURLOPT(CURLOPT_FNMATCH_DATA, CURLOPTTYPE_OBJECTPOINT, 202),
+ CURLOPT(CURLOPT_FNMATCH_DATA, CURLOPTTYPE_CBPOINT, 202),
/* send linked-list of name:port:address sets */
CURLOPT(CURLOPT_RESOLVE, CURLOPTTYPE_SLISTPOINT, 203),
@@ -1696,10 +1781,10 @@ typedef enum {
/* Callback function for closing socket (instead of close(2)). The callback
should have type curl_closesocket_callback */
CURLOPT(CURLOPT_CLOSESOCKETFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 208),
- CURLOPT(CURLOPT_CLOSESOCKETDATA, CURLOPTTYPE_OBJECTPOINT, 209),
+ CURLOPT(CURLOPT_CLOSESOCKETDATA, CURLOPTTYPE_CBPOINT, 209),
/* allow GSSAPI credential delegation */
- CURLOPT(CURLOPT_GSSAPI_DELEGATION, CURLOPTTYPE_LONG, 210),
+ CURLOPT(CURLOPT_GSSAPI_DELEGATION, CURLOPTTYPE_VALUES, 210),
/* Set the name servers to use for DNS resolution */
CURLOPT(CURLOPT_DNS_SERVERS, CURLOPTTYPE_STRINGPOINT, 211),
@@ -1716,7 +1801,7 @@ typedef enum {
CURLOPT(CURLOPT_TCP_KEEPINTVL, CURLOPTTYPE_LONG, 215),
/* Enable/disable specific SSL features with a bitmask, see CURLSSLOPT_* */
- CURLOPT(CURLOPT_SSL_OPTIONS, CURLOPTTYPE_LONG, 216),
+ CURLOPT(CURLOPT_SSL_OPTIONS, CURLOPTTYPE_VALUES, 216),
/* Set the SMTP auth originator */
CURLOPT(CURLOPT_MAIL_AUTH, CURLOPTTYPE_STRINGPOINT, 217),
@@ -1763,7 +1848,7 @@ typedef enum {
CURLOPT(CURLOPT_PROXYHEADER, CURLOPTTYPE_SLISTPOINT, 228),
/* Pass in a bitmask of "header options" */
- CURLOPT(CURLOPT_HEADEROPT, CURLOPTTYPE_LONG, 229),
+ CURLOPT(CURLOPT_HEADEROPT, CURLOPTTYPE_VALUES, 229),
/* The public key in DER form used to validate the peer public key
this option is used only if SSL_VERIFYPEER is true */
@@ -1835,7 +1920,7 @@ typedef enum {
/* What version to specifically try to use for proxy.
See CURL_SSLVERSION defines below. */
- CURLOPT(CURLOPT_PROXY_SSLVERSION, CURLOPTTYPE_LONG, 250),
+ CURLOPT(CURLOPT_PROXY_SSLVERSION, CURLOPTTYPE_VALUES, 250),
/* Set a username for authenticated TLS for proxy */
CURLOPT(CURLOPT_PROXY_TLSAUTH_USERNAME, CURLOPTTYPE_STRINGPOINT, 251),
@@ -1909,7 +1994,7 @@ typedef enum {
CURLOPT(CURLOPT_RESOLVER_START_FUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 272),
/* User data to pass to the resolver start callback. */
- CURLOPT(CURLOPT_RESOLVER_START_DATA, CURLOPTTYPE_OBJECTPOINT, 273),
+ CURLOPT(CURLOPT_RESOLVER_START_DATA, CURLOPTTYPE_CBPOINT, 273),
/* send HAProxy PROXY protocol header? */
CURLOPT(CURLOPT_HAPROXYPROTOCOL, CURLOPTTYPE_LONG, 274),
@@ -1940,7 +2025,7 @@ typedef enum {
CURLOPT(CURLOPT_TRAILERFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 283),
/* pointer to be passed to HTTP_TRAILER_FUNCTION */
- CURLOPT(CURLOPT_TRAILERDATA, CURLOPTTYPE_OBJECTPOINT, 284),
+ CURLOPT(CURLOPT_TRAILERDATA, CURLOPTTYPE_CBPOINT, 284),
/* set this to 1L to allow HTTP/0.9 responses or 0L to disallow */
CURLOPT(CURLOPT_HTTP09_ALLOWED, CURLOPTTYPE_LONG, 285),
@@ -1971,6 +2056,28 @@ typedef enum {
CURLOPT(CURLOPT_PROXY_ISSUERCERT, CURLOPTTYPE_STRINGPOINT, 296),
CURLOPT(CURLOPT_PROXY_ISSUERCERT_BLOB, CURLOPTTYPE_BLOB, 297),
+ /* the EC curves requested by the TLS client (RFC 8422, 5.1);
+ * OpenSSL support via 'set_groups'/'set_curves':
+ * https://www.openssl.org/docs/manmaster/man3/SSL_CTX_set1_groups.html
+ */
+ CURLOPT(CURLOPT_SSL_EC_CURVES, CURLOPTTYPE_STRINGPOINT, 298),
+
+ /* HSTS bitmask */
+ CURLOPT(CURLOPT_HSTS_CTRL, CURLOPTTYPE_LONG, 299),
+ /* HSTS file name */
+ CURLOPT(CURLOPT_HSTS, CURLOPTTYPE_STRINGPOINT, 300),
+
+ /* HSTS read callback */
+ CURLOPT(CURLOPT_HSTSREADFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 301),
+ CURLOPT(CURLOPT_HSTSREADDATA, CURLOPTTYPE_CBPOINT, 302),
+
+ /* HSTS write callback */
+ CURLOPT(CURLOPT_HSTSWRITEFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 303),
+ CURLOPT(CURLOPT_HSTSWRITEDATA, CURLOPTTYPE_CBPOINT, 304),
+
+ /* Parameters for V4 signature */
+ CURLOPT(CURLOPT_AWS_SIGV4, CURLOPTTYPE_STRINGPOINT, 305),
+
CURLOPT_LASTENTRY /* the last unused */
} CURLoption;
@@ -2643,8 +2750,9 @@ typedef enum {
CURLINFO_APPCONNECT_TIME_T = CURLINFO_OFF_T + 56,
CURLINFO_RETRY_AFTER = CURLINFO_OFF_T + 57,
CURLINFO_EFFECTIVE_METHOD = CURLINFO_STRING + 58,
+ CURLINFO_PROXY_ERROR = CURLINFO_LONG + 59,
- CURLINFO_LASTONE = 58
+ CURLINFO_LASTONE = 59
} CURLINFO;
/* CURLINFO_RESPONSE_CODE is the new name for the option previously known as
@@ -2746,6 +2854,7 @@ typedef enum {
CURLVERSION_SIXTH,
CURLVERSION_SEVENTH,
CURLVERSION_EIGHTH,
+ CURLVERSION_NINTH,
CURLVERSION_LAST /* never actually use this */
} CURLversion;
@@ -2754,7 +2863,7 @@ typedef enum {
meant to be a built-in version number for what kind of struct the caller
expects. If the struct ever changes, we redefine the NOW to another enum
from above. */
-#define CURLVERSION_NOW CURLVERSION_EIGHTH
+#define CURLVERSION_NOW CURLVERSION_NINTH
struct curl_version_info_data {
CURLversion age; /* age of the returned struct */
@@ -2805,6 +2914,8 @@ struct curl_version_info_data {
(MAJOR << 24) | (MINOR << 12) | PATCH */
const char *zstd_version; /* human readable string. */
+ /* These fields were added in CURLVERSION_NINTH */
+ const char *hyper_version; /* human readable string. */
};
typedef struct curl_version_info_data curl_version_info_data;
@@ -2841,6 +2952,7 @@ typedef struct curl_version_info_data curl_version_info_data;
#define CURL_VERSION_HTTP3 (1<<25) /* HTTP3 support built-in */
#define CURL_VERSION_ZSTD (1<<26) /* zstd features are present */
#define CURL_VERSION_UNICODE (1<<27) /* Unicode support on Windows */
+#define CURL_VERSION_HSTS (1<<28) /* HSTS is supported */
/*
* NAME curl_version_info()
@@ -2903,6 +3015,7 @@ CURL_EXTERN CURLcode curl_easy_pause(CURL *handle, int bitmask);
#include "easy.h" /* nothing in curl is fun without the easy stuff */
#include "multi.h"
#include "urlapi.h"
+#include "options.h"
/* the typechecker doesn't work in C++ (yet) */
#if defined(__GNUC__) && defined(__GNUC_MINOR__) && \
diff --git a/Utilities/cmcurl/include/curl/curlver.h b/Utilities/cmcurl/include/curl/curlver.h
index a881bb7ca..71a64505a 100644
--- a/Utilities/cmcurl/include/curl/curlver.h
+++ b/Utilities/cmcurl/include/curl/curlver.h
@@ -11,7 +11,7 @@
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -30,12 +30,12 @@
/* This is the version number of the libcurl package from which this header
file origins: */
-#define LIBCURL_VERSION "7.72.0"
+#define LIBCURL_VERSION "7.75.0"
/* The numeric version number is also available "in parts" by using these
defines: */
#define LIBCURL_VERSION_MAJOR 7
-#define LIBCURL_VERSION_MINOR 72
+#define LIBCURL_VERSION_MINOR 75
#define LIBCURL_VERSION_PATCH 0
/* This is the numeric version of the libcurl version number, meant for easier
@@ -57,7 +57,7 @@
CURL_VERSION_BITS() macro since curl's own configure script greps for it
and needs it to contain the full number.
*/
-#define LIBCURL_VERSION_NUM 0x074800
+#define LIBCURL_VERSION_NUM 0x074b00
/*
* This is the date and time when the full source package was created. The
diff --git a/Utilities/cmcurl/include/curl/easy.h b/Utilities/cmcurl/include/curl/easy.h
index 9aef13396..2dbfb26b5 100644
--- a/Utilities/cmcurl/include/curl/easy.h
+++ b/Utilities/cmcurl/include/curl/easy.h
@@ -11,7 +11,7 @@
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/include/curl/mprintf.h b/Utilities/cmcurl/include/curl/mprintf.h
index f615ed7d6..3549552db 100644
--- a/Utilities/cmcurl/include/curl/mprintf.h
+++ b/Utilities/cmcurl/include/curl/mprintf.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
diff --git a/Utilities/cmcurl/include/curl/multi.h b/Utilities/cmcurl/include/curl/multi.h
index b911ba92d..37f9829b3 100644
--- a/Utilities/cmcurl/include/curl/multi.h
+++ b/Utilities/cmcurl/include/curl/multi.h
@@ -11,7 +11,7 @@
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/include/curl/options.h b/Utilities/cmcurl/include/curl/options.h
new file mode 100644
index 000000000..14373b551
--- /dev/null
+++ b/Utilities/cmcurl/include/curl/options.h
@@ -0,0 +1,68 @@
+#ifndef CURLINC_OPTIONS_H
+#define CURLINC_OPTIONS_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2018 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.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.
+ *
+ ***************************************************************************/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef enum {
+ CURLOT_LONG, /* long (a range of values) */
+ CURLOT_VALUES, /* (a defined set or bitmask) */
+ CURLOT_OFF_T, /* curl_off_t (a range of values) */
+ CURLOT_OBJECT, /* pointer (void *) */
+ CURLOT_STRING, /* (char * to zero terminated buffer) */
+ CURLOT_SLIST, /* (struct curl_slist *) */
+ CURLOT_CBPTR, /* (void * passed as-is to a callback) */
+ CURLOT_BLOB, /* blob (struct curl_blob *) */
+ CURLOT_FUNCTION /* function pointer */
+} curl_easytype;
+
+/* Flag bits */
+
+/* "alias" means it is provided for old programs to remain functional,
+ we prefer another name */
+#define CURLOT_FLAG_ALIAS (1<<0)
+
+/* The CURLOPTTYPE_* id ranges can still be used to figure out what type/size
+ to use for curl_easy_setopt() for the given id */
+struct curl_easyoption {
+ const char *name;
+ CURLoption id;
+ curl_easytype type;
+ unsigned int flags;
+};
+
+CURL_EXTERN const struct curl_easyoption *
+curl_easy_option_by_name(const char *name);
+
+CURL_EXTERN const struct curl_easyoption *
+curl_easy_option_by_id (CURLoption id);
+
+CURL_EXTERN const struct curl_easyoption *
+curl_easy_option_next(const struct curl_easyoption *prev);
+
+#ifdef __cplusplus
+} /* end of extern "C" */
+#endif
+#endif /* CURLINC_OPTIONS_H */
diff --git a/Utilities/cmcurl/include/curl/stdcheaders.h b/Utilities/cmcurl/include/curl/stdcheaders.h
index a6bdc1a25..60596c756 100644
--- a/Utilities/cmcurl/include/curl/stdcheaders.h
+++ b/Utilities/cmcurl/include/curl/stdcheaders.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
diff --git a/Utilities/cmcurl/include/curl/system.h b/Utilities/cmcurl/include/curl/system.h
index 867af6141..faf8fcf84 100644
--- a/Utilities/cmcurl/include/curl/system.h
+++ b/Utilities/cmcurl/include/curl/system.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
diff --git a/Utilities/cmcurl/include/curl/typecheck-gcc.h b/Utilities/cmcurl/include/curl/typecheck-gcc.h
index f8cb921f2..230f4c106 100644
--- a/Utilities/cmcurl/include/curl/typecheck-gcc.h
+++ b/Utilities/cmcurl/include/curl/typecheck-gcc.h
@@ -11,7 +11,7 @@
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -273,6 +273,7 @@ CURLWARNING(_curl_easy_getinfo_err_curl_off_t,
(option) == CURLOPT_FTPPORT || \
(option) == CURLOPT_FTP_ACCOUNT || \
(option) == CURLOPT_FTP_ALTERNATIVE_TO_USER || \
+ (option) == CURLOPT_HSTS || \
(option) == CURLOPT_INTERFACE || \
(option) == CURLOPT_ISSUERCERT || \
(option) == CURLOPT_KEYPASSWD || \
@@ -292,6 +293,7 @@ CURLWARNING(_curl_easy_getinfo_err_curl_off_t,
(option) == CURLOPT_PROXY_CAINFO || \
(option) == CURLOPT_PROXY_CAPATH || \
(option) == CURLOPT_PROXY_CRLFILE || \
+ (option) == CURLOPT_PROXY_ISSUERCERT || \
(option) == CURLOPT_PROXY_KEYPASSWD || \
(option) == CURLOPT_PROXY_PINNEDPUBLICKEY || \
(option) == CURLOPT_PROXY_SERVICE_NAME || \
@@ -332,8 +334,10 @@ CURLWARNING(_curl_easy_getinfo_err_curl_off_t,
(option) == CURLOPT_URL || \
(option) == CURLOPT_USERAGENT || \
(option) == CURLOPT_USERNAME || \
+ (option) == CURLOPT_AWS_SIGV4 || \
(option) == CURLOPT_USERPWD || \
(option) == CURLOPT_XOAUTH2_BEARER || \
+ (option) == CURLOPT_SSL_EC_CURVES || \
0)
/* evaluates to true if option takes a curl_write_callback argument */
@@ -354,10 +358,11 @@ CURLWARNING(_curl_easy_getinfo_err_curl_off_t,
(option) == CURLOPT_DEBUGDATA || \
(option) == CURLOPT_FNMATCH_DATA || \
(option) == CURLOPT_HEADERDATA || \
+ (option) == CURLOPT_HSTSREADDATA || \
+ (option) == CURLOPT_HSTSWRITEDATA || \
(option) == CURLOPT_INTERLEAVEDATA || \
(option) == CURLOPT_IOCTLDATA || \
(option) == CURLOPT_OPENSOCKETDATA || \
- (option) == CURLOPT_PRIVATE || \
(option) == CURLOPT_PROGRESSDATA || \
(option) == CURLOPT_READDATA || \
(option) == CURLOPT_SEEKDATA || \
diff --git a/Utilities/cmcurl/include/curl/urlapi.h b/Utilities/cmcurl/include/curl/urlapi.h
index f2d06770d..7343cb659 100644
--- a/Utilities/cmcurl/include/curl/urlapi.h
+++ b/Utilities/cmcurl/include/curl/urlapi.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2018 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2018 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/CMakeLists.txt b/Utilities/cmcurl/lib/CMakeLists.txt
index 32bea68c3..703d0ad02 100644
--- a/Utilities/cmcurl/lib/CMakeLists.txt
+++ b/Utilities/cmcurl/lib/CMakeLists.txt
@@ -9,7 +9,7 @@
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
-# are also available at https://curl.haxx.se/docs/copyright.html.
+# 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
@@ -39,7 +39,7 @@ list(APPEND HHEADERS
${CMAKE_CURRENT_BINARY_DIR}/curl_config.h
)
-if(MSVC AND NOT CURL_STATICLIB)
+if(WIN32 AND NOT CURL_STATICLIB)
list(APPEND CSOURCES libcurl.rc)
endif()
@@ -50,15 +50,6 @@ endif()
# # strtoofft.c - specify later
# )
-# # if we have Kerberos 4, right now this is never on
-# #OPTION(CURL_KRB4 "Use Kerberos 4" OFF)
-# IF(CURL_KRB4)
-# SET(CSOURCES ${CSOURCES}
-# krb4.c
-# security.c
-# )
-# ENDIF(CURL_KRB4)
-
# #OPTION(CURL_MALLOC_DEBUG "Debug mallocs in Curl" OFF)
# MARK_AS_ADVANCED(CURL_MALLOC_DEBUG)
# IF(CURL_MALLOC_DEBUG)
diff --git a/Utilities/cmcurl/lib/Makefile.inc b/Utilities/cmcurl/lib/Makefile.inc
index ae3f961cf..e8d2259f2 100644
--- a/Utilities/cmcurl/lib/Makefile.inc
+++ b/Utilities/cmcurl/lib/Makefile.inc
@@ -5,11 +5,11 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
-# are also available at https://curl.haxx.se/docs/copyright.html.
+# 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
@@ -20,67 +20,314 @@
#
###########################################################################
-LIB_VAUTH_CFILES = vauth/cleartext.c vauth/cram.c vauth/digest.c \
- vauth/digest_sspi.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 \
+LIB_VAUTH_CFILES = \
+ vauth/cleartext.c \
+ vauth/cram.c \
+ vauth/digest.c \
+ vauth/digest_sspi.c \
+ vauth/krb5_gssapi.c \
+ vauth/krb5_sspi.c \
+ vauth/ntlm.c \
+ vauth/ntlm_sspi.c \
+ vauth/oauth2.c \
+ vauth/spnego_gssapi.c \
+ vauth/spnego_sspi.c \
vauth/vauth.c
-LIB_VAUTH_HFILES = vauth/digest.h vauth/ntlm.h vauth/vauth.h
+LIB_VAUTH_HFILES = \
+ vauth/digest.h \
+ vauth/ntlm.h \
+ vauth/vauth.h
-LIB_VTLS_CFILES = vtls/bearssl.c vtls/gskit.c vtls/gtls.c vtls/keylog.c \
- vtls/mbedtls.c vtls/mbedtls_threadlock.c vtls/mesalink.c vtls/nss.c \
- vtls/openssl.c vtls/schannel.c vtls/schannel_verify.c vtls/sectransp.c \
- vtls/vtls.c vtls/wolfssl.c
+LIB_VTLS_CFILES = \
+ vtls/bearssl.c \
+ vtls/gskit.c \
+ vtls/gtls.c \
+ vtls/keylog.c \
+ vtls/mbedtls.c \
+ vtls/mbedtls_threadlock.c \
+ vtls/mesalink.c \
+ vtls/nss.c \
+ vtls/openssl.c \
+ vtls/schannel.c \
+ vtls/schannel_verify.c \
+ vtls/sectransp.c \
+ vtls/vtls.c \
+ vtls/wolfssl.c
-LIB_VTLS_HFILES = vtls/bearssl.h vtls/gskit.h vtls/gtls.h vtls/keylog.h \
- vtls/mbedtls.h vtls/mbedtls_threadlock.h vtls/mesalink.h vtls/nssg.h \
- vtls/openssl.h vtls/schannel.h vtls/sectransp.h vtls/vtls.h vtls/wolfssl.h
+LIB_VTLS_HFILES = \
+ vtls/bearssl.h \
+ vtls/gskit.h \
+ vtls/gtls.h \
+ vtls/keylog.h \
+ vtls/mbedtls.h \
+ vtls/mbedtls_threadlock.h \
+ vtls/mesalink.h \
+ vtls/nssg.h \
+ vtls/openssl.h \
+ vtls/schannel.h \
+ vtls/sectransp.h \
+ vtls/vtls.h \
+ vtls/wolfssl.h
-LIB_VQUIC_CFILES = vquic/ngtcp2.c vquic/quiche.c vquic/vquic.c
+LIB_VQUIC_CFILES = \
+ vquic/ngtcp2.c \
+ vquic/quiche.c \
+ vquic/vquic.c
-LIB_VQUIC_HFILES = vquic/ngtcp2.h vquic/quiche.h vquic/vquic.h
+LIB_VQUIC_HFILES = \
+ vquic/ngtcp2.h \
+ vquic/quiche.h \
+ vquic/vquic.h
-LIB_VSSH_CFILES = vssh/libssh.c vssh/libssh2.c vssh/wolfssh.c
+LIB_VSSH_CFILES = \
+ vssh/libssh.c \
+ vssh/libssh2.c \
+ vssh/wolfssh.c
-LIB_VSSH_HFILES = vssh/ssh.h
+LIB_VSSH_HFILES = \
+ vssh/ssh.h
-LIB_CFILES = altsvc.c amigaos.c asyn-ares.c asyn-thread.c base64.c \
- conncache.c connect.c content_encoding.c cookie.c curl_addrinfo.c \
- curl_ctype.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_ntlm_wb.c curl_path.c curl_range.c curl_rtmp.c \
- curl_sasl.c curl_sspi.c curl_threads.c dict.c dotdot.c easy.c escape.c \
- file.c fileinfo.c formdata.c ftp.c url.c ftplistparser.c getenv.c getinfo.c \
- gopher.c hash.c hmac.c hostasyn.c hostcheck.c hostip.c hostip4.c hostip6.c \
- hostsyn.c http.c http2.c http_chunks.c http_digest.c http_negotiate.c \
- http_ntlm.c http_proxy.c idn_win32.c if2ip.c imap.c inet_ntop.c inet_pton.c \
- krb5.c ldap.c llist.c md4.c md5.c memdebug.c mime.c mprintf.c mqtt.c \
- multi.c netrc.c non-ascii.c nonblock.c openldap.c parsedate.c pingpong.c \
- pop3.c progress.c psl.c doh.c rand.c rename.c rtsp.c security.c select.c \
- sendf.c setopt.c sha256.c share.c slist.c smb.c smtp.c socketpair.c socks.c \
- socks_gssapi.c socks_sspi.c speedcheck.c splay.c strcase.c strdup.c \
- strerror.c strtok.c strtoofft.c system_win32.c telnet.c tftp.c timeval.c \
- transfer.c urlapi.c version.c warnless.c wildcard.c x509asn1.c dynbuf.c \
- version_win32.c
+LIB_CFILES = \
+ altsvc.c \
+ amigaos.c \
+ asyn-ares.c \
+ asyn-thread.c \
+ base64.c \
+ c-hyper.c \
+ conncache.c \
+ connect.c \
+ content_encoding.c \
+ cookie.c \
+ curl_addrinfo.c \
+ curl_ctype.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_ntlm_wb.c \
+ curl_path.c \
+ curl_range.c \
+ curl_rtmp.c \
+ curl_sasl.c \
+ curl_sspi.c \
+ curl_threads.c \
+ dict.c \
+ doh.c \
+ dotdot.c \
+ dynbuf.c \
+ easy.c \
+ easygetopt.c \
+ easyoptions.c \
+ escape.c \
+ file.c \
+ fileinfo.c \
+ formdata.c \
+ ftp.c \
+ ftplistparser.c \
+ getenv.c \
+ getinfo.c \
+ gopher.c \
+ hash.c \
+ hmac.c \
+ hostasyn.c \
+ hostcheck.c \
+ hostip.c \
+ hostip4.c \
+ hostip6.c \
+ hostsyn.c \
+ hsts.c \
+ http.c \
+ http2.c \
+ http_chunks.c \
+ http_digest.c \
+ http_negotiate.c \
+ http_ntlm.c \
+ http_proxy.c \
+ http_aws_sigv4.c \
+ idn_win32.c \
+ if2ip.c \
+ imap.c \
+ inet_ntop.c \
+ inet_pton.c \
+ krb5.c \
+ ldap.c \
+ llist.c \
+ md4.c \
+ md5.c \
+ memdebug.c \
+ mime.c \
+ mprintf.c \
+ mqtt.c \
+ multi.c \
+ netrc.c \
+ non-ascii.c \
+ nonblock.c \
+ openldap.c \
+ parsedate.c \
+ pingpong.c \
+ pop3.c \
+ progress.c \
+ psl.c \
+ rand.c \
+ rename.c \
+ rtsp.c \
+ select.c \
+ sendf.c \
+ setopt.c \
+ sha256.c \
+ share.c \
+ slist.c \
+ smb.c \
+ smtp.c \
+ socketpair.c \
+ socks.c \
+ socks_gssapi.c \
+ socks_sspi.c \
+ speedcheck.c \
+ splay.c \
+ strcase.c \
+ strdup.c \
+ strerror.c \
+ strtok.c \
+ strtoofft.c \
+ system_win32.c \
+ telnet.c \
+ tftp.c \
+ timeval.c \
+ transfer.c \
+ url.c \
+ urlapi.c \
+ version.c \
+ version_win32.c \
+ warnless.c \
+ wildcard.c \
+ x509asn1.c
-LIB_HFILES = altsvc.h amigaos.h arpa_telnet.h asyn.h conncache.h connect.h \
- content_encoding.h cookie.h curl_addrinfo.h curl_base64.h curl_ctype.h \
- curl_des.h curl_endian.h curl_fnmatch.h curl_get_line.h curl_gethostname.h \
- curl_gssapi.h curl_hmac.h curl_ldap.h curl_md4.h curl_md5.h curl_memory.h \
- curl_memrchr.h curl_multibyte.h curl_ntlm_core.h curl_ntlm_wb.h curl_path.h \
- curl_printf.h curl_range.h curl_rtmp.h curl_sasl.h curl_sec.h curl_setup.h \
- curl_setup_once.h curl_sha256.h curl_sspi.h curl_threads.h curlx.h dict.h \
- dotdot.h easyif.h escape.h file.h fileinfo.h formdata.h ftp.h url.h \
- ftplistparser.h getinfo.h gopher.h hash.h hostcheck.h hostip.h http.h \
- http2.h http_chunks.h http_digest.h http_negotiate.h http_ntlm.h \
- http_proxy.h if2ip.h imap.h inet_ntop.h inet_pton.h llist.h memdebug.h \
- mime.h mqtt.h multihandle.h multiif.h netrc.h non-ascii.h nonblock.h \
- parsedate.h pingpong.h pop3.h progress.h psl.h doh.h quic.h rand.h rename.h \
- rtsp.h select.h sendf.h setopt.h setup-vms.h share.h sigpipe.h slist.h \
- smb.h smtp.h sockaddr.h socketpair.h socks.h speedcheck.h splay.h strcase.h \
- strdup.h strerror.h strtok.h strtoofft.h system_win32.h telnet.h tftp.h \
- timeval.h transfer.h urlapi-int.h urldata.h warnless.h wildcard.h \
- x509asn1.h dynbuf.h version_win32.h
+LIB_HFILES = \
+ altsvc.h \
+ amigaos.h \
+ arpa_telnet.h \
+ asyn.h \
+ c-hyper.h \
+ conncache.h \
+ connect.h \
+ content_encoding.h \
+ cookie.h \
+ curl_addrinfo.h \
+ curl_base64.h \
+ curl_ctype.h \
+ curl_des.h \
+ curl_endian.h \
+ curl_fnmatch.h \
+ curl_get_line.h \
+ curl_gethostname.h \
+ curl_gssapi.h \
+ curl_hmac.h \
+ curl_krb5.h \
+ curl_ldap.h \
+ curl_md4.h \
+ curl_md5.h \
+ curl_memory.h \
+ curl_memrchr.h \
+ curl_multibyte.h \
+ curl_ntlm_core.h \
+ curl_ntlm_wb.h \
+ curl_path.h \
+ curl_printf.h \
+ curl_range.h \
+ curl_rtmp.h \
+ curl_sasl.h \
+ curl_setup.h \
+ curl_setup_once.h \
+ curl_sha256.h \
+ curl_sspi.h \
+ curl_threads.h \
+ curlx.h \
+ dict.h \
+ doh.h \
+ dotdot.h \
+ dynbuf.h \
+ easyif.h \
+ easyoptions.h \
+ escape.h \
+ file.h \
+ fileinfo.h \
+ formdata.h \
+ ftp.h \
+ ftplistparser.h \
+ getinfo.h \
+ gopher.h \
+ hash.h \
+ hostcheck.h \
+ hostip.h \
+ hsts.h \
+ http.h \
+ http2.h \
+ http_chunks.h \
+ http_digest.h \
+ http_negotiate.h \
+ http_ntlm.h \
+ http_proxy.h \
+ http_aws_sigv4.h \
+ if2ip.h \
+ imap.h \
+ inet_ntop.h \
+ inet_pton.h \
+ llist.h \
+ memdebug.h \
+ mime.h \
+ mqtt.h \
+ multihandle.h \
+ multiif.h \
+ netrc.h \
+ non-ascii.h \
+ nonblock.h \
+ parsedate.h \
+ pingpong.h \
+ pop3.h \
+ progress.h \
+ psl.h \
+ quic.h \
+ rand.h \
+ rename.h \
+ rtsp.h \
+ select.h \
+ sendf.h \
+ setopt.h \
+ setup-vms.h \
+ share.h \
+ sigpipe.h \
+ slist.h \
+ smb.h \
+ smtp.h \
+ sockaddr.h \
+ socketpair.h \
+ socks.h \
+ speedcheck.h \
+ splay.h \
+ strcase.h \
+ strdup.h \
+ strerror.h \
+ strtok.h \
+ strtoofft.h \
+ system_win32.h \
+ telnet.h \
+ tftp.h \
+ timeval.h \
+ transfer.h \
+ url.h \
+ urlapi-int.h \
+ urldata.h \
+ version_win32.h \
+ warnless.h \
+ wildcard.h \
+ x509asn1.h
LIB_RCFILES = libcurl.rc
diff --git a/Utilities/cmcurl/lib/altsvc.c b/Utilities/cmcurl/lib/altsvc.c
index c2ec489d9..4ab77fdfc 100644
--- a/Utilities/cmcurl/lib/altsvc.c
+++ b/Utilities/cmcurl/lib/altsvc.c
@@ -9,7 +9,7 @@
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -25,7 +25,7 @@
*/
#include "curl_setup.h"
-#if !defined(CURL_DISABLE_HTTP) && defined(USE_ALTSVC)
+#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_ALTSVC)
#include <curl/curl.h>
#include "urldata.h"
#include "altsvc.h"
@@ -302,11 +302,12 @@ CURLcode Curl_altsvc_ctrl(struct altsvcinfo *asi, const long ctrl)
* Curl_altsvc_cleanup() frees an altsvc cache instance and all associated
* resources.
*/
-void Curl_altsvc_cleanup(struct altsvcinfo *altsvc)
+void Curl_altsvc_cleanup(struct altsvcinfo **altsvcp)
{
- struct curl_llist_element *e;
- struct curl_llist_element *n;
- if(altsvc) {
+ struct Curl_llist_element *e;
+ struct Curl_llist_element *n;
+ if(*altsvcp) {
+ struct altsvcinfo *altsvc = *altsvcp;
for(e = altsvc->list.head; e; e = n) {
struct altsvc *as = e->ptr;
n = e->next;
@@ -314,6 +315,7 @@ void Curl_altsvc_cleanup(struct altsvcinfo *altsvc)
}
free(altsvc->filename);
free(altsvc);
+ *altsvcp = NULL; /* clear the pointer */
}
}
@@ -323,8 +325,8 @@ void Curl_altsvc_cleanup(struct altsvcinfo *altsvc)
CURLcode Curl_altsvc_save(struct Curl_easy *data,
struct altsvcinfo *altsvc, const char *file)
{
- struct curl_llist_element *e;
- struct curl_llist_element *n;
+ struct Curl_llist_element *e;
+ struct Curl_llist_element *n;
CURLcode result = CURLE_OK;
FILE *out;
char *tempstore;
@@ -353,7 +355,7 @@ CURLcode Curl_altsvc_save(struct Curl_easy *data,
if(!out)
result = CURLE_WRITE_ERROR;
else {
- fputs("# Your alt-svc cache. https://curl.haxx.se/docs/alt-svc.html\n"
+ fputs("# Your alt-svc cache. https://curl.se/docs/alt-svc.html\n"
"# This file was generated by libcurl! Edit at your own risk.\n",
out);
for(e = altsvc->list.head; e; e = n) {
@@ -399,8 +401,8 @@ static CURLcode getalnum(const char **ptr, char *alpnbuf, size_t buflen)
static void altsvc_flush(struct altsvcinfo *asi, enum alpnid srcalpnid,
const char *srchost, unsigned short srcport)
{
- struct curl_llist_element *e;
- struct curl_llist_element *n;
+ struct Curl_llist_element *e;
+ struct Curl_llist_element *n;
for(e = asi->list.head; e; e = n) {
struct altsvc *as = e->ptr;
n = e->next;
@@ -449,12 +451,14 @@ CURLcode Curl_altsvc_parse(struct Curl_easy *data,
{
const char *p = value;
size_t len;
- enum alpnid dstalpnid = srcalpnid; /* the same by default */
char namebuf[MAX_ALTSVC_HOSTLEN] = "";
char alpnbuf[MAX_ALTSVC_ALPNLEN] = "";
struct altsvc *as;
unsigned short dstport = srcport; /* the same by default */
CURLcode result = getalnum(&p, alpnbuf, sizeof(alpnbuf));
+#ifdef CURL_DISABLE_VERBOSE_STRINGS
+ (void)data;
+#endif
if(result) {
infof(data, "Excessive alt-svc header, ignoring...\n");
return CURLE_OK;
@@ -473,7 +477,7 @@ CURLcode Curl_altsvc_parse(struct Curl_easy *data,
do {
if(*p == '=') {
/* [protocol]="[host][:port]" */
- dstalpnid = alpn2alpnid(alpnbuf);
+ enum alpnid dstalpnid = alpn2alpnid(alpnbuf); /* the same by default */
p++;
if(*p == '\"') {
const char *dsthost = "";
@@ -612,8 +616,8 @@ bool Curl_altsvc_lookup(struct altsvcinfo *asi,
struct altsvc **dstentry,
const int versions) /* one or more bits */
{
- struct curl_llist_element *e;
- struct curl_llist_element *n;
+ struct Curl_llist_element *e;
+ struct Curl_llist_element *n;
time_t now = time(NULL);
DEBUGASSERT(asi);
DEBUGASSERT(srchost);
@@ -640,4 +644,4 @@ bool Curl_altsvc_lookup(struct altsvcinfo *asi,
return FALSE;
}
-#endif /* CURL_DISABLE_HTTP || USE_ALTSVC */
+#endif /* !CURL_DISABLE_HTTP && !CURL_DISABLE_ALTSVC */
diff --git a/Utilities/cmcurl/lib/altsvc.h b/Utilities/cmcurl/lib/altsvc.h
index 578a4fbfb..2ab89e705 100644
--- a/Utilities/cmcurl/lib/altsvc.h
+++ b/Utilities/cmcurl/lib/altsvc.h
@@ -11,7 +11,7 @@
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -23,7 +23,7 @@
***************************************************************************/
#include "curl_setup.h"
-#if !defined(CURL_DISABLE_HTTP) && defined(USE_ALTSVC)
+#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_ALTSVC)
#include <curl/curl.h>
#include "llist.h"
@@ -46,12 +46,12 @@ struct altsvc {
time_t expires;
bool persist;
int prio;
- struct curl_llist_element node;
+ struct Curl_llist_element node;
};
struct altsvcinfo {
char *filename;
- struct curl_llist list; /* list of entries */
+ struct Curl_llist list; /* list of entries */
long flags; /* the publicly set bitmask */
};
@@ -61,7 +61,7 @@ CURLcode Curl_altsvc_load(struct altsvcinfo *asi, const char *file);
CURLcode Curl_altsvc_save(struct Curl_easy *data,
struct altsvcinfo *asi, const char *file);
CURLcode Curl_altsvc_ctrl(struct altsvcinfo *asi, const long ctrl);
-void Curl_altsvc_cleanup(struct altsvcinfo *altsvc);
+void Curl_altsvc_cleanup(struct altsvcinfo **altsvc);
CURLcode Curl_altsvc_parse(struct Curl_easy *data,
struct altsvcinfo *altsvc, const char *value,
enum alpnid srcalpn, const char *srchost,
@@ -74,5 +74,6 @@ bool Curl_altsvc_lookup(struct altsvcinfo *asi,
#else
/* disabled */
#define Curl_altsvc_save(a,b,c)
-#endif /* CURL_DISABLE_HTTP || USE_ALTSVC */
+#define Curl_altsvc_cleanup(x)
+#endif /* !CURL_DISABLE_HTTP && !CURL_DISABLE_ALTSVC */
#endif /* HEADER_CURL_ALTSVC_H */
diff --git a/Utilities/cmcurl/lib/amigaos.c b/Utilities/cmcurl/lib/amigaos.c
index cf44bdc8d..d3b00d908 100644
--- a/Utilities/cmcurl/lib/amigaos.c
+++ b/Utilities/cmcurl/lib/amigaos.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
diff --git a/Utilities/cmcurl/lib/amigaos.h b/Utilities/cmcurl/lib/amigaos.h
index c776c9c9b..02e5bb546 100644
--- a/Utilities/cmcurl/lib/amigaos.h
+++ b/Utilities/cmcurl/lib/amigaos.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
diff --git a/Utilities/cmcurl/lib/arpa_telnet.h b/Utilities/cmcurl/lib/arpa_telnet.h
index 232680e7d..cbe31de5a 100644
--- a/Utilities/cmcurl/lib/arpa_telnet.h
+++ b/Utilities/cmcurl/lib/arpa_telnet.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
diff --git a/Utilities/cmcurl/lib/asyn-ares.c b/Utilities/cmcurl/lib/asyn-ares.c
index e65150744..2484a7b49 100644
--- a/Utilities/cmcurl/lib/asyn-ares.c
+++ b/Utilities/cmcurl/lib/asyn-ares.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -67,8 +67,8 @@
#include "select.h"
#include "progress.h"
-# if defined(CURL_STATICLIB) && !defined(CARES_STATICLIB) && \
- (defined(WIN32) || defined(__SYMBIAN32__))
+# if defined(CURL_STATICLIB) && !defined(CARES_STATICLIB) && \
+ defined(WIN32)
# define CARES_STATICLIB
# endif
# include <ares.h>
@@ -85,7 +85,7 @@
#include "curl_memory.h"
#include "memdebug.h"
-struct ResolverResults {
+struct thread_data {
int num_pending; /* number of ares_gethostbyname() requests */
struct Curl_addrinfo *temp_ai; /* intermediary result while fetching c-ares
parts */
@@ -133,8 +133,8 @@ void Curl_resolver_global_cleanup(void)
}
-static void Curl_ares_sock_state_cb(void *data, ares_socket_t socket_fd,
- int readable, int writable)
+static void sock_state_cb(void *data, ares_socket_t socket_fd,
+ int readable, int writable)
{
struct Curl_easy *easy = data;
if(!readable && !writable) {
@@ -155,7 +155,7 @@ CURLcode Curl_resolver_init(struct Curl_easy *easy, void **resolver)
int status;
struct ares_options options;
int optmask = ARES_OPT_SOCK_STATE_CB;
- options.sock_state_cb = Curl_ares_sock_state_cb;
+ options.sock_state_cb = sock_state_cb;
options.sock_state_cb_data = easy;
status = ares_init_options((ares_channel*)resolver, &options, optmask);
if(status != ARES_SUCCESS) {
@@ -204,22 +204,22 @@ static void destroy_async_data(struct Curl_async *async);
/*
* Cancel all possibly still on-going resolves for this connection.
*/
-void Curl_resolver_cancel(struct connectdata *conn)
+void Curl_resolver_cancel(struct Curl_easy *data)
{
- if(conn->data && conn->data->state.resolver)
- ares_cancel((ares_channel)conn->data->state.resolver);
- destroy_async_data(&conn->async);
+ if(data && data->state.async.resolver)
+ ares_cancel((ares_channel)data->state.async.resolver);
+ destroy_async_data(&data->state.async);
}
/*
* We're equivalent to Curl_resolver_cancel() for the c-ares resolver. We
* never block.
*/
-void Curl_resolver_kill(struct connectdata *conn)
+void Curl_resolver_kill(struct Curl_easy *data)
{
/* We don't need to check the resolver state because we can be called safely
at any time and we always do the same thing. */
- Curl_resolver_cancel(conn);
+ Curl_resolver_cancel(data);
}
/*
@@ -229,8 +229,8 @@ static void destroy_async_data(struct Curl_async *async)
{
free(async->hostname);
- if(async->os_specific) {
- struct ResolverResults *res = (struct ResolverResults *)async->os_specific;
+ if(async->tdata) {
+ struct thread_data *res = async->tdata;
if(res) {
if(res->temp_ai) {
Curl_freeaddrinfo(res->temp_ai);
@@ -238,7 +238,7 @@ static void destroy_async_data(struct Curl_async *async)
}
free(res);
}
- async->os_specific = NULL;
+ async->tdata = NULL;
}
async->hostname = NULL;
@@ -253,25 +253,25 @@ static void destroy_async_data(struct Curl_async *async)
* Returns: sockets-in-use-bitmap
*/
-int Curl_resolver_getsock(struct connectdata *conn,
+int Curl_resolver_getsock(struct Curl_easy *data,
curl_socket_t *socks)
{
struct timeval maxtime;
struct timeval timebuf;
struct timeval *timeout;
long milli;
- int max = ares_getsock((ares_channel)conn->data->state.resolver,
+ int max = ares_getsock((ares_channel)data->state.async.resolver,
(ares_socket_t *)socks, MAX_SOCKSPEREASYHANDLE);
maxtime.tv_sec = CURL_TIMEOUT_RESOLVE;
maxtime.tv_usec = 0;
- timeout = ares_timeout((ares_channel)conn->data->state.resolver, &maxtime,
+ timeout = ares_timeout((ares_channel)data->state.async.resolver, &maxtime,
&timebuf);
milli = (timeout->tv_sec * 1000) + (timeout->tv_usec/1000);
if(milli == 0)
milli += 10;
- Curl_expire(conn->data, milli, EXPIRE_ASYNC_NAME);
+ Curl_expire(data, milli, EXPIRE_ASYNC_NAME);
return max;
}
@@ -286,9 +286,8 @@ int Curl_resolver_getsock(struct connectdata *conn,
* return number of sockets it worked on
*/
-static int waitperform(struct connectdata *conn, timediff_t timeout_ms)
+static int waitperform(struct Curl_easy *data, timediff_t timeout_ms)
{
- struct Curl_easy *data = conn->data;
int nfds;
int bitmask;
ares_socket_t socks[ARES_GETSOCK_MAXNUM];
@@ -296,7 +295,7 @@ static int waitperform(struct connectdata *conn, timediff_t timeout_ms)
int i;
int num = 0;
- bitmask = ares_getsock((ares_channel)data->state.resolver, socks,
+ bitmask = ares_getsock((ares_channel)data->state.async.resolver, socks,
ARES_GETSOCK_MAXNUM);
for(i = 0; i < ARES_GETSOCK_MAXNUM; i++) {
@@ -324,12 +323,12 @@ static int waitperform(struct connectdata *conn, timediff_t timeout_ms)
if(!nfds)
/* Call ares_process() unconditonally here, even if we simply timed out
above, as otherwise the ares name resolve won't timeout! */
- ares_process_fd((ares_channel)data->state.resolver, ARES_SOCKET_BAD,
+ ares_process_fd((ares_channel)data->state.async.resolver, ARES_SOCKET_BAD,
ARES_SOCKET_BAD);
else {
/* move through the descriptors and ask for processing on them */
for(i = 0; i < num; i++)
- ares_process_fd((ares_channel)data->state.resolver,
+ ares_process_fd((ares_channel)data->state.async.resolver,
(pfd[i].revents & (POLLRDNORM|POLLIN))?
pfd[i].fd:ARES_SOCKET_BAD,
(pfd[i].revents & (POLLWRNORM|POLLOUT))?
@@ -345,18 +344,16 @@ static int waitperform(struct connectdata *conn, timediff_t timeout_ms)
*
* Returns normal CURLcode errors.
*/
-CURLcode Curl_resolver_is_resolved(struct connectdata *conn,
+CURLcode Curl_resolver_is_resolved(struct Curl_easy *data,
struct Curl_dns_entry **dns)
{
- struct Curl_easy *data = conn->data;
- struct ResolverResults *res = (struct ResolverResults *)
- conn->async.os_specific;
+ struct thread_data *res = data->state.async.tdata;
CURLcode result = CURLE_OK;
DEBUGASSERT(dns);
*dns = NULL;
- waitperform(conn, 0);
+ waitperform(data, 0);
/* Now that we've checked for any last minute results above, see if there are
any responses still pending when the EXPIRE_HAPPY_EYEBALLS_DNS timer
@@ -377,26 +374,27 @@ CURLcode Curl_resolver_is_resolved(struct connectdata *conn,
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.resolver);
+ ares_cancel((ares_channel)data->state.async.resolver);
DEBUGASSERT(res->num_pending == 0);
}
if(res && !res->num_pending) {
- (void)Curl_addrinfo_callback(conn, res->last_status, res->temp_ai);
+ (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;
- if(!conn->async.dns) {
+ if(!data->state.async.dns) {
failf(data, "Could not resolve: %s (%s)",
- conn->async.hostname, ares_strerror(conn->async.status));
- result = conn->bits.proxy?CURLE_COULDNT_RESOLVE_PROXY:
+ data->state.async.hostname,
+ ares_strerror(data->state.async.status));
+ result = data->conn->bits.proxy?CURLE_COULDNT_RESOLVE_PROXY:
CURLE_COULDNT_RESOLVE_HOST;
}
else
- *dns = conn->async.dns;
+ *dns = data->state.async.dns;
- destroy_async_data(&conn->async);
+ destroy_async_data(&data->state.async);
}
return result;
@@ -413,11 +411,10 @@ CURLcode Curl_resolver_is_resolved(struct connectdata *conn,
* 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 connectdata *conn,
+CURLcode Curl_resolver_wait_resolv(struct Curl_easy *data,
struct Curl_dns_entry **entry)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
timediff_t timeout;
struct curltime now = Curl_now();
@@ -427,7 +424,7 @@ CURLcode Curl_resolver_wait_resolv(struct connectdata *conn,
timeout = Curl_timeleft(data, &now, TRUE);
if(timeout < 0) {
/* already expired! */
- connclose(conn, "Timed out before name resolve started");
+ connclose(data->conn, "Timed out before name resolve started");
return CURLE_OPERATION_TIMEDOUT;
}
if(!timeout)
@@ -448,7 +445,7 @@ CURLcode Curl_resolver_wait_resolv(struct connectdata *conn,
store.tv_sec = itimeout/1000;
store.tv_usec = (itimeout%1000)*1000;
- tvp = ares_timeout((ares_channel)data->state.resolver, &store, &tv);
+ tvp = ares_timeout((ares_channel)data->state.async.resolver, &store, &tv);
/* use the timeout period ares returned to us above if less than one
second is left, otherwise just use 1000ms to make sure the progress
@@ -458,13 +455,13 @@ CURLcode Curl_resolver_wait_resolv(struct connectdata *conn,
else
timeout_ms = 1000;
- waitperform(conn, timeout_ms);
- result = Curl_resolver_is_resolved(conn, entry);
+ waitperform(data, timeout_ms);
+ result = Curl_resolver_is_resolved(data, entry);
- if(result || conn->async.done)
+ if(result || data->state.async.done)
break;
- if(Curl_pgrsUpdate(conn))
+ if(Curl_pgrsUpdate(data))
result = CURLE_ABORTED_BY_CALLBACK;
else {
struct curltime now2 = Curl_now();
@@ -482,23 +479,23 @@ CURLcode Curl_resolver_wait_resolv(struct connectdata *conn,
}
if(result)
/* failure, so we cancel the ares operation */
- ares_cancel((ares_channel)data->state.resolver);
+ ares_cancel((ares_channel)data->state.async.resolver);
/* Operation complete, if the lookup was successful we now have the entry
in the cache. */
if(entry)
- *entry = conn->async.dns;
+ *entry = data->state.async.dns;
if(result)
/* close the connection, since we can't return failure here without
cleaning up this connection properly. */
- connclose(conn, "c-ares resolve failed");
+ connclose(data->conn, "c-ares resolve failed");
return result;
}
/* Connects results to the list */
-static void compound_results(struct ResolverResults *res,
+static void compound_results(struct thread_data *res,
struct Curl_addrinfo *ai)
{
struct Curl_addrinfo *ai_tail;
@@ -526,8 +523,8 @@ static void query_completed_cb(void *arg, /* (struct connectdata *) */
#endif
struct hostent *hostent)
{
- struct connectdata *conn = (struct connectdata *)arg;
- struct ResolverResults *res;
+ struct Curl_easy *data = (struct Curl_easy *)arg;
+ struct thread_data *res;
#ifdef HAVE_CARES_CALLBACK_TIMEOUTS
(void)timeouts; /* ignored */
@@ -538,12 +535,12 @@ 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 = (struct ResolverResults *)conn->async.os_specific;
+ res = data->state.async.tdata;
if(res) {
res->num_pending--;
if(CURL_ASYNC_SUCCESS == status) {
- struct Curl_addrinfo *ai = Curl_he2ai(hostent, conn->async.port);
+ struct Curl_addrinfo *ai = Curl_he2ai(hostent, data->state.async.port);
if(ai) {
compound_results(res, ai);
}
@@ -608,8 +605,8 @@ static void query_completed_cb(void *arg, /* (struct connectdata *) */
c-ares retry cycle each request is.
*/
res->happy_eyeballs_dns_time = Curl_now();
- Curl_expire(
- conn->data, HAPPY_EYEBALLS_DNS_TIMEOUT, EXPIRE_HAPPY_EYEBALLS_DNS);
+ Curl_expire(data, HAPPY_EYEBALLS_DNS_TIMEOUT,
+ EXPIRE_HAPPY_EYEBALLS_DNS);
}
}
}
@@ -622,19 +619,18 @@ static void query_completed_cb(void *arg, /* (struct connectdata *) */
* memory we need to free after use. That memory *MUST* be freed with
* Curl_freeaddrinfo(), nothing else.
*/
-struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn,
+struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data,
const char *hostname,
int port,
int *waitp)
{
char *bufp;
- struct Curl_easy *data = conn->data;
int family = PF_INET;
*waitp = 0; /* default to synchronous response */
#ifdef ENABLE_IPV6
- switch(conn->ip_version) {
+ switch(data->set.ipver) {
default:
#if ARES_VERSION >= 0x010601
family = PF_UNSPEC; /* supported by c-ares since 1.6.1, so for older
@@ -653,40 +649,40 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn,
bufp = strdup(hostname);
if(bufp) {
- struct ResolverResults *res = NULL;
- free(conn->async.hostname);
- conn->async.hostname = bufp;
- conn->async.port = port;
- conn->async.done = FALSE; /* not done */
- conn->async.status = 0; /* clear */
- conn->async.dns = NULL; /* clear */
- res = calloc(sizeof(struct ResolverResults), 1);
+ struct thread_data *res = NULL;
+ free(data->state.async.hostname);
+ data->state.async.hostname = bufp;
+ data->state.async.port = port;
+ data->state.async.done = FALSE; /* not done */
+ data->state.async.status = 0; /* clear */
+ data->state.async.dns = NULL; /* clear */
+ res = calloc(sizeof(struct thread_data), 1);
if(!res) {
- free(conn->async.hostname);
- conn->async.hostname = NULL;
+ free(data->state.async.hostname);
+ data->state.async.hostname = NULL;
return NULL;
}
- conn->async.os_specific = res;
+ data->state.async.tdata = res;
/* initial status - failed */
res->last_status = ARES_ENOTFOUND;
#ifdef ENABLE_IPV6
if(family == PF_UNSPEC) {
- if(Curl_ipv6works(conn)) {
+ if(Curl_ipv6works(data)) {
res->num_pending = 2;
/* areschannel is already setup in the Curl_open() function */
- ares_gethostbyname((ares_channel)data->state.resolver, hostname,
- PF_INET, query_completed_cb, conn);
- ares_gethostbyname((ares_channel)data->state.resolver, hostname,
- PF_INET6, query_completed_cb, conn);
+ ares_gethostbyname((ares_channel)data->state.async.resolver, hostname,
+ PF_INET, query_completed_cb, data);
+ ares_gethostbyname((ares_channel)data->state.async.resolver, hostname,
+ PF_INET6, query_completed_cb, data);
}
else {
res->num_pending = 1;
/* areschannel is already setup in the Curl_open() function */
- ares_gethostbyname((ares_channel)data->state.resolver, hostname,
- PF_INET, query_completed_cb, conn);
+ ares_gethostbyname((ares_channel)data->state.async.resolver, hostname,
+ PF_INET, query_completed_cb, data);
}
}
else
@@ -695,8 +691,9 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn,
res->num_pending = 1;
/* areschannel is already setup in the Curl_open() function */
- ares_gethostbyname((ares_channel)data->state.resolver, hostname, family,
- query_completed_cb, conn);
+ ares_gethostbyname((ares_channel)data->state.async.resolver,
+ hostname, family,
+ query_completed_cb, data);
}
*waitp = 1; /* expect asynchronous response */
@@ -721,9 +718,10 @@ CURLcode Curl_set_dns_servers(struct Curl_easy *data,
#if (ARES_VERSION >= 0x010704)
#if (ARES_VERSION >= 0x010b00)
- ares_result = ares_set_servers_ports_csv(data->state.resolver, servers);
+ ares_result = ares_set_servers_ports_csv(data->state.async.resolver,
+ servers);
#else
- ares_result = ares_set_servers_csv(data->state.resolver, servers);
+ ares_result = ares_set_servers_csv(data->state.async.resolver, servers);
#endif
switch(ares_result) {
case ARES_SUCCESS:
@@ -753,7 +751,7 @@ CURLcode Curl_set_dns_interface(struct Curl_easy *data,
if(!interf)
interf = "";
- ares_set_local_dev((ares_channel)data->state.resolver, interf);
+ ares_set_local_dev((ares_channel)data->state.async.resolver, interf);
return CURLE_OK;
#else /* c-ares version too old! */
@@ -778,7 +776,8 @@ CURLcode Curl_set_dns_local_ip4(struct Curl_easy *data,
}
}
- ares_set_local_ip4((ares_channel)data->state.resolver, ntohl(a4.s_addr));
+ ares_set_local_ip4((ares_channel)data->state.async.resolver,
+ ntohl(a4.s_addr));
return CURLE_OK;
#else /* c-ares version too old! */
@@ -804,7 +803,7 @@ CURLcode Curl_set_dns_local_ip6(struct Curl_easy *data,
}
}
- ares_set_local_ip6((ares_channel)data->state.resolver, a6);
+ ares_set_local_ip6((ares_channel)data->state.async.resolver, a6);
return CURLE_OK;
#else /* c-ares version too old! */
diff --git a/Utilities/cmcurl/lib/asyn-thread.c b/Utilities/cmcurl/lib/asyn-thread.c
index a60f4f066..9fcbc3c1f 100644
--- a/Utilities/cmcurl/lib/asyn-thread.c
+++ b/Utilities/cmcurl/lib/asyn-thread.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -145,13 +145,13 @@ static void destroy_async_data(struct Curl_async *);
/*
* Cancel all possibly still on-going resolves for this connection.
*/
-void Curl_resolver_cancel(struct connectdata *conn)
+void Curl_resolver_cancel(struct Curl_easy *data)
{
- destroy_async_data(&conn->async);
+ destroy_async_data(&data->state.async);
}
/* This function is used to init a threaded resolve */
-static bool init_resolve_thread(struct connectdata *conn,
+static bool init_resolve_thread(struct Curl_easy *data,
const char *hostname, int port,
const struct addrinfo *hints);
@@ -160,12 +160,11 @@ static bool init_resolve_thread(struct connectdata *conn,
struct thread_sync_data {
curl_mutex_t *mtx;
int done;
-
+ int port;
char *hostname; /* hostname to resolve, Curl_async.hostname
duplicate */
- int port;
#ifdef USE_SOCKETPAIR
- struct connectdata *conn;
+ struct Curl_easy *data;
curl_socket_t sock_pair[2]; /* socket pair */
#endif
int sock_error;
@@ -183,9 +182,9 @@ struct thread_data {
struct thread_sync_data tsd;
};
-static struct thread_sync_data *conn_thread_sync_data(struct connectdata *conn)
+static struct thread_sync_data *conn_thread_sync_data(struct Curl_easy *data)
{
- return &(((struct thread_data *)conn->async.os_specific)->tsd);
+ return &(data->state.async.tdata->tsd);
}
/* Destroy resolver thread synchronization data */
@@ -269,12 +268,12 @@ int init_thread_sync_data(struct thread_data *td,
return 0;
}
-static int getaddrinfo_complete(struct connectdata *conn)
+static int getaddrinfo_complete(struct Curl_easy *data)
{
- struct thread_sync_data *tsd = conn_thread_sync_data(conn);
+ struct thread_sync_data *tsd = conn_thread_sync_data(data);
int rc;
- rc = Curl_addrinfo_callback(conn, tsd->sock_error, tsd->res);
+ rc = 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 doesn't free it.
*/
@@ -294,7 +293,7 @@ static int getaddrinfo_complete(struct connectdata *conn)
*/
static unsigned int CURL_STDCALL getaddrinfo_thread(void *arg)
{
- struct thread_sync_data *tsd = (struct thread_sync_data*)arg;
+ struct thread_sync_data *tsd = (struct thread_sync_data *)arg;
struct thread_data *td = tsd->td;
char service[12];
int rc;
@@ -380,12 +379,12 @@ static unsigned int CURL_STDCALL gethostbyname_thread(void *arg)
*/
static void destroy_async_data(struct Curl_async *async)
{
- if(async->os_specific) {
- struct thread_data *td = (struct thread_data*) async->os_specific;
+ if(async->tdata) {
+ struct thread_data *td = async->tdata;
int done;
#ifdef USE_SOCKETPAIR
curl_socket_t sock_rd = td->tsd.sock_pair[0];
- struct connectdata *conn = td->tsd.conn;
+ struct Curl_easy *data = td->tsd.data;
#endif
/*
@@ -406,19 +405,18 @@ static void destroy_async_data(struct Curl_async *async)
destroy_thread_sync_data(&td->tsd);
- free(async->os_specific);
+ free(async->tdata);
}
#ifdef USE_SOCKETPAIR
/*
* ensure CURLMOPT_SOCKETFUNCTION fires CURL_POLL_REMOVE
* before the FD is invalidated to avoid EBADF on EPOLL_CTL_DEL
*/
- if(conn)
- Curl_multi_closed(conn->data, sock_rd);
+ Curl_multi_closed(data, sock_rd);
sclose(sock_rd);
#endif
}
- async->os_specific = NULL;
+ async->tdata = NULL;
free(async->hostname);
async->hostname = NULL;
@@ -430,32 +428,33 @@ static void destroy_async_data(struct Curl_async *async)
*
* Returns FALSE in case of failure, otherwise TRUE.
*/
-static bool init_resolve_thread(struct connectdata *conn,
+static bool init_resolve_thread(struct Curl_easy *data,
const char *hostname, int port,
const struct addrinfo *hints)
{
struct thread_data *td = calloc(1, sizeof(struct thread_data));
int err = ENOMEM;
+ struct Curl_async *asp = &data->state.async;
- conn->async.os_specific = (void *)td;
+ data->state.async.tdata = td;
if(!td)
goto errno_exit;
- conn->async.port = port;
- conn->async.done = FALSE;
- conn->async.status = 0;
- conn->async.dns = NULL;
+ asp->port = port;
+ asp->done = FALSE;
+ asp->status = 0;
+ asp->dns = NULL;
td->thread_hnd = curl_thread_t_null;
if(!init_thread_sync_data(td, hostname, port, hints)) {
- conn->async.os_specific = NULL;
+ asp->tdata = NULL;
free(td);
goto errno_exit;
}
- free(conn->async.hostname);
- conn->async.hostname = strdup(hostname);
- if(!conn->async.hostname)
+ free(asp->hostname);
+ asp->hostname = strdup(hostname);
+ if(!asp->hostname)
goto err_exit;
/* The thread will set this to 1 when complete. */
@@ -477,7 +476,7 @@ static bool init_resolve_thread(struct connectdata *conn,
return TRUE;
err_exit:
- destroy_async_data(&conn->async);
+ destroy_async_data(asp);
errno_exit:
errno = err;
@@ -489,12 +488,13 @@ static bool init_resolve_thread(struct connectdata *conn,
* error
*/
-static CURLcode resolver_error(struct connectdata *conn)
+static CURLcode resolver_error(struct Curl_easy *data)
{
const char *host_or_proxy;
CURLcode result;
#ifndef CURL_DISABLE_PROXY
+ struct connectdata *conn = data->conn;
if(conn->bits.httpproxy) {
host_or_proxy = "proxy";
result = CURLE_COULDNT_RESOLVE_PROXY;
@@ -506,8 +506,8 @@ static CURLcode resolver_error(struct connectdata *conn)
result = CURLE_COULDNT_RESOLVE_HOST;
}
- failf(conn->data, "Could not resolve %s: %s", host_or_proxy,
- conn->async.hostname);
+ failf(data, "Could not resolve %s: %s", host_or_proxy,
+ data->state.async.hostname);
return result;
}
@@ -515,37 +515,39 @@ static CURLcode resolver_error(struct connectdata *conn)
/*
* 'entry' may be NULL and then no data is returned
*/
-static CURLcode thread_wait_resolv(struct connectdata *conn,
+static CURLcode thread_wait_resolv(struct Curl_easy *data,
struct Curl_dns_entry **entry,
bool report)
{
- struct thread_data *td = (struct thread_data*) conn->async.os_specific;
+ struct thread_data *td;
CURLcode result = CURLE_OK;
- DEBUGASSERT(conn && td);
+ DEBUGASSERT(data);
+ td = data->state.async.tdata;
+ 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(conn);
+ result = getaddrinfo_complete(data);
}
else
DEBUGASSERT(0);
- conn->async.done = TRUE;
+ data->state.async.done = TRUE;
if(entry)
- *entry = conn->async.dns;
+ *entry = data->state.async.dns;
- if(!conn->async.dns && report)
+ if(!data->state.async.dns && report)
/* a name was not resolved, report error */
- result = resolver_error(conn);
+ result = resolver_error(data);
- destroy_async_data(&conn->async);
+ destroy_async_data(&data->state.async);
- if(!conn->async.dns && report)
- connclose(conn, "asynch resolve failed");
+ if(!data->state.async.dns && report)
+ connclose(data->conn, "asynch resolve failed");
return result;
}
@@ -555,17 +557,17 @@ static CURLcode thread_wait_resolv(struct connectdata *conn,
* 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 connectdata *conn)
+void Curl_resolver_kill(struct Curl_easy *data)
{
- struct thread_data *td = (struct thread_data*) conn->async.os_specific;
+ struct thread_data *td = data->state.async.tdata;
/* If we're still resolving, we must wait for the threads to fully clean up,
unfortunately. Otherwise, we can simply cancel to clean up any resolver
data. */
if(td && td->thread_hnd != curl_thread_t_null)
- (void)thread_wait_resolv(conn, NULL, FALSE);
+ (void)thread_wait_resolv(data, NULL, FALSE);
else
- Curl_resolver_cancel(conn);
+ Curl_resolver_cancel(data);
}
/*
@@ -581,10 +583,10 @@ void Curl_resolver_kill(struct connectdata *conn)
*
* This is the version for resolves-in-a-thread.
*/
-CURLcode Curl_resolver_wait_resolv(struct connectdata *conn,
+CURLcode Curl_resolver_wait_resolv(struct Curl_easy *data,
struct Curl_dns_entry **entry)
{
- return thread_wait_resolv(conn, entry, TRUE);
+ return thread_wait_resolv(data, entry, TRUE);
}
/*
@@ -592,11 +594,10 @@ CURLcode Curl_resolver_wait_resolv(struct connectdata *conn,
* 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 connectdata *conn,
+CURLcode Curl_resolver_is_resolved(struct Curl_easy *data,
struct Curl_dns_entry **entry)
{
- struct Curl_easy *data = conn->data;
- struct thread_data *td = (struct thread_data*) conn->async.os_specific;
+ struct thread_data *td = data->state.async.tdata;
int done = 0;
DEBUGASSERT(entry);
@@ -612,15 +613,15 @@ CURLcode Curl_resolver_is_resolved(struct connectdata *conn,
Curl_mutex_release(td->tsd.mtx);
if(done) {
- getaddrinfo_complete(conn);
+ getaddrinfo_complete(data);
- if(!conn->async.dns) {
- CURLcode result = resolver_error(conn);
- destroy_async_data(&conn->async);
+ if(!data->state.async.dns) {
+ CURLcode result = resolver_error(data);
+ destroy_async_data(&data->state.async);
return result;
}
- destroy_async_data(&conn->async);
- *entry = conn->async.dns;
+ destroy_async_data(&data->state.async);
+ *entry = data->state.async.dns;
}
else {
/* poll for name lookup done with exponential backoff up to 250ms */
@@ -641,22 +642,20 @@ CURLcode Curl_resolver_is_resolved(struct connectdata *conn,
td->poll_interval = 250;
td->interval_end = elapsed + td->poll_interval;
- Curl_expire(conn->data, td->poll_interval, EXPIRE_ASYNC_NAME);
+ Curl_expire(data, td->poll_interval, EXPIRE_ASYNC_NAME);
}
return CURLE_OK;
}
-int Curl_resolver_getsock(struct connectdata *conn,
- curl_socket_t *socks)
+int Curl_resolver_getsock(struct Curl_easy *data, curl_socket_t *socks)
{
int ret_val = 0;
timediff_t milli;
timediff_t ms;
- struct Curl_easy *data = conn->data;
- struct resdata *reslv = (struct resdata *)data->state.resolver;
+ struct resdata *reslv = (struct resdata *)data->state.async.resolver;
#ifdef USE_SOCKETPAIR
- struct thread_data *td = (struct thread_data*)conn->async.os_specific;
+ struct thread_data *td = data->state.async.tdata;
#else
(void)socks;
#endif
@@ -665,8 +664,7 @@ int Curl_resolver_getsock(struct connectdata *conn,
if(td) {
/* return read fd to client for polling the DNS resolution status */
socks[0] = td->tsd.sock_pair[0];
- DEBUGASSERT(td->tsd.conn == conn || !td->tsd.conn);
- td->tsd.conn = conn;
+ td->tsd.data = data;
ret_val = GETSOCK_READSOCK(0);
}
else {
@@ -693,25 +691,24 @@ int Curl_resolver_getsock(struct connectdata *conn,
/*
* Curl_getaddrinfo() - for platforms without getaddrinfo
*/
-struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn,
+struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data,
const char *hostname,
int port,
int *waitp)
{
- struct Curl_easy *data = conn->data;
- struct resdata *reslv = (struct resdata *)data->state.resolver;
+ struct resdata *reslv = (struct resdata *)data->state.async.resolver;
*waitp = 0; /* default to synchronous response */
reslv->start = Curl_now();
/* fire up a new resolver thread! */
- if(init_resolve_thread(conn, hostname, port, NULL)) {
+ if(init_resolve_thread(data, hostname, port, NULL)) {
*waitp = 1; /* expect asynchronous response */
return NULL;
}
- failf(conn->data, "getaddrinfo() thread failed\n");
+ failf(data, "getaddrinfo() thread failed");
return NULL;
}
@@ -721,15 +718,14 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn,
/*
* Curl_resolver_getaddrinfo() - for getaddrinfo
*/
-struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn,
+struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data,
const char *hostname,
int port,
int *waitp)
{
struct addrinfo hints;
int pf = PF_INET;
- struct Curl_easy *data = conn->data;
- struct resdata *reslv = (struct resdata *)data->state.resolver;
+ struct resdata *reslv = (struct resdata *)data->state.async.resolver;
*waitp = 0; /* default to synchronous response */
@@ -737,7 +733,7 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn,
/*
* Check if a limited name resolve has been requested.
*/
- switch(conn->ip_version) {
+ switch(data->set.ipver) {
case CURL_IPRESOLVE_V4:
pf = PF_INET;
break;
@@ -749,24 +745,24 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn,
break;
}
- if((pf != PF_INET) && !Curl_ipv6works(conn))
+ if((pf != PF_INET) && !Curl_ipv6works(data))
/* The stack seems to be a non-IPv6 one */
pf = PF_INET;
#endif /* CURLRES_IPV6 */
memset(&hints, 0, sizeof(hints));
hints.ai_family = pf;
- hints.ai_socktype = (conn->transport == TRNSPRT_TCP)?
+ hints.ai_socktype = (data->conn->transport == TRNSPRT_TCP)?
SOCK_STREAM : SOCK_DGRAM;
reslv->start = Curl_now();
/* fire up a new resolver thread! */
- if(init_resolve_thread(conn, hostname, port, &hints)) {
+ if(init_resolve_thread(data, hostname, port, &hints)) {
*waitp = 1; /* expect asynchronous response */
return NULL;
}
- failf(data, "getaddrinfo() thread failed to start\n");
+ failf(data, "getaddrinfo() thread failed to start");
return NULL;
}
diff --git a/Utilities/cmcurl/lib/asyn.h b/Utilities/cmcurl/lib/asyn.h
index bd3c3c123..313039582 100644
--- a/Utilities/cmcurl/lib/asyn.h
+++ b/Utilities/cmcurl/lib/asyn.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -91,7 +91,7 @@ CURLcode Curl_resolver_duphandle(struct Curl_easy *easy, void **to,
*
* It is safe to call this when conn is in any state.
*/
-void Curl_resolver_cancel(struct connectdata *conn);
+void Curl_resolver_cancel(struct Curl_easy *data);
/*
* Curl_resolver_kill().
@@ -104,7 +104,7 @@ void Curl_resolver_cancel(struct connectdata *conn);
*
* It is safe to call this when conn is in any state.
*/
-void Curl_resolver_kill(struct connectdata *conn);
+void Curl_resolver_kill(struct Curl_easy *data);
/* Curl_resolver_getsock()
*
@@ -114,7 +114,7 @@ void Curl_resolver_kill(struct connectdata *conn);
* return bitmask indicating what file descriptors (referring to array indexes
* in the 'sock' array) to wait for, read/write.
*/
-int Curl_resolver_getsock(struct connectdata *conn, curl_socket_t *sock);
+int Curl_resolver_getsock(struct Curl_easy *data, curl_socket_t *sock);
/*
* Curl_resolver_is_resolved()
@@ -125,7 +125,7 @@ int Curl_resolver_getsock(struct connectdata *conn, curl_socket_t *sock);
*
* Returns normal CURLcode errors.
*/
-CURLcode Curl_resolver_is_resolved(struct connectdata *conn,
+CURLcode Curl_resolver_is_resolved(struct Curl_easy *data,
struct Curl_dns_entry **dns);
/*
@@ -139,7 +139,7 @@ CURLcode Curl_resolver_is_resolved(struct connectdata *conn,
* 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 connectdata *conn,
+CURLcode Curl_resolver_wait_resolv(struct Curl_easy *data,
struct Curl_dns_entry **dnsentry);
/*
@@ -153,7 +153,7 @@ CURLcode Curl_resolver_wait_resolv(struct connectdata *conn,
* 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 connectdata *conn,
+struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data,
const char *hostname,
int port,
int *waitp);
diff --git a/Utilities/cmcurl/lib/base64.c b/Utilities/cmcurl/lib/base64.c
index 643cef625..be6f163dc 100644
--- a/Utilities/cmcurl/lib/base64.c
+++ b/Utilities/cmcurl/lib/base64.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
@@ -26,6 +26,9 @@
#if !defined(CURL_DISABLE_HTTP_AUTH) || defined(USE_SSH) || \
!defined(CURL_DISABLE_LDAP) || \
+ !defined(CURL_DISABLE_SMTP) || \
+ !defined(CURL_DISABLE_POP3) || \
+ !defined(CURL_DISABLE_IMAP) || \
!defined(CURL_DISABLE_DOH) || defined(USE_SSL)
#include "urldata.h" /* for the Curl_easy definition */
diff --git a/Utilities/cmcurl/lib/c-hyper.c b/Utilities/cmcurl/lib/c-hyper.c
new file mode 100644
index 000000000..10bd7ef9b
--- /dev/null
+++ b/Utilities/cmcurl/lib/c-hyper.c
@@ -0,0 +1,908 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#if !defined(CURL_DISABLE_HTTP) && defined(USE_HYPER)
+
+#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 HAVE_NET_IF_H
+#include <net/if.h>
+#endif
+#ifdef HAVE_SYS_IOCTL_H
+#include <sys/ioctl.h>
+#endif
+
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+
+#include <hyper.h>
+#include "urldata.h"
+#include "sendf.h"
+#include "transfer.h"
+#include "multiif.h"
+#include "progress.h"
+
+/* The last 3 #include files should be in this order */
+#include "curl_printf.h"
+#include "curl_memory.h"
+#include "memdebug.h"
+
+size_t Curl_hyper_recv(void *userp, hyper_context *ctx,
+ uint8_t *buf, size_t buflen)
+{
+ struct Curl_easy *data = userp;
+ struct connectdata *conn = data->conn;
+ CURLcode result;
+ ssize_t nread;
+ DEBUGASSERT(conn);
+ (void)ctx;
+
+ result = Curl_read(data, conn->sockfd, (char *)buf, buflen, &nread);
+ if(result == CURLE_AGAIN) {
+ /* would block, register interest */
+ if(data->hyp.read_waker)
+ hyper_waker_free(data->hyp.read_waker);
+ data->hyp.read_waker = hyper_context_waker(ctx);
+ if(!data->hyp.read_waker) {
+ failf(data, "Couldn't make the read hyper_context_waker");
+ return HYPER_IO_ERROR;
+ }
+ return HYPER_IO_PENDING;
+ }
+ else if(result) {
+ failf(data, "Curl_read failed");
+ return HYPER_IO_ERROR;
+ }
+ return (size_t)nread;
+}
+
+size_t Curl_hyper_send(void *userp, hyper_context *ctx,
+ const uint8_t *buf, size_t buflen)
+{
+ struct Curl_easy *data = userp;
+ struct connectdata *conn = data->conn;
+ CURLcode result;
+ ssize_t nwrote;
+
+ result = Curl_write(data, conn->sockfd, (void *)buf, buflen, &nwrote);
+ if(result == CURLE_AGAIN) {
+ /* would block, register interest */
+ if(data->hyp.write_waker)
+ hyper_waker_free(data->hyp.write_waker);
+ data->hyp.write_waker = hyper_context_waker(ctx);
+ if(!data->hyp.write_waker) {
+ failf(data, "Couldn't make the write hyper_context_waker");
+ return HYPER_IO_ERROR;
+ }
+ return HYPER_IO_PENDING;
+ }
+ else if(result) {
+ failf(data, "Curl_write failed");
+ return HYPER_IO_ERROR;
+ }
+ return (size_t)nwrote;
+}
+
+static int hyper_each_header(void *userdata,
+ const uint8_t *name,
+ size_t name_len,
+ const uint8_t *value,
+ size_t value_len)
+{
+ struct Curl_easy *data = (struct Curl_easy *)userdata;
+ size_t len;
+ char *headp;
+ CURLcode result;
+ Curl_dyn_reset(&data->state.headerb);
+ if(name_len) {
+ if(Curl_dyn_addf(&data->state.headerb, "%.*s: %.*s\r\n",
+ (int) name_len, name, (int) value_len, value))
+ return HYPER_ITER_BREAK;
+ }
+ else {
+ if(Curl_dyn_add(&data->state.headerb, "\r\n"))
+ return HYPER_ITER_BREAK;
+ }
+ len = Curl_dyn_len(&data->state.headerb);
+ headp = Curl_dyn_ptr(&data->state.headerb);
+
+ result = Curl_http_header(data, data->conn, headp);
+ if(result) {
+ data->state.hresult = result;
+ return HYPER_ITER_BREAK;
+ }
+
+ Curl_debug(data, CURLINFO_HEADER_IN, headp, len);
+
+ result = Curl_client_write(data, CLIENTWRITE_HEADER, headp, len);
+ if(result) {
+ data->state.hresult = CURLE_ABORTED_BY_CALLBACK;
+ return HYPER_ITER_BREAK;
+ }
+
+ data->info.header_size += (long)len;
+ data->req.headerbytecount += (long)len;
+ return HYPER_ITER_CONTINUE;
+}
+
+static int hyper_body_chunk(void *userdata, const hyper_buf *chunk)
+{
+ char *buf = (char *)hyper_buf_bytes(chunk);
+ size_t len = hyper_buf_len(chunk);
+ struct Curl_easy *data = (struct Curl_easy *)userdata;
+ struct SingleRequest *k = &data->req;
+ CURLcode result;
+
+ if(0 == k->bodywrites++) {
+ bool done = FALSE;
+ result = Curl_http_firstwrite(data, data->conn, &done);
+ if(result || done) {
+ infof(data, "Return early from hyper_body_chunk\n");
+ data->state.hresult = result;
+ return HYPER_ITER_BREAK;
+ }
+ }
+ if(k->ignorebody)
+ return HYPER_ITER_CONTINUE;
+ Curl_debug(data, CURLINFO_DATA_IN, buf, len);
+ result = Curl_client_write(data, CLIENTWRITE_BODY, buf, len);
+
+ if(result) {
+ data->state.hresult = result;
+ return HYPER_ITER_BREAK;
+ }
+
+ data->req.bytecount += len;
+ Curl_pgrsSetDownloadCounter(data, data->req.bytecount);
+ return HYPER_ITER_CONTINUE;
+}
+
+/*
+ * Hyper does not consider the status line, the first line in a HTTP/1
+ * response, to be a header. The libcurl API does. This function sends the
+ * status line in the header callback. */
+static CURLcode status_line(struct Curl_easy *data,
+ struct connectdata *conn,
+ uint16_t http_status,
+ int http_version,
+ const uint8_t *reason, size_t rlen)
+{
+ CURLcode result;
+ size_t wrote;
+ size_t len;
+ const char *vstr;
+ curl_write_callback writeheader =
+ data->set.fwrite_header? data->set.fwrite_header: data->set.fwrite_func;
+ vstr = http_version == HYPER_HTTP_VERSION_1_1 ? "1.1" :
+ (http_version == HYPER_HTTP_VERSION_2 ? "2" : "1.0");
+ conn->httpversion =
+ http_version == HYPER_HTTP_VERSION_1_1 ? 11 :
+ (http_version == HYPER_HTTP_VERSION_2 ? 20 : 10);
+ data->req.httpcode = http_status;
+
+ result = Curl_http_statusline(data, conn);
+ if(result)
+ return result;
+
+ Curl_dyn_reset(&data->state.headerb);
+
+ result = Curl_dyn_addf(&data->state.headerb, "HTTP/%s %03d %.*s\r\n",
+ vstr,
+ (int)http_status,
+ (int)rlen, reason);
+ if(result)
+ return result;
+ len = Curl_dyn_len(&data->state.headerb);
+ Curl_debug(data, CURLINFO_HEADER_IN, Curl_dyn_ptr(&data->state.headerb),
+ len);
+ Curl_set_in_callback(data, true);
+ wrote = writeheader(Curl_dyn_ptr(&data->state.headerb), 1, len,
+ data->set.writeheader);
+ Curl_set_in_callback(data, false);
+ if(wrote != len)
+ return CURLE_WRITE_ERROR;
+
+ data->info.header_size += (long)len;
+ data->req.headerbytecount += (long)len;
+ data->req.httpcode = http_status;
+ return CURLE_OK;
+}
+
+/*
+ * Hyper does not pass on the last empty response header. The libcurl API
+ * does. This function sends an empty header in the header callback.
+ */
+static CURLcode empty_header(struct Curl_easy *data)
+{
+ return hyper_each_header(data, NULL, 0, NULL, 0) ?
+ CURLE_WRITE_ERROR : CURLE_OK;
+}
+
+CURLcode Curl_hyper_stream(struct Curl_easy *data,
+ struct connectdata *conn,
+ int *didwhat,
+ bool *done,
+ int select_res)
+{
+ hyper_response *resp = NULL;
+ uint16_t http_status;
+ int http_version;
+ hyper_headers *headers = NULL;
+ hyper_body *resp_body = NULL;
+ struct hyptransfer *h = &data->hyp;
+ hyper_task *task;
+ hyper_task *foreach;
+ hyper_error *hypererr = NULL;
+ const uint8_t *reasonp;
+ size_t reason_len;
+ CURLcode result = CURLE_OK;
+ (void)conn;
+
+ if(select_res & CURL_CSELECT_IN) {
+ if(h->read_waker)
+ hyper_waker_wake(h->read_waker);
+ h->read_waker = NULL;
+ }
+ if(select_res & CURL_CSELECT_OUT) {
+ if(h->write_waker)
+ hyper_waker_wake(h->write_waker);
+ h->write_waker = NULL;
+ }
+
+ *done = FALSE;
+ do {
+ hyper_task_return_type t;
+ task = hyper_executor_poll(h->exec);
+ if(!task) {
+ *didwhat = KEEP_RECV;
+ break;
+ }
+ t = hyper_task_type(task);
+ switch(t) {
+ case HYPER_TASK_ERROR:
+ hypererr = hyper_task_value(task);
+ break;
+ case HYPER_TASK_RESPONSE:
+ resp = hyper_task_value(task);
+ break;
+ default:
+ break;
+ }
+ hyper_task_free(task);
+
+ if(t == HYPER_TASK_ERROR) {
+ hyper_code errnum = hyper_error_code(hypererr);
+ if(errnum == HYPERE_ABORTED_BY_CALLBACK) {
+ /* override Hyper's view, might not even be an error */
+ result = data->state.hresult;
+ infof(data, "hyperstream is done (by early callback)\n");
+ }
+ else {
+ uint8_t errbuf[256];
+ size_t errlen = hyper_error_print(hypererr, errbuf, sizeof(errbuf));
+ hyper_code code = hyper_error_code(hypererr);
+ failf(data, "Hyper: [%d] %.*s", (int)code, (int)errlen, errbuf);
+ if((code == HYPERE_UNEXPECTED_EOF) && !data->req.bytecount)
+ result = CURLE_GOT_NOTHING;
+ else
+ result = CURLE_RECV_ERROR;
+ }
+ *done = TRUE;
+ hyper_error_free(hypererr);
+ break;
+ }
+ else if(h->endtask == task) {
+ /* end of transfer */
+ *done = TRUE;
+ infof(data, "hyperstream is done!\n");
+ break;
+ }
+ else if(t != HYPER_TASK_RESPONSE) {
+ *didwhat = KEEP_RECV;
+ break;
+ }
+ /* HYPER_TASK_RESPONSE */
+
+ *didwhat = KEEP_RECV;
+ if(!resp) {
+ failf(data, "hyperstream: couldn't get response");
+ return CURLE_RECV_ERROR;
+ }
+
+ http_status = hyper_response_status(resp);
+ http_version = hyper_response_version(resp);
+ reasonp = hyper_response_reason_phrase(resp);
+ reason_len = hyper_response_reason_phrase_len(resp);
+
+ result = status_line(data, conn,
+ http_status, http_version, reasonp, reason_len);
+ if(result)
+ break;
+
+ headers = hyper_response_headers(resp);
+ if(!headers) {
+ failf(data, "hyperstream: couldn't get response headers");
+ result = CURLE_RECV_ERROR;
+ break;
+ }
+
+ /* the headers are already received */
+ hyper_headers_foreach(headers, hyper_each_header, data);
+ if(data->state.hresult) {
+ result = data->state.hresult;
+ break;
+ }
+
+ if(empty_header(data)) {
+ failf(data, "hyperstream: couldn't pass blank header");
+ result = CURLE_OUT_OF_MEMORY;
+ break;
+ }
+
+ /* Curl_http_auth_act() checks what authentication methods that are
+ * available and decides which one (if any) to use. It will set 'newurl'
+ * if an auth method was picked. */
+ result = Curl_http_auth_act(data);
+ if(result)
+ break;
+
+ resp_body = hyper_response_body(resp);
+ if(!resp_body) {
+ failf(data, "hyperstream: couldn't get response body");
+ result = CURLE_RECV_ERROR;
+ break;
+ }
+ foreach = hyper_body_foreach(resp_body, hyper_body_chunk, data);
+ if(!foreach) {
+ failf(data, "hyperstream: body foreach failed");
+ result = CURLE_OUT_OF_MEMORY;
+ break;
+ }
+ DEBUGASSERT(hyper_task_type(foreach) == HYPER_TASK_EMPTY);
+ if(HYPERE_OK != hyper_executor_push(h->exec, foreach)) {
+ failf(data, "Couldn't hyper_executor_push the body-foreach");
+ result = CURLE_OUT_OF_MEMORY;
+ break;
+ }
+ h->endtask = foreach;
+
+ hyper_response_free(resp);
+ resp = NULL;
+ } while(1);
+ if(resp)
+ hyper_response_free(resp);
+ return result;
+}
+
+static CURLcode debug_request(struct Curl_easy *data,
+ const char *method,
+ const char *path,
+ bool h2)
+{
+ char *req = aprintf("%s %s HTTP/%s\r\n", method, path,
+ h2?"2":"1.1");
+ if(!req)
+ return CURLE_OUT_OF_MEMORY;
+ Curl_debug(data, CURLINFO_HEADER_OUT, req, strlen(req));
+ free(req);
+ return CURLE_OK;
+}
+
+/*
+ * Given a full header line "name: value" (optional CRLF in the input, should
+ * be in the output), add to Hyper and send to the debug callback.
+ *
+ * Supports multiple headers.
+ */
+
+CURLcode Curl_hyper_header(struct Curl_easy *data, hyper_headers *headers,
+ const char *line)
+{
+ const char *p;
+ const char *n;
+ size_t nlen;
+ const char *v;
+ size_t vlen;
+ bool newline = TRUE;
+ int numh = 0;
+
+ if(!line)
+ return CURLE_OK;
+ n = line;
+ do {
+ size_t linelen = 0;
+
+ p = strchr(n, ':');
+ if(!p)
+ /* this is fine if we already added at least one header */
+ return numh ? CURLE_OK : CURLE_BAD_FUNCTION_ARGUMENT;
+ nlen = p - n;
+ p++; /* move past the colon */
+ while(*p == ' ')
+ p++;
+ v = p;
+ p = strchr(v, '\r');
+ if(!p) {
+ p = strchr(v, '\n');
+ if(p)
+ linelen = 1; /* LF only */
+ else {
+ p = strchr(v, '\0');
+ newline = FALSE; /* no newline */
+ }
+ }
+ else
+ linelen = 2; /* CRLF ending */
+ linelen += (p - n);
+ if(!n)
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ vlen = p - v;
+
+ if(HYPERE_OK != hyper_headers_add(headers, (uint8_t *)n, nlen,
+ (uint8_t *)v, vlen)) {
+ failf(data, "hyper_headers_add host");
+ return CURLE_OUT_OF_MEMORY;
+ }
+ if(data->set.verbose) {
+ char *ptr = NULL;
+ if(!newline) {
+ ptr = aprintf("%.*s\r\n", (int)linelen, line);
+ if(!ptr)
+ return CURLE_OUT_OF_MEMORY;
+ Curl_debug(data, CURLINFO_HEADER_OUT, ptr, linelen + 2);
+ free(ptr);
+ }
+ else
+ Curl_debug(data, CURLINFO_HEADER_OUT, (char *)line, linelen);
+ }
+ numh++;
+ n += linelen;
+ } while(newline);
+ return CURLE_OK;
+}
+
+static CURLcode request_target(struct Curl_easy *data,
+ struct connectdata *conn,
+ const char *method,
+ bool h2,
+ hyper_request *req)
+{
+ CURLcode result;
+ struct dynbuf r;
+
+ Curl_dyn_init(&r, DYN_HTTP_REQUEST);
+
+ result = Curl_http_target(data, conn, &r);
+ if(result)
+ return result;
+
+ if(hyper_request_set_uri(req, (uint8_t *)Curl_dyn_uptr(&r),
+ Curl_dyn_len(&r))) {
+ failf(data, "error setting path");
+ result = CURLE_OUT_OF_MEMORY;
+ }
+ else
+ result = debug_request(data, method, Curl_dyn_ptr(&r), h2);
+
+ Curl_dyn_free(&r);
+
+ return result;
+}
+
+static int uploadpostfields(void *userdata, hyper_context *ctx,
+ hyper_buf **chunk)
+{
+ struct Curl_easy *data = (struct Curl_easy *)userdata;
+ (void)ctx;
+ if(data->req.upload_done)
+ *chunk = NULL; /* nothing more to deliver */
+ else {
+ /* send everything off in a single go */
+ *chunk = hyper_buf_copy(data->set.postfields,
+ (size_t)data->req.p.http->postsize);
+ data->req.upload_done = TRUE;
+ }
+ return HYPER_POLL_READY;
+}
+
+static int uploadstreamed(void *userdata, hyper_context *ctx,
+ hyper_buf **chunk)
+{
+ size_t fillcount;
+ struct Curl_easy *data = (struct Curl_easy *)userdata;
+ CURLcode result =
+ Curl_fillreadbuffer(data, data->set.upload_buffer_size, &fillcount);
+ (void)ctx;
+ if(result)
+ return HYPER_POLL_ERROR;
+ if(!fillcount)
+ /* done! */
+ *chunk = NULL;
+ else
+ *chunk = hyper_buf_copy((uint8_t *)data->state.ulbuf, fillcount);
+ return HYPER_POLL_READY;
+}
+
+/*
+ * bodysend() sets up headers in the outgoing request for a HTTP transfer that
+ * sends a body
+ */
+
+static CURLcode bodysend(struct Curl_easy *data,
+ struct connectdata *conn,
+ hyper_headers *headers,
+ hyper_request *hyperreq,
+ Curl_HttpReq httpreq)
+{
+ CURLcode result = CURLE_OK;
+ struct dynbuf req;
+ if((httpreq == HTTPREQ_GET) || (httpreq == HTTPREQ_HEAD))
+ Curl_pgrsSetUploadSize(data, 0); /* no request body */
+ else {
+ hyper_body *body;
+ Curl_dyn_init(&req, DYN_HTTP_REQUEST);
+ result = Curl_http_bodysend(data, conn, &req, httpreq);
+
+ if(!result)
+ result = Curl_hyper_header(data, headers, Curl_dyn_ptr(&req));
+
+ Curl_dyn_free(&req);
+
+ body = hyper_body_new();
+ hyper_body_set_userdata(body, data);
+ if(data->set.postfields)
+ hyper_body_set_data_func(body, uploadpostfields);
+ else {
+ result = Curl_get_upload_buffer(data);
+ if(result)
+ return result;
+ /* init the "upload from here" pointer */
+ data->req.upload_fromhere = data->state.ulbuf;
+ hyper_body_set_data_func(body, uploadstreamed);
+ }
+ if(HYPERE_OK != hyper_request_set_body(hyperreq, body)) {
+ /* fail */
+ hyper_body_free(body);
+ result = CURLE_OUT_OF_MEMORY;
+ }
+ }
+ return result;
+}
+
+static CURLcode cookies(struct Curl_easy *data,
+ struct connectdata *conn,
+ hyper_headers *headers)
+{
+ struct dynbuf req;
+ CURLcode result;
+ Curl_dyn_init(&req, DYN_HTTP_REQUEST);
+
+ result = Curl_http_cookies(data, conn, &req);
+ if(!result)
+ result = Curl_hyper_header(data, headers, Curl_dyn_ptr(&req));
+ Curl_dyn_free(&req);
+ return result;
+}
+
+/*
+ * Curl_http() gets called from the generic multi_do() function when a HTTP
+ * request is to be performed. This creates and sends a properly constructed
+ * HTTP request.
+ */
+CURLcode Curl_http(struct Curl_easy *data, bool *done)
+{
+ struct connectdata *conn = data->conn;
+ struct hyptransfer *h = &data->hyp;
+ hyper_io *io = NULL;
+ hyper_clientconn_options *options = NULL;
+ hyper_task *task = NULL; /* for the handshake */
+ hyper_task *sendtask = NULL; /* for the send */
+ hyper_clientconn *client = NULL;
+ hyper_request *req = NULL;
+ hyper_headers *headers = NULL;
+ hyper_task *handshake = NULL;
+ hyper_error *hypererr = NULL;
+ CURLcode result;
+ const char *p_accept; /* Accept: string */
+ const char *method;
+ Curl_HttpReq httpreq;
+ bool h2 = FALSE;
+ const char *te = NULL; /* transfer-encoding */
+
+ /* Always consider the DO phase done after this function call, even if there
+ may be parts of the request that is not yet sent, since we can deal with
+ the rest of the request in the PERFORM phase. */
+ *done = TRUE;
+
+ infof(data, "Time for the Hyper dance\n");
+ memset(h, 0, sizeof(struct hyptransfer));
+
+ result = Curl_http_host(data, conn);
+ if(result)
+ return result;
+
+ Curl_http_method(data, conn, &method, &httpreq);
+
+ /* setup the authentication headers */
+ {
+ char *pq = NULL;
+ if(data->state.up.query) {
+ pq = aprintf("%s?%s", data->state.up.path, data->state.up.query);
+ if(!pq)
+ return CURLE_OUT_OF_MEMORY;
+ }
+ result = Curl_http_output_auth(data, conn, method, httpreq,
+ (pq ? pq : data->state.up.path), FALSE);
+ free(pq);
+ if(result)
+ return result;
+ }
+
+ result = Curl_http_resume(data, conn, httpreq);
+ if(result)
+ return result;
+
+ result = Curl_http_range(data, httpreq);
+ if(result)
+ return result;
+
+ result = Curl_http_useragent(data);
+ if(result)
+ return result;
+
+ io = hyper_io_new();
+ if(!io) {
+ failf(data, "Couldn't create hyper IO");
+ goto error;
+ }
+ /* tell Hyper how to read/write network data */
+ hyper_io_set_userdata(io, data);
+ hyper_io_set_read(io, Curl_hyper_recv);
+ hyper_io_set_write(io, Curl_hyper_send);
+
+ /* create an executor to poll futures */
+ if(!h->exec) {
+ h->exec = hyper_executor_new();
+ if(!h->exec) {
+ failf(data, "Couldn't create hyper executor");
+ goto error;
+ }
+ }
+
+ options = hyper_clientconn_options_new();
+ if(!options) {
+ failf(data, "Couldn't create hyper client options");
+ goto error;
+ }
+ if(conn->negnpn == CURL_HTTP_VERSION_2) {
+ hyper_clientconn_options_http2(options, 1);
+ h2 = TRUE;
+ }
+
+ hyper_clientconn_options_exec(options, h->exec);
+
+ /* "Both the `io` and the `options` are consumed in this function call" */
+ handshake = hyper_clientconn_handshake(io, options);
+ if(!handshake) {
+ failf(data, "Couldn't create hyper client handshake");
+ goto error;
+ }
+ io = NULL;
+ options = NULL;
+
+ if(HYPERE_OK != hyper_executor_push(h->exec, handshake)) {
+ failf(data, "Couldn't hyper_executor_push the handshake");
+ goto error;
+ }
+ handshake = NULL; /* ownership passed on */
+
+ task = hyper_executor_poll(h->exec);
+ if(!task) {
+ failf(data, "Couldn't hyper_executor_poll the handshake");
+ goto error;
+ }
+
+ client = hyper_task_value(task);
+ hyper_task_free(task);
+
+ req = hyper_request_new();
+ if(!req) {
+ failf(data, "Couldn't hyper_request_new");
+ goto error;
+ }
+
+ if(data->set.httpversion == CURL_HTTP_VERSION_1_0) {
+ if(HYPERE_OK != hyper_request_set_version(req,
+ HYPER_HTTP_VERSION_1_0)) {
+ failf(data, "error setting HTTP version");
+ goto error;
+ }
+ }
+
+ if(hyper_request_set_method(req, (uint8_t *)method, strlen(method))) {
+ failf(data, "error setting method");
+ goto error;
+ }
+
+ result = request_target(data, conn, method, h2, req);
+ if(result)
+ goto error;
+
+ headers = hyper_request_headers(req);
+ if(!headers) {
+ failf(data, "hyper_request_headers");
+ goto error;
+ }
+
+ result = Curl_http_body(data, conn, httpreq, &te);
+ if(result)
+ return result;
+
+ if(data->state.aptr.host &&
+ Curl_hyper_header(data, headers, data->state.aptr.host))
+ goto error;
+
+ if(data->state.aptr.proxyuserpwd &&
+ Curl_hyper_header(data, headers, data->state.aptr.proxyuserpwd))
+ goto error;
+
+ if(data->state.aptr.userpwd &&
+ Curl_hyper_header(data, headers, data->state.aptr.userpwd))
+ goto error;
+
+ if((data->state.use_range && data->state.aptr.rangeline) &&
+ Curl_hyper_header(data, headers, data->state.aptr.rangeline))
+ goto error;
+
+ if(data->set.str[STRING_USERAGENT] &&
+ *data->set.str[STRING_USERAGENT] &&
+ data->state.aptr.uagent &&
+ Curl_hyper_header(data, headers, data->state.aptr.uagent))
+ goto error;
+
+ p_accept = Curl_checkheaders(data, "Accept")?NULL:"Accept: */*\r\n";
+ if(p_accept && Curl_hyper_header(data, headers, p_accept))
+ goto error;
+
+ if(te && Curl_hyper_header(data, headers, te))
+ goto error;
+
+#ifndef CURL_DISABLE_PROXY
+ if(conn->bits.httpproxy && !conn->bits.tunnel_proxy &&
+ !Curl_checkheaders(data, "Proxy-Connection") &&
+ !Curl_checkProxyheaders(data, conn, "Proxy-Connection")) {
+ if(Curl_hyper_header(data, headers, "Proxy-Connection: Keep-Alive"))
+ goto error;
+ }
+#endif
+
+ Curl_safefree(data->state.aptr.ref);
+ if(data->change.referer && !Curl_checkheaders(data, "Referer")) {
+ data->state.aptr.ref = aprintf("Referer: %s\r\n", data->change.referer);
+ if(!data->state.aptr.ref)
+ return CURLE_OUT_OF_MEMORY;
+ if(Curl_hyper_header(data, headers, data->state.aptr.ref))
+ goto error;
+ }
+
+ result = cookies(data, conn, headers);
+ if(result)
+ return result;
+
+ result = Curl_add_timecondition(data, headers);
+ if(result)
+ return result;
+
+ result = Curl_add_custom_headers(data, FALSE, headers);
+ if(result)
+ return result;
+
+ result = bodysend(data, conn, headers, req, httpreq);
+ if(result)
+ return result;
+
+ Curl_debug(data, CURLINFO_HEADER_OUT, (char *)"\r\n", 2);
+
+ data->req.upload_chunky = FALSE;
+ sendtask = hyper_clientconn_send(client, req);
+ if(!sendtask) {
+ failf(data, "hyper_clientconn_send");
+ goto error;
+ }
+
+ if(HYPERE_OK != hyper_executor_push(h->exec, sendtask)) {
+ failf(data, "Couldn't hyper_executor_push the send");
+ goto error;
+ }
+
+ hyper_clientconn_free(client);
+
+ do {
+ task = hyper_executor_poll(h->exec);
+ if(task) {
+ bool error = hyper_task_type(task) == HYPER_TASK_ERROR;
+ if(error)
+ hypererr = hyper_task_value(task);
+ hyper_task_free(task);
+ if(error)
+ goto error;
+ }
+ } while(task);
+
+ if((httpreq == HTTPREQ_GET) || (httpreq == HTTPREQ_HEAD)) {
+ /* HTTP GET/HEAD download */
+ Curl_pgrsSetUploadSize(data, 0); /* nothing */
+ Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE, -1);
+ }
+ conn->datastream = Curl_hyper_stream;
+
+ return CURLE_OK;
+ error:
+
+ if(io)
+ hyper_io_free(io);
+
+ if(options)
+ hyper_clientconn_options_free(options);
+
+ if(handshake)
+ hyper_task_free(handshake);
+
+ if(hypererr) {
+ uint8_t errbuf[256];
+ size_t errlen = hyper_error_print(hypererr, errbuf, sizeof(errbuf));
+ hyper_code code = hyper_error_code(hypererr);
+ failf(data, "Hyper: [%d] %.*s", (int)code, (int)errlen, errbuf);
+ hyper_error_free(hypererr);
+ }
+ return CURLE_OUT_OF_MEMORY;
+}
+
+void Curl_hyper_done(struct Curl_easy *data)
+{
+ struct hyptransfer *h = &data->hyp;
+ if(h->exec) {
+ hyper_executor_free(h->exec);
+ h->exec = NULL;
+ }
+ if(h->read_waker) {
+ hyper_waker_free(h->read_waker);
+ h->read_waker = NULL;
+ }
+ if(h->write_waker) {
+ hyper_waker_free(h->write_waker);
+ h->write_waker = NULL;
+ }
+}
+
+#endif /* !defined(CURL_DISABLE_HTTP) && defined(USE_HYPER) */
diff --git a/Utilities/cmcurl/lib/c-hyper.h b/Utilities/cmcurl/lib/c-hyper.h
new file mode 100644
index 000000000..d60ed78d1
--- /dev/null
+++ b/Utilities/cmcurl/lib/c-hyper.h
@@ -0,0 +1,56 @@
+#ifndef HEADER_CURL_HYPER_H
+#define HEADER_CURL_HYPER_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "curl_setup.h"
+
+#if !defined(CURL_DISABLE_HTTP) && defined(USE_HYPER)
+
+#include <hyper.h>
+
+/* per-transfer data for the Hyper backend */
+struct hyptransfer {
+ hyper_waker *write_waker;
+ hyper_waker *read_waker;
+ const hyper_executor *exec;
+ hyper_task *endtask;
+};
+
+size_t Curl_hyper_recv(void *userp, hyper_context *ctx,
+ uint8_t *buf, size_t buflen);
+size_t Curl_hyper_send(void *userp, hyper_context *ctx,
+ const uint8_t *buf, size_t buflen);
+CURLcode Curl_hyper_stream(struct Curl_easy *data,
+ struct connectdata *conn,
+ int *didwhat,
+ bool *done,
+ int select_res);
+
+CURLcode Curl_hyper_header(struct Curl_easy *data, hyper_headers *headers,
+ const char *line);
+void Curl_hyper_done(struct Curl_easy *);
+
+#else
+#define Curl_hyper_done(x)
+
+#endif /* !defined(CURL_DISABLE_HTTP) && defined(USE_HYPER) */
+#endif /* HEADER_CURL_HYPER_H */
diff --git a/Utilities/cmcurl/lib/conncache.c b/Utilities/cmcurl/lib/conncache.c
index d21a00cfd..8dfdc0ac8 100644
--- a/Utilities/cmcurl/lib/conncache.c
+++ b/Utilities/cmcurl/lib/conncache.c
@@ -6,11 +6,11 @@
* \___|\___/|_| \_\_____|
*
* Copyright (C) 2012 - 2016, Linus Nielsen Feltzing, <linus@haxx.se>
- * Copyright (C) 2012 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2012 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -59,7 +59,7 @@ static CURLcode bundle_create(struct connectbundle **bundlep)
(*bundlep)->num_connections = 0;
(*bundlep)->multiuse = BUNDLE_UNKNOWN;
- Curl_llist_init(&(*bundlep)->conn_list, (curl_llist_dtor) conn_llist_dtor);
+ Curl_llist_init(&(*bundlep)->conn_list, (Curl_llist_dtor) conn_llist_dtor);
return CURLE_OK;
}
@@ -87,7 +87,7 @@ static void bundle_add_conn(struct connectbundle *bundle,
static int bundle_remove_conn(struct connectbundle *bundle,
struct connectdata *conn)
{
- struct curl_llist_element *curr;
+ struct Curl_llist_element *curr;
curr = bundle->conn_list.head;
while(curr) {
@@ -179,12 +179,14 @@ size_t Curl_conncache_size(struct Curl_easy *data)
connectdata struct is setup to use.
**NOTE**: When it returns, it holds the connection cache lock! */
-struct connectbundle *Curl_conncache_find_bundle(struct connectdata *conn,
- struct conncache *connc,
- const char **hostp)
+struct connectbundle *
+Curl_conncache_find_bundle(struct Curl_easy *data,
+ struct connectdata *conn,
+ struct conncache *connc,
+ const char **hostp)
{
struct connectbundle *bundle = NULL;
- CONNCACHE_LOCK(conn->data);
+ CONNCACHE_LOCK(data);
if(connc) {
char key[HASHKEY_SIZE];
hashkey(conn, key, sizeof(key), hostp);
@@ -206,8 +208,8 @@ static bool conncache_add_bundle(struct conncache *connc,
static void conncache_remove_bundle(struct conncache *connc,
struct connectbundle *bundle)
{
- struct curl_hash_iterator iter;
- struct curl_hash_element *he;
+ struct Curl_hash_iterator iter;
+ struct Curl_hash_element *he;
if(!connc)
return;
@@ -227,15 +229,17 @@ static void conncache_remove_bundle(struct conncache *connc,
}
}
-CURLcode Curl_conncache_add_conn(struct conncache *connc,
- struct connectdata *conn)
+CURLcode Curl_conncache_add_conn(struct Curl_easy *data)
{
CURLcode result = CURLE_OK;
struct connectbundle *bundle = NULL;
- struct Curl_easy *data = conn->data;
+ struct connectdata *conn = data->conn;
+ struct conncache *connc = data->state.conn_cache;
+ DEBUGASSERT(conn);
/* *find_bundle() locks the connection cache */
- bundle = Curl_conncache_find_bundle(conn, data->state.conn_cache, NULL);
+ bundle = Curl_conncache_find_bundle(data, conn, data->state.conn_cache,
+ NULL);
if(!bundle) {
int rc;
char key[HASHKEY_SIZE];
@@ -259,7 +263,7 @@ CURLcode Curl_conncache_add_conn(struct conncache *connc,
conn->connection_id = connc->next_connection_id++;
connc->num_conn++;
- DEBUGF(infof(conn->data, "Added connection %ld. "
+ DEBUGF(infof(data, "Added connection %ld. "
"The cache now contains %zu members\n",
conn->connection_id, connc->num_conn));
@@ -270,8 +274,8 @@ CURLcode Curl_conncache_add_conn(struct conncache *connc,
}
/*
- * Removes the connectdata object from the connection cache, but does *not*
- * clear the conn->data association. The transfer still owns this connection.
+ * Removes the connectdata object from the connection cache, but the transfer
+ * still owns this connection.
*
* Pass TRUE/FALSE in the 'lock' argument depending on if the parent function
* already holds the lock or not.
@@ -318,11 +322,12 @@ void Curl_conncache_remove_conn(struct Curl_easy *data,
bool Curl_conncache_foreach(struct Curl_easy *data,
struct conncache *connc,
void *param,
- int (*func)(struct connectdata *conn, void *param))
+ int (*func)(struct Curl_easy *data,
+ struct connectdata *conn, void *param))
{
- struct curl_hash_iterator iter;
- struct curl_llist_element *curr;
- struct curl_hash_element *he;
+ struct Curl_hash_iterator iter;
+ struct Curl_llist_element *curr;
+ struct Curl_hash_element *he;
if(!connc)
return FALSE;
@@ -344,7 +349,7 @@ bool Curl_conncache_foreach(struct Curl_easy *data,
struct connectdata *conn = curr->ptr;
curr = curr->next;
- if(1 == func(conn, param)) {
+ if(1 == func(data, conn, param)) {
CONNCACHE_UNLOCK(data);
return TRUE;
}
@@ -363,15 +368,15 @@ bool Curl_conncache_foreach(struct Curl_easy *data,
static struct connectdata *
conncache_find_first_connection(struct conncache *connc)
{
- struct curl_hash_iterator iter;
- struct curl_hash_element *he;
+ struct Curl_hash_iterator iter;
+ struct Curl_hash_element *he;
struct connectbundle *bundle;
Curl_hash_start_iterate(&connc->hash, &iter);
he = Curl_hash_next_element(&iter);
while(he) {
- struct curl_llist_element *curr;
+ struct Curl_llist_element *curr;
bundle = he->ptr;
curr = bundle->conn_list.head;
@@ -429,7 +434,7 @@ struct connectdata *
Curl_conncache_extract_bundle(struct Curl_easy *data,
struct connectbundle *bundle)
{
- struct curl_llist_element *curr;
+ struct Curl_llist_element *curr;
timediff_t highscore = -1;
timediff_t score;
struct curltime now;
@@ -444,7 +449,7 @@ Curl_conncache_extract_bundle(struct Curl_easy *data,
while(curr) {
conn = curr->ptr;
- if(!CONN_INUSE(conn) && !conn->data) {
+ if(!CONN_INUSE(conn)) {
/* Set higher score for the age passed since the connection was used */
score = Curl_timediff(now, conn->lastused);
@@ -477,9 +482,9 @@ struct connectdata *
Curl_conncache_extract_oldest(struct Curl_easy *data)
{
struct conncache *connc = data->state.conn_cache;
- struct curl_hash_iterator iter;
- struct curl_llist_element *curr;
- struct curl_hash_element *he;
+ struct Curl_hash_iterator iter;
+ struct Curl_llist_element *curr;
+ struct Curl_hash_element *he;
timediff_t highscore =- 1;
timediff_t score;
struct curltime now;
@@ -502,7 +507,7 @@ Curl_conncache_extract_oldest(struct Curl_easy *data)
while(curr) {
conn = curr->ptr;
- if(!CONN_INUSE(conn) && !conn->data && !conn->bits.close &&
+ if(!CONN_INUSE(conn) && !conn->bits.close &&
!conn->bits.connect_only) {
/* Set higher score for the age passed since the connection was used */
score = Curl_timediff(now, conn->lastused);
@@ -543,12 +548,10 @@ void Curl_conncache_close_all_connections(struct conncache *connc)
conn = conncache_find_first_connection(connc);
while(conn) {
SIGPIPE_VARIABLE(pipe_st);
- conn->data = connc->closure_handle;
-
- sigpipe_ignore(conn->data, &pipe_st);
+ sigpipe_ignore(connc->closure_handle, &pipe_st);
/* This will remove the connection from the cache */
connclose(conn, "kill all");
- Curl_conncache_remove_conn(conn->data, conn, TRUE);
+ Curl_conncache_remove_conn(connc->closure_handle, conn, TRUE);
(void)Curl_disconnect(connc->closure_handle, conn, FALSE);
sigpipe_restore(&pipe_st);
@@ -571,9 +574,9 @@ void Curl_conncache_close_all_connections(struct conncache *connc)
/* Useful for debugging the connection cache */
void Curl_conncache_print(struct conncache *connc)
{
- struct curl_hash_iterator iter;
- struct curl_llist_element *curr;
- struct curl_hash_element *he;
+ struct Curl_hash_iterator iter;
+ struct Curl_llist_element *curr;
+ struct Curl_hash_element *he;
if(!connc)
return;
diff --git a/Utilities/cmcurl/lib/conncache.h b/Utilities/cmcurl/lib/conncache.h
index 3dda21cdc..e9c1e32f8 100644
--- a/Utilities/cmcurl/lib/conncache.h
+++ b/Utilities/cmcurl/lib/conncache.h
@@ -7,12 +7,12 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2015 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2015 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 2012 - 2014, Linus Nielsen Feltzing, <linus@haxx.se>
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -29,8 +29,12 @@
* be shared.
*/
+#include "timeval.h"
+
+struct connectdata;
+
struct conncache {
- struct curl_hash hash;
+ struct Curl_hash hash;
size_t num_conn;
long next_connection_id;
struct curltime last_cleanup;
@@ -45,17 +49,24 @@ struct conncache {
#ifdef CURLDEBUG
/* the debug versions of these macros make extra certain that the lock is
never doubly locked or unlocked */
-#define CONNCACHE_LOCK(x) if((x)->share) { \
- Curl_share_lock((x), CURL_LOCK_DATA_CONNECT, CURL_LOCK_ACCESS_SINGLE); \
- DEBUGASSERT(!(x)->state.conncache_lock); \
- (x)->state.conncache_lock = TRUE; \
- }
+#define CONNCACHE_LOCK(x) \
+ do { \
+ if((x)->share) { \
+ Curl_share_lock((x), CURL_LOCK_DATA_CONNECT, \
+ CURL_LOCK_ACCESS_SINGLE); \
+ DEBUGASSERT(!(x)->state.conncache_lock); \
+ (x)->state.conncache_lock = TRUE; \
+ } \
+ } while(0)
-#define CONNCACHE_UNLOCK(x) if((x)->share) { \
- DEBUGASSERT((x)->state.conncache_lock); \
- (x)->state.conncache_lock = FALSE; \
- Curl_share_unlock((x), CURL_LOCK_DATA_CONNECT); \
- }
+#define CONNCACHE_UNLOCK(x) \
+ do { \
+ if((x)->share) { \
+ DEBUGASSERT((x)->state.conncache_lock); \
+ (x)->state.conncache_lock = FALSE; \
+ Curl_share_unlock((x), CURL_LOCK_DATA_CONNECT); \
+ } \
+ } while(0)
#else
#define CONNCACHE_LOCK(x) if((x)->share) \
Curl_share_lock((x), CURL_LOCK_DATA_CONNECT, CURL_LOCK_ACCESS_SINGLE)
@@ -66,7 +77,7 @@ struct conncache {
struct connectbundle {
int multiuse; /* supports multi-use */
size_t num_connections; /* Number of connections in the bundle */
- struct curl_llist conn_list; /* The connectdata members of the bundle */
+ struct Curl_llist conn_list; /* The connectdata members of the bundle */
};
/* returns 1 on error, 0 is fine */
@@ -74,7 +85,8 @@ int Curl_conncache_init(struct conncache *, int size);
void Curl_conncache_destroy(struct conncache *connc);
/* return the correct bundle, to a host or a proxy */
-struct connectbundle *Curl_conncache_find_bundle(struct connectdata *conn,
+struct connectbundle *Curl_conncache_find_bundle(struct Curl_easy *data,
+ struct connectdata *conn,
struct conncache *connc,
const char **hostp);
/* returns number of connections currently held in the connection cache */
@@ -82,15 +94,15 @@ size_t Curl_conncache_size(struct Curl_easy *data);
bool Curl_conncache_return_conn(struct Curl_easy *data,
struct connectdata *conn);
-CURLcode Curl_conncache_add_conn(struct conncache *connc,
- struct connectdata *conn) WARN_UNUSED_RESULT;
+CURLcode Curl_conncache_add_conn(struct Curl_easy *data) WARN_UNUSED_RESULT;
void Curl_conncache_remove_conn(struct Curl_easy *data,
struct connectdata *conn,
bool lock);
bool Curl_conncache_foreach(struct Curl_easy *data,
struct conncache *connc,
void *param,
- int (*func)(struct connectdata *conn,
+ int (*func)(struct Curl_easy *data,
+ struct connectdata *conn,
void *param));
struct connectdata *
diff --git a/Utilities/cmcurl/lib/connect.c b/Utilities/cmcurl/lib/connect.c
index b000b1b2c..baab1840e 100644
--- a/Utilities/cmcurl/lib/connect.c
+++ b/Utilities/cmcurl/lib/connect.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -83,11 +83,6 @@
#include "curl_memory.h"
#include "memdebug.h"
-#ifdef __SYMBIAN32__
-/* This isn't actually supported under Symbian OS */
-#undef SO_NOSIGPIPE
-#endif
-
static bool verifyconnect(curl_socket_t sockfd, int *error);
#if defined(__DragonFly__) || defined(HAVE_WINSOCK_H)
@@ -165,7 +160,8 @@ tcpkeepalive(struct Curl_easy *data,
}
static CURLcode
-singleipconnect(struct connectdata *conn,
+singleipconnect(struct Curl_easy *data,
+ struct connectdata *conn,
const struct Curl_addrinfo *ai, /* start connecting to this */
int tempindex); /* 0 or 1 among the temp ones */
@@ -241,11 +237,10 @@ timediff_t Curl_timeleft(struct Curl_easy *data,
return timeout_ms;
}
-static CURLcode bindlocal(struct connectdata *conn,
+static CURLcode bindlocal(struct Curl_easy *data,
curl_socket_t sockfd, int af, unsigned int scope)
{
- struct Curl_easy *data = conn->data;
-
+ struct connectdata *conn = data->conn;
struct Curl_sockaddr_storage sa;
struct sockaddr *sock = (struct sockaddr *)&sa; /* bind to this address */
curl_socklen_t sizeof_sa = 0; /* size of the data sock points to */
@@ -261,6 +256,9 @@ static CURLcode bindlocal(struct connectdata *conn,
int portnum = data->set.localportrange;
const char *dev = data->set.str[STRING_DEVICE];
int error;
+#ifdef IP_BIND_ADDRESS_NO_PORT
+ int on = 1;
+#endif
/*************************************************************
* Select device to bind socket to
@@ -350,7 +348,7 @@ static CURLcode bindlocal(struct connectdata *conn,
* of the connection. The resolve functions should really be changed
* to take a type parameter instead.
*/
- long ipver = conn->ip_version;
+ unsigned char ipver = conn->ip_version;
int rc;
if(af == AF_INET)
@@ -360,9 +358,9 @@ static CURLcode bindlocal(struct connectdata *conn,
conn->ip_version = CURL_IPRESOLVE_V6;
#endif
- rc = Curl_resolv(conn, dev, 0, FALSE, &h);
+ rc = Curl_resolv(data, dev, 0, FALSE, &h);
if(rc == CURLRESOLV_PENDING)
- (void)Curl_resolver_wait_resolv(conn, &h);
+ (void)Curl_resolver_wait_resolv(data, &h);
conn->ip_version = ipver;
if(h) {
@@ -446,7 +444,9 @@ static CURLcode bindlocal(struct connectdata *conn,
sizeof_sa = sizeof(struct sockaddr_in);
}
}
-
+#ifdef IP_BIND_ADDRESS_NO_PORT
+ (void)setsockopt(sockfd, SOL_IP, IP_BIND_ADDRESS_NO_PORT, &on, sizeof(on));
+#endif
for(;;) {
if(bind(sockfd, sock, sizeof_sa) >= 0) {
/* we succeeded to bind */
@@ -573,7 +573,8 @@ static struct Curl_addrinfo *ainext(struct connectdata *conn,
/* Used within the multi interface. Try next IP address, returns error if no
more address exists or error */
-static CURLcode trynextip(struct connectdata *conn,
+static CURLcode trynextip(struct Curl_easy *data,
+ struct connectdata *conn,
int sockindex,
int tempindex)
{
@@ -591,7 +592,7 @@ static CURLcode trynextip(struct connectdata *conn,
while(ai) {
if(ai) {
- result = singleipconnect(conn, ai, tempindex);
+ result = singleipconnect(data, conn, ai, tempindex);
if(result == CURLE_COULDNT_CONNECT) {
ai = ainext(conn, tempindex, TRUE);
continue;
@@ -602,21 +603,25 @@ static CURLcode trynextip(struct connectdata *conn,
}
if(fd_to_close != CURL_SOCKET_BAD)
- Curl_closesocket(conn, fd_to_close);
+ Curl_closesocket(data, conn, fd_to_close);
return result;
}
-/* Copies connection info into the session handle to make it available
- when the session handle is no longer associated with a connection. */
-void Curl_persistconninfo(struct connectdata *conn)
+/* Copies connection info into the transfer handle to make it available when
+ the transfer handle is no longer associated with the connection. */
+void Curl_persistconninfo(struct Curl_easy *data, struct connectdata *conn,
+ char *local_ip, long local_port)
{
- memcpy(conn->data->info.conn_primary_ip, conn->primary_ip, MAX_IPADR_LEN);
- memcpy(conn->data->info.conn_local_ip, conn->local_ip, MAX_IPADR_LEN);
- conn->data->info.conn_scheme = conn->handler->scheme;
- conn->data->info.conn_protocol = conn->handler->protocol;
- conn->data->info.conn_primary_port = conn->primary_port;
- conn->data->info.conn_local_port = conn->local_port;
+ memcpy(data->info.conn_primary_ip, conn->primary_ip, MAX_IPADR_LEN);
+ if(local_ip && local_ip[0])
+ memcpy(data->info.conn_local_ip, local_ip, MAX_IPADR_LEN);
+ else
+ data->info.conn_local_ip[0] = 0;
+ data->info.conn_scheme = conn->handler->scheme;
+ data->info.conn_protocol = conn->handler->protocol;
+ data->info.conn_primary_port = conn->port;
+ data->info.conn_local_port = local_port;
}
/* retrieves ip address and port from a sockaddr structure.
@@ -678,61 +683,86 @@ bool Curl_addr2string(struct sockaddr *sa, curl_socklen_t salen,
/* retrieves the start/end point information of a socket of an established
connection */
-void Curl_updateconninfo(struct connectdata *conn, curl_socket_t sockfd)
+void Curl_conninfo_remote(struct Curl_easy *data,
+ struct connectdata *conn, curl_socket_t sockfd)
{
- if(conn->transport == TRNSPRT_TCP) {
-#if defined(HAVE_GETPEERNAME) || defined(HAVE_GETSOCKNAME)
- if(!conn->bits.reuse && !conn->bits.tcp_fastopen) {
- struct Curl_easy *data = conn->data;
- char buffer[STRERROR_LEN];
- struct Curl_sockaddr_storage ssrem;
- struct Curl_sockaddr_storage ssloc;
- curl_socklen_t plen;
- curl_socklen_t slen;
#ifdef HAVE_GETPEERNAME
- plen = sizeof(struct Curl_sockaddr_storage);
- if(getpeername(sockfd, (struct sockaddr*) &ssrem, &plen)) {
- int error = SOCKERRNO;
- failf(data, "getpeername() failed with errno %d: %s",
- error, Curl_strerror(error, buffer, sizeof(buffer)));
- return;
- }
-#endif
-#ifdef HAVE_GETSOCKNAME
- slen = sizeof(struct Curl_sockaddr_storage);
- memset(&ssloc, 0, sizeof(ssloc));
- if(getsockname(sockfd, (struct sockaddr*) &ssloc, &slen)) {
- int error = SOCKERRNO;
- failf(data, "getsockname() failed with errno %d: %s",
- error, Curl_strerror(error, buffer, sizeof(buffer)));
- return;
- }
-#endif
-#ifdef HAVE_GETPEERNAME
- if(!Curl_addr2string((struct sockaddr*)&ssrem, plen,
- conn->primary_ip, &conn->primary_port)) {
- failf(data, "ssrem inet_ntop() failed with errno %d: %s",
- errno, Curl_strerror(errno, buffer, sizeof(buffer)));
- return;
- }
- memcpy(conn->ip_addr_str, conn->primary_ip, MAX_IPADR_LEN);
+ char buffer[STRERROR_LEN];
+ struct Curl_sockaddr_storage ssrem;
+ curl_socklen_t plen;
+ long port;
+ plen = sizeof(struct Curl_sockaddr_storage);
+ memset(&ssrem, 0, sizeof(ssrem));
+ if(getpeername(sockfd, (struct sockaddr*) &ssrem, &plen)) {
+ int error = SOCKERRNO;
+ failf(data, "getpeername() failed with errno %d: %s",
+ error, Curl_strerror(error, buffer, sizeof(buffer)));
+ return;
+ }
+ if(!Curl_addr2string((struct sockaddr*)&ssrem, plen,
+ conn->primary_ip, &port)) {
+ failf(data, "ssrem inet_ntop() failed with errno %d: %s",
+ errno, Curl_strerror(errno, buffer, sizeof(buffer)));
+ return;
+ }
+#else
+ (void)data;
+ (void)conn;
+ (void)sockfd;
#endif
+}
+
+/* retrieves the start/end point information of a socket of an established
+ connection */
+void Curl_conninfo_local(struct Curl_easy *data, curl_socket_t sockfd,
+ char *local_ip, long *local_port)
+{
#ifdef HAVE_GETSOCKNAME
- if(!Curl_addr2string((struct sockaddr*)&ssloc, slen,
- conn->local_ip, &conn->local_port)) {
- failf(data, "ssloc inet_ntop() failed with errno %d: %s",
- errno, Curl_strerror(errno, buffer, sizeof(buffer)));
- return;
- }
+ char buffer[STRERROR_LEN];
+ struct Curl_sockaddr_storage ssloc;
+ curl_socklen_t slen;
+ slen = sizeof(struct Curl_sockaddr_storage);
+ memset(&ssloc, 0, sizeof(ssloc));
+ if(getsockname(sockfd, (struct sockaddr*) &ssloc, &slen)) {
+ int error = SOCKERRNO;
+ failf(data, "getsockname() failed with errno %d: %s",
+ error, Curl_strerror(error, buffer, sizeof(buffer)));
+ return;
+ }
+ if(!Curl_addr2string((struct sockaddr*)&ssloc, slen,
+ local_ip, local_port)) {
+ failf(data, "ssloc inet_ntop() failed with errno %d: %s",
+ errno, Curl_strerror(errno, buffer, sizeof(buffer)));
+ return;
+ }
+#else
+ (void)data;
+ (void)sockfd;
+ (void)local_ip;
+ (void)local_port;
#endif
+}
+
+/* retrieves the start/end point information of a socket of an established
+ connection */
+void Curl_updateconninfo(struct Curl_easy *data, struct connectdata *conn,
+ curl_socket_t sockfd)
+{
+ /* 'local_ip' and 'local_port' get filled with local's numerical
+ ip address and port number whenever an outgoing connection is
+ **established** from the primary socket to a remote address. */
+ char local_ip[MAX_IPADR_LEN] = "";
+ long local_port = -1;
+
+ if(conn->transport == TRNSPRT_TCP) {
+ if(!conn->bits.reuse && !conn->bits.tcp_fastopen) {
+ Curl_conninfo_remote(data, conn, sockfd);
+ Curl_conninfo_local(data, sockfd, local_ip, &local_port);
}
-#else /* !HAVE_GETSOCKNAME && !HAVE_GETPEERNAME */
- (void)sockfd; /* unused */
-#endif
} /* end of TCP-only section */
/* persist connection info in session handle */
- Curl_persistconninfo(conn);
+ Curl_persistconninfo(data, conn, local_ip, local_port);
}
/* After a TCP connection to the proxy has been verified, this function does
@@ -742,12 +772,13 @@ void Curl_updateconninfo(struct connectdata *conn, curl_socket_t sockfd)
Note: this function's sub-functions call failf()
*/
-static CURLcode connect_SOCKS(struct connectdata *conn, int sockindex,
+static CURLcode connect_SOCKS(struct Curl_easy *data, int sockindex,
bool *done)
{
CURLcode result = CURLE_OK;
-
#ifndef CURL_DISABLE_PROXY
+ CURLproxycode pxresult = CURLPX_OK;
+ struct connectdata *conn = data->conn;
if(conn->bits.socksproxy) {
/* for the secondary socket (FTP), use the "connect to host"
* but ignore the "connect to port" (use the secondary port)
@@ -767,24 +798,28 @@ static CURLcode connect_SOCKS(struct connectdata *conn, int sockindex,
switch(conn->socks_proxy.proxytype) {
case CURLPROXY_SOCKS5:
case CURLPROXY_SOCKS5_HOSTNAME:
- result = Curl_SOCKS5(conn->socks_proxy.user, conn->socks_proxy.passwd,
- host, port, sockindex, conn, done);
+ pxresult = Curl_SOCKS5(conn->socks_proxy.user, conn->socks_proxy.passwd,
+ host, port, sockindex, data, done);
break;
case CURLPROXY_SOCKS4:
case CURLPROXY_SOCKS4A:
- result = Curl_SOCKS4(conn->socks_proxy.user, host, port, sockindex,
- conn, done);
+ pxresult = Curl_SOCKS4(conn->socks_proxy.user, host, port, sockindex,
+ data, done);
break;
default:
- failf(conn->data, "unknown proxytype option given");
+ failf(data, "unknown proxytype option given");
result = CURLE_COULDNT_CONNECT;
} /* switch proxytype */
+ if(pxresult) {
+ result = CURLE_PROXY;
+ data->info.pxcode = pxresult;
+ }
}
else
#else
- (void)conn;
+ (void)data;
(void)sockindex;
#endif /* CURL_DISABLE_PROXY */
*done = TRUE; /* no SOCKS proxy, so consider us connected */
@@ -796,7 +831,8 @@ static CURLcode connect_SOCKS(struct connectdata *conn, int sockindex,
* post_SOCKS() is called after a successful connect to the peer, which
* *could* be a SOCKS proxy
*/
-static void post_SOCKS(struct connectdata *conn,
+static void post_SOCKS(struct Curl_easy *data,
+ struct connectdata *conn,
int sockindex,
bool *connected)
{
@@ -804,21 +840,21 @@ static void post_SOCKS(struct connectdata *conn,
*connected = TRUE;
if(sockindex == FIRSTSOCKET)
- Curl_pgrsTime(conn->data, TIMER_CONNECT); /* connect done */
- Curl_updateconninfo(conn, conn->sock[sockindex]);
- Curl_verboseconnect(conn);
- conn->data->info.numconnects++; /* to track the number of connections made */
+ Curl_pgrsTime(data, TIMER_CONNECT); /* connect done */
+ Curl_updateconninfo(data, conn, conn->sock[sockindex]);
+ Curl_verboseconnect(data, conn);
+ data->info.numconnects++; /* to track the number of connections made */
}
/*
* Curl_is_connected() checks if the socket has connected.
*/
-CURLcode Curl_is_connected(struct connectdata *conn,
+CURLcode Curl_is_connected(struct Curl_easy *data,
+ struct connectdata *conn,
int sockindex,
bool *connected)
{
- struct Curl_easy *data = conn->data;
CURLcode result = CURLE_OK;
timediff_t allow;
int error = 0;
@@ -849,9 +885,9 @@ CURLcode Curl_is_connected(struct connectdata *conn,
if(SOCKS_STATE(conn->cnnct.state)) {
/* still doing SOCKS */
- result = connect_SOCKS(conn, sockindex, connected);
+ result = connect_SOCKS(data, sockindex, connected);
if(!result && *connected)
- post_SOCKS(conn, sockindex, connected);
+ post_SOCKS(data, conn, sockindex, connected);
return result;
}
@@ -862,13 +898,13 @@ CURLcode Curl_is_connected(struct connectdata *conn,
error = 0;
#ifdef ENABLE_QUIC
if(conn->transport == TRNSPRT_QUIC) {
- result = Curl_quic_is_connected(conn, i, connected);
+ result = Curl_quic_is_connected(data, conn, i, connected);
if(!result && *connected) {
/* use this socket from now on */
conn->sock[sockindex] = conn->tempsock[i];
conn->ip_addr = conn->tempaddr[i];
conn->tempsock[i] = CURL_SOCKET_BAD;
- post_SOCKS(conn, sockindex, connected);
+ post_SOCKS(data, conn, sockindex, connected);
connkeep(conn, "HTTP/3 default");
return CURLE_OK;
}
@@ -903,7 +939,7 @@ CURLcode Curl_is_connected(struct connectdata *conn,
(Curl_timediff(now, conn->connecttime) >=
data->set.happy_eyeballs_timeout)) {
conn->bits.parallel_connect = TRUE; /* starting now */
- trynextip(conn, sockindex, 1);
+ trynextip(data, conn, sockindex, 1);
}
}
else if(rc == CURL_CSELECT_OUT || conn->bits.tcp_fastopen) {
@@ -920,17 +956,17 @@ CURLcode Curl_is_connected(struct connectdata *conn,
/* close the other socket, if open */
if(conn->tempsock[other] != CURL_SOCKET_BAD) {
- Curl_closesocket(conn, conn->tempsock[other]);
+ Curl_closesocket(data, conn, conn->tempsock[other]);
conn->tempsock[other] = CURL_SOCKET_BAD;
}
/* see if we need to kick off any SOCKS proxy magic once we
connected */
- result = connect_SOCKS(conn, sockindex, connected);
+ result = connect_SOCKS(data, sockindex, connected);
if(result || !*connected)
return result;
- post_SOCKS(conn, sockindex, connected);
+ post_SOCKS(data, conn, sockindex, connected);
return CURLE_OK;
}
@@ -961,7 +997,7 @@ CURLcode Curl_is_connected(struct connectdata *conn,
conn->timeoutms_per_addr[i] = conn->tempaddr[i]->ai_next == NULL ?
allow : allow / 2;
ainext(conn, i, TRUE);
- status = trynextip(conn, sockindex, i);
+ status = trynextip(data, conn, sockindex, i);
if((status != CURLE_COULDNT_CONNECT) ||
conn->tempsock[other] == CURL_SOCKET_BAD)
/* the last attempt failed and no other sockets remain open */
@@ -979,7 +1015,7 @@ CURLcode Curl_is_connected(struct connectdata *conn,
/* if the first address family runs out of addresses to try before the
happy eyeball timeout, go ahead and try the next family now */
- result = trynextip(conn, sockindex, 1);
+ result = trynextip(data, conn, sockindex, 1);
if(!result)
return result;
@@ -999,8 +1035,8 @@ CURLcode Curl_is_connected(struct connectdata *conn,
hostname, conn->port,
Curl_strerror(error, buffer, sizeof(buffer)));
- Curl_quic_disconnect(conn, 0);
- Curl_quic_disconnect(conn, 1);
+ Curl_quic_disconnect(data, conn, 0);
+ Curl_quic_disconnect(data, conn, 1);
#ifdef WSAETIMEDOUT
if(WSAETIMEDOUT == data->state.os_errno)
@@ -1016,16 +1052,15 @@ CURLcode Curl_is_connected(struct connectdata *conn,
return result;
}
-static void tcpnodelay(struct connectdata *conn, curl_socket_t sockfd)
+static void tcpnodelay(struct Curl_easy *data, curl_socket_t sockfd)
{
#if defined(TCP_NODELAY)
curl_socklen_t onoff = (curl_socklen_t) 1;
int level = IPPROTO_TCP;
#if !defined(CURL_DISABLE_VERBOSE_STRINGS)
- struct Curl_easy *data = conn->data;
char buffer[STRERROR_LEN];
#else
- (void) conn;
+ (void) data;
#endif
if(setsockopt(sockfd, level, TCP_NODELAY, (void *)&onoff,
@@ -1033,7 +1068,7 @@ static void tcpnodelay(struct connectdata *conn, curl_socket_t sockfd)
infof(data, "Could not set TCP_NODELAY: %s\n",
Curl_strerror(SOCKERRNO, buffer, sizeof(buffer)));
#else
- (void)conn;
+ (void)data;
(void)sockfd;
#endif
}
@@ -1043,10 +1078,9 @@ static void tcpnodelay(struct connectdata *conn, curl_socket_t sockfd)
sending data to a dead peer (instead of relying on the 4th argument to send
being MSG_NOSIGNAL). Possibly also existing and in use on other BSD
systems? */
-static void nosigpipe(struct connectdata *conn,
+static void nosigpipe(struct Curl_easy *data,
curl_socket_t sockfd)
{
- struct Curl_easy *data = conn->data;
int onoff = 1;
if(setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, (void *)&onoff,
sizeof(onoff)) < 0) {
@@ -1112,7 +1146,8 @@ void Curl_sndbufset(curl_socket_t sockfd)
* singleipconnect() connects to the given IP only, and it may return without
* having connected.
*/
-static CURLcode singleipconnect(struct connectdata *conn,
+static CURLcode singleipconnect(struct Curl_easy *data,
+ struct connectdata *conn,
const struct Curl_addrinfo *ai,
int tempindex)
{
@@ -1120,7 +1155,6 @@ static CURLcode singleipconnect(struct connectdata *conn,
int rc = -1;
int error = 0;
bool isconnected = FALSE;
- struct Curl_easy *data = conn->data;
curl_socket_t sockfd;
CURLcode result;
char ipaddress[MAX_IPADR_LEN];
@@ -1133,7 +1167,7 @@ static CURLcode singleipconnect(struct connectdata *conn,
curl_socket_t *sockp = &conn->tempsock[tempindex];
*sockp = CURL_SOCKET_BAD;
- result = Curl_socket(conn, ai, &addr, &sockfd);
+ result = Curl_socket(data, ai, &addr, &sockfd);
if(result)
return result;
@@ -1143,7 +1177,7 @@ static CURLcode singleipconnect(struct connectdata *conn,
/* malformed address or bug in inet_ntop, try next address */
failf(data, "sa_addr inet_ntop() failed with errno %d: %s",
errno, Curl_strerror(errno, buffer, sizeof(buffer)));
- Curl_closesocket(conn, sockfd);
+ Curl_closesocket(data, conn, sockfd);
return CURLE_OK;
}
infof(data, " Trying %s:%ld...\n", ipaddress, port);
@@ -1155,9 +1189,9 @@ static CURLcode singleipconnect(struct connectdata *conn,
is_tcp = (addr.family == AF_INET) && addr.socktype == SOCK_STREAM;
#endif
if(is_tcp && data->set.tcp_nodelay)
- tcpnodelay(conn, sockfd);
+ tcpnodelay(data, sockfd);
- nosigpipe(conn, sockfd);
+ nosigpipe(data, sockfd);
Curl_sndbufset(sockfd);
@@ -1175,7 +1209,7 @@ static CURLcode singleipconnect(struct connectdata *conn,
if(error == CURL_SOCKOPT_ALREADY_CONNECTED)
isconnected = TRUE;
else if(error) {
- Curl_closesocket(conn, sockfd); /* close the socket and bail out */
+ Curl_closesocket(data, conn, sockfd); /* close the socket and bail out */
return CURLE_ABORTED_BY_CALLBACK;
}
}
@@ -1186,10 +1220,10 @@ static CURLcode singleipconnect(struct connectdata *conn,
|| addr.family == AF_INET6
#endif
) {
- result = bindlocal(conn, sockfd, addr.family,
+ result = bindlocal(data, sockfd, addr.family,
Curl_ipv6_scope((struct sockaddr*)&addr.sa_addr));
if(result) {
- Curl_closesocket(conn, sockfd); /* close socket and bail out */
+ Curl_closesocket(data, conn, sockfd); /* close socket and bail out */
if(result == CURLE_UNSUPPORTED_PROTOCOL) {
/* The address family is not supported on this interface.
We can continue trying addresses */
@@ -1257,7 +1291,7 @@ static CURLcode singleipconnect(struct connectdata *conn,
else if(conn->transport == TRNSPRT_QUIC) {
/* pass in 'sockfd' separately since it hasn't been put into the
tempsock array at this point */
- result = Curl_quic_connect(conn, sockfd, tempindex,
+ result = Curl_quic_connect(data, conn, sockfd, tempindex,
&addr.sa_addr, addr.addrlen);
if(result)
error = SOCKERRNO;
@@ -1292,7 +1326,7 @@ static CURLcode singleipconnect(struct connectdata *conn,
data->state.os_errno = error;
/* connect failed */
- Curl_closesocket(conn, sockfd);
+ Curl_closesocket(data, conn, sockfd);
result = CURLE_COULDNT_CONNECT;
}
}
@@ -1309,14 +1343,13 @@ static CURLcode singleipconnect(struct connectdata *conn,
* pointer with the connected socket.
*/
-CURLcode Curl_connecthost(struct connectdata *conn, /* context */
+CURLcode Curl_connecthost(struct Curl_easy *data,
+ struct connectdata *conn, /* context */
const struct Curl_dns_entry *remotehost)
{
- struct Curl_easy *data = conn->data;
- struct curltime before = Curl_now();
CURLcode result = CURLE_COULDNT_CONNECT;
int i;
- timediff_t timeout_ms = Curl_timeleft(data, &before, TRUE);
+ timediff_t timeout_ms = Curl_timeleft(data, NULL, TRUE);
if(timeout_ms < 0) {
/* a precaution, no need to continue if time already is up */
@@ -1336,8 +1369,12 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */
conn->tempfamily[0] = conn->tempaddr[0]?
conn->tempaddr[0]->ai_family:0;
+#ifdef ENABLE_IPV6
conn->tempfamily[1] = conn->tempfamily[0] == AF_INET6 ?
AF_INET : AF_INET6;
+#else
+ conn->tempfamily[1] = AF_UNSPEC;
+#endif
ainext(conn, 1, FALSE); /* assigns conn->tempaddr[1] accordingly */
DEBUGF(infof(data, "family0 == %s, family1 == %s\n",
@@ -1347,7 +1384,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */
/* get through the list in family order in case of quick failures */
for(i = 0; (i < 2) && result; i++) {
while(conn->tempaddr[i]) {
- result = singleipconnect(conn, conn->tempaddr[i], i);
+ result = singleipconnect(data, conn, conn->tempaddr[i], i);
if(!result)
break;
ainext(conn, i, TRUE);
@@ -1356,7 +1393,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */
if(result)
return result;
- Curl_expire(conn->data, data->set.happy_eyeballs_timeout,
+ Curl_expire(data, data->set.happy_eyeballs_timeout,
EXPIRE_HAPPY_EYEBALLS);
return CURLE_OK;
@@ -1367,9 +1404,11 @@ struct connfind {
struct connectdata *found;
};
-static int conn_is_conn(struct connectdata *conn, void *param)
+static int conn_is_conn(struct Curl_easy *data,
+ struct connectdata *conn, void *param)
{
struct connfind *f = (struct connfind *)param;
+ (void)data;
if(conn->connection_id == f->id_tofind) {
f->found = conn;
return 1;
@@ -1416,8 +1455,7 @@ curl_socket_t Curl_getconnectinfo(struct Curl_easy *data,
}
return c->sock[FIRSTSOCKET];
}
- else
- return CURL_SOCKET_BAD;
+ return CURL_SOCKET_BAD;
}
/*
@@ -1452,8 +1490,8 @@ bool Curl_connalive(struct connectdata *conn)
*
* 'conn' can be NULL, beware!
*/
-int Curl_closesocket(struct connectdata *conn,
- curl_socket_t sock)
+int Curl_closesocket(struct Curl_easy *data, struct connectdata *conn,
+ curl_socket_t sock)
{
if(conn && conn->fclosesocket) {
if((sock == conn->sock[SECONDARYSOCKET]) && conn->bits.sock_accepted)
@@ -1463,17 +1501,17 @@ int Curl_closesocket(struct connectdata *conn,
conn->bits.sock_accepted = FALSE;
else {
int rc;
- Curl_multi_closed(conn->data, sock);
- Curl_set_in_callback(conn->data, true);
+ Curl_multi_closed(data, sock);
+ Curl_set_in_callback(data, true);
rc = conn->fclosesocket(conn->closesocket_client, sock);
- Curl_set_in_callback(conn->data, false);
+ Curl_set_in_callback(data, false);
return rc;
}
}
if(conn)
/* tell the multi-socket code about this */
- Curl_multi_closed(conn->data, sock);
+ Curl_multi_closed(data, sock);
sclose(sock);
@@ -1489,12 +1527,12 @@ int Curl_closesocket(struct connectdata *conn,
* If the open socket callback is set, used that!
*
*/
-CURLcode Curl_socket(struct connectdata *conn,
+CURLcode Curl_socket(struct Curl_easy *data,
const struct Curl_addrinfo *ai,
struct Curl_sockaddr_ex *addr,
curl_socket_t *sockfd)
{
- struct Curl_easy *data = conn->data;
+ struct connectdata *conn = data->conn;
struct Curl_sockaddr_ex dummy;
if(!addr)
@@ -1555,8 +1593,21 @@ CURLcode Curl_socket(struct connectdata *conn,
}
#endif
- return CURLE_OK;
+#if defined(__linux__) && defined(IP_RECVERR)
+ if(addr->socktype == SOCK_DGRAM) {
+ int one = 1;
+ switch(addr->family) {
+ case AF_INET:
+ (void)setsockopt(*sockfd, SOL_IP, IP_RECVERR, &one, sizeof(one));
+ break;
+ case AF_INET6:
+ (void)setsockopt(*sockfd, SOL_IPV6, IPV6_RECVERR, &one, sizeof(one));
+ break;
+ }
+ }
+#endif
+ return CURLE_OK;
}
/*
@@ -1569,16 +1620,20 @@ void Curl_conncontrol(struct connectdata *conn,
#endif
)
{
- /* close if a connection, or a stream that isn't multiplexed */
- bool closeit = (ctrl == CONNCTRL_CONNECTION) ||
- ((ctrl == CONNCTRL_STREAM) && !(conn->handler->flags & PROTOPT_STREAM));
+ /* close if a connection, or a stream that isn't multiplexed. */
+ /* This function will be called both before and after this connection is
+ associated with a transfer. */
+ bool closeit;
DEBUGASSERT(conn);
+#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
+ (void)reason; /* useful for debugging */
+#endif
+ closeit = (ctrl == CONNCTRL_CONNECTION) ||
+ ((ctrl == CONNCTRL_STREAM) && !(conn->handler->flags & PROTOPT_STREAM));
if((ctrl == CONNCTRL_STREAM) &&
(conn->handler->flags & PROTOPT_STREAM))
- DEBUGF(infof(conn->data, "Kill stream: %s\n", reason));
+ ;
else if((bit)closeit != conn->bits.close) {
- DEBUGF(infof(conn->data, "Marked for [%s]: %s\n",
- closeit?"closure":"keep alive", reason));
conn->bits.close = closeit; /* the only place in the source code that
should assign this bit */
}
diff --git a/Utilities/cmcurl/lib/connect.h b/Utilities/cmcurl/lib/connect.h
index 6fd9ea878..566b3531d 100644
--- a/Utilities/cmcurl/lib/connect.h
+++ b/Utilities/cmcurl/lib/connect.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -27,11 +27,13 @@
#include "sockaddr.h"
#include "timeval.h"
-CURLcode Curl_is_connected(struct connectdata *conn,
+CURLcode Curl_is_connected(struct Curl_easy *data,
+ struct connectdata *conn,
int sockindex,
bool *connected);
-CURLcode Curl_connecthost(struct connectdata *conn,
+CURLcode Curl_connecthost(struct Curl_easy *data,
+ struct connectdata *conn,
const struct Curl_dns_entry *host);
/* generic function that returns how much time there's left to run, according
@@ -74,9 +76,16 @@ void Curl_sndbufset(curl_socket_t sockfd);
#define Curl_sndbufset(y) Curl_nop_stmt
#endif
-void Curl_updateconninfo(struct connectdata *conn, curl_socket_t sockfd);
-void Curl_persistconninfo(struct connectdata *conn);
-int Curl_closesocket(struct connectdata *conn, curl_socket_t sock);
+void Curl_updateconninfo(struct Curl_easy *data, struct connectdata *conn,
+ curl_socket_t sockfd);
+void Curl_conninfo_remote(struct Curl_easy *data, struct connectdata *conn,
+ curl_socket_t sockfd);
+void Curl_conninfo_local(struct Curl_easy *data, curl_socket_t sockfd,
+ char *local_ip, long *local_port);
+void Curl_persistconninfo(struct Curl_easy *data, struct connectdata *conn,
+ char *local_ip, long local_port);
+int Curl_closesocket(struct Curl_easy *data, struct connectdata *conn,
+ curl_socket_t sock);
/*
* The Curl_sockaddr_ex structure is basically libcurl's external API
@@ -104,7 +113,7 @@ struct Curl_sockaddr_ex {
* socket callback is set, used that!
*
*/
-CURLcode Curl_socket(struct connectdata *conn,
+CURLcode Curl_socket(struct Curl_easy *data,
const struct Curl_addrinfo *ai,
struct Curl_sockaddr_ex *addr,
curl_socket_t *sockfd);
diff --git a/Utilities/cmcurl/lib/content_encoding.c b/Utilities/cmcurl/lib/content_encoding.c
index 2fc3d43c4..f179b8179 100644
--- a/Utilities/cmcurl/lib/content_encoding.c
+++ b/Utilities/cmcurl/lib/content_encoding.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -28,10 +28,6 @@
#ifdef HAVE_ZLIB_H
#include <zlib.h>
-#ifdef __SYMBIAN32__
-/* zlib pollutes the namespace with this definition */
-#undef WIN32
-#endif
#endif
#ifdef HAVE_BROTLI
@@ -108,9 +104,8 @@ zfree_cb(voidpf opaque, voidpf ptr)
}
static CURLcode
-process_zlib_error(struct connectdata *conn, z_stream *z)
+process_zlib_error(struct Curl_easy *data, z_stream *z)
{
- struct Curl_easy *data = conn->data;
if(z->msg)
failf(data, "Error while processing content unencoding: %s",
z->msg);
@@ -122,7 +117,7 @@ process_zlib_error(struct connectdata *conn, z_stream *z)
}
static CURLcode
-exit_zlib(struct connectdata *conn,
+exit_zlib(struct Curl_easy *data,
z_stream *z, zlibInitState *zlib_init, CURLcode result)
{
if(*zlib_init == ZLIB_GZIP_HEADER)
@@ -130,14 +125,14 @@ exit_zlib(struct connectdata *conn,
if(*zlib_init != ZLIB_UNINIT) {
if(inflateEnd(z) != Z_OK && result == CURLE_OK)
- result = process_zlib_error(conn, z);
+ result = process_zlib_error(data, z);
*zlib_init = ZLIB_UNINIT;
}
return result;
}
-static CURLcode process_trailer(struct connectdata *conn,
+static CURLcode process_trailer(struct Curl_easy *data,
struct zlib_params *zp)
{
z_stream *z = &zp->z;
@@ -153,7 +148,7 @@ static CURLcode process_trailer(struct connectdata *conn,
if(z->avail_in)
result = CURLE_WRITE_ERROR;
if(result || !zp->trailerlen)
- result = exit_zlib(conn, z, &zp->zlib_init, result);
+ result = exit_zlib(data, z, &zp->zlib_init, result);
else {
/* Only occurs for gzip with zlib < 1.2.0.4 or raw deflate. */
zp->zlib_init = ZLIB_EXTERNAL_TRAILER;
@@ -161,7 +156,7 @@ static CURLcode process_trailer(struct connectdata *conn,
return result;
}
-static CURLcode inflate_stream(struct connectdata *conn,
+static CURLcode inflate_stream(struct Curl_easy *data,
struct contenc_writer *writer,
zlibInitState started)
{
@@ -178,13 +173,13 @@ static CURLcode inflate_stream(struct connectdata *conn,
zp->zlib_init != ZLIB_INFLATING &&
zp->zlib_init != ZLIB_INIT_GZIP &&
zp->zlib_init != ZLIB_GZIP_INFLATING)
- return exit_zlib(conn, z, &zp->zlib_init, CURLE_WRITE_ERROR);
+ return exit_zlib(data, z, &zp->zlib_init, CURLE_WRITE_ERROR);
/* Dynamically allocate a buffer for decompression because it's uncommonly
large to hold on the stack */
decomp = malloc(DSIZ);
if(decomp == NULL)
- return exit_zlib(conn, z, &zp->zlib_init, CURLE_OUT_OF_MEMORY);
+ return exit_zlib(data, z, &zp->zlib_init, CURLE_OUT_OF_MEMORY);
/* because the buffer size is fixed, iteratively decompress and transfer to
the client via downstream_write function. */
@@ -208,10 +203,10 @@ static CURLcode inflate_stream(struct connectdata *conn,
if(z->avail_out != DSIZ) {
if(status == Z_OK || status == Z_STREAM_END) {
zp->zlib_init = started; /* Data started. */
- result = Curl_unencode_write(conn, writer->downstream, decomp,
+ result = Curl_unencode_write(data, writer->downstream, decomp,
DSIZ - z->avail_out);
if(result) {
- exit_zlib(conn, z, &zp->zlib_init, result);
+ exit_zlib(data, z, &zp->zlib_init, result);
break;
}
}
@@ -227,7 +222,7 @@ static CURLcode inflate_stream(struct connectdata *conn,
/* No more data to flush: just exit loop. */
break;
case Z_STREAM_END:
- result = process_trailer(conn, zp);
+ result = process_trailer(data, zp);
break;
case Z_DATA_ERROR:
/* some servers seem to not generate zlib headers, so this is an attempt
@@ -247,7 +242,7 @@ static CURLcode inflate_stream(struct connectdata *conn,
}
/* FALLTHROUGH */
default:
- result = exit_zlib(conn, z, &zp->zlib_init, process_zlib_error(conn, z));
+ result = exit_zlib(data, z, &zp->zlib_init, process_zlib_error(data, z));
break;
}
}
@@ -264,7 +259,7 @@ static CURLcode inflate_stream(struct connectdata *conn,
/* Deflate handler. */
-static CURLcode deflate_init_writer(struct connectdata *conn,
+static CURLcode deflate_init_writer(struct Curl_easy *data,
struct contenc_writer *writer)
{
struct zlib_params *zp = (struct zlib_params *) &writer->params;
@@ -278,12 +273,12 @@ static CURLcode deflate_init_writer(struct connectdata *conn,
z->zfree = (free_func) zfree_cb;
if(inflateInit(z) != Z_OK)
- return process_zlib_error(conn, z);
+ return process_zlib_error(data, z);
zp->zlib_init = ZLIB_INIT;
return CURLE_OK;
}
-static CURLcode deflate_unencode_write(struct connectdata *conn,
+static CURLcode deflate_unencode_write(struct Curl_easy *data,
struct contenc_writer *writer,
const char *buf, size_t nbytes)
{
@@ -295,19 +290,19 @@ static CURLcode deflate_unencode_write(struct connectdata *conn,
z->avail_in = (uInt) nbytes;
if(zp->zlib_init == ZLIB_EXTERNAL_TRAILER)
- return process_trailer(conn, zp);
+ return process_trailer(data, zp);
/* Now uncompress the data */
- return inflate_stream(conn, writer, ZLIB_INFLATING);
+ return inflate_stream(data, writer, ZLIB_INFLATING);
}
-static void deflate_close_writer(struct connectdata *conn,
+static void deflate_close_writer(struct Curl_easy *data,
struct contenc_writer *writer)
{
struct zlib_params *zp = (struct zlib_params *) &writer->params;
z_stream *z = &zp->z; /* zlib state structure */
- exit_zlib(conn, z, &zp->zlib_init, CURLE_OK);
+ exit_zlib(data, z, &zp->zlib_init, CURLE_OK);
}
static const struct content_encoding deflate_encoding = {
@@ -321,7 +316,7 @@ static const struct content_encoding deflate_encoding = {
/* Gzip handler. */
-static CURLcode gzip_init_writer(struct connectdata *conn,
+static CURLcode gzip_init_writer(struct Curl_easy *data,
struct contenc_writer *writer)
{
struct zlib_params *zp = (struct zlib_params *) &writer->params;
@@ -337,14 +332,14 @@ static CURLcode gzip_init_writer(struct connectdata *conn,
if(strcmp(zlibVersion(), "1.2.0.4") >= 0) {
/* zlib ver. >= 1.2.0.4 supports transparent gzip decompressing */
if(inflateInit2(z, MAX_WBITS + 32) != Z_OK) {
- return process_zlib_error(conn, z);
+ return process_zlib_error(data, z);
}
zp->zlib_init = ZLIB_INIT_GZIP; /* Transparent gzip decompress state */
}
else {
/* we must parse the gzip header and trailer ourselves */
if(inflateInit2(z, -MAX_WBITS) != Z_OK) {
- return process_zlib_error(conn, z);
+ return process_zlib_error(data, z);
}
zp->trailerlen = 8; /* A CRC-32 and a 32-bit input size (RFC 1952, 2.2) */
zp->zlib_init = ZLIB_INIT; /* Initial call state */
@@ -437,7 +432,7 @@ static enum {
}
#endif
-static CURLcode gzip_unencode_write(struct connectdata *conn,
+static CURLcode gzip_unencode_write(struct Curl_easy *data,
struct contenc_writer *writer,
const char *buf, size_t nbytes)
{
@@ -449,13 +444,13 @@ static CURLcode gzip_unencode_write(struct connectdata *conn,
z->next_in = (Bytef *) buf;
z->avail_in = (uInt) nbytes;
/* Now uncompress the data */
- return inflate_stream(conn, writer, ZLIB_INIT_GZIP);
+ return inflate_stream(data, writer, ZLIB_INIT_GZIP);
}
#ifndef OLD_ZLIB_SUPPORT
/* Support for old zlib versions is compiled away and we are running with
an old version, so return an error. */
- return exit_zlib(conn, z, &zp->zlib_init, CURLE_WRITE_ERROR);
+ return exit_zlib(data, z, &zp->zlib_init, CURLE_WRITE_ERROR);
#else
/* This next mess is to get around the potential case where there isn't
@@ -493,7 +488,7 @@ static CURLcode gzip_unencode_write(struct connectdata *conn,
z->avail_in = (uInt) nbytes;
z->next_in = malloc(z->avail_in);
if(z->next_in == NULL) {
- return exit_zlib(conn, z, &zp->zlib_init, CURLE_OUT_OF_MEMORY);
+ return exit_zlib(data, z, &zp->zlib_init, CURLE_OUT_OF_MEMORY);
}
memcpy(z->next_in, buf, z->avail_in);
zp->zlib_init = ZLIB_GZIP_HEADER; /* Need more gzip header data state */
@@ -502,7 +497,7 @@ static CURLcode gzip_unencode_write(struct connectdata *conn,
case GZIP_BAD:
default:
- return exit_zlib(conn, z, &zp->zlib_init, process_zlib_error(conn, z));
+ return exit_zlib(data, z, &zp->zlib_init, process_zlib_error(data, z));
}
}
@@ -515,7 +510,7 @@ static CURLcode gzip_unencode_write(struct connectdata *conn,
z->avail_in += (uInt) nbytes;
z->next_in = Curl_saferealloc(z->next_in, z->avail_in);
if(z->next_in == NULL) {
- return exit_zlib(conn, z, &zp->zlib_init, CURLE_OUT_OF_MEMORY);
+ return exit_zlib(data, z, &zp->zlib_init, CURLE_OUT_OF_MEMORY);
}
/* Append the new block of data to the previous one */
memcpy(z->next_in + z->avail_in - nbytes, buf, nbytes);
@@ -536,7 +531,7 @@ static CURLcode gzip_unencode_write(struct connectdata *conn,
case GZIP_BAD:
default:
- return exit_zlib(conn, z, &zp->zlib_init, process_zlib_error(conn, z));
+ return exit_zlib(data, z, &zp->zlib_init, process_zlib_error(data, z));
}
}
@@ -545,7 +540,7 @@ static CURLcode gzip_unencode_write(struct connectdata *conn,
case ZLIB_EXTERNAL_TRAILER:
z->next_in = (Bytef *) buf;
z->avail_in = (uInt) nbytes;
- return process_trailer(conn, zp);
+ return process_trailer(data, zp);
case ZLIB_GZIP_INFLATING:
default:
@@ -561,17 +556,17 @@ static CURLcode gzip_unencode_write(struct connectdata *conn,
}
/* We've parsed the header, now uncompress the data */
- return inflate_stream(conn, writer, ZLIB_GZIP_INFLATING);
+ return inflate_stream(data, writer, ZLIB_GZIP_INFLATING);
#endif
}
-static void gzip_close_writer(struct connectdata *conn,
+static void gzip_close_writer(struct Curl_easy *data,
struct contenc_writer *writer)
{
struct zlib_params *zp = (struct zlib_params *) &writer->params;
z_stream *z = &zp->z; /* zlib state structure */
- exit_zlib(conn, z, &zp->zlib_init, CURLE_OK);
+ exit_zlib(data, z, &zp->zlib_init, CURLE_OK);
}
static const struct content_encoding gzip_encoding = {
@@ -630,11 +625,11 @@ static CURLcode brotli_map_error(BrotliDecoderErrorCode be)
return CURLE_WRITE_ERROR;
}
-static CURLcode brotli_init_writer(struct connectdata *conn,
+static CURLcode brotli_init_writer(struct Curl_easy *data,
struct contenc_writer *writer)
{
struct brotli_params *bp = (struct brotli_params *) &writer->params;
- (void) conn;
+ (void) data;
if(!writer->downstream)
return CURLE_WRITE_ERROR;
@@ -643,7 +638,7 @@ static CURLcode brotli_init_writer(struct connectdata *conn,
return bp->br? CURLE_OK: CURLE_OUT_OF_MEMORY;
}
-static CURLcode brotli_unencode_write(struct connectdata *conn,
+static CURLcode brotli_unencode_write(struct Curl_easy *data,
struct contenc_writer *writer,
const char *buf, size_t nbytes)
{
@@ -668,7 +663,7 @@ static CURLcode brotli_unencode_write(struct connectdata *conn,
dstleft = DSIZ;
r = BrotliDecoderDecompressStream(bp->br,
&nbytes, &src, &dstleft, &dst, NULL);
- result = Curl_unencode_write(conn, writer->downstream,
+ result = Curl_unencode_write(data, writer->downstream,
decomp, DSIZ - dstleft);
if(result)
break;
@@ -691,11 +686,11 @@ static CURLcode brotli_unencode_write(struct connectdata *conn,
return result;
}
-static void brotli_close_writer(struct connectdata *conn,
+static void brotli_close_writer(struct Curl_easy *data,
struct contenc_writer *writer)
{
struct brotli_params *bp = (struct brotli_params *) &writer->params;
- (void) conn;
+ (void) data;
if(bp->br) {
BrotliDecoderDestroyInstance(bp->br);
@@ -721,11 +716,11 @@ struct zstd_params {
void *decomp;
};
-static CURLcode zstd_init_writer(struct connectdata *conn,
+static CURLcode zstd_init_writer(struct Curl_easy *data,
struct contenc_writer *writer)
{
struct zstd_params *zp = (struct zstd_params *)&writer->params;
- (void)conn;
+ (void)data;
if(!writer->downstream)
return CURLE_WRITE_ERROR;
@@ -735,9 +730,9 @@ static CURLcode zstd_init_writer(struct connectdata *conn,
return zp->zds ? CURLE_OK : CURLE_OUT_OF_MEMORY;
}
-static CURLcode zstd_unencode_write(struct connectdata *conn,
- struct contenc_writer *writer,
- const char *buf, size_t nbytes)
+static CURLcode zstd_unencode_write(struct Curl_easy *data,
+ struct contenc_writer *writer,
+ const char *buf, size_t nbytes)
{
CURLcode result = CURLE_OK;
struct zstd_params *zp = (struct zstd_params *)&writer->params;
@@ -764,7 +759,7 @@ static CURLcode zstd_unencode_write(struct connectdata *conn,
return CURLE_BAD_CONTENT_ENCODING;
}
if(out.pos > 0) {
- result = Curl_unencode_write(conn, writer->downstream,
+ result = Curl_unencode_write(data, writer->downstream,
zp->decomp, out.pos);
if(result)
break;
@@ -776,11 +771,11 @@ static CURLcode zstd_unencode_write(struct connectdata *conn,
return result;
}
-static void zstd_close_writer(struct connectdata *conn,
- struct contenc_writer *writer)
+static void zstd_close_writer(struct Curl_easy *data,
+ struct contenc_writer *writer)
{
struct zstd_params *zp = (struct zstd_params *)&writer->params;
- (void)conn;
+ (void)data;
if(zp->decomp) {
free(zp->decomp);
@@ -804,24 +799,24 @@ static const struct content_encoding zstd_encoding = {
/* Identity handler. */
-static CURLcode identity_init_writer(struct connectdata *conn,
+static CURLcode identity_init_writer(struct Curl_easy *data,
struct contenc_writer *writer)
{
- (void) conn;
+ (void) data;
return writer->downstream? CURLE_OK: CURLE_WRITE_ERROR;
}
-static CURLcode identity_unencode_write(struct connectdata *conn,
+static CURLcode identity_unencode_write(struct Curl_easy *data,
struct contenc_writer *writer,
const char *buf, size_t nbytes)
{
- return Curl_unencode_write(conn, writer->downstream, buf, nbytes);
+ return Curl_unencode_write(data, writer->downstream, buf, nbytes);
}
-static void identity_close_writer(struct connectdata *conn,
+static void identity_close_writer(struct Curl_easy *data,
struct contenc_writer *writer)
{
- (void) conn;
+ (void) data;
(void) writer;
}
@@ -889,18 +884,17 @@ char *Curl_all_content_encodings(void)
/* Real client writer: no downstream. */
-static CURLcode client_init_writer(struct connectdata *conn,
+static CURLcode client_init_writer(struct Curl_easy *data,
struct contenc_writer *writer)
{
- (void) conn;
+ (void) data;
return writer->downstream? CURLE_WRITE_ERROR: CURLE_OK;
}
-static CURLcode client_unencode_write(struct connectdata *conn,
+static CURLcode client_unencode_write(struct Curl_easy *data,
struct contenc_writer *writer,
const char *buf, size_t nbytes)
{
- struct Curl_easy *data = conn->data;
struct SingleRequest *k = &data->req;
(void) writer;
@@ -908,13 +902,13 @@ static CURLcode client_unencode_write(struct connectdata *conn,
if(!nbytes || k->ignorebody)
return CURLE_OK;
- return Curl_client_write(conn, CLIENTWRITE_BODY, (char *) buf, nbytes);
+ return Curl_client_write(data, CLIENTWRITE_BODY, (char *) buf, nbytes);
}
-static void client_close_writer(struct connectdata *conn,
+static void client_close_writer(struct Curl_easy *data,
struct contenc_writer *writer)
{
- (void) conn;
+ (void) data;
(void) writer;
}
@@ -929,14 +923,14 @@ static const struct content_encoding client_encoding = {
/* Deferred error dummy writer. */
-static CURLcode error_init_writer(struct connectdata *conn,
+static CURLcode error_init_writer(struct Curl_easy *data,
struct contenc_writer *writer)
{
- (void) conn;
+ (void) data;
return writer->downstream? CURLE_OK: CURLE_WRITE_ERROR;
}
-static CURLcode error_unencode_write(struct connectdata *conn,
+static CURLcode error_unencode_write(struct Curl_easy *data,
struct contenc_writer *writer,
const char *buf, size_t nbytes)
{
@@ -948,16 +942,16 @@ static CURLcode error_unencode_write(struct connectdata *conn,
if(!all)
return CURLE_OUT_OF_MEMORY;
- failf(conn->data, "Unrecognized content encoding type. "
- "libcurl understands %s content encodings.", all);
+ failf(data, "Unrecognized content encoding type. "
+ "libcurl understands %s content encodings.", all);
free(all);
return CURLE_BAD_CONTENT_ENCODING;
}
-static void error_close_writer(struct connectdata *conn,
+static void error_close_writer(struct Curl_easy *data,
struct contenc_writer *writer)
{
- (void) conn;
+ (void) data;
(void) writer;
}
@@ -972,7 +966,7 @@ static const struct content_encoding error_encoding = {
/* Create an unencoding writer stage using the given handler. */
static struct contenc_writer *
-new_unencoding_writer(struct connectdata *conn,
+new_unencoding_writer(struct Curl_easy *data,
const struct content_encoding *handler,
struct contenc_writer *downstream)
{
@@ -982,7 +976,7 @@ new_unencoding_writer(struct connectdata *conn,
if(writer) {
writer->handler = handler;
writer->downstream = downstream;
- if(handler->init_writer(conn, writer)) {
+ if(handler->init_writer(data, writer)) {
free(writer);
writer = NULL;
}
@@ -992,25 +986,24 @@ new_unencoding_writer(struct connectdata *conn,
}
/* Write data using an unencoding writer stack. */
-CURLcode Curl_unencode_write(struct connectdata *conn,
+CURLcode Curl_unencode_write(struct Curl_easy *data,
struct contenc_writer *writer,
const char *buf, size_t nbytes)
{
if(!nbytes)
return CURLE_OK;
- return writer->handler->unencode_write(conn, writer, buf, nbytes);
+ return writer->handler->unencode_write(data, writer, buf, nbytes);
}
/* Close and clean-up the connection's writer stack. */
-void Curl_unencode_cleanup(struct connectdata *conn)
+void Curl_unencode_cleanup(struct Curl_easy *data)
{
- struct Curl_easy *data = conn->data;
struct SingleRequest *k = &data->req;
struct contenc_writer *writer = k->writer_stack;
while(writer) {
k->writer_stack = writer->downstream;
- writer->handler->close_writer(conn, writer);
+ writer->handler->close_writer(data, writer);
free(writer);
writer = k->writer_stack;
}
@@ -1033,10 +1026,9 @@ static const struct content_encoding *find_encoding(const char *name,
/* Set-up the unencoding stack from the Content-Encoding header value.
* See RFC 7231 section 3.1.2.2. */
-CURLcode Curl_build_unencoding_stack(struct connectdata *conn,
+CURLcode Curl_build_unencoding_stack(struct Curl_easy *data,
const char *enclist, int maybechunked)
{
- struct Curl_easy *data = conn->data;
struct SingleRequest *k = &data->req;
do {
@@ -1056,14 +1048,14 @@ CURLcode Curl_build_unencoding_stack(struct connectdata *conn,
/* Special case: chunked encoding is handled at the reader level. */
if(maybechunked && namelen == 7 && strncasecompare(name, "chunked", 7)) {
k->chunk = TRUE; /* chunks coming our way. */
- Curl_httpchunk_init(conn); /* init our chunky engine. */
+ Curl_httpchunk_init(data); /* init our chunky engine. */
}
else if(namelen) {
const struct content_encoding *encoding = find_encoding(name, namelen);
struct contenc_writer *writer;
if(!k->writer_stack) {
- k->writer_stack = new_unencoding_writer(conn, &client_encoding, NULL);
+ k->writer_stack = new_unencoding_writer(data, &client_encoding, NULL);
if(!k->writer_stack)
return CURLE_OUT_OF_MEMORY;
@@ -1073,7 +1065,7 @@ CURLcode Curl_build_unencoding_stack(struct connectdata *conn,
encoding = &error_encoding; /* Defer error at stack use. */
/* Stack the unencoding stage. */
- writer = new_unencoding_writer(conn, encoding, k->writer_stack);
+ writer = new_unencoding_writer(data, encoding, k->writer_stack);
if(!writer)
return CURLE_OUT_OF_MEMORY;
k->writer_stack = writer;
@@ -1085,29 +1077,29 @@ CURLcode Curl_build_unencoding_stack(struct connectdata *conn,
#else
/* Stubs for builds without HTTP. */
-CURLcode Curl_build_unencoding_stack(struct connectdata *conn,
+CURLcode Curl_build_unencoding_stack(struct Curl_easy *data,
const char *enclist, int maybechunked)
{
- (void) conn;
+ (void) data;
(void) enclist;
(void) maybechunked;
return CURLE_NOT_BUILT_IN;
}
-CURLcode Curl_unencode_write(struct connectdata *conn,
+CURLcode Curl_unencode_write(struct Curl_easy *data,
struct contenc_writer *writer,
const char *buf, size_t nbytes)
{
- (void) conn;
+ (void) data;
(void) writer;
(void) buf;
(void) nbytes;
return CURLE_NOT_BUILT_IN;
}
-void Curl_unencode_cleanup(struct connectdata *conn)
+void Curl_unencode_cleanup(struct Curl_easy *data)
{
- (void) conn;
+ (void) data;
}
char *Curl_all_content_encodings(void)
diff --git a/Utilities/cmcurl/lib/content_encoding.h b/Utilities/cmcurl/lib/content_encoding.h
index bdd3f1c8c..acfd0c27b 100644
--- a/Utilities/cmcurl/lib/content_encoding.h
+++ b/Utilities/cmcurl/lib/content_encoding.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -33,23 +33,23 @@ struct contenc_writer {
struct content_encoding {
const char *name; /* Encoding name. */
const char *alias; /* Encoding name alias. */
- CURLcode (*init_writer)(struct connectdata *conn,
+ CURLcode (*init_writer)(struct Curl_easy *data,
struct contenc_writer *writer);
- CURLcode (*unencode_write)(struct connectdata *conn,
+ CURLcode (*unencode_write)(struct Curl_easy *data,
struct contenc_writer *writer,
const char *buf, size_t nbytes);
- void (*close_writer)(struct connectdata *conn,
+ void (*close_writer)(struct Curl_easy *data,
struct contenc_writer *writer);
size_t paramsize;
};
-CURLcode Curl_build_unencoding_stack(struct connectdata *conn,
+CURLcode Curl_build_unencoding_stack(struct Curl_easy *data,
const char *enclist, int maybechunked);
-CURLcode Curl_unencode_write(struct connectdata *conn,
+CURLcode Curl_unencode_write(struct Curl_easy *data,
struct contenc_writer *writer,
const char *buf, size_t nbytes);
-void Curl_unencode_cleanup(struct connectdata *conn);
+void Curl_unencode_cleanup(struct Curl_easy *data);
char *Curl_all_content_encodings(void);
#endif /* HEADER_CURL_CONTENT_ENCODING_H */
diff --git a/Utilities/cmcurl/lib/cookie.c b/Utilities/cmcurl/lib/cookie.c
index cb7d94b10..09fd092ac 100644
--- a/Utilities/cmcurl/lib/cookie.c
+++ b/Utilities/cmcurl/lib/cookie.c
@@ -9,7 +9,7 @@
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -264,6 +264,11 @@ static const char *get_top_domain(const char * const domain, size_t *outlen)
return first? first: domain;
}
+/* Avoid C1001, an "internal error" with MSVC14 */
+#if defined(_MSC_VER) && (_MSC_VER == 1900)
+#pragma optimize("", off)
+#endif
+
/*
* A case-insensitive hash for the cookie domains.
*/
@@ -280,6 +285,10 @@ static size_t cookie_hash_domain(const char *domain, const size_t len)
return (h % COOKIE_HASH_SIZE);
}
+#if defined(_MSC_VER) && (_MSC_VER == 1900)
+#pragma optimize("", on)
+#endif
+
/*
* Hash this domain.
*/
@@ -1539,7 +1548,7 @@ static int cookie_output(struct Curl_easy *data,
}
fputs("# Netscape HTTP Cookie File\n"
- "# https://curl.haxx.se/docs/http-cookies.html\n"
+ "# https://curl.se/docs/http-cookies.html\n"
"# This file was generated by libcurl! Edit at your own risk.\n\n",
out);
diff --git a/Utilities/cmcurl/lib/cookie.h b/Utilities/cmcurl/lib/cookie.h
index b3865e601..e0aa383be 100644
--- a/Utilities/cmcurl/lib/cookie.h
+++ b/Utilities/cmcurl/lib/cookie.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -34,12 +34,12 @@ struct Cookie {
char *domain; /* domain = <this> */
curl_off_t expires; /* expires = <this> */
char *expirestr; /* the plain text version */
- bool tailmatch; /* whether we do tail-matching of the domain name */
/* RFC 2109 keywords. Version=1 means 2109-compliant cookie sending */
char *version; /* Version = <value> */
char *maxage; /* Max-Age = <value> */
+ bool tailmatch; /* whether we do tail-matching of the domain name */
bool secure; /* whether the 'secure' keyword was used */
bool livecookie; /* updated from a server, not a stored file */
bool httponly; /* true if the httponly directive is present */
@@ -61,8 +61,8 @@ struct CookieInfo {
struct Cookie *cookies[COOKIE_HASH_SIZE];
char *filename; /* file we read from/write to */
- bool running; /* state info, for cookie adding information */
long numcookies; /* number of cookies in the "jar" */
+ bool running; /* state info, for cookie adding information */
bool newsession; /* new session, discard session cookies on load */
int lastct; /* last creation-time used in the jar */
};
diff --git a/Utilities/cmcurl/lib/curl_addrinfo.c b/Utilities/cmcurl/lib/curl_addrinfo.c
index 947d0d375..06537b275 100644
--- a/Utilities/cmcurl/lib/curl_addrinfo.c
+++ b/Utilities/cmcurl/lib/curl_addrinfo.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -285,7 +285,7 @@ Curl_he2ai(const struct hostent *he, int port)
#endif
ss_size = sizeof(struct sockaddr_in);
- /* allocate memory to told the struct, the address and the name */
+ /* allocate memory to hold the struct, the address and the name */
ai = calloc(1, sizeof(struct Curl_addrinfo) + ss_size + namelen);
if(!ai) {
result = CURLE_OUT_OF_MEMORY;
diff --git a/Utilities/cmcurl/lib/curl_addrinfo.h b/Utilities/cmcurl/lib/curl_addrinfo.h
index a0cade614..73a8c1b33 100644
--- a/Utilities/cmcurl/lib/curl_addrinfo.h
+++ b/Utilities/cmcurl/lib/curl_addrinfo.h
@@ -11,7 +11,7 @@
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/curl_base64.h b/Utilities/cmcurl/lib/curl_base64.h
index cfb6ee75b..d48edc424 100644
--- a/Utilities/cmcurl/lib/curl_base64.h
+++ b/Utilities/cmcurl/lib/curl_base64.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
diff --git a/Utilities/cmcurl/lib/curl_config.h.cmake b/Utilities/cmcurl/lib/curl_config.h.cmake
index d5bf4feff..8dfe3285c 100644
--- a/Utilities/cmcurl/lib/curl_config.h.cmake
+++ b/Utilities/cmcurl/lib/curl_config.h.cmake
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -56,8 +56,8 @@
/* to disable LDAPS */
#cmakedefine CURL_DISABLE_LDAPS 1
-/* to enable MQTT */
-#undef CURL_ENABLE_MQTT
+/* to disable MQTT */
+#cmakedefine CURL_DISABLE_MQTT 1
/* to disable POP3 */
#cmakedefine CURL_DISABLE_POP3 1
@@ -388,8 +388,11 @@
/* Define to 1 if you have the <libgen.h> header file. */
#cmakedefine HAVE_LIBGEN_H 1
-/* Define to 1 if you have the `idn' library (-lidn). */
-#cmakedefine HAVE_LIBIDN 1
+/* Define to 1 if you have the `idn2' library (-lidn2). */
+#cmakedefine HAVE_LIBIDN2 1
+
+/* Define to 1 if you have the idn2.h header file. */
+#cmakedefine HAVE_IDN2_H 1
/* Define to 1 if you have the `resolv' library (-lresolv). */
#cmakedefine HAVE_LIBRESOLV 1
@@ -462,6 +465,9 @@
/* Define to 1 if you have the <netinet/tcp.h> header file. */
#cmakedefine HAVE_NETINET_TCP_H 1
+/* Define to 1 if you have the <linux/tcp.h> header file. */
+#cmakedefine HAVE_LINUX_TCP_H 1
+
/* Define to 1 if you have the <net/if.h> header file. */
#cmakedefine HAVE_NET_IF_H 1
@@ -999,6 +1005,10 @@ ${SIZEOF_TIME_T_CODE}
/* if OpenSSL is in use */
#cmakedefine USE_OPENSSL 1
+/* Define to 1 if you don't want the OpenSSL configuration to be loaded
+ automatically */
+#cmakedefine CURL_DISABLE_OPENSSL_AUTO_LOAD_CONFIG 1
+
/* to enable NGHTTP2 */
#cmakedefine USE_NGHTTP2 1
@@ -1017,8 +1027,8 @@ ${SIZEOF_TIME_T_CODE}
/* if Unix domain sockets are enabled */
#cmakedefine USE_UNIX_SOCKETS
-/* to enable alt-svc */
-#cmakedefine USE_ALTSVC 1
+/* to disable alt-svc */
+#cmakedefine CURL_DISABLE_ALTSVC 1
/* to enable SSPI support */
#cmakedefine USE_WINDOWS_SSPI 1
diff --git a/Utilities/cmcurl/lib/curl_ctype.c b/Utilities/cmcurl/lib/curl_ctype.c
index 1a47fb5e6..d6cd08a07 100644
--- a/Utilities/cmcurl/lib/curl_ctype.c
+++ b/Utilities/cmcurl/lib/curl_ctype.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
diff --git a/Utilities/cmcurl/lib/curl_ctype.h b/Utilities/cmcurl/lib/curl_ctype.h
index 6e94bb1b4..17dfaa094 100644
--- a/Utilities/cmcurl/lib/curl_ctype.h
+++ b/Utilities/cmcurl/lib/curl_ctype.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
diff --git a/Utilities/cmcurl/lib/curl_des.c b/Utilities/cmcurl/lib/curl_des.c
index 39c0f35ee..8c5af19cd 100644
--- a/Utilities/cmcurl/lib/curl_des.c
+++ b/Utilities/cmcurl/lib/curl_des.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2015 - 2019, Steve Holme, <steve_holme@hotmail.com>.
+ * Copyright (C) 2015 - 2020, Steve Holme, <steve_holme@hotmail.com>.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/curl_des.h b/Utilities/cmcurl/lib/curl_des.h
index a42eeb53f..438706a0d 100644
--- a/Utilities/cmcurl/lib/curl_des.h
+++ b/Utilities/cmcurl/lib/curl_des.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2015 - 2019, Steve Holme, <steve_holme@hotmail.com>.
+ * Copyright (C) 2015 - 2020, Steve Holme, <steve_holme@hotmail.com>.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/curl_endian.c b/Utilities/cmcurl/lib/curl_endian.c
index a774d136e..2fc25bc17 100644
--- a/Utilities/cmcurl/lib/curl_endian.c
+++ b/Utilities/cmcurl/lib/curl_endian.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
diff --git a/Utilities/cmcurl/lib/curl_endian.h b/Utilities/cmcurl/lib/curl_endian.h
index 9830e58fd..341dfaf3c 100644
--- a/Utilities/cmcurl/lib/curl_endian.h
+++ b/Utilities/cmcurl/lib/curl_endian.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
diff --git a/Utilities/cmcurl/lib/curl_fnmatch.c b/Utilities/cmcurl/lib/curl_fnmatch.c
index ab3e7428d..4bfa58598 100644
--- a/Utilities/cmcurl/lib/curl_fnmatch.c
+++ b/Utilities/cmcurl/lib/curl_fnmatch.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
diff --git a/Utilities/cmcurl/lib/curl_fnmatch.h b/Utilities/cmcurl/lib/curl_fnmatch.h
index 34fccae48..1c80ea779 100644
--- a/Utilities/cmcurl/lib/curl_fnmatch.h
+++ b/Utilities/cmcurl/lib/curl_fnmatch.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
diff --git a/Utilities/cmcurl/lib/curl_get_line.c b/Utilities/cmcurl/lib/curl_get_line.c
index c4194851a..438ede704 100644
--- a/Utilities/cmcurl/lib/curl_get_line.c
+++ b/Utilities/cmcurl/lib/curl_get_line.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
@@ -22,6 +22,9 @@
#include "curl_setup.h"
+#if !defined(CURL_DISABLE_COOKIES) || !defined(CURL_DISABLE_ALTSVC) || \
+ defined(USE_HSTS)
+
#include "curl_get_line.h"
#include "curl_memory.h"
/* The last #include file should be: */
@@ -53,3 +56,5 @@ char *Curl_get_line(char *buf, int len, FILE *input)
}
return NULL;
}
+
+#endif /* if not disabled */
diff --git a/Utilities/cmcurl/lib/curl_get_line.h b/Utilities/cmcurl/lib/curl_get_line.h
index 532ab080a..597aa09a9 100644
--- a/Utilities/cmcurl/lib/curl_get_line.h
+++ b/Utilities/cmcurl/lib/curl_get_line.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
diff --git a/Utilities/cmcurl/lib/curl_gethostname.c b/Utilities/cmcurl/lib/curl_gethostname.c
index 8337c72e8..2d5ff61cf 100644
--- a/Utilities/cmcurl/lib/curl_gethostname.c
+++ b/Utilities/cmcurl/lib/curl_gethostname.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
@@ -48,7 +48,7 @@
* For libcurl static library release builds no overriding takes place.
*/
-int Curl_gethostname(char *name, GETHOSTNAME_TYPE_ARG2 namelen)
+int Curl_gethostname(char * const name, GETHOSTNAME_TYPE_ARG2 namelen)
{
#ifndef HAVE_GETHOSTNAME
diff --git a/Utilities/cmcurl/lib/curl_gethostname.h b/Utilities/cmcurl/lib/curl_gethostname.h
index 8ae15e6c1..2161c40ac 100644
--- a/Utilities/cmcurl/lib/curl_gethostname.h
+++ b/Utilities/cmcurl/lib/curl_gethostname.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
@@ -26,6 +26,6 @@
#define HOSTNAME_MAX 1024
/* This returns the local machine's un-qualified hostname */
-int Curl_gethostname(char *name, GETHOSTNAME_TYPE_ARG2 namelen);
+int Curl_gethostname(char * const name, GETHOSTNAME_TYPE_ARG2 namelen);
#endif /* HEADER_CURL_GETHOSTNAME_H */
diff --git a/Utilities/cmcurl/lib/curl_gssapi.c b/Utilities/cmcurl/lib/curl_gssapi.c
index d854ab0c7..6445fbad0 100644
--- a/Utilities/cmcurl/lib/curl_gssapi.c
+++ b/Utilities/cmcurl/lib/curl_gssapi.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2011 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2011 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -131,6 +131,10 @@ void Curl_gss_log_error(struct Curl_easy *data, const char *prefix,
display_gss_error(minor, GSS_C_MECH_CODE, buf, len);
infof(data, "%s%s\n", prefix, buf);
+#ifdef CURL_DISABLE_VERBOSE_STRINGS
+ (void)data;
+ (void)prefix;
+#endif
}
#endif /* HAVE_GSSAPI */
diff --git a/Utilities/cmcurl/lib/curl_gssapi.h b/Utilities/cmcurl/lib/curl_gssapi.h
index 88f68dbbb..466d09ed0 100644
--- a/Utilities/cmcurl/lib/curl_gssapi.h
+++ b/Utilities/cmcurl/lib/curl_gssapi.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2011 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2011 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/curl_hmac.h b/Utilities/cmcurl/lib/curl_hmac.h
index 9b70c8468..84c73121b 100644
--- a/Utilities/cmcurl/lib/curl_hmac.h
+++ b/Utilities/cmcurl/lib/curl_hmac.h
@@ -11,7 +11,7 @@
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/curl_sec.h b/Utilities/cmcurl/lib/curl_krb5.h
index 7bdde269b..3f40f9a6c 100644
--- a/Utilities/cmcurl/lib/curl_sec.h
+++ b/Utilities/cmcurl/lib/curl_krb5.h
@@ -1,5 +1,5 @@
-#ifndef HEADER_CURL_SECURITY_H
-#define HEADER_CURL_SECURITY_H
+#ifndef HEADER_CURL_KRB5_H
+#define HEADER_CURL_KRB5_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -26,7 +26,7 @@ struct Curl_sec_client_mech {
const char *name;
size_t size;
int (*init)(void *);
- int (*auth)(void *, struct connectdata *);
+ int (*auth)(void *, struct Curl_easy *data, struct connectdata *);
void (*end)(void *);
int (*check_prot)(void *, int);
int (*overhead)(void *, int, int);
@@ -39,13 +39,13 @@ struct Curl_sec_client_mech {
#define AUTH_ERROR 2
#ifdef HAVE_GSSAPI
-int Curl_sec_read_msg(struct connectdata *conn, char *,
+int Curl_sec_read_msg(struct Curl_easy *data, struct connectdata *conn, char *,
enum protection_level);
void Curl_sec_end(struct connectdata *);
-CURLcode Curl_sec_login(struct connectdata *);
+CURLcode Curl_sec_login(struct Curl_easy *, struct connectdata *);
int Curl_sec_request_prot(struct connectdata *conn, const char *level);
-
-extern struct Curl_sec_client_mech Curl_krb5_client_mech;
+#else
+#define Curl_sec_end(x)
#endif
-#endif /* HEADER_CURL_SECURITY_H */
+#endif /* HEADER_CURL_KRB5_H */
diff --git a/Utilities/cmcurl/lib/curl_ldap.h b/Utilities/cmcurl/lib/curl_ldap.h
index 912e13107..124e18b13 100644
--- a/Utilities/cmcurl/lib/curl_ldap.h
+++ b/Utilities/cmcurl/lib/curl_ldap.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
diff --git a/Utilities/cmcurl/lib/curl_md4.h b/Utilities/cmcurl/lib/curl_md4.h
index c7bb20981..f9dafcb53 100644
--- a/Utilities/cmcurl/lib/curl_md4.h
+++ b/Utilities/cmcurl/lib/curl_md4.h
@@ -11,7 +11,7 @@
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/curl_md5.h b/Utilities/cmcurl/lib/curl_md5.h
index e06c68edf..5739c89ca 100644
--- a/Utilities/cmcurl/lib/curl_md5.h
+++ b/Utilities/cmcurl/lib/curl_md5.h
@@ -11,7 +11,7 @@
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/curl_memory.h b/Utilities/cmcurl/lib/curl_memory.h
index ce38a08cd..580629063 100644
--- a/Utilities/cmcurl/lib/curl_memory.h
+++ b/Utilities/cmcurl/lib/curl_memory.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
diff --git a/Utilities/cmcurl/lib/curl_memrchr.c b/Utilities/cmcurl/lib/curl_memrchr.c
index eeb3044a9..0bd845f69 100644
--- a/Utilities/cmcurl/lib/curl_memrchr.c
+++ b/Utilities/cmcurl/lib/curl_memrchr.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
diff --git a/Utilities/cmcurl/lib/curl_memrchr.h b/Utilities/cmcurl/lib/curl_memrchr.h
index 90a8a07cc..c8394bb43 100644
--- a/Utilities/cmcurl/lib/curl_memrchr.h
+++ b/Utilities/cmcurl/lib/curl_memrchr.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
diff --git a/Utilities/cmcurl/lib/curl_multibyte.c b/Utilities/cmcurl/lib/curl_multibyte.c
index 2c8925b53..d327c8ba7 100644
--- a/Utilities/cmcurl/lib/curl_multibyte.c
+++ b/Utilities/cmcurl/lib/curl_multibyte.c
@@ -9,7 +9,7 @@
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/curl_multibyte.h b/Utilities/cmcurl/lib/curl_multibyte.h
index 5f8c05afc..8adaf4978 100644
--- a/Utilities/cmcurl/lib/curl_multibyte.h
+++ b/Utilities/cmcurl/lib/curl_multibyte.h
@@ -11,7 +11,7 @@
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/curl_ntlm_core.c b/Utilities/cmcurl/lib/curl_ntlm_core.c
index 0eefb1587..9a075ac90 100644
--- a/Utilities/cmcurl/lib/curl_ntlm_core.c
+++ b/Utilities/cmcurl/lib/curl_ntlm_core.c
@@ -9,7 +9,7 @@
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -22,7 +22,7 @@
#include "curl_setup.h"
-#if defined(USE_NTLM)
+#if defined(USE_CURL_NTLM_CORE)
/*
* NTLM details:
@@ -50,8 +50,6 @@
in NTLM type-3 messages.
*/
-#if !defined(USE_WINDOWS_SSPI) || defined(USE_WIN32_CRYPTO)
-
#if defined(USE_OPENSSL) || defined(USE_WOLFSSL)
#ifdef USE_WOLFSSL
@@ -582,15 +580,11 @@ CURLcode Curl_ntlm_core_mk_ntlmv2_hash(const char *user, size_t userlen,
unsigned char *identity;
CURLcode result = CURLE_OK;
- /* we do the length checks below separately to avoid integer overflow risk
- on extreme data lengths */
- if((userlen > SIZE_T_MAX/2) ||
- (domlen > SIZE_T_MAX/2) ||
- ((userlen + domlen) > SIZE_T_MAX/2))
+ if((userlen > CURL_MAX_INPUT_LENGTH) || (domlen > CURL_MAX_INPUT_LENGTH))
return CURLE_OUT_OF_MEMORY;
identity_len = (userlen + domlen) * 2;
- identity = malloc(identity_len);
+ identity = malloc(identity_len + 1);
if(!identity)
return CURLE_OUT_OF_MEMORY;
@@ -744,6 +738,4 @@ CURLcode Curl_ntlm_core_mk_lmv2_resp(unsigned char *ntlmv2hash,
#endif /* USE_NTRESPONSES */
-#endif /* !USE_WINDOWS_SSPI || USE_WIN32_CRYPTO */
-
-#endif /* USE_NTLM */
+#endif /* USE_CURL_NTLM_CORE */
diff --git a/Utilities/cmcurl/lib/curl_ntlm_core.h b/Utilities/cmcurl/lib/curl_ntlm_core.h
index 7895b6470..fab628c59 100644
--- a/Utilities/cmcurl/lib/curl_ntlm_core.h
+++ b/Utilities/cmcurl/lib/curl_ntlm_core.h
@@ -11,7 +11,7 @@
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -24,7 +24,7 @@
#include "curl_setup.h"
-#if defined(USE_NTLM)
+#if defined(USE_CURL_NTLM_CORE)
/* If NSS is the first available SSL backend (see order in curl_ntlm_core.c)
then it must be initialized to be used by NTLM. */
@@ -36,8 +36,6 @@
#define NTLM_NEEDS_NSS_INIT
#endif
-#if !defined(USE_WINDOWS_SSPI) || defined(USE_WIN32_CRYPTO)
-
#if defined(USE_OPENSSL) || defined(USE_WOLFSSL)
#ifdef USE_WOLFSSL
# include <wolfssl/options.h>
@@ -102,8 +100,6 @@ CURLcode Curl_ntlm_core_mk_lmv2_resp(unsigned char *ntlmv2hash,
#endif /* USE_NTRESPONSES */
-#endif /* !USE_WINDOWS_SSPI || USE_WIN32_CRYPTO */
-
-#endif /* USE_NTLM */
+#endif /* USE_CURL_NTLM_CORE */
#endif /* HEADER_CURL_NTLM_CORE_H */
diff --git a/Utilities/cmcurl/lib/curl_ntlm_wb.c b/Utilities/cmcurl/lib/curl_ntlm_wb.c
index 17a92f8ca..9af79fd66 100644
--- a/Utilities/cmcurl/lib/curl_ntlm_wb.c
+++ b/Utilities/cmcurl/lib/curl_ntlm_wb.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -329,13 +329,16 @@ done:
return CURLE_REMOTE_ACCESS_DENIED;
}
-CURLcode Curl_input_ntlm_wb(struct connectdata *conn,
+CURLcode Curl_input_ntlm_wb(struct Curl_easy *data,
+ struct connectdata *conn,
bool proxy,
const char *header)
{
struct ntlmdata *ntlm = proxy ? &conn->proxyntlm : &conn->ntlm;
curlntlm *state = proxy ? &conn->proxy_ntlm_state : &conn->http_ntlm_state;
+ (void) data; /* In case it gets unused by nop log macros. */
+
if(!checkprefix("NTLM", header))
return CURLE_BAD_CONTENT_ENCODING;
@@ -352,17 +355,17 @@ CURLcode Curl_input_ntlm_wb(struct connectdata *conn,
}
else {
if(*state == NTLMSTATE_LAST) {
- infof(conn->data, "NTLM auth restarted\n");
+ infof(data, "NTLM auth restarted\n");
Curl_http_auth_cleanup_ntlm_wb(conn);
}
else if(*state == NTLMSTATE_TYPE3) {
- infof(conn->data, "NTLM handshake rejected\n");
+ infof(data, "NTLM handshake rejected\n");
Curl_http_auth_cleanup_ntlm_wb(conn);
*state = NTLMSTATE_NONE;
return CURLE_REMOTE_ACCESS_DENIED;
}
else if(*state >= NTLMSTATE_TYPE1) {
- infof(conn->data, "NTLM handshake failure (internal error)\n");
+ infof(data, "NTLM handshake failure (internal error)\n");
return CURLE_REMOTE_ACCESS_DENIED;
}
@@ -376,7 +379,8 @@ CURLcode Curl_input_ntlm_wb(struct connectdata *conn,
* This is for creating ntlm header output by delegating challenge/response
* to Samba's winbind daemon helper ntlm_auth.
*/
-CURLcode Curl_output_ntlm_wb(struct connectdata *conn, bool proxy)
+CURLcode Curl_output_ntlm_wb(struct Curl_easy *data, struct connectdata *conn,
+ bool proxy)
{
/* point to the address of the pointer that holds the string to send to the
server, which is for a plain host or for a HTTP proxy */
@@ -386,12 +390,11 @@ CURLcode Curl_output_ntlm_wb(struct connectdata *conn, bool proxy)
struct ntlmdata *ntlm;
curlntlm *state;
struct auth *authp;
- struct Curl_easy *data = conn->data;
CURLcode res = CURLE_OK;
DEBUGASSERT(conn);
- DEBUGASSERT(conn->data);
+ DEBUGASSERT(data);
if(proxy) {
#ifndef CURL_DISABLE_PROXY
@@ -399,7 +402,7 @@ CURLcode Curl_output_ntlm_wb(struct connectdata *conn, bool proxy)
userp = conn->http_proxy.user;
ntlm = &conn->proxyntlm;
state = &conn->proxy_ntlm_state;
- authp = &conn->data->state.authproxy;
+ authp = &data->state.authproxy;
#else
return CURLE_NOT_BUILT_IN;
#endif
@@ -409,7 +412,7 @@ CURLcode Curl_output_ntlm_wb(struct connectdata *conn, bool proxy)
userp = conn->user;
ntlm = &conn->ntlm;
state = &conn->http_ntlm_state;
- authp = &conn->data->state.authhost;
+ authp = &data->state.authhost;
}
authp->done = FALSE;
@@ -433,10 +436,10 @@ CURLcode Curl_output_ntlm_wb(struct connectdata *conn, bool proxy)
* request handling process.
*/
/* Create communication with ntlm_auth */
- res = ntlm_wb_init(conn->data, ntlm, userp);
+ res = ntlm_wb_init(data, ntlm, userp);
if(res)
return res;
- res = ntlm_wb_response(conn->data, ntlm, "YR\n", *state);
+ res = ntlm_wb_response(data, ntlm, "YR\n", *state);
if(res)
return res;
@@ -454,7 +457,7 @@ CURLcode Curl_output_ntlm_wb(struct connectdata *conn, bool proxy)
char *input = aprintf("TT %s\n", ntlm->challenge);
if(!input)
return CURLE_OUT_OF_MEMORY;
- res = ntlm_wb_response(conn->data, ntlm, input, *state);
+ res = ntlm_wb_response(data, ntlm, input, *state);
free(input);
if(res)
return res;
diff --git a/Utilities/cmcurl/lib/curl_ntlm_wb.h b/Utilities/cmcurl/lib/curl_ntlm_wb.h
index 3cf841cf2..961b56873 100644
--- a/Utilities/cmcurl/lib/curl_ntlm_wb.h
+++ b/Utilities/cmcurl/lib/curl_ntlm_wb.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -28,11 +28,13 @@
defined(NTLM_WB_ENABLED)
/* this is for ntlm header input */
-CURLcode Curl_input_ntlm_wb(struct connectdata *conn, bool proxy,
+CURLcode Curl_input_ntlm_wb(struct Curl_easy *data,
+ struct connectdata *conn, bool proxy,
const char *header);
/* this is for creating ntlm header output */
-CURLcode Curl_output_ntlm_wb(struct connectdata *conn, bool proxy);
+CURLcode Curl_output_ntlm_wb(struct Curl_easy *data, struct connectdata *conn,
+ bool proxy);
void Curl_http_auth_cleanup_ntlm_wb(struct connectdata *conn);
diff --git a/Utilities/cmcurl/lib/curl_path.c b/Utilities/cmcurl/lib/curl_path.c
index fbd98cb39..6100d77bd 100644
--- a/Utilities/cmcurl/lib/curl_path.c
+++ b/Utilities/cmcurl/lib/curl_path.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -31,12 +31,11 @@
#include "memdebug.h"
/* figure out the path to work with in this particular request */
-CURLcode Curl_getworkingpath(struct connectdata *conn,
+CURLcode Curl_getworkingpath(struct Curl_easy *data,
char *homedir, /* when SFTP is used */
char **path) /* returns the allocated
real path to work with */
{
- struct Curl_easy *data = conn->data;
char *real_path = NULL;
char *working_path;
size_t working_path_len;
@@ -47,7 +46,7 @@ CURLcode Curl_getworkingpath(struct connectdata *conn,
return result;
/* Check for /~/, indicating relative to the user's home directory */
- if(conn->handler->protocol & CURLPROTO_SCP) {
+ if(data->conn->handler->protocol & CURLPROTO_SCP) {
real_path = malloc(working_path_len + 1);
if(real_path == NULL) {
free(working_path);
@@ -59,7 +58,7 @@ CURLcode Curl_getworkingpath(struct connectdata *conn,
else
memcpy(real_path, working_path, 1 + working_path_len);
}
- else if(conn->handler->protocol & CURLPROTO_SFTP) {
+ else if(data->conn->handler->protocol & CURLPROTO_SFTP) {
if((working_path_len > 1) && (working_path[1] == '~')) {
size_t homelen = strlen(homedir);
real_path = malloc(homelen + working_path_len + 1);
@@ -168,7 +167,7 @@ CURLcode Curl_get_pathname(const char **cpp, char **path, char *homedir)
*cpp = cp + i + strspn(cp + i, WHITESPACE);
}
else {
- /* Read to end of filename - either to white space or terminator */
+ /* Read to end of filename - either to whitespace or terminator */
end = strpbrk(cp, WHITESPACE);
if(end == NULL)
end = strchr(cp, '\0');
@@ -184,7 +183,7 @@ CURLcode Curl_get_pathname(const char **cpp, char **path, char *homedir)
(*path)[pathLength] = '\0';
cp += 3;
}
- /* Copy path name up until first "white space" */
+ /* Copy path name up until first "whitespace" */
memcpy(&(*path)[pathLength], cp, (int)(end - cp));
pathLength += (int)(end - cp);
(*path)[pathLength] = '\0';
diff --git a/Utilities/cmcurl/lib/curl_path.h b/Utilities/cmcurl/lib/curl_path.h
index 636c37f20..a376bd1d2 100644
--- a/Utilities/cmcurl/lib/curl_path.h
+++ b/Utilities/cmcurl/lib/curl_path.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -39,7 +39,7 @@
have their definition hidden well */
#endif
-CURLcode Curl_getworkingpath(struct connectdata *conn,
+CURLcode Curl_getworkingpath(struct Curl_easy *data,
char *homedir,
char **path);
diff --git a/Utilities/cmcurl/lib/curl_printf.h b/Utilities/cmcurl/lib/curl_printf.h
index 0d37b8e57..9fa625f10 100644
--- a/Utilities/cmcurl/lib/curl_printf.h
+++ b/Utilities/cmcurl/lib/curl_printf.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
diff --git a/Utilities/cmcurl/lib/curl_range.c b/Utilities/cmcurl/lib/curl_range.c
index aa3c49332..f7fb7c082 100644
--- a/Utilities/cmcurl/lib/curl_range.c
+++ b/Utilities/cmcurl/lib/curl_range.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -33,12 +33,11 @@
Check if this is a range download, and if so, set the internal variables
properly.
*/
-CURLcode Curl_range(struct connectdata *conn)
+CURLcode Curl_range(struct Curl_easy *data)
{
curl_off_t from, to;
char *ptr;
char *ptr2;
- struct Curl_easy *data = conn->data;
if(data->state.use_range && data->state.range) {
CURLofft from_t;
diff --git a/Utilities/cmcurl/lib/curl_range.h b/Utilities/cmcurl/lib/curl_range.h
index 2350df992..0a07baf14 100644
--- a/Utilities/cmcurl/lib/curl_range.h
+++ b/Utilities/cmcurl/lib/curl_range.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -25,6 +25,5 @@
#include "curl_setup.h"
#include "urldata.h"
-CURLcode Curl_range(struct connectdata *conn);
-
+CURLcode Curl_range(struct Curl_easy *data);
#endif /* HEADER_CURL_RANGE_H */
diff --git a/Utilities/cmcurl/lib/curl_rtmp.c b/Utilities/cmcurl/lib/curl_rtmp.c
index df8f2b1d9..fabdc8848 100644
--- a/Utilities/cmcurl/lib/curl_rtmp.c
+++ b/Utilities/cmcurl/lib/curl_rtmp.c
@@ -5,12 +5,12 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2012 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2012 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 2010, Howard Chu, <hyc@highlandsun.com>
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -48,11 +48,13 @@
#define DEF_BUFTIME (2*60*60*1000) /* 2 hours */
-static CURLcode rtmp_setup_connection(struct connectdata *conn);
-static CURLcode rtmp_do(struct connectdata *conn, bool *done);
-static CURLcode rtmp_done(struct connectdata *conn, CURLcode, bool premature);
-static CURLcode rtmp_connect(struct connectdata *conn, bool *done);
-static CURLcode rtmp_disconnect(struct connectdata *conn, bool dead);
+static CURLcode rtmp_setup_connection(struct Curl_easy *data,
+ struct connectdata *conn);
+static CURLcode rtmp_do(struct Curl_easy *data, bool *done);
+static CURLcode rtmp_done(struct Curl_easy *data, CURLcode, bool premature);
+static CURLcode rtmp_connect(struct Curl_easy *data, bool *done);
+static CURLcode rtmp_disconnect(struct Curl_easy *data,
+ struct connectdata *conn, bool dead);
static Curl_recv rtmp_recv;
static Curl_send rtmp_send;
@@ -79,6 +81,7 @@ const struct Curl_handler Curl_handler_rtmp = {
ZERO_NULL, /* connection_check */
PORT_RTMP, /* defport */
CURLPROTO_RTMP, /* protocol */
+ CURLPROTO_RTMP, /* family */
PROTOPT_NONE /* flags*/
};
@@ -100,6 +103,7 @@ const struct Curl_handler Curl_handler_rtmpt = {
ZERO_NULL, /* connection_check */
PORT_RTMPT, /* defport */
CURLPROTO_RTMPT, /* protocol */
+ CURLPROTO_RTMPT, /* family */
PROTOPT_NONE /* flags*/
};
@@ -121,6 +125,7 @@ const struct Curl_handler Curl_handler_rtmpe = {
ZERO_NULL, /* connection_check */
PORT_RTMP, /* defport */
CURLPROTO_RTMPE, /* protocol */
+ CURLPROTO_RTMPE, /* family */
PROTOPT_NONE /* flags*/
};
@@ -142,6 +147,7 @@ const struct Curl_handler Curl_handler_rtmpte = {
ZERO_NULL, /* connection_check */
PORT_RTMPT, /* defport */
CURLPROTO_RTMPTE, /* protocol */
+ CURLPROTO_RTMPTE, /* family */
PROTOPT_NONE /* flags*/
};
@@ -163,6 +169,7 @@ const struct Curl_handler Curl_handler_rtmps = {
ZERO_NULL, /* connection_check */
PORT_RTMPS, /* defport */
CURLPROTO_RTMPS, /* protocol */
+ CURLPROTO_RTMP, /* family */
PROTOPT_NONE /* flags*/
};
@@ -184,10 +191,12 @@ const struct Curl_handler Curl_handler_rtmpts = {
ZERO_NULL, /* connection_check */
PORT_RTMPS, /* defport */
CURLPROTO_RTMPTS, /* protocol */
+ CURLPROTO_RTMPT, /* family */
PROTOPT_NONE /* flags*/
};
-static CURLcode rtmp_setup_connection(struct connectdata *conn)
+static CURLcode rtmp_setup_connection(struct Curl_easy *data,
+ struct connectdata *conn)
{
RTMP *r = RTMP_Alloc();
if(!r)
@@ -195,7 +204,7 @@ static CURLcode rtmp_setup_connection(struct connectdata *conn)
RTMP_Init(r);
RTMP_SetBufferMS(r, DEF_BUFTIME);
- if(!RTMP_SetupURL(r, conn->data->change.url)) {
+ if(!RTMP_SetupURL(r, data->change.url)) {
RTMP_Free(r);
return CURLE_URL_MALFORMAT;
}
@@ -203,8 +212,9 @@ static CURLcode rtmp_setup_connection(struct connectdata *conn)
return CURLE_OK;
}
-static CURLcode rtmp_connect(struct connectdata *conn, bool *done)
+static CURLcode rtmp_connect(struct Curl_easy *data, bool *done)
{
+ struct connectdata *conn = data->conn;
RTMP *r = conn->proto.rtmp;
SET_RCVTIMEO(tv, 10);
@@ -213,7 +223,7 @@ static CURLcode rtmp_connect(struct connectdata *conn, bool *done)
/* We have to know if it's a write before we send the
* connect request packet
*/
- if(conn->data->set.upload)
+ if(data->set.upload)
r->Link.protocol |= RTMP_FEATURE_WRITE;
/* For plain streams, use the buffer toggle trick to keep data flowing */
@@ -237,15 +247,15 @@ static CURLcode rtmp_connect(struct connectdata *conn, bool *done)
return CURLE_OK;
}
-static CURLcode rtmp_do(struct connectdata *conn, bool *done)
+static CURLcode rtmp_do(struct Curl_easy *data, bool *done)
{
- struct Curl_easy *data = conn->data;
+ struct connectdata *conn = data->conn;
RTMP *r = conn->proto.rtmp;
if(!RTMP_ConnectStream(r, 0))
return CURLE_FAILED_INIT;
- if(conn->data->set.upload) {
+ if(data->set.upload) {
Curl_pgrsSetUploadSize(data, data->state.infilesize);
Curl_setup_transfer(data, -1, -1, FALSE, FIRSTSOCKET);
}
@@ -255,20 +265,22 @@ static CURLcode rtmp_do(struct connectdata *conn, bool *done)
return CURLE_OK;
}
-static CURLcode rtmp_done(struct connectdata *conn, CURLcode status,
+static CURLcode rtmp_done(struct Curl_easy *data, CURLcode status,
bool premature)
{
- (void)conn; /* unused */
+ (void)data; /* unused */
(void)status; /* unused */
(void)premature; /* unused */
return CURLE_OK;
}
-static CURLcode rtmp_disconnect(struct connectdata *conn,
+static CURLcode rtmp_disconnect(struct Curl_easy *data,
+ struct connectdata *conn,
bool dead_connection)
{
RTMP *r = conn->proto.rtmp;
+ (void)data;
(void)dead_connection;
if(r) {
conn->proto.rtmp = NULL;
@@ -278,9 +290,10 @@ static CURLcode rtmp_disconnect(struct connectdata *conn,
return CURLE_OK;
}
-static ssize_t rtmp_recv(struct connectdata *conn, int sockindex, char *buf,
+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;
ssize_t nread;
@@ -289,8 +302,8 @@ static ssize_t rtmp_recv(struct connectdata *conn, int sockindex, char *buf,
nread = RTMP_Read(r, buf, curlx_uztosi(len));
if(nread < 0) {
if(r->m_read.status == RTMP_READ_COMPLETE ||
- r->m_read.status == RTMP_READ_EOF) {
- conn->data->req.size = conn->data->req.bytecount;
+ r->m_read.status == RTMP_READ_EOF) {
+ data->req.size = data->req.bytecount;
nread = 0;
}
else
@@ -299,9 +312,10 @@ static ssize_t rtmp_recv(struct connectdata *conn, int sockindex, char *buf,
return nread;
}
-static ssize_t rtmp_send(struct connectdata *conn, int sockindex,
+static ssize_t rtmp_send(struct Curl_easy *data, int sockindex,
const void *buf, size_t len, CURLcode *err)
{
+ struct connectdata *conn = data->conn;
RTMP *r = conn->proto.rtmp;
ssize_t num;
diff --git a/Utilities/cmcurl/lib/curl_rtmp.h b/Utilities/cmcurl/lib/curl_rtmp.h
index 86a01382d..f45fa71d1 100644
--- a/Utilities/cmcurl/lib/curl_rtmp.h
+++ b/Utilities/cmcurl/lib/curl_rtmp.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2010 - 2019, Howard Chu, <hyc@highlandsun.com>
+ * Copyright (C) 2010 - 2020, Howard Chu, <hyc@highlandsun.com>
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/curl_sasl.c b/Utilities/cmcurl/lib/curl_sasl.c
index 83fe896e3..ffeb75164 100644
--- a/Utilities/cmcurl/lib/curl_sasl.c
+++ b/Utilities/cmcurl/lib/curl_sasl.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2012 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2012 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -194,7 +194,7 @@ void Curl_sasl_init(struct SASL *sasl, const struct SASLproto *params)
*
* This is the ONLY way to change SASL state!
*/
-static void state(struct SASL *sasl, struct connectdata *conn,
+static void state(struct SASL *sasl, struct Curl_easy *data,
saslstate newstate)
{
#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
@@ -221,10 +221,10 @@ static void state(struct SASL *sasl, struct connectdata *conn,
};
if(sasl->state != newstate)
- infof(conn->data, "SASL %p state change from %s to %s\n",
+ infof(data, "SASL %p state change from %s to %s\n",
(void *)sasl, names[sasl->state], names[newstate]);
#else
- (void) conn;
+ (void) data;
#endif
sasl->state = newstate;
@@ -253,11 +253,11 @@ bool Curl_sasl_can_authenticate(struct SASL *sasl, struct connectdata *conn)
*
* Calculate the required login details for SASL authentication.
*/
-CURLcode Curl_sasl_start(struct SASL *sasl, struct connectdata *conn,
+CURLcode Curl_sasl_start(struct SASL *sasl, struct Curl_easy *data,
+ struct connectdata *conn,
bool force_ir, saslprogress *progress)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
unsigned int enabledmechs;
const char *mech = NULL;
char *resp = NULL;
@@ -398,10 +398,10 @@ CURLcode Curl_sasl_start(struct SASL *sasl, struct connectdata *conn,
resp = NULL;
}
- result = sasl->params->sendauth(conn, mech, resp);
+ result = sasl->params->sendauth(data, conn, mech, resp);
if(!result) {
*progress = SASL_INPROGRESS;
- state(sasl, conn, resp ? state2 : state1);
+ state(sasl, data, resp ? state2 : state1);
}
}
@@ -415,11 +415,11 @@ CURLcode Curl_sasl_start(struct SASL *sasl, struct connectdata *conn,
*
* Continue the authentication.
*/
-CURLcode Curl_sasl_continue(struct SASL *sasl, struct connectdata *conn,
+CURLcode Curl_sasl_continue(struct SASL *sasl, struct Curl_easy *data,
+ struct connectdata *conn,
int code, saslprogress *progress)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
saslstate newstate = SASL_FINAL;
char *resp = NULL;
#ifndef CURL_DISABLE_PROXY
@@ -450,14 +450,14 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct connectdata *conn,
if(code != sasl->params->finalcode)
result = CURLE_LOGIN_DENIED;
*progress = SASL_DONE;
- state(sasl, conn, SASL_STOP);
+ state(sasl, data, SASL_STOP);
return result;
}
if(sasl->state != SASL_CANCEL && sasl->state != SASL_OAUTH2_RESP &&
code != sasl->params->contcode) {
*progress = SASL_DONE;
- state(sasl, conn, SASL_STOP);
+ state(sasl, data, SASL_STOP);
return CURLE_LOGIN_DENIED;
}
@@ -587,7 +587,7 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct connectdata *conn,
if(code == sasl->params->finalcode) {
/* Final response was received so we are done */
*progress = SASL_DONE;
- state(sasl, conn, SASL_STOP);
+ state(sasl, data, SASL_STOP);
return result;
}
else if(code == sasl->params->contcode) {
@@ -600,7 +600,7 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct connectdata *conn,
}
else {
*progress = SASL_DONE;
- state(sasl, conn, SASL_STOP);
+ state(sasl, data, SASL_STOP);
return CURLE_LOGIN_DENIED;
}
@@ -609,7 +609,7 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct connectdata *conn,
sasl->authmechs ^= sasl->authused;
/* Start an alternative SASL authentication */
- result = Curl_sasl_start(sasl, conn, sasl->force_ir, progress);
+ result = Curl_sasl_start(sasl, data, conn, sasl->force_ir, progress);
newstate = sasl->state; /* Use state from Curl_sasl_start() */
break;
default:
@@ -621,12 +621,12 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct connectdata *conn,
switch(result) {
case CURLE_BAD_CONTENT_ENCODING:
/* Cancel dialog */
- result = sasl->params->sendcont(conn, "*");
+ result = sasl->params->sendcont(data, conn, "*");
newstate = SASL_CANCEL;
break;
case CURLE_OK:
if(resp)
- result = sasl->params->sendcont(conn, resp);
+ result = sasl->params->sendcont(data, conn, resp);
break;
default:
newstate = SASL_STOP; /* Stop on error */
@@ -636,7 +636,7 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct connectdata *conn,
free(resp);
- state(sasl, conn, newstate);
+ state(sasl, data, newstate);
return result;
}
diff --git a/Utilities/cmcurl/lib/curl_sasl.h b/Utilities/cmcurl/lib/curl_sasl.h
index 7647a48be..75a957583 100644
--- a/Utilities/cmcurl/lib/curl_sasl.h
+++ b/Utilities/cmcurl/lib/curl_sasl.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2012 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2012 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -88,10 +88,12 @@ struct SASLproto {
int contcode; /* Code to receive when continuation is expected */
int finalcode; /* Code to receive upon authentication success */
size_t maxirlen; /* Maximum initial response length */
- CURLcode (*sendauth)(struct connectdata *conn,
+ CURLcode (*sendauth)(struct Curl_easy *data,
+ struct connectdata *conn,
const char *mech, const char *ir);
/* Send authentication command */
- CURLcode (*sendcont)(struct connectdata *conn, const char *contauth);
+ CURLcode (*sendcont)(struct Curl_easy *data,
+ struct connectdata *conn, const char *contauth);
/* Send authentication continuation */
void (*getmessage)(char *buffer, char **outptr);
/* Get SASL response message */
@@ -133,11 +135,13 @@ void Curl_sasl_init(struct SASL *sasl, const struct SASLproto *params);
bool Curl_sasl_can_authenticate(struct SASL *sasl, struct connectdata *conn);
/* Calculate the required login details for SASL authentication */
-CURLcode Curl_sasl_start(struct SASL *sasl, struct connectdata *conn,
+CURLcode Curl_sasl_start(struct SASL *sasl, struct Curl_easy *data,
+ struct connectdata *conn,
bool force_ir, saslprogress *progress);
/* Continue an SASL authentication */
-CURLcode Curl_sasl_continue(struct SASL *sasl, struct connectdata *conn,
+CURLcode Curl_sasl_continue(struct SASL *sasl, struct Curl_easy *data,
+ struct connectdata *conn,
int code, saslprogress *progress);
#endif /* HEADER_CURL_SASL_H */
diff --git a/Utilities/cmcurl/lib/curl_setup.h b/Utilities/cmcurl/lib/curl_setup.h
index 45a093fbb..ef43b2b49 100644
--- a/Utilities/cmcurl/lib/curl_setup.h
+++ b/Utilities/cmcurl/lib/curl_setup.h
@@ -11,7 +11,7 @@
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -38,8 +38,7 @@
* Define WIN32 when build target is Win32 API
*/
-#if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32) && \
- !defined(__SYMBIAN32__)
+#if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32)
#define WIN32
#endif
@@ -88,10 +87,6 @@
# include "config-amigaos.h"
#endif
-#ifdef __SYMBIAN32__
-# include "config-symbian.h"
-#endif
-
#ifdef __OS400__
# include "config-os400.h"
#endif
@@ -247,7 +242,7 @@
* interface doesn't support IPv4, but supports IPv6, NAT64, and DNS64,
* performing this task will result in a synthesized IPv6 address.
*/
-#ifdef __APPLE__
+#if defined(__APPLE__) && !defined(USE_ARES)
#define USE_RESOLVE_ON_IPS 1
#endif
@@ -286,10 +281,16 @@
# include <exec/execbase.h>
# include <proto/exec.h>
# include <proto/dos.h>
+# include <unistd.h>
# ifdef HAVE_PROTO_BSDSOCKET_H
# include <proto/bsdsocket.h> /* ensure bsdsocket.library use */
# define select(a,b,c,d,e) WaitSelect(a,b,c,d,e,0)
# endif
+/*
+ * In clib2 arpa/inet.h warns that some prototypes may clash
+ * with bsdsocket.library. This avoids the definition of those.
+ */
+# define __NO_NET_API
#endif
#include <stdio.h>
@@ -575,14 +576,6 @@
/* ---------------------------------------------------------------- */
/*
- * When using WINSOCK, TELNET protocol requires WINSOCK2 API.
- */
-
-#if defined(USE_WINSOCK) && (USE_WINSOCK != 2)
-# define CURL_DISABLE_TELNET 1
-#endif
-
-/*
* msvc 6.0 does not have struct sockaddr_storage and
* does not define IPPROTO_ESP in winsock2.h. But both
* are available if PSDK is properly installed.
@@ -652,13 +645,12 @@ int netware_init(void);
/* Single point where USE_NTLM definition might be defined */
#if !defined(CURL_DISABLE_NTLM) && !defined(CURL_DISABLE_CRYPTO_AUTH)
-#if defined(USE_OPENSSL) || defined(USE_WINDOWS_SSPI) || \
+#if defined(USE_OPENSSL) || defined(USE_MBEDTLS) || \
defined(USE_GNUTLS) || defined(USE_NSS) || defined(USE_SECTRANSP) || \
defined(USE_OS400CRYPTO) || defined(USE_WIN32_CRYPTO) || \
- defined(USE_MBEDTLS) || \
(defined(USE_WOLFSSL) && defined(HAVE_WOLFSSL_DES_ECB_ENCRYPT))
-#define USE_NTLM
+#define USE_CURL_NTLM_CORE
# if defined(USE_MBEDTLS)
/* Get definition of MBEDTLS_MD4_C */
@@ -666,6 +658,10 @@ int netware_init(void);
# endif
#endif
+
+#if defined(USE_CURL_NTLM_CORE) || defined(USE_WINDOWS_SSPI)
+#define USE_NTLM
+#endif
#endif
#ifdef CURL_WANTS_CA_BUNDLE_ENV
@@ -717,7 +713,7 @@ int netware_init(void);
defined(HAVE_WINSOCK_H) || \
defined(HAVE_WINSOCK2_H) || \
defined(HAVE_WS2TCPIP_H)
-# error "Winsock and lwIP TCP/IP stack definitions shall not coexist!"
+# error "WinSock and lwIP TCP/IP stack definitions shall not coexist!"
# endif
#endif
diff --git a/Utilities/cmcurl/lib/curl_setup_once.h b/Utilities/cmcurl/lib/curl_setup_once.h
index e7c00deab..ef60bc7ae 100644
--- a/Utilities/cmcurl/lib/curl_setup_once.h
+++ b/Utilities/cmcurl/lib/curl_setup_once.h
@@ -11,7 +11,7 @@
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/curl_sha256.h b/Utilities/cmcurl/lib/curl_sha256.h
index 35d286ceb..b4579d769 100644
--- a/Utilities/cmcurl/lib/curl_sha256.h
+++ b/Utilities/cmcurl/lib/curl_sha256.h
@@ -12,7 +12,7 @@
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -24,6 +24,9 @@
***************************************************************************/
#ifndef CURL_DISABLE_CRYPTO_AUTH
+#include "curl_hmac.h"
+
+extern const struct HMAC_params Curl_HMAC_SHA256[1];
#define SHA256_DIGEST_LENGTH 32
diff --git a/Utilities/cmcurl/lib/curl_sspi.c b/Utilities/cmcurl/lib/curl_sspi.c
index 512ce2411..06841ddec 100644
--- a/Utilities/cmcurl/lib/curl_sspi.c
+++ b/Utilities/cmcurl/lib/curl_sspi.c
@@ -9,7 +9,7 @@
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/curl_sspi.h b/Utilities/cmcurl/lib/curl_sspi.h
index c09026ebb..881384d4e 100644
--- a/Utilities/cmcurl/lib/curl_sspi.h
+++ b/Utilities/cmcurl/lib/curl_sspi.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
diff --git a/Utilities/cmcurl/lib/curl_threads.c b/Utilities/cmcurl/lib/curl_threads.c
index b5f10a20e..414614401 100644
--- a/Utilities/cmcurl/lib/curl_threads.c
+++ b/Utilities/cmcurl/lib/curl_threads.c
@@ -9,7 +9,7 @@
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -41,14 +41,14 @@
#if defined(USE_THREADS_POSIX)
-struct curl_actual_call {
+struct Curl_actual_call {
unsigned int (*func)(void *);
void *arg;
};
static void *curl_thread_create_thunk(void *arg)
{
- struct curl_actual_call *ac = arg;
+ struct Curl_actual_call *ac = arg;
unsigned int (*func)(void *) = ac->func;
void *real_arg = ac->arg;
@@ -62,7 +62,7 @@ static void *curl_thread_create_thunk(void *arg)
curl_thread_t Curl_thread_create(unsigned int (*func) (void *), void *arg)
{
curl_thread_t t = malloc(sizeof(pthread_t));
- struct curl_actual_call *ac = malloc(sizeof(struct curl_actual_call));
+ struct Curl_actual_call *ac = malloc(sizeof(struct Curl_actual_call));
if(!(ac && t))
goto err;
diff --git a/Utilities/cmcurl/lib/curl_threads.h b/Utilities/cmcurl/lib/curl_threads.h
index 65d1a790c..e10b7a1b0 100644
--- a/Utilities/cmcurl/lib/curl_threads.h
+++ b/Utilities/cmcurl/lib/curl_threads.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
diff --git a/Utilities/cmcurl/lib/curlx.h b/Utilities/cmcurl/lib/curlx.h
index 98e51bf56..9f21f60d5 100644
--- a/Utilities/cmcurl/lib/curlx.h
+++ b/Utilities/cmcurl/lib/curlx.h
@@ -11,7 +11,7 @@
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/dict.c b/Utilities/cmcurl/lib/dict.c
index f529b48f7..4319dadba 100644
--- a/Utilities/cmcurl/lib/dict.c
+++ b/Utilities/cmcurl/lib/dict.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -57,6 +57,7 @@
#include "escape.h"
#include "progress.h"
#include "dict.h"
+#include "curl_printf.h"
#include "strcase.h"
#include "curl_memory.h"
/* The last #include file should be: */
@@ -66,7 +67,7 @@
* Forward declarations.
*/
-static CURLcode dict_do(struct connectdata *conn, bool *done);
+static CURLcode dict_do(struct Curl_easy *data, bool *done);
/*
* DICT protocol handler.
@@ -90,7 +91,8 @@ const struct Curl_handler Curl_handler_dict = {
ZERO_NULL, /* connection_check */
PORT_DICT, /* defport */
CURLPROTO_DICT, /* protocol */
- PROTOPT_NONE | PROTOPT_NOURLQUERY /* flags */
+ CURLPROTO_DICT, /* family */
+ PROTOPT_NONE | PROTOPT_NOURLQUERY /* flags */
};
static char *unescape_word(struct Curl_easy *data, const char *inputbuff)
@@ -126,7 +128,51 @@ static char *unescape_word(struct Curl_easy *data, const char *inputbuff)
return dictp;
}
-static CURLcode dict_do(struct connectdata *conn, bool *done)
+/* sendf() sends formatted data to the server */
+static CURLcode sendf(curl_socket_t sockfd, struct Curl_easy *data,
+ const char *fmt, ...)
+{
+ ssize_t bytes_written;
+ size_t write_len;
+ CURLcode result = CURLE_OK;
+ char *s;
+ char *sptr;
+ va_list ap;
+ va_start(ap, fmt);
+ s = vaprintf(fmt, ap); /* returns an allocated string */
+ va_end(ap);
+ if(!s)
+ return CURLE_OUT_OF_MEMORY; /* failure */
+
+ bytes_written = 0;
+ write_len = strlen(s);
+ sptr = s;
+
+ for(;;) {
+ /* Write the buffer to the socket */
+ result = Curl_write(data, sockfd, sptr, write_len, &bytes_written);
+
+ if(result)
+ break;
+
+ Curl_debug(data, CURLINFO_DATA_OUT, sptr, (size_t)bytes_written);
+
+ if((size_t)bytes_written != write_len) {
+ /* if not all was written at once, we must advance the pointer, decrease
+ the size left and try again! */
+ write_len -= bytes_written;
+ sptr += bytes_written;
+ }
+ else
+ break;
+ }
+
+ free(s); /* free the output string */
+
+ return result;
+}
+
+static CURLcode dict_do(struct Curl_easy *data, bool *done)
{
char *word;
char *eword;
@@ -136,7 +182,7 @@ static CURLcode dict_do(struct connectdata *conn, bool *done)
char *nthdef = NULL; /* This is not part of the protocol, but required
by RFC 2229 */
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
+ struct connectdata *conn = data->conn;
curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
char *path = data->state.up.path;
@@ -183,18 +229,16 @@ static CURLcode dict_do(struct connectdata *conn, bool *done)
if(!eword)
return CURLE_OUT_OF_MEMORY;
- result = Curl_sendf(sockfd, conn,
- "CLIENT " LIBCURL_NAME " " LIBCURL_VERSION "\r\n"
- "MATCH "
- "%s " /* database */
- "%s " /* strategy */
- "%s\r\n" /* word */
- "QUIT\r\n",
-
- database,
- strategy,
- eword
- );
+ result = sendf(sockfd, data,
+ "CLIENT " LIBCURL_NAME " " LIBCURL_VERSION "\r\n"
+ "MATCH "
+ "%s " /* database */
+ "%s " /* strategy */
+ "%s\r\n" /* word */
+ "QUIT\r\n",
+ database,
+ strategy,
+ eword);
free(eword);
@@ -233,14 +277,14 @@ static CURLcode dict_do(struct connectdata *conn, bool *done)
if(!eword)
return CURLE_OUT_OF_MEMORY;
- result = Curl_sendf(sockfd, conn,
- "CLIENT " LIBCURL_NAME " " LIBCURL_VERSION "\r\n"
- "DEFINE "
- "%s " /* database */
- "%s\r\n" /* word */
- "QUIT\r\n",
- database,
- eword);
+ result = sendf(sockfd, data,
+ "CLIENT " LIBCURL_NAME " " LIBCURL_VERSION "\r\n"
+ "DEFINE "
+ "%s " /* database */
+ "%s\r\n" /* word */
+ "QUIT\r\n",
+ database,
+ eword);
free(eword);
@@ -261,10 +305,10 @@ static CURLcode dict_do(struct connectdata *conn, bool *done)
if(ppath[i] == ':')
ppath[i] = ' ';
}
- result = Curl_sendf(sockfd, conn,
- "CLIENT " LIBCURL_NAME " " LIBCURL_VERSION "\r\n"
- "%s\r\n"
- "QUIT\r\n", ppath);
+ result = sendf(sockfd, data,
+ "CLIENT " LIBCURL_NAME " " LIBCURL_VERSION "\r\n"
+ "%s\r\n"
+ "QUIT\r\n", ppath);
if(result) {
failf(data, "Failed sending DICT request");
return result;
diff --git a/Utilities/cmcurl/lib/dict.h b/Utilities/cmcurl/lib/dict.h
index 38a55ac0d..6a6c772d1 100644
--- a/Utilities/cmcurl/lib/dict.h
+++ b/Utilities/cmcurl/lib/dict.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
diff --git a/Utilities/cmcurl/lib/doh.c b/Utilities/cmcurl/lib/doh.c
index 8bc3428ff..004244c8d 100644
--- a/Utilities/cmcurl/lib/doh.c
+++ b/Utilities/cmcurl/lib/doh.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2018 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2018 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -57,12 +57,13 @@ static const char * const errors[]={
"Unexpected TYPE",
"Unexpected CLASS",
"No content",
- "Bad ID"
+ "Bad ID",
+ "Name too long"
};
static const char *doh_strerror(DOHcode code)
{
- if((code >= DOH_OK) && (code <= DOH_DNS_BAD_ID))
+ if((code >= DOH_OK) && (code <= DOH_DNS_NAME_TOO_LONG))
return errors[code];
return "bad error code";
}
@@ -186,19 +187,20 @@ doh_write_cb(const void *contents, size_t size, size_t nmemb, void *userp)
}
/* called from multi.c when this DOH transfer is complete */
-static int Curl_doh_done(struct Curl_easy *doh, CURLcode result)
+static int doh_done(struct Curl_easy *doh, CURLcode result)
{
struct Curl_easy *data = doh->set.dohfor;
+ struct dohdata *dohp = data->req.doh;
/* so one of the DOH request done for the 'data' transfer is now complete! */
- data->req.doh.pending--;
- infof(data, "a DOH request is completed, %u to go\n", data->req.doh.pending);
+ dohp->pending--;
+ infof(data, "a DOH request is completed, %u to go\n", dohp->pending);
if(result)
infof(data, "DOH request %s\n", curl_easy_strerror(result));
- if(!data->req.doh.pending) {
+ if(!dohp->pending) {
/* DOH completed */
- curl_slist_free_all(data->req.doh.headers);
- data->req.doh.headers = NULL;
+ curl_slist_free_all(dohp->headers);
+ dohp->headers = NULL;
Curl_expire(data, 0, EXPIRE_RUN_NOW);
}
return 0;
@@ -224,7 +226,7 @@ static CURLcode dohprobe(struct Curl_easy *data,
DOHcode d = doh_encode(host, dnstype, p->dohbuffer, sizeof(p->dohbuffer),
&p->dohlen);
if(d) {
- failf(data, "Failed to encode DOH packet [%d]\n", d);
+ failf(data, "Failed to encode DOH packet [%d]", d);
return CURLE_OUT_OF_MEMORY;
}
@@ -348,8 +350,12 @@ static CURLcode dohprobe(struct Curl_easy *data,
ERROR_CHECK_SETOPT(CURLOPT_SSL_CTX_FUNCTION, data->set.ssl.fsslctx);
if(data->set.ssl.fsslctxp)
ERROR_CHECK_SETOPT(CURLOPT_SSL_CTX_DATA, data->set.ssl.fsslctxp);
+ if(data->set.str[STRING_SSL_EC_CURVES]) {
+ ERROR_CHECK_SETOPT(CURLOPT_SSL_EC_CURVES,
+ data->set.str[STRING_SSL_EC_CURVES]);
+ }
- doh->set.fmultidone = Curl_doh_done;
+ doh->set.fmultidone = doh_done;
doh->set.dohfor = data; /* identify for which transfer this is done */
p->easy = doh;
@@ -373,58 +379,64 @@ static CURLcode dohprobe(struct Curl_easy *data,
* 'Curl_addrinfo *' with the address information.
*/
-struct Curl_addrinfo *Curl_doh(struct connectdata *conn,
+struct Curl_addrinfo *Curl_doh(struct Curl_easy *data,
const char *hostname,
int port,
int *waitp)
{
- struct Curl_easy *data = conn->data;
CURLcode result = CURLE_OK;
int slot;
+ struct dohdata *dohp;
+ struct connectdata *conn = data->conn;
*waitp = TRUE; /* this never returns synchronously */
- (void)conn;
(void)hostname;
(void)port;
+ DEBUGASSERT(!data->req.doh);
+ DEBUGASSERT(conn);
+
/* start clean, consider allocating this struct on demand */
- memset(&data->req.doh, 0, sizeof(struct dohdata));
+ dohp = data->req.doh = calloc(sizeof(struct dohdata), 1);
+ if(!dohp)
+ return NULL;
conn->bits.doh = TRUE;
- data->req.doh.host = hostname;
- data->req.doh.port = port;
- data->req.doh.headers =
+ dohp->host = hostname;
+ dohp->port = port;
+ dohp->headers =
curl_slist_append(NULL,
"Content-Type: application/dns-message");
- if(!data->req.doh.headers)
+ if(!dohp->headers)
goto error;
if(conn->ip_version != CURL_IPRESOLVE_V6) {
/* create IPv4 DOH request */
- result = dohprobe(data, &data->req.doh.probe[DOH_PROBE_SLOT_IPADDR_V4],
+ result = dohprobe(data, &dohp->probe[DOH_PROBE_SLOT_IPADDR_V4],
DNS_TYPE_A, hostname, data->set.str[STRING_DOH],
- data->multi, data->req.doh.headers);
+ data->multi, dohp->headers);
if(result)
goto error;
- data->req.doh.pending++;
+ dohp->pending++;
}
if(conn->ip_version != CURL_IPRESOLVE_V4) {
/* create IPv6 DOH request */
- result = dohprobe(data, &data->req.doh.probe[DOH_PROBE_SLOT_IPADDR_V6],
+ result = dohprobe(data, &dohp->probe[DOH_PROBE_SLOT_IPADDR_V6],
DNS_TYPE_AAAA, hostname, data->set.str[STRING_DOH],
- data->multi, data->req.doh.headers);
+ data->multi, dohp->headers);
if(result)
goto error;
- data->req.doh.pending++;
+ dohp->pending++;
}
return NULL;
error:
- curl_slist_free_all(data->req.doh.headers);
- data->req.doh.headers = NULL;
+ curl_slist_free_all(dohp->headers);
+ data->req.doh->headers = NULL;
for(slot = 0; slot < DOH_PROBE_SLOTS; slot++) {
- Curl_close(&data->req.doh.probe[slot].easy);
+ Curl_close(&dohp->probe[slot].easy);
}
+ Curl_safefree(data->req.doh);
return NULL;
}
@@ -463,7 +475,7 @@ static unsigned int get32bit(const unsigned char *doh, int index)
the pointer first. */
doh += index;
- /* avoid undefined behaviour by casting to unsigned before shifting
+ /* avoid undefined behavior by casting to unsigned before shifting
24 bits, possibly into the sign bit. codegen is same, but
ub sanitizer won't be upset */
return ( (unsigned)doh[0] << 24) | (doh[1] << 16) |(doh[2] << 8) | doh[3];
@@ -899,20 +911,22 @@ UNITTEST void de_cleanup(struct dohentry *d)
}
}
-CURLcode Curl_doh_is_resolved(struct connectdata *conn,
+CURLcode Curl_doh_is_resolved(struct Curl_easy *data,
struct Curl_dns_entry **dnsp)
{
CURLcode result;
- struct Curl_easy *data = conn->data;
+ struct dohdata *dohp = data->req.doh;
*dnsp = NULL; /* defaults to no response */
+ if(!dohp)
+ return CURLE_OUT_OF_MEMORY;
- if(!data->req.doh.probe[DOH_PROBE_SLOT_IPADDR_V4].easy &&
- !data->req.doh.probe[DOH_PROBE_SLOT_IPADDR_V6].easy) {
- failf(data, "Could not DOH-resolve: %s", conn->async.hostname);
- return conn->bits.proxy?CURLE_COULDNT_RESOLVE_PROXY:
+ if(!dohp->probe[DOH_PROBE_SLOT_IPADDR_V4].easy &&
+ !dohp->probe[DOH_PROBE_SLOT_IPADDR_V6].easy) {
+ failf(data, "Could not DOH-resolve: %s", data->state.async.hostname);
+ return data->conn->bits.proxy?CURLE_COULDNT_RESOLVE_PROXY:
CURLE_COULDNT_RESOLVE_HOST;
}
- else if(!data->req.doh.pending) {
+ else if(!dohp->pending) {
DOHcode rc[DOH_PROBE_SLOTS] = {
DOH_OK, DOH_OK
};
@@ -920,13 +934,13 @@ CURLcode Curl_doh_is_resolved(struct connectdata *conn,
int slot;
/* remove DOH handles from multi handle and close them */
for(slot = 0; slot < DOH_PROBE_SLOTS; slot++) {
- curl_multi_remove_handle(data->multi, data->req.doh.probe[slot].easy);
- Curl_close(&data->req.doh.probe[slot].easy);
+ curl_multi_remove_handle(data->multi, dohp->probe[slot].easy);
+ Curl_close(&dohp->probe[slot].easy);
}
/* parse the responses, create the struct and return it! */
de_init(&de);
for(slot = 0; slot < DOH_PROBE_SLOTS; slot++) {
- struct dnsprobe *p = &data->req.doh.probe[slot];
+ struct dnsprobe *p = &dohp->probe[slot];
if(!p->dnstype)
continue;
rc[slot] = doh_decode(Curl_dyn_uptr(&p->serverdoh),
@@ -936,7 +950,7 @@ CURLcode Curl_doh_is_resolved(struct connectdata *conn,
Curl_dyn_free(&p->serverdoh);
if(rc[slot]) {
infof(data, "DOH: %s type %s for %s\n", doh_strerror(rc[slot]),
- type2name(p->dnstype), data->req.doh.host);
+ type2name(p->dnstype), dohp->host);
}
} /* next slot */
@@ -946,10 +960,10 @@ CURLcode Curl_doh_is_resolved(struct connectdata *conn,
struct Curl_dns_entry *dns;
struct Curl_addrinfo *ai;
- infof(data, "DOH Host name: %s\n", data->req.doh.host);
+ infof(data, "DOH Host name: %s\n", dohp->host);
showdoh(data, &de);
- ai = doh2ai(&de, data->req.doh.host, data->req.doh.port);
+ ai = doh2ai(&de, dohp->host, dohp->port);
if(!ai) {
de_cleanup(&de);
return CURLE_OUT_OF_MEMORY;
@@ -959,7 +973,7 @@ CURLcode Curl_doh_is_resolved(struct connectdata *conn,
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, data->req.doh.host, data->req.doh.port);
+ dns = Curl_cache_addr(data, ai, dohp->host, dohp->port);
if(data->share)
Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
@@ -969,7 +983,7 @@ CURLcode Curl_doh_is_resolved(struct connectdata *conn,
Curl_freeaddrinfo(ai);
}
else {
- conn->async.dns = dns;
+ data->state.async.dns = dns;
*dnsp = dns;
result = CURLE_OK; /* address resolution OK */
}
@@ -979,9 +993,10 @@ CURLcode Curl_doh_is_resolved(struct connectdata *conn,
/* All done */
de_cleanup(&de);
+ Curl_safefree(data->req.doh);
return result;
- } /* !data->req.doh.pending */
+ } /* !dohp->pending */
/* else wait for pending DOH transactions to complete */
return CURLE_OK;
diff --git a/Utilities/cmcurl/lib/doh.h b/Utilities/cmcurl/lib/doh.h
index bbd4c1a65..b3584d1b2 100644
--- a/Utilities/cmcurl/lib/doh.h
+++ b/Utilities/cmcurl/lib/doh.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2018 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2018 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -32,12 +32,12 @@
* and returns a 'Curl_addrinfo *' with the address information.
*/
-struct Curl_addrinfo *Curl_doh(struct connectdata *conn,
+struct Curl_addrinfo *Curl_doh(struct Curl_easy *data,
const char *hostname,
int port,
int *waitp);
-CURLcode Curl_doh_is_resolved(struct connectdata *conn,
+CURLcode Curl_doh_is_resolved(struct Curl_easy *data,
struct Curl_dns_entry **dns);
int Curl_doh_getsock(struct connectdata *conn, curl_socket_t *socks);
diff --git a/Utilities/cmcurl/lib/dotdot.c b/Utilities/cmcurl/lib/dotdot.c
index ce9a05214..3a1435f8e 100644
--- a/Utilities/cmcurl/lib/dotdot.c
+++ b/Utilities/cmcurl/lib/dotdot.c
@@ -9,7 +9,7 @@
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/dotdot.h b/Utilities/cmcurl/lib/dotdot.h
index f70b1db3f..ac1ea363e 100644
--- a/Utilities/cmcurl/lib/dotdot.h
+++ b/Utilities/cmcurl/lib/dotdot.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
diff --git a/Utilities/cmcurl/lib/dynbuf.c b/Utilities/cmcurl/lib/dynbuf.c
index 38d370b07..ada7e0ccf 100644
--- a/Utilities/cmcurl/lib/dynbuf.c
+++ b/Utilities/cmcurl/lib/dynbuf.c
@@ -9,7 +9,7 @@
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -21,12 +21,11 @@
***************************************************************************/
#include "curl_setup.h"
-#include "strdup.h"
#include "dynbuf.h"
-
-/* The last 3 #include files should be in this order */
#include "curl_printf.h"
+#ifdef BUILDING_LIBCURL
#include "curl_memory.h"
+#endif
#include "memdebug.h"
#define MIN_FIRST_ALLOC 32
@@ -94,11 +93,15 @@ static CURLcode dyn_nappend(struct dynbuf *s,
}
if(a != s->allc) {
- s->bufr = Curl_saferealloc(s->bufr, a);
- if(!s->bufr) {
+ /* this logic is not using Curl_saferealloc() to make the tool not have to
+ include that as well when it uses this code */
+ void *p = realloc(s->bufr, a);
+ if(!p) {
+ Curl_safefree(s->bufr);
s->leng = s->allc = 0;
return CURLE_OUT_OF_MEMORY;
}
+ s->bufr = p;
s->allc = a;
}
@@ -143,6 +146,7 @@ CURLcode Curl_dyn_tail(struct dynbuf *s, size_t trail)
else {
memmove(&s->bufr[0], &s->bufr[s->leng - trail], trail);
s->leng = trail;
+ s->bufr[s->leng] = 0;
}
return CURLE_OK;
@@ -173,15 +177,22 @@ CURLcode Curl_dyn_add(struct dynbuf *s, const char *str)
}
/*
- * Append a string printf()-style
+ * Append a string vprintf()-style
*/
-CURLcode Curl_dyn_addf(struct dynbuf *s, const char *fmt, ...)
+CURLcode Curl_dyn_vaddf(struct dynbuf *s, const char *fmt, va_list ap)
{
+#ifdef BUILDING_LIBCURL
+ int rc;
+ DEBUGASSERT(s);
+ DEBUGASSERT(s->init == DYNINIT);
+ DEBUGASSERT(!s->leng || s->bufr);
+ rc = Curl_dyn_vprintf(s, fmt, ap);
+
+ if(!rc)
+ return CURLE_OK;
+#else
char *str;
- va_list ap;
- va_start(ap, fmt);
str = vaprintf(fmt, ap); /* this allocs a new string to append */
- va_end(ap);
if(str) {
CURLcode result = dyn_nappend(s, (unsigned char *)str, strlen(str));
@@ -190,10 +201,27 @@ CURLcode Curl_dyn_addf(struct dynbuf *s, const char *fmt, ...)
}
/* If we failed, we cleanup the whole buffer and return error */
Curl_dyn_free(s);
+#endif
return CURLE_OUT_OF_MEMORY;
}
/*
+ * Append a string printf()-style
+ */
+CURLcode Curl_dyn_addf(struct dynbuf *s, const char *fmt, ...)
+{
+ CURLcode result;
+ va_list ap;
+ DEBUGASSERT(s);
+ DEBUGASSERT(s->init == DYNINIT);
+ DEBUGASSERT(!s->leng || s->bufr);
+ va_start(ap, fmt);
+ result = Curl_dyn_vaddf(s, fmt, ap);
+ va_end(ap);
+ return result;
+}
+
+/*
* Returns a pointer to the buffer.
*/
char *Curl_dyn_ptr(const struct dynbuf *s)
diff --git a/Utilities/cmcurl/lib/dynbuf.h b/Utilities/cmcurl/lib/dynbuf.h
index ecc995755..484e40c64 100644
--- a/Utilities/cmcurl/lib/dynbuf.h
+++ b/Utilities/cmcurl/lib/dynbuf.h
@@ -11,7 +11,7 @@
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -22,6 +22,23 @@
*
***************************************************************************/
+#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_tail(a,b) curlx_dyn_tail(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 zero terminator */
@@ -40,12 +57,18 @@ CURLcode Curl_dyn_add(struct dynbuf *s, const char *str)
WARN_UNUSED_RESULT;
CURLcode Curl_dyn_addf(struct dynbuf *s, const char *fmt, ...)
WARN_UNUSED_RESULT;
+CURLcode Curl_dyn_vaddf(struct dynbuf *s, const char *fmt, va_list ap)
+ WARN_UNUSED_RESULT;
void Curl_dyn_reset(struct dynbuf *s);
CURLcode Curl_dyn_tail(struct dynbuf *s, size_t trail);
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);
+/* 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);
+
/* Dynamic buffer max sizes */
#define DYN_DOH_RESPONSE 3000
#define DYN_DOH_CNAME 256
@@ -60,4 +83,6 @@ size_t Curl_dyn_len(const struct dynbuf *s);
#define DYN_PROXY_CONNECT_HEADERS 16384
#define DYN_QLOG_NAME 1024
#define DYN_H1_TRAILER 4096
+#define DYN_PINGPPONG_CMD (64*1024)
+#define DYN_IMAP_CMD (64*1024)
#endif
diff --git a/Utilities/cmcurl/lib/easy.c b/Utilities/cmcurl/lib/easy.c
index a69eb9e56..0fb255af4 100644
--- a/Utilities/cmcurl/lib/easy.c
+++ b/Utilities/cmcurl/lib/easy.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -78,6 +78,8 @@
#include "system_win32.h"
#include "http2.h"
#include "dynbuf.h"
+#include "altsvc.h"
+#include "hsts.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
@@ -105,7 +107,6 @@ static long init_flags;
# pragma warning(disable:4232) /* MSVC extension, dllimport identity */
#endif
-#ifndef __SYMBIAN32__
/*
* If a memory-using function (like curl_getenv) is used before
* curl_global_init() is called, we need to have these pointers set already.
@@ -118,22 +119,15 @@ curl_calloc_callback Curl_ccalloc = (curl_calloc_callback)calloc;
#if defined(WIN32) && defined(UNICODE)
curl_wcsdup_callback Curl_cwcsdup = (curl_wcsdup_callback)_wcsdup;
#endif
-#else
-/*
- * Symbian OS doesn't support initialization to code in writable static data.
- * Initialization will occur in the curl_global_init() call.
- */
-curl_malloc_callback Curl_cmalloc;
-curl_free_callback Curl_cfree;
-curl_realloc_callback Curl_crealloc;
-curl_strdup_callback Curl_cstrdup;
-curl_calloc_callback Curl_ccalloc;
-#endif
#if defined(_MSC_VER) && defined(_DLL) && !defined(__POCC__)
# pragma warning(default:4232) /* MSVC extension, dllimport identity */
#endif
+#ifdef DEBUGBUILD
+static char *leakpointer;
+#endif
+
/**
* curl_global_init() globally initializes curl given a bitwise set of the
* different features of what to initialize.
@@ -200,6 +194,12 @@ static CURLcode global_init(long flags, bool memoryfuncs)
init_flags = flags;
+#ifdef DEBUGBUILD
+ if(getenv("CURL_GLOBAL_INIT"))
+ /* alloc data that will leak if *cleanup() is not called! */
+ leakpointer = malloc(1);
+#endif
+
return CURLE_OK;
fail:
@@ -275,6 +275,9 @@ void curl_global_cleanup(void)
#ifdef USE_WOLFSSH
(void)wolfSSH_Cleanup();
#endif
+#ifdef DEBUGBUILD
+ free(leakpointer);
+#endif
init_flags = 0;
}
@@ -883,10 +886,30 @@ struct Curl_easy *curl_easy_duphandle(struct Curl_easy *data)
goto fail;
}
+#ifdef USE_ALTSVC
+ if(data->asi) {
+ outcurl->asi = Curl_altsvc_init();
+ if(!outcurl->asi)
+ goto fail;
+ if(outcurl->set.str[STRING_ALTSVC])
+ (void)Curl_altsvc_load(outcurl->asi, outcurl->set.str[STRING_ALTSVC]);
+ }
+#endif
+#ifdef USE_HSTS
+ if(data->hsts) {
+ outcurl->hsts = Curl_hsts_init();
+ if(!outcurl->hsts)
+ goto fail;
+ if(outcurl->set.str[STRING_HSTS])
+ (void)Curl_hsts_loadfile(outcurl,
+ outcurl->hsts, outcurl->set.str[STRING_HSTS]);
+ (void)Curl_hsts_loadcb(outcurl, outcurl->hsts);
+ }
+#endif
/* Clone the resolver handle, if present, for the new handle */
if(Curl_resolver_duphandle(outcurl,
- &outcurl->state.resolver,
- data->state.resolver))
+ &outcurl->state.async.resolver,
+ data->state.async.resolver))
goto fail;
#ifdef USE_ARES
@@ -930,6 +953,8 @@ struct Curl_easy *curl_easy_duphandle(struct Curl_easy *data)
Curl_dyn_free(&outcurl->state.headerb);
Curl_safefree(outcurl->change.url);
Curl_safefree(outcurl->change.referer);
+ Curl_altsvc_cleanup(&outcurl->asi);
+ Curl_hsts_cleanup(&outcurl->hsts);
Curl_freeset(outcurl);
free(outcurl);
}
@@ -958,6 +983,7 @@ void curl_easy_reset(struct Curl_easy *data)
data->progress.flags |= PGRS_HIDE;
data->state.current_speed = -1; /* init to negative == impossible */
+ data->state.retrycount = 0; /* reset the retry counter */
/* zero out authentication data: */
memset(&data->state.authhost, 0, sizeof(struct auth));
@@ -1046,7 +1072,7 @@ CURLcode curl_easy_pause(struct Curl_easy *data, int action)
/* even if one function returns error, this loops through and frees
all buffers */
if(!result)
- result = Curl_client_write(conn, writebuf[i].type,
+ result = Curl_client_write(data, writebuf[i].type,
Curl_dyn_ptr(&writebuf[i].b),
Curl_dyn_len(&writebuf[i].b));
Curl_dyn_free(&writebuf[i].b);
@@ -1067,9 +1093,13 @@ CURLcode curl_easy_pause(struct Curl_easy *data, int action)
(KEEP_RECV_PAUSE|KEEP_SEND_PAUSE)) {
Curl_expire(data, 0, EXPIRE_RUN_NOW); /* get this handle going again */
- /* force a recv/send check of this connection, as the data might've been
- read off the socket already */
- data->conn->cselect_bits = CURL_CSELECT_IN | CURL_CSELECT_OUT;
+ /* reset the too-slow time keeper */
+ data->state.keeps_speed.tv_sec = 0;
+
+ if(!data->state.tempcount)
+ /* if not pausing again, force a recv/send check of this connection as
+ the data might've been read off the socket already */
+ data->conn->cselect_bits = CURL_CSELECT_IN | CURL_CSELECT_OUT;
if(data->multi)
Curl_update_timer(data->multi);
}
@@ -1126,8 +1156,13 @@ CURLcode curl_easy_recv(struct Curl_easy *data, void *buffer, size_t buflen,
if(result)
return result;
+ if(!data->conn)
+ /* on first invoke, the transfer has been detached from the connection and
+ needs to be reattached */
+ Curl_attach_connnection(data, c);
+
*n = 0;
- result = Curl_read(c, sfd, buffer, buflen, &n1);
+ result = Curl_read(data, sfd, buffer, buflen, &n1);
if(result)
return result;
@@ -1156,8 +1191,13 @@ CURLcode curl_easy_send(struct Curl_easy *data, const void *buffer,
if(result)
return result;
+ if(!data->conn)
+ /* on first invoke, the transfer has been detached from the connection and
+ needs to be reattached */
+ Curl_attach_connnection(data, c);
+
*n = 0;
- result = Curl_write(c, sfd, buffer, buflen, &n1);
+ result = Curl_write(data, sfd, buffer, buflen, &n1);
if(n1 == -1)
return CURLE_SEND_ERROR;
@@ -1176,16 +1216,16 @@ CURLcode curl_easy_send(struct Curl_easy *data, const void *buffer,
*
* Returns always 0.
*/
-static int conn_upkeep(struct connectdata *conn,
+static int conn_upkeep(struct Curl_easy *data,
+ struct connectdata *conn,
void *param)
{
/* Param is unused. */
(void)param;
- if(conn->handler->connection_check) {
+ if(conn->handler->connection_check)
/* Do a protocol-specific keepalive check on the connection. */
- conn->handler->connection_check(conn, CONNCHECK_KEEPALIVE);
- }
+ conn->handler->connection_check(data, conn, CONNCHECK_KEEPALIVE);
return 0; /* continue iteration */
}
diff --git a/Utilities/cmcurl/lib/easygetopt.c b/Utilities/cmcurl/lib/easygetopt.c
new file mode 100644
index 000000000..7b2213fb2
--- /dev/null
+++ b/Utilities/cmcurl/lib/easygetopt.c
@@ -0,0 +1,96 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ | |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * ___|___/|_| ______|
+ *
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel.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.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+#include "strcase.h"
+#include "easyoptions.h"
+
+#ifndef CURL_DISABLE_GETOPTIONS
+
+/* Lookups easy options at runtime */
+static 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];
+ do {
+ if(name) {
+ if(strcasecompare(o->name, name))
+ return o;
+ }
+ else {
+ if((o->id == id) && !(o->flags & CURLOT_FLAG_ALIAS))
+ /* don't match alias options */
+ return o;
+ }
+ o++;
+ } while(o->name);
+ }
+ return NULL;
+}
+
+const struct curl_easyoption *curl_easy_option_by_name(const char *name)
+{
+ /* when name is used, the id argument is ignored */
+ return lookup(name, CURLOPT_LASTENTRY);
+}
+
+const struct curl_easyoption *curl_easy_option_by_id(CURLoption id)
+{
+ return lookup(NULL, id);
+}
+
+/* Iterates over available options */
+const struct curl_easyoption *
+curl_easy_option_next(const struct curl_easyoption *prev)
+{
+ if(prev && prev->name) {
+ prev++;
+ if(prev->name)
+ return prev;
+ }
+ else if(!prev)
+ return &Curl_easyopts[0];
+ return NULL;
+}
+
+#else
+const struct curl_easyoption *curl_easy_option_by_name(const char *name)
+{
+ (void)name;
+ return NULL;
+}
+
+const struct curl_easyoption *curl_easy_option_by_id (CURLoption id)
+{
+ (void)id;
+ return NULL;
+}
+
+const struct curl_easyoption *
+curl_easy_option_next(const struct curl_easyoption *prev)
+{
+ (void)prev;
+ return NULL;
+}
+#endif
diff --git a/Utilities/cmcurl/lib/easyif.h b/Utilities/cmcurl/lib/easyif.h
index eda0d62e5..336441828 100644
--- a/Utilities/cmcurl/lib/easyif.h
+++ b/Utilities/cmcurl/lib/easyif.h
@@ -11,7 +11,7 @@
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/easyoptions.c b/Utilities/cmcurl/lib/easyoptions.c
new file mode 100644
index 000000000..b54829ba3
--- /dev/null
+++ b/Utilities/cmcurl/lib/easyoptions.c
@@ -0,0 +1,354 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ | |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * ___|___/|_| ______|
+ *
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel.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.
+ *
+ ***************************************************************************/
+
+/* This source code is generated by optiontable.pl - DO NOT EDIT BY HAND */
+
+#include "curl_setup.h"
+#include "easyoptions.h"
+
+/* all easy setopt options listed in alphabetical order */
+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},
+ {"ADDRESS_SCOPE", CURLOPT_ADDRESS_SCOPE, CURLOT_LONG, 0},
+ {"ALTSVC", CURLOPT_ALTSVC, CURLOT_STRING, 0},
+ {"ALTSVC_CTRL", CURLOPT_ALTSVC_CTRL, CURLOT_LONG, 0},
+ {"APPEND", CURLOPT_APPEND, CURLOT_LONG, 0},
+ {"AUTOREFERER", CURLOPT_AUTOREFERER, CURLOT_LONG, 0},
+ {"AWS_SIGV4", CURLOPT_AWS_SIGV4, CURLOT_STRING, 0},
+ {"BUFFERSIZE", CURLOPT_BUFFERSIZE, CURLOT_LONG, 0},
+ {"CAINFO", CURLOPT_CAINFO, CURLOT_STRING, 0},
+ {"CAPATH", CURLOPT_CAPATH, CURLOT_STRING, 0},
+ {"CERTINFO", CURLOPT_CERTINFO, CURLOT_LONG, 0},
+ {"CHUNK_BGN_FUNCTION", CURLOPT_CHUNK_BGN_FUNCTION, CURLOT_FUNCTION, 0},
+ {"CHUNK_DATA", CURLOPT_CHUNK_DATA, CURLOT_CBPTR, 0},
+ {"CHUNK_END_FUNCTION", CURLOPT_CHUNK_END_FUNCTION, CURLOT_FUNCTION, 0},
+ {"CLOSESOCKETDATA", CURLOPT_CLOSESOCKETDATA, CURLOT_CBPTR, 0},
+ {"CLOSESOCKETFUNCTION", CURLOPT_CLOSESOCKETFUNCTION, CURLOT_FUNCTION, 0},
+ {"CONNECTTIMEOUT", CURLOPT_CONNECTTIMEOUT, CURLOT_LONG, 0},
+ {"CONNECTTIMEOUT_MS", CURLOPT_CONNECTTIMEOUT_MS, CURLOT_LONG, 0},
+ {"CONNECT_ONLY", CURLOPT_CONNECT_ONLY, CURLOT_LONG, 0},
+ {"CONNECT_TO", CURLOPT_CONNECT_TO, CURLOT_SLIST, 0},
+ {"CONV_FROM_NETWORK_FUNCTION", CURLOPT_CONV_FROM_NETWORK_FUNCTION,
+ CURLOT_FUNCTION, 0},
+ {"CONV_FROM_UTF8_FUNCTION", CURLOPT_CONV_FROM_UTF8_FUNCTION,
+ CURLOT_FUNCTION, 0},
+ {"CONV_TO_NETWORK_FUNCTION", CURLOPT_CONV_TO_NETWORK_FUNCTION,
+ CURLOT_FUNCTION, 0},
+ {"COOKIE", CURLOPT_COOKIE, CURLOT_STRING, 0},
+ {"COOKIEFILE", CURLOPT_COOKIEFILE, CURLOT_STRING, 0},
+ {"COOKIEJAR", CURLOPT_COOKIEJAR, CURLOT_STRING, 0},
+ {"COOKIELIST", CURLOPT_COOKIELIST, CURLOT_STRING, 0},
+ {"COOKIESESSION", CURLOPT_COOKIESESSION, CURLOT_LONG, 0},
+ {"COPYPOSTFIELDS", CURLOPT_COPYPOSTFIELDS, CURLOT_OBJECT, 0},
+ {"CRLF", CURLOPT_CRLF, CURLOT_LONG, 0},
+ {"CRLFILE", CURLOPT_CRLFILE, CURLOT_STRING, 0},
+ {"CURLU", CURLOPT_CURLU, CURLOT_OBJECT, 0},
+ {"CUSTOMREQUEST", CURLOPT_CUSTOMREQUEST, CURLOT_STRING, 0},
+ {"DEBUGDATA", CURLOPT_DEBUGDATA, CURLOT_CBPTR, 0},
+ {"DEBUGFUNCTION", CURLOPT_DEBUGFUNCTION, CURLOT_FUNCTION, 0},
+ {"DEFAULT_PROTOCOL", CURLOPT_DEFAULT_PROTOCOL, CURLOT_STRING, 0},
+ {"DIRLISTONLY", CURLOPT_DIRLISTONLY, CURLOT_LONG, 0},
+ {"DISALLOW_USERNAME_IN_URL", CURLOPT_DISALLOW_USERNAME_IN_URL,
+ CURLOT_LONG, 0},
+ {"DNS_CACHE_TIMEOUT", CURLOPT_DNS_CACHE_TIMEOUT, CURLOT_LONG, 0},
+ {"DNS_INTERFACE", CURLOPT_DNS_INTERFACE, CURLOT_STRING, 0},
+ {"DNS_LOCAL_IP4", CURLOPT_DNS_LOCAL_IP4, CURLOT_STRING, 0},
+ {"DNS_LOCAL_IP6", CURLOPT_DNS_LOCAL_IP6, CURLOT_STRING, 0},
+ {"DNS_SERVERS", CURLOPT_DNS_SERVERS, CURLOT_STRING, 0},
+ {"DNS_SHUFFLE_ADDRESSES", CURLOPT_DNS_SHUFFLE_ADDRESSES, CURLOT_LONG, 0},
+ {"DNS_USE_GLOBAL_CACHE", CURLOPT_DNS_USE_GLOBAL_CACHE, CURLOT_LONG, 0},
+ {"DOH_URL", CURLOPT_DOH_URL, CURLOT_STRING, 0},
+ {"EGDSOCKET", CURLOPT_EGDSOCKET, CURLOT_STRING, 0},
+ {"ENCODING", CURLOPT_ACCEPT_ENCODING, CURLOT_STRING, CURLOT_FLAG_ALIAS},
+ {"ERRORBUFFER", CURLOPT_ERRORBUFFER, CURLOT_OBJECT, 0},
+ {"EXPECT_100_TIMEOUT_MS", CURLOPT_EXPECT_100_TIMEOUT_MS, CURLOT_LONG, 0},
+ {"FAILONERROR", CURLOPT_FAILONERROR, CURLOT_LONG, 0},
+ {"FILE", CURLOPT_WRITEDATA, CURLOT_CBPTR, CURLOT_FLAG_ALIAS},
+ {"FILETIME", CURLOPT_FILETIME, CURLOT_LONG, 0},
+ {"FNMATCH_DATA", CURLOPT_FNMATCH_DATA, CURLOT_CBPTR, 0},
+ {"FNMATCH_FUNCTION", CURLOPT_FNMATCH_FUNCTION, CURLOT_FUNCTION, 0},
+ {"FOLLOWLOCATION", CURLOPT_FOLLOWLOCATION, CURLOT_LONG, 0},
+ {"FORBID_REUSE", CURLOPT_FORBID_REUSE, CURLOT_LONG, 0},
+ {"FRESH_CONNECT", CURLOPT_FRESH_CONNECT, CURLOT_LONG, 0},
+ {"FTPAPPEND", CURLOPT_APPEND, CURLOT_LONG, CURLOT_FLAG_ALIAS},
+ {"FTPLISTONLY", CURLOPT_DIRLISTONLY, CURLOT_LONG, CURLOT_FLAG_ALIAS},
+ {"FTPPORT", CURLOPT_FTPPORT, CURLOT_STRING, 0},
+ {"FTPSSLAUTH", CURLOPT_FTPSSLAUTH, CURLOT_VALUES, 0},
+ {"FTP_ACCOUNT", CURLOPT_FTP_ACCOUNT, CURLOT_STRING, 0},
+ {"FTP_ALTERNATIVE_TO_USER", CURLOPT_FTP_ALTERNATIVE_TO_USER,
+ CURLOT_STRING, 0},
+ {"FTP_CREATE_MISSING_DIRS", CURLOPT_FTP_CREATE_MISSING_DIRS,
+ CURLOT_LONG, 0},
+ {"FTP_FILEMETHOD", CURLOPT_FTP_FILEMETHOD, CURLOT_VALUES, 0},
+ {"FTP_RESPONSE_TIMEOUT", CURLOPT_FTP_RESPONSE_TIMEOUT, CURLOT_LONG, 0},
+ {"FTP_SKIP_PASV_IP", CURLOPT_FTP_SKIP_PASV_IP, CURLOT_LONG, 0},
+ {"FTP_SSL", CURLOPT_USE_SSL, CURLOT_VALUES, CURLOT_FLAG_ALIAS},
+ {"FTP_SSL_CCC", CURLOPT_FTP_SSL_CCC, CURLOT_LONG, 0},
+ {"FTP_USE_EPRT", CURLOPT_FTP_USE_EPRT, CURLOT_LONG, 0},
+ {"FTP_USE_EPSV", CURLOPT_FTP_USE_EPSV, CURLOT_LONG, 0},
+ {"FTP_USE_PRET", CURLOPT_FTP_USE_PRET, CURLOT_LONG, 0},
+ {"GSSAPI_DELEGATION", CURLOPT_GSSAPI_DELEGATION, CURLOT_VALUES, 0},
+ {"HAPPY_EYEBALLS_TIMEOUT_MS", CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS,
+ CURLOT_LONG, 0},
+ {"HAPROXYPROTOCOL", CURLOPT_HAPROXYPROTOCOL, CURLOT_LONG, 0},
+ {"HEADER", CURLOPT_HEADER, CURLOT_LONG, 0},
+ {"HEADERDATA", CURLOPT_HEADERDATA, CURLOT_CBPTR, 0},
+ {"HEADERFUNCTION", CURLOPT_HEADERFUNCTION, CURLOT_FUNCTION, 0},
+ {"HEADEROPT", CURLOPT_HEADEROPT, CURLOT_VALUES, 0},
+ {"HSTS", CURLOPT_HSTS, CURLOT_STRING, 0},
+ {"HSTSREADDATA", CURLOPT_HSTSREADDATA, CURLOT_CBPTR, 0},
+ {"HSTSREADFUNCTION", CURLOPT_HSTSREADFUNCTION, CURLOT_FUNCTION, 0},
+ {"HSTSWRITEDATA", CURLOPT_HSTSWRITEDATA, CURLOT_CBPTR, 0},
+ {"HSTSWRITEFUNCTION", CURLOPT_HSTSWRITEFUNCTION, CURLOT_FUNCTION, 0},
+ {"HSTS_CTRL", CURLOPT_HSTS_CTRL, CURLOT_LONG, 0},
+ {"HTTP09_ALLOWED", CURLOPT_HTTP09_ALLOWED, CURLOT_LONG, 0},
+ {"HTTP200ALIASES", CURLOPT_HTTP200ALIASES, CURLOT_SLIST, 0},
+ {"HTTPAUTH", CURLOPT_HTTPAUTH, CURLOT_VALUES, 0},
+ {"HTTPGET", CURLOPT_HTTPGET, CURLOT_LONG, 0},
+ {"HTTPHEADER", CURLOPT_HTTPHEADER, CURLOT_SLIST, 0},
+ {"HTTPPOST", CURLOPT_HTTPPOST, CURLOT_OBJECT, 0},
+ {"HTTPPROXYTUNNEL", CURLOPT_HTTPPROXYTUNNEL, CURLOT_LONG, 0},
+ {"HTTP_CONTENT_DECODING", CURLOPT_HTTP_CONTENT_DECODING, CURLOT_LONG, 0},
+ {"HTTP_TRANSFER_DECODING", CURLOPT_HTTP_TRANSFER_DECODING, CURLOT_LONG, 0},
+ {"HTTP_VERSION", CURLOPT_HTTP_VERSION, CURLOT_VALUES, 0},
+ {"IGNORE_CONTENT_LENGTH", CURLOPT_IGNORE_CONTENT_LENGTH, CURLOT_LONG, 0},
+ {"INFILE", CURLOPT_READDATA, CURLOT_CBPTR, CURLOT_FLAG_ALIAS},
+ {"INFILESIZE", CURLOPT_INFILESIZE, CURLOT_LONG, 0},
+ {"INFILESIZE_LARGE", CURLOPT_INFILESIZE_LARGE, CURLOT_OFF_T, 0},
+ {"INTERFACE", CURLOPT_INTERFACE, CURLOT_STRING, 0},
+ {"INTERLEAVEDATA", CURLOPT_INTERLEAVEDATA, CURLOT_CBPTR, 0},
+ {"INTERLEAVEFUNCTION", CURLOPT_INTERLEAVEFUNCTION, CURLOT_FUNCTION, 0},
+ {"IOCTLDATA", CURLOPT_IOCTLDATA, CURLOT_CBPTR, 0},
+ {"IOCTLFUNCTION", CURLOPT_IOCTLFUNCTION, CURLOT_FUNCTION, 0},
+ {"IPRESOLVE", CURLOPT_IPRESOLVE, CURLOT_VALUES, 0},
+ {"ISSUERCERT", CURLOPT_ISSUERCERT, CURLOT_STRING, 0},
+ {"ISSUERCERT_BLOB", CURLOPT_ISSUERCERT_BLOB, CURLOT_BLOB, 0},
+ {"KEEP_SENDING_ON_ERROR", CURLOPT_KEEP_SENDING_ON_ERROR, CURLOT_LONG, 0},
+ {"KEYPASSWD", CURLOPT_KEYPASSWD, CURLOT_STRING, 0},
+ {"KRB4LEVEL", CURLOPT_KRBLEVEL, CURLOT_STRING, CURLOT_FLAG_ALIAS},
+ {"KRBLEVEL", CURLOPT_KRBLEVEL, CURLOT_STRING, 0},
+ {"LOCALPORT", CURLOPT_LOCALPORT, CURLOT_LONG, 0},
+ {"LOCALPORTRANGE", CURLOPT_LOCALPORTRANGE, CURLOT_LONG, 0},
+ {"LOGIN_OPTIONS", CURLOPT_LOGIN_OPTIONS, CURLOT_STRING, 0},
+ {"LOW_SPEED_LIMIT", CURLOPT_LOW_SPEED_LIMIT, CURLOT_LONG, 0},
+ {"LOW_SPEED_TIME", CURLOPT_LOW_SPEED_TIME, CURLOT_LONG, 0},
+ {"MAIL_AUTH", CURLOPT_MAIL_AUTH, CURLOT_STRING, 0},
+ {"MAIL_FROM", CURLOPT_MAIL_FROM, CURLOT_STRING, 0},
+ {"MAIL_RCPT", CURLOPT_MAIL_RCPT, CURLOT_SLIST, 0},
+ {"MAIL_RCPT_ALLLOWFAILS", CURLOPT_MAIL_RCPT_ALLLOWFAILS, CURLOT_LONG, 0},
+ {"MAXAGE_CONN", CURLOPT_MAXAGE_CONN, CURLOT_LONG, 0},
+ {"MAXCONNECTS", CURLOPT_MAXCONNECTS, CURLOT_LONG, 0},
+ {"MAXFILESIZE", CURLOPT_MAXFILESIZE, CURLOT_LONG, 0},
+ {"MAXFILESIZE_LARGE", CURLOPT_MAXFILESIZE_LARGE, CURLOT_OFF_T, 0},
+ {"MAXREDIRS", CURLOPT_MAXREDIRS, CURLOT_LONG, 0},
+ {"MAX_RECV_SPEED_LARGE", CURLOPT_MAX_RECV_SPEED_LARGE, CURLOT_OFF_T, 0},
+ {"MAX_SEND_SPEED_LARGE", CURLOPT_MAX_SEND_SPEED_LARGE, CURLOT_OFF_T, 0},
+ {"MIMEPOST", CURLOPT_MIMEPOST, CURLOT_OBJECT, 0},
+ {"NETRC", CURLOPT_NETRC, CURLOT_VALUES, 0},
+ {"NETRC_FILE", CURLOPT_NETRC_FILE, CURLOT_STRING, 0},
+ {"NEW_DIRECTORY_PERMS", CURLOPT_NEW_DIRECTORY_PERMS, CURLOT_LONG, 0},
+ {"NEW_FILE_PERMS", CURLOPT_NEW_FILE_PERMS, CURLOT_LONG, 0},
+ {"NOBODY", CURLOPT_NOBODY, CURLOT_LONG, 0},
+ {"NOPROGRESS", CURLOPT_NOPROGRESS, CURLOT_LONG, 0},
+ {"NOPROXY", CURLOPT_NOPROXY, CURLOT_STRING, 0},
+ {"NOSIGNAL", CURLOPT_NOSIGNAL, CURLOT_LONG, 0},
+ {"OPENSOCKETDATA", CURLOPT_OPENSOCKETDATA, CURLOT_CBPTR, 0},
+ {"OPENSOCKETFUNCTION", CURLOPT_OPENSOCKETFUNCTION, CURLOT_FUNCTION, 0},
+ {"PASSWORD", CURLOPT_PASSWORD, CURLOT_STRING, 0},
+ {"PATH_AS_IS", CURLOPT_PATH_AS_IS, CURLOT_LONG, 0},
+ {"PINNEDPUBLICKEY", CURLOPT_PINNEDPUBLICKEY, CURLOT_STRING, 0},
+ {"PIPEWAIT", CURLOPT_PIPEWAIT, CURLOT_LONG, 0},
+ {"PORT", CURLOPT_PORT, CURLOT_LONG, 0},
+ {"POST", CURLOPT_POST, CURLOT_LONG, 0},
+ {"POST301", CURLOPT_POSTREDIR, CURLOT_VALUES, CURLOT_FLAG_ALIAS},
+ {"POSTFIELDS", CURLOPT_POSTFIELDS, CURLOT_OBJECT, 0},
+ {"POSTFIELDSIZE", CURLOPT_POSTFIELDSIZE, CURLOT_LONG, 0},
+ {"POSTFIELDSIZE_LARGE", CURLOPT_POSTFIELDSIZE_LARGE, CURLOT_OFF_T, 0},
+ {"POSTQUOTE", CURLOPT_POSTQUOTE, CURLOT_SLIST, 0},
+ {"POSTREDIR", CURLOPT_POSTREDIR, CURLOT_VALUES, 0},
+ {"PREQUOTE", CURLOPT_PREQUOTE, CURLOT_SLIST, 0},
+ {"PRE_PROXY", CURLOPT_PRE_PROXY, CURLOT_STRING, 0},
+ {"PRIVATE", CURLOPT_PRIVATE, CURLOT_OBJECT, 0},
+ {"PROGRESSDATA", CURLOPT_XFERINFODATA, CURLOT_CBPTR, CURLOT_FLAG_ALIAS},
+ {"PROGRESSFUNCTION", CURLOPT_PROGRESSFUNCTION, CURLOT_FUNCTION, 0},
+ {"PROTOCOLS", CURLOPT_PROTOCOLS, CURLOT_LONG, 0},
+ {"PROXY", CURLOPT_PROXY, CURLOT_STRING, 0},
+ {"PROXYAUTH", CURLOPT_PROXYAUTH, CURLOT_VALUES, 0},
+ {"PROXYHEADER", CURLOPT_PROXYHEADER, CURLOT_SLIST, 0},
+ {"PROXYPASSWORD", CURLOPT_PROXYPASSWORD, CURLOT_STRING, 0},
+ {"PROXYPORT", CURLOPT_PROXYPORT, CURLOT_LONG, 0},
+ {"PROXYTYPE", CURLOPT_PROXYTYPE, CURLOT_VALUES, 0},
+ {"PROXYUSERNAME", CURLOPT_PROXYUSERNAME, CURLOT_STRING, 0},
+ {"PROXYUSERPWD", CURLOPT_PROXYUSERPWD, CURLOT_STRING, 0},
+ {"PROXY_CAINFO", CURLOPT_PROXY_CAINFO, CURLOT_STRING, 0},
+ {"PROXY_CAPATH", CURLOPT_PROXY_CAPATH, CURLOT_STRING, 0},
+ {"PROXY_CRLFILE", CURLOPT_PROXY_CRLFILE, CURLOT_STRING, 0},
+ {"PROXY_ISSUERCERT", CURLOPT_PROXY_ISSUERCERT, CURLOT_STRING, 0},
+ {"PROXY_ISSUERCERT_BLOB", CURLOPT_PROXY_ISSUERCERT_BLOB, CURLOT_BLOB, 0},
+ {"PROXY_KEYPASSWD", CURLOPT_PROXY_KEYPASSWD, CURLOT_STRING, 0},
+ {"PROXY_PINNEDPUBLICKEY", CURLOPT_PROXY_PINNEDPUBLICKEY, CURLOT_STRING, 0},
+ {"PROXY_SERVICE_NAME", CURLOPT_PROXY_SERVICE_NAME, CURLOT_STRING, 0},
+ {"PROXY_SSLCERT", CURLOPT_PROXY_SSLCERT, CURLOT_STRING, 0},
+ {"PROXY_SSLCERTTYPE", CURLOPT_PROXY_SSLCERTTYPE, CURLOT_STRING, 0},
+ {"PROXY_SSLCERT_BLOB", CURLOPT_PROXY_SSLCERT_BLOB, CURLOT_BLOB, 0},
+ {"PROXY_SSLKEY", CURLOPT_PROXY_SSLKEY, CURLOT_STRING, 0},
+ {"PROXY_SSLKEYTYPE", CURLOPT_PROXY_SSLKEYTYPE, CURLOT_STRING, 0},
+ {"PROXY_SSLKEY_BLOB", CURLOPT_PROXY_SSLKEY_BLOB, CURLOT_BLOB, 0},
+ {"PROXY_SSLVERSION", CURLOPT_PROXY_SSLVERSION, CURLOT_VALUES, 0},
+ {"PROXY_SSL_CIPHER_LIST", CURLOPT_PROXY_SSL_CIPHER_LIST, CURLOT_STRING, 0},
+ {"PROXY_SSL_OPTIONS", CURLOPT_PROXY_SSL_OPTIONS, CURLOT_LONG, 0},
+ {"PROXY_SSL_VERIFYHOST", CURLOPT_PROXY_SSL_VERIFYHOST, CURLOT_LONG, 0},
+ {"PROXY_SSL_VERIFYPEER", CURLOPT_PROXY_SSL_VERIFYPEER, CURLOT_LONG, 0},
+ {"PROXY_TLS13_CIPHERS", CURLOPT_PROXY_TLS13_CIPHERS, CURLOT_STRING, 0},
+ {"PROXY_TLSAUTH_PASSWORD", CURLOPT_PROXY_TLSAUTH_PASSWORD,
+ CURLOT_STRING, 0},
+ {"PROXY_TLSAUTH_TYPE", CURLOPT_PROXY_TLSAUTH_TYPE, CURLOT_STRING, 0},
+ {"PROXY_TLSAUTH_USERNAME", CURLOPT_PROXY_TLSAUTH_USERNAME,
+ CURLOT_STRING, 0},
+ {"PROXY_TRANSFER_MODE", CURLOPT_PROXY_TRANSFER_MODE, CURLOT_LONG, 0},
+ {"PUT", CURLOPT_PUT, CURLOT_LONG, 0},
+ {"QUOTE", CURLOPT_QUOTE, CURLOT_SLIST, 0},
+ {"RANDOM_FILE", CURLOPT_RANDOM_FILE, CURLOT_STRING, 0},
+ {"RANGE", CURLOPT_RANGE, CURLOT_STRING, 0},
+ {"READDATA", CURLOPT_READDATA, CURLOT_CBPTR, 0},
+ {"READFUNCTION", CURLOPT_READFUNCTION, CURLOT_FUNCTION, 0},
+ {"REDIR_PROTOCOLS", CURLOPT_REDIR_PROTOCOLS, CURLOT_LONG, 0},
+ {"REFERER", CURLOPT_REFERER, CURLOT_STRING, 0},
+ {"REQUEST_TARGET", CURLOPT_REQUEST_TARGET, CURLOT_STRING, 0},
+ {"RESOLVE", CURLOPT_RESOLVE, CURLOT_SLIST, 0},
+ {"RESOLVER_START_DATA", CURLOPT_RESOLVER_START_DATA, CURLOT_CBPTR, 0},
+ {"RESOLVER_START_FUNCTION", CURLOPT_RESOLVER_START_FUNCTION,
+ CURLOT_FUNCTION, 0},
+ {"RESUME_FROM", CURLOPT_RESUME_FROM, CURLOT_LONG, 0},
+ {"RESUME_FROM_LARGE", CURLOPT_RESUME_FROM_LARGE, CURLOT_OFF_T, 0},
+ {"RTSPHEADER", CURLOPT_HTTPHEADER, CURLOT_SLIST, CURLOT_FLAG_ALIAS},
+ {"RTSP_CLIENT_CSEQ", CURLOPT_RTSP_CLIENT_CSEQ, CURLOT_LONG, 0},
+ {"RTSP_REQUEST", CURLOPT_RTSP_REQUEST, CURLOT_VALUES, 0},
+ {"RTSP_SERVER_CSEQ", CURLOPT_RTSP_SERVER_CSEQ, CURLOT_LONG, 0},
+ {"RTSP_SESSION_ID", CURLOPT_RTSP_SESSION_ID, CURLOT_STRING, 0},
+ {"RTSP_STREAM_URI", CURLOPT_RTSP_STREAM_URI, CURLOT_STRING, 0},
+ {"RTSP_TRANSPORT", CURLOPT_RTSP_TRANSPORT, CURLOT_STRING, 0},
+ {"SASL_AUTHZID", CURLOPT_SASL_AUTHZID, CURLOT_STRING, 0},
+ {"SASL_IR", CURLOPT_SASL_IR, CURLOT_LONG, 0},
+ {"SEEKDATA", CURLOPT_SEEKDATA, CURLOT_CBPTR, 0},
+ {"SEEKFUNCTION", CURLOPT_SEEKFUNCTION, CURLOT_FUNCTION, 0},
+ {"SERVER_RESPONSE_TIMEOUT", CURLOPT_FTP_RESPONSE_TIMEOUT,
+ CURLOT_LONG, CURLOT_FLAG_ALIAS},
+ {"SERVICE_NAME", CURLOPT_SERVICE_NAME, CURLOT_STRING, 0},
+ {"SHARE", CURLOPT_SHARE, CURLOT_OBJECT, 0},
+ {"SOCKOPTDATA", CURLOPT_SOCKOPTDATA, CURLOT_CBPTR, 0},
+ {"SOCKOPTFUNCTION", CURLOPT_SOCKOPTFUNCTION, CURLOT_FUNCTION, 0},
+ {"SOCKS5_AUTH", CURLOPT_SOCKS5_AUTH, CURLOT_LONG, 0},
+ {"SOCKS5_GSSAPI_NEC", CURLOPT_SOCKS5_GSSAPI_NEC, CURLOT_LONG, 0},
+ {"SOCKS5_GSSAPI_SERVICE", CURLOPT_SOCKS5_GSSAPI_SERVICE, CURLOT_STRING, 0},
+ {"SSH_AUTH_TYPES", CURLOPT_SSH_AUTH_TYPES, CURLOT_VALUES, 0},
+ {"SSH_COMPRESSION", CURLOPT_SSH_COMPRESSION, CURLOT_LONG, 0},
+ {"SSH_HOST_PUBLIC_KEY_MD5", CURLOPT_SSH_HOST_PUBLIC_KEY_MD5,
+ CURLOT_STRING, 0},
+ {"SSH_KEYDATA", CURLOPT_SSH_KEYDATA, CURLOT_CBPTR, 0},
+ {"SSH_KEYFUNCTION", CURLOPT_SSH_KEYFUNCTION, CURLOT_FUNCTION, 0},
+ {"SSH_KNOWNHOSTS", CURLOPT_SSH_KNOWNHOSTS, CURLOT_STRING, 0},
+ {"SSH_PRIVATE_KEYFILE", CURLOPT_SSH_PRIVATE_KEYFILE, CURLOT_STRING, 0},
+ {"SSH_PUBLIC_KEYFILE", CURLOPT_SSH_PUBLIC_KEYFILE, CURLOT_STRING, 0},
+ {"SSLCERT", CURLOPT_SSLCERT, CURLOT_STRING, 0},
+ {"SSLCERTPASSWD", CURLOPT_KEYPASSWD, CURLOT_STRING, CURLOT_FLAG_ALIAS},
+ {"SSLCERTTYPE", CURLOPT_SSLCERTTYPE, CURLOT_STRING, 0},
+ {"SSLCERT_BLOB", CURLOPT_SSLCERT_BLOB, CURLOT_BLOB, 0},
+ {"SSLENGINE", CURLOPT_SSLENGINE, CURLOT_STRING, 0},
+ {"SSLENGINE_DEFAULT", CURLOPT_SSLENGINE_DEFAULT, CURLOT_LONG, 0},
+ {"SSLKEY", CURLOPT_SSLKEY, CURLOT_STRING, 0},
+ {"SSLKEYPASSWD", CURLOPT_KEYPASSWD, CURLOT_STRING, CURLOT_FLAG_ALIAS},
+ {"SSLKEYTYPE", CURLOPT_SSLKEYTYPE, CURLOT_STRING, 0},
+ {"SSLKEY_BLOB", CURLOPT_SSLKEY_BLOB, CURLOT_BLOB, 0},
+ {"SSLVERSION", CURLOPT_SSLVERSION, CURLOT_VALUES, 0},
+ {"SSL_CIPHER_LIST", CURLOPT_SSL_CIPHER_LIST, CURLOT_STRING, 0},
+ {"SSL_CTX_DATA", CURLOPT_SSL_CTX_DATA, CURLOT_CBPTR, 0},
+ {"SSL_CTX_FUNCTION", CURLOPT_SSL_CTX_FUNCTION, CURLOT_FUNCTION, 0},
+ {"SSL_EC_CURVES", CURLOPT_SSL_EC_CURVES, CURLOT_STRING, 0},
+ {"SSL_ENABLE_ALPN", CURLOPT_SSL_ENABLE_ALPN, CURLOT_LONG, 0},
+ {"SSL_ENABLE_NPN", CURLOPT_SSL_ENABLE_NPN, CURLOT_LONG, 0},
+ {"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_VERIFYHOST", CURLOPT_SSL_VERIFYHOST, CURLOT_LONG, 0},
+ {"SSL_VERIFYPEER", CURLOPT_SSL_VERIFYPEER, CURLOT_LONG, 0},
+ {"SSL_VERIFYSTATUS", CURLOPT_SSL_VERIFYSTATUS, CURLOT_LONG, 0},
+ {"STDERR", CURLOPT_STDERR, CURLOT_OBJECT, 0},
+ {"STREAM_DEPENDS", CURLOPT_STREAM_DEPENDS, CURLOT_OBJECT, 0},
+ {"STREAM_DEPENDS_E", CURLOPT_STREAM_DEPENDS_E, CURLOT_OBJECT, 0},
+ {"STREAM_WEIGHT", CURLOPT_STREAM_WEIGHT, CURLOT_LONG, 0},
+ {"SUPPRESS_CONNECT_HEADERS", CURLOPT_SUPPRESS_CONNECT_HEADERS,
+ CURLOT_LONG, 0},
+ {"TCP_FASTOPEN", CURLOPT_TCP_FASTOPEN, CURLOT_LONG, 0},
+ {"TCP_KEEPALIVE", CURLOPT_TCP_KEEPALIVE, CURLOT_LONG, 0},
+ {"TCP_KEEPIDLE", CURLOPT_TCP_KEEPIDLE, CURLOT_LONG, 0},
+ {"TCP_KEEPINTVL", CURLOPT_TCP_KEEPINTVL, CURLOT_LONG, 0},
+ {"TCP_NODELAY", CURLOPT_TCP_NODELAY, CURLOT_LONG, 0},
+ {"TELNETOPTIONS", CURLOPT_TELNETOPTIONS, CURLOT_SLIST, 0},
+ {"TFTP_BLKSIZE", CURLOPT_TFTP_BLKSIZE, CURLOT_LONG, 0},
+ {"TFTP_NO_OPTIONS", CURLOPT_TFTP_NO_OPTIONS, CURLOT_LONG, 0},
+ {"TIMECONDITION", CURLOPT_TIMECONDITION, CURLOT_VALUES, 0},
+ {"TIMEOUT", CURLOPT_TIMEOUT, CURLOT_LONG, 0},
+ {"TIMEOUT_MS", CURLOPT_TIMEOUT_MS, CURLOT_LONG, 0},
+ {"TIMEVALUE", CURLOPT_TIMEVALUE, CURLOT_LONG, 0},
+ {"TIMEVALUE_LARGE", CURLOPT_TIMEVALUE_LARGE, CURLOT_OFF_T, 0},
+ {"TLS13_CIPHERS", CURLOPT_TLS13_CIPHERS, CURLOT_STRING, 0},
+ {"TLSAUTH_PASSWORD", CURLOPT_TLSAUTH_PASSWORD, CURLOT_STRING, 0},
+ {"TLSAUTH_TYPE", CURLOPT_TLSAUTH_TYPE, CURLOT_STRING, 0},
+ {"TLSAUTH_USERNAME", CURLOPT_TLSAUTH_USERNAME, CURLOT_STRING, 0},
+ {"TRAILERDATA", CURLOPT_TRAILERDATA, CURLOT_CBPTR, 0},
+ {"TRAILERFUNCTION", CURLOPT_TRAILERFUNCTION, CURLOT_FUNCTION, 0},
+ {"TRANSFERTEXT", CURLOPT_TRANSFERTEXT, CURLOT_LONG, 0},
+ {"TRANSFER_ENCODING", CURLOPT_TRANSFER_ENCODING, CURLOT_LONG, 0},
+ {"UNIX_SOCKET_PATH", CURLOPT_UNIX_SOCKET_PATH, CURLOT_STRING, 0},
+ {"UNRESTRICTED_AUTH", CURLOPT_UNRESTRICTED_AUTH, CURLOT_LONG, 0},
+ {"UPKEEP_INTERVAL_MS", CURLOPT_UPKEEP_INTERVAL_MS, CURLOT_LONG, 0},
+ {"UPLOAD", CURLOPT_UPLOAD, CURLOT_LONG, 0},
+ {"UPLOAD_BUFFERSIZE", CURLOPT_UPLOAD_BUFFERSIZE, CURLOT_LONG, 0},
+ {"URL", CURLOPT_URL, CURLOT_STRING, 0},
+ {"USERAGENT", CURLOPT_USERAGENT, CURLOT_STRING, 0},
+ {"USERNAME", CURLOPT_USERNAME, CURLOT_STRING, 0},
+ {"USERPWD", CURLOPT_USERPWD, CURLOT_STRING, 0},
+ {"USE_SSL", CURLOPT_USE_SSL, CURLOT_VALUES, 0},
+ {"VERBOSE", CURLOPT_VERBOSE, CURLOT_LONG, 0},
+ {"WILDCARDMATCH", CURLOPT_WILDCARDMATCH, CURLOT_LONG, 0},
+ {"WRITEDATA", CURLOPT_WRITEDATA, CURLOT_CBPTR, 0},
+ {"WRITEFUNCTION", CURLOPT_WRITEFUNCTION, CURLOT_FUNCTION, 0},
+ {"WRITEHEADER", CURLOPT_HEADERDATA, CURLOT_CBPTR, CURLOT_FLAG_ALIAS},
+ {"XFERINFODATA", CURLOPT_XFERINFODATA, CURLOT_CBPTR, 0},
+ {"XFERINFOFUNCTION", CURLOPT_XFERINFOFUNCTION, CURLOT_FUNCTION, 0},
+ {"XOAUTH2_BEARER", CURLOPT_XOAUTH2_BEARER, CURLOT_STRING, 0},
+ {NULL, CURLOPT_LASTENTRY, 0, 0} /* end of table */
+};
+
+#ifdef DEBUGBUILD
+/*
+ * Curl_easyopts_check() is a debug-only function that returns non-zero
+ * if this source file is not in sync with the options listed in curl/curl.h
+ */
+int Curl_easyopts_check(void)
+{
+ return ((CURLOPT_LASTENTRY%10000) != (305 + 1));
+}
+#endif
diff --git a/Utilities/cmcurl/lib/easyoptions.h b/Utilities/cmcurl/lib/easyoptions.h
new file mode 100644
index 000000000..91e11908b
--- /dev/null
+++ b/Utilities/cmcurl/lib/easyoptions.h
@@ -0,0 +1,35 @@
+#ifndef HEADER_CURL_EASYOPTIONS_H
+#define HEADER_CURL_EASYOPTIONS_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.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.
+ *
+ ***************************************************************************/
+
+/* should probably go into the public header */
+
+#include <curl/curl.h>
+
+/* generated table with all easy options */
+extern struct curl_easyoption Curl_easyopts[];
+
+#ifdef DEBUGBUILD
+int Curl_easyopts_check(void);
+#endif
+#endif
diff --git a/Utilities/cmcurl/lib/escape.c b/Utilities/cmcurl/lib/escape.c
index 2bea145f4..683b6fc4a 100644
--- a/Utilities/cmcurl/lib/escape.c
+++ b/Utilities/cmcurl/lib/escape.c
@@ -9,7 +9,7 @@
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -86,7 +86,7 @@ char *curl_easy_escape(struct Curl_easy *data, const char *string,
if(inlength < 0)
return NULL;
- Curl_dyn_init(&d, CURL_MAX_INPUT_LENGTH);
+ Curl_dyn_init(&d, CURL_MAX_INPUT_LENGTH * 3);
length = (inlength?(size_t)inlength:strlen(string));
if(!length)
diff --git a/Utilities/cmcurl/lib/escape.h b/Utilities/cmcurl/lib/escape.h
index 586db7e67..46cb59039 100644
--- a/Utilities/cmcurl/lib/escape.h
+++ b/Utilities/cmcurl/lib/escape.h
@@ -11,7 +11,7 @@
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/file.c b/Utilities/cmcurl/lib/file.c
index cd3e49c33..dd8a1fd12 100644
--- a/Utilities/cmcurl/lib/file.c
+++ b/Utilities/cmcurl/lib/file.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -67,8 +67,7 @@
#include "curl_memory.h"
#include "memdebug.h"
-#if defined(WIN32) || defined(MSDOS) || defined(__EMX__) || \
- defined(__SYMBIAN32__)
+#if defined(WIN32) || defined(MSDOS) || defined(__EMX__)
#define DOS_FILESYSTEM 1
#endif
@@ -82,13 +81,15 @@
* Forward declarations.
*/
-static CURLcode file_do(struct connectdata *, bool *done);
-static CURLcode file_done(struct connectdata *conn,
+static CURLcode file_do(struct Curl_easy *data, bool *done);
+static CURLcode file_done(struct Curl_easy *data,
CURLcode status, bool premature);
-static CURLcode file_connect(struct connectdata *conn, bool *done);
-static CURLcode file_disconnect(struct connectdata *conn,
+static CURLcode file_connect(struct Curl_easy *data, bool *done);
+static CURLcode file_disconnect(struct Curl_easy *data,
+ struct connectdata *conn,
bool dead_connection);
-static CURLcode file_setup_connection(struct connectdata *conn);
+static CURLcode file_setup_connection(struct Curl_easy *data,
+ struct connectdata *conn);
/*
* FILE scheme handler.
@@ -112,15 +113,18 @@ const struct Curl_handler Curl_handler_file = {
ZERO_NULL, /* connection_check */
0, /* defport */
CURLPROTO_FILE, /* protocol */
+ CURLPROTO_FILE, /* family */
PROTOPT_NONETWORK | PROTOPT_NOURLQUERY /* flags */
};
-static CURLcode file_setup_connection(struct connectdata *conn)
+static CURLcode file_setup_connection(struct Curl_easy *data,
+ struct connectdata *conn)
{
+ (void)conn;
/* allocate the FILE specific struct */
- conn->data->req.protop = calloc(1, sizeof(struct FILEPROTO));
- if(!conn->data->req.protop)
+ data->req.p.file = calloc(1, sizeof(struct FILEPROTO));
+ if(!data->req.p.file)
return CURLE_OUT_OF_MEMORY;
return CURLE_OK;
@@ -131,11 +135,10 @@ static CURLcode file_setup_connection(struct connectdata *conn)
* do protocol-specific actions at connect-time. We emulate a
* connect-then-transfer protocol and "connect" to the file here
*/
-static CURLcode file_connect(struct connectdata *conn, bool *done)
+static CURLcode file_connect(struct Curl_easy *data, bool *done)
{
- struct Curl_easy *data = conn->data;
char *real_path;
- struct FILEPROTO *file = data->req.protop;
+ struct FILEPROTO *file = data->req.p.file;
int fd;
#ifdef DOS_FILESYSTEM
size_t i;
@@ -198,7 +201,7 @@ static CURLcode file_connect(struct connectdata *conn, bool *done)
file->fd = fd;
if(!data->set.upload && (fd == -1)) {
failf(data, "Couldn't open file %s", data->state.up.path);
- file_done(conn, CURLE_FILE_COULDNT_READ_FILE, FALSE);
+ file_done(data, CURLE_FILE_COULDNT_READ_FILE, FALSE);
return CURLE_FILE_COULDNT_READ_FILE;
}
*done = TRUE;
@@ -206,10 +209,10 @@ static CURLcode file_connect(struct connectdata *conn, bool *done)
return CURLE_OK;
}
-static CURLcode file_done(struct connectdata *conn,
- CURLcode status, bool premature)
+static CURLcode file_done(struct Curl_easy *data,
+ CURLcode status, bool premature)
{
- struct FILEPROTO *file = conn->data->req.protop;
+ struct FILEPROTO *file = data->req.p.file;
(void)status; /* not used */
(void)premature; /* not used */
@@ -224,21 +227,13 @@ static CURLcode file_done(struct connectdata *conn,
return CURLE_OK;
}
-static CURLcode file_disconnect(struct connectdata *conn,
+static CURLcode file_disconnect(struct Curl_easy *data,
+ struct connectdata *conn,
bool dead_connection)
{
- struct FILEPROTO *file = conn->data->req.protop;
(void)dead_connection; /* not used */
-
- if(file) {
- Curl_safefree(file->freepath);
- file->path = NULL;
- if(file->fd != -1)
- close(file->fd);
- file->fd = -1;
- }
-
- return CURLE_OK;
+ (void)conn;
+ return file_done(data, 0, 0);
}
#ifdef DOS_FILESYSTEM
@@ -247,14 +242,13 @@ static CURLcode file_disconnect(struct connectdata *conn,
#define DIRSEP '/'
#endif
-static CURLcode file_upload(struct connectdata *conn)
+static CURLcode file_upload(struct Curl_easy *data)
{
- struct FILEPROTO *file = conn->data->req.protop;
+ struct FILEPROTO *file = data->req.p.file;
const char *dir = strchr(file->path, DIRSEP);
int fd;
int mode;
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
char *buf = data->state.buffer;
curl_off_t bytecount = 0;
struct_stat file_stat;
@@ -264,7 +258,7 @@ static CURLcode file_upload(struct connectdata *conn)
* Since FILE: doesn't do the full init, we need to provide some extra
* assignments here.
*/
- conn->data->req.upload_fromhere = buf;
+ data->req.upload_fromhere = buf;
if(!dir)
return CURLE_FILE_COULDNT_READ_FILE; /* fix: better error code */
@@ -283,7 +277,7 @@ static CURLcode file_upload(struct connectdata *conn)
else
mode = MODE_DEFAULT|O_TRUNC;
- fd = open(file->path, mode, conn->data->set.new_file_perms);
+ fd = open(file->path, mode, data->set.new_file_perms);
if(fd < 0) {
failf(data, "Can't open %s for writing", file->path);
return CURLE_WRITE_ERROR;
@@ -307,7 +301,7 @@ static CURLcode file_upload(struct connectdata *conn)
size_t nread;
size_t nwrite;
size_t readcount;
- result = Curl_fillreadbuffer(conn, data->set.buffer_size, &readcount);
+ result = Curl_fillreadbuffer(data, data->set.buffer_size, &readcount);
if(result)
break;
@@ -343,12 +337,12 @@ static CURLcode file_upload(struct connectdata *conn)
Curl_pgrsSetUploadCounter(data, bytecount);
- if(Curl_pgrsUpdate(conn))
+ if(Curl_pgrsUpdate(data))
result = CURLE_ABORTED_BY_CALLBACK;
else
result = Curl_speedcheck(data, Curl_now());
}
- if(!result && Curl_pgrsUpdate(conn))
+ if(!result && Curl_pgrsUpdate(data))
result = CURLE_ABORTED_BY_CALLBACK;
close(fd);
@@ -364,7 +358,7 @@ static CURLcode file_upload(struct connectdata *conn)
* opposed to sockets) we instead perform the whole do-operation in this
* function.
*/
-static CURLcode file_do(struct connectdata *conn, bool *done)
+static CURLcode file_do(struct Curl_easy *data, bool *done)
{
/* This implementation ignores the host name in conformance with
RFC 1738. Only local files (reachable via the standard file system)
@@ -375,10 +369,9 @@ static CURLcode file_do(struct connectdata *conn, bool *done)
struct_stat statbuf; /* struct_stat instead of struct stat just to allow the
Windows version to have a different struct without
having to redefine the simple word 'stat' */
- curl_off_t expected_size = 0;
+ curl_off_t expected_size = -1;
bool size_known;
bool fstated = FALSE;
- struct Curl_easy *data = conn->data;
char *buf = data->state.buffer;
curl_off_t bytecount = 0;
int fd;
@@ -389,17 +382,17 @@ static CURLcode file_do(struct connectdata *conn, bool *done)
Curl_pgrsStartNow(data);
if(data->set.upload)
- return file_upload(conn);
+ return file_upload(data);
- file = conn->data->req.protop;
+ file = data->req.p.file;
/* get the fd from the connection phase */
fd = file->fd;
/* VMS: This only works reliable for STREAMLF files */
if(-1 != fstat(fd, &statbuf)) {
- /* we could stat it, then read out the size */
- expected_size = statbuf.st_size;
+ if(!S_ISDIR(statbuf.st_mode))
+ expected_size = statbuf.st_size;
/* and store the modification time */
data->info.filetime = statbuf.st_mtime;
fstated = TRUE;
@@ -417,14 +410,16 @@ static CURLcode file_do(struct connectdata *conn, bool *done)
struct tm buffer;
const struct tm *tm = &buffer;
char header[80];
- msnprintf(header, sizeof(header),
- "Content-Length: %" CURL_FORMAT_CURL_OFF_T "\r\n",
- expected_size);
- result = Curl_client_write(conn, CLIENTWRITE_HEADER, header, 0);
- if(result)
- return result;
+ if(expected_size >= 0) {
+ msnprintf(header, sizeof(header),
+ "Content-Length: %" CURL_FORMAT_CURL_OFF_T "\r\n",
+ expected_size);
+ result = Curl_client_write(data, CLIENTWRITE_HEADER, header, 0);
+ if(result)
+ return result;
+ }
- result = Curl_client_write(conn, CLIENTWRITE_HEADER,
+ result = Curl_client_write(data, CLIENTWRITE_HEADER,
(char *)"Accept-ranges: bytes\r\n", 0);
if(result)
return result;
@@ -445,7 +440,7 @@ static CURLcode file_do(struct connectdata *conn, bool *done)
tm->tm_min,
tm->tm_sec,
data->set.opt_no_body ? "": "\r\n");
- result = Curl_client_write(conn, CLIENTWRITE_HEADER, header, 0);
+ result = Curl_client_write(data, CLIENTWRITE_HEADER, header, 0);
if(result)
return result;
/* set the file size to make it available post transfer */
@@ -455,7 +450,7 @@ static CURLcode file_do(struct connectdata *conn, bool *done)
}
/* Check whether file range has been specified */
- result = Curl_range(conn);
+ result = Curl_range(data);
if(result)
return result;
@@ -524,18 +519,18 @@ static CURLcode file_do(struct connectdata *conn, bool *done)
if(size_known)
expected_size -= nread;
- result = Curl_client_write(conn, CLIENTWRITE_BODY, buf, nread);
+ result = Curl_client_write(data, CLIENTWRITE_BODY, buf, nread);
if(result)
return result;
Curl_pgrsSetDownloadCounter(data, bytecount);
- if(Curl_pgrsUpdate(conn))
+ if(Curl_pgrsUpdate(data))
result = CURLE_ABORTED_BY_CALLBACK;
else
result = Curl_speedcheck(data, Curl_now());
}
- if(Curl_pgrsUpdate(conn))
+ if(Curl_pgrsUpdate(data))
result = CURLE_ABORTED_BY_CALLBACK;
return result;
diff --git a/Utilities/cmcurl/lib/file.h b/Utilities/cmcurl/lib/file.h
index f6b74a7f7..338f92e46 100644
--- a/Utilities/cmcurl/lib/file.h
+++ b/Utilities/cmcurl/lib/file.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
diff --git a/Utilities/cmcurl/lib/fileinfo.c b/Utilities/cmcurl/lib/fileinfo.c
index 2630c9e46..b7e9f0f5e 100644
--- a/Utilities/cmcurl/lib/fileinfo.c
+++ b/Utilities/cmcurl/lib/fileinfo.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2010 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2010 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/fileinfo.h b/Utilities/cmcurl/lib/fileinfo.h
index f4d8f3b90..5ae23ad4a 100644
--- a/Utilities/cmcurl/lib/fileinfo.h
+++ b/Utilities/cmcurl/lib/fileinfo.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2010 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2010 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -27,7 +27,7 @@
struct fileinfo {
struct curl_fileinfo info;
- struct curl_llist_element list;
+ struct Curl_llist_element list;
};
struct fileinfo *Curl_fileinfo_alloc(void);
diff --git a/Utilities/cmcurl/lib/formdata.c b/Utilities/cmcurl/lib/formdata.c
index 1cab2c5c2..769f06a70 100644
--- a/Utilities/cmcurl/lib/formdata.c
+++ b/Utilities/cmcurl/lib/formdata.c
@@ -9,7 +9,7 @@
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/formdata.h b/Utilities/cmcurl/lib/formdata.h
index 3766d38f2..09c6e9c28 100644
--- a/Utilities/cmcurl/lib/formdata.h
+++ b/Utilities/cmcurl/lib/formdata.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -29,22 +29,22 @@
/* used by FormAdd for temporary storage */
struct FormInfo {
char *name;
- bool name_alloc;
size_t namelength;
char *value;
- bool value_alloc;
curl_off_t contentslength;
char *contenttype;
- bool contenttype_alloc;
long flags;
char *buffer; /* pointer to existing buffer used for file upload */
size_t bufferlength;
char *showfilename; /* The file name to show. If not set, the actual
file name will be used */
- bool showfilename_alloc;
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;
};
CURLcode Curl_getformdata(struct Curl_easy *data,
diff --git a/Utilities/cmcurl/lib/ftp.c b/Utilities/cmcurl/lib/ftp.c
index 7d805fac8..f8f970cc8 100644
--- a/Utilities/cmcurl/lib/ftp.c
+++ b/Utilities/cmcurl/lib/ftp.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -59,7 +59,7 @@
#include "fileinfo.h"
#include "ftplistparser.h"
#include "curl_range.h"
-#include "curl_sec.h"
+#include "curl_krb5.h"
#include "strtoofft.h"
#include "strcase.h"
#include "vtls/vtls.h"
@@ -96,68 +96,65 @@
/* Local API functions */
#ifndef DEBUGBUILD
-static void _state(struct connectdata *conn,
+static void _state(struct Curl_easy *data,
ftpstate newstate);
#define state(x,y) _state(x,y)
#else
-static void _state(struct connectdata *conn,
+static void _state(struct Curl_easy *data,
ftpstate newstate,
int lineno);
#define state(x,y) _state(x,y,__LINE__)
#endif
-static CURLcode ftp_sendquote(struct connectdata *conn,
+static CURLcode ftp_sendquote(struct Curl_easy *data,
+ struct connectdata *conn,
struct curl_slist *quote);
-static CURLcode ftp_quit(struct connectdata *conn);
-static CURLcode ftp_parse_url_path(struct connectdata *conn);
-static CURLcode ftp_regular_transfer(struct connectdata *conn, bool *done);
+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);
#ifndef CURL_DISABLE_VERBOSE_STRINGS
-static void ftp_pasv_verbose(struct connectdata *conn,
+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 connectdata *conn);
-static CURLcode ftp_state_mdtm(struct connectdata *conn);
-static CURLcode ftp_state_quote(struct connectdata *conn,
+static CURLcode ftp_state_prepare_transfer(struct Curl_easy *data);
+static CURLcode ftp_state_mdtm(struct Curl_easy *data);
+static CURLcode ftp_state_quote(struct Curl_easy *data,
bool init, ftpstate instate);
-static CURLcode ftp_nb_type(struct connectdata *conn,
+static CURLcode ftp_nb_type(struct Curl_easy *data,
+ struct connectdata *conn,
bool ascii, ftpstate newstate);
static int ftp_need_type(struct connectdata *conn,
bool ascii);
-static CURLcode ftp_do(struct connectdata *conn, bool *done);
-static CURLcode ftp_done(struct connectdata *conn,
+static CURLcode ftp_do(struct Curl_easy *data, bool *done);
+static CURLcode ftp_done(struct Curl_easy *data,
CURLcode, bool premature);
-static CURLcode ftp_connect(struct connectdata *conn, bool *done);
-static CURLcode ftp_disconnect(struct connectdata *conn, bool dead_connection);
-static CURLcode ftp_do_more(struct connectdata *conn, int *completed);
-static CURLcode ftp_multi_statemach(struct connectdata *conn, bool *done);
-static int ftp_getsock(struct connectdata *conn, curl_socket_t *socks);
-static int ftp_domore_getsock(struct connectdata *conn, curl_socket_t *socks);
-static CURLcode ftp_doing(struct connectdata *conn,
+static CURLcode ftp_connect(struct Curl_easy *data, bool *done);
+static CURLcode ftp_disconnect(struct Curl_easy *data,
+ struct connectdata *conn, bool dead_connection);
+static CURLcode ftp_do_more(struct Curl_easy *data, int *completed);
+static CURLcode ftp_multi_statemach(struct Curl_easy *data, bool *done);
+static int ftp_getsock(struct Curl_easy *data, struct connectdata *conn,
+ curl_socket_t *socks);
+static int ftp_domore_getsock(struct Curl_easy *data,
+ struct connectdata *conn, curl_socket_t *socks);
+static CURLcode ftp_doing(struct Curl_easy *data,
bool *dophase_done);
-static CURLcode ftp_setup_connection(struct connectdata *conn);
-
-static CURLcode init_wc_data(struct connectdata *conn);
-static CURLcode wc_statemach(struct connectdata *conn);
-
+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 void wc_data_dtor(void *ptr);
-
-static CURLcode ftp_state_retr(struct connectdata *conn, curl_off_t filesize);
-
-static CURLcode ftp_readresp(curl_socket_t sockfd,
+static CURLcode ftp_state_retr(struct Curl_easy *data, curl_off_t filesize);
+static CURLcode ftp_readresp(struct Curl_easy *data,
+ curl_socket_t sockfd,
struct pingpong *pp,
int *ftpcode,
size_t *size);
-static CURLcode ftp_dophase_done(struct connectdata *conn,
+static CURLcode ftp_dophase_done(struct Curl_easy *data,
bool connected);
-/* easy-to-use macro: */
-#define PPSENDF(x,y,z) result = Curl_pp_sendf(x,y,z); \
- if(result) \
- return result
-
-
/*
* FTP protocol handler.
*/
@@ -180,6 +177,7 @@ const struct Curl_handler Curl_handler_ftp = {
ZERO_NULL, /* connection_check */
PORT_FTP, /* defport */
CURLPROTO_FTP, /* protocol */
+ CURLPROTO_FTP, /* family */
PROTOPT_DUAL | PROTOPT_CLOSEACTION | PROTOPT_NEEDSPWD |
PROTOPT_NOURLQUERY | PROTOPT_PROXY_AS_HTTP |
PROTOPT_WILDCARD /* flags */
@@ -209,15 +207,17 @@ const struct Curl_handler Curl_handler_ftps = {
ZERO_NULL, /* connection_check */
PORT_FTPS, /* defport */
CURLPROTO_FTPS, /* protocol */
+ CURLPROTO_FTP, /* family */
PROTOPT_SSL | PROTOPT_DUAL | PROTOPT_CLOSEACTION |
PROTOPT_NEEDSPWD | PROTOPT_NOURLQUERY | PROTOPT_WILDCARD /* flags */
};
#endif
-static void close_secondarysocket(struct connectdata *conn)
+static void close_secondarysocket(struct Curl_easy *data,
+ struct connectdata *conn)
{
if(CURL_SOCKET_BAD != conn->sock[SECONDARYSOCKET]) {
- Curl_closesocket(conn, conn->sock[SECONDARYSOCKET]);
+ Curl_closesocket(data, conn, conn->sock[SECONDARYSOCKET]);
conn->sock[SECONDARYSOCKET] = CURL_SOCKET_BAD;
}
conn->bits.tcpconnect[SECONDARYSOCKET] = FALSE;
@@ -264,9 +264,9 @@ static void freedirs(struct ftp_conn *ftpc)
* called to accept the connection and close the listening socket
*
*/
-static CURLcode AcceptServerConnect(struct connectdata *conn)
+static CURLcode AcceptServerConnect(struct Curl_easy *data)
{
- struct Curl_easy *data = conn->data;
+ struct connectdata *conn = data->conn;
curl_socket_t sock = conn->sock[SECONDARYSOCKET];
curl_socket_t s = CURL_SOCKET_BAD;
#ifdef ENABLE_IPV6
@@ -281,7 +281,7 @@ static CURLcode AcceptServerConnect(struct connectdata *conn)
s = accept(sock, (struct sockaddr *) &add, &size);
}
- Curl_closesocket(conn, sock); /* close the first socket */
+ Curl_closesocket(data, conn, sock); /* close the first socket */
if(CURL_SOCKET_BAD == s) {
failf(data, "Error accept()ing server connect");
@@ -307,7 +307,7 @@ static CURLcode AcceptServerConnect(struct connectdata *conn)
Curl_set_in_callback(data, false);
if(error) {
- close_secondarysocket(conn);
+ close_secondarysocket(data, conn);
return CURLE_ABORTED_BY_CALLBACK;
}
}
@@ -363,9 +363,9 @@ static timediff_t ftp_timeleft_accept(struct Curl_easy *data)
* connection for a negative response regarding a failure in connecting
*
*/
-static CURLcode ReceivedServerConnect(struct connectdata *conn, bool *received)
+static CURLcode ReceivedServerConnect(struct Curl_easy *data, bool *received)
{
- struct Curl_easy *data = conn->data;
+ struct connectdata *conn = data->conn;
curl_socket_t ctrl_sock = conn->sock[FIRSTSOCKET];
curl_socket_t data_sock = conn->sock[SECONDARYSOCKET];
struct ftp_conn *ftpc = &conn->proto.ftpc;
@@ -389,7 +389,7 @@ static CURLcode ReceivedServerConnect(struct connectdata *conn, bool *received)
if(pp->cache_size && pp->cache && pp->cache[0] > '3') {
/* Data connection could not be established, let's return */
infof(data, "There is negative response in cache while serv connect\n");
- (void)Curl_GetFTPResponse(&nread, conn, &ftpcode);
+ (void)Curl_GetFTPResponse(data, &nread, &ftpcode);
return CURLE_FTP_ACCEPT_FAILED;
}
@@ -411,7 +411,7 @@ static CURLcode ReceivedServerConnect(struct connectdata *conn, bool *received)
}
else if(result & CURL_CSELECT_IN) {
infof(data, "Ctrl conn has data while waiting for data conn\n");
- (void)Curl_GetFTPResponse(&nread, conn, &ftpcode);
+ (void)Curl_GetFTPResponse(data, &nread, &ftpcode);
if(ftpcode/100 > 3)
return CURLE_FTP_ACCEPT_FAILED;
@@ -434,16 +434,16 @@ static CURLcode ReceivedServerConnect(struct connectdata *conn, bool *received)
* setup transfer parameters and initiate the data transfer.
*
*/
-static CURLcode InitiateTransfer(struct connectdata *conn)
+static CURLcode InitiateTransfer(struct Curl_easy *data)
{
- struct Curl_easy *data = conn->data;
CURLcode result = CURLE_OK;
+ struct connectdata *conn = data->conn;
if(conn->bits.ftp_use_data_ssl) {
/* since we only have a plaintext TCP connection here, we must now
* do the TLS stuff */
infof(data, "Doing the SSL/TLS handshake on the data stream\n");
- result = Curl_ssl_connect(conn, SECONDARYSOCKET);
+ result = Curl_ssl_connect(data, conn, SECONDARYSOCKET);
if(result)
return result;
}
@@ -465,7 +465,7 @@ static CURLcode InitiateTransfer(struct connectdata *conn)
}
conn->proto.ftpc.pp.pending_resp = TRUE; /* expect server response */
- state(conn, FTP_STOP);
+ state(data, FTP_STOP);
return CURLE_OK;
}
@@ -479,9 +479,8 @@ static CURLcode InitiateTransfer(struct connectdata *conn)
* accepted.
*
*/
-static CURLcode AllowServerConnect(struct connectdata *conn, bool *connected)
+static CURLcode AllowServerConnect(struct Curl_easy *data, bool *connected)
{
- struct Curl_easy *data = conn->data;
timediff_t timeout_ms;
CURLcode result = CURLE_OK;
@@ -499,16 +498,16 @@ static CURLcode AllowServerConnect(struct connectdata *conn, bool *connected)
}
/* see if the connection request is already here */
- result = ReceivedServerConnect(conn, connected);
+ result = ReceivedServerConnect(data, connected);
if(result)
return result;
if(*connected) {
- result = AcceptServerConnect(conn);
+ result = AcceptServerConnect(data);
if(result)
return result;
- result = InitiateTransfer(conn);
+ result = InitiateTransfer(data);
if(result)
return result;
}
@@ -531,9 +530,10 @@ static CURLcode AllowServerConnect(struct connectdata *conn, bool *connected)
/* macro to check for the last line in an FTP server response */
#define LASTLINE(line) (STATUSCODE(line) && (' ' == line[3]))
-static bool ftp_endofresp(struct connectdata *conn, char *line, size_t len,
- int *code)
+static bool ftp_endofresp(struct Curl_easy *data, struct connectdata *conn,
+ char *line, size_t len, int *code)
{
+ (void)data;
(void)conn;
if((len > 3) && LASTLINE(line)) {
@@ -544,34 +544,35 @@ static bool ftp_endofresp(struct connectdata *conn, char *line, size_t len,
return FALSE;
}
-static CURLcode ftp_readresp(curl_socket_t sockfd,
+static CURLcode ftp_readresp(struct Curl_easy *data,
+ curl_socket_t sockfd,
struct pingpong *pp,
int *ftpcode, /* return the ftp-code if done */
size_t *size) /* size of the response */
{
- struct connectdata *conn = pp->conn;
- struct Curl_easy *data = conn->data;
-#ifdef HAVE_GSSAPI
- char * const buf = data->state.buffer;
-#endif
int code;
- CURLcode result = Curl_pp_readresp(sockfd, pp, &code, size);
+ CURLcode result = Curl_pp_readresp(data, sockfd, pp, &code, size);
-#if defined(HAVE_GSSAPI)
- /* handle the security-oriented responses 6xx ***/
- switch(code) {
- case 631:
- code = Curl_sec_read_msg(conn, buf, PROT_SAFE);
- break;
- case 632:
- code = Curl_sec_read_msg(conn, buf, PROT_PRIVATE);
- break;
- case 633:
- code = Curl_sec_read_msg(conn, buf, PROT_CONFIDENTIAL);
- break;
- default:
- /* normal ftp stuff we pass through! */
- break;
+#ifdef HAVE_GSSAPI
+ {
+ struct connectdata *conn = data->conn;
+ char * const buf = data->state.buffer;
+
+ /* handle the security-oriented responses 6xx ***/
+ switch(code) {
+ case 631:
+ code = Curl_sec_read_msg(data, conn, buf, PROT_SAFE);
+ break;
+ case 632:
+ code = Curl_sec_read_msg(data, conn, buf, PROT_PRIVATE);
+ break;
+ case 633:
+ code = Curl_sec_read_msg(data, conn, buf, PROT_CONFIDENTIAL);
+ break;
+ default:
+ /* normal ftp stuff we pass through! */
+ break;
+ }
}
#endif
@@ -590,7 +591,7 @@ static CURLcode ftp_readresp(curl_socket_t sockfd,
* generically is a good idea.
*/
infof(data, "We got a 421 - timeout!\n");
- state(conn, FTP_STOP);
+ state(data, FTP_STOP);
return CURLE_OPERATION_TIMEDOUT;
}
@@ -605,8 +606,8 @@ static CURLcode ftp_readresp(curl_socket_t sockfd,
*
*/
-CURLcode Curl_GetFTPResponse(ssize_t *nreadp, /* return number of bytes read */
- struct connectdata *conn,
+CURLcode Curl_GetFTPResponse(struct Curl_easy *data,
+ ssize_t *nreadp, /* return number of bytes read */
int *ftpcode) /* return the ftp-code */
{
/*
@@ -616,8 +617,8 @@ CURLcode Curl_GetFTPResponse(ssize_t *nreadp, /* return number of bytes read */
* Alas, read as much as possible, split up into lines, use the ending
* line in a response or continue reading. */
+ struct connectdata *conn = data->conn;
curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
- struct Curl_easy *data = conn->data;
CURLcode result = CURLE_OK;
struct ftp_conn *ftpc = &conn->proto.ftpc;
struct pingpong *pp = &ftpc->pp;
@@ -635,7 +636,7 @@ CURLcode Curl_GetFTPResponse(ssize_t *nreadp, /* return number of bytes read */
while(!*ftpcode && !result) {
/* check and reset timeout value every lap */
- timediff_t timeout = Curl_pp_state_timeout(pp, FALSE);
+ timediff_t timeout = Curl_pp_state_timeout(data, pp, FALSE);
timediff_t interval_ms;
if(timeout <= 0) {
@@ -677,7 +678,7 @@ CURLcode Curl_GetFTPResponse(ssize_t *nreadp, /* return number of bytes read */
return CURLE_RECV_ERROR;
case 0: /* timeout */
- if(Curl_pgrsUpdate(conn))
+ if(Curl_pgrsUpdate(data))
return CURLE_ABORTED_BY_CALLBACK;
continue; /* just continue in our loop for the timeout duration */
@@ -685,7 +686,7 @@ CURLcode Curl_GetFTPResponse(ssize_t *nreadp, /* return number of bytes read */
break;
}
}
- result = ftp_readresp(sockfd, pp, ftpcode, &nread);
+ result = ftp_readresp(data, sockfd, pp, ftpcode, &nread);
if(result)
break;
@@ -749,13 +750,14 @@ static const char * const ftp_state_names[]={
#endif
/* This is the ONLY way to change FTP state! */
-static void _state(struct connectdata *conn,
+static void _state(struct Curl_easy *data,
ftpstate newstate
#ifdef DEBUGBUILD
, int lineno
#endif
)
{
+ struct connectdata *conn = data->conn;
struct ftp_conn *ftpc = &conn->proto.ftpc;
#if defined(DEBUGBUILD)
@@ -764,7 +766,7 @@ static void _state(struct connectdata *conn,
(void) lineno;
#else
if(ftpc->state != newstate)
- infof(conn->data, "FTP %p (line %d) state change from %s to %s\n",
+ infof(data, "FTP %p (line %d) state change from %s to %s\n",
(void *)ftpc, lineno, ftp_state_names[ftpc->state],
ftp_state_names[newstate]);
#endif
@@ -773,40 +775,43 @@ static void _state(struct connectdata *conn,
ftpc->state = newstate;
}
-static CURLcode ftp_state_user(struct connectdata *conn)
+static CURLcode ftp_state_user(struct Curl_easy *data,
+ struct connectdata *conn)
{
- CURLcode result;
- /* send USER */
- PPSENDF(&conn->proto.ftpc.pp, "USER %s", conn->user?conn->user:"");
-
- state(conn, FTP_USER);
- conn->data->state.ftp_trying_alternative = FALSE;
-
- return CURLE_OK;
+ CURLcode result = Curl_pp_sendf(data,
+ &conn->proto.ftpc.pp, "USER %s",
+ conn->user?conn->user:"");
+ if(!result) {
+ state(data, FTP_USER);
+ data->state.ftp_trying_alternative = FALSE;
+ }
+ return result;
}
-static CURLcode ftp_state_pwd(struct connectdata *conn)
+static CURLcode ftp_state_pwd(struct Curl_easy *data,
+ struct connectdata *conn)
{
- CURLcode result;
-
- /* send PWD to discover our entry point */
- PPSENDF(&conn->proto.ftpc.pp, "%s", "PWD");
- state(conn, FTP_PWD);
+ CURLcode result = Curl_pp_sendf(data, &conn->proto.ftpc.pp, "%s", "PWD");
+ if(!result)
+ state(data, FTP_PWD);
- return CURLE_OK;
+ return result;
}
/* For the FTP "protocol connect" and "doing" phases only */
-static int ftp_getsock(struct connectdata *conn,
+static int ftp_getsock(struct Curl_easy *data,
+ struct connectdata *conn,
curl_socket_t *socks)
{
- return Curl_pp_getsock(&conn->proto.ftpc.pp, socks);
+ return Curl_pp_getsock(data, &conn->proto.ftpc.pp, socks);
}
/* For the FTP "DO_MORE" phase only */
-static int ftp_domore_getsock(struct connectdata *conn, curl_socket_t *socks)
+static int ftp_domore_getsock(struct Curl_easy *data,
+ struct connectdata *conn, curl_socket_t *socks)
{
struct ftp_conn *ftpc = &conn->proto.ftpc;
+ (void)data;
/* 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
@@ -824,7 +829,7 @@ static int ftp_domore_getsock(struct connectdata *conn, curl_socket_t *socks)
connect on the secondary connection */
socks[0] = conn->sock[FIRSTSOCKET];
- if(!conn->data->set.ftp_use_port) {
+ if(!data->set.ftp_use_port) {
int s;
int i;
/* PORT is used to tell the server to connect to us, and during that we
@@ -844,7 +849,7 @@ static int ftp_domore_getsock(struct connectdata *conn, curl_socket_t *socks)
return bits;
}
- return Curl_pp_getsock(&conn->proto.ftpc.pp, socks);
+ return Curl_pp_getsock(data, &conn->proto.ftpc.pp, socks);
}
/* This is called after the FTP_QUOTE state is passed.
@@ -853,17 +858,18 @@ static int ftp_domore_getsock(struct connectdata *conn, curl_socket_t *socks)
the correct directory. It may also need to send MKD commands to create
missing ones, if that option is enabled.
*/
-static CURLcode ftp_state_cwd(struct connectdata *conn)
+static CURLcode ftp_state_cwd(struct Curl_easy *data,
+ struct connectdata *conn)
{
CURLcode result = CURLE_OK;
struct ftp_conn *ftpc = &conn->proto.ftpc;
if(ftpc->cwddone)
/* already done and fine */
- result = ftp_state_mdtm(conn);
+ result = ftp_state_mdtm(data);
else {
/* FTPFILE_NOCWD with full path: expect ftpc->cwddone! */
- DEBUGASSERT((conn->data->set.ftp_filemethod != FTPFILE_NOCWD) ||
+ DEBUGASSERT((data->set.ftp_filemethod != FTPFILE_NOCWD) ||
!(ftpc->dirdepth && ftpc->dirs[0][0] == '/'));
ftpc->count2 = 0; /* count2 counts failed CWDs */
@@ -871,7 +877,7 @@ static CURLcode ftp_state_cwd(struct connectdata *conn)
/* count3 is set to allow a MKD to fail once. In the case when first CWD
fails and then MKD fails (due to another session raced it to create the
dir) this then allows for a second try to CWD to it */
- ftpc->count3 = (conn->data->set.ftp_create_missing_dirs == 2)?1:0;
+ ftpc->count3 = (data->set.ftp_create_missing_dirs == 2)?1:0;
if(conn->bits.reuse && ftpc->entrypath &&
/* no need to go to entrypath when we have an absolute path */
@@ -881,20 +887,23 @@ static CURLcode ftp_state_cwd(struct connectdata *conn)
where we ended up after login: */
ftpc->cwdcount = 0; /* we count this as the first path, then we add one
for all upcoming ones in the ftp->dirs[] array */
- PPSENDF(&conn->proto.ftpc.pp, "CWD %s", ftpc->entrypath);
- state(conn, FTP_CWD);
+ result = Curl_pp_sendf(data, &ftpc->pp, "CWD %s", ftpc->entrypath);
+ if(!result)
+ state(data, FTP_CWD);
}
else {
if(ftpc->dirdepth) {
ftpc->cwdcount = 1;
/* issue the first CWD, the rest is sent when the CWD responses are
received... */
- PPSENDF(&conn->proto.ftpc.pp, "CWD %s", ftpc->dirs[ftpc->cwdcount -1]);
- state(conn, FTP_CWD);
+ result = Curl_pp_sendf(data, &ftpc->pp, "CWD %s",
+ ftpc->dirs[ftpc->cwdcount -1]);
+ if(!result)
+ state(data, FTP_CWD);
}
else {
/* No CWD necessary */
- result = ftp_state_mdtm(conn);
+ result = ftp_state_mdtm(data);
}
}
}
@@ -907,13 +916,12 @@ typedef enum {
DONE
} ftpport;
-static CURLcode ftp_state_use_port(struct connectdata *conn,
+static CURLcode ftp_state_use_port(struct Curl_easy *data,
ftpport fcmd) /* start with this */
-
{
CURLcode result = CURLE_OK;
+ struct connectdata *conn = data->conn;
struct ftp_conn *ftpc = &conn->proto.ftpc;
- struct Curl_easy *data = conn->data;
curl_socket_t portsock = CURL_SOCKET_BAD;
char myhost[MAX_IPADR_LEN + 1] = "";
@@ -1070,9 +1078,9 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
}
/* resolv ip/host to ip */
- rc = Curl_resolv(conn, host, 0, FALSE, &h);
+ rc = Curl_resolv(data, host, 0, FALSE, &h);
if(rc == CURLRESOLV_PENDING)
- (void)Curl_resolver_wait_resolv(conn, &h);
+ (void)Curl_resolver_wait_resolv(data, &h);
if(h) {
res = h->addr;
/* when we return from this function, we can forget about this entry
@@ -1096,7 +1104,7 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
portsock = CURL_SOCKET_BAD;
error = 0;
for(ai = res; ai; ai = ai->ai_next) {
- result = Curl_socket(conn, ai, NULL, &portsock);
+ result = Curl_socket(data, ai, NULL, &portsock);
if(result) {
error = SOCKERRNO;
continue;
@@ -1136,7 +1144,7 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
if(getsockname(conn->sock[FIRSTSOCKET], sa, &sslen)) {
failf(data, "getsockname() failed: %s",
Curl_strerror(SOCKERRNO, buffer, sizeof(buffer)));
- Curl_closesocket(conn, portsock);
+ Curl_closesocket(data, conn, portsock);
return CURLE_FTP_PORT_FAILED;
}
port = port_min;
@@ -1146,7 +1154,7 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
if(error != EADDRINUSE && error != EACCES) {
failf(data, "bind(port=%hu) failed: %s", port,
Curl_strerror(error, buffer, sizeof(buffer)));
- Curl_closesocket(conn, portsock);
+ Curl_closesocket(data, conn, portsock);
return CURLE_FTP_PORT_FAILED;
}
}
@@ -1159,7 +1167,7 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
/* maybe all ports were in use already*/
if(port > port_max) {
failf(data, "bind() failed, we ran out of ports!");
- Curl_closesocket(conn, portsock);
+ Curl_closesocket(data, conn, portsock);
return CURLE_FTP_PORT_FAILED;
}
@@ -1169,7 +1177,7 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
if(getsockname(portsock, (struct sockaddr *)sa, &sslen)) {
failf(data, "getsockname() failed: %s",
Curl_strerror(SOCKERRNO, buffer, sizeof(buffer)));
- Curl_closesocket(conn, portsock);
+ Curl_closesocket(data, conn, portsock);
return CURLE_FTP_PORT_FAILED;
}
@@ -1178,7 +1186,7 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
if(listen(portsock, 1)) {
failf(data, "socket failure: %s",
Curl_strerror(SOCKERRNO, buffer, sizeof(buffer)));
- Curl_closesocket(conn, portsock);
+ Curl_closesocket(data, conn, portsock);
return CURLE_FTP_PORT_FAILED;
}
@@ -1227,17 +1235,17 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
* EPRT |2|1080::8:800:200C:417A|5282|
*/
- result = Curl_pp_sendf(&ftpc->pp, "%s |%d|%s|%hu|", mode[fcmd],
+ result = Curl_pp_sendf(data, &ftpc->pp, "%s |%d|%s|%hu|", mode[fcmd],
sa->sa_family == AF_INET?1:2,
myhost, port);
if(result) {
failf(data, "Failure sending EPRT command: %s",
curl_easy_strerror(result));
- Curl_closesocket(conn, portsock);
+ Curl_closesocket(data, conn, portsock);
/* don't retry using PORT */
ftpc->count1 = PORT;
/* bail out */
- state(conn, FTP_STOP);
+ state(data, FTP_STOP);
return result;
}
break;
@@ -1260,13 +1268,13 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
*dest = 0;
msnprintf(dest, 20, ",%d,%d", (int)(port>>8), (int)(port&0xff));
- result = Curl_pp_sendf(&ftpc->pp, "%s %s", mode[fcmd], target);
+ result = Curl_pp_sendf(data, &ftpc->pp, "%s %s", mode[fcmd], target);
if(result) {
failf(data, "Failure sending PORT command: %s",
curl_easy_strerror(result));
- Curl_closesocket(conn, portsock);
+ Curl_closesocket(data, conn, portsock);
/* bail out */
- state(conn, FTP_STOP);
+ state(data, FTP_STOP);
return result;
}
break;
@@ -1276,7 +1284,7 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
/* store which command was sent */
ftpc->count1 = fcmd;
- close_secondarysocket(conn);
+ close_secondarysocket(data, conn);
/* we set the secondary socket variable to this for now, it is only so that
the cleanup function will close it in case we fail before the true
@@ -1292,11 +1300,12 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
*/
conn->bits.tcpconnect[SECONDARYSOCKET] = TRUE;
- state(conn, FTP_PORT);
+ state(data, FTP_PORT);
return result;
}
-static CURLcode ftp_state_use_pasv(struct connectdata *conn)
+static CURLcode ftp_state_use_pasv(struct Curl_easy *data,
+ struct connectdata *conn)
{
struct ftp_conn *ftpc = &conn->proto.ftpc;
CURLcode result = CURLE_OK;
@@ -1326,12 +1335,12 @@ static CURLcode ftp_state_use_pasv(struct connectdata *conn)
modeoff = conn->bits.ftp_use_epsv?0:1;
- PPSENDF(&ftpc->pp, "%s", mode[modeoff]);
-
- ftpc->count1 = modeoff;
- state(conn, FTP_PASV);
- infof(conn->data, "Connect data stream passively\n");
-
+ result = Curl_pp_sendf(data, &ftpc->pp, "%s", mode[modeoff]);
+ if(!result) {
+ ftpc->count1 = modeoff;
+ state(data, FTP_PASV);
+ infof(data, "Connect data stream passively\n");
+ }
return result;
}
@@ -1342,53 +1351,54 @@ static CURLcode ftp_state_use_pasv(struct connectdata *conn)
* 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 connectdata *conn)
+static CURLcode ftp_state_prepare_transfer(struct Curl_easy *data)
{
CURLcode result = CURLE_OK;
- struct FTP *ftp = conn->data->req.protop;
- struct Curl_easy *data = conn->data;
+ struct FTP *ftp = data->req.p.ftp;
+ struct connectdata *conn = data->conn;
if(ftp->transfer != FTPTRANSFER_BODY) {
/* doesn't transfer any data */
/* still possibly do PRE QUOTE jobs */
- state(conn, FTP_RETR_PREQUOTE);
- result = ftp_state_quote(conn, TRUE, FTP_RETR_PREQUOTE);
+ state(data, FTP_RETR_PREQUOTE);
+ result = ftp_state_quote(data, 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(conn, EPRT);
+ result = ftp_state_use_port(data, 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 */
- if(!conn->proto.ftpc.file) {
- PPSENDF(&conn->proto.ftpc.pp, "PRET %s",
- data->set.str[STRING_CUSTOMREQUEST]?
- data->set.str[STRING_CUSTOMREQUEST]:
- (data->set.ftp_list_only?"NLST":"LIST"));
- }
- else if(data->set.upload) {
- PPSENDF(&conn->proto.ftpc.pp, "PRET STOR %s", conn->proto.ftpc.file);
- }
- else {
- PPSENDF(&conn->proto.ftpc.pp, "PRET RETR %s", conn->proto.ftpc.file);
- }
- state(conn, FTP_PRET);
- }
- else {
- result = ftp_state_use_pasv(conn);
+ struct ftp_conn *ftpc = &conn->proto.ftpc;
+ if(!conn->proto.ftpc.file)
+ result = Curl_pp_sendf(data, &ftpc->pp, "PRET %s",
+ data->set.str[STRING_CUSTOMREQUEST]?
+ data->set.str[STRING_CUSTOMREQUEST]:
+ (data->set.ftp_list_only?"NLST":"LIST"));
+ else if(data->set.upload)
+ result = Curl_pp_sendf(data, &ftpc->pp, "PRET STOR %s",
+ conn->proto.ftpc.file);
+ else
+ result = Curl_pp_sendf(data, &ftpc->pp, "PRET RETR %s",
+ conn->proto.ftpc.file);
+ if(!result)
+ state(data, FTP_PRET);
}
+ else
+ result = ftp_state_use_pasv(data, conn);
}
return result;
}
-static CURLcode ftp_state_rest(struct connectdata *conn)
+static CURLcode ftp_state_rest(struct Curl_easy *data,
+ struct connectdata *conn)
{
CURLcode result = CURLE_OK;
- struct FTP *ftp = conn->data->req.protop;
+ struct FTP *ftp = data->req.p.ftp;
struct ftp_conn *ftpc = &conn->proto.ftpc;
if((ftp->transfer != FTPTRANSFER_BODY) && ftpc->file) {
@@ -1396,41 +1406,42 @@ static CURLcode ftp_state_rest(struct connectdata *conn)
/* Determine if server can respond to REST command and therefore
whether it supports range */
- PPSENDF(&conn->proto.ftpc.pp, "REST %d", 0);
-
- state(conn, FTP_REST);
+ result = Curl_pp_sendf(data, &ftpc->pp, "REST %d", 0);
+ if(!result)
+ state(data, FTP_REST);
}
else
- result = ftp_state_prepare_transfer(conn);
+ result = ftp_state_prepare_transfer(data);
return result;
}
-static CURLcode ftp_state_size(struct connectdata *conn)
+static CURLcode ftp_state_size(struct Curl_easy *data,
+ struct connectdata *conn)
{
CURLcode result = CURLE_OK;
- struct FTP *ftp = conn->data->req.protop;
+ struct FTP *ftp = data->req.p.ftp;
struct ftp_conn *ftpc = &conn->proto.ftpc;
if((ftp->transfer == FTPTRANSFER_INFO) && ftpc->file) {
/* if a "head"-like request is being made (on a file) */
/* we know ftpc->file is a valid pointer to a file name */
- PPSENDF(&ftpc->pp, "SIZE %s", ftpc->file);
-
- state(conn, FTP_SIZE);
+ result = Curl_pp_sendf(data, &ftpc->pp, "SIZE %s", ftpc->file);
+ if(!result)
+ state(data, FTP_SIZE);
}
else
- result = ftp_state_rest(conn);
+ result = ftp_state_rest(data, conn);
return result;
}
-static CURLcode ftp_state_list(struct connectdata *conn)
+static CURLcode ftp_state_list(struct Curl_easy *data)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
- struct FTP *ftp = data->req.protop;
+ 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
@@ -1482,34 +1493,32 @@ static CURLcode ftp_state_list(struct connectdata *conn)
if(!cmd)
return CURLE_OUT_OF_MEMORY;
- result = Curl_pp_sendf(&conn->proto.ftpc.pp, "%s", cmd);
+ result = Curl_pp_sendf(data, &conn->proto.ftpc.pp, "%s", cmd);
free(cmd);
- if(result)
- return result;
-
- state(conn, FTP_LIST);
+ if(!result)
+ state(data, FTP_LIST);
return result;
}
-static CURLcode ftp_state_retr_prequote(struct connectdata *conn)
+static CURLcode ftp_state_retr_prequote(struct Curl_easy *data)
{
/* We've sent the TYPE, now we must send the list of prequote strings */
- return ftp_state_quote(conn, TRUE, FTP_RETR_PREQUOTE);
+ return ftp_state_quote(data, TRUE, FTP_RETR_PREQUOTE);
}
-static CURLcode ftp_state_stor_prequote(struct connectdata *conn)
+static CURLcode ftp_state_stor_prequote(struct Curl_easy *data)
{
/* We've sent the TYPE, now we must send the list of prequote strings */
- return ftp_state_quote(conn, TRUE, FTP_STOR_PREQUOTE);
+ return ftp_state_quote(data, TRUE, FTP_STOR_PREQUOTE);
}
-static CURLcode ftp_state_type(struct connectdata *conn)
+static CURLcode ftp_state_type(struct Curl_easy *data)
{
CURLcode result = CURLE_OK;
- struct FTP *ftp = conn->data->req.protop;
- struct Curl_easy *data = conn->data;
+ 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
@@ -1526,22 +1535,22 @@ static CURLcode ftp_state_type(struct connectdata *conn)
/* 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(conn, data->set.prefer_ascii, FTP_TYPE);
+ result = ftp_nb_type(data, conn, data->set.prefer_ascii, FTP_TYPE);
if(result)
return result;
}
else
- result = ftp_state_size(conn);
+ result = ftp_state_size(data, conn);
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 connectdata *conn)
+static CURLcode ftp_state_mdtm(struct Curl_easy *data)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
+ struct connectdata *conn = data->conn;
struct ftp_conn *ftpc = &conn->proto.ftpc;
/* Requested time of file or time-depended transfer? */
@@ -1549,24 +1558,25 @@ static CURLcode ftp_state_mdtm(struct connectdata *conn)
/* we have requested to get the modified-time of the file, this is a white
spot as the MDTM is not mentioned in RFC959 */
- PPSENDF(&ftpc->pp, "MDTM %s", ftpc->file);
+ result = Curl_pp_sendf(data, &ftpc->pp, "MDTM %s", ftpc->file);
- state(conn, FTP_MDTM);
+ if(!result)
+ state(data, FTP_MDTM);
}
else
- result = ftp_state_type(conn);
+ result = ftp_state_type(data);
return result;
}
/* This is called after the TYPE and possible quote commands have been sent */
-static CURLcode ftp_state_ul_setup(struct connectdata *conn,
+static CURLcode ftp_state_ul_setup(struct Curl_easy *data,
bool sizechecked)
{
CURLcode result = CURLE_OK;
- struct FTP *ftp = conn->data->req.protop;
- struct Curl_easy *data = conn->data;
+ struct connectdata *conn = data->conn;
+ struct FTP *ftp = data->req.p.ftp;
struct ftp_conn *ftpc = &conn->proto.ftpc;
if((data->state.resume_from && !sizechecked) ||
@@ -1587,8 +1597,9 @@ static CURLcode ftp_state_ul_setup(struct connectdata *conn,
if(data->state.resume_from < 0) {
/* Got no given size to start from, figure it out */
- PPSENDF(&ftpc->pp, "SIZE %s", ftpc->file);
- state(conn, FTP_STOR_SIZE);
+ result = Curl_pp_sendf(data, &ftpc->pp, "SIZE %s", ftpc->file);
+ if(!result)
+ state(data, FTP_STOR_SIZE);
return result;
}
@@ -1643,28 +1654,29 @@ static CURLcode ftp_state_ul_setup(struct connectdata *conn,
* ftp_done() because we didn't transfer anything! */
ftp->transfer = FTPTRANSFER_NONE;
- state(conn, FTP_STOP);
+ state(data, FTP_STOP);
return CURLE_OK;
}
}
/* we've passed, proceed as normal */
} /* resume_from */
- PPSENDF(&ftpc->pp, data->set.ftp_append?"APPE %s":"STOR %s",
- ftpc->file);
-
- state(conn, FTP_STOR);
+ result = Curl_pp_sendf(data, &ftpc->pp,
+ data->set.ftp_append?"APPE %s":"STOR %s",
+ ftpc->file);
+ if(!result)
+ state(data, FTP_STOR);
return result;
}
-static CURLcode ftp_state_quote(struct connectdata *conn,
+static CURLcode ftp_state_quote(struct Curl_easy *data,
bool init,
ftpstate instate)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
- struct FTP *ftp = data->req.protop;
+ 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;
@@ -1711,8 +1723,10 @@ static CURLcode ftp_state_quote(struct connectdata *conn,
else
ftpc->count2 = 0; /* failure means cancel operation */
- PPSENDF(&ftpc->pp, "%s", cmd);
- state(conn, instate);
+ result = Curl_pp_sendf(data, &ftpc->pp, "%s", cmd);
+ if(result)
+ return result;
+ state(data, instate);
quote = TRUE;
}
}
@@ -1722,15 +1736,15 @@ static CURLcode ftp_state_quote(struct connectdata *conn,
switch(instate) {
case FTP_QUOTE:
default:
- result = ftp_state_cwd(conn);
+ result = ftp_state_cwd(data, conn);
break;
case FTP_RETR_PREQUOTE:
if(ftp->transfer != FTPTRANSFER_BODY)
- state(conn, FTP_STOP);
+ state(data, FTP_STOP);
else {
if(ftpc->known_filesize != -1) {
Curl_pgrsSetDownloadSize(data, ftpc->known_filesize);
- result = ftp_state_retr(conn, ftpc->known_filesize);
+ result = ftp_state_retr(data, ftpc->known_filesize);
}
else {
if(data->set.ignorecl) {
@@ -1740,18 +1754,20 @@ static CURLcode ftp_state_quote(struct connectdata *conn,
the server terminates it, otherwise the client stops if the
received byte count exceeds the reported file size. Set option
CURLOPT_IGNORE_CONTENT_LENGTH to 1 to enable this behavior.*/
- PPSENDF(&ftpc->pp, "RETR %s", ftpc->file);
- state(conn, FTP_RETR);
+ result = Curl_pp_sendf(data, &ftpc->pp, "RETR %s", ftpc->file);
+ if(!result)
+ state(data, FTP_RETR);
}
else {
- PPSENDF(&ftpc->pp, "SIZE %s", ftpc->file);
- state(conn, FTP_RETR_SIZE);
+ result = Curl_pp_sendf(data, &ftpc->pp, "SIZE %s", ftpc->file);
+ if(!result)
+ state(data, FTP_RETR_SIZE);
}
}
}
break;
case FTP_STOR_PREQUOTE:
- result = ftp_state_ul_setup(conn, FALSE);
+ result = ftp_state_ul_setup(data, FALSE);
break;
case FTP_POSTQUOTE:
break;
@@ -1763,7 +1779,8 @@ static CURLcode ftp_state_quote(struct connectdata *conn,
/* called from ftp_state_pasv_resp to switch to PASV in case of EPSV
problems */
-static CURLcode ftp_epsv_disable(struct connectdata *conn)
+static CURLcode ftp_epsv_disable(struct Curl_easy *data,
+ struct connectdata *conn)
{
CURLcode result = CURLE_OK;
@@ -1773,19 +1790,21 @@ static CURLcode ftp_epsv_disable(struct connectdata *conn)
#endif
) {
/* We can't disable EPSV when doing IPv6, so this is instead a fail */
- failf(conn->data, "Failed EPSV attempt, exiting\n");
+ failf(data, "Failed EPSV attempt, exiting");
return CURLE_WEIRD_SERVER_REPLY;
}
- infof(conn->data, "Failed EPSV attempt. Disabling EPSV\n");
+ infof(data, "Failed EPSV attempt. Disabling EPSV\n");
/* disable it for next transfer */
conn->bits.ftp_use_epsv = FALSE;
- conn->data->state.errorbuf = FALSE; /* allow error message to get
+ data->state.errorbuf = FALSE; /* allow error message to get
rewritten */
- PPSENDF(&conn->proto.ftpc.pp, "%s", "PASV");
- conn->proto.ftpc.count1++;
- /* remain in/go to the FTP_PASV state */
- state(conn, FTP_PASV);
+ result = Curl_pp_sendf(data, &conn->proto.ftpc.pp, "%s", "PASV");
+ if(!result) {
+ conn->proto.ftpc.count1++;
+ /* remain in/go to the FTP_PASV state */
+ state(data, FTP_PASV);
+ }
return result;
}
@@ -1800,15 +1819,15 @@ static char *control_address(struct connectdata *conn)
if(conn->bits.tunnel_proxy || conn->bits.socksproxy)
return conn->host.name;
#endif
- return conn->ip_addr_str;
+ return conn->primary_ip;
}
-static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
+static CURLcode ftp_state_pasv_resp(struct Curl_easy *data,
int ftpcode)
{
+ struct connectdata *conn = data->conn;
struct ftp_conn *ftpc = &conn->proto.ftpc;
CURLcode result;
- struct Curl_easy *data = conn->data;
struct Curl_dns_entry *addr = NULL;
enum resolve_t rc;
unsigned short connectport; /* the local port connect() should use! */
@@ -1864,8 +1883,8 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
else if((ftpc->count1 == 1) &&
(ftpcode == 227)) {
/* positive PASV response */
- unsigned int ip[4];
- unsigned int port[2];
+ unsigned int ip[4] = {0, 0, 0, 0};
+ unsigned int port[2] = {0, 0};
/*
* Scan for a sequence of six comma-separated numbers and use them as
@@ -1909,7 +1928,7 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
}
else if(ftpc->count1 == 0) {
/* EPSV failed, move on to PASV */
- return ftp_epsv_disable(conn);
+ return ftp_epsv_disable(data, conn);
}
else {
failf(data, "Bad PASV/EPSV response: %03d", ftpcode);
@@ -1925,11 +1944,11 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
*/
const char * const host_name = conn->bits.socksproxy ?
conn->socks_proxy.host.name : conn->http_proxy.host.name;
- rc = Curl_resolv(conn, host_name, (int)conn->port, FALSE, &addr);
+ rc = Curl_resolv(data, host_name, (int)conn->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(conn, &addr);
+ (void)Curl_resolver_wait_resolv(data, &addr);
connectport =
(unsigned short)conn->port; /* we connect to the proxy's port */
@@ -1943,10 +1962,21 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
#endif
{
/* normal, direct, ftp connection */
- rc = Curl_resolv(conn, ftpc->newhost, ftpc->newport, FALSE, &addr);
+ DEBUGASSERT(ftpc->newhost);
+
+ /* postponed address resolution in case of tcp fastopen */
+ if(conn->bits.tcp_fastopen && !conn->bits.reuse && !ftpc->newhost[0]) {
+ Curl_conninfo_remote(data, conn, conn->sock[FIRSTSOCKET]);
+ Curl_safefree(ftpc->newhost);
+ ftpc->newhost = strdup(control_address(conn));
+ if(!ftpc->newhost)
+ 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(conn, &addr);
+ (void)Curl_resolver_wait_resolv(data, &addr);
connectport = ftpc->newport; /* we connect to the remote port */
@@ -1957,12 +1987,12 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
}
conn->bits.tcpconnect[SECONDARYSOCKET] = FALSE;
- result = Curl_connecthost(conn, addr);
+ result = Curl_connecthost(data, conn, addr);
if(result) {
Curl_resolv_unlock(data, addr); /* we're done using this address */
if(ftpc->count1 == 0 && ftpcode == 229)
- return ftp_epsv_disable(conn);
+ return ftp_epsv_disable(data, conn);
return result;
}
@@ -1976,7 +2006,7 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
if(data->set.verbose)
/* this just dumps information about this second connection */
- ftp_pasv_verbose(conn, addr->addr, ftpc->newhost, connectport);
+ ftp_pasv_verbose(data, addr->addr, ftpc->newhost, connectport);
Curl_resolv_unlock(data, addr); /* we're done using this address */
@@ -1987,15 +2017,15 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
return CURLE_OUT_OF_MEMORY;
conn->bits.do_more = TRUE;
- state(conn, FTP_STOP); /* this phase is completed */
+ state(data, FTP_STOP); /* this phase is completed */
return result;
}
-static CURLcode ftp_state_port_resp(struct connectdata *conn,
+static CURLcode ftp_state_port_resp(struct Curl_easy *data,
int ftpcode)
{
- struct Curl_easy *data = conn->data;
+ struct connectdata *conn = data->conn;
struct ftp_conn *ftpc = &conn->proto.ftpc;
ftpport fcmd = (ftpport)ftpc->count1;
CURLcode result = CURLE_OK;
@@ -2017,23 +2047,23 @@ static CURLcode ftp_state_port_resp(struct connectdata *conn,
}
else
/* try next */
- result = ftp_state_use_port(conn, fcmd);
+ result = ftp_state_use_port(data, fcmd);
}
else {
infof(data, "Connect data stream actively\n");
- state(conn, FTP_STOP); /* end of DO phase */
- result = ftp_dophase_done(conn, FALSE);
+ state(data, FTP_STOP); /* end of DO phase */
+ result = ftp_dophase_done(data, FALSE);
}
return result;
}
-static CURLcode ftp_state_mdtm_resp(struct connectdata *conn,
+static CURLcode ftp_state_mdtm_resp(struct Curl_easy *data,
int ftpcode)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
- struct FTP *ftp = data->req.protop;
+ struct FTP *ftp = data->req.p.ftp;
+ struct connectdata *conn = data->conn;
struct ftp_conn *ftpc = &conn->proto.ftpc;
switch(ftpcode) {
@@ -2080,7 +2110,7 @@ static CURLcode ftp_state_mdtm_resp(struct connectdata *conn,
tm->tm_hour,
tm->tm_min,
tm->tm_sec);
- result = Curl_client_write(conn, CLIENTWRITE_BOTH, headerbuf, 0);
+ result = Curl_client_write(data, CLIENTWRITE_BOTH, headerbuf, 0);
if(result)
return result;
} /* end of a ridiculous amount of conditionals */
@@ -2092,7 +2122,7 @@ static CURLcode ftp_state_mdtm_resp(struct connectdata *conn,
break;
case 550: /* "No such file or directory" */
failf(data, "Given file does not exist");
- result = CURLE_FTP_COULDNT_RETR_FILE;
+ result = CURLE_REMOTE_FILE_NOT_FOUND;
break;
}
@@ -2105,7 +2135,7 @@ static CURLcode ftp_state_mdtm_resp(struct connectdata *conn,
infof(data, "The requested document is not new enough\n");
ftp->transfer = FTPTRANSFER_NONE; /* mark to not transfer data */
data->info.timecond = TRUE;
- state(conn, FTP_STOP);
+ state(data, FTP_STOP);
return CURLE_OK;
}
break;
@@ -2114,7 +2144,7 @@ static CURLcode ftp_state_mdtm_resp(struct connectdata *conn,
infof(data, "The requested document is not old enough\n");
ftp->transfer = FTPTRANSFER_NONE; /* mark to not transfer data */
data->info.timecond = TRUE;
- state(conn, FTP_STOP);
+ state(data, FTP_STOP);
return CURLE_OK;
}
break;
@@ -2126,17 +2156,17 @@ static CURLcode ftp_state_mdtm_resp(struct connectdata *conn,
}
if(!result)
- result = ftp_state_type(conn);
+ result = ftp_state_type(data);
return result;
}
-static CURLcode ftp_state_type_resp(struct connectdata *conn,
+static CURLcode ftp_state_type_resp(struct Curl_easy *data,
int ftpcode,
ftpstate instate)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
+ struct connectdata *conn = data->conn;
if(ftpcode/100 != 2) {
/* "sasserftpd" and "(u)r(x)bot ftpd" both responds with 226 after a
@@ -2150,23 +2180,23 @@ static CURLcode ftp_state_type_resp(struct connectdata *conn,
ftpcode);
if(instate == FTP_TYPE)
- result = ftp_state_size(conn);
+ result = ftp_state_size(data, conn);
else if(instate == FTP_LIST_TYPE)
- result = ftp_state_list(conn);
+ result = ftp_state_list(data);
else if(instate == FTP_RETR_TYPE)
- result = ftp_state_retr_prequote(conn);
+ result = ftp_state_retr_prequote(data);
else if(instate == FTP_STOR_TYPE)
- result = ftp_state_stor_prequote(conn);
+ result = ftp_state_stor_prequote(data);
return result;
}
-static CURLcode ftp_state_retr(struct connectdata *conn,
- curl_off_t filesize)
+static CURLcode ftp_state_retr(struct Curl_easy *data,
+ curl_off_t filesize)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
- struct FTP *ftp = data->req.protop;
+ struct FTP *ftp = data->req.p.ftp;
+ struct connectdata *conn = data->conn;
struct ftp_conn *ftpc = &conn->proto.ftpc;
if(data->set.max_filesize && (filesize > data->set.max_filesize)) {
@@ -2221,7 +2251,7 @@ static CURLcode ftp_state_retr(struct connectdata *conn,
/* Set ->transfer so that we won't get any error in ftp_done()
* because we didn't transfer the any file */
ftp->transfer = FTPTRANSFER_NONE;
- state(conn, FTP_STOP);
+ state(data, FTP_STOP);
return CURLE_OK;
}
@@ -2229,26 +2259,26 @@ static CURLcode ftp_state_retr(struct connectdata *conn,
infof(data, "Instructs server to resume from offset %"
CURL_FORMAT_CURL_OFF_T "\n", data->state.resume_from);
- PPSENDF(&ftpc->pp, "REST %" CURL_FORMAT_CURL_OFF_T,
- data->state.resume_from);
-
- state(conn, FTP_RETR_REST);
+ result = Curl_pp_sendf(data, &ftpc->pp, "REST %" CURL_FORMAT_CURL_OFF_T,
+ data->state.resume_from);
+ if(!result)
+ state(data, FTP_RETR_REST);
}
else {
/* no resume */
- PPSENDF(&ftpc->pp, "RETR %s", ftpc->file);
- state(conn, FTP_RETR);
+ result = Curl_pp_sendf(data, &ftpc->pp, "RETR %s", ftpc->file);
+ if(!result)
+ state(data, FTP_RETR);
}
return result;
}
-static CURLcode ftp_state_size_resp(struct connectdata *conn,
+static CURLcode ftp_state_size_resp(struct Curl_easy *data,
int ftpcode,
ftpstate instate)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
curl_off_t filesize = -1;
char *buf = data->state.buffer;
@@ -2272,6 +2302,10 @@ static CURLcode ftp_state_size_resp(struct connectdata *conn,
(void)curlx_strtoofft(fdigit, NULL, 0, &filesize);
}
+ else if(ftpcode == 550) { /* "No such file or directory" */
+ failf(data, "The file does not exist");
+ return CURLE_REMOTE_FILE_NOT_FOUND;
+ }
if(instate == FTP_SIZE) {
#ifdef CURL_FTP_HTTPSTYLE_HEAD
@@ -2279,27 +2313,28 @@ static CURLcode ftp_state_size_resp(struct connectdata *conn,
char clbuf[128];
msnprintf(clbuf, sizeof(clbuf),
"Content-Length: %" CURL_FORMAT_CURL_OFF_T "\r\n", filesize);
- result = Curl_client_write(conn, CLIENTWRITE_BOTH, clbuf, 0);
+ result = Curl_client_write(data, CLIENTWRITE_BOTH, clbuf, 0);
if(result)
return result;
}
#endif
Curl_pgrsSetDownloadSize(data, filesize);
- result = ftp_state_rest(conn);
+ result = ftp_state_rest(data, data->conn);
}
else if(instate == FTP_RETR_SIZE) {
Curl_pgrsSetDownloadSize(data, filesize);
- result = ftp_state_retr(conn, filesize);
+ result = ftp_state_retr(data, filesize);
}
else if(instate == FTP_STOR_SIZE) {
data->state.resume_from = filesize;
- result = ftp_state_ul_setup(conn, TRUE);
+ result = ftp_state_ul_setup(data, TRUE);
}
return result;
}
-static CURLcode ftp_state_rest_resp(struct connectdata *conn,
+static CURLcode ftp_state_rest_resp(struct Curl_easy *data,
+ struct connectdata *conn,
int ftpcode,
ftpstate instate)
{
@@ -2312,22 +2347,23 @@ static CURLcode ftp_state_rest_resp(struct connectdata *conn,
#ifdef CURL_FTP_HTTPSTYLE_HEAD
if(ftpcode == 350) {
char buffer[24]= { "Accept-ranges: bytes\r\n" };
- result = Curl_client_write(conn, CLIENTWRITE_BOTH, buffer, 0);
+ result = Curl_client_write(data, CLIENTWRITE_BOTH, buffer, 0);
if(result)
return result;
}
#endif
- result = ftp_state_prepare_transfer(conn);
+ result = ftp_state_prepare_transfer(data);
break;
case FTP_RETR_REST:
if(ftpcode != 350) {
- failf(conn->data, "Couldn't use REST");
+ failf(data, "Couldn't use REST");
result = CURLE_FTP_COULDNT_USE_REST;
}
else {
- PPSENDF(&ftpc->pp, "RETR %s", ftpc->file);
- state(conn, FTP_RETR);
+ result = Curl_pp_sendf(data, &ftpc->pp, "RETR %s", ftpc->file);
+ if(!result)
+ state(data, FTP_RETR);
}
break;
}
@@ -2335,15 +2371,15 @@ static CURLcode ftp_state_rest_resp(struct connectdata *conn,
return result;
}
-static CURLcode ftp_state_stor_resp(struct connectdata *conn,
+static CURLcode ftp_state_stor_resp(struct Curl_easy *data,
int ftpcode, ftpstate instate)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
+ struct connectdata *conn = data->conn;
if(ftpcode >= 400) {
failf(data, "Failed FTP upload: %0d", ftpcode);
- state(conn, FTP_STOP);
+ state(data, FTP_STOP);
/* oops, we never close the sockets! */
return CURLE_UPLOAD_FAILED;
}
@@ -2354,9 +2390,9 @@ static CURLcode ftp_state_stor_resp(struct connectdata *conn,
if(data->set.ftp_use_port) {
bool connected;
- state(conn, FTP_STOP); /* no longer in STOR state */
+ state(data, FTP_STOP); /* no longer in STOR state */
- result = AllowServerConnect(conn, &connected);
+ result = AllowServerConnect(data, &connected);
if(result)
return result;
@@ -2368,17 +2404,17 @@ static CURLcode ftp_state_stor_resp(struct connectdata *conn,
return CURLE_OK;
}
- return InitiateTransfer(conn);
+ return InitiateTransfer(data);
}
/* for LIST and RETR responses */
-static CURLcode ftp_state_get_resp(struct connectdata *conn,
- int ftpcode,
- ftpstate instate)
+static CURLcode ftp_state_get_resp(struct Curl_easy *data,
+ int ftpcode,
+ ftpstate instate)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
- struct FTP *ftp = data->req.protop;
+ struct FTP *ftp = data->req.p.ftp;
+ struct connectdata *conn = data->conn;
if((ftpcode == 150) || (ftpcode == 125)) {
@@ -2468,25 +2504,25 @@ static CURLcode ftp_state_get_resp(struct connectdata *conn,
if(data->set.ftp_use_port) {
bool connected;
- result = AllowServerConnect(conn, &connected);
+ result = AllowServerConnect(data, &connected);
if(result)
return result;
if(!connected) {
struct ftp_conn *ftpc = &conn->proto.ftpc;
infof(data, "Data conn was not available immediately\n");
- state(conn, FTP_STOP);
+ state(data, FTP_STOP);
ftpc->wait_data_conn = TRUE;
}
}
else
- return InitiateTransfer(conn);
+ return InitiateTransfer(data);
}
else {
if((instate == FTP_LIST) && (ftpcode == 450)) {
/* simply no matching files in the dir listing */
ftp->transfer = FTPTRANSFER_NONE; /* don't download anything */
- state(conn, FTP_STOP); /* this phase is over */
+ state(data, FTP_STOP); /* this phase is over */
}
else {
failf(data, "RETR response: %03d", ftpcode);
@@ -2500,11 +2536,12 @@ static CURLcode ftp_state_get_resp(struct connectdata *conn,
}
/* after USER, PASS and ACCT */
-static CURLcode ftp_state_loggedin(struct connectdata *conn)
+static CURLcode ftp_state_loggedin(struct Curl_easy *data)
{
CURLcode result = CURLE_OK;
+ struct connectdata *conn = data->conn;
- if(conn->ssl[FIRSTSOCKET].use) {
+ if(conn->bits.ftp_use_control_ssl) {
/* PBSZ = PROTECTION BUFFER SIZE.
The 'draft-murray-auth-ftp-ssl' (draft 12, page 7) says:
@@ -2519,22 +2556,23 @@ static CURLcode ftp_state_loggedin(struct connectdata *conn)
parameter of '0' to indicate that no buffering is taking place
and the data connection should not be encapsulated.
*/
- PPSENDF(&conn->proto.ftpc.pp, "PBSZ %d", 0);
- state(conn, FTP_PBSZ);
+ result = Curl_pp_sendf(data, &conn->proto.ftpc.pp, "PBSZ %d", 0);
+ if(!result)
+ state(data, FTP_PBSZ);
}
else {
- result = ftp_state_pwd(conn);
+ result = ftp_state_pwd(data, conn);
}
return result;
}
/* for USER and PASS responses */
-static CURLcode ftp_state_user_resp(struct connectdata *conn,
+static CURLcode ftp_state_user_resp(struct Curl_easy *data,
int ftpcode,
ftpstate instate)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
+ struct connectdata *conn = data->conn;
struct ftp_conn *ftpc = &conn->proto.ftpc;
(void)instate; /* no use for this yet */
@@ -2542,18 +2580,22 @@ static CURLcode ftp_state_user_resp(struct connectdata *conn,
if((ftpcode == 331) && (ftpc->state == FTP_USER)) {
/* 331 Password required for ...
(the server requires to send the user's password too) */
- PPSENDF(&ftpc->pp, "PASS %s", conn->passwd?conn->passwd:"");
- state(conn, FTP_PASS);
+ result = Curl_pp_sendf(data, &ftpc->pp, "PASS %s",
+ conn->passwd?conn->passwd:"");
+ if(!result)
+ state(data, FTP_PASS);
}
else if(ftpcode/100 == 2) {
/* 230 User ... logged in.
(the user logged in with or without password) */
- result = ftp_state_loggedin(conn);
+ result = ftp_state_loggedin(data);
}
else if(ftpcode == 332) {
if(data->set.str[STRING_FTP_ACCOUNT]) {
- PPSENDF(&ftpc->pp, "ACCT %s", data->set.str[STRING_FTP_ACCOUNT]);
- state(conn, FTP_ACCT);
+ result = Curl_pp_sendf(data, &ftpc->pp, "ACCT %s",
+ data->set.str[STRING_FTP_ACCOUNT]);
+ if(!result)
+ state(data, FTP_ACCT);
}
else {
failf(data, "ACCT requested but none available");
@@ -2566,14 +2608,16 @@ static CURLcode ftp_state_user_resp(struct connectdata *conn,
530 User ... access denied
(the server denies to log the specified user) */
- if(conn->data->set.str[STRING_FTP_ALTERNATIVE_TO_USER] &&
- !conn->data->state.ftp_trying_alternative) {
+ if(data->set.str[STRING_FTP_ALTERNATIVE_TO_USER] &&
+ !data->state.ftp_trying_alternative) {
/* Ok, USER failed. Let's try the supplied command. */
- PPSENDF(&conn->proto.ftpc.pp, "%s",
- conn->data->set.str[STRING_FTP_ALTERNATIVE_TO_USER]);
- conn->data->state.ftp_trying_alternative = TRUE;
- state(conn, FTP_USER);
- result = CURLE_OK;
+ result =
+ Curl_pp_sendf(data, &ftpc->pp, "%s",
+ data->set.str[STRING_FTP_ALTERNATIVE_TO_USER]);
+ if(!result) {
+ data->state.ftp_trying_alternative = TRUE;
+ state(data, FTP_USER);
+ }
}
else {
failf(data, "Access denied: %03d", ftpcode);
@@ -2584,27 +2628,26 @@ static CURLcode ftp_state_user_resp(struct connectdata *conn,
}
/* for ACCT response */
-static CURLcode ftp_state_acct_resp(struct connectdata *conn,
+static CURLcode ftp_state_acct_resp(struct Curl_easy *data,
int ftpcode)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
if(ftpcode != 230) {
failf(data, "ACCT rejected by server: %03d", ftpcode);
result = CURLE_FTP_WEIRD_PASS_REPLY; /* FIX */
}
else
- result = ftp_state_loggedin(conn);
+ result = ftp_state_loggedin(data);
return result;
}
-static CURLcode ftp_statemach_act(struct connectdata *conn)
+static CURLcode ftp_statemachine(struct Curl_easy *data,
+ struct connectdata *conn)
{
CURLcode result;
curl_socket_t sock = conn->sock[FIRSTSOCKET];
- struct Curl_easy *data = conn->data;
int ftpcode;
struct ftp_conn *ftpc = &conn->proto.ftpc;
struct pingpong *pp = &ftpc->pp;
@@ -2612,9 +2655,9 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
size_t nread = 0;
if(pp->sendleft)
- return Curl_pp_flushsend(pp);
+ return Curl_pp_flushsend(data, pp);
- result = ftp_readresp(sock, pp, &ftpcode, &nread);
+ result = ftp_readresp(data, sock, pp, &ftpcode, &nread);
if(result)
return result;
@@ -2624,7 +2667,7 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
case FTP_WAIT220:
if(ftpcode == 230)
/* 230 User logged in - already! */
- return ftp_state_user_resp(conn, ftpcode, ftpc->state);
+ return ftp_state_user_resp(data, ftpcode, ftpc->state);
else if(ftpcode != 220) {
failf(data, "Got a %03d ftp-server response when 220 was expected",
ftpcode);
@@ -2642,21 +2685,15 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
set a valid level */
Curl_sec_request_prot(conn, data->set.str[STRING_KRB_LEVEL]);
- if(Curl_sec_login(conn))
+ if(Curl_sec_login(data, conn))
infof(data, "Logging in with password in cleartext!\n");
else
infof(data, "Authentication successful\n");
}
#endif
- if(data->set.use_ssl &&
- (!conn->ssl[FIRSTSOCKET].use
-#ifndef CURL_DISABLE_PROXY
- || (conn->bits.proxy_ssl_connected[FIRSTSOCKET] &&
- !conn->proxy_ssl[FIRSTSOCKET].use)
-#endif
- )) {
- /* We don't have a SSL/TLS connection yet, but FTPS is
+ if(data->set.use_ssl && !conn->bits.ftp_use_control_ssl) {
+ /* We don't have a SSL/TLS control connection yet, but FTPS is
requested. Try a FTPS connection now */
ftpc->count3 = 0;
@@ -2675,15 +2712,13 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
(int)data->set.ftpsslauth);
return CURLE_UNKNOWN_OPTION; /* we don't know what to do */
}
- PPSENDF(&ftpc->pp, "AUTH %s", ftpauth[ftpc->count1]);
- state(conn, FTP_AUTH);
- }
- else {
- result = ftp_state_user(conn);
- if(result)
- return result;
+ result = Curl_pp_sendf(data, &ftpc->pp, "AUTH %s",
+ ftpauth[ftpc->count1]);
+ if(!result)
+ state(data, FTP_AUTH);
}
-
+ else
+ result = ftp_state_user(data, conn);
break;
case FTP_AUTH:
@@ -2698,16 +2733,18 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
if((ftpcode == 234) || (ftpcode == 334)) {
/* Curl_ssl_connect is BLOCKING */
- result = Curl_ssl_connect(conn, FIRSTSOCKET);
+ result = Curl_ssl_connect(data, conn, FIRSTSOCKET);
if(!result) {
conn->bits.ftp_use_data_ssl = FALSE; /* clear-text data */
- result = ftp_state_user(conn);
+ conn->bits.ftp_use_control_ssl = TRUE; /* SSL on control */
+ result = ftp_state_user(data, conn);
}
}
else if(ftpc->count3 < 1) {
ftpc->count3++;
ftpc->count1 += ftpc->count2; /* get next attempt */
- result = Curl_pp_sendf(&ftpc->pp, "AUTH %s", ftpauth[ftpc->count1]);
+ result = Curl_pp_sendf(data, &ftpc->pp, "AUTH %s",
+ ftpauth[ftpc->count1]);
/* remain in this same state */
}
else {
@@ -2716,27 +2753,25 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
result = CURLE_USE_SSL_FAILED;
else
/* ignore the failure and continue */
- result = ftp_state_user(conn);
+ result = ftp_state_user(data, conn);
}
-
- if(result)
- return result;
break;
case FTP_USER:
case FTP_PASS:
- result = ftp_state_user_resp(conn, ftpcode, ftpc->state);
+ result = ftp_state_user_resp(data, ftpcode, ftpc->state);
break;
case FTP_ACCT:
- result = ftp_state_acct_resp(conn, ftpcode);
+ result = ftp_state_acct_resp(data, ftpcode);
break;
case FTP_PBSZ:
- PPSENDF(&ftpc->pp, "PROT %c",
- data->set.use_ssl == CURLUSESSL_CONTROL ? 'C' : 'P');
- state(conn, FTP_PROT);
-
+ result =
+ Curl_pp_sendf(data, &ftpc->pp, "PROT %c",
+ data->set.use_ssl == CURLUSESSL_CONTROL ? 'C' : 'P');
+ if(!result)
+ state(data, FTP_PROT);
break;
case FTP_PROT:
@@ -2753,31 +2788,25 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
if(data->set.ftp_ccc) {
/* CCC - Clear Command Channel
*/
- PPSENDF(&ftpc->pp, "%s", "CCC");
- state(conn, FTP_CCC);
- }
- else {
- result = ftp_state_pwd(conn);
- if(result)
- return result;
+ result = Curl_pp_sendf(data, &ftpc->pp, "%s", "CCC");
+ if(!result)
+ state(data, FTP_CCC);
}
+ else
+ result = ftp_state_pwd(data, conn);
break;
case FTP_CCC:
if(ftpcode < 500) {
/* First shut down the SSL layer (note: this call will block) */
- result = Curl_ssl_shutdown(conn, FIRSTSOCKET);
+ result = Curl_ssl_shutdown(data, conn, FIRSTSOCKET);
- if(result) {
- failf(conn->data, "Failed to clear the command channel (CCC)");
- return result;
- }
+ if(result)
+ failf(data, "Failed to clear the command channel (CCC)");
}
-
- /* Then continue as normal */
- result = ftp_state_pwd(conn);
- if(result)
- return result;
+ if(!result)
+ /* Then continue as normal */
+ result = ftp_state_pwd(data, conn);
break;
case FTP_PWD:
@@ -2843,8 +2872,7 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
systems. */
if(!ftpc->server_os && dir[0] != '/') {
-
- result = Curl_pp_sendf(&ftpc->pp, "%s", "SYST");
+ result = Curl_pp_sendf(data, &ftpc->pp, "%s", "SYST");
if(result) {
free(dir);
return result;
@@ -2854,7 +2882,7 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
infof(data, "Entry path is '%s'\n", ftpc->entrypath);
/* also save it where getinfo can access it: */
data->state.most_recent_ftp_entrypath = ftpc->entrypath;
- state(conn, FTP_SYST);
+ state(data, FTP_SYST);
break;
}
@@ -2870,7 +2898,7 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
infof(data, "Failed to figure out path\n");
}
}
- state(conn, FTP_STOP); /* we are done with the CONNECT phase! */
+ state(data, FTP_STOP); /* we are done with the CONNECT phase! */
DEBUGF(infof(data, "protocol connect phase DONE\n"));
break;
@@ -2897,7 +2925,7 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
if(strcasecompare(os, "OS/400")) {
/* Force OS400 name format 1. */
- result = Curl_pp_sendf(&ftpc->pp, "%s", "SITE NAMEFMT 1");
+ result = Curl_pp_sendf(data, &ftpc->pp, "%s", "SITE NAMEFMT 1");
if(result) {
free(os);
return result;
@@ -2905,7 +2933,7 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
/* remember target server OS */
Curl_safefree(ftpc->server_os);
ftpc->server_os = os;
- state(conn, FTP_NAMEFMT);
+ state(data, FTP_NAMEFMT);
break;
}
/* Nothing special for the target server. */
@@ -2917,18 +2945,18 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
/* Cannot identify server OS. Continue anyway and cross fingers. */
}
- state(conn, FTP_STOP); /* we are done with the CONNECT phase! */
+ state(data, FTP_STOP); /* we are done with the CONNECT phase! */
DEBUGF(infof(data, "protocol connect phase DONE\n"));
break;
case FTP_NAMEFMT:
if(ftpcode == 250) {
/* Name format change successful: reload initial path. */
- ftp_state_pwd(conn);
+ ftp_state_pwd(data, conn);
break;
}
- state(conn, FTP_STOP); /* we are done with the CONNECT phase! */
+ state(data, FTP_STOP); /* we are done with the CONNECT phase! */
DEBUGF(infof(data, "protocol connect phase DONE\n"));
break;
@@ -2938,45 +2966,42 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
case FTP_STOR_PREQUOTE:
if((ftpcode >= 400) && !ftpc->count2) {
/* failure response code, and not allowed to fail */
- failf(conn->data, "QUOT command failed with %03d", ftpcode);
- return CURLE_QUOTE_ERROR;
+ failf(data, "QUOT command failed with %03d", ftpcode);
+ result = CURLE_QUOTE_ERROR;
}
- result = ftp_state_quote(conn, FALSE, ftpc->state);
- if(result)
- return result;
-
+ else
+ result = ftp_state_quote(data, FALSE, ftpc->state);
break;
case FTP_CWD:
if(ftpcode/100 != 2) {
/* failure to CWD there */
- if(conn->data->set.ftp_create_missing_dirs &&
+ if(data->set.ftp_create_missing_dirs &&
ftpc->cwdcount && !ftpc->count2) {
/* try making it */
ftpc->count2++; /* counter to prevent CWD-MKD loops */
- PPSENDF(&ftpc->pp, "MKD %s", ftpc->dirs[ftpc->cwdcount - 1]);
- state(conn, FTP_MKD);
+ result = Curl_pp_sendf(data, &ftpc->pp, "MKD %s",
+ ftpc->dirs[ftpc->cwdcount - 1]);
+ if(!result)
+ state(data, FTP_MKD);
}
else {
/* return failure */
failf(data, "Server denied you to change to the given directory");
ftpc->cwdfail = TRUE; /* don't remember this path as we failed
to enter it */
- return CURLE_REMOTE_ACCESS_DENIED;
+ result = CURLE_REMOTE_ACCESS_DENIED;
}
}
else {
/* success */
ftpc->count2 = 0;
- if(++ftpc->cwdcount <= ftpc->dirdepth) {
+ if(++ftpc->cwdcount <= ftpc->dirdepth)
/* send next CWD */
- PPSENDF(&ftpc->pp, "CWD %s", ftpc->dirs[ftpc->cwdcount - 1]);
- }
- else {
- result = ftp_state_mdtm(conn);
- if(result)
- return result;
- }
+ result = Curl_pp_sendf(data, &ftpc->pp, "CWD %s",
+ ftpc->dirs[ftpc->cwdcount - 1]);
+ else
+ result = ftp_state_mdtm(data);
}
break;
@@ -2984,33 +3009,36 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
if((ftpcode/100 != 2) && !ftpc->count3--) {
/* failure to MKD the dir */
failf(data, "Failed to MKD dir: %03d", ftpcode);
- return CURLE_REMOTE_ACCESS_DENIED;
+ result = CURLE_REMOTE_ACCESS_DENIED;
+ }
+ else {
+ state(data, FTP_CWD);
+ /* send CWD */
+ result = Curl_pp_sendf(data, &ftpc->pp, "CWD %s",
+ ftpc->dirs[ftpc->cwdcount - 1]);
}
- state(conn, FTP_CWD);
- /* send CWD */
- PPSENDF(&ftpc->pp, "CWD %s", ftpc->dirs[ftpc->cwdcount - 1]);
break;
case FTP_MDTM:
- result = ftp_state_mdtm_resp(conn, ftpcode);
+ result = ftp_state_mdtm_resp(data, ftpcode);
break;
case FTP_TYPE:
case FTP_LIST_TYPE:
case FTP_RETR_TYPE:
case FTP_STOR_TYPE:
- result = ftp_state_type_resp(conn, ftpcode, ftpc->state);
+ result = ftp_state_type_resp(data, ftpcode, ftpc->state);
break;
case FTP_SIZE:
case FTP_RETR_SIZE:
case FTP_STOR_SIZE:
- result = ftp_state_size_resp(conn, ftpcode, ftpc->state);
+ result = ftp_state_size_resp(data, ftpcode, ftpc->state);
break;
case FTP_REST:
case FTP_RETR_REST:
- result = ftp_state_rest_resp(conn, ftpcode, ftpc->state);
+ result = ftp_state_rest_resp(data, conn, ftpcode, ftpc->state);
break;
case FTP_PRET:
@@ -3019,31 +3047,31 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
failf(data, "PRET command not accepted: %03d", ftpcode);
return CURLE_FTP_PRET_FAILED;
}
- result = ftp_state_use_pasv(conn);
+ result = ftp_state_use_pasv(data, conn);
break;
case FTP_PASV:
- result = ftp_state_pasv_resp(conn, ftpcode);
+ result = ftp_state_pasv_resp(data, ftpcode);
break;
case FTP_PORT:
- result = ftp_state_port_resp(conn, ftpcode);
+ result = ftp_state_port_resp(data, ftpcode);
break;
case FTP_LIST:
case FTP_RETR:
- result = ftp_state_get_resp(conn, ftpcode, ftpc->state);
+ result = ftp_state_get_resp(data, ftpcode, ftpc->state);
break;
case FTP_STOR:
- result = ftp_state_stor_resp(conn, ftpcode, ftpc->state);
+ result = ftp_state_stor_resp(data, ftpcode, ftpc->state);
break;
case FTP_QUIT:
/* fallthrough, just stop! */
default:
/* internal error */
- state(conn, FTP_STOP);
+ state(data, FTP_STOP);
break;
}
} /* if(ftpcode) */
@@ -3053,11 +3081,12 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
/* called repeatedly until done from multi.c */
-static CURLcode ftp_multi_statemach(struct connectdata *conn,
+static CURLcode ftp_multi_statemach(struct Curl_easy *data,
bool *done)
{
+ struct connectdata *conn = data->conn;
struct ftp_conn *ftpc = &conn->proto.ftpc;
- CURLcode result = Curl_pp_statemach(&ftpc->pp, FALSE, FALSE);
+ CURLcode result = Curl_pp_statemach(data, &ftpc->pp, FALSE, FALSE);
/* Check for the state outside of the Curl_socket_check() return code checks
since at times we are in fact already in this state when this function
@@ -3067,14 +3096,15 @@ static CURLcode ftp_multi_statemach(struct connectdata *conn,
return result;
}
-static CURLcode ftp_block_statemach(struct connectdata *conn)
+static CURLcode ftp_block_statemach(struct Curl_easy *data,
+ struct connectdata *conn)
{
struct ftp_conn *ftpc = &conn->proto.ftpc;
struct pingpong *pp = &ftpc->pp;
CURLcode result = CURLE_OK;
while(ftpc->state != FTP_STOP) {
- result = Curl_pp_statemach(pp, TRUE, TRUE /* disconnecting */);
+ result = Curl_pp_statemach(data, pp, TRUE, TRUE /* disconnecting */);
if(result)
break;
}
@@ -3090,10 +3120,11 @@ static CURLcode ftp_block_statemach(struct connectdata *conn)
* phase is done when this function returns, or FALSE if not.
*
*/
-static CURLcode ftp_connect(struct connectdata *conn,
- bool *done) /* see description above */
+static CURLcode ftp_connect(struct Curl_easy *data,
+ bool *done) /* see description above */
{
CURLcode result;
+ struct connectdata *conn = data->conn;
struct ftp_conn *ftpc = &conn->proto.ftpc;
struct pingpong *pp = &ftpc->pp;
@@ -3102,25 +3133,24 @@ static CURLcode ftp_connect(struct connectdata *conn,
/* We always support persistent connections on ftp */
connkeep(conn, "FTP default");
- pp->response_time = RESP_TIMEOUT; /* set default response time-out */
- pp->statemach_act = ftp_statemach_act;
- pp->endofresp = ftp_endofresp;
- pp->conn = conn;
+ PINGPONG_SETUP(pp, ftp_statemachine, ftp_endofresp);
if(conn->handler->flags & PROTOPT_SSL) {
/* BLOCKING */
- result = Curl_ssl_connect(conn, FIRSTSOCKET);
+ result = Curl_ssl_connect(data, conn, FIRSTSOCKET);
if(result)
return result;
+ conn->bits.ftp_use_control_ssl = TRUE;
}
- Curl_pp_init(pp); /* init the generic pingpong data */
+ Curl_pp_setup(pp); /* once per transfer */
+ Curl_pp_init(data, pp); /* init the generic pingpong data */
/* When we connect, we start in the state where we await the 220
response */
- state(conn, FTP_WAIT220);
+ state(data, FTP_WAIT220);
- result = ftp_multi_statemach(conn, done);
+ result = ftp_multi_statemach(data, done);
return result;
}
@@ -3134,11 +3164,11 @@ static CURLcode ftp_connect(struct connectdata *conn,
*
* Input argument is already checked for validity.
*/
-static CURLcode ftp_done(struct connectdata *conn, CURLcode status,
+static CURLcode ftp_done(struct Curl_easy *data, CURLcode status,
bool premature)
{
- struct Curl_easy *data = conn->data;
- struct FTP *ftp = data->req.protop;
+ struct connectdata *conn = data->conn;
+ struct FTP *ftp = data->req.p.ftp;
struct ftp_conn *ftpc = &conn->proto.ftpc;
struct pingpong *pp = &ftpc->pp;
ssize_t nread;
@@ -3241,7 +3271,7 @@ static CURLcode ftp_done(struct connectdata *conn, CURLcode status,
if(conn->sock[SECONDARYSOCKET] != CURL_SOCKET_BAD) {
if(!result && ftpc->dont_check && data->req.maxdownload > 0) {
/* partial download completed */
- result = Curl_pp_sendf(pp, "%s", "ABOR");
+ result = Curl_pp_sendf(data, pp, "%s", "ABOR");
if(result) {
failf(data, "Failure sending ABOR command: %s",
curl_easy_strerror(result));
@@ -3253,12 +3283,12 @@ static CURLcode ftp_done(struct connectdata *conn, CURLcode status,
if(conn->ssl[SECONDARYSOCKET].use) {
/* The secondary socket is using SSL so we must close down that part
first before we close the socket for real */
- Curl_ssl_close(conn, SECONDARYSOCKET);
+ Curl_ssl_close(data, conn, SECONDARYSOCKET);
/* Note that we keep "use" set to TRUE since that (next) connection is
still requested to use SSL */
}
- close_secondarysocket(conn);
+ close_secondarysocket(data, conn);
}
if(!result && (ftp->transfer == FTPTRANSFER_BODY) && ftpc->ctl_valid &&
@@ -3274,7 +3304,7 @@ static CURLcode ftp_done(struct connectdata *conn, CURLcode status,
pp->response_time = 60*1000; /* give it only a minute for now */
pp->response = Curl_now(); /* timeout relative now */
- result = Curl_GetFTPResponse(&nread, conn, &ftpcode);
+ result = Curl_GetFTPResponse(data, &nread, &ftpcode);
pp->response_time = old_time; /* set this back to previous value */
@@ -3297,9 +3327,18 @@ static CURLcode ftp_done(struct connectdata *conn, CURLcode status,
if(!ftpc->dont_check) {
/* 226 Transfer complete, 250 Requested file action okay, completed. */
- if((ftpcode != 226) && (ftpcode != 250)) {
+ switch(ftpcode) {
+ case 226:
+ case 250:
+ break;
+ case 552:
+ failf(data, "Exceeded storage allocation");
+ result = CURLE_REMOTE_DISK_FULL;
+ break;
+ default:
failf(data, "server did not report OK, got %d", ftpcode);
result = CURLE_PARTIAL_FILE;
+ break;
}
}
}
@@ -3349,7 +3388,7 @@ static CURLcode ftp_done(struct connectdata *conn, CURLcode status,
/* Send any post-transfer QUOTE strings? */
if(!status && !result && !premature && data->set.postquote)
- result = ftp_sendquote(conn, data->set.postquote);
+ result = ftp_sendquote(data, conn, data->set.postquote);
Curl_safefree(ftp->pathalloc);
return result;
}
@@ -3365,20 +3404,21 @@ static CURLcode ftp_done(struct connectdata *conn, CURLcode status,
*/
static
-CURLcode ftp_sendquote(struct connectdata *conn, struct curl_slist *quote)
+CURLcode ftp_sendquote(struct Curl_easy *data,
+ struct connectdata *conn, struct curl_slist *quote)
{
struct curl_slist *item;
- ssize_t nread;
- int ftpcode;
- CURLcode result;
struct ftp_conn *ftpc = &conn->proto.ftpc;
struct pingpong *pp = &ftpc->pp;
item = quote;
while(item) {
if(item->data) {
+ ssize_t nread;
char *cmd = item->data;
bool acceptfail = FALSE;
+ CURLcode result;
+ int ftpcode = 0;
/* if a command starts with an asterisk, which a legal FTP command never
can, the command will be allowed to fail without it causing any
@@ -3390,16 +3430,16 @@ CURLcode ftp_sendquote(struct connectdata *conn, struct curl_slist *quote)
acceptfail = TRUE;
}
- PPSENDF(&conn->proto.ftpc.pp, "%s", cmd);
-
- pp->response = Curl_now(); /* timeout relative now */
-
- result = Curl_GetFTPResponse(&nread, conn, &ftpcode);
+ result = Curl_pp_sendf(data, &ftpc->pp, "%s", cmd);
+ if(!result) {
+ pp->response = Curl_now(); /* timeout relative now */
+ result = Curl_GetFTPResponse(data, &nread, &ftpcode);
+ }
if(result)
return result;
if(!acceptfail && (ftpcode >= 400)) {
- failf(conn->data, "QUOT string not accepted: %s", cmd);
+ failf(data, "QUOT string not accepted: %s", cmd);
return CURLE_QUOTE_ERROR;
}
}
@@ -3430,7 +3470,8 @@ static int ftp_need_type(struct connectdata *conn,
* sets one of them.
* If the transfer type is not sent, simulate on OK response in newstate
*/
-static CURLcode ftp_nb_type(struct connectdata *conn,
+static CURLcode ftp_nb_type(struct Curl_easy *data,
+ struct connectdata *conn,
bool ascii, ftpstate newstate)
{
struct ftp_conn *ftpc = &conn->proto.ftpc;
@@ -3438,16 +3479,18 @@ static CURLcode ftp_nb_type(struct connectdata *conn,
char want = (char)(ascii?'A':'I');
if(ftpc->transfertype == want) {
- state(conn, newstate);
- return ftp_state_type_resp(conn, 200, newstate);
+ state(data, newstate);
+ return ftp_state_type_resp(data, 200, newstate);
}
- PPSENDF(&ftpc->pp, "TYPE %c", want);
- state(conn, newstate);
+ result = Curl_pp_sendf(data, &ftpc->pp, "TYPE %c", want);
+ if(!result) {
+ state(data, newstate);
- /* keep track of our current transfer type */
- ftpc->transfertype = want;
- return CURLE_OK;
+ /* keep track of our current transfer type */
+ ftpc->transfertype = want;
+ }
+ return result;
}
/***************************************************************************
@@ -3461,14 +3504,14 @@ static CURLcode ftp_nb_type(struct connectdata *conn,
*/
#ifndef CURL_DISABLE_VERBOSE_STRINGS
static void
-ftp_pasv_verbose(struct connectdata *conn,
+ftp_pasv_verbose(struct Curl_easy *data,
struct Curl_addrinfo *ai,
char *newhost, /* ascii version */
int port)
{
char buf[256];
Curl_printable_address(ai, buf, sizeof(buf));
- infof(conn->data, "Connecting to %s (%s) port %d\n", newhost, buf, port);
+ infof(data, "Connecting to %s (%s) port %d\n", newhost, buf, port);
}
#endif
@@ -3483,28 +3526,28 @@ ftp_pasv_verbose(struct connectdata *conn,
* EPSV).
*/
-static CURLcode ftp_do_more(struct connectdata *conn, int *completep)
+static CURLcode ftp_do_more(struct Curl_easy *data, int *completep)
{
- struct Curl_easy *data = conn->data;
+ struct connectdata *conn = data->conn;
struct ftp_conn *ftpc = &conn->proto.ftpc;
CURLcode result = CURLE_OK;
bool connected = FALSE;
bool complete = FALSE;
/* the ftp struct is inited in ftp_connect() */
- struct FTP *ftp = data->req.protop;
+ struct FTP *ftp = data->req.p.ftp;
/* if the second connection isn't done yet, wait for it */
if(!conn->bits.tcpconnect[SECONDARYSOCKET]) {
if(Curl_connect_ongoing(conn)) {
/* As we're in TUNNEL_CONNECT state now, we know the proxy name and port
aren't used so we blank their arguments. */
- result = Curl_proxyCONNECT(conn, SECONDARYSOCKET, NULL, 0);
+ result = Curl_proxyCONNECT(data, SECONDARYSOCKET, NULL, 0);
return result;
}
- result = Curl_is_connected(conn, SECONDARYSOCKET, &connected);
+ result = Curl_is_connected(data, conn, SECONDARYSOCKET, &connected);
/* Ready to do more? */
if(connected) {
@@ -3514,14 +3557,14 @@ static CURLcode ftp_do_more(struct connectdata *conn, int *completep)
if(result && (ftpc->count1 == 0)) {
*completep = -1; /* go back to DOING please */
/* this is a EPSV connect failing, try PASV instead */
- return ftp_epsv_disable(conn);
+ return ftp_epsv_disable(data, conn);
}
return result;
}
}
#ifndef CURL_DISABLE_PROXY
- result = Curl_proxy_connect(conn, SECONDARYSOCKET);
+ result = Curl_proxy_connect(data, SECONDARYSOCKET);
if(result)
return result;
@@ -3536,7 +3579,7 @@ static CURLcode ftp_do_more(struct connectdata *conn, int *completep)
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(conn, &complete);
+ result = ftp_multi_statemach(data, &complete);
*completep = (int)complete;
@@ -3558,16 +3601,16 @@ static CURLcode ftp_do_more(struct connectdata *conn, int *completep)
if(ftpc->wait_data_conn == TRUE) {
bool serv_conned;
- result = ReceivedServerConnect(conn, &serv_conned);
+ result = ReceivedServerConnect(data, &serv_conned);
if(result)
return result; /* Failed to accept data connection */
if(serv_conned) {
/* It looks data connection is established */
- result = AcceptServerConnect(conn);
+ result = AcceptServerConnect(data);
ftpc->wait_data_conn = FALSE;
if(!result)
- result = InitiateTransfer(conn);
+ result = InitiateTransfer(data);
if(result)
return result;
@@ -3577,11 +3620,11 @@ static CURLcode ftp_do_more(struct connectdata *conn, int *completep)
}
}
else if(data->set.upload) {
- result = ftp_nb_type(conn, data->set.prefer_ascii, FTP_STOR_TYPE);
+ result = ftp_nb_type(data, conn, data->set.prefer_ascii, FTP_STOR_TYPE);
if(result)
return result;
- result = ftp_multi_statemach(conn, &complete);
+ result = ftp_multi_statemach(data, &complete);
/* ftpc->wait_data_conn is always false here */
*completep = (int)complete;
}
@@ -3589,7 +3632,7 @@ static CURLcode ftp_do_more(struct connectdata *conn, int *completep)
/* download */
ftp->downloadsize = -1; /* unknown as of yet */
- result = Curl_range(conn);
+ result = Curl_range(data);
if(result == CURLE_OK && data->req.maxdownload >= 0) {
/* Don't check for successful transfer */
@@ -3605,19 +3648,20 @@ static CURLcode ftp_do_more(struct connectdata *conn, int *completep)
/* But only if a body transfer was requested. */
if(ftp->transfer == FTPTRANSFER_BODY) {
- result = ftp_nb_type(conn, TRUE, FTP_LIST_TYPE);
+ result = ftp_nb_type(data, conn, TRUE, FTP_LIST_TYPE);
if(result)
return result;
}
/* otherwise just fall through */
}
else {
- result = ftp_nb_type(conn, data->set.prefer_ascii, FTP_RETR_TYPE);
+ result = ftp_nb_type(data, conn, data->set.prefer_ascii,
+ FTP_RETR_TYPE);
if(result)
return result;
}
- result = ftp_multi_statemach(conn, &complete);
+ result = ftp_multi_statemach(data, &complete);
*completep = (int)complete;
}
return result;
@@ -3646,37 +3690,38 @@ static CURLcode ftp_do_more(struct connectdata *conn, int *completep)
*/
static
-CURLcode ftp_perform(struct connectdata *conn,
+CURLcode ftp_perform(struct Curl_easy *data,
bool *connected, /* connect status after PASV / PORT */
bool *dophase_done)
{
/* this is FTP and no proxy */
CURLcode result = CURLE_OK;
+ struct connectdata *conn = data->conn;
- DEBUGF(infof(conn->data, "DO phase starts\n"));
+ DEBUGF(infof(data, "DO phase starts\n"));
- if(conn->data->set.opt_no_body) {
+ if(data->set.opt_no_body) {
/* requested no body means no transfer... */
- struct FTP *ftp = conn->data->req.protop;
+ struct FTP *ftp = data->req.p.ftp;
ftp->transfer = FTPTRANSFER_INFO;
}
*dophase_done = FALSE; /* not done yet */
/* start the first command in the DO phase */
- result = ftp_state_quote(conn, TRUE, FTP_QUOTE);
+ result = ftp_state_quote(data, TRUE, FTP_QUOTE);
if(result)
return result;
/* run the state-machine */
- result = ftp_multi_statemach(conn, dophase_done);
+ result = ftp_multi_statemach(data, dophase_done);
*connected = conn->bits.tcpconnect[SECONDARYSOCKET];
- infof(conn->data, "ftp_perform ends with SECONDARY: %d\n", *connected);
+ infof(data, "ftp_perform ends with SECONDARY: %d\n", *connected);
if(*dophase_done) {
- DEBUGF(infof(conn->data, "DO phase is complete1\n"));
+ DEBUGF(infof(data, "DO phase is complete1\n"));
}
return result;
@@ -3690,12 +3735,12 @@ static void wc_data_dtor(void *ptr)
free(ftpwc);
}
-static CURLcode init_wc_data(struct connectdata *conn)
+static CURLcode init_wc_data(struct Curl_easy *data)
{
char *last_slash;
- struct FTP *ftp = conn->data->req.protop;
+ struct FTP *ftp = data->req.p.ftp;
char *path = ftp->path;
- struct WildcardData *wildcard = &(conn->data->wildcard);
+ struct WildcardData *wildcard = &(data->wildcard);
CURLcode result = CURLE_OK;
struct ftp_wc *ftpwc = NULL;
@@ -3704,7 +3749,7 @@ static CURLcode init_wc_data(struct connectdata *conn)
last_slash++;
if(last_slash[0] == '\0') {
wildcard->state = CURLWC_CLEAN;
- result = ftp_parse_url_path(conn);
+ result = ftp_parse_url_path(data);
return result;
}
wildcard->pattern = strdup(last_slash);
@@ -3721,7 +3766,7 @@ static CURLcode init_wc_data(struct connectdata *conn)
}
else { /* only list */
wildcard->state = CURLWC_CLEAN;
- result = ftp_parse_url_path(conn);
+ result = ftp_parse_url_path(data);
return result;
}
}
@@ -3747,11 +3792,11 @@ static CURLcode init_wc_data(struct connectdata *conn)
wildcard->dtor = wc_data_dtor;
/* wildcard does not support NOCWD option (assert it?) */
- if(conn->data->set.ftp_filemethod == FTPFILE_NOCWD)
- conn->data->set.ftp_filemethod = FTPFILE_MULTICWD;
+ if(data->set.ftp_filemethod == FTPFILE_NOCWD)
+ data->set.ftp_filemethod = FTPFILE_MULTICWD;
/* try to parse ftp url */
- result = ftp_parse_url_path(conn);
+ result = ftp_parse_url_path(data);
if(result) {
goto fail;
}
@@ -3763,15 +3808,15 @@ static CURLcode init_wc_data(struct connectdata *conn)
}
/* backup old write_function */
- ftpwc->backup.write_function = conn->data->set.fwrite_func;
+ ftpwc->backup.write_function = data->set.fwrite_func;
/* parsing write function */
- conn->data->set.fwrite_func = Curl_ftp_parselist;
+ data->set.fwrite_func = Curl_ftp_parselist;
/* backup old file descriptor */
- ftpwc->backup.file_descriptor = conn->data->set.out;
- /* let the writefunc callback know what curl pointer is working with */
- conn->data->set.out = conn;
+ ftpwc->backup.file_descriptor = data->set.out;
+ /* let the writefunc callback know the transfer */
+ data->set.out = data;
- infof(conn->data, "Wildcard - Parsing started\n");
+ infof(data, "Wildcard - Parsing started\n");
return CURLE_OK;
fail:
@@ -3785,129 +3830,132 @@ static CURLcode init_wc_data(struct connectdata *conn)
return result;
}
-/* This is called recursively */
-static CURLcode wc_statemach(struct connectdata *conn)
+static CURLcode wc_statemach(struct Curl_easy *data)
{
- struct WildcardData * const wildcard = &(conn->data->wildcard);
+ struct WildcardData * const wildcard = &(data->wildcard);
+ struct connectdata *conn = data->conn;
CURLcode result = CURLE_OK;
- switch(wildcard->state) {
- case CURLWC_INIT:
- result = init_wc_data(conn);
- if(wildcard->state == CURLWC_CLEAN)
- /* only listing! */
- break;
- wildcard->state = result ? CURLWC_ERROR : CURLWC_MATCHING;
- break;
+ for(;;) {
+ switch(wildcard->state) {
+ case CURLWC_INIT:
+ result = init_wc_data(data);
+ if(wildcard->state == CURLWC_CLEAN)
+ /* only listing! */
+ return result;
+ wildcard->state = result ? CURLWC_ERROR : CURLWC_MATCHING;
+ return result;
- case CURLWC_MATCHING: {
- /* In this state is LIST response successfully parsed, so lets restore
- previous WRITEFUNCTION callback and WRITEDATA pointer */
- struct ftp_wc *ftpwc = wildcard->protdata;
- conn->data->set.fwrite_func = ftpwc->backup.write_function;
- conn->data->set.out = ftpwc->backup.file_descriptor;
- ftpwc->backup.write_function = ZERO_NULL;
- ftpwc->backup.file_descriptor = NULL;
- wildcard->state = CURLWC_DOWNLOADING;
-
- if(Curl_ftp_parselist_geterror(ftpwc->parser)) {
- /* error found in LIST parsing */
- wildcard->state = CURLWC_CLEAN;
- return wc_statemach(conn);
- }
- if(wildcard->filelist.size == 0) {
- /* no corresponding file */
- wildcard->state = CURLWC_CLEAN;
- return CURLE_REMOTE_FILE_NOT_FOUND;
+ case CURLWC_MATCHING: {
+ /* In this state is LIST response successfully parsed, so lets restore
+ previous WRITEFUNCTION callback and WRITEDATA pointer */
+ struct ftp_wc *ftpwc = wildcard->protdata;
+ data->set.fwrite_func = ftpwc->backup.write_function;
+ data->set.out = ftpwc->backup.file_descriptor;
+ ftpwc->backup.write_function = ZERO_NULL;
+ ftpwc->backup.file_descriptor = NULL;
+ wildcard->state = CURLWC_DOWNLOADING;
+
+ if(Curl_ftp_parselist_geterror(ftpwc->parser)) {
+ /* error found in LIST parsing */
+ wildcard->state = CURLWC_CLEAN;
+ continue;
+ }
+ if(wildcard->filelist.size == 0) {
+ /* no corresponding file */
+ wildcard->state = CURLWC_CLEAN;
+ return CURLE_REMOTE_FILE_NOT_FOUND;
+ }
+ continue;
}
- return wc_statemach(conn);
- }
- case CURLWC_DOWNLOADING: {
- /* filelist has at least one file, lets get first one */
- struct ftp_conn *ftpc = &conn->proto.ftpc;
- struct curl_fileinfo *finfo = wildcard->filelist.head->ptr;
- struct FTP *ftp = conn->data->req.protop;
+ case CURLWC_DOWNLOADING: {
+ /* filelist has at least one file, lets get first one */
+ struct ftp_conn *ftpc = &conn->proto.ftpc;
+ struct curl_fileinfo *finfo = wildcard->filelist.head->ptr;
+ struct FTP *ftp = data->req.p.ftp;
- char *tmp_path = aprintf("%s%s", wildcard->path, finfo->filename);
- if(!tmp_path)
- return CURLE_OUT_OF_MEMORY;
+ char *tmp_path = aprintf("%s%s", wildcard->path, finfo->filename);
+ if(!tmp_path)
+ return CURLE_OUT_OF_MEMORY;
- /* switch default ftp->path and tmp_path */
- free(ftp->pathalloc);
- ftp->pathalloc = ftp->path = tmp_path;
-
- infof(conn->data, "Wildcard - START of \"%s\"\n", finfo->filename);
- if(conn->data->set.chunk_bgn) {
- long userresponse;
- Curl_set_in_callback(conn->data, true);
- userresponse = conn->data->set.chunk_bgn(
- finfo, wildcard->customptr, (int)wildcard->filelist.size);
- Curl_set_in_callback(conn->data, false);
- switch(userresponse) {
- case CURL_CHUNK_BGN_FUNC_SKIP:
- infof(conn->data, "Wildcard - \"%s\" skipped by user\n",
- finfo->filename);
- wildcard->state = CURLWC_SKIP;
- return wc_statemach(conn);
- case CURL_CHUNK_BGN_FUNC_FAIL:
- return CURLE_CHUNK_FAILED;
+ /* switch default ftp->path and tmp_path */
+ free(ftp->pathalloc);
+ ftp->pathalloc = ftp->path = tmp_path;
+
+ infof(data, "Wildcard - START of \"%s\"\n", finfo->filename);
+ if(data->set.chunk_bgn) {
+ long userresponse;
+ Curl_set_in_callback(data, true);
+ userresponse = data->set.chunk_bgn(
+ finfo, wildcard->customptr, (int)wildcard->filelist.size);
+ Curl_set_in_callback(data, false);
+ switch(userresponse) {
+ case CURL_CHUNK_BGN_FUNC_SKIP:
+ infof(data, "Wildcard - \"%s\" skipped by user\n",
+ finfo->filename);
+ wildcard->state = CURLWC_SKIP;
+ continue;
+ case CURL_CHUNK_BGN_FUNC_FAIL:
+ return CURLE_CHUNK_FAILED;
+ }
}
- }
- if(finfo->filetype != CURLFILETYPE_FILE) {
- wildcard->state = CURLWC_SKIP;
- return wc_statemach(conn);
- }
+ if(finfo->filetype != CURLFILETYPE_FILE) {
+ wildcard->state = CURLWC_SKIP;
+ continue;
+ }
- if(finfo->flags & CURLFINFOFLAG_KNOWN_SIZE)
- ftpc->known_filesize = finfo->size;
+ if(finfo->flags & CURLFINFOFLAG_KNOWN_SIZE)
+ ftpc->known_filesize = finfo->size;
- result = ftp_parse_url_path(conn);
- if(result)
- return result;
+ result = ftp_parse_url_path(data);
+ if(result)
+ return result;
- /* we don't need the Curl_fileinfo of first file anymore */
- Curl_llist_remove(&wildcard->filelist, wildcard->filelist.head, NULL);
+ /* we don't need the Curl_fileinfo of first file anymore */
+ Curl_llist_remove(&wildcard->filelist, wildcard->filelist.head, NULL);
- if(wildcard->filelist.size == 0) { /* remains only one file to down. */
- wildcard->state = CURLWC_CLEAN;
- /* after that will be ftp_do called once again and no transfer
- will be done because of CURLWC_CLEAN state */
- return CURLE_OK;
+ if(wildcard->filelist.size == 0) { /* remains only one file to down. */
+ wildcard->state = CURLWC_CLEAN;
+ /* after that will be ftp_do called once again and no transfer
+ will be done because of CURLWC_CLEAN state */
+ return CURLE_OK;
+ }
+ return result;
}
- } break;
- case CURLWC_SKIP: {
- if(conn->data->set.chunk_end) {
- Curl_set_in_callback(conn->data, true);
- conn->data->set.chunk_end(conn->data->wildcard.customptr);
- Curl_set_in_callback(conn->data, false);
+ case CURLWC_SKIP: {
+ if(data->set.chunk_end) {
+ Curl_set_in_callback(data, true);
+ data->set.chunk_end(data->wildcard.customptr);
+ Curl_set_in_callback(data, false);
+ }
+ Curl_llist_remove(&wildcard->filelist, wildcard->filelist.head, NULL);
+ wildcard->state = (wildcard->filelist.size == 0) ?
+ CURLWC_CLEAN : CURLWC_DOWNLOADING;
+ continue;
}
- Curl_llist_remove(&wildcard->filelist, wildcard->filelist.head, NULL);
- wildcard->state = (wildcard->filelist.size == 0) ?
- CURLWC_CLEAN : CURLWC_DOWNLOADING;
- return wc_statemach(conn);
- }
- case CURLWC_CLEAN: {
- struct ftp_wc *ftpwc = wildcard->protdata;
- result = CURLE_OK;
- if(ftpwc)
- result = Curl_ftp_parselist_geterror(ftpwc->parser);
+ case CURLWC_CLEAN: {
+ struct ftp_wc *ftpwc = wildcard->protdata;
+ result = CURLE_OK;
+ if(ftpwc)
+ result = Curl_ftp_parselist_geterror(ftpwc->parser);
- wildcard->state = result ? CURLWC_ERROR : CURLWC_DONE;
- } break;
+ wildcard->state = result ? CURLWC_ERROR : CURLWC_DONE;
+ return result;
+ }
- case CURLWC_DONE:
- case CURLWC_ERROR:
- case CURLWC_CLEAR:
- if(wildcard->dtor)
- wildcard->dtor(wildcard->protdata);
- break;
+ case CURLWC_DONE:
+ case CURLWC_ERROR:
+ case CURLWC_CLEAR:
+ if(wildcard->dtor)
+ wildcard->dtor(wildcard->protdata);
+ return result;
+ }
}
-
- return result;
+ /* UNREACHABLE */
}
/***********************************************************************
@@ -3919,18 +3967,19 @@ static CURLcode wc_statemach(struct connectdata *conn)
*
* The input argument is already checked for validity.
*/
-static CURLcode ftp_do(struct connectdata *conn, bool *done)
+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;
*done = FALSE; /* default to false */
ftpc->wait_data_conn = FALSE; /* default to no such wait */
- if(conn->data->state.wildcardmatch) {
- result = wc_statemach(conn);
- if(conn->data->wildcard.state == CURLWC_SKIP ||
- conn->data->wildcard.state == CURLWC_DONE) {
+ if(data->state.wildcardmatch) {
+ result = wc_statemach(data);
+ if(data->wildcard.state == CURLWC_SKIP ||
+ data->wildcard.state == CURLWC_DONE) {
/* do not call ftp_regular_transfer */
return CURLE_OK;
}
@@ -3938,70 +3987,12 @@ static CURLcode ftp_do(struct connectdata *conn, bool *done)
return result;
}
else { /* no wildcard FSM needed */
- result = ftp_parse_url_path(conn);
+ result = ftp_parse_url_path(data);
if(result)
return result;
}
- result = ftp_regular_transfer(conn, done);
-
- return result;
-}
-
-
-CURLcode Curl_ftpsend(struct connectdata *conn, const char *cmd)
-{
- ssize_t bytes_written;
-#define SBUF_SIZE 1024
- char s[SBUF_SIZE];
- size_t write_len;
- char *sptr = s;
- CURLcode result = CURLE_OK;
-#ifdef HAVE_GSSAPI
- enum protection_level data_sec = conn->data_prot;
-#endif
-
- if(!cmd)
- return CURLE_BAD_FUNCTION_ARGUMENT;
-
- write_len = strlen(cmd);
- if(!write_len || write_len > (sizeof(s) -3))
- return CURLE_BAD_FUNCTION_ARGUMENT;
-
- memcpy(&s, cmd, write_len);
- strcpy(&s[write_len], "\r\n"); /* append a trailing CRLF */
- write_len += 2;
- bytes_written = 0;
-
- result = Curl_convert_to_network(conn->data, s, write_len);
- /* Curl_convert_to_network calls failf if unsuccessful */
- if(result)
- return result;
-
- for(;;) {
-#ifdef HAVE_GSSAPI
- conn->data_prot = PROT_CMD;
-#endif
- result = Curl_write(conn, conn->sock[FIRSTSOCKET], sptr, write_len,
- &bytes_written);
-#ifdef HAVE_GSSAPI
- DEBUGASSERT(data_sec > PROT_NONE && data_sec < PROT_LAST);
- conn->data_prot = data_sec;
-#endif
-
- if(result)
- break;
-
- if(conn->data->set.verbose)
- Curl_debug(conn->data, CURLINFO_HEADER_OUT, sptr, (size_t)bytes_written);
-
- if(bytes_written != (ssize_t)write_len) {
- write_len -= bytes_written;
- sptr += bytes_written;
- }
- else
- break;
- }
+ result = ftp_regular_transfer(data, done);
return result;
}
@@ -4016,24 +4007,24 @@ CURLcode Curl_ftpsend(struct connectdata *conn, const char *cmd)
* connection.
*
*/
-static CURLcode ftp_quit(struct connectdata *conn)
+static CURLcode ftp_quit(struct Curl_easy *data, struct connectdata *conn)
{
CURLcode result = CURLE_OK;
if(conn->proto.ftpc.ctl_valid) {
- result = Curl_pp_sendf(&conn->proto.ftpc.pp, "%s", "QUIT");
+ result = Curl_pp_sendf(data, &conn->proto.ftpc.pp, "%s", "QUIT");
if(result) {
- failf(conn->data, "Failure sending QUIT command: %s",
+ 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 */
- state(conn, FTP_STOP);
+ state(data, FTP_STOP);
return result;
}
- state(conn, FTP_QUIT);
+ state(data, FTP_QUIT);
- result = ftp_block_statemach(conn);
+ result = ftp_block_statemach(data, conn);
}
return result;
@@ -4046,7 +4037,9 @@ static CURLcode ftp_quit(struct connectdata *conn)
* Disconnect from an FTP server. Cleanup protocol-specific per-connection
* resources. BLOCKING.
*/
-static CURLcode ftp_disconnect(struct connectdata *conn, bool dead_connection)
+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;
@@ -4062,29 +4055,20 @@ static CURLcode ftp_disconnect(struct connectdata *conn, bool dead_connection)
ftpc->ctl_valid = FALSE;
/* The FTP session may or may not have been allocated/setup at this point! */
- (void)ftp_quit(conn); /* ignore errors on the QUIT */
+ (void)ftp_quit(data, conn); /* ignore errors on the QUIT */
if(ftpc->entrypath) {
- struct Curl_easy *data = conn->data;
if(data->state.most_recent_ftp_entrypath == ftpc->entrypath) {
data->state.most_recent_ftp_entrypath = NULL;
}
- free(ftpc->entrypath);
- ftpc->entrypath = NULL;
+ Curl_safefree(ftpc->entrypath);
}
freedirs(ftpc);
- free(ftpc->prevpath);
- ftpc->prevpath = NULL;
- free(ftpc->server_os);
- ftpc->server_os = NULL;
-
+ Curl_safefree(ftpc->prevpath);
+ Curl_safefree(ftpc->server_os);
Curl_pp_disconnect(pp);
-
-#ifdef HAVE_GSSAPI
Curl_sec_end(conn);
-#endif
-
return CURLE_OK;
}
@@ -4096,11 +4080,11 @@ static CURLcode ftp_disconnect(struct connectdata *conn, bool dead_connection)
*
*/
static
-CURLcode ftp_parse_url_path(struct connectdata *conn)
+CURLcode ftp_parse_url_path(struct Curl_easy *data)
{
- struct Curl_easy *data = conn->data;
/* the ftp struct is already inited in ftp_connect() */
- struct FTP *ftp = data->req.protop;
+ 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;
@@ -4242,25 +4226,25 @@ CURLcode ftp_parse_url_path(struct connectdata *conn)
}
/* call this when the DO phase has completed */
-static CURLcode ftp_dophase_done(struct connectdata *conn,
- bool connected)
+static CURLcode ftp_dophase_done(struct Curl_easy *data, bool connected)
{
- struct FTP *ftp = conn->data->req.protop;
+ 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(conn, &completed);
+ CURLcode result = ftp_do_more(data, &completed);
if(result) {
- close_secondarysocket(conn);
+ close_secondarysocket(data, conn);
return result;
}
}
if(ftp->transfer != FTPTRANSFER_BODY)
/* no data to transfer */
- Curl_setup_transfer(conn->data, -1, -1, FALSE, -1);
+ Curl_setup_transfer(data, -1, -1, FALSE, -1);
else if(!connected)
/* since we didn't connect now, we want do_more to get called */
conn->bits.do_more = TRUE;
@@ -4271,17 +4255,17 @@ static CURLcode ftp_dophase_done(struct connectdata *conn,
}
/* called from multi.c while DOing */
-static CURLcode ftp_doing(struct connectdata *conn,
+static CURLcode ftp_doing(struct Curl_easy *data,
bool *dophase_done)
{
- CURLcode result = ftp_multi_statemach(conn, dophase_done);
+ CURLcode result = ftp_multi_statemach(data, dophase_done);
if(result)
- DEBUGF(infof(conn->data, "DO phase failed\n"));
+ DEBUGF(infof(data, "DO phase failed\n"));
else if(*dophase_done) {
- result = ftp_dophase_done(conn, FALSE /* not connected */);
+ result = ftp_dophase_done(data, FALSE /* not connected */);
- DEBUGF(infof(conn->data, "DO phase is complete2\n"));
+ DEBUGF(infof(data, "DO phase is complete2\n"));
}
return result;
}
@@ -4299,12 +4283,12 @@ static CURLcode ftp_doing(struct connectdata *conn,
* ftp_done() function without finding any major problem.
*/
static
-CURLcode ftp_regular_transfer(struct connectdata *conn,
+CURLcode ftp_regular_transfer(struct Curl_easy *data,
bool *dophase_done)
{
CURLcode result = CURLE_OK;
bool connected = FALSE;
- struct Curl_easy *data = conn->data;
+ struct connectdata *conn = data->conn;
struct ftp_conn *ftpc = &conn->proto.ftpc;
data->req.size = -1; /* make sure this is unknown at this point */
@@ -4315,7 +4299,7 @@ CURLcode ftp_regular_transfer(struct connectdata *conn,
ftpc->ctl_valid = TRUE; /* starts good */
- result = ftp_perform(conn,
+ result = ftp_perform(data,
&connected, /* have we connected after PASV/PORT */
dophase_done); /* all commands in the DO-phase done? */
@@ -4325,7 +4309,7 @@ CURLcode ftp_regular_transfer(struct connectdata *conn,
/* the DO phase has not completed yet */
return CURLE_OK;
- result = ftp_dophase_done(conn, connected);
+ result = ftp_dophase_done(data, connected);
if(result)
return result;
@@ -4336,13 +4320,13 @@ CURLcode ftp_regular_transfer(struct connectdata *conn,
return result;
}
-static CURLcode ftp_setup_connection(struct connectdata *conn)
+static CURLcode ftp_setup_connection(struct Curl_easy *data,
+ struct connectdata *conn)
{
- struct Curl_easy *data = conn->data;
char *type;
struct FTP *ftp;
- conn->data->req.protop = ftp = calloc(sizeof(struct FTP), 1);
+ data->req.p.ftp = ftp = calloc(sizeof(struct FTP), 1);
if(NULL == ftp)
return CURLE_OUT_OF_MEMORY;
diff --git a/Utilities/cmcurl/lib/ftp.h b/Utilities/cmcurl/lib/ftp.h
index 06421c6a4..1cfdac085 100644
--- a/Utilities/cmcurl/lib/ftp.h
+++ b/Utilities/cmcurl/lib/ftp.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -31,8 +31,7 @@ extern const struct Curl_handler Curl_handler_ftp;
extern const struct Curl_handler Curl_handler_ftps;
#endif
-CURLcode Curl_ftpsend(struct connectdata *, const char *cmd);
-CURLcode Curl_GetFTPResponse(ssize_t *nread, struct connectdata *conn,
+CURLcode Curl_GetFTPResponse(struct Curl_easy *data, ssize_t *nread,
int *ftpcode);
#endif /* CURL_DISABLE_FTP */
@@ -117,9 +116,9 @@ struct FTP {
struct ftp_conn {
struct pingpong pp;
char *entrypath; /* the PWD reply when we logged on */
+ char *file; /* url-decoded file name (or path) */
char **dirs; /* realloc()ed array for path components */
int dirdepth; /* number of entries used in the 'dirs' array */
- char *file; /* url-decoded file name (or path) */
bool dont_check; /* Set to TRUE to prevent the final (post-transfer)
file size and 226/250 status check. It should still
read the line, just ignore the result. */
@@ -132,6 +131,10 @@ struct ftp_conn {
bool cwdfail; /* set TRUE if a CWD command fails, as then we must prevent
caching the current directory */
bool wait_data_conn; /* this is set TRUE if data connection is waited */
+ /* newhost is the (allocated) IP addr or host name to connect the data
+ connection to */
+ unsigned short newport;
+ char *newhost;
char *prevpath; /* url-decoded conn->path from the previous transfer */
char transfertype; /* set by ftp_transfertype for use by Curl_client_write()a
and others (A/I or zero) */
@@ -146,10 +149,6 @@ struct ftp_conn {
curl_off_t known_filesize; /* file size is different from -1, if wildcard
LIST parsing was done and wc_statemach set
it */
- /* newhost is the (allocated) IP addr or host name to connect the data
- connection to */
- char *newhost; /* this is the pair to connect the DATA... */
- unsigned short newport; /* connection to */
};
#define DEFAULT_ACCEPT_TIMEOUT 60000 /* milliseconds == one minute */
diff --git a/Utilities/cmcurl/lib/ftplistparser.c b/Utilities/cmcurl/lib/ftplistparser.c
index f399a4c27..d3720b1f1 100644
--- a/Utilities/cmcurl/lib/ftplistparser.c
+++ b/Utilities/cmcurl/lib/ftplistparser.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -268,13 +268,13 @@ static int ftp_pl_get_permission(const char *str)
return permissions;
}
-static CURLcode ftp_pl_insert_finfo(struct connectdata *conn,
+static CURLcode ftp_pl_insert_finfo(struct Curl_easy *data,
struct fileinfo *infop)
{
curl_fnmatch_callback compare;
- struct WildcardData *wc = &conn->data->wildcard;
+ struct WildcardData *wc = &data->wildcard;
struct ftp_wc *ftpwc = wc->protdata;
- struct curl_llist *llist = &wc->filelist;
+ struct Curl_llist *llist = &wc->filelist;
struct ftp_parselist_data *parser = ftpwc->parser;
bool add = TRUE;
struct curl_fileinfo *finfo = &infop->info;
@@ -293,13 +293,13 @@ static CURLcode ftp_pl_insert_finfo(struct connectdata *conn,
str + parser->offsets.user : NULL;
/* get correct fnmatch callback */
- compare = conn->data->set.fnmatch;
+ compare = data->set.fnmatch;
if(!compare)
compare = Curl_fnmatch;
/* filter pattern-corresponding filenames */
- Curl_set_in_callback(conn->data, true);
- if(compare(conn->data->set.fnmatch_data, wc->pattern,
+ Curl_set_in_callback(data, true);
+ if(compare(data->set.fnmatch_data, wc->pattern,
finfo->filename) == 0) {
/* discard symlink which is containing multiple " -> " */
if((finfo->filetype == CURLFILETYPE_SYMLINK) && finfo->strings.target &&
@@ -310,7 +310,7 @@ static CURLcode ftp_pl_insert_finfo(struct connectdata *conn,
else {
add = FALSE;
}
- Curl_set_in_callback(conn->data, false);
+ Curl_set_in_callback(data, false);
if(add) {
Curl_llist_insert_next(llist, llist->tail, finfo, &infop->list);
@@ -327,8 +327,8 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
void *connptr)
{
size_t bufflen = size*nmemb;
- struct connectdata *conn = (struct connectdata *)connptr;
- struct ftp_wc *ftpwc = conn->data->wildcard.protdata;
+ struct Curl_easy *data = (struct Curl_easy *)connptr;
+ struct ftp_wc *ftpwc = data->wildcard.protdata;
struct ftp_parselist_data *parser = ftpwc->parser;
struct fileinfo *infop;
struct curl_fileinfo *finfo;
@@ -418,8 +418,8 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
finfo->b_data[parser->item_length - 1] = 0;
if(strncmp("total ", finfo->b_data, 6) == 0) {
char *endptr = finfo->b_data + 6;
- /* here we can deal with directory size, pass the leading white
- spaces and then the digits */
+ /* here we can deal with directory size, pass the leading
+ whitespace and then the digits */
while(ISSPACE(*endptr))
endptr++;
while(ISDIGIT(*endptr))
@@ -728,7 +728,7 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
finfo->b_data[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(conn, infop);
+ result = ftp_pl_insert_finfo(data, infop);
if(result) {
parser->error = result;
goto fail;
@@ -740,7 +740,7 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
finfo->b_data[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(conn, infop);
+ result = ftp_pl_insert_finfo(data, infop);
if(result) {
parser->error = result;
goto fail;
@@ -835,7 +835,7 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
else if(c == '\n') {
finfo->b_data[parser->item_offset + parser->item_length - 1] = 0;
parser->offsets.symlink_target = parser->item_offset;
- result = ftp_pl_insert_finfo(conn, infop);
+ result = ftp_pl_insert_finfo(data, infop);
if(result) {
parser->error = result;
goto fail;
@@ -847,7 +847,7 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
if(c == '\n') {
finfo->b_data[parser->item_offset + parser->item_length - 1] = 0;
parser->offsets.symlink_target = parser->item_offset;
- result = ftp_pl_insert_finfo(conn, infop);
+ result = ftp_pl_insert_finfo(data, infop);
if(result) {
parser->error = result;
goto fail;
@@ -967,7 +967,7 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
parser->offsets.filename = parser->item_offset;
finfo->b_data[finfo->b_used - 1] = 0;
parser->offsets.filename = parser->item_offset;
- result = ftp_pl_insert_finfo(conn, infop);
+ result = ftp_pl_insert_finfo(data, infop);
if(result) {
parser->error = result;
goto fail;
@@ -979,7 +979,7 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
case PL_WINNT_FILENAME_WINEOL:
if(c == '\n') {
parser->offsets.filename = parser->item_offset;
- result = ftp_pl_insert_finfo(conn, infop);
+ result = ftp_pl_insert_finfo(data, infop);
if(result) {
parser->error = result;
goto fail;
diff --git a/Utilities/cmcurl/lib/ftplistparser.h b/Utilities/cmcurl/lib/ftplistparser.h
index b34ae9b63..e4cd8201d 100644
--- a/Utilities/cmcurl/lib/ftplistparser.h
+++ b/Utilities/cmcurl/lib/ftplistparser.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
diff --git a/Utilities/cmcurl/lib/getenv.c b/Utilities/cmcurl/lib/getenv.c
index 9385b8f67..92c53505c 100644
--- a/Utilities/cmcurl/lib/getenv.c
+++ b/Utilities/cmcurl/lib/getenv.c
@@ -9,7 +9,7 @@
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/getinfo.c b/Utilities/cmcurl/lib/getinfo.c
index 82691dcc7..67ea07d2e 100644
--- a/Utilities/cmcurl/lib/getinfo.c
+++ b/Utilities/cmcurl/lib/getinfo.c
@@ -9,7 +9,7 @@
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -101,6 +101,7 @@ static CURLcode getinfo_char(struct Curl_easy *data, CURLINFO info,
if(!m) {
if(data->set.opt_no_body)
m = "HEAD";
+#ifndef CURL_DISABLE_HTTP
else {
switch(data->state.httpreq) {
case HTTPREQ_POST:
@@ -120,6 +121,7 @@ static CURLcode getinfo_char(struct Curl_easy *data, CURLINFO info,
break;
}
}
+#endif
}
*param_charp = m;
}
@@ -269,6 +271,9 @@ static CURLcode getinfo_long(struct Curl_easy *data, CURLINFO info,
/* Return the local port of the most recent (primary) connection */
*param_longp = data->info.conn_local_port;
break;
+ case CURLINFO_PROXY_ERROR:
+ *param_longp = (long)data->info.pxcode;
+ break;
case CURLINFO_CONDITION_UNMET:
if(data->info.httpcode == 304)
*param_longp = 1L;
diff --git a/Utilities/cmcurl/lib/getinfo.h b/Utilities/cmcurl/lib/getinfo.h
index 8d2af4266..f35d1b4b3 100644
--- a/Utilities/cmcurl/lib/getinfo.h
+++ b/Utilities/cmcurl/lib/getinfo.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
diff --git a/Utilities/cmcurl/lib/gopher.c b/Utilities/cmcurl/lib/gopher.c
index b4811b289..a39cc7e6b 100644
--- a/Utilities/cmcurl/lib/gopher.c
+++ b/Utilities/cmcurl/lib/gopher.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -33,6 +33,7 @@
#include "gopher.h"
#include "select.h"
#include "strdup.h"
+#include "vtls/vtls.h"
#include "url.h"
#include "escape.h"
#include "warnless.h"
@@ -45,7 +46,11 @@
* Forward declarations.
*/
-static CURLcode gopher_do(struct connectdata *conn, bool *done);
+static CURLcode gopher_do(struct Curl_easy *data, bool *done);
+#ifdef USE_SSL
+static CURLcode gopher_connect(struct Curl_easy *data, bool *done);
+static CURLcode gopher_connecting(struct Curl_easy *data, bool *done);
+#endif
/*
* Gopher protocol handler.
@@ -71,13 +76,55 @@ const struct Curl_handler Curl_handler_gopher = {
ZERO_NULL, /* connection_check */
PORT_GOPHER, /* defport */
CURLPROTO_GOPHER, /* protocol */
+ CURLPROTO_GOPHER, /* family */
PROTOPT_NONE /* flags */
};
-static CURLcode gopher_do(struct connectdata *conn, bool *done)
+#ifdef USE_SSL
+const struct Curl_handler Curl_handler_gophers = {
+ "GOPHERS", /* scheme */
+ ZERO_NULL, /* setup_connection */
+ gopher_do, /* do_it */
+ ZERO_NULL, /* done */
+ ZERO_NULL, /* do_more */
+ gopher_connect, /* connect_it */
+ gopher_connecting, /* connecting */
+ ZERO_NULL, /* doing */
+ ZERO_NULL, /* proto_getsock */
+ ZERO_NULL, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
+ ZERO_NULL, /* perform_getsock */
+ ZERO_NULL, /* disconnect */
+ ZERO_NULL, /* readwrite */
+ ZERO_NULL, /* connection_check */
+ PORT_GOPHER, /* defport */
+ CURLPROTO_GOPHERS, /* protocol */
+ CURLPROTO_GOPHER, /* family */
+ PROTOPT_SSL /* flags */
+};
+
+static CURLcode gopher_connect(struct Curl_easy *data, bool *done)
+{
+ (void)data;
+ (void)done;
+ return CURLE_OK;
+}
+
+static CURLcode gopher_connecting(struct Curl_easy *data, bool *done)
+{
+ struct connectdata *conn = data->conn;
+ CURLcode result = Curl_ssl_connect(data, conn, FIRSTSOCKET);
+ if(result)
+ connclose(conn, "Failed TLS connection");
+ *done = TRUE;
+ return result;
+}
+#endif
+
+static CURLcode gopher_do(struct Curl_easy *data, bool *done)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
+ struct connectdata *conn = data->conn;
curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
char *gopherpath;
char *path = data->state.up.path;
@@ -123,14 +170,17 @@ static CURLcode gopher_do(struct connectdata *conn, bool *done)
sel_org = sel;
}
- /* We use Curl_write instead of Curl_sendf to make sure the entire buffer is
- sent, which could be sizeable with long selectors. */
k = curlx_uztosz(len);
for(;;) {
- result = Curl_write(conn, sockfd, sel, k, &amount);
+ /* Break out of the loop if the selector is empty because OpenSSL and/or
+ LibreSSL fail with errno 0 if this is the case. */
+ if(strlen(sel) < 1)
+ break;
+
+ result = Curl_write(data, sockfd, sel, k, &amount);
if(!result) { /* Which may not have written it all! */
- result = Curl_client_write(conn, CLIENTWRITE_HEADER, sel, amount);
+ result = Curl_client_write(data, CLIENTWRITE_HEADER, sel, amount);
if(result)
break;
@@ -142,7 +192,7 @@ static CURLcode gopher_do(struct connectdata *conn, bool *done)
else
break;
- timeout_ms = Curl_timeleft(conn->data, NULL, FALSE);
+ timeout_ms = Curl_timeleft(data, NULL, FALSE);
if(timeout_ms < 0) {
result = CURLE_OPERATION_TIMEDOUT;
break;
@@ -170,14 +220,12 @@ static CURLcode gopher_do(struct connectdata *conn, bool *done)
free(sel_org);
if(!result)
- /* We can use Curl_sendf to send the terminal \r\n relatively safely and
- save allocing another string/doing another _write loop. */
- result = Curl_sendf(sockfd, conn, "\r\n");
+ result = Curl_write(data, sockfd, "\r\n", 2, &amount);
if(result) {
failf(data, "Failed sending Gopher request");
return result;
}
- result = Curl_client_write(conn, CLIENTWRITE_HEADER, (char *)"\r\n", 2);
+ result = Curl_client_write(data, CLIENTWRITE_HEADER, (char *)"\r\n", 2);
if(result)
return result;
diff --git a/Utilities/cmcurl/lib/gopher.h b/Utilities/cmcurl/lib/gopher.h
index dec2557fc..6b8bd554a 100644
--- a/Utilities/cmcurl/lib/gopher.h
+++ b/Utilities/cmcurl/lib/gopher.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
@@ -24,6 +24,9 @@
#ifndef CURL_DISABLE_GOPHER
extern const struct Curl_handler Curl_handler_gopher;
+#ifdef USE_SSL
+extern const struct Curl_handler Curl_handler_gophers;
+#endif
#endif
#endif /* HEADER_CURL_GOPHER_H */
diff --git a/Utilities/cmcurl/lib/hash.c b/Utilities/cmcurl/lib/hash.c
index 421d68f76..5d433ad1f 100644
--- a/Utilities/cmcurl/lib/hash.c
+++ b/Utilities/cmcurl/lib/hash.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
@@ -34,8 +34,8 @@
static void
hash_element_dtor(void *user, void *element)
{
- struct curl_hash *h = (struct curl_hash *) user;
- struct curl_hash_element *e = (struct curl_hash_element *) element;
+ struct Curl_hash *h = (struct Curl_hash *) user;
+ struct Curl_hash_element *e = (struct Curl_hash_element *) element;
if(e->ptr) {
h->dtor(e->ptr);
@@ -54,11 +54,11 @@ hash_element_dtor(void *user, void *element)
* @unittest: 1603
*/
int
-Curl_hash_init(struct curl_hash *h,
+Curl_hash_init(struct Curl_hash *h,
int slots,
hash_function hfunc,
comp_function comparator,
- curl_hash_dtor dtor)
+ Curl_hash_dtor dtor)
{
if(!slots || !hfunc || !comparator ||!dtor) {
return 1; /* failure */
@@ -70,22 +70,22 @@ Curl_hash_init(struct curl_hash *h,
h->size = 0;
h->slots = slots;
- h->table = malloc(slots * sizeof(struct curl_llist));
+ h->table = malloc(slots * sizeof(struct Curl_llist));
if(h->table) {
int i;
for(i = 0; i < slots; ++i)
- Curl_llist_init(&h->table[i], (curl_llist_dtor) hash_element_dtor);
+ Curl_llist_init(&h->table[i], (Curl_llist_dtor) hash_element_dtor);
return 0; /* fine */
}
h->slots = 0;
return 1; /* failure */
}
-static struct curl_hash_element *
+static struct Curl_hash_element *
mk_hash_element(const void *key, size_t key_len, const void *p)
{
/* allocate the struct plus memory after it to store the key */
- struct curl_hash_element *he = malloc(sizeof(struct curl_hash_element) +
+ struct Curl_hash_element *he = malloc(sizeof(struct Curl_hash_element) +
key_len);
if(he) {
/* copy the key */
@@ -106,14 +106,14 @@ mk_hash_element(const void *key, size_t key_len, const void *p)
* @unittest: 1603
*/
void *
-Curl_hash_add(struct curl_hash *h, void *key, size_t key_len, void *p)
+Curl_hash_add(struct Curl_hash *h, void *key, size_t key_len, void *p)
{
- struct curl_hash_element *he;
- struct curl_llist_element *le;
- struct curl_llist *l = FETCH_LIST(h, key, key_len);
+ struct Curl_hash_element *he;
+ struct Curl_llist_element *le;
+ struct Curl_llist *l = FETCH_LIST(h, key, key_len);
for(le = l->head; le; le = le->next) {
- he = (struct curl_hash_element *) le->ptr;
+ he = (struct Curl_hash_element *) le->ptr;
if(h->comp_func(he->key, he->key_len, key, key_len)) {
Curl_llist_remove(l, le, (void *)h);
--h->size;
@@ -136,13 +136,13 @@ Curl_hash_add(struct curl_hash *h, void *key, size_t key_len, void *p)
*
* @unittest: 1603
*/
-int Curl_hash_delete(struct curl_hash *h, void *key, size_t key_len)
+int Curl_hash_delete(struct Curl_hash *h, void *key, size_t key_len)
{
- struct curl_llist_element *le;
- struct curl_llist *l = FETCH_LIST(h, key, key_len);
+ struct Curl_llist_element *le;
+ struct Curl_llist *l = FETCH_LIST(h, key, key_len);
for(le = l->head; le; le = le->next) {
- struct curl_hash_element *he = le->ptr;
+ struct Curl_hash_element *he = le->ptr;
if(h->comp_func(he->key, he->key_len, key, key_len)) {
Curl_llist_remove(l, le, (void *) h);
--h->size;
@@ -157,15 +157,15 @@ int Curl_hash_delete(struct curl_hash *h, void *key, size_t key_len)
* @unittest: 1603
*/
void *
-Curl_hash_pick(struct curl_hash *h, void *key, size_t key_len)
+Curl_hash_pick(struct Curl_hash *h, void *key, size_t key_len)
{
- struct curl_llist_element *le;
- struct curl_llist *l;
+ struct Curl_llist_element *le;
+ struct Curl_llist *l;
if(h) {
l = FETCH_LIST(h, key, key_len);
for(le = l->head; le; le = le->next) {
- struct curl_hash_element *he = le->ptr;
+ struct Curl_hash_element *he = le->ptr;
if(h->comp_func(he->key, he->key_len, key, key_len)) {
return he->ptr;
}
@@ -175,19 +175,19 @@ Curl_hash_pick(struct curl_hash *h, void *key, size_t key_len)
return NULL;
}
-#if defined(DEBUGBUILD) && defined(AGGRESIVE_TEST)
+#if defined(DEBUGBUILD) && defined(AGGRESSIVE_TEST)
void
-Curl_hash_apply(curl_hash *h, void *user,
+Curl_hash_apply(Curl_hash *h, void *user,
void (*cb)(void *user, void *ptr))
{
- struct curl_llist_element *le;
+ struct Curl_llist_element *le;
int i;
for(i = 0; i < h->slots; ++i) {
for(le = (h->table[i])->head;
le;
le = le->next) {
- curl_hash_element *el = le->ptr;
+ Curl_hash_element *el = le->ptr;
cb(user, el->ptr);
}
}
@@ -202,7 +202,7 @@ Curl_hash_apply(curl_hash *h, void *user,
* @unittest: 1603
*/
void
-Curl_hash_destroy(struct curl_hash *h)
+Curl_hash_destroy(struct Curl_hash *h)
{
int i;
@@ -220,19 +220,19 @@ Curl_hash_destroy(struct curl_hash *h)
* @unittest: 1602
*/
void
-Curl_hash_clean(struct curl_hash *h)
+Curl_hash_clean(struct Curl_hash *h)
{
Curl_hash_clean_with_criterium(h, NULL, NULL);
}
/* Cleans all entries that pass the comp function criteria. */
void
-Curl_hash_clean_with_criterium(struct curl_hash *h, void *user,
+Curl_hash_clean_with_criterium(struct Curl_hash *h, void *user,
int (*comp)(void *, void *))
{
- struct curl_llist_element *le;
- struct curl_llist_element *lnext;
- struct curl_llist *list;
+ struct Curl_llist_element *le;
+ struct Curl_llist_element *lnext;
+ struct Curl_llist *list;
int i;
if(!h)
@@ -242,7 +242,7 @@ Curl_hash_clean_with_criterium(struct curl_hash *h, void *user,
list = &h->table[i];
le = list->head; /* get first list entry */
while(le) {
- struct curl_hash_element *he = le->ptr;
+ struct Curl_hash_element *he = le->ptr;
lnext = le->next;
/* ask the callback function if we shall remove this entry or not */
if(comp == NULL || comp(user, he->ptr)) {
@@ -277,18 +277,18 @@ size_t Curl_str_key_compare(void *k1, size_t key1_len,
return 0;
}
-void Curl_hash_start_iterate(struct curl_hash *hash,
- struct curl_hash_iterator *iter)
+void Curl_hash_start_iterate(struct Curl_hash *hash,
+ struct Curl_hash_iterator *iter)
{
iter->hash = hash;
iter->slot_index = 0;
iter->current_element = NULL;
}
-struct curl_hash_element *
-Curl_hash_next_element(struct curl_hash_iterator *iter)
+struct Curl_hash_element *
+Curl_hash_next_element(struct Curl_hash_iterator *iter)
{
- struct curl_hash *h = iter->hash;
+ struct Curl_hash *h = iter->hash;
/* Get the next element in the current list, if any */
if(iter->current_element)
@@ -307,7 +307,7 @@ Curl_hash_next_element(struct curl_hash_iterator *iter)
}
if(iter->current_element) {
- struct curl_hash_element *he = iter->current_element->ptr;
+ struct Curl_hash_element *he = iter->current_element->ptr;
return he;
}
iter->current_element = NULL;
@@ -315,11 +315,11 @@ Curl_hash_next_element(struct curl_hash_iterator *iter)
}
#if 0 /* useful function for debugging hashes and their contents */
-void Curl_hash_print(struct curl_hash *h,
+void Curl_hash_print(struct Curl_hash *h,
void (*func)(void *))
{
- struct curl_hash_iterator iter;
- struct curl_hash_element *he;
+ struct Curl_hash_iterator iter;
+ struct Curl_hash_element *he;
int last_index = -1;
if(!h)
diff --git a/Utilities/cmcurl/lib/hash.h b/Utilities/cmcurl/lib/hash.h
index 558d0f47c..b7f828e07 100644
--- a/Utilities/cmcurl/lib/hash.h
+++ b/Utilities/cmcurl/lib/hash.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
@@ -41,59 +41,59 @@ typedef size_t (*comp_function) (void *key1,
void *key2,
size_t key2_len);
-typedef void (*curl_hash_dtor)(void *);
+typedef void (*Curl_hash_dtor)(void *);
-struct curl_hash {
- struct curl_llist *table;
+struct Curl_hash {
+ struct Curl_llist *table;
/* Hash function to be used for this hash table */
hash_function hash_func;
/* Comparator function to compare keys */
comp_function comp_func;
- curl_hash_dtor dtor;
+ Curl_hash_dtor dtor;
int slots;
size_t size;
};
-struct curl_hash_element {
- struct curl_llist_element list;
+struct Curl_hash_element {
+ struct Curl_llist_element list;
void *ptr;
size_t key_len;
char key[1]; /* allocated memory following the struct */
};
-struct curl_hash_iterator {
- struct curl_hash *hash;
+struct Curl_hash_iterator {
+ struct Curl_hash *hash;
int slot_index;
- struct curl_llist_element *current_element;
+ struct Curl_llist_element *current_element;
};
-int Curl_hash_init(struct curl_hash *h,
+int Curl_hash_init(struct Curl_hash *h,
int slots,
hash_function hfunc,
comp_function comparator,
- curl_hash_dtor dtor);
+ Curl_hash_dtor dtor);
-void *Curl_hash_add(struct curl_hash *h, void *key, size_t key_len, void *p);
-int Curl_hash_delete(struct curl_hash *h, void *key, size_t key_len);
-void *Curl_hash_pick(struct curl_hash *, void *key, size_t key_len);
-void Curl_hash_apply(struct curl_hash *h, void *user,
+void *Curl_hash_add(struct Curl_hash *h, void *key, size_t key_len, void *p);
+int Curl_hash_delete(struct Curl_hash *h, void *key, size_t key_len);
+void *Curl_hash_pick(struct Curl_hash *, void *key, size_t key_len);
+void Curl_hash_apply(struct Curl_hash *h, void *user,
void (*cb)(void *user, void *ptr));
#define Curl_hash_count(h) ((h)->size)
-void Curl_hash_destroy(struct curl_hash *h);
-void Curl_hash_clean(struct curl_hash *h);
-void Curl_hash_clean_with_criterium(struct curl_hash *h, void *user,
+void Curl_hash_destroy(struct Curl_hash *h);
+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 key2_len);
-void Curl_hash_start_iterate(struct curl_hash *hash,
- struct curl_hash_iterator *iter);
-struct curl_hash_element *
-Curl_hash_next_element(struct curl_hash_iterator *iter);
+void Curl_hash_start_iterate(struct Curl_hash *hash,
+ struct Curl_hash_iterator *iter);
+struct Curl_hash_element *
+Curl_hash_next_element(struct Curl_hash_iterator *iter);
-void Curl_hash_print(struct curl_hash *h,
+void Curl_hash_print(struct Curl_hash *h,
void (*func)(void *));
diff --git a/Utilities/cmcurl/lib/hmac.c b/Utilities/cmcurl/lib/hmac.c
index e4fea8a50..590abe6d2 100644
--- a/Utilities/cmcurl/lib/hmac.c
+++ b/Utilities/cmcurl/lib/hmac.c
@@ -9,7 +9,7 @@
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/hostasyn.c b/Utilities/cmcurl/lib/hostasyn.c
index ed9190f4c..b25de1d41 100644
--- a/Utilities/cmcurl/lib/hostasyn.c
+++ b/Utilities/cmcurl/lib/hostasyn.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -66,25 +66,23 @@
*
* The storage operation locks and unlocks the DNS cache.
*/
-CURLcode Curl_addrinfo_callback(struct connectdata *conn,
+CURLcode Curl_addrinfo_callback(struct Curl_easy *data,
int status,
struct Curl_addrinfo *ai)
{
struct Curl_dns_entry *dns = NULL;
CURLcode result = CURLE_OK;
- conn->async.status = status;
+ data->state.async.status = status;
if(CURL_ASYNC_SUCCESS == status) {
if(ai) {
- struct Curl_easy *data = conn->data;
-
if(data->share)
Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);
dns = Curl_cache_addr(data, ai,
- conn->async.hostname,
- conn->async.port);
+ data->state.async.hostname,
+ data->state.async.port);
if(data->share)
Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
@@ -99,12 +97,12 @@ CURLcode Curl_addrinfo_callback(struct connectdata *conn,
}
}
- conn->async.dns = dns;
+ 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 */
- conn->async.done = TRUE;
+ data->state.async.done = TRUE;
/* IPv4: The input hostent struct will be freed by ares when we return from
this function */
@@ -117,12 +115,12 @@ CURLcode Curl_addrinfo_callback(struct connectdata *conn,
* name resolve layers (selected at build-time). They all take this same set
* of arguments
*/
-struct Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
+struct Curl_addrinfo *Curl_getaddrinfo(struct Curl_easy *data,
const char *hostname,
int port,
int *waitp)
{
- return Curl_resolver_getaddrinfo(conn, hostname, port, waitp);
+ return Curl_resolver_getaddrinfo(data, hostname, port, waitp);
}
#endif /* CURLRES_ASYNCH */
diff --git a/Utilities/cmcurl/lib/hostcheck.c b/Utilities/cmcurl/lib/hostcheck.c
index 9e0db05fa..0fef98b2a 100644
--- a/Utilities/cmcurl/lib/hostcheck.c
+++ b/Utilities/cmcurl/lib/hostcheck.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
diff --git a/Utilities/cmcurl/lib/hostcheck.h b/Utilities/cmcurl/lib/hostcheck.h
index 9c180856a..52155f43b 100644
--- a/Utilities/cmcurl/lib/hostcheck.h
+++ b/Utilities/cmcurl/lib/hostcheck.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
diff --git a/Utilities/cmcurl/lib/hostip.c b/Utilities/cmcurl/lib/hostip.c
index dd5916e33..8ba3fe81c 100644
--- a/Utilities/cmcurl/lib/hostip.c
+++ b/Utilities/cmcurl/lib/hostip.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -206,7 +206,7 @@ hostcache_timestamp_remove(void *datap, void *hc)
* Prune the DNS cache. This assumes that a lock has already been taken.
*/
static void
-hostcache_prune(struct curl_hash *hostcache, long cache_timeout, time_t now)
+hostcache_prune(struct Curl_hash *hostcache, long cache_timeout, time_t now)
{
struct hostcache_prune_data user;
@@ -253,14 +253,12 @@ sigjmp_buf curl_jmpenv;
#endif
/* lookup address, returns entry if found and not stale */
-static struct Curl_dns_entry *
-fetch_addr(struct connectdata *conn,
- const char *hostname,
- int port)
+static struct Curl_dns_entry *fetch_addr(struct Curl_easy *data,
+ const char *hostname,
+ int port)
{
struct Curl_dns_entry *dns = NULL;
size_t entry_len;
- struct Curl_easy *data = conn->data;
char entry_id[MAX_HOSTCACHE_LEN];
/* Create an entry id, based upon the hostname and port */
@@ -311,17 +309,16 @@ fetch_addr(struct connectdata *conn,
* use, or we'll leak memory!
*/
struct Curl_dns_entry *
-Curl_fetch_addr(struct connectdata *conn,
+Curl_fetch_addr(struct Curl_easy *data,
const char *hostname,
int port)
{
- struct Curl_easy *data = conn->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(conn, hostname, port);
+ dns = fetch_addr(data, hostname, port);
if(dns)
dns->inuse++; /* we use it! */
@@ -444,7 +441,7 @@ Curl_cache_addr(struct Curl_easy *data,
dns->addr = addr; /* this is the address(es) */
time(&dns->timestamp);
if(dns->timestamp == 0)
- dns->timestamp = 1; /* zero indicates CURLOPT_RESOLVE entry */
+ dns->timestamp = 1; /* zero indicates permanent CURLOPT_RESOLVE entry */
/* Store the resolved data in our DNS cache. */
dns2 = Curl_hash_add(data->dns.hostcache, entry_id, entry_len + 1,
@@ -480,16 +477,16 @@ Curl_cache_addr(struct Curl_easy *data,
* CURLRESOLV_PENDING (1) = waiting for response, no pointer
*/
-enum resolve_t Curl_resolv(struct connectdata *conn,
+enum resolve_t Curl_resolv(struct Curl_easy *data,
const char *hostname,
int port,
bool allowDOH,
struct Curl_dns_entry **entry)
{
struct Curl_dns_entry *dns = NULL;
- struct Curl_easy *data = conn->data;
CURLcode result;
enum resolve_t rc = CURLRESOLV_ERROR; /* default to failure */
+ struct connectdata *conn = data->conn;
*entry = NULL;
conn->bits.doh = FALSE; /* default is not */
@@ -497,7 +494,7 @@ enum resolve_t Curl_resolv(struct connectdata *conn,
if(data->share)
Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);
- dns = fetch_addr(conn, hostname, port);
+ dns = fetch_addr(data, hostname, port);
if(dns) {
infof(data, "Hostname %s was found in DNS cache\n", hostname);
@@ -523,7 +520,7 @@ enum resolve_t Curl_resolv(struct connectdata *conn,
if(data->set.resolver_start) {
int st;
Curl_set_in_callback(data, true);
- st = data->set.resolver_start(data->state.resolver, NULL,
+ st = data->set.resolver_start(data->state.async.resolver, NULL,
data->set.resolver_start_client);
Curl_set_in_callback(data, false);
if(st)
@@ -565,17 +562,17 @@ enum resolve_t Curl_resolv(struct connectdata *conn,
if(!addr) {
/* Check what IP specifics the app has requested and if we can provide
* it. If not, bail out. */
- if(!Curl_ipvalid(conn))
+ if(!Curl_ipvalid(data, conn))
return CURLRESOLV_ERROR;
if(allowDOH && data->set.doh && !ipnum) {
- addr = Curl_doh(conn, hostname, port, &respwait);
+ addr = Curl_doh(data, hostname, port, &respwait);
}
else {
/* 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(conn,
+ addr = Curl_getaddrinfo(data,
#ifdef DEBUGBUILD
(data->set.str[STRING_DEVICE]
&& !strcmp(data->set.str[STRING_DEVICE],
@@ -589,7 +586,7 @@ enum resolve_t Curl_resolv(struct connectdata *conn,
/* the response to our resolve call will come asynchronously at
a later time, good or bad */
/* First, check that we haven't received the info by now */
- result = Curl_resolv_check(conn, &dns);
+ result = Curl_resolv_check(data, &dns);
if(result) /* error detected */
return CURLRESOLV_ERROR;
if(dns)
@@ -658,7 +655,7 @@ RETSIGTYPE alarmfunc(int sig)
* CURLRESOLV_PENDING (1) = waiting for response, no pointer
*/
-enum resolve_t Curl_resolv_timeout(struct connectdata *conn,
+enum resolve_t Curl_resolv_timeout(struct Curl_easy *data,
const char *hostname,
int port,
struct Curl_dns_entry **entry,
@@ -676,7 +673,6 @@ enum resolve_t Curl_resolv_timeout(struct connectdata *conn,
#endif /* HAVE_SIGACTION */
volatile long timeout;
volatile unsigned int prev_alarm = 0;
- struct Curl_easy *data = conn->data;
#endif /* USE_ALARM_TIMEOUT */
enum resolve_t rc;
@@ -695,7 +691,7 @@ enum resolve_t Curl_resolv_timeout(struct connectdata *conn,
if(!timeout)
/* USE_ALARM_TIMEOUT defined, but no timeout actually requested */
- return Curl_resolv(conn, hostname, port, TRUE, entry);
+ return Curl_resolv(data, hostname, port, TRUE, entry);
if(timeout < 1000) {
/* The alarm() function only provides integer second resolution, so if
@@ -728,7 +724,7 @@ enum resolve_t Curl_resolv_timeout(struct connectdata *conn,
keep_copysig = TRUE; /* yes, we have a copy */
sigact.sa_handler = alarmfunc;
#ifdef SA_RESTART
- /* HPUX doesn't have SA_RESTART but defaults to that behaviour! */
+ /* HPUX doesn't have SA_RESTART but defaults to that behavior! */
sigact.sa_flags &= ~SA_RESTART;
#endif
/* now set the new struct */
@@ -748,7 +744,7 @@ enum resolve_t Curl_resolv_timeout(struct connectdata *conn,
#else
#ifndef CURLRES_ASYNCH
if(timeoutms)
- infof(conn->data, "timeout on name lookup is not supported\n");
+ infof(data, "timeout on name lookup is not supported\n");
#else
(void)timeoutms; /* timeoutms not used with an async resolver */
#endif
@@ -757,7 +753,7 @@ enum resolve_t Curl_resolv_timeout(struct connectdata *conn,
/* Perform the actual name resolution. This might be interrupted by an
* alarm if it takes too long.
*/
- rc = Curl_resolv(conn, hostname, port, TRUE, entry);
+ rc = Curl_resolv(data, hostname, port, TRUE, entry);
#ifdef USE_ALARM_TIMEOUT
clean_up:
@@ -784,7 +780,7 @@ clean_up:
if(prev_alarm) {
/* there was an alarm() set before us, now put it back */
timediff_t elapsed_secs = Curl_timediff(Curl_now(),
- conn->created) / 1000;
+ data->conn->created) / 1000;
/* the alarm period is counted in even number of seconds */
unsigned long alarm_set = (unsigned long)(prev_alarm - elapsed_secs);
@@ -843,7 +839,7 @@ static void freednsentry(void *freethis)
/*
* Curl_mk_dnscache() inits a new DNS cache and returns success/failure.
*/
-int Curl_mk_dnscache(struct curl_hash *hash)
+int Curl_mk_dnscache(struct Curl_hash *hash)
{
return Curl_hash_init(hash, 7, Curl_hash_str, Curl_str_key_compare,
freednsentry);
@@ -857,7 +853,7 @@ int Curl_mk_dnscache(struct curl_hash *hash)
*/
void Curl_hostcache_clean(struct Curl_easy *data,
- struct curl_hash *hash)
+ struct Curl_hash *hash)
{
if(data && data->share)
Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);
@@ -916,17 +912,24 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data)
char *addr_end;
char *port_ptr;
char *end_ptr;
+ bool permanent = TRUE;
+ char *host_begin;
char *host_end;
unsigned long tmp_port;
bool error = true;
- host_end = strchr(hostp->data, ':');
+ host_begin = hostp->data;
+ if(host_begin[0] == '+') {
+ host_begin++;
+ permanent = FALSE;
+ }
+ host_end = strchr(host_begin, ':');
if(!host_end ||
- ((host_end - hostp->data) >= (ptrdiff_t)sizeof(hostname)))
+ ((host_end - host_begin) >= (ptrdiff_t)sizeof(hostname)))
goto err;
- memcpy(hostname, hostp->data, host_end - hostp->data);
- hostname[host_end - hostp->data] = '\0';
+ memcpy(hostname, host_begin, host_end - host_begin);
+ hostname[host_end - host_begin] = '\0';
port_ptr = host_end + 1;
tmp_port = strtoul(port_ptr, &end_ptr, 10);
@@ -1008,18 +1011,22 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data)
if(data->share)
Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);
- /* See if its already in our dns cache */
+ /* See if it's already in our dns cache */
dns = Curl_hash_pick(data->dns.hostcache, entry_id, entry_len + 1);
if(dns) {
infof(data, "RESOLVE %s:%d is - old addresses discarded!\n",
hostname, port);
- /* delete old entry entry, there are two reasons for this
+ /* 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,
but if it is close to expire, then by the time next http
request is made, it can get expired and pruned because old
- entry is not necessarily marked as added by CURLOPT_RESOLVE. */
+ entry is not necessarily marked as permanent.
+ 3. when adding a non-permanent entry, we want it to remove and
+ replace an existing permanent entry.
+ 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);
}
@@ -1027,10 +1034,11 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data)
/* put this new host in the cache */
dns = Curl_cache_addr(data, head, hostname, port);
if(dns) {
- dns->timestamp = 0; /* mark as added by CURLOPT_RESOLVE */
+ if(permanent)
+ dns->timestamp = 0; /* mark as permanent */
/* release the returned reference; the cache itself will keep the
* entry alive: */
- dns->inuse--;
+ dns->inuse--;
}
if(data->share)
@@ -1040,8 +1048,8 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data)
Curl_freeaddrinfo(head);
return CURLE_OUT_OF_MEMORY;
}
- infof(data, "Added %s:%d:%s to DNS cache\n",
- hostname, port, addresses);
+ infof(data, "Added %s:%d:%s to DNS cache%s\n",
+ hostname, port, addresses, permanent ? "" : " (non-permanent)");
/* Wildcard hostname */
if(hostname[0] == '*' && hostname[1] == '\0') {
@@ -1056,29 +1064,29 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data)
return CURLE_OK;
}
-CURLcode Curl_resolv_check(struct connectdata *conn,
+CURLcode Curl_resolv_check(struct Curl_easy *data,
struct Curl_dns_entry **dns)
{
#if defined(CURL_DISABLE_DOH) && !defined(CURLRES_ASYNCH)
(void)dns;
#endif
- if(conn->bits.doh)
- return Curl_doh_is_resolved(conn, dns);
- return Curl_resolver_is_resolved(conn, dns);
+ if(data->conn->bits.doh)
+ return Curl_doh_is_resolved(data, dns);
+ return Curl_resolver_is_resolved(data, dns);
}
-int Curl_resolv_getsock(struct connectdata *conn,
+int Curl_resolv_getsock(struct Curl_easy *data,
curl_socket_t *socks)
{
#ifdef CURLRES_ASYNCH
- if(conn->bits.doh)
+ if(data->conn->bits.doh)
/* nothing to wait for during DOH resolve, those handles have their own
sockets */
return GETSOCK_BLANK;
- return Curl_resolver_getsock(conn, socks);
+ return Curl_resolver_getsock(data, socks);
#else
- (void)conn;
+ (void)data;
(void)socks;
return GETSOCK_BLANK;
#endif
@@ -1089,21 +1097,19 @@ int Curl_resolv_getsock(struct connectdata *conn,
Note: this function disconnects and frees the conn data in case of
resolve failure */
-CURLcode Curl_once_resolved(struct connectdata *conn,
- bool *protocol_done)
+CURLcode Curl_once_resolved(struct Curl_easy *data, bool *protocol_done)
{
CURLcode result;
+ struct connectdata *conn = data->conn;
- if(conn->async.dns) {
- conn->dns_entry = conn->async.dns;
- conn->async.dns = NULL;
+ if(data->state.async.dns) {
+ conn->dns_entry = data->state.async.dns;
+ data->state.async.dns = NULL;
}
- result = Curl_setup_conn(conn, protocol_done);
+ result = Curl_setup_conn(data, protocol_done);
if(result) {
- struct Curl_easy *data = conn->data;
- DEBUGASSERT(data);
Curl_detach_connnection(data);
Curl_conncache_remove_conn(data, conn, TRUE);
Curl_disconnect(data, conn, TRUE);
diff --git a/Utilities/cmcurl/lib/hostip.h b/Utilities/cmcurl/lib/hostip.h
index 374b06c85..c495c21e0 100644
--- a/Utilities/cmcurl/lib/hostip.h
+++ b/Utilities/cmcurl/lib/hostip.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -59,13 +59,13 @@ struct connectdata;
* 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.
+ * Returns a struct Curl_hash pointer on success, NULL on failure.
*/
-struct curl_hash *Curl_global_host_cache_init(void);
+struct Curl_hash *Curl_global_host_cache_init(void);
struct Curl_dns_entry {
struct Curl_addrinfo *addr;
- /* timestamp == 0 -- CURLOPT_RESOLVE entry, doesn't timeout */
+ /* timestamp == 0 -- permanent CURLOPT_RESOLVE entry (doesn't time out) */
time_t timestamp;
/* use-counter, use Curl_resolv_unlock to release reference */
long inuse;
@@ -85,12 +85,12 @@ enum resolve_t {
CURLRESOLV_RESOLVED = 0,
CURLRESOLV_PENDING = 1
};
-enum resolve_t Curl_resolv(struct connectdata *conn,
+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 connectdata *conn,
+enum resolve_t Curl_resolv_timeout(struct Curl_easy *data,
const char *hostname, int port,
struct Curl_dns_entry **dnsentry,
timediff_t timeoutms);
@@ -99,7 +99,7 @@ enum resolve_t Curl_resolv_timeout(struct connectdata *conn,
/*
* Curl_ipv6works() returns TRUE if IPv6 seems to work.
*/
-bool Curl_ipv6works(struct connectdata *conn);
+bool Curl_ipv6works(struct Curl_easy *data);
#else
#define Curl_ipv6works(x) FALSE
#endif
@@ -108,7 +108,7 @@ bool Curl_ipv6works(struct connectdata *conn);
* Curl_ipvalid() checks what CURL_IPRESOLVE_* requirements that might've
* been set and returns TRUE if they are OK.
*/
-bool Curl_ipvalid(struct connectdata *conn);
+bool Curl_ipvalid(struct Curl_easy *data, struct connectdata *conn);
/*
@@ -117,7 +117,7 @@ bool Curl_ipvalid(struct connectdata *conn);
* name resolve layers (selected at build-time). They all take this same set
* of arguments
*/
-struct Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
+struct Curl_addrinfo *Curl_getaddrinfo(struct Curl_easy *data,
const char *hostname,
int port,
int *waitp);
@@ -128,7 +128,7 @@ void Curl_resolv_unlock(struct Curl_easy *data,
struct Curl_dns_entry *dns);
/* init a new dns cache and return success */
-int Curl_mk_dnscache(struct curl_hash *hash);
+int Curl_mk_dnscache(struct Curl_hash *hash);
/* prune old entries from the DNS cache */
void Curl_hostcache_prune(struct Curl_easy *data);
@@ -148,7 +148,7 @@ int curl_dogetnameinfo(GETNAMEINFO_QUAL_ARG1 GETNAMEINFO_TYPE_ARG1 sa,
/* 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 connectdata *conn, bool *protocol_connect);
+CURLcode Curl_once_resolved(struct Curl_easy *data, bool *protocol_connect);
/*
* Curl_addrinfo_callback() is used when we build with any asynch specialty.
@@ -156,7 +156,7 @@ CURLcode Curl_once_resolved(struct connectdata *conn, bool *protocol_connect);
* status is CURL_ASYNC_SUCCESS. Twiddles fields in conn to indicate async
* request completed whether successful or failed.
*/
-CURLcode Curl_addrinfo_callback(struct connectdata *conn,
+CURLcode Curl_addrinfo_callback(struct Curl_easy *data,
int status,
struct Curl_addrinfo *ai);
@@ -177,7 +177,7 @@ void Curl_printable_address(const struct Curl_addrinfo *ip,
* use, or we'll leak memory!
*/
struct Curl_dns_entry *
-Curl_fetch_addr(struct connectdata *conn,
+Curl_fetch_addr(struct Curl_easy *data,
const char *hostname,
int port);
@@ -234,16 +234,15 @@ CURLcode Curl_set_dns_local_ip6(struct Curl_easy *data,
/*
* Clean off entries from the cache
*/
-void Curl_hostcache_clean(struct Curl_easy *data, struct curl_hash *hash);
+void Curl_hostcache_clean(struct Curl_easy *data, struct Curl_hash *hash);
/*
* Populate the cache with specified entries from CURLOPT_RESOLVE.
*/
CURLcode Curl_loadhostpairs(struct Curl_easy *data);
-
-CURLcode Curl_resolv_check(struct connectdata *conn,
+CURLcode Curl_resolv_check(struct Curl_easy *data,
struct Curl_dns_entry **dns);
-int Curl_resolv_getsock(struct connectdata *conn,
+int Curl_resolv_getsock(struct Curl_easy *data,
curl_socket_t *socks);
#endif /* HEADER_CURL_HOSTIP_H */
diff --git a/Utilities/cmcurl/lib/hostip4.c b/Utilities/cmcurl/lib/hostip4.c
index eae941674..d0754af22 100644
--- a/Utilities/cmcurl/lib/hostip4.c
+++ b/Utilities/cmcurl/lib/hostip4.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -61,8 +61,9 @@
* Curl_ipvalid() checks what CURL_IPRESOLVE_* requirements that might've
* been set and returns TRUE if they are OK.
*/
-bool Curl_ipvalid(struct connectdata *conn)
+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 can't get/use one */
return FALSE;
@@ -88,7 +89,7 @@ bool Curl_ipvalid(struct connectdata *conn)
* flavours have thread-safe versions of the plain gethostbyname() etc.
*
*/
-struct Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
+struct Curl_addrinfo *Curl_getaddrinfo(struct Curl_easy *data,
const char *hostname,
int port,
int *waitp)
@@ -96,14 +97,14 @@ struct Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
struct Curl_addrinfo *ai = NULL;
#ifdef CURL_DISABLE_VERBOSE_STRINGS
- (void)conn;
+ (void)data;
#endif
*waitp = 0; /* synchronous response only */
ai = Curl_ipv4_resolve_r(hostname, port);
if(!ai)
- infof(conn->data, "Curl_ipv4_resolve_r failed for %s\n", hostname);
+ infof(data, "Curl_ipv4_resolve_r failed for %s\n", hostname);
return ai;
}
diff --git a/Utilities/cmcurl/lib/hostip6.c b/Utilities/cmcurl/lib/hostip6.c
index 11215758d..53b3c6722 100644
--- a/Utilities/cmcurl/lib/hostip6.c
+++ b/Utilities/cmcurl/lib/hostip6.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -62,16 +62,15 @@
/*
* Curl_ipv6works() returns TRUE if IPv6 seems to work.
*/
-bool Curl_ipv6works(struct connectdata *conn)
+bool Curl_ipv6works(struct Curl_easy *data)
{
- if(conn) {
+ if(data) {
/* the nature of most system is that IPv6 status doesn't come and go
during a program's lifetime so we only probe the first time and then we
have the info kept for fast re-use */
- DEBUGASSERT(conn);
- DEBUGASSERT(conn->data);
- DEBUGASSERT(conn->data->multi);
- return conn->data->multi->ipv6_works;
+ DEBUGASSERT(data);
+ DEBUGASSERT(data->multi);
+ return data->multi->ipv6_works;
}
else {
int ipv6_works = -1;
@@ -82,7 +81,7 @@ bool Curl_ipv6works(struct connectdata *conn)
ipv6_works = 0;
else {
ipv6_works = 1;
- Curl_closesocket(NULL, s);
+ sclose(s);
}
return (ipv6_works>0)?TRUE:FALSE;
}
@@ -92,10 +91,10 @@ bool Curl_ipv6works(struct connectdata *conn)
* Curl_ipvalid() checks what CURL_IPRESOLVE_* requirements that might've
* been set and returns TRUE if they are OK.
*/
-bool Curl_ipvalid(struct connectdata *conn)
+bool Curl_ipvalid(struct Curl_easy *data, struct connectdata *conn)
{
if(conn->ip_version == CURL_IPRESOLVE_V6)
- return Curl_ipv6works(conn);
+ return Curl_ipv6works(data);
return TRUE;
}
@@ -128,7 +127,7 @@ static void dump_addrinfo(struct connectdata *conn,
* memory we need to free after use. That memory *MUST* be freed with
* Curl_freeaddrinfo(), nothing else.
*/
-struct Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
+struct Curl_addrinfo *Curl_getaddrinfo(struct Curl_easy *data,
const char *hostname,
int port,
int *waitp)
@@ -142,14 +141,11 @@ struct Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
char addrbuf[128];
#endif
int pf;
-#if !defined(CURL_DISABLE_VERBOSE_STRINGS)
- struct Curl_easy *data = conn->data;
-#endif
*waitp = 0; /* synchronous response only */
/* Check if a limited name resolve has been requested */
- switch(conn->ip_version) {
+ switch(data->set.ipver) {
case CURL_IPRESOLVE_V4:
pf = PF_INET;
break;
@@ -161,13 +157,13 @@ struct Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
break;
}
- if((pf != PF_INET) && !Curl_ipv6works(conn))
+ if((pf != PF_INET) && !Curl_ipv6works(data))
/* The stack seems to be a non-IPv6 one */
pf = PF_INET;
memset(&hints, 0, sizeof(hints));
hints.ai_family = pf;
- hints.ai_socktype = (conn->transport == TRNSPRT_TCP) ?
+ hints.ai_socktype = (data->conn->transport == TRNSPRT_TCP) ?
SOCK_STREAM : SOCK_DGRAM;
#ifndef USE_RESOLVE_ON_IPS
diff --git a/Utilities/cmcurl/lib/hostsyn.c b/Utilities/cmcurl/lib/hostsyn.c
index 9e31008d2..550b43a08 100644
--- a/Utilities/cmcurl/lib/hostsyn.c
+++ b/Utilities/cmcurl/lib/hostsyn.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
diff --git a/Utilities/cmcurl/lib/hsts.c b/Utilities/cmcurl/lib/hsts.c
new file mode 100644
index 000000000..0e7c19cfb
--- /dev/null
+++ b/Utilities/cmcurl/lib/hsts.c
@@ -0,0 +1,522 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2020 - 2021, 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.
+ *
+ ***************************************************************************/
+/*
+ * The Strict-Transport-Security header is defined in RFC 6797:
+ * https://tools.ietf.org/html/rfc6797
+ */
+#include "curl_setup.h"
+
+#if !defined(CURL_DISABLE_HTTP) && defined(USE_HSTS)
+#include <curl/curl.h>
+#include "urldata.h"
+#include "llist.h"
+#include "hsts.h"
+#include "curl_get_line.h"
+#include "strcase.h"
+#include "sendf.h"
+#include "strtoofft.h"
+#include "parsedate.h"
+#include "rand.h"
+#include "rename.h"
+
+/* The last 3 #include files should be in this order */
+#include "curl_printf.h"
+#include "curl_memory.h"
+#include "memdebug.h"
+
+#define MAX_HSTS_LINE 4095
+#define MAX_HSTS_HOSTLEN 256
+#define MAX_HSTS_HOSTLENSTR "256"
+#define MAX_HSTS_SUBLEN 4
+#define MAX_HSTS_SUBLENSTR "4"
+#define MAX_HSTS_DATELEN 64
+#define MAX_HSTS_DATELENSTR "64"
+
+#ifdef DEBUGBUILD
+/* to play well with debug builds, we can *set* a fixed time this will
+ return */
+time_t deltatime; /* allow for "adjustments" for unit test purposes */
+static time_t debugtime(void *unused)
+{
+ char *timestr = getenv("CURL_TIME");
+ (void)unused;
+ if(timestr) {
+ unsigned long val = strtol(timestr, NULL, 10) + deltatime;
+ return (time_t)val;
+ }
+ return time(NULL);
+}
+#define time(x) debugtime(x)
+#endif
+
+struct hsts *Curl_hsts_init(void)
+{
+ struct hsts *h = calloc(sizeof(struct hsts), 1);
+ if(h) {
+ Curl_llist_init(&h->list, NULL);
+ }
+ return h;
+}
+
+static void hsts_free(struct stsentry *e)
+{
+ free((char *)e->host);
+ free(e);
+}
+
+void Curl_hsts_cleanup(struct hsts **hp)
+{
+ struct hsts *h = *hp;
+ if(h) {
+ struct Curl_llist_element *e;
+ struct Curl_llist_element *n;
+ for(e = h->list.head; e; e = n) {
+ struct stsentry *sts = e->ptr;
+ n = e->next;
+ hsts_free(sts);
+ }
+ free(h->filename);
+ free(h);
+ *hp = NULL;
+ }
+}
+
+static struct stsentry *hsts_entry(void)
+{
+ return calloc(sizeof(struct stsentry), 1);
+}
+
+static CURLcode hsts_create(struct hsts *h,
+ const char *hostname,
+ bool subdomains,
+ curl_off_t expires)
+{
+ struct stsentry *sts = hsts_entry();
+ if(!sts)
+ return CURLE_OUT_OF_MEMORY;
+
+ sts->expires = expires;
+ sts->includeSubDomains = subdomains;
+ sts->host = strdup(hostname);
+ if(!sts->host) {
+ free(sts);
+ return CURLE_OUT_OF_MEMORY;
+ }
+ Curl_llist_insert_next(&h->list, h->list.tail, sts, &sts->node);
+ return CURLE_OK;
+}
+
+CURLcode Curl_hsts_parse(struct hsts *h, const char *hostname,
+ const char *header)
+{
+ const char *p = header;
+ curl_off_t expires = 0;
+ bool gotma = FALSE;
+ bool gotinc = FALSE;
+ bool subdomains = FALSE;
+ struct stsentry *sts;
+ time_t now = time(NULL);
+
+ do {
+ while(*p && ISSPACE(*p))
+ p++;
+ if(Curl_strncasecompare("max-age=", p, 8)) {
+ bool quoted = FALSE;
+ CURLofft offt;
+ char *endp;
+
+ if(gotma)
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+
+ p += 8;
+ while(*p && ISSPACE(*p))
+ p++;
+ if(*p == '\"') {
+ p++;
+ quoted = TRUE;
+ }
+ offt = curlx_strtoofft(p, &endp, 10, &expires);
+ if(offt == CURL_OFFT_FLOW)
+ expires = CURL_OFF_T_MAX;
+ else if(offt)
+ /* invalid max-age */
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ p = endp;
+ if(quoted) {
+ if(*p != '\"')
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ p++;
+ }
+ gotma = TRUE;
+ }
+ else if(Curl_strncasecompare("includesubdomains", p, 17)) {
+ if(gotinc)
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ subdomains = TRUE;
+ p += 17;
+ gotinc = TRUE;
+ }
+ else {
+ /* unknown directive, do a lame attempt to skip */
+ while(*p && (*p != ';'))
+ p++;
+ }
+
+ while(*p && ISSPACE(*p))
+ p++;
+ if(*p == ';')
+ p++;
+ } while (*p);
+
+ if(!gotma)
+ /* max-age is mandatory */
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+
+ if(!expires) {
+ /* remove the entry if present verbatim (without subdomain match) */
+ sts = Curl_hsts(h, hostname, FALSE);
+ if(sts) {
+ Curl_llist_remove(&h->list, &sts->node, NULL);
+ hsts_free(sts);
+ }
+ return CURLE_OK;
+ }
+
+ if(CURL_OFF_T_MAX - now < expires)
+ /* would overflow, use maximum value */
+ expires = CURL_OFF_T_MAX;
+ else
+ expires += now;
+
+ /* check if it already exists */
+ sts = Curl_hsts(h, hostname, FALSE);
+ if(sts) {
+ /* just update these fields */
+ sts->expires = expires;
+ sts->includeSubDomains = subdomains;
+ }
+ else
+ return hsts_create(h, hostname, subdomains, expires);
+
+ return CURLE_OK;
+}
+
+/*
+ * Return TRUE if the given host name is currently an HSTS one.
+ *
+ * The 'subdomain' argument tells the function if subdomain matching should be
+ * attempted.
+ */
+struct stsentry *Curl_hsts(struct hsts *h, const char *hostname,
+ bool subdomain)
+{
+ if(h) {
+ time_t now = time(NULL);
+ size_t hlen = strlen(hostname);
+ struct Curl_llist_element *e;
+ struct Curl_llist_element *n;
+ for(e = h->list.head; e; e = n) {
+ struct stsentry *sts = e->ptr;
+ n = e->next;
+ if(sts->expires <= now) {
+ /* remove expired entries */
+ Curl_llist_remove(&h->list, &sts->node, NULL);
+ hsts_free(sts);
+ continue;
+ }
+ if(subdomain && sts->includeSubDomains) {
+ size_t ntail = strlen(sts->host);
+ if(ntail < hlen) {
+ size_t offs = hlen - ntail;
+ if((hostname[offs-1] == '.') &&
+ Curl_strncasecompare(&hostname[offs], sts->host, ntail))
+ return sts;
+ }
+ }
+ if(Curl_strcasecompare(hostname, sts->host))
+ return sts;
+ }
+ }
+ return NULL; /* no match */
+}
+
+/*
+ * Send this HSTS entry to the write callback.
+ */
+static CURLcode hsts_push(struct Curl_easy *data,
+ struct curl_index *i,
+ struct stsentry *sts,
+ bool *stop)
+{
+ struct curl_hstsentry e;
+ CURLSTScode sc;
+ struct tm stamp;
+ CURLcode result;
+
+ e.name = (char *)sts->host;
+ e.namelen = strlen(sts->host);
+ e.includeSubDomains = sts->includeSubDomains;
+
+ result = Curl_gmtime(sts->expires, &stamp);
+ if(result)
+ return result;
+
+ msnprintf(e.expire, sizeof(e.expire), "%d%02d%02d %02d:%02d:%02d",
+ stamp.tm_year + 1900, stamp.tm_mon + 1, stamp.tm_mday,
+ stamp.tm_hour, stamp.tm_min, stamp.tm_sec);
+
+ sc = data->set.hsts_write(data, &e, i,
+ data->set.hsts_write_userp);
+ *stop = (sc != CURLSTS_OK);
+ return sc == CURLSTS_FAIL ? CURLE_BAD_FUNCTION_ARGUMENT : CURLE_OK;
+}
+
+/*
+ * Write this single hsts entry to a single output line
+ */
+static CURLcode hsts_out(struct stsentry *sts, FILE *fp)
+{
+ struct tm stamp;
+ CURLcode result = Curl_gmtime(sts->expires, &stamp);
+ if(result)
+ return result;
+
+ fprintf(fp, "%s%s \"%d%02d%02d %02d:%02d:%02d\"\n",
+ sts->includeSubDomains ? ".": "", sts->host,
+ stamp.tm_year + 1900, stamp.tm_mon + 1, stamp.tm_mday,
+ stamp.tm_hour, stamp.tm_min, stamp.tm_sec);
+ return CURLE_OK;
+}
+
+
+/*
+ * Curl_https_save() writes the HSTS cache to file and callback.
+ */
+CURLcode Curl_hsts_save(struct Curl_easy *data, struct hsts *h,
+ const char *file)
+{
+ struct Curl_llist_element *e;
+ struct Curl_llist_element *n;
+ CURLcode result = CURLE_OK;
+ FILE *out;
+ char *tempstore;
+ unsigned char randsuffix[9];
+
+ if(!h)
+ /* no cache activated */
+ return CURLE_OK;
+
+ /* if no new name is given, use the one we stored from the load */
+ if(!file && h->filename)
+ file = h->filename;
+
+ if((h->flags & CURLHSTS_READONLYFILE) || !file || !file[0])
+ /* marked as read-only, no file or zero length file name */
+ goto skipsave;
+
+ if(Curl_rand_hex(data, randsuffix, sizeof(randsuffix)))
+ return CURLE_FAILED_INIT;
+
+ tempstore = aprintf("%s.%s.tmp", file, randsuffix);
+ if(!tempstore)
+ return CURLE_OUT_OF_MEMORY;
+
+ out = fopen(tempstore, FOPEN_WRITETEXT);
+ if(!out)
+ result = CURLE_WRITE_ERROR;
+ else {
+ fputs("# Your HSTS cache. https://curl.se/docs/hsts.html\n"
+ "# This file was generated by libcurl! Edit at your own risk.\n",
+ out);
+ for(e = h->list.head; e; e = n) {
+ struct stsentry *sts = e->ptr;
+ n = e->next;
+ result = hsts_out(sts, out);
+ if(result)
+ break;
+ }
+ fclose(out);
+ if(!result && Curl_rename(tempstore, file))
+ result = CURLE_WRITE_ERROR;
+
+ if(result)
+ unlink(tempstore);
+ }
+ free(tempstore);
+ skipsave:
+ if(data->set.hsts_write) {
+ /* if there's a write callback */
+ struct curl_index i; /* count */
+ i.total = h->list.size;
+ i.index = 0;
+ for(e = h->list.head; e; e = n) {
+ struct stsentry *sts = e->ptr;
+ bool stop;
+ n = e->next;
+ result = hsts_push(data, &i, sts, &stop);
+ if(result || stop)
+ break;
+ i.index++;
+ }
+ }
+ return result;
+}
+
+/* only returns SERIOUS errors */
+static CURLcode hsts_add(struct hsts *h, char *line)
+{
+ /* Example lines:
+ example.com "20191231 10:00:00"
+ .example.net "20191231 10:00:00"
+ */
+ char host[MAX_HSTS_HOSTLEN + 1];
+ char date[MAX_HSTS_DATELEN + 1];
+ int rc;
+
+ rc = sscanf(line,
+ "%" MAX_HSTS_HOSTLENSTR "s \"%" MAX_HSTS_DATELENSTR "[^\"]\"",
+ host, date);
+ if(2 == rc) {
+ time_t expires = Curl_getdate_capped(date);
+ CURLcode result;
+ char *p = host;
+ bool subdomain = FALSE;
+ if(p[0] == '.') {
+ p++;
+ subdomain = TRUE;
+ }
+ result = hsts_create(h, p, subdomain, expires);
+ if(result)
+ return result;
+ }
+
+ return CURLE_OK;
+}
+
+/*
+ * Load HSTS data from callback.
+ *
+ */
+static CURLcode hsts_pull(struct Curl_easy *data, struct hsts *h)
+{
+ /* if the HSTS read callback is set, use it */
+ if(data->set.hsts_read) {
+ CURLSTScode sc;
+ DEBUGASSERT(h);
+ do {
+ char buffer[257];
+ struct curl_hstsentry e;
+ e.name = buffer;
+ e.namelen = sizeof(buffer)-1;
+ e.includeSubDomains = FALSE; /* default */
+ e.expire[0] = 0;
+ e.name[0] = 0; /* just to make it clean */
+ sc = data->set.hsts_read(data, &e, data->set.hsts_read_userp);
+ if(sc == CURLSTS_OK) {
+ time_t expires;
+ CURLcode result;
+ if(!e.name[0])
+ /* bail out if no name was stored */
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ if(e.expire[0])
+ expires = Curl_getdate_capped(e.expire);
+ else
+ expires = TIME_T_MAX; /* the end of time */
+ result = hsts_create(h, e.name, e.includeSubDomains, expires);
+ if(result)
+ return result;
+ }
+ else if(sc == CURLSTS_FAIL)
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ } while(sc == CURLSTS_OK);
+ }
+ return CURLE_OK;
+}
+
+/*
+ * Load the HSTS cache from the given file. The text based line-oriented file
+ * format is documented here:
+ * https://github.com/curl/curl/wiki/HSTS
+ *
+ * This function only returns error on major problems that prevent hsts
+ * handling to work completely. It will ignore individual syntactical errors
+ * etc.
+ */
+static CURLcode hsts_load(struct hsts *h, const char *file)
+{
+ CURLcode result = CURLE_OK;
+ char *line = NULL;
+ FILE *fp;
+
+ /* we need a private copy of the file name so that the hsts cache file
+ name survives an easy handle reset */
+ free(h->filename);
+ h->filename = strdup(file);
+ if(!h->filename)
+ return CURLE_OUT_OF_MEMORY;
+
+ fp = fopen(file, FOPEN_READTEXT);
+ if(fp) {
+ line = malloc(MAX_HSTS_LINE);
+ if(!line)
+ goto fail;
+ while(Curl_get_line(line, MAX_HSTS_LINE, fp)) {
+ char *lineptr = line;
+ while(*lineptr && ISBLANK(*lineptr))
+ lineptr++;
+ if(*lineptr == '#')
+ /* skip commented lines */
+ continue;
+
+ hsts_add(h, lineptr);
+ }
+ free(line); /* free the line buffer */
+ fclose(fp);
+ }
+ return result;
+
+ fail:
+ Curl_safefree(h->filename);
+ fclose(fp);
+ return CURLE_OUT_OF_MEMORY;
+}
+
+/*
+ * Curl_hsts_loadfile() loads HSTS from file
+ */
+CURLcode Curl_hsts_loadfile(struct Curl_easy *data,
+ struct hsts *h, const char *file)
+{
+ DEBUGASSERT(h);
+ (void)data;
+ return hsts_load(h, file);
+}
+
+/*
+ * Curl_hsts_loadcb() loads HSTS from callback
+ */
+CURLcode Curl_hsts_loadcb(struct Curl_easy *data, struct hsts *h)
+{
+ return hsts_pull(data, h);
+}
+
+#endif /* CURL_DISABLE_HTTP || USE_HSTS */
diff --git a/Utilities/cmcurl/lib/hsts.h b/Utilities/cmcurl/lib/hsts.h
new file mode 100644
index 000000000..ae5db74a2
--- /dev/null
+++ b/Utilities/cmcurl/lib/hsts.h
@@ -0,0 +1,65 @@
+#ifndef HEADER_CURL_HSTS_H
+#define HEADER_CURL_HSTS_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "curl_setup.h"
+
+#if !defined(CURL_DISABLE_HTTP) && defined(USE_HSTS)
+#include <curl/curl.h>
+#include "llist.h"
+
+#ifdef DEBUGBUILD
+extern time_t deltatime;
+#endif
+
+struct stsentry {
+ struct Curl_llist_element node;
+ const char *host;
+ bool includeSubDomains;
+ time_t expires; /* the timestamp of this entry's expiry */
+};
+
+/* The HSTS cache. Needs to be able to tailmatch host names. */
+struct hsts {
+ struct Curl_llist list;
+ char *filename;
+ unsigned int flags;
+};
+
+struct hsts *Curl_hsts_init(void);
+void Curl_hsts_cleanup(struct hsts **hp);
+CURLcode Curl_hsts_parse(struct hsts *h, const char *hostname,
+ const char *sts);
+struct stsentry *Curl_hsts(struct hsts *h, const char *hostname,
+ bool subdomain);
+CURLcode Curl_hsts_save(struct Curl_easy *data, struct hsts *h,
+ const char *file);
+CURLcode Curl_hsts_loadfile(struct Curl_easy *data,
+ struct hsts *h, const char *file);
+CURLcode Curl_hsts_loadcb(struct Curl_easy *data,
+ struct hsts *h);
+#else
+#define Curl_hsts_cleanup(x)
+#define Curl_hsts_loadcb(x,y)
+#define Curl_hsts_save(x,y,z)
+#endif /* CURL_DISABLE_HTTP || USE_HSTS */
+#endif /* HEADER_CURL_HSTS_H */
diff --git a/Utilities/cmcurl/lib/http.c b/Utilities/cmcurl/lib/http.c
index 8fcdd436d..6f7f55d07 100644
--- a/Utilities/cmcurl/lib/http.c
+++ b/Utilities/cmcurl/lib/http.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -45,6 +45,10 @@
#include <sys/param.h>
#endif
+#ifdef USE_HYPER
+#include <hyper.h>
+#endif
+
#include "urldata.h"
#include <curl/curl.h>
#include "transfer.h"
@@ -60,6 +64,7 @@
#include "http_ntlm.h"
#include "curl_ntlm_wb.h"
#include "http_negotiate.h"
+#include "http_aws_sigv4.h"
#include "url.h"
#include "share.h"
#include "hostip.h"
@@ -77,6 +82,8 @@
#include "connect.h"
#include "strdup.h"
#include "altsvc.h"
+#include "hsts.h"
+#include "c-hyper.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
@@ -87,22 +94,25 @@
* Forward declarations.
*/
-static int http_getsock_do(struct connectdata *conn,
+static int http_getsock_do(struct Curl_easy *data,
+ struct connectdata *conn,
curl_socket_t *socks);
-static int http_should_fail(struct connectdata *conn);
+static bool http_should_fail(struct Curl_easy *data);
#ifndef CURL_DISABLE_PROXY
-static CURLcode add_haproxy_protocol_header(struct connectdata *conn);
+static CURLcode add_haproxy_protocol_header(struct Curl_easy *data);
#endif
#ifdef USE_SSL
-static CURLcode https_connecting(struct connectdata *conn, bool *done);
-static int https_getsock(struct connectdata *conn,
+static CURLcode https_connecting(struct Curl_easy *data, bool *done);
+static int https_getsock(struct Curl_easy *data,
+ struct connectdata *conn,
curl_socket_t *socks);
#else
#define https_connecting(x,y) CURLE_COULDNT_CONNECT
#endif
-static CURLcode http_setup_conn(struct connectdata *conn);
+static CURLcode http_setup_conn(struct Curl_easy *data,
+ struct connectdata *conn);
/*
* HTTP handler interface.
@@ -125,6 +135,7 @@ const struct Curl_handler Curl_handler_http = {
ZERO_NULL, /* connection_check */
PORT_HTTP, /* defport */
CURLPROTO_HTTP, /* protocol */
+ CURLPROTO_HTTP, /* family */
PROTOPT_CREDSPERREQUEST | /* flags */
PROTOPT_USERPWDCTRL
};
@@ -151,25 +162,26 @@ const struct Curl_handler Curl_handler_https = {
ZERO_NULL, /* connection_check */
PORT_HTTPS, /* defport */
CURLPROTO_HTTPS, /* protocol */
+ CURLPROTO_HTTP, /* family */
PROTOPT_SSL | PROTOPT_CREDSPERREQUEST | PROTOPT_ALPN_NPN | /* flags */
PROTOPT_USERPWDCTRL
};
#endif
-static CURLcode http_setup_conn(struct connectdata *conn)
+static CURLcode http_setup_conn(struct Curl_easy *data,
+ struct connectdata *conn)
{
/* allocate the HTTP-specific struct for the Curl_easy, only to survive
during this request */
struct HTTP *http;
- struct Curl_easy *data = conn->data;
- DEBUGASSERT(data->req.protop == NULL);
+ DEBUGASSERT(data->req.p.http == NULL);
http = calloc(1, sizeof(struct HTTP));
if(!http)
return CURLE_OUT_OF_MEMORY;
- Curl_mime_initpart(&http->form, conn->data);
- data->req.protop = http;
+ Curl_mime_initpart(&http->form, data);
+ data->req.p.http = http;
if(data->set.httpversion == CURL_HTTP_VERSION_3) {
if(conn->handler->flags & PROTOPT_SSL)
@@ -196,16 +208,16 @@ static CURLcode http_setup_conn(struct connectdata *conn)
* if proxy headers are not available, then it will lookup into http header
* link list
*
- * It takes a connectdata struct as input instead of the Curl_easy simply to
- * know if this is a proxy request or not, as it then might check a different
- * header list. Provide the header prefix without colon!.
+ * It takes a connectdata struct as input to see if this is a proxy request or
+ * not, as it then might check a different header list. Provide the header
+ * prefix without colon!
*/
-char *Curl_checkProxyheaders(const struct connectdata *conn,
+char *Curl_checkProxyheaders(struct Curl_easy *data,
+ const struct connectdata *conn,
const char *thisheader)
{
struct curl_slist *head;
size_t thislen = strlen(thisheader);
- struct Curl_easy *data = conn->data;
for(head = (conn->bits.proxy && data->set.sep_headers) ?
data->set.proxyheaders : data->set.headers;
@@ -219,7 +231,7 @@ char *Curl_checkProxyheaders(const struct connectdata *conn,
}
#else
/* disabled */
-#define Curl_checkProxyheaders(x,y) NULL
+#define Curl_checkProxyheaders(x,y,z) NULL
#endif
/*
@@ -282,11 +294,11 @@ char *Curl_copy_header_value(const char *header)
*
* Returns CURLcode.
*/
-static CURLcode http_output_basic(struct connectdata *conn, bool proxy)
+static CURLcode http_output_basic(struct Curl_easy *data, bool proxy)
{
size_t size = 0;
char *authorization = NULL;
- struct Curl_easy *data = conn->data;
+ struct connectdata *conn = data->conn;
char **userp;
const char *user;
const char *pwd;
@@ -342,16 +354,15 @@ static CURLcode http_output_basic(struct connectdata *conn, bool proxy)
*
* Returns CURLcode.
*/
-static CURLcode http_output_bearer(struct connectdata *conn)
+static CURLcode http_output_bearer(struct Curl_easy *data)
{
char **userp;
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
userp = &data->state.aptr.userpwd;
free(*userp);
*userp = aprintf("Authorization: Bearer %s\r\n",
- conn->data->set.str[STRING_BEARER]);
+ data->set.str[STRING_BEARER]);
if(!*userp) {
result = CURLE_OUT_OF_MEMORY;
@@ -390,6 +401,8 @@ static bool pickoneauth(struct auth *pick, unsigned long mask)
pick->picked = CURLAUTH_NTLM_WB;
else if(avail & CURLAUTH_BASIC)
pick->picked = CURLAUTH_BASIC;
+ else if(avail & CURLAUTH_AWS_SIGV4)
+ pick->picked = CURLAUTH_AWS_SIGV4;
else {
pick->picked = CURLAUTH_PICKNONE; /* we select to use nothing */
picked = FALSE;
@@ -422,10 +435,10 @@ static bool pickoneauth(struct auth *pick, unsigned long mask)
* }
* }
*/
-static CURLcode http_perhapsrewind(struct connectdata *conn)
+static CURLcode http_perhapsrewind(struct Curl_easy *data,
+ struct connectdata *conn)
{
- struct Curl_easy *data = conn->data;
- struct HTTP *http = data->req.protop;
+ struct HTTP *http = data->req.p.http;
curl_off_t bytessent;
curl_off_t expectsend = -1; /* default is unknown */
@@ -542,7 +555,7 @@ static CURLcode http_perhapsrewind(struct connectdata *conn)
if(bytessent)
/* we rewind now at once since if we already sent something */
- return Curl_readrewind(conn);
+ return Curl_readrewind(data);
return CURLE_OK;
}
@@ -554,9 +567,9 @@ static CURLcode http_perhapsrewind(struct connectdata *conn)
* picked.
*/
-CURLcode Curl_http_auth_act(struct connectdata *conn)
+CURLcode Curl_http_auth_act(struct Curl_easy *data)
{
- struct Curl_easy *data = conn->data;
+ struct connectdata *conn = data->conn;
bool pickhost = FALSE;
bool pickproxy = FALSE;
CURLcode result = CURLE_OK;
@@ -582,7 +595,7 @@ CURLcode Curl_http_auth_act(struct connectdata *conn)
conn->httpversion > 11) {
infof(data, "Forcing HTTP/1.1 for NTLM");
connclose(conn, "Force HTTP/1.1 connection");
- conn->data->set.httpversion = CURL_HTTP_VERSION_1_1;
+ data->set.httpversion = CURL_HTTP_VERSION_1_1;
}
}
#ifndef CURL_DISABLE_PROXY
@@ -600,7 +613,7 @@ CURLcode Curl_http_auth_act(struct connectdata *conn)
if((data->state.httpreq != HTTPREQ_GET) &&
(data->state.httpreq != HTTPREQ_HEAD) &&
!conn->bits.rewindaftersend) {
- result = http_perhapsrewind(conn);
+ result = http_perhapsrewind(data, conn);
if(result)
return result;
}
@@ -627,7 +640,7 @@ CURLcode Curl_http_auth_act(struct connectdata *conn)
data->state.authhost.done = TRUE;
}
}
- if(http_should_fail(conn)) {
+ if(http_should_fail(data)) {
failf(data, "The requested URL returned error: %d",
data->req.httpcode);
result = CURLE_HTTP_RETURNED_ERROR;
@@ -642,7 +655,8 @@ CURLcode Curl_http_auth_act(struct connectdata *conn)
* and whether or not it is to a proxy.
*/
static CURLcode
-output_auth_headers(struct connectdata *conn,
+output_auth_headers(struct Curl_easy *data,
+ struct connectdata *conn,
struct auth *authstatus,
const char *request,
const char *path,
@@ -650,17 +664,24 @@ output_auth_headers(struct connectdata *conn,
{
const char *auth = NULL;
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
#ifdef CURL_DISABLE_CRYPTO_AUTH
(void)request;
(void)path;
#endif
-
+#ifndef CURL_DISABLE_CRYPTO_AUTH
+ if(authstatus->picked == CURLAUTH_AWS_SIGV4) {
+ auth = "AWS_SIGV4";
+ result = Curl_output_aws_sigv4(data, proxy);
+ if(result)
+ return result;
+ }
+ else
+#endif
#ifdef USE_SPNEGO
if(authstatus->picked == CURLAUTH_NEGOTIATE) {
auth = "Negotiate";
- result = Curl_output_negotiate(conn, proxy);
+ result = Curl_output_negotiate(data, conn, proxy);
if(result)
return result;
}
@@ -669,7 +690,7 @@ output_auth_headers(struct connectdata *conn,
#ifdef USE_NTLM
if(authstatus->picked == CURLAUTH_NTLM) {
auth = "NTLM";
- result = Curl_output_ntlm(conn, proxy);
+ result = Curl_output_ntlm(data, proxy);
if(result)
return result;
}
@@ -678,7 +699,7 @@ output_auth_headers(struct connectdata *conn,
#if defined(USE_NTLM) && defined(NTLM_WB_ENABLED)
if(authstatus->picked == CURLAUTH_NTLM_WB) {
auth = "NTLM_WB";
- result = Curl_output_ntlm_wb(conn, proxy);
+ result = Curl_output_ntlm_wb(data, conn, proxy);
if(result)
return result;
}
@@ -687,7 +708,8 @@ output_auth_headers(struct connectdata *conn,
#ifndef CURL_DISABLE_CRYPTO_AUTH
if(authstatus->picked == CURLAUTH_DIGEST) {
auth = "Digest";
- result = Curl_output_digest(conn,
+ result = Curl_output_digest(data,
+ conn,
proxy,
(const unsigned char *)request,
(const unsigned char *)path);
@@ -701,12 +723,12 @@ output_auth_headers(struct connectdata *conn,
if(
#ifndef CURL_DISABLE_PROXY
(proxy && conn->bits.proxy_user_passwd &&
- !Curl_checkProxyheaders(conn, "Proxy-authorization")) ||
+ !Curl_checkProxyheaders(data, conn, "Proxy-authorization")) ||
#endif
(!proxy && conn->bits.user_passwd &&
- !Curl_checkheaders(conn, "Authorization"))) {
+ !Curl_checkheaders(data, "Authorization"))) {
auth = "Basic";
- result = http_output_basic(conn, proxy);
+ result = http_output_basic(data, proxy);
if(result)
return result;
}
@@ -718,9 +740,9 @@ output_auth_headers(struct connectdata *conn,
if(authstatus->picked == CURLAUTH_BEARER) {
/* Bearer */
if((!proxy && data->set.str[STRING_BEARER] &&
- !Curl_checkheaders(conn, "Authorization:"))) {
+ !Curl_checkheaders(data, "Authorization:"))) {
auth = "Bearer";
- result = http_output_bearer(conn);
+ result = http_output_bearer(data);
if(result)
return result;
}
@@ -751,7 +773,7 @@ output_auth_headers(struct connectdata *conn,
/**
* Curl_http_output_auth() setups the authentication headers for the
* host/proxy and the correct authentication
- * method. conn->data->state.authdone is set to TRUE when authentication is
+ * method. data->state.authdone is set to TRUE when authentication is
* done.
*
* @param conn all information about the current connection
@@ -763,14 +785,15 @@ output_auth_headers(struct connectdata *conn,
* @returns CURLcode
*/
CURLcode
-Curl_http_output_auth(struct connectdata *conn,
+Curl_http_output_auth(struct Curl_easy *data,
+ struct connectdata *conn,
const char *request,
+ Curl_HttpReq httpreq,
const char *path,
bool proxytunnel) /* TRUE if this is the request setting
up the proxy tunnel */
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
struct auth *authhost;
struct auth *authproxy;
@@ -807,7 +830,7 @@ Curl_http_output_auth(struct connectdata *conn,
/* Send proxy authentication header if needed */
if(conn->bits.httpproxy &&
(conn->bits.tunnel_proxy == (bit)proxytunnel)) {
- result = output_auth_headers(conn, authproxy, request, path, TRUE);
+ result = output_auth_headers(data, conn, authproxy, request, path, TRUE);
if(result)
return result;
}
@@ -826,11 +849,22 @@ Curl_http_output_auth(struct connectdata *conn,
!data->state.first_host ||
data->set.allow_auth_to_other_hosts ||
strcasecompare(data->state.first_host, conn->host.name)) {
- result = output_auth_headers(conn, authhost, request, path, FALSE);
+ result = output_auth_headers(data, conn, authhost, request, path, FALSE);
}
else
authhost->done = TRUE;
+ if(((authhost->multipass && !authhost->done) ||
+ (authproxy->multipass && !authproxy->done)) &&
+ (httpreq != HTTPREQ_GET) &&
+ (httpreq != HTTPREQ_HEAD)) {
+ /* Auth is required and we are not authenticated yet. Make a PUT or POST
+ with content-length zero as a "probe". */
+ conn->bits.authneg = TRUE;
+ }
+ else
+ conn->bits.authneg = FALSE;
+
return result;
}
@@ -856,14 +890,13 @@ Curl_http_output_auth(struct connectdata *conn,
* proxy CONNECT loop.
*/
-CURLcode Curl_http_input_auth(struct connectdata *conn, bool proxy,
+CURLcode Curl_http_input_auth(struct Curl_easy *data, bool proxy,
const char *auth) /* the first non-space */
{
/*
* This resource requires authentication
*/
- struct Curl_easy *data = conn->data;
-
+ struct connectdata *conn = data->conn;
#ifdef USE_SPNEGO
curlnegotiate *negstate = proxy ? &conn->proxy_negotiate_state :
&conn->http_negotiate_state;
@@ -871,6 +904,8 @@ CURLcode Curl_http_input_auth(struct connectdata *conn, bool proxy,
unsigned long *availp;
struct auth *authp;
+ (void) conn; /* In case conditionals make it unused. */
+
if(proxy) {
availp = &data->info.proxyauthavail;
authp = &data->state.authproxy;
@@ -905,7 +940,7 @@ CURLcode Curl_http_input_auth(struct connectdata *conn, bool proxy,
authp->avail |= CURLAUTH_NEGOTIATE;
if(authp->picked == CURLAUTH_NEGOTIATE) {
- CURLcode result = Curl_input_negotiate(conn, proxy, auth);
+ CURLcode result = Curl_input_negotiate(data, conn, proxy, auth);
if(!result) {
DEBUGASSERT(!data->req.newurl);
data->req.newurl = strdup(data->change.url);
@@ -934,7 +969,7 @@ CURLcode Curl_http_input_auth(struct connectdata *conn, bool proxy,
if(authp->picked == CURLAUTH_NTLM ||
authp->picked == CURLAUTH_NTLM_WB) {
/* NTLM authentication is picked and activated */
- CURLcode result = Curl_input_ntlm(conn, proxy, auth);
+ CURLcode result = Curl_input_ntlm(data, proxy, auth);
if(!result) {
data->state.authproblem = FALSE;
#ifdef NTLM_WB_ENABLED
@@ -944,7 +979,7 @@ CURLcode Curl_http_input_auth(struct connectdata *conn, bool proxy,
*availp |= CURLAUTH_NTLM_WB;
authp->avail |= CURLAUTH_NTLM_WB;
- result = Curl_input_ntlm_wb(conn, proxy, auth);
+ result = Curl_input_ntlm_wb(data, conn, proxy, auth);
if(result) {
infof(data, "Authentication problem. Ignoring this.\n");
data->state.authproblem = TRUE;
@@ -975,7 +1010,7 @@ CURLcode Curl_http_input_auth(struct connectdata *conn, bool proxy,
* authentication isn't activated yet, as we need to store the
* incoming data from this header in case we are going to use
* Digest */
- result = Curl_input_digest(conn, proxy, auth);
+ result = Curl_input_digest(data, proxy, auth);
if(result) {
infof(data, "Authentication problem. Ignoring this.\n");
data->state.authproblem = TRUE;
@@ -1027,18 +1062,15 @@ CURLcode Curl_http_input_auth(struct connectdata *conn, bool proxy,
*
* @param conn all information about the current connection
*
- * @retval 0 communications should continue
+ * @retval FALSE communications should continue
*
- * @retval 1 communications should not continue
+ * @retval TRUE communications should not continue
*/
-static int http_should_fail(struct connectdata *conn)
+static bool http_should_fail(struct Curl_easy *data)
{
- struct Curl_easy *data;
int httpcode;
-
- DEBUGASSERT(conn);
- data = conn->data;
DEBUGASSERT(data);
+ DEBUGASSERT(data->conn);
httpcode = data->req.httpcode;
@@ -1047,20 +1079,20 @@ static int http_should_fail(struct connectdata *conn)
** don't fail.
*/
if(!data->set.http_fail_on_error)
- return 0;
+ return FALSE;
/*
** Any code < 400 is never terminal.
*/
if(httpcode < 400)
- return 0;
+ return FALSE;
/*
** Any code >= 400 that's not 401 or 407 is always
** a terminal error
*/
if((httpcode != 401) && (httpcode != 407))
- return 1;
+ return TRUE;
/*
** All we have left to deal with is 401 and 407
@@ -1085,16 +1117,17 @@ static int http_should_fail(struct connectdata *conn)
** Either we're not authenticating, or we're supposed to
** be authenticating something else. This is an error.
*/
- if((httpcode == 401) && !conn->bits.user_passwd)
+ if((httpcode == 401) && !data->conn->bits.user_passwd)
return TRUE;
#ifndef CURL_DISABLE_PROXY
- if((httpcode == 407) && !conn->bits.proxy_user_passwd)
+ if((httpcode == 407) && !data->conn->bits.proxy_user_passwd)
return TRUE;
#endif
return data->state.authproblem;
}
+#ifndef USE_HYPER
/*
* readmoredata() is a "fread() emulation" to provide POST and/or request
* data. It is used when a huge POST is to be made and the entire chunk wasn't
@@ -1108,8 +1141,8 @@ static size_t readmoredata(char *buffer,
size_t nitems,
void *userp)
{
- struct connectdata *conn = (struct connectdata *)userp;
- struct HTTP *http = conn->data->req.protop;
+ struct Curl_easy *data = (struct Curl_easy *)userp;
+ struct HTTP *http = data->req.p.http;
size_t fullsize = size * nitems;
if(!http->postsize)
@@ -1117,7 +1150,7 @@ static size_t readmoredata(char *buffer,
return 0;
/* make sure that a HTTP request is never sent away chunked! */
- conn->data->req.forbidchunk = (http->sending == HTTPSEND_REQUEST)?TRUE:FALSE;
+ data->req.forbidchunk = (http->sending == HTTPSEND_REQUEST)?TRUE:FALSE;
if(http->postsize <= (curl_off_t)fullsize) {
memcpy(buffer, http->postdata, (size_t)http->postsize);
@@ -1127,8 +1160,8 @@ static size_t readmoredata(char *buffer,
/* move backup data into focus and continue on that */
http->postdata = http->backup.postdata;
http->postsize = http->backup.postsize;
- conn->data->state.fread_func = http->backup.fread_func;
- conn->data->state.in = http->backup.fread_in;
+ data->state.fread_func = http->backup.fread_func;
+ data->state.in = http->backup.fread_in;
http->sending++; /* move one step up */
@@ -1154,7 +1187,7 @@ static size_t readmoredata(char *buffer,
* Returns CURLcode
*/
CURLcode Curl_buffer_send(struct dynbuf *in,
- struct connectdata *conn,
+ struct Curl_easy *data,
/* add the number of sent bytes to this
counter */
curl_off_t *bytes_written,
@@ -1166,8 +1199,8 @@ CURLcode Curl_buffer_send(struct dynbuf *in,
CURLcode result;
char *ptr;
size_t size;
- struct Curl_easy *data = conn->data;
- struct HTTP *http = data->req.protop;
+ struct connectdata *conn = data->conn;
+ struct HTTP *http = data->req.p.http;
size_t sendsize;
curl_socket_t sockfd;
size_t headersize;
@@ -1226,7 +1259,9 @@ CURLcode Curl_buffer_send(struct dynbuf *in,
}
else {
#ifdef CURLDEBUG
- /* Allow debug builds override this logic to force short initial sends */
+ /* Allow debug builds to override this logic to force short initial
+ sends
+ */
char *p = getenv("CURL_SMALLREQSEND");
if(p) {
size_t altsize = (size_t)strtoul(p, NULL, 10);
@@ -1240,7 +1275,7 @@ CURLcode Curl_buffer_send(struct dynbuf *in,
sendsize = size;
}
- result = Curl_write(conn, sockfd, ptr, sendsize, &amount);
+ result = Curl_write(data, sockfd, ptr, sendsize, &amount);
if(!result) {
/*
@@ -1252,16 +1287,12 @@ CURLcode Curl_buffer_send(struct dynbuf *in,
size_t headlen = (size_t)amount>headersize ? headersize : (size_t)amount;
size_t bodylen = amount - headlen;
- if(data->set.verbose) {
- /* this data _may_ contain binary stuff */
- Curl_debug(data, CURLINFO_HEADER_OUT, ptr, headlen);
- if(bodylen) {
- /* there was body data sent beyond the initial header part, pass that
- on to the debug callback too */
- Curl_debug(data, CURLINFO_DATA_OUT,
- ptr + headlen, bodylen);
- }
- }
+ /* this data _may_ contain binary stuff */
+ Curl_debug(data, CURLINFO_HEADER_OUT, ptr, headlen);
+ if(bodylen)
+ /* there was body data sent beyond the initial header part, pass that on
+ to the debug callback too */
+ Curl_debug(data, CURLINFO_DATA_OUT, ptr + headlen, bodylen);
/* 'amount' can never be a very large value here so typecasting it so a
signed 31 bit value should not cause problems even if ssize_t is
@@ -1291,10 +1322,13 @@ CURLcode Curl_buffer_send(struct dynbuf *in,
/* set the new pointers for the request-sending */
data->state.fread_func = (curl_read_callback)readmoredata;
- data->state.in = (void *)conn;
+ data->state.in = (void *)data;
http->postdata = ptr;
http->postsize = (curl_off_t)size;
+ /* this much data is remaining header: */
+ data->req.pendingheader = headersize - headlen;
+
http->send_buffer = *in; /* copy the whole struct */
http->sending = HTTPSEND_REQUEST;
@@ -1317,9 +1351,13 @@ CURLcode Curl_buffer_send(struct dynbuf *in,
}
Curl_dyn_free(in);
+ /* no remaining header data */
+ data->req.pendingheader = 0;
return result;
}
+#endif
+
/* end of the add_buffer functions */
/* ------------------------------------------------------------------------- */
@@ -1353,7 +1391,7 @@ Curl_compareheader(const char *headerline, /* line to check */
/* pass the header */
start = &headerline[hlen];
- /* pass all white spaces */
+ /* pass all whitespace */
while(*start && ISSPACE(*start))
start++;
@@ -1384,9 +1422,10 @@ Curl_compareheader(const char *headerline, /* line to check */
* Curl_http_connect() performs HTTP stuff to do at connect-time, called from
* the generic Curl_connect().
*/
-CURLcode Curl_http_connect(struct connectdata *conn, bool *done)
+CURLcode Curl_http_connect(struct Curl_easy *data, bool *done)
{
CURLcode result;
+ struct connectdata *conn = data->conn;
/* We default to persistent connections. We set this already in this connect
function to make the re-use checks properly be able to check this bit. */
@@ -1394,7 +1433,7 @@ CURLcode Curl_http_connect(struct connectdata *conn, bool *done)
#ifndef CURL_DISABLE_PROXY
/* the CONNECT procedure might not have been completed */
- result = Curl_proxy_connect(conn, FIRSTSOCKET);
+ result = Curl_proxy_connect(data, FIRSTSOCKET);
if(result)
return result;
@@ -1409,9 +1448,9 @@ CURLcode Curl_http_connect(struct connectdata *conn, bool *done)
/* nothing else to do except wait right now - we're not done here. */
return CURLE_OK;
- if(conn->data->set.haproxyprotocol) {
+ if(data->set.haproxyprotocol) {
/* add HAProxy PROXY protocol header */
- result = add_haproxy_protocol_header(conn);
+ result = add_haproxy_protocol_header(data);
if(result)
return result;
}
@@ -1419,7 +1458,7 @@ CURLcode Curl_http_connect(struct connectdata *conn, bool *done)
if(conn->given->protocol & CURLPROTO_HTTPS) {
/* perform SSL initialization */
- result = https_connecting(conn, done);
+ result = https_connecting(data, done);
if(result)
return result;
}
@@ -1432,24 +1471,27 @@ CURLcode Curl_http_connect(struct connectdata *conn, bool *done)
/* this returns the socket to wait for in the DO and DOING state for the multi
interface and then we're always _sending_ a request and thus we wait for
the single socket to become writable only */
-static int http_getsock_do(struct connectdata *conn,
+static int http_getsock_do(struct Curl_easy *data,
+ struct connectdata *conn,
curl_socket_t *socks)
{
/* write mode */
+ (void)data;
socks[0] = conn->sock[FIRSTSOCKET];
return GETSOCK_WRITESOCK(0);
}
#ifndef CURL_DISABLE_PROXY
-static CURLcode add_haproxy_protocol_header(struct connectdata *conn)
+static CURLcode add_haproxy_protocol_header(struct Curl_easy *data)
{
char proxy_header[128];
struct dynbuf req;
CURLcode result;
char tcp_version[5];
+ DEBUGASSERT(data->conn);
/* Emit the correct prefix for IPv6 */
- if(conn->bits.ipv6) {
+ if(data->conn->bits.ipv6) {
strcpy(tcp_version, "TCP6");
}
else {
@@ -1460,10 +1502,10 @@ static CURLcode add_haproxy_protocol_header(struct connectdata *conn)
sizeof(proxy_header),
"PROXY %s %s %s %li %li\r\n",
tcp_version,
- conn->data->info.conn_local_ip,
- conn->data->info.conn_primary_ip,
- conn->data->info.conn_local_port,
- conn->data->info.conn_primary_port);
+ data->info.conn_local_ip,
+ data->info.conn_primary_ip,
+ data->info.conn_local_port,
+ data->info.conn_primary_port);
Curl_dyn_init(&req, DYN_HAXPROXY);
@@ -1471,7 +1513,7 @@ static CURLcode add_haproxy_protocol_header(struct connectdata *conn)
if(result)
return result;
- result = Curl_buffer_send(&req, conn, &conn->data->info.request_size,
+ result = Curl_buffer_send(&req, data, &data->info.request_size,
0, FIRSTSOCKET);
return result;
@@ -1479,10 +1521,11 @@ static CURLcode add_haproxy_protocol_header(struct connectdata *conn)
#endif
#ifdef USE_SSL
-static CURLcode https_connecting(struct connectdata *conn, bool *done)
+static CURLcode https_connecting(struct Curl_easy *data, bool *done)
{
CURLcode result;
- DEBUGASSERT((conn) && (conn->handler->flags & PROTOPT_SSL));
+ struct connectdata *conn = data->conn;
+ DEBUGASSERT((data) && (data->conn->handler->flags & PROTOPT_SSL));
#ifdef ENABLE_QUIC
if(conn->transport == TRNSPRT_QUIC) {
@@ -1492,16 +1535,18 @@ static CURLcode https_connecting(struct connectdata *conn, bool *done)
#endif
/* perform SSL initialization for this socket */
- result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, done);
+ result = Curl_ssl_connect_nonblocking(data, conn, FIRSTSOCKET, done);
if(result)
connclose(conn, "Failed HTTPS connection");
return result;
}
-static int https_getsock(struct connectdata *conn,
+static int https_getsock(struct Curl_easy *data,
+ struct connectdata *conn,
curl_socket_t *socks)
{
+ (void)data;
if(conn->handler->flags & PROTOPT_SSL)
return Curl_ssl_getsock(conn, socks);
return GETSOCK_BLANK;
@@ -1513,18 +1558,18 @@ static int https_getsock(struct connectdata *conn,
* performed.
*/
-CURLcode Curl_http_done(struct connectdata *conn,
+CURLcode Curl_http_done(struct Curl_easy *data,
CURLcode status, bool premature)
{
- struct Curl_easy *data = conn->data;
- struct HTTP *http = data->req.protop;
+ struct connectdata *conn = data->conn;
+ struct HTTP *http = data->req.p.http;
/* Clear multipass flag. If authentication isn't done yet, then it will get
* a chance to be set back to true when we output the next auth header */
data->state.authhost.multipass = FALSE;
data->state.authproxy.multipass = FALSE;
- Curl_unencode_cleanup(conn);
+ Curl_unencode_cleanup(data);
/* set the proper values (possibly modified on POST) */
conn->seek_func = data->set.seek_func; /* restore */
@@ -1538,6 +1583,7 @@ CURLcode Curl_http_done(struct connectdata *conn,
Curl_quic_done(data, premature);
Curl_mime_cleanpart(&http->form);
Curl_dyn_reset(&data->state.headerb);
+ Curl_hyper_done(data);
if(status)
return status;
@@ -1553,6 +1599,8 @@ CURLcode Curl_http_done(struct connectdata *conn,
read from the HTTP server (that counts), this can't be right so we
return an error here */
failf(data, "Empty reply from server");
+ /* Mark it as closed to avoid the "left intact" message */
+ streamclose(conn, "Empty reply from server");
return CURLE_GOT_NOTHING;
}
@@ -1580,6 +1628,7 @@ static bool use_http_1_1plus(const struct Curl_easy *data,
(data->set.httpversion >= CURL_HTTP_VERSION_1_1));
}
+#ifndef USE_HYPER
static const char *get_http_string(const struct Curl_easy *data,
const struct connectdata *conn)
{
@@ -1599,6 +1648,7 @@ static const char *get_http_string(const struct Curl_easy *data,
return "1.0";
}
+#endif
/* check and possibly add an Expect: header */
static CURLcode expect100(struct Curl_easy *data,
@@ -1613,7 +1663,7 @@ static CURLcode expect100(struct Curl_easy *data,
/* if not doing HTTP 1.0 or version 2, or disabled explicitly, we add an
Expect: 100-continue to the headers which actually speeds up post
operations (as there is one packet coming back from the web server) */
- const char *ptr = Curl_checkheaders(conn, "Expect");
+ const char *ptr = Curl_checkheaders(data, "Expect");
if(ptr) {
data->state.expect100header =
Curl_compareheader(ptr, "Expect:", "100-continue");
@@ -1679,15 +1729,20 @@ CURLcode Curl_http_compile_trailers(struct curl_slist *trailers,
return result;
}
-CURLcode Curl_add_custom_headers(struct connectdata *conn,
+CURLcode Curl_add_custom_headers(struct Curl_easy *data,
bool is_connect,
- struct dynbuf *req)
+#ifndef USE_HYPER
+ struct dynbuf *req
+#else
+ void *req
+#endif
+ )
{
+ struct connectdata *conn = data->conn;
char *ptr;
struct curl_slist *h[2];
struct curl_slist *headers;
int numlists = 1; /* by default */
- struct Curl_easy *data = conn->data;
int i;
#ifndef CURL_DISABLE_PROXY
@@ -1748,7 +1803,9 @@ CURLcode Curl_add_custom_headers(struct connectdata *conn,
/* copy the source */
semicolonp = strdup(headers->data);
if(!semicolonp) {
+#ifndef USE_HYPER
Curl_dyn_free(req);
+#endif
return CURLE_OUT_OF_MEMORY;
}
/* put a colon where the semicolon is */
@@ -1809,7 +1866,11 @@ CURLcode Curl_add_custom_headers(struct connectdata *conn,
!strcasecompare(data->state.first_host, conn->host.name)))
;
else {
+#ifdef USE_HYPER
+ result = Curl_hyper_header(data, req, compare);
+#else
result = Curl_dyn_addf(req, "%s\r\n", compare);
+#endif
}
if(semicolonp)
free(semicolonp);
@@ -1825,10 +1886,14 @@ CURLcode Curl_add_custom_headers(struct connectdata *conn,
}
#ifndef CURL_DISABLE_PARSEDATE
-CURLcode Curl_add_timecondition(const struct connectdata *conn,
- struct dynbuf *req)
+CURLcode Curl_add_timecondition(struct Curl_easy *data,
+#ifndef USE_HYPER
+ struct dynbuf *req
+#else
+ void *req
+#endif
+ )
{
- struct Curl_easy *data = conn->data;
const struct tm *tm;
struct tm keeptime;
CURLcode result;
@@ -1861,7 +1926,7 @@ CURLcode Curl_add_timecondition(const struct connectdata *conn,
break;
}
- if(Curl_checkheaders(conn, condp)) {
+ if(Curl_checkheaders(data, condp)) {
/* A custom header was specified; it will be sent instead. */
return CURLE_OK;
}
@@ -1885,7 +1950,11 @@ CURLcode Curl_add_timecondition(const struct connectdata *conn,
tm->tm_min,
tm->tm_sec);
+#ifndef USE_HYPER
result = Curl_dyn_add(req, datestr);
+#else
+ result = Curl_hyper_header(data, req, datestr);
+#endif
return result;
}
@@ -1900,102 +1969,14 @@ CURLcode Curl_add_timecondition(const struct connectdata *conn,
}
#endif
-/*
- * Curl_http() gets called from the generic multi_do() function when a HTTP
- * request is to be performed. This creates and sends a properly constructed
- * HTTP request.
- */
-CURLcode Curl_http(struct connectdata *conn, bool *done)
+void Curl_http_method(struct Curl_easy *data, struct connectdata *conn,
+ const char **method, Curl_HttpReq *reqp)
{
- struct Curl_easy *data = conn->data;
- CURLcode result = CURLE_OK;
- struct HTTP *http;
- const char *path = data->state.up.path;
- const char *query = data->state.up.query;
- bool paste_ftp_userpwd = FALSE;
- char ftp_typecode[sizeof("/;type=?")] = "";
- const char *host = conn->host.name;
- const char *te = ""; /* transfer-encoding */
- const char *ptr;
- const char *request;
Curl_HttpReq httpreq = data->state.httpreq;
-#if !defined(CURL_DISABLE_COOKIES)
- char *addcookies = NULL;
-#endif
- curl_off_t included_body = 0;
- const char *httpstring;
- struct dynbuf req;
- curl_off_t postsize = 0; /* curl_off_t to handle large file sizes */
- char *altused = NULL;
-
- /* Always consider the DO phase done after this function call, even if there
- may be parts of the request that is not yet sent, since we can deal with
- the rest of the request in the PERFORM phase. */
- *done = TRUE;
-
- if(conn->transport != TRNSPRT_QUIC) {
- if(conn->httpversion < 20) { /* unless the connection is re-used and
- already http2 */
- switch(conn->negnpn) {
- case CURL_HTTP_VERSION_2:
- conn->httpversion = 20; /* we know we're on HTTP/2 now */
-
- result = Curl_http2_switched(conn, NULL, 0);
- if(result)
- return result;
- break;
- case CURL_HTTP_VERSION_1_1:
- /* continue with HTTP/1.1 when explicitly requested */
- break;
- default:
- /* Check if user wants to use HTTP/2 with clear TCP*/
-#ifdef USE_NGHTTP2
- if(conn->data->set.httpversion ==
- CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE) {
-#ifndef CURL_DISABLE_PROXY
- if(conn->bits.httpproxy && !conn->bits.tunnel_proxy) {
- /* We don't support HTTP/2 proxies yet. Also it's debatable
- whether or not this setting should apply to HTTP/2 proxies. */
- infof(data, "Ignoring HTTP/2 prior knowledge due to proxy\n");
- break;
- }
-#endif
- DEBUGF(infof(data, "HTTP/2 over clean TCP\n"));
- conn->httpversion = 20;
-
- result = Curl_http2_switched(conn, NULL, 0);
- if(result)
- return result;
- }
-#endif
- break;
- }
- }
- else {
- /* prepare for a http2 request */
- result = Curl_http2_setup(conn);
- if(result)
- return result;
- }
- }
- http = data->req.protop;
- DEBUGASSERT(http);
-
- if(!data->state.this_is_a_follow) {
- /* Free to avoid leaking memory on multiple requests*/
- free(data->state.first_host);
-
- data->state.first_host = strdup(conn->host.name);
- if(!data->state.first_host)
- return CURLE_OUT_OF_MEMORY;
-
- data->state.first_remote_port = conn->remote_port;
- }
-
+ const char *request;
if((conn->handler->protocol&(PROTO_FAMILY_HTTP|CURLPROTO_FTP)) &&
- data->set.upload) {
+ data->set.upload)
httpreq = HTTPREQ_PUT;
- }
/* Now set the 'request' pointer to the proper request string */
if(data->set.str[STRING_CUSTOMREQUEST])
@@ -2004,7 +1985,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
if(data->set.opt_no_body)
request = "HEAD";
else {
- DEBUGASSERT((httpreq > HTTPREQ_NONE) && (httpreq < HTTPREQ_LAST));
+ DEBUGASSERT((httpreq >= HTTPREQ_GET) && (httpreq <= HTTPREQ_HEAD));
switch(httpreq) {
case HTTPREQ_POST:
case HTTPREQ_POST_FORM:
@@ -2024,180 +2005,40 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
}
}
}
+ *method = request;
+ *reqp = httpreq;
+}
+CURLcode Curl_http_useragent(struct Curl_easy *data)
+{
/* The User-Agent string might have been allocated in url.c already, because
it might have been used in the proxy connect, but if we have got a header
with the user-agent string specified, we erase the previously made string
here. */
- if(Curl_checkheaders(conn, "User-Agent")) {
+ if(Curl_checkheaders(data, "User-Agent")) {
free(data->state.aptr.uagent);
data->state.aptr.uagent = NULL;
}
+ return CURLE_OK;
+}
- /* setup the authentication headers */
- {
- char *pq = NULL;
- if(query && *query) {
- pq = aprintf("%s?%s", path, query);
- if(!pq)
- return CURLE_OUT_OF_MEMORY;
- }
- result = Curl_http_output_auth(conn, request, (pq ? pq : path), FALSE);
- free(pq);
- if(result)
- return result;
- }
-
- if(((data->state.authhost.multipass && !data->state.authhost.done)
- || (data->state.authproxy.multipass && !data->state.authproxy.done)) &&
- (httpreq != HTTPREQ_GET) &&
- (httpreq != HTTPREQ_HEAD)) {
- /* Auth is required and we are not authenticated yet. Make a PUT or POST
- with content-length zero as a "probe". */
- conn->bits.authneg = TRUE;
- }
- else
- conn->bits.authneg = FALSE;
-
- Curl_safefree(data->state.aptr.ref);
- if(data->change.referer && !Curl_checkheaders(conn, "Referer")) {
- data->state.aptr.ref = aprintf("Referer: %s\r\n", data->change.referer);
- if(!data->state.aptr.ref)
- return CURLE_OUT_OF_MEMORY;
- }
- else
- data->state.aptr.ref = NULL;
-
-#if !defined(CURL_DISABLE_COOKIES)
- if(data->set.str[STRING_COOKIE] && !Curl_checkheaders(conn, "Cookie"))
- addcookies = data->set.str[STRING_COOKIE];
-#endif
-
- if(!Curl_checkheaders(conn, "Accept-Encoding") &&
- data->set.str[STRING_ENCODING]) {
- Curl_safefree(data->state.aptr.accept_encoding);
- data->state.aptr.accept_encoding =
- aprintf("Accept-Encoding: %s\r\n", data->set.str[STRING_ENCODING]);
- if(!data->state.aptr.accept_encoding)
- return CURLE_OUT_OF_MEMORY;
- }
- else {
- Curl_safefree(data->state.aptr.accept_encoding);
- data->state.aptr.accept_encoding = NULL;
- }
-
-#ifdef HAVE_LIBZ
- /* we only consider transfer-encoding magic if libz support is built-in */
-
- if(!Curl_checkheaders(conn, "TE") &&
- data->set.http_transfer_encoding) {
- /* When we are to insert a TE: header in the request, we must also insert
- TE in a Connection: header, so we need to merge the custom provided
- Connection: header and prevent the original to get sent. Note that if
- the user has inserted his/hers own TE: header we don't do this magic
- but then assume that the user will handle it all! */
- char *cptr = Curl_checkheaders(conn, "Connection");
-#define TE_HEADER "TE: gzip\r\n"
-
- Curl_safefree(data->state.aptr.te);
-
- if(cptr) {
- cptr = Curl_copy_header_value(cptr);
- if(!cptr)
- return CURLE_OUT_OF_MEMORY;
- }
- /* Create the (updated) Connection: header */
- data->state.aptr.te = aprintf("Connection: %s%sTE\r\n" TE_HEADER,
- cptr ? cptr : "", (cptr && *cptr) ? ", ":"");
+CURLcode Curl_http_host(struct Curl_easy *data, struct connectdata *conn)
+{
+ const char *ptr;
+ if(!data->state.this_is_a_follow) {
+ /* Free to avoid leaking memory on multiple requests*/
+ free(data->state.first_host);
- free(cptr);
- if(!data->state.aptr.te)
+ data->state.first_host = strdup(conn->host.name);
+ if(!data->state.first_host)
return CURLE_OUT_OF_MEMORY;
- }
-#endif
-
- switch(httpreq) {
- case HTTPREQ_POST_MIME:
- http->sendit = &data->set.mimepost;
- break;
- case HTTPREQ_POST_FORM:
- /* Convert the form structure into a mime structure. */
- Curl_mime_cleanpart(&http->form);
- result = Curl_getformdata(data, &http->form, data->set.httppost,
- data->state.fread_func);
- if(result)
- return result;
- http->sendit = &http->form;
- break;
- default:
- http->sendit = NULL;
- }
-
-#ifndef CURL_DISABLE_MIME
- if(http->sendit) {
- const char *cthdr = Curl_checkheaders(conn, "Content-Type");
-
- /* Read and seek body only. */
- http->sendit->flags |= MIME_BODY_ONLY;
-
- /* Prepare the mime structure headers & set content type. */
-
- if(cthdr)
- for(cthdr += 13; *cthdr == ' '; cthdr++)
- ;
- else if(http->sendit->kind == MIMEKIND_MULTIPART)
- cthdr = "multipart/form-data";
- curl_mime_headers(http->sendit, data->set.headers, 0);
- result = Curl_mime_prepare_headers(http->sendit, cthdr,
- NULL, MIMESTRATEGY_FORM);
- curl_mime_headers(http->sendit, NULL, 0);
- if(!result)
- result = Curl_mime_rewind(http->sendit);
- if(result)
- return result;
- http->postsize = Curl_mime_size(http->sendit);
- }
-#endif
-
- ptr = Curl_checkheaders(conn, "Transfer-Encoding");
- if(ptr) {
- /* Some kind of TE is requested, check if 'chunked' is chosen */
- data->req.upload_chunky =
- Curl_compareheader(ptr, "Transfer-Encoding:", "chunked");
- }
- else {
- if((conn->handler->protocol & PROTO_FAMILY_HTTP) &&
- (((httpreq == HTTPREQ_POST_MIME || httpreq == HTTPREQ_POST_FORM) &&
- http->postsize < 0) ||
- ((data->set.upload || httpreq == HTTPREQ_POST) &&
- data->state.infilesize == -1))) {
- if(conn->bits.authneg)
- /* don't enable chunked during auth neg */
- ;
- else if(use_http_1_1plus(data, conn)) {
- if(conn->httpversion < 20)
- /* HTTP, upload, unknown file size and not HTTP 1.0 */
- data->req.upload_chunky = TRUE;
- }
- else {
- failf(data, "Chunky upload is not supported by HTTP 1.0");
- return CURLE_UPLOAD_FAILED;
- }
- }
- else {
- /* else, no chunky upload */
- data->req.upload_chunky = FALSE;
- }
-
- if(data->req.upload_chunky)
- te = "Transfer-Encoding: chunked\r\n";
+ data->state.first_remote_port = conn->remote_port;
}
-
Curl_safefree(data->state.aptr.host);
- ptr = Curl_checkheaders(conn, "Host");
+ ptr = Curl_checkheaders(data, "Host");
if(ptr && (!data->state.this_is_a_follow ||
strcasecompare(data->state.first_host, conn->host.name))) {
#if !defined(CURL_DISABLE_COOKIES)
@@ -2247,6 +2088,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
else {
/* When building Host: headers, we must put the host name within
[brackets] if the host name is a plain IPv6-address. RFC2732-style. */
+ const char *host = conn->host.name;
if(((conn->given->protocol&CURLPROTO_HTTPS) &&
(conn->remote_port == PORT_HTTPS)) ||
@@ -2269,6 +2111,24 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
/* without Host: we can't make a nice request */
return CURLE_OUT_OF_MEMORY;
}
+ return CURLE_OK;
+}
+
+/*
+ * Append the request-target to the HTTP request
+ */
+CURLcode Curl_http_target(struct Curl_easy *data,
+ struct connectdata *conn,
+ struct dynbuf *r)
+{
+ CURLcode result = CURLE_OK;
+ const char *path = data->state.up.path;
+ const char *query = data->state.up.query;
+
+ if(data->set.str[STRING_TARGET]) {
+ path = data->set.str[STRING_TARGET];
+ query = NULL;
+ }
#ifndef CURL_DISABLE_PROXY
if(conn->bits.httpproxy && !conn->bits.tunnel_proxy) {
@@ -2280,6 +2140,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
/* and no fragment part */
CURLUcode uc;
+ char *url;
CURLU *h = curl_url_dup(data->state.uh);
if(!h)
return CURLE_OUT_OF_MEMORY;
@@ -2313,7 +2174,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
/* Extract the URL to use in the request. Store in STRING_TEMP_URL for
clean-up reasons if the function returns before the free() further
down. */
- uc = curl_url_get(h, CURLUPART_URL, &data->set.str[STRING_TEMP_URL], 0);
+ uc = curl_url_get(h, CURLUPART_URL, &url, 0);
if(uc) {
curl_url_cleanup(h);
return CURLE_OUT_OF_MEMORY;
@@ -2321,6 +2182,13 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
curl_url_cleanup(h);
+ /* target or url */
+ result = Curl_dyn_add(r, data->set.str[STRING_TARGET]?
+ data->set.str[STRING_TARGET]:url);
+ free(url);
+ if(result)
+ return (result);
+
if(strcasecompare("ftp", data->state.up.scheme)) {
if(data->set.proxy_transfer_mode) {
/* when doing ftp, append ;type=<a|i> if not present */
@@ -2336,325 +2204,128 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
}
}
if(!type) {
- char *p = ftp_typecode;
- /* avoid sending invalid URLs like ftp://example.com;type=i if the
- * user specified ftp://example.com without the slash */
- if(!*data->state.up.path && path[strlen(path) - 1] != '/') {
- *p++ = '/';
- }
- msnprintf(p, sizeof(ftp_typecode) - 1, ";type=%c",
- data->set.prefer_ascii ? 'a' : 'i');
- }
- }
- if(conn->bits.user_passwd)
- paste_ftp_userpwd = TRUE;
- }
- }
-#endif /* CURL_DISABLE_PROXY */
-
- http->p_accept = Curl_checkheaders(conn, "Accept")?NULL:"Accept: */*\r\n";
-
- if((HTTPREQ_POST == httpreq || HTTPREQ_PUT == httpreq) &&
- data->state.resume_from) {
- /**********************************************************************
- * Resuming upload in HTTP means that we PUT or POST and that we have
- * got a resume_from value set. The resume value has already created
- * a Range: header that will be passed along. We need to "fast forward"
- * the file the given number of bytes and decrease the assume upload
- * file size before we continue this venture in the dark lands of HTTP.
- * Resuming mime/form posting at an offset > 0 has no sense and is ignored.
- *********************************************************************/
-
- if(data->state.resume_from < 0) {
- /*
- * This is meant to get the size of the present remote-file by itself.
- * We don't support this now. Bail out!
- */
- data->state.resume_from = 0;
- }
-
- if(data->state.resume_from && !data->state.this_is_a_follow) {
- /* do we still game? */
-
- /* Now, let's read off the proper amount of bytes from the
- input. */
- int seekerr = CURL_SEEKFUNC_CANTSEEK;
- if(conn->seek_func) {
- Curl_set_in_callback(data, true);
- seekerr = conn->seek_func(conn->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_READ_ERROR;
- }
- /* when seekerr == CURL_SEEKFUNC_CANTSEEK (can't seek to offset) */
- do {
- size_t readthisamountnow =
- (data->state.resume_from - passed > data->set.buffer_size) ?
- (size_t)data->set.buffer_size :
- curlx_sotouz(data->state.resume_from - passed);
-
- size_t actuallyread =
- data->state.fread_func(data->state.buffer, 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, "Could only read %" CURL_FORMAT_CURL_OFF_T
- " bytes from the input", passed);
- return CURLE_READ_ERROR;
- }
- } while(passed < data->state.resume_from);
- }
-
- /* now, decrease the size of the read */
- if(data->state.infilesize>0) {
- data->state.infilesize -= data->state.resume_from;
-
- if(data->state.infilesize <= 0) {
- failf(data, "File already completely uploaded");
- return CURLE_PARTIAL_FILE;
+ result = Curl_dyn_addf(r, ";type=%c",
+ data->set.prefer_ascii ? 'a' : 'i');
+ if(result)
+ return result;
}
}
- /* we've passed, proceed as normal */
}
}
- if(data->state.use_range) {
- /*
- * A range is selected. We use different headers whether we're downloading
- * or uploading and we always let customized headers override our internal
- * ones if any such are specified.
- */
- if(((httpreq == HTTPREQ_GET) || (httpreq == HTTPREQ_HEAD)) &&
- !Curl_checkheaders(conn, "Range")) {
- /* if a line like this was already allocated, free the previous one */
- free(data->state.aptr.rangeline);
- data->state.aptr.rangeline = aprintf("Range: bytes=%s\r\n",
- data->state.range);
- }
- else if((httpreq == HTTPREQ_POST || httpreq == HTTPREQ_PUT) &&
- !Curl_checkheaders(conn, "Content-Range")) {
-
- /* if a line like this was already allocated, free the previous one */
- free(data->state.aptr.rangeline);
-
- if(data->set.set_resume_from < 0) {
- /* Upload resume was asked for, but we don't know the size of the
- remote part so we tell the server (and act accordingly) that we
- upload the whole file (again) */
- data->state.aptr.rangeline =
- aprintf("Content-Range: bytes 0-%" CURL_FORMAT_CURL_OFF_T
- "/%" CURL_FORMAT_CURL_OFF_T "\r\n",
- data->state.infilesize - 1, data->state.infilesize);
- }
- else if(data->state.resume_from) {
- /* This is because "resume" was selected */
- curl_off_t total_expected_size =
- data->state.resume_from + data->state.infilesize;
- data->state.aptr.rangeline =
- aprintf("Content-Range: bytes %s%" CURL_FORMAT_CURL_OFF_T
- "/%" CURL_FORMAT_CURL_OFF_T "\r\n",
- data->state.range, total_expected_size-1,
- total_expected_size);
- }
- else {
- /* Range was selected and then we just pass the incoming range and
- append total size */
- data->state.aptr.rangeline =
- aprintf("Content-Range: bytes %s/%" CURL_FORMAT_CURL_OFF_T "\r\n",
- data->state.range, data->state.infilesize);
- }
- if(!data->state.aptr.rangeline)
- return CURLE_OUT_OF_MEMORY;
- }
- }
-
- httpstring = get_http_string(data, conn);
-
- /* initialize a dynamic send-buffer */
- Curl_dyn_init(&req, DYN_HTTP_REQUEST);
-
- /* add the main request stuff */
- /* GET/HEAD/POST/PUT */
- result = Curl_dyn_addf(&req, "%s ", request);
- if(result)
- return result;
-
- if(data->set.str[STRING_TARGET]) {
- path = data->set.str[STRING_TARGET];
- query = NULL;
- }
-
-#ifndef CURL_DISABLE_PROXY
- /* url */
- if(conn->bits.httpproxy && !conn->bits.tunnel_proxy) {
- char *url = data->set.str[STRING_TEMP_URL];
- result = Curl_dyn_add(&req, url);
- Curl_safefree(data->set.str[STRING_TEMP_URL]);
- }
else
+#else
+ (void)conn; /* not used in disabled-proxy builds */
#endif
- if(paste_ftp_userpwd)
- result = Curl_dyn_addf(&req, "ftp://%s:%s@%s", conn->user, conn->passwd,
- path + sizeof("ftp://") - 1);
- else {
- result = Curl_dyn_add(&req, path);
+ {
+ result = Curl_dyn_add(r, path);
if(result)
return result;
if(query)
- result = Curl_dyn_addf(&req, "?%s", query);
+ result = Curl_dyn_addf(r, "?%s", query);
}
- if(result)
- return result;
-
-#ifdef USE_ALTSVC
- if(conn->bits.altused && !Curl_checkheaders(conn, "Alt-Used")) {
- altused = aprintf("Alt-Used: %s:%d\r\n",
- conn->conn_to_host.name, conn->conn_to_port);
- if(!altused) {
- Curl_dyn_free(&req);
- return CURLE_OUT_OF_MEMORY;
- }
- }
-#endif
- result =
- Curl_dyn_addf(&req,
- "%s" /* ftp typecode (;type=x) */
- " 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 */
- ftp_typecode,
- httpstring,
- (data->state.aptr.host?data->state.aptr.host:""),
- data->state.aptr.proxyuserpwd?
- data->state.aptr.proxyuserpwd:"",
- 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:"",
- http->p_accept?http->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->change.referer && data->state.aptr.ref)?
- data->state.aptr.ref:"" /* Referer: <data> */,
-#ifndef CURL_DISABLE_PROXY
- (conn->bits.httpproxy &&
- !conn->bits.tunnel_proxy &&
- !Curl_checkProxyheaders(conn, "Proxy-Connection"))?
- "Proxy-Connection: Keep-Alive\r\n":"",
-#else
- "",
-#endif
- te,
- altused ? altused : ""
- );
-
- /* clear userpwd and proxyuserpwd to avoid re-using old credentials
- * from re-used connections */
- Curl_safefree(data->state.aptr.userpwd);
- Curl_safefree(data->state.aptr.proxyuserpwd);
- free(altused);
+ return result;
+}
- if(result)
- return result;
+CURLcode Curl_http_body(struct Curl_easy *data, struct connectdata *conn,
+ Curl_HttpReq httpreq, const char **tep)
+{
+ CURLcode result = CURLE_OK;
+ const char *ptr;
+ struct HTTP *http = data->req.p.http;
+ http->postsize = 0;
- if(!(conn->handler->flags&PROTOPT_SSL) &&
- conn->httpversion != 20 &&
- (data->set.httpversion == CURL_HTTP_VERSION_2)) {
- /* append HTTP2 upgrade magic stuff to the HTTP request if it isn't done
- over SSL */
- result = Curl_http2_request_upgrade(&req, conn);
+ switch(httpreq) {
+ case HTTPREQ_POST_MIME:
+ http->sendit = &data->set.mimepost;
+ break;
+ case HTTPREQ_POST_FORM:
+ /* Convert the form structure into a mime structure. */
+ Curl_mime_cleanpart(&http->form);
+ result = Curl_getformdata(data, &http->form, data->set.httppost,
+ data->state.fread_func);
if(result)
return result;
+ http->sendit = &http->form;
+ break;
+ default:
+ http->sendit = NULL;
}
-#if !defined(CURL_DISABLE_COOKIES)
- if(data->cookies || addcookies) {
- struct Cookie *co = NULL; /* no cookies from start */
- int count = 0;
+#ifndef CURL_DISABLE_MIME
+ if(http->sendit) {
+ const char *cthdr = Curl_checkheaders(data, "Content-Type");
- if(data->cookies && data->state.cookie_engine) {
- Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
- co = Curl_cookie_getlist(data->cookies,
- data->state.aptr.cookiehost?
- data->state.aptr.cookiehost:host,
- data->state.up.path,
- (conn->handler->protocol&CURLPROTO_HTTPS)?
- TRUE:FALSE);
- Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
- }
- if(co) {
- struct Cookie *store = co;
- /* now loop through all cookies that matched */
- while(co) {
- if(co->value) {
- if(0 == count) {
- result = Curl_dyn_add(&req, "Cookie: ");
- if(result)
- break;
- }
- result = Curl_dyn_addf(&req, "%s%s=%s", count?"; ":"",
- co->name, co->value);
- if(result)
- break;
- count++;
- }
- co = co->next; /* next cookie please */
- }
- Curl_cookie_freelist(store);
- }
- if(addcookies && !result) {
- if(!count)
- result = Curl_dyn_add(&req, "Cookie: ");
- if(!result) {
- result = Curl_dyn_addf(&req, "%s%s", count?"; ":"", addcookies);
- count++;
- }
- }
- if(count && !result)
- result = Curl_dyn_add(&req, "\r\n");
+ /* Read and seek body only. */
+ http->sendit->flags |= MIME_BODY_ONLY;
+
+ /* Prepare the mime structure headers & set content type. */
+ if(cthdr)
+ for(cthdr += 13; *cthdr == ' '; cthdr++)
+ ;
+ else if(http->sendit->kind == MIMEKIND_MULTIPART)
+ cthdr = "multipart/form-data";
+
+ curl_mime_headers(http->sendit, data->set.headers, 0);
+ result = Curl_mime_prepare_headers(http->sendit, cthdr,
+ NULL, MIMESTRATEGY_FORM);
+ curl_mime_headers(http->sendit, NULL, 0);
+ if(!result)
+ result = Curl_mime_rewind(http->sendit);
if(result)
return result;
+ http->postsize = Curl_mime_size(http->sendit);
}
#endif
- result = Curl_add_timecondition(conn, &req);
- if(result)
- return result;
+ ptr = Curl_checkheaders(data, "Transfer-Encoding");
+ if(ptr) {
+ /* Some kind of TE is requested, check if 'chunked' is chosen */
+ data->req.upload_chunky =
+ Curl_compareheader(ptr, "Transfer-Encoding:", "chunked");
+ }
+ else {
+ if((conn->handler->protocol & PROTO_FAMILY_HTTP) &&
+ (((httpreq == HTTPREQ_POST_MIME || httpreq == HTTPREQ_POST_FORM) &&
+ http->postsize < 0) ||
+ ((data->set.upload || httpreq == HTTPREQ_POST) &&
+ data->state.infilesize == -1))) {
+ if(conn->bits.authneg)
+ /* don't enable chunked during auth neg */
+ ;
+ else if(use_http_1_1plus(data, conn)) {
+ if(conn->httpversion < 20)
+ /* HTTP, upload, unknown file size and not HTTP 1.0 */
+ data->req.upload_chunky = TRUE;
+ }
+ else {
+ failf(data, "Chunky upload is not supported by HTTP 1.0");
+ return CURLE_UPLOAD_FAILED;
+ }
+ }
+ else {
+ /* else, no chunky upload */
+ data->req.upload_chunky = FALSE;
+ }
- result = Curl_add_custom_headers(conn, FALSE, &req);
- if(result)
- return result;
+ if(data->req.upload_chunky)
+ *tep = "Transfer-Encoding: chunked\r\n";
+ }
+ return result;
+}
- http->postdata = NULL; /* nothing to post at this point */
- Curl_pgrsSetUploadSize(data, -1); /* upload size is unknown atm */
+CURLcode Curl_http_bodysend(struct Curl_easy *data, struct connectdata *conn,
+ struct dynbuf *r, Curl_HttpReq httpreq)
+{
+#ifndef USE_HYPER
+ /* Hyper always handles the body separately */
+ curl_off_t included_body = 0;
+#endif
+ CURLcode result = CURLE_OK;
+ struct HTTP *http = data->req.p.http;
+ const char *ptr;
/* If 'authdone' is FALSE, we must not set the write socket index to the
Curl_transfer() call below, as we're not ready to actually upload any
@@ -2665,42 +2336,42 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
case HTTPREQ_PUT: /* Let's PUT the data to the server! */
if(conn->bits.authneg)
- postsize = 0;
+ http->postsize = 0;
else
- postsize = data->state.infilesize;
+ http->postsize = data->state.infilesize;
- if((postsize != -1) && !data->req.upload_chunky &&
- (conn->bits.authneg || !Curl_checkheaders(conn, "Content-Length"))) {
+ if((http->postsize != -1) && !data->req.upload_chunky &&
+ (conn->bits.authneg || !Curl_checkheaders(data, "Content-Length"))) {
/* only add Content-Length if not uploading chunked */
- result = Curl_dyn_addf(&req, "Content-Length: %" CURL_FORMAT_CURL_OFF_T
- "\r\n", postsize);
+ result = Curl_dyn_addf(r, "Content-Length: %" CURL_FORMAT_CURL_OFF_T
+ "\r\n", http->postsize);
if(result)
return result;
}
- if(postsize != 0) {
- result = expect100(data, conn, &req);
+ if(http->postsize) {
+ result = expect100(data, conn, r);
if(result)
return result;
}
/* end of headers */
- result = Curl_dyn_add(&req, "\r\n");
+ result = Curl_dyn_add(r, "\r\n");
if(result)
return result;
/* set the upload size to the progress meter */
- Curl_pgrsSetUploadSize(data, postsize);
+ Curl_pgrsSetUploadSize(data, http->postsize);
/* this sends the buffer and frees all the buffer resources */
- result = Curl_buffer_send(&req, conn, &data->info.request_size, 0,
+ result = Curl_buffer_send(r, data, &data->info.request_size, 0,
FIRSTSOCKET);
if(result)
failf(data, "Failed sending PUT request");
else
/* prepare for transfer */
Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE,
- postsize?FIRSTSOCKET:-1);
+ http->postsize?FIRSTSOCKET:-1);
if(result)
return result;
break;
@@ -2710,11 +2381,11 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
/* This is form posting using mime data. */
if(conn->bits.authneg) {
/* nothing to post! */
- result = Curl_dyn_add(&req, "Content-Length: 0\r\n\r\n");
+ result = Curl_dyn_add(r, "Content-Length: 0\r\n\r\n");
if(result)
return result;
- result = Curl_buffer_send(&req, conn, &data->info.request_size, 0,
+ result = Curl_buffer_send(r, data, &data->info.request_size, 0,
FIRSTSOCKET);
if(result)
failf(data, "Failed sending POST request");
@@ -2724,18 +2395,18 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
break;
}
- data->state.infilesize = postsize = http->postsize;
+ data->state.infilesize = http->postsize;
/* We only set Content-Length and allow a custom Content-Length if
we don't upload data chunked, as RFC2616 forbids us to set both
kinds of headers (Transfer-Encoding: chunked and Content-Length) */
- if(postsize != -1 && !data->req.upload_chunky &&
- (conn->bits.authneg || !Curl_checkheaders(conn, "Content-Length"))) {
+ if(http->postsize != -1 && !data->req.upload_chunky &&
+ (conn->bits.authneg || !Curl_checkheaders(data, "Content-Length"))) {
/* we allow replacing this header if not during auth negotiation,
although it isn't very wise to actually set your own */
- result = Curl_dyn_addf(&req,
+ result = Curl_dyn_addf(r,
"Content-Length: %" CURL_FORMAT_CURL_OFF_T
- "\r\n", postsize);
+ "\r\n", http->postsize);
if(result)
return result;
}
@@ -2746,7 +2417,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
struct curl_slist *hdr;
for(hdr = http->sendit->curlheaders; hdr; hdr = hdr->next) {
- result = Curl_dyn_addf(&req, "%s\r\n", hdr->data);
+ result = Curl_dyn_addf(r, "%s\r\n", hdr->data);
if(result)
return result;
}
@@ -2757,13 +2428,13 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
the somewhat bigger ones we allow the app to disable it. Just make
sure that the expect100header is always set to the preferred value
here. */
- ptr = Curl_checkheaders(conn, "Expect");
+ ptr = Curl_checkheaders(data, "Expect");
if(ptr) {
data->state.expect100header =
Curl_compareheader(ptr, "Expect:", "100-continue");
}
- else if(postsize > EXPECT_100_THRESHOLD || postsize < 0) {
- result = expect100(data, conn, &req);
+ else if(http->postsize > EXPECT_100_THRESHOLD || http->postsize < 0) {
+ result = expect100(data, conn, r);
if(result)
return result;
}
@@ -2771,12 +2442,12 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
data->state.expect100header = FALSE;
/* make the request end in a true CRLF */
- result = Curl_dyn_add(&req, "\r\n");
+ result = Curl_dyn_add(r, "\r\n");
if(result)
return result;
/* set the upload size to the progress meter */
- Curl_pgrsSetUploadSize(data, postsize);
+ Curl_pgrsSetUploadSize(data, http->postsize);
/* Read from mime structure. */
data->state.fread_func = (curl_read_callback) Curl_mime_read;
@@ -2784,14 +2455,14 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
http->sending = HTTPSEND_BODY;
/* this sends the buffer and frees all the buffer resources */
- result = Curl_buffer_send(&req, conn, &data->info.request_size, 0,
+ result = Curl_buffer_send(r, data, &data->info.request_size, 0,
FIRSTSOCKET);
if(result)
failf(data, "Failed sending POST request");
else
/* prepare for transfer */
Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE,
- postsize?FIRSTSOCKET:-1);
+ http->postsize?FIRSTSOCKET:-1);
if(result)
return result;
@@ -2801,26 +2472,26 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
/* this is the simple POST, using x-www-form-urlencoded style */
if(conn->bits.authneg)
- postsize = 0;
+ http->postsize = 0;
else
/* the size of the post body */
- postsize = data->state.infilesize;
+ http->postsize = data->state.infilesize;
/* We only set Content-Length and allow a custom Content-Length if
we don't upload data chunked, as RFC2616 forbids us to set both
kinds of headers (Transfer-Encoding: chunked and Content-Length) */
- if((postsize != -1) && !data->req.upload_chunky &&
- (conn->bits.authneg || !Curl_checkheaders(conn, "Content-Length"))) {
+ if((http->postsize != -1) && !data->req.upload_chunky &&
+ (conn->bits.authneg || !Curl_checkheaders(data, "Content-Length"))) {
/* we allow replacing this header if not during auth negotiation,
although it isn't very wise to actually set your own */
- result = Curl_dyn_addf(&req, "Content-Length: %" CURL_FORMAT_CURL_OFF_T
- "\r\n", postsize);
+ result = Curl_dyn_addf(r, "Content-Length: %" CURL_FORMAT_CURL_OFF_T
+ "\r\n", http->postsize);
if(result)
return result;
}
- if(!Curl_checkheaders(conn, "Content-Type")) {
- result = Curl_dyn_add(&req, "Content-Type: application/"
+ if(!Curl_checkheaders(data, "Content-Type")) {
+ result = Curl_dyn_add(r, "Content-Type: application/"
"x-www-form-urlencoded\r\n");
if(result)
return result;
@@ -2830,26 +2501,28 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
the somewhat bigger ones we allow the app to disable it. Just make
sure that the expect100header is always set to the preferred value
here. */
- ptr = Curl_checkheaders(conn, "Expect");
+ ptr = Curl_checkheaders(data, "Expect");
if(ptr) {
data->state.expect100header =
Curl_compareheader(ptr, "Expect:", "100-continue");
}
- else if(postsize > EXPECT_100_THRESHOLD || postsize < 0) {
- result = expect100(data, conn, &req);
+ else if(http->postsize > EXPECT_100_THRESHOLD || http->postsize < 0) {
+ result = expect100(data, conn, r);
if(result)
return result;
}
else
data->state.expect100header = FALSE;
+#ifndef USE_HYPER
+ /* With Hyper the body is always passed on separately */
if(data->set.postfields) {
/* In HTTP2, we send request body in DATA frame regardless of
its size. */
if(conn->httpversion != 20 &&
!data->state.expect100header &&
- (postsize < MAX_INITIAL_POST_SIZE)) {
+ (http->postsize < MAX_INITIAL_POST_SIZE)) {
/* if we don't use expect: 100 AND
postsize is less than MAX_INITIAL_POST_SIZE
@@ -2858,68 +2531,73 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
get the data duplicated with malloc() and family. */
/* end of headers! */
- result = Curl_dyn_add(&req, "\r\n");
+ result = Curl_dyn_add(r, "\r\n");
if(result)
return result;
if(!data->req.upload_chunky) {
/* We're not sending it 'chunked', append it to the request
already now to reduce the number if send() calls */
- result = Curl_dyn_addn(&req, data->set.postfields,
- (size_t)postsize);
- included_body = postsize;
+ result = Curl_dyn_addn(r, data->set.postfields,
+ (size_t)http->postsize);
+ included_body = http->postsize;
}
else {
- if(postsize) {
+ if(http->postsize) {
+ char chunk[16];
/* Append the POST data chunky-style */
- result = Curl_dyn_addf(&req, "%x\r\n", (int)postsize);
+ msnprintf(chunk, sizeof(chunk), "%x\r\n", (int)http->postsize);
+ result = Curl_dyn_add(r, chunk);
if(!result) {
- result = Curl_dyn_addn(&req, data->set.postfields,
- (size_t)postsize);
+ included_body = http->postsize + strlen(chunk);
+ result = Curl_dyn_addn(r, data->set.postfields,
+ (size_t)http->postsize);
if(!result)
- result = Curl_dyn_add(&req, "\r\n");
- included_body = postsize + 2;
+ result = Curl_dyn_add(r, "\r\n");
+ included_body += 2;
}
}
- if(!result)
- result = Curl_dyn_add(&req, "\x30\x0d\x0a\x0d\x0a");
- /* 0 CR LF CR LF */
- included_body += 5;
+ if(!result) {
+ result = Curl_dyn_add(r, "\x30\x0d\x0a\x0d\x0a");
+ /* 0 CR LF CR LF */
+ included_body += 5;
+ }
}
if(result)
return result;
/* Make sure the progress information is accurate */
- Curl_pgrsSetUploadSize(data, postsize);
+ Curl_pgrsSetUploadSize(data, http->postsize);
}
else {
/* A huge POST coming up, do data separate from the request */
- http->postsize = postsize;
http->postdata = data->set.postfields;
http->sending = HTTPSEND_BODY;
data->state.fread_func = (curl_read_callback)readmoredata;
- data->state.in = (void *)conn;
+ data->state.in = (void *)data;
/* set the upload size to the progress meter */
Curl_pgrsSetUploadSize(data, http->postsize);
/* end of headers! */
- result = Curl_dyn_add(&req, "\r\n");
+ result = Curl_dyn_add(r, "\r\n");
if(result)
return result;
}
}
- else {
+ else
+#endif
+ {
/* end of headers! */
- result = Curl_dyn_add(&req, "\r\n");
+ result = Curl_dyn_add(r, "\r\n");
if(result)
return result;
if(data->req.upload_chunky && conn->bits.authneg) {
/* Chunky upload is selected and we're negotiating auth still, send
end-of-data only */
- result = Curl_dyn_add(&req, (char *)"\x30\x0d\x0a\x0d\x0a");
+ result = Curl_dyn_add(r, (char *)"\x30\x0d\x0a\x0d\x0a");
/* 0 CR LF CR LF */
if(result)
return result;
@@ -2927,19 +2605,16 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
else if(data->state.infilesize) {
/* set the upload size to the progress meter */
- Curl_pgrsSetUploadSize(data, postsize?postsize:-1);
+ Curl_pgrsSetUploadSize(data, http->postsize?http->postsize:-1);
/* set the pointer to mark that we will send the post body using the
- read callback, but only if we're not in authenticate
- negotiation */
- if(!conn->bits.authneg) {
+ read callback, but only if we're not in authenticate negotiation */
+ if(!conn->bits.authneg)
http->postdata = (char *)&http->postdata;
- http->postsize = postsize;
- }
}
}
/* issue the request */
- result = Curl_buffer_send(&req, conn, &data->info.request_size,
+ result = Curl_buffer_send(r, data, &data->info.request_size,
(size_t)included_body, FIRSTSOCKET);
if(result)
@@ -2950,12 +2625,12 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
break;
default:
- result = Curl_dyn_add(&req, "\r\n");
+ result = Curl_dyn_add(r, "\r\n");
if(result)
return result;
/* issue the request */
- result = Curl_buffer_send(&req, conn, &data->info.request_size, 0,
+ result = Curl_buffer_send(r, data, &data->info.request_size, 0,
FIRSTSOCKET);
if(result)
@@ -2964,24 +2639,567 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
/* HTTP GET/HEAD download: */
Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE, -1);
}
+
+ return result;
+}
+
+#if !defined(CURL_DISABLE_COOKIES)
+CURLcode Curl_http_cookies(struct Curl_easy *data,
+ struct connectdata *conn,
+ struct dynbuf *r)
+{
+ CURLcode result = CURLE_OK;
+ char *addcookies = NULL;
+ if(data->set.str[STRING_COOKIE] && !Curl_checkheaders(data, "Cookie"))
+ addcookies = data->set.str[STRING_COOKIE];
+
+ if(data->cookies || addcookies) {
+ struct Cookie *co = NULL; /* no cookies from start */
+ int count = 0;
+
+ if(data->cookies && data->state.cookie_engine) {
+ Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
+ co = Curl_cookie_getlist(data->cookies,
+ data->state.aptr.cookiehost?
+ data->state.aptr.cookiehost:
+ conn->host.name,
+ data->state.up.path,
+ (conn->handler->protocol&CURLPROTO_HTTPS)?
+ TRUE:FALSE);
+ Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
+ }
+ if(co) {
+ struct Cookie *store = co;
+ /* now loop through all cookies that matched */
+ while(co) {
+ if(co->value) {
+ if(0 == count) {
+ result = Curl_dyn_add(r, "Cookie: ");
+ if(result)
+ break;
+ }
+ result = Curl_dyn_addf(r, "%s%s=%s", count?"; ":"",
+ co->name, co->value);
+ if(result)
+ break;
+ count++;
+ }
+ co = co->next; /* next cookie please */
+ }
+ Curl_cookie_freelist(store);
+ }
+ if(addcookies && !result) {
+ if(!count)
+ result = Curl_dyn_add(r, "Cookie: ");
+ if(!result) {
+ result = Curl_dyn_addf(r, "%s%s", count?"; ":"", addcookies);
+ count++;
+ }
+ }
+ if(count && !result)
+ result = Curl_dyn_add(r, "\r\n");
+
+ if(result)
+ return result;
+ }
+ return result;
+}
+#endif
+
+CURLcode Curl_http_range(struct Curl_easy *data,
+ Curl_HttpReq httpreq)
+{
+ if(data->state.use_range) {
+ /*
+ * A range is selected. We use different headers whether we're downloading
+ * or uploading and we always let customized headers override our internal
+ * ones if any such are specified.
+ */
+ if(((httpreq == HTTPREQ_GET) || (httpreq == HTTPREQ_HEAD)) &&
+ !Curl_checkheaders(data, "Range")) {
+ /* if a line like this was already allocated, free the previous one */
+ free(data->state.aptr.rangeline);
+ data->state.aptr.rangeline = aprintf("Range: bytes=%s\r\n",
+ data->state.range);
+ }
+ else if((httpreq == HTTPREQ_POST || httpreq == HTTPREQ_PUT) &&
+ !Curl_checkheaders(data, "Content-Range")) {
+
+ /* if a line like this was already allocated, free the previous one */
+ free(data->state.aptr.rangeline);
+
+ if(data->set.set_resume_from < 0) {
+ /* Upload resume was asked for, but we don't know the size of the
+ remote part so we tell the server (and act accordingly) that we
+ upload the whole file (again) */
+ data->state.aptr.rangeline =
+ aprintf("Content-Range: bytes 0-%" CURL_FORMAT_CURL_OFF_T
+ "/%" CURL_FORMAT_CURL_OFF_T "\r\n",
+ data->state.infilesize - 1, data->state.infilesize);
+
+ }
+ else if(data->state.resume_from) {
+ /* This is because "resume" was selected */
+ curl_off_t total_expected_size =
+ data->state.resume_from + data->state.infilesize;
+ data->state.aptr.rangeline =
+ aprintf("Content-Range: bytes %s%" CURL_FORMAT_CURL_OFF_T
+ "/%" CURL_FORMAT_CURL_OFF_T "\r\n",
+ data->state.range, total_expected_size-1,
+ total_expected_size);
+ }
+ else {
+ /* Range was selected and then we just pass the incoming range and
+ append total size */
+ data->state.aptr.rangeline =
+ aprintf("Content-Range: bytes %s/%" CURL_FORMAT_CURL_OFF_T "\r\n",
+ data->state.range, data->state.infilesize);
+ }
+ if(!data->state.aptr.rangeline)
+ return CURLE_OUT_OF_MEMORY;
+ }
+ }
+ return CURLE_OK;
+}
+
+CURLcode Curl_http_resume(struct Curl_easy *data,
+ struct connectdata *conn,
+ Curl_HttpReq httpreq)
+{
+ if((HTTPREQ_POST == httpreq || HTTPREQ_PUT == httpreq) &&
+ data->state.resume_from) {
+ /**********************************************************************
+ * Resuming upload in HTTP means that we PUT or POST and that we have
+ * got a resume_from value set. The resume value has already created
+ * a Range: header that will be passed along. We need to "fast forward"
+ * the file the given number of bytes and decrease the assume upload
+ * file size before we continue this venture in the dark lands of HTTP.
+ * Resuming mime/form posting at an offset > 0 has no sense and is ignored.
+ *********************************************************************/
+
+ if(data->state.resume_from < 0) {
+ /*
+ * This is meant to get the size of the present remote-file by itself.
+ * We don't support this now. Bail out!
+ */
+ data->state.resume_from = 0;
+ }
+
+ if(data->state.resume_from && !data->state.this_is_a_follow) {
+ /* do we still game? */
+
+ /* Now, let's read off the proper amount of bytes from the
+ input. */
+ int seekerr = CURL_SEEKFUNC_CANTSEEK;
+ if(conn->seek_func) {
+ Curl_set_in_callback(data, true);
+ seekerr = conn->seek_func(conn->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_READ_ERROR;
+ }
+ /* when seekerr == CURL_SEEKFUNC_CANTSEEK (can't seek to offset) */
+ do {
+ size_t readthisamountnow =
+ (data->state.resume_from - passed > data->set.buffer_size) ?
+ (size_t)data->set.buffer_size :
+ curlx_sotouz(data->state.resume_from - passed);
+
+ size_t actuallyread =
+ data->state.fread_func(data->state.buffer, 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, "Could only read %" CURL_FORMAT_CURL_OFF_T
+ " bytes from the input", passed);
+ return CURLE_READ_ERROR;
+ }
+ } while(passed < data->state.resume_from);
+ }
+
+ /* now, decrease the size of the read */
+ if(data->state.infilesize>0) {
+ data->state.infilesize -= data->state.resume_from;
+
+ if(data->state.infilesize <= 0) {
+ failf(data, "File already completely uploaded");
+ return CURLE_PARTIAL_FILE;
+ }
+ }
+ /* we've passed, proceed as normal */
+ }
+ }
+ return CURLE_OK;
+}
+
+CURLcode Curl_http_firstwrite(struct Curl_easy *data,
+ struct connectdata *conn,
+ bool *done)
+{
+ struct SingleRequest *k = &data->req;
+ DEBUGASSERT(conn->handler->protocol&(PROTO_FAMILY_HTTP|CURLPROTO_RTSP));
+ if(data->req.newurl) {
+ if(conn->bits.close) {
+ /* Abort after the headers if "follow Location" is set
+ and we're set to close anyway. */
+ k->keepon &= ~KEEP_RECV;
+ *done = TRUE;
+ return CURLE_OK;
+ }
+ /* We have a new url to load, but since we want to be able to re-use this
+ connection properly, we read the full response in "ignore more" */
+ k->ignorebody = TRUE;
+ infof(data, "Ignoring the response-body\n");
+ }
+ if(data->state.resume_from && !k->content_range &&
+ (data->state.httpreq == HTTPREQ_GET) &&
+ !k->ignorebody) {
+
+ if(k->size == data->state.resume_from) {
+ /* The resume point is at the end of file, consider this fine even if it
+ doesn't allow resume from here. */
+ infof(data, "The entire document is already downloaded");
+ connclose(conn, "already downloaded");
+ /* Abort download */
+ k->keepon &= ~KEEP_RECV;
+ *done = TRUE;
+ return CURLE_OK;
+ }
+
+ /* we wanted to resume a download, although the server doesn't seem to
+ * support this and we did this with a GET (if it wasn't a GET we did a
+ * POST or PUT resume) */
+ failf(data, "HTTP server doesn't seem to support "
+ "byte ranges. Cannot resume.");
+ return CURLE_RANGE_ERROR;
+ }
+
+ if(data->set.timecondition && !data->state.range) {
+ /* A time condition has been set AND no ranges have been requested. This
+ seems to be what chapter 13.3.4 of RFC 2616 defines to be the correct
+ action for a HTTP/1.1 client */
+
+ if(!Curl_meets_timecondition(data, k->timeofdoc)) {
+ *done = TRUE;
+ /* We're simulating a http 304 from server so we return
+ what should have been returned from the server */
+ data->info.httpcode = 304;
+ infof(data, "Simulate a HTTP 304 response!\n");
+ /* we abort the transfer before it is completed == we ruin the
+ re-use ability. Close the connection */
+ connclose(conn, "Simulated 304 handling");
+ return CURLE_OK;
+ }
+ } /* we have a time condition */
+
+ return CURLE_OK;
+}
+
+#ifndef USE_HYPER
+/*
+ * Curl_http() gets called from the generic multi_do() function when a HTTP
+ * request is to be performed. This creates and sends a properly constructed
+ * HTTP request.
+ */
+CURLcode Curl_http(struct Curl_easy *data, bool *done)
+{
+ struct connectdata *conn = data->conn;
+ CURLcode result = CURLE_OK;
+ struct HTTP *http;
+ Curl_HttpReq httpreq;
+ const char *te = ""; /* transfer-encoding */
+ const char *request;
+ const char *httpstring;
+ struct dynbuf req;
+ char *altused = NULL;
+ const char *p_accept; /* Accept: string */
+
+ /* Always consider the DO phase done after this function call, even if there
+ may be parts of the request that are not yet sent, since we can deal with
+ the rest of the request in the PERFORM phase. */
+ *done = TRUE;
+
+ if(conn->transport != TRNSPRT_QUIC) {
+ if(conn->httpversion < 20) { /* unless the connection is re-used and
+ already http2 */
+ switch(conn->negnpn) {
+ case CURL_HTTP_VERSION_2:
+ conn->httpversion = 20; /* we know we're on HTTP/2 now */
+
+ result = Curl_http2_switched(data, NULL, 0);
+ if(result)
+ return result;
+ break;
+ case CURL_HTTP_VERSION_1_1:
+ /* continue with HTTP/1.1 when explicitly requested */
+ break;
+ default:
+ /* Check if user wants to use HTTP/2 with clear TCP*/
+#ifdef USE_NGHTTP2
+ if(data->set.httpversion == CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE) {
+#ifndef CURL_DISABLE_PROXY
+ if(conn->bits.httpproxy && !conn->bits.tunnel_proxy) {
+ /* We don't support HTTP/2 proxies yet. Also it's debatable
+ whether or not this setting should apply to HTTP/2 proxies. */
+ infof(data, "Ignoring HTTP/2 prior knowledge due to proxy\n");
+ break;
+ }
+#endif
+ DEBUGF(infof(data, "HTTP/2 over clean TCP\n"));
+ conn->httpversion = 20;
+
+ result = Curl_http2_switched(data, NULL, 0);
+ if(result)
+ return result;
+ }
+#endif
+ break;
+ }
+ }
+ else {
+ /* prepare for a http2 request */
+ result = Curl_http2_setup(data, conn);
+ if(result)
+ return result;
+ }
+ }
+ http = data->req.p.http;
+ DEBUGASSERT(http);
+
+ result = Curl_http_host(data, conn);
+ if(result)
+ return result;
+
+ result = Curl_http_useragent(data);
+ if(result)
+ return result;
+
+ Curl_http_method(data, conn, &request, &httpreq);
+
+ /* setup the authentication headers */
+ {
+ char *pq = NULL;
+ if(data->state.up.query) {
+ pq = aprintf("%s?%s", data->state.up.path, data->state.up.query);
+ if(!pq)
+ return CURLE_OUT_OF_MEMORY;
+ }
+ result = Curl_http_output_auth(data, conn, request, httpreq,
+ (pq ? pq : data->state.up.path), FALSE);
+ free(pq);
+ if(result)
+ return result;
+ }
+
+ Curl_safefree(data->state.aptr.ref);
+ if(data->change.referer && !Curl_checkheaders(data, "Referer")) {
+ data->state.aptr.ref = aprintf("Referer: %s\r\n", data->change.referer);
+ if(!data->state.aptr.ref)
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ if(!Curl_checkheaders(data, "Accept-Encoding") &&
+ data->set.str[STRING_ENCODING]) {
+ Curl_safefree(data->state.aptr.accept_encoding);
+ data->state.aptr.accept_encoding =
+ aprintf("Accept-Encoding: %s\r\n", data->set.str[STRING_ENCODING]);
+ if(!data->state.aptr.accept_encoding)
+ return CURLE_OUT_OF_MEMORY;
+ }
+ else {
+ Curl_safefree(data->state.aptr.accept_encoding);
+ data->state.aptr.accept_encoding = NULL;
+ }
+
+#ifdef HAVE_LIBZ
+ /* we only consider transfer-encoding magic if libz support is built-in */
+
+ if(!Curl_checkheaders(data, "TE") &&
+ data->set.http_transfer_encoding) {
+ /* When we are to insert a TE: header in the request, we must also insert
+ TE in a Connection: header, so we need to merge the custom provided
+ Connection: header and prevent the original to get sent. Note that if
+ the user has inserted his/her own TE: header we don't do this magic
+ but then assume that the user will handle it all! */
+ char *cptr = Curl_checkheaders(data, "Connection");
+#define TE_HEADER "TE: gzip\r\n"
+
+ Curl_safefree(data->state.aptr.te);
+
+ if(cptr) {
+ cptr = Curl_copy_header_value(cptr);
+ if(!cptr)
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ /* Create the (updated) Connection: header */
+ data->state.aptr.te = aprintf("Connection: %s%sTE\r\n" TE_HEADER,
+ cptr ? cptr : "", (cptr && *cptr) ? ", ":"");
+
+ free(cptr);
+ if(!data->state.aptr.te)
+ return CURLE_OUT_OF_MEMORY;
+ }
+#endif
+
+ result = Curl_http_body(data, conn, httpreq, &te);
+ if(result)
+ return result;
+
+ p_accept = Curl_checkheaders(data, "Accept")?NULL:"Accept: */*\r\n";
+
+ result = Curl_http_resume(data, conn, httpreq);
if(result)
return result;
- if(!postsize && (http->sending != HTTPSEND_REQUEST))
+
+ result = Curl_http_range(data, httpreq);
+ if(result)
+ return result;
+
+ httpstring = get_http_string(data, conn);
+
+ /* initialize a dynamic send-buffer */
+ Curl_dyn_init(&req, DYN_HTTP_REQUEST);
+
+ /* add the main request stuff */
+ /* GET/HEAD/POST/PUT */
+ result = Curl_dyn_addf(&req, "%s ", request);
+ if(!result)
+ result = Curl_http_target(data, conn, &req);
+ if(result) {
+ Curl_dyn_free(&req);
+ return result;
+ }
+
+#ifndef CURL_DISABLE_ALTSVC
+ if(conn->bits.altused && !Curl_checkheaders(data, "Alt-Used")) {
+ altused = aprintf("Alt-Used: %s:%d\r\n",
+ conn->conn_to_host.name, conn->conn_to_port);
+ if(!altused) {
+ Curl_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:""),
+ data->state.aptr.proxyuserpwd?
+ data->state.aptr.proxyuserpwd:"",
+ 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->change.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, "Proxy-Connection") &&
+ !Curl_checkProxyheaders(data, conn, "Proxy-Connection"))?
+ "Proxy-Connection: Keep-Alive\r\n":"",
+#else
+ "",
+#endif
+ te,
+ altused ? altused : ""
+ );
+
+ /* clear userpwd and proxyuserpwd to avoid re-using old credentials
+ * from re-used connections */
+ Curl_safefree(data->state.aptr.userpwd);
+ Curl_safefree(data->state.aptr.proxyuserpwd);
+ free(altused);
+
+ if(result) {
+ Curl_dyn_free(&req);
+ return result;
+ }
+
+ if(!(conn->handler->flags&PROTOPT_SSL) &&
+ conn->httpversion != 20 &&
+ (data->set.httpversion == CURL_HTTP_VERSION_2)) {
+ /* append HTTP2 upgrade magic stuff to the HTTP request if it isn't done
+ over SSL */
+ result = Curl_http2_request_upgrade(&req, conn);
+ if(result) {
+ Curl_dyn_free(&req);
+ return result;
+ }
+ }
+
+ result = Curl_http_cookies(data, conn, &req);
+ if(!result)
+ result = Curl_add_timecondition(data, &req);
+ if(!result)
+ result = Curl_add_custom_headers(data, FALSE, &req);
+
+ if(!result) {
+ http->postdata = NULL; /* nothing to post at this point */
+ if((httpreq == HTTPREQ_GET) ||
+ (httpreq == HTTPREQ_HEAD))
+ Curl_pgrsSetUploadSize(data, 0); /* nothing */
+
+ /* bodysend takes ownership of the 'req' memory on success */
+ result = Curl_http_bodysend(data, conn, &req, httpreq);
+ }
+ if(result) {
+ Curl_dyn_free(&req);
+ return result;
+ }
+
+ if((http->postsize > -1) &&
+ (http->postsize <= data->req.writebytecount) &&
+ (http->sending != HTTPSEND_REQUEST))
data->req.upload_done = TRUE;
if(data->req.writebytecount) {
/* if a request-body has been sent off, we make sure this progress is noted
properly */
Curl_pgrsSetUploadCounter(data, data->req.writebytecount);
- if(Curl_pgrsUpdate(conn))
+ if(Curl_pgrsUpdate(data))
result = CURLE_ABORTED_BY_CALLBACK;
- if(data->req.writebytecount >= postsize) {
+ if(!http->postsize) {
/* already sent the entire request body, mark the "upload" as
complete */
infof(data, "upload completely sent off: %" CURL_FORMAT_CURL_OFF_T
" out of %" CURL_FORMAT_CURL_OFF_T " bytes\n",
- data->req.writebytecount, postsize);
+ data->req.writebytecount, http->postsize);
data->req.upload_done = TRUE;
data->req.keepon &= ~KEEP_SEND; /* we're done writing */
data->req.exp100 = EXP100_SEND_DATA; /* already sent */
@@ -2997,6 +3215,8 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
return result;
}
+#endif /* USE_HYPER */
+
typedef enum {
STATUS_UNKNOWN, /* not enough data to tell yet */
STATUS_DONE, /* a status line was read */
@@ -3101,41 +3321,383 @@ checkprotoprefix(struct Curl_easy *data, struct connectdata *conn,
return checkhttpprefix(data, s, len);
}
-static void print_http_error(struct Curl_easy *data)
+/*
+ * Curl_http_header() parses a single response header.
+ */
+CURLcode Curl_http_header(struct Curl_easy *data, struct connectdata *conn,
+ char *headp)
{
+ CURLcode result;
struct SingleRequest *k = &data->req;
- char *beg = Curl_dyn_ptr(&data->state.headerb);
-
- /* make sure that data->req.p points to the HTTP status line */
- if(!strncmp(beg, "HTTP", 4)) {
-
- /* skip to HTTP status code */
- beg = strchr(beg, ' ');
- if(beg && *++beg) {
-
- /* find trailing CR */
- char end_char = '\r';
- char *end = strchr(beg, end_char);
- if(!end) {
- /* try to find LF (workaround for non-compliant HTTP servers) */
- end_char = '\n';
- end = strchr(beg, end_char);
+ /* Check for Content-Length: header lines to get size */
+ if(!k->http_bodyless &&
+ !data->set.ignorecl && checkprefix("Content-Length:", headp)) {
+ curl_off_t contentlength;
+ CURLofft offt = curlx_strtoofft(headp + 15, NULL, 10, &contentlength);
+
+ if(offt == CURL_OFFT_OK) {
+ if(data->set.max_filesize &&
+ contentlength > data->set.max_filesize) {
+ failf(data, "Maximum file size exceeded");
+ return CURLE_FILESIZE_EXCEEDED;
}
+ k->size = contentlength;
+ k->maxdownload = k->size;
+ /* we set the progress download size already at this point
+ just to make it easier for apps/callbacks to extract this
+ info as soon as possible */
+ Curl_pgrsSetDownloadSize(data, k->size);
+ }
+ else if(offt == CURL_OFFT_FLOW) {
+ /* out of range */
+ if(data->set.max_filesize) {
+ failf(data, "Maximum file size exceeded");
+ return CURLE_FILESIZE_EXCEEDED;
+ }
+ streamclose(conn, "overflow content-length");
+ infof(data, "Overflow Content-Length: value!\n");
+ }
+ else {
+ /* negative or just rubbish - bad HTTP */
+ failf(data, "Invalid Content-Length: value");
+ return CURLE_WEIRD_SERVER_REPLY;
+ }
+ }
+ /* check for Content-Type: header lines to get the MIME-type */
+ else if(checkprefix("Content-Type:", headp)) {
+ char *contenttype = Curl_copy_header_value(headp);
+ if(!contenttype)
+ return CURLE_OUT_OF_MEMORY;
+ if(!*contenttype)
+ /* ignore empty data */
+ free(contenttype);
+ else {
+ Curl_safefree(data->info.contenttype);
+ data->info.contenttype = contenttype;
+ }
+ }
+#ifndef CURL_DISABLE_PROXY
+ else if((conn->httpversion == 10) &&
+ conn->bits.httpproxy &&
+ Curl_compareheader(headp, "Proxy-Connection:", "keep-alive")) {
+ /*
+ * When a HTTP/1.0 reply comes when using a proxy, the
+ * 'Proxy-Connection: keep-alive' line tells us the
+ * connection will be kept alive for our pleasure.
+ * Default action for 1.0 is to close.
+ */
+ connkeep(conn, "Proxy-Connection keep-alive"); /* don't close */
+ infof(data, "HTTP/1.0 proxy connection set to keep alive!\n");
+ }
+ else if((conn->httpversion == 11) &&
+ conn->bits.httpproxy &&
+ Curl_compareheader(headp, "Proxy-Connection:", "close")) {
+ /*
+ * We get a HTTP/1.1 response from a proxy and it says it'll
+ * close down after this transfer.
+ */
+ connclose(conn, "Proxy-Connection: asked to close after done");
+ infof(data, "HTTP/1.1 proxy connection set close!\n");
+ }
+#endif
+ else if((conn->httpversion == 10) &&
+ Curl_compareheader(headp, "Connection:", "keep-alive")) {
+ /*
+ * A HTTP/1.0 reply with the 'Connection: keep-alive' line
+ * tells us the connection will be kept alive for our
+ * pleasure. Default action for 1.0 is to close.
+ *
+ * [RFC2068, section 19.7.1] */
+ connkeep(conn, "Connection keep-alive");
+ infof(data, "HTTP/1.0 connection set to keep alive!\n");
+ }
+ else if(Curl_compareheader(headp, "Connection:", "close")) {
+ /*
+ * [RFC 2616, section 8.1.2.1]
+ * "Connection: close" is HTTP/1.1 language and means that
+ * the connection will close when this request has been
+ * served.
+ */
+ streamclose(conn, "Connection: close used");
+ }
+ else if(!k->http_bodyless && checkprefix("Transfer-Encoding:", headp)) {
+ /* One or more encodings. We check for chunked and/or a compression
+ algorithm. */
+ /*
+ * [RFC 2616, section 3.6.1] A 'chunked' transfer encoding
+ * means that the server will send a series of "chunks". Each
+ * chunk starts with line with info (including size of the
+ * coming block) (terminated with CRLF), then a block of data
+ * with the previously mentioned size. There can be any amount
+ * of chunks, and a chunk-data set to zero signals the
+ * end-of-chunks. */
+
+ result = Curl_build_unencoding_stack(data, headp + 18, TRUE);
+ if(result)
+ return result;
+ }
+ else if(!k->http_bodyless && checkprefix("Content-Encoding:", headp) &&
+ data->set.str[STRING_ENCODING]) {
+ /*
+ * Process Content-Encoding. Look for the values: identity,
+ * gzip, deflate, compress, x-gzip and x-compress. x-gzip and
+ * x-compress are the same as gzip and compress. (Sec 3.5 RFC
+ * 2616). zlib cannot handle compress. However, errors are
+ * handled further down when the response body is processed
+ */
+ result = Curl_build_unencoding_stack(data, headp + 17, FALSE);
+ if(result)
+ return result;
+ }
+ else if(checkprefix("Retry-After:", headp)) {
+ /* Retry-After = HTTP-date / delay-seconds */
+ curl_off_t retry_after = 0; /* zero for unknown or "now" */
+ time_t date = Curl_getdate_capped(&headp[12]);
+ if(-1 == date) {
+ /* not a date, try it as a decimal number */
+ (void)curlx_strtoofft(&headp[12], NULL, 10, &retry_after);
+ }
+ else
+ /* convert date to number of seconds into the future */
+ retry_after = date - time(NULL);
+ data->info.retry_after = retry_after; /* store it */
+ }
+ else if(!k->http_bodyless && checkprefix("Content-Range:", headp)) {
+ /* Content-Range: bytes [num]-
+ Content-Range: bytes: [num]-
+ Content-Range: [num]-
+ Content-Range: [asterisk]/[total]
+
+ The second format was added since Sun's webserver
+ JavaWebServer/1.1.1 obviously sends the header this way!
+ The third added since some servers use that!
+ The forth means the requested range was unsatisfied.
+ */
+
+ char *ptr = headp + 14;
- if(end) {
- /* temporarily replace CR or LF by NUL and print the error message */
- *end = '\0';
- failf(data, "The requested URL returned error: %s", beg);
+ /* Move forward until first digit or asterisk */
+ while(*ptr && !ISDIGIT(*ptr) && *ptr != '*')
+ ptr++;
- /* restore the previously replaced CR or LF */
- *end = end_char;
- return;
+ /* if it truly stopped on a digit */
+ if(ISDIGIT(*ptr)) {
+ if(!curlx_strtoofft(ptr, NULL, 10, &k->offset)) {
+ if(data->state.resume_from == k->offset)
+ /* we asked for a resume and we got it */
+ k->content_range = TRUE;
}
}
+ else
+ data->state.resume_from = 0; /* get everything */
+ }
+#if !defined(CURL_DISABLE_COOKIES)
+ else if(data->cookies && data->state.cookie_engine &&
+ checkprefix("Set-Cookie:", headp)) {
+ Curl_share_lock(data, CURL_LOCK_DATA_COOKIE,
+ CURL_LOCK_ACCESS_SINGLE);
+ Curl_cookie_add(data,
+ data->cookies, TRUE, FALSE, headp + 11,
+ /* If there is a custom-set Host: name, use it
+ here, or else use real peer host name. */
+ data->state.aptr.cookiehost?
+ data->state.aptr.cookiehost:conn->host.name,
+ data->state.up.path,
+ (conn->handler->protocol&CURLPROTO_HTTPS)?
+ TRUE:FALSE);
+ Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
+ }
+#endif
+ else if(!k->http_bodyless && checkprefix("Last-Modified:", headp) &&
+ (data->set.timecondition || data->set.get_filetime) ) {
+ k->timeofdoc = Curl_getdate_capped(headp + strlen("Last-Modified:"));
+ if(data->set.get_filetime)
+ data->info.filetime = k->timeofdoc;
+ }
+ else if((checkprefix("WWW-Authenticate:", headp) &&
+ (401 == k->httpcode)) ||
+ (checkprefix("Proxy-authenticate:", headp) &&
+ (407 == k->httpcode))) {
+
+ bool proxy = (k->httpcode == 407) ? TRUE : FALSE;
+ char *auth = Curl_copy_header_value(headp);
+ if(!auth)
+ return CURLE_OUT_OF_MEMORY;
+
+ result = Curl_http_input_auth(data, proxy, auth);
+
+ free(auth);
+
+ if(result)
+ return result;
+ }
+#ifdef USE_SPNEGO
+ else if(checkprefix("Persistent-Auth", headp)) {
+ struct negotiatedata *negdata = &conn->negotiate;
+ struct auth *authp = &data->state.authhost;
+ if(authp->picked == CURLAUTH_NEGOTIATE) {
+ char *persistentauth = Curl_copy_header_value(headp);
+ if(!persistentauth)
+ return CURLE_OUT_OF_MEMORY;
+ negdata->noauthpersist = checkprefix("false", persistentauth)?
+ TRUE:FALSE;
+ negdata->havenoauthpersist = TRUE;
+ infof(data, "Negotiate: noauthpersist -> %d, header part: %s",
+ negdata->noauthpersist, persistentauth);
+ free(persistentauth);
+ }
}
+#endif
+ else if((k->httpcode >= 300 && k->httpcode < 400) &&
+ checkprefix("Location:", headp) &&
+ !data->req.location) {
+ /* this is the URL that the server advises us to use instead */
+ char *location = Curl_copy_header_value(headp);
+ if(!location)
+ return CURLE_OUT_OF_MEMORY;
+ if(!*location)
+ /* ignore empty data */
+ free(location);
+ else {
+ data->req.location = location;
+
+ if(data->set.http_follow_location) {
+ DEBUGASSERT(!data->req.newurl);
+ data->req.newurl = strdup(data->req.location); /* clone */
+ if(!data->req.newurl)
+ return CURLE_OUT_OF_MEMORY;
- /* fall-back to printing the HTTP status code only */
- failf(data, "The requested URL returned error: %d", k->httpcode);
+ /* some cases of POST and PUT etc needs to rewind the data
+ stream at this point */
+ result = http_perhapsrewind(data, conn);
+ if(result)
+ return result;
+ }
+ }
+ }
+
+#ifdef USE_HSTS
+ /* If enabled, the header is incoming and this is over HTTPS */
+ else if(data->hsts && checkprefix("Strict-Transport-Security:", headp) &&
+ (conn->handler->flags & PROTOPT_SSL)) {
+ CURLcode check =
+ Curl_hsts_parse(data->hsts, data->state.up.hostname,
+ &headp[ sizeof("Strict-Transport-Security:") -1 ]);
+ if(check)
+ infof(data, "Illegal STS header skipped\n");
+#ifdef DEBUGBUILD
+ else
+ infof(data, "Parsed STS header fine (%zu entries)\n",
+ data->hsts->list.size);
+#endif
+ }
+#endif
+#ifndef CURL_DISABLE_ALTSVC
+ /* If enabled, the header is incoming and this is over HTTPS */
+ else if(data->asi && checkprefix("Alt-Svc:", headp) &&
+ ((conn->handler->flags & PROTOPT_SSL) ||
+#ifdef CURLDEBUG
+ /* allow debug builds to circumvent the HTTPS restriction */
+ getenv("CURL_ALTSVC_HTTP")
+#else
+ 0
+#endif
+ )) {
+ /* the ALPN of the current request */
+ enum alpnid id = (conn->httpversion == 20) ? ALPN_h2 : ALPN_h1;
+ result = Curl_altsvc_parse(data, data->asi,
+ &headp[ strlen("Alt-Svc:") ],
+ id, conn->host.name,
+ curlx_uitous(conn->remote_port));
+ if(result)
+ return result;
+ }
+#endif
+ else if(conn->handler->protocol & CURLPROTO_RTSP) {
+ result = Curl_rtsp_parseheader(data, headp);
+ if(result)
+ return result;
+ }
+ return CURLE_OK;
+}
+
+/*
+ * Called after the first HTTP response line (the status line) has been
+ * received and parsed.
+ */
+
+CURLcode Curl_http_statusline(struct Curl_easy *data,
+ struct connectdata *conn)
+{
+ struct SingleRequest *k = &data->req;
+ data->info.httpcode = k->httpcode;
+
+ data->info.httpversion = conn->httpversion;
+ if(!data->state.httpversion ||
+ data->state.httpversion > conn->httpversion)
+ /* store the lowest server version we encounter */
+ data->state.httpversion = conn->httpversion;
+
+ /*
+ * This code executes as part of processing the header. As a
+ * result, it's not totally clear how to interpret the
+ * response code yet as that depends on what other headers may
+ * be present. 401 and 407 may be errors, but may be OK
+ * depending on how authentication is working. Other codes
+ * are definitely errors, so give up here.
+ */
+ if(data->state.resume_from && data->state.httpreq == HTTPREQ_GET &&
+ k->httpcode == 416) {
+ /* "Requested Range Not Satisfiable", just proceed and
+ pretend this is no error */
+ k->ignorebody = TRUE; /* Avoid appending error msg to good data. */
+ }
+
+ if(conn->httpversion == 10) {
+ /* Default action for HTTP/1.0 must be to close, unless
+ we get one of those fancy headers that tell us the
+ server keeps it open for us! */
+ infof(data, "HTTP 1.0, assume close after body\n");
+ connclose(conn, "HTTP/1.0 close after body");
+ }
+ else if(conn->httpversion == 20 ||
+ (k->upgr101 == UPGR101_REQUESTED && k->httpcode == 101)) {
+ DEBUGF(infof(data, "HTTP/2 found, allow multiplexing\n"));
+ /* HTTP/2 cannot avoid multiplexing since it is a core functionality
+ of the protocol */
+ conn->bundle->multiuse = BUNDLE_MULTIPLEX;
+ }
+ else if(conn->httpversion >= 11 &&
+ !conn->bits.close) {
+ /* If HTTP version is >= 1.1 and connection is persistent */
+ DEBUGF(infof(data,
+ "HTTP 1.1 or later with persistent connection\n"));
+ }
+
+ k->http_bodyless = k->httpcode >= 100 && k->httpcode < 200;
+ switch(k->httpcode) {
+ case 304:
+ /* (quote from RFC2616, section 10.3.5): The 304 response
+ * MUST NOT contain a message-body, and thus is always
+ * terminated by the first empty line after the header
+ * fields. */
+ if(data->set.timecondition)
+ data->info.timecond = TRUE;
+ /* FALLTHROUGH */
+ case 204:
+ /* (quote from RFC2616, section 10.2.5): The server has
+ * fulfilled the request but does not need to return an
+ * entity-body ... The 204 response MUST NOT include a
+ * message-body, and thus is always terminated by the first
+ * empty line after the header fields. */
+ k->size = 0;
+ k->maxdownload = 0;
+ k->http_bodyless = TRUE;
+ break;
+ default:
+ break;
+ }
+ return CURLE_OK;
}
/*
@@ -3186,7 +3748,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
k->badheader = HEADER_ALLBAD;
streamclose(conn, "bad HTTP: No end-of-message indicator");
if(!data->set.http09_allowed) {
- failf(data, "Received HTTP/0.9 when not allowed\n");
+ failf(data, "Received HTTP/0.9 when not allowed");
return CURLE_UNSUPPORTED_PROTOCOL;
}
break;
@@ -3221,7 +3783,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
streamclose(conn, "bad HTTP: No end-of-message indicator");
/* this is not the beginning of a protocol first header line */
if(!data->set.http09_allowed) {
- failf(data, "Received HTTP/0.9 when not allowed\n");
+ failf(data, "Received HTTP/0.9 when not allowed");
return CURLE_UNSUPPORTED_PROTOCOL;
}
k->header = FALSE;
@@ -3296,7 +3858,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
/* switch to http2 now. The bytes after response headers
are also processed here, otherwise they are lost. */
- result = Curl_http2_switched(conn, k->str, *nread);
+ result = Curl_http2_switched(data, k->str, *nread);
if(result)
return result;
*nread = 0;
@@ -3362,15 +3924,6 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
conn->proxy_negotiate_state = GSS_AUTHSUCC;
}
#endif
- /*
- * When all the headers have been parsed, see if we should give
- * up and return an error.
- */
- if(http_should_fail(conn)) {
- failf(data, "The requested URL returned error: %d",
- k->httpcode);
- return CURLE_HTTP_RETURNED_ERROR;
- }
/* now, only output this if the header AND body are requested:
*/
@@ -3379,7 +3932,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
writetype |= CLIENTWRITE_BODY;
headerlen = Curl_dyn_len(&data->state.headerb);
- result = Curl_client_write(conn, writetype,
+ result = Curl_client_write(data, writetype,
Curl_dyn_ptr(&data->state.headerb),
headerlen);
if(result)
@@ -3388,13 +3941,23 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
data->info.header_size += (long)headerlen;
data->req.headerbytecount += (long)headerlen;
+ /*
+ * When all the headers have been parsed, see if we should give
+ * up and return an error.
+ */
+ if(http_should_fail(data)) {
+ failf(data, "The requested URL returned error: %d",
+ k->httpcode);
+ return CURLE_HTTP_RETURNED_ERROR;
+ }
+
data->req.deductheadercount =
(100 <= k->httpcode && 199 >= k->httpcode)?data->req.headerbytecount:0;
/* Curl_http_auth_act() checks what authentication methods
* that are available and decides which one (if any) to
* use. It will set 'newurl' if an auth method was picked. */
- result = Curl_http_auth_act(conn);
+ result = Curl_http_auth_act(data);
if(result)
return result;
@@ -3432,8 +3995,8 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
infof(data, "Got 417 while waiting for a 100\n");
data->state.disableexpect = TRUE;
DEBUGASSERT(!data->req.newurl);
- data->req.newurl = strdup(conn->data->change.url);
- Curl_done_sending(conn, k);
+ data->req.newurl = strdup(data->change.url);
+ Curl_done_sending(data, k);
}
else if(data->set.http_keep_sending_on_error) {
infof(data, "HTTP error before end of send, keep sending\n");
@@ -3445,7 +4008,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
else {
infof(data, "HTTP error before end of send, stop sending\n");
streamclose(conn, "Stop sending data before everything sent");
- result = Curl_done_sending(conn, k);
+ result = Curl_done_sending(data, k);
if(result)
return result;
k->upload_done = TRUE;
@@ -3531,10 +4094,8 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
k->keepon &= ~KEEP_RECV;
}
- if(data->set.verbose)
- Curl_debug(data, CURLINFO_HEADER_IN,
- str_start, headerlen);
- break; /* exit header line loop */
+ Curl_debug(data, CURLINFO_HEADER_IN, str_start, headerlen);
+ break; /* exit header line loop */
}
/* We continue reading headers, reset the line-based header */
@@ -3655,83 +4216,9 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
}
if(nc) {
- data->info.httpcode = k->httpcode;
-
- data->info.httpversion = conn->httpversion;
- if(!data->state.httpversion ||
- data->state.httpversion > conn->httpversion)
- /* store the lowest server version we encounter */
- data->state.httpversion = conn->httpversion;
-
- /*
- * This code executes as part of processing the header. As a
- * result, it's not totally clear how to interpret the
- * response code yet as that depends on what other headers may
- * be present. 401 and 407 may be errors, but may be OK
- * depending on how authentication is working. Other codes
- * are definitely errors, so give up here.
- */
- if(data->state.resume_from && data->state.httpreq == HTTPREQ_GET &&
- k->httpcode == 416) {
- /* "Requested Range Not Satisfiable", just proceed and
- pretend this is no error */
- k->ignorebody = TRUE; /* Avoid appending error msg to good data. */
- }
- else if(data->set.http_fail_on_error && (k->httpcode >= 400) &&
- ((k->httpcode != 401) || !conn->bits.user_passwd)
-#ifndef CURL_DISABLE_PROXY
- && ((k->httpcode != 407) || !conn->bits.proxy_user_passwd)
-#endif
- ) {
- /* serious error, go home! */
- print_http_error(data);
- return CURLE_HTTP_RETURNED_ERROR;
- }
-
- if(conn->httpversion == 10) {
- /* Default action for HTTP/1.0 must be to close, unless
- we get one of those fancy headers that tell us the
- server keeps it open for us! */
- infof(data, "HTTP 1.0, assume close after body\n");
- connclose(conn, "HTTP/1.0 close after body");
- }
- else if(conn->httpversion == 20 ||
- (k->upgr101 == UPGR101_REQUESTED && k->httpcode == 101)) {
- DEBUGF(infof(data, "HTTP/2 found, allow multiplexing\n"));
- /* HTTP/2 cannot avoid multiplexing since it is a core functionality
- of the protocol */
- conn->bundle->multiuse = BUNDLE_MULTIPLEX;
- }
- else if(conn->httpversion >= 11 &&
- !conn->bits.close) {
- /* If HTTP version is >= 1.1 and connection is persistent */
- DEBUGF(infof(data,
- "HTTP 1.1 or later with persistent connection\n"));
- }
-
- k->http_bodyless = k->httpcode >= 100 && k->httpcode < 200;
- switch(k->httpcode) {
- case 304:
- /* (quote from RFC2616, section 10.3.5): The 304 response
- * MUST NOT contain a message-body, and thus is always
- * terminated by the first empty line after the header
- * fields. */
- if(data->set.timecondition)
- data->info.timecond = TRUE;
- /* FALLTHROUGH */
- case 204:
- /* (quote from RFC2616, section 10.2.5): The server has
- * fulfilled the request but does not need to return an
- * entity-body ... The 204 response MUST NOT include a
- * message-body, and thus is always terminated by the first
- * empty line after the header fields. */
- k->size = 0;
- k->maxdownload = 0;
- k->http_bodyless = TRUE;
- break;
- default:
- break;
- }
+ result = Curl_http_statusline(data, conn);
+ if(result)
+ return result;
}
else {
k->header = FALSE; /* this is not a header line */
@@ -3744,278 +4231,9 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
if(result)
return result;
- /* Check for Content-Length: header lines to get size */
- if(!k->http_bodyless &&
- !data->set.ignorecl && checkprefix("Content-Length:", headp)) {
- curl_off_t contentlength;
- CURLofft offt = curlx_strtoofft(headp + 15, NULL, 10, &contentlength);
-
- if(offt == CURL_OFFT_OK) {
- if(data->set.max_filesize &&
- contentlength > data->set.max_filesize) {
- failf(data, "Maximum file size exceeded");
- return CURLE_FILESIZE_EXCEEDED;
- }
- k->size = contentlength;
- k->maxdownload = k->size;
- /* we set the progress download size already at this point
- just to make it easier for apps/callbacks to extract this
- info as soon as possible */
- Curl_pgrsSetDownloadSize(data, k->size);
- }
- else if(offt == CURL_OFFT_FLOW) {
- /* out of range */
- if(data->set.max_filesize) {
- failf(data, "Maximum file size exceeded");
- return CURLE_FILESIZE_EXCEEDED;
- }
- streamclose(conn, "overflow content-length");
- infof(data, "Overflow Content-Length: value!\n");
- }
- else {
- /* negative or just rubbish - bad HTTP */
- failf(data, "Invalid Content-Length: value");
- return CURLE_WEIRD_SERVER_REPLY;
- }
- }
- /* check for Content-Type: header lines to get the MIME-type */
- else if(checkprefix("Content-Type:", headp)) {
- char *contenttype = Curl_copy_header_value(headp);
- if(!contenttype)
- return CURLE_OUT_OF_MEMORY;
- if(!*contenttype)
- /* ignore empty data */
- free(contenttype);
- else {
- Curl_safefree(data->info.contenttype);
- data->info.contenttype = contenttype;
- }
- }
-#ifndef CURL_DISABLE_PROXY
- else if((conn->httpversion == 10) &&
- conn->bits.httpproxy &&
- Curl_compareheader(headp, "Proxy-Connection:", "keep-alive")) {
- /*
- * When a HTTP/1.0 reply comes when using a proxy, the
- * 'Proxy-Connection: keep-alive' line tells us the
- * connection will be kept alive for our pleasure.
- * Default action for 1.0 is to close.
- */
- connkeep(conn, "Proxy-Connection keep-alive"); /* don't close */
- infof(data, "HTTP/1.0 proxy connection set to keep alive!\n");
- }
- else if((conn->httpversion == 11) &&
- conn->bits.httpproxy &&
- Curl_compareheader(headp, "Proxy-Connection:", "close")) {
- /*
- * We get a HTTP/1.1 response from a proxy and it says it'll
- * close down after this transfer.
- */
- connclose(conn, "Proxy-Connection: asked to close after done");
- infof(data, "HTTP/1.1 proxy connection set close!\n");
- }
-#endif
- else if((conn->httpversion == 10) &&
- Curl_compareheader(headp, "Connection:", "keep-alive")) {
- /*
- * A HTTP/1.0 reply with the 'Connection: keep-alive' line
- * tells us the connection will be kept alive for our
- * pleasure. Default action for 1.0 is to close.
- *
- * [RFC2068, section 19.7.1] */
- connkeep(conn, "Connection keep-alive");
- infof(data, "HTTP/1.0 connection set to keep alive!\n");
- }
- else if(Curl_compareheader(headp, "Connection:", "close")) {
- /*
- * [RFC 2616, section 8.1.2.1]
- * "Connection: close" is HTTP/1.1 language and means that
- * the connection will close when this request has been
- * served.
- */
- streamclose(conn, "Connection: close used");
- }
- else if(!k->http_bodyless && checkprefix("Transfer-Encoding:", headp)) {
- /* One or more encodings. We check for chunked and/or a compression
- algorithm. */
- /*
- * [RFC 2616, section 3.6.1] A 'chunked' transfer encoding
- * means that the server will send a series of "chunks". Each
- * chunk starts with line with info (including size of the
- * coming block) (terminated with CRLF), then a block of data
- * with the previously mentioned size. There can be any amount
- * of chunks, and a chunk-data set to zero signals the
- * end-of-chunks. */
-
- result = Curl_build_unencoding_stack(conn, headp + 18, TRUE);
- if(result)
- return result;
- }
- else if(!k->http_bodyless && checkprefix("Content-Encoding:", headp) &&
- data->set.str[STRING_ENCODING]) {
- /*
- * Process Content-Encoding. Look for the values: identity,
- * gzip, deflate, compress, x-gzip and x-compress. x-gzip and
- * x-compress are the same as gzip and compress. (Sec 3.5 RFC
- * 2616). zlib cannot handle compress. However, errors are
- * handled further down when the response body is processed
- */
- result = Curl_build_unencoding_stack(conn, headp + 17, FALSE);
- if(result)
- return result;
- }
- else if(checkprefix("Retry-After:", headp)) {
- /* Retry-After = HTTP-date / delay-seconds */
- curl_off_t retry_after = 0; /* zero for unknown or "now" */
- time_t date = Curl_getdate_capped(&headp[12]);
- if(-1 == date) {
- /* not a date, try it as a decimal number */
- (void)curlx_strtoofft(&headp[12], NULL, 10, &retry_after);
- }
- else
- /* convert date to number of seconds into the future */
- retry_after = date - time(NULL);
- data->info.retry_after = retry_after; /* store it */
- }
- else if(!k->http_bodyless && checkprefix("Content-Range:", headp)) {
- /* Content-Range: bytes [num]-
- Content-Range: bytes: [num]-
- Content-Range: [num]-
- Content-Range: [asterisk]/[total]
-
- The second format was added since Sun's webserver
- JavaWebServer/1.1.1 obviously sends the header this way!
- The third added since some servers use that!
- The forth means the requested range was unsatisfied.
- */
-
- char *ptr = headp + 14;
-
- /* Move forward until first digit or asterisk */
- while(*ptr && !ISDIGIT(*ptr) && *ptr != '*')
- ptr++;
-
- /* if it truly stopped on a digit */
- if(ISDIGIT(*ptr)) {
- if(!curlx_strtoofft(ptr, NULL, 10, &k->offset)) {
- if(data->state.resume_from == k->offset)
- /* we asked for a resume and we got it */
- k->content_range = TRUE;
- }
- }
- else
- data->state.resume_from = 0; /* get everything */
- }
-#if !defined(CURL_DISABLE_COOKIES)
- else if(data->cookies && data->state.cookie_engine &&
- checkprefix("Set-Cookie:", headp)) {
- Curl_share_lock(data, CURL_LOCK_DATA_COOKIE,
- CURL_LOCK_ACCESS_SINGLE);
- Curl_cookie_add(data,
- data->cookies, TRUE, FALSE, headp + 11,
- /* If there is a custom-set Host: name, use it
- here, or else use real peer host name. */
- data->state.aptr.cookiehost?
- data->state.aptr.cookiehost:conn->host.name,
- data->state.up.path,
- (conn->handler->protocol&CURLPROTO_HTTPS)?
- TRUE:FALSE);
- Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
- }
-#endif
- else if(!k->http_bodyless && checkprefix("Last-Modified:", headp) &&
- (data->set.timecondition || data->set.get_filetime) ) {
- k->timeofdoc = Curl_getdate_capped(headp + strlen("Last-Modified:"));
- if(data->set.get_filetime)
- data->info.filetime = k->timeofdoc;
- }
- else if((checkprefix("WWW-Authenticate:", headp) &&
- (401 == k->httpcode)) ||
- (checkprefix("Proxy-authenticate:", headp) &&
- (407 == k->httpcode))) {
-
- bool proxy = (k->httpcode == 407) ? TRUE : FALSE;
- char *auth = Curl_copy_header_value(headp);
- if(!auth)
- return CURLE_OUT_OF_MEMORY;
-
- result = Curl_http_input_auth(conn, proxy, auth);
-
- free(auth);
-
- if(result)
- return result;
- }
-#ifdef USE_SPNEGO
- else if(checkprefix("Persistent-Auth", headp)) {
- struct negotiatedata *negdata = &conn->negotiate;
- struct auth *authp = &data->state.authhost;
- if(authp->picked == CURLAUTH_NEGOTIATE) {
- char *persistentauth = Curl_copy_header_value(headp);
- if(!persistentauth)
- return CURLE_OUT_OF_MEMORY;
- negdata->noauthpersist = checkprefix("false", persistentauth)?
- TRUE:FALSE;
- negdata->havenoauthpersist = TRUE;
- infof(data, "Negotiate: noauthpersist -> %d, header part: %s",
- negdata->noauthpersist, persistentauth);
- free(persistentauth);
- }
- }
-#endif
- else if((k->httpcode >= 300 && k->httpcode < 400) &&
- checkprefix("Location:", headp) &&
- !data->req.location) {
- /* this is the URL that the server advises us to use instead */
- char *location = Curl_copy_header_value(headp);
- if(!location)
- return CURLE_OUT_OF_MEMORY;
- if(!*location)
- /* ignore empty data */
- free(location);
- else {
- data->req.location = location;
-
- if(data->set.http_follow_location) {
- DEBUGASSERT(!data->req.newurl);
- data->req.newurl = strdup(data->req.location); /* clone */
- if(!data->req.newurl)
- return CURLE_OUT_OF_MEMORY;
-
- /* some cases of POST and PUT etc needs to rewind the data
- stream at this point */
- result = http_perhapsrewind(conn);
- if(result)
- return result;
- }
- }
- }
-#ifdef USE_ALTSVC
- /* If enabled, the header is incoming and this is over HTTPS */
- else if(data->asi && checkprefix("Alt-Svc:", headp) &&
- ((conn->handler->flags & PROTOPT_SSL) ||
-#ifdef CURLDEBUG
- /* allow debug builds to circumvent the HTTPS restriction */
- getenv("CURL_ALTSVC_HTTP")
-#else
- 0
-#endif
- )) {
- /* the ALPN of the current request */
- enum alpnid id = (conn->httpversion == 20) ? ALPN_h2 : ALPN_h1;
- result = Curl_altsvc_parse(data, data->asi,
- &headp[ strlen("Alt-Svc:") ],
- id, conn->host.name,
- curlx_uitous(conn->remote_port));
- if(result)
- return result;
- }
-#endif
- else if(conn->handler->protocol & CURLPROTO_RTSP) {
- result = Curl_rtsp_parseheader(conn, headp);
- if(result)
- return result;
- }
+ result = Curl_http_header(data, conn, headp);
+ if(result)
+ return result;
/*
* End of header-checks. Write them to the client.
@@ -4025,11 +4243,10 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
if(data->set.include_header)
writetype |= CLIENTWRITE_BODY;
- if(data->set.verbose)
- Curl_debug(data, CURLINFO_HEADER_IN, headp,
- Curl_dyn_len(&data->state.headerb));
+ Curl_debug(data, CURLINFO_HEADER_IN, headp,
+ Curl_dyn_len(&data->state.headerb));
- result = Curl_client_write(conn, writetype, headp,
+ result = Curl_client_write(data, writetype, headp,
Curl_dyn_len(&data->state.headerb));
if(result)
return result;
diff --git a/Utilities/cmcurl/lib/http.h b/Utilities/cmcurl/lib/http.h
index 9ea3eb283..28f9341f6 100644
--- a/Utilities/cmcurl/lib/http.h
+++ b/Utilities/cmcurl/lib/http.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -23,6 +23,15 @@
***************************************************************************/
#include "curl_setup.h"
+typedef enum {
+ HTTPREQ_GET,
+ HTTPREQ_POST,
+ HTTPREQ_POST_FORM, /* we make a difference internally */
+ HTTPREQ_POST_MIME, /* we make a difference internally */
+ HTTPREQ_PUT,
+ HTTPREQ_HEAD
+} Curl_HttpReq;
+
#ifndef CURL_DISABLE_HTTP
#ifdef USE_NGHTTP2
@@ -42,32 +51,78 @@ bool Curl_compareheader(const char *headerline, /* line to check */
char *Curl_copy_header_value(const char *header);
-char *Curl_checkProxyheaders(const struct connectdata *conn,
+char *Curl_checkProxyheaders(struct Curl_easy *data,
+ const struct connectdata *conn,
const char *thisheader);
+#ifndef USE_HYPER
CURLcode Curl_buffer_send(struct dynbuf *in,
- struct connectdata *conn,
+ struct Curl_easy *data,
curl_off_t *bytes_written,
size_t included_body_bytes,
int socketindex);
+#else
+#define Curl_buffer_send(a,b,c,d,e) CURLE_OK
+#endif
-CURLcode Curl_add_timecondition(const struct connectdata *conn,
- struct dynbuf *buf);
-CURLcode Curl_add_custom_headers(struct connectdata *conn,
+CURLcode Curl_add_timecondition(struct Curl_easy *data,
+#ifndef USE_HYPER
+ struct dynbuf *req
+#else
+ void *headers
+#endif
+ );
+CURLcode Curl_add_custom_headers(struct Curl_easy *data,
bool is_connect,
- struct dynbuf *req_buffer);
+#ifndef USE_HYPER
+ struct dynbuf *req
+#else
+ void *headers
+#endif
+ );
CURLcode Curl_http_compile_trailers(struct curl_slist *trailers,
struct dynbuf *buf,
struct Curl_easy *handle);
+void Curl_http_method(struct Curl_easy *data, struct connectdata *conn,
+ const char **method, Curl_HttpReq *);
+CURLcode Curl_http_useragent(struct Curl_easy *data);
+CURLcode Curl_http_host(struct Curl_easy *data, struct connectdata *conn);
+CURLcode Curl_http_target(struct Curl_easy *data, struct connectdata *conn,
+ struct dynbuf *req);
+CURLcode Curl_http_statusline(struct Curl_easy *data,
+ struct connectdata *conn);
+CURLcode Curl_http_header(struct Curl_easy *data, struct connectdata *conn,
+ char *headp);
+CURLcode Curl_http_body(struct Curl_easy *data, struct connectdata *conn,
+ Curl_HttpReq httpreq,
+ const char **teep);
+CURLcode Curl_http_bodysend(struct Curl_easy *data, struct connectdata *conn,
+ struct dynbuf *r, Curl_HttpReq httpreq);
+#ifndef CURL_DISABLE_COOKIES
+CURLcode Curl_http_cookies(struct Curl_easy *data,
+ struct connectdata *conn,
+ struct dynbuf *r);
+#else
+#define Curl_http_cookies(a,b,c) CURLE_OK
+#endif
+CURLcode Curl_http_resume(struct Curl_easy *data,
+ struct connectdata *conn,
+ Curl_HttpReq httpreq);
+CURLcode Curl_http_range(struct Curl_easy *data,
+ Curl_HttpReq httpreq);
+CURLcode Curl_http_firstwrite(struct Curl_easy *data,
+ struct connectdata *conn,
+ bool *done);
+
/* protocol-specific functions set up to be called by the main engine */
-CURLcode Curl_http(struct connectdata *conn, bool *done);
-CURLcode Curl_http_done(struct connectdata *, CURLcode, bool premature);
-CURLcode Curl_http_connect(struct connectdata *conn, bool *done);
+CURLcode Curl_http(struct Curl_easy *data, bool *done);
+CURLcode Curl_http_done(struct Curl_easy *data, CURLcode, bool premature);
+CURLcode Curl_http_connect(struct Curl_easy *data, bool *done);
/* These functions are in http.c */
-CURLcode Curl_http_input_auth(struct connectdata *conn, bool proxy,
+CURLcode Curl_http_input_auth(struct Curl_easy *data, bool proxy,
const char *auth);
-CURLcode Curl_http_auth_act(struct connectdata *conn);
+CURLcode Curl_http_auth_act(struct Curl_easy *data);
/* If only the PICKNONE bit is set, there has been a round-trip and we
selected to use no auth at all. Ie, we actively select no auth, as opposed
@@ -115,7 +170,6 @@ struct HTTP {
const char *postdata;
const char *p_pragma; /* Pragma: string */
- const char *p_accept; /* Accept: string */
/* For FORM posting */
curl_mimepart form;
@@ -234,11 +288,13 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
/**
* Curl_http_output_auth() setups the authentication headers for the
* host/proxy and the correct authentication
- * method. conn->data->state.authdone is set to TRUE when authentication is
+ * method. data->state.authdone is set to TRUE when authentication is
* done.
*
+ * @param data all information about the current transfer
* @param conn all information about the current connection
* @param request pointer to the request keyword
+ * @param httpreq is the request type
* @param path pointer to the requested path
* @param proxytunnel boolean if this is the request setting up a "proxy
* tunnel"
@@ -246,8 +302,10 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
* @returns CURLcode
*/
CURLcode
-Curl_http_output_auth(struct connectdata *conn,
+Curl_http_output_auth(struct Curl_easy *data,
+ struct connectdata *conn,
const char *request,
+ Curl_HttpReq httpreq,
const char *path,
bool proxytunnel); /* TRUE if this is the request setting
up the proxy tunnel */
diff --git a/Utilities/cmcurl/lib/http2.c b/Utilities/cmcurl/lib/http2.c
index d316da8b6..be4c71242 100644
--- a/Utilities/cmcurl/lib/http2.c
+++ b/Utilities/cmcurl/lib/http2.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -65,12 +65,13 @@
#endif
-static ssize_t http2_recv(struct connectdata *conn, int sockindex,
+static ssize_t http2_recv(struct Curl_easy *data, int sockindex,
char *mem, size_t len, CURLcode *err);
-static bool http2_connisdead(struct connectdata *conn);
+static bool http2_connisdead(struct Curl_easy *data,
+ struct connectdata *conn);
static int h2_session_send(struct Curl_easy *data,
nghttp2_session *h2);
-static int h2_process_pending_input(struct connectdata *conn,
+static int h2_process_pending_input(struct Curl_easy *data,
struct http_conn *httpc,
CURLcode *err);
@@ -92,18 +93,20 @@ void Curl_http2_init_userset(struct UserDefined *set)
set->stream_weight = NGHTTP2_DEFAULT_WEIGHT;
}
-static int http2_perform_getsock(const struct connectdata *conn,
- curl_socket_t *sock)
+static int http2_getsock(struct Curl_easy *data,
+ struct connectdata *conn,
+ curl_socket_t *sock)
{
const struct http_conn *c = &conn->proto.httpc;
- struct SingleRequest *k = &conn->data->req;
+ struct SingleRequest *k = &data->req;
int bitmap = GETSOCK_BLANK;
sock[0] = conn->sock[FIRSTSOCKET];
- /* in a HTTP/2 connection we can basically always get a frame so we should
- always be ready for one */
- bitmap |= GETSOCK_READSOCK(FIRSTSOCKET);
+ if(!(k->keepon & KEEP_RECV_PAUSE))
+ /* Unless paused - in a HTTP/2 connection we can basically always get a
+ frame so we should always be ready for one */
+ bitmap |= GETSOCK_READSOCK(FIRSTSOCKET);
/* we're still uploading or the HTTP/2 layer wants to send data */
if(((k->keepon & (KEEP_SEND|KEEP_SEND_PAUSE)) == KEEP_SEND) ||
@@ -113,12 +116,6 @@ static int http2_perform_getsock(const struct connectdata *conn,
return bitmap;
}
-static int http2_getsock(struct connectdata *conn,
- curl_socket_t *socks)
-{
- return http2_perform_getsock(conn, socks);
-}
-
/*
* http2_stream_free() free HTTP2 stream related data
*/
@@ -139,18 +136,22 @@ static void http2_stream_free(struct HTTP *http)
* connection cache and not the "main" one. Don't touch the easy handle!
*/
-static CURLcode http2_disconnect(struct connectdata *conn,
+static CURLcode http2_disconnect(struct Curl_easy *data,
+ struct connectdata *conn,
bool dead_connection)
{
struct http_conn *c = &conn->proto.httpc;
(void)dead_connection;
+#ifndef DEBUG_HTTP2
+ (void)data;
+#endif
- H2BUGF(infof(conn->data, "HTTP/2 DISCONNECT starts now\n"));
+ H2BUGF(infof(data, "HTTP/2 DISCONNECT starts now\n"));
nghttp2_session_del(c->h2);
Curl_safefree(c->inbuf);
- H2BUGF(infof(conn->data, "HTTP/2 DISCONNECT done\n"));
+ H2BUGF(infof(data, "HTTP/2 DISCONNECT done\n"));
return CURLE_OK;
}
@@ -162,7 +163,7 @@ static CURLcode http2_disconnect(struct connectdata *conn,
* Instead, if it is readable, run Curl_connalive() to peek at the socket
* and distinguish between closed and data.
*/
-static bool http2_connisdead(struct connectdata *conn)
+static bool http2_connisdead(struct Curl_easy *data, struct connectdata *conn)
{
int sval;
bool dead = TRUE;
@@ -192,14 +193,14 @@ static bool http2_connisdead(struct connectdata *conn)
if(httpc->recv_underlying)
/* if called "too early", this pointer isn't setup yet! */
nread = ((Curl_recv *)httpc->recv_underlying)(
- conn, FIRSTSOCKET, httpc->inbuf, H2_BUFSIZE, &result);
+ data, FIRSTSOCKET, httpc->inbuf, H2_BUFSIZE, &result);
if(nread != -1) {
- infof(conn->data,
+ infof(data,
"%d bytes stray data read before trying h2 connection\n",
(int)nread);
httpc->nread_inbuf = 0;
httpc->inbuflen = nread;
- (void)h2_process_pending_input(conn, httpc, &result);
+ (void)h2_process_pending_input(data, httpc, &result);
}
else
/* the read failed so let's say this is dead anyway */
@@ -210,24 +211,25 @@ static bool http2_connisdead(struct connectdata *conn)
return dead;
}
-static unsigned int http2_conncheck(struct connectdata *check,
+static unsigned int http2_conncheck(struct Curl_easy *data,
+ struct connectdata *conn,
unsigned int checks_to_perform)
{
unsigned int ret_val = CONNRESULT_NONE;
- struct http_conn *c = &check->proto.httpc;
+ struct http_conn *c = &conn->proto.httpc;
int rc;
bool send_frames = false;
if(checks_to_perform & CONNCHECK_ISDEAD) {
- if(http2_connisdead(check))
+ if(http2_connisdead(data, conn))
ret_val |= CONNRESULT_DEAD;
}
if(checks_to_perform & CONNCHECK_KEEPALIVE) {
struct curltime now = Curl_now();
- timediff_t elapsed = Curl_timediff(now, check->keepalive);
+ timediff_t elapsed = Curl_timediff(now, conn->keepalive);
- if(elapsed > check->upkeep_interval_ms) {
+ if(elapsed > data->set.upkeep_interval_ms) {
/* Perform an HTTP/2 PING */
rc = nghttp2_submit_ping(c->h2, 0, ZERO_NULL);
if(!rc) {
@@ -236,18 +238,18 @@ static unsigned int http2_conncheck(struct connectdata *check,
send_frames = true;
}
else {
- failf(check->data, "nghttp2_submit_ping() failed: %s(%d)",
+ failf(data, "nghttp2_submit_ping() failed: %s(%d)",
nghttp2_strerror(rc), rc);
}
- check->keepalive = now;
+ conn->keepalive = now;
}
}
if(send_frames) {
rc = nghttp2_session_send(c->h2);
if(rc)
- failf(check->data, "nghttp2_session_send() failed: %s(%d)",
+ failf(data, "nghttp2_session_send() failed: %s(%d)",
nghttp2_strerror(rc), rc);
}
@@ -257,7 +259,7 @@ static unsigned int http2_conncheck(struct connectdata *check,
/* called from http_setup_conn */
void Curl_http2_setup_req(struct Curl_easy *data)
{
- struct HTTP *http = data->req.protop;
+ struct HTTP *http = data->req.p.http;
http->bodystarted = FALSE;
http->status_code = -1;
http->pausedata = NULL;
@@ -294,12 +296,13 @@ static const struct Curl_handler Curl_handler_http2 = {
http2_getsock, /* proto_getsock */
http2_getsock, /* doing_getsock */
ZERO_NULL, /* domore_getsock */
- http2_perform_getsock, /* perform_getsock */
+ http2_getsock, /* perform_getsock */
http2_disconnect, /* disconnect */
ZERO_NULL, /* readwrite */
http2_conncheck, /* connection_check */
PORT_HTTP, /* defport */
CURLPROTO_HTTP, /* protocol */
+ CURLPROTO_HTTP, /* family */
PROTOPT_STREAM /* flags */
};
@@ -315,12 +318,13 @@ static const struct Curl_handler Curl_handler_http2_ssl = {
http2_getsock, /* proto_getsock */
http2_getsock, /* doing_getsock */
ZERO_NULL, /* domore_getsock */
- http2_perform_getsock, /* perform_getsock */
+ http2_getsock, /* perform_getsock */
http2_disconnect, /* disconnect */
ZERO_NULL, /* readwrite */
http2_conncheck, /* connection_check */
PORT_HTTP, /* defport */
CURLPROTO_HTTPS, /* protocol */
+ CURLPROTO_HTTP, /* family */
PROTOPT_SSL | PROTOPT_STREAM /* flags */
};
@@ -340,7 +344,7 @@ int Curl_http2_ver(char *p, size_t len)
* written. See the documentation of nghttp2_send_callback for the details.
*/
static ssize_t send_callback(nghttp2_session *h2,
- const uint8_t *data, size_t length, int flags,
+ const uint8_t *mem, size_t length, int flags,
void *userp)
{
struct connectdata *conn = (struct connectdata *)userp;
@@ -355,8 +359,8 @@ static ssize_t send_callback(nghttp2_session *h2,
/* called before setup properly! */
return NGHTTP2_ERR_CALLBACK_FAILURE;
- written = ((Curl_send*)c->send_underlying)(conn, FIRSTSOCKET,
- data, length, &result);
+ written = ((Curl_send*)c->send_underlying)(conn->data, FIRSTSOCKET,
+ mem, length, &result);
if(result == CURLE_AGAIN) {
return NGHTTP2_ERR_WOULDBLOCK;
@@ -391,7 +395,7 @@ char *curl_pushheader_bynum(struct curl_pushheaders *h, size_t num)
if(!h || !GOOD_EASY_HANDLE(h->data))
return NULL;
else {
- struct HTTP *stream = h->data->req.protop;
+ struct HTTP *stream = h->data->req.p.http;
if(num < stream->push_headers_used)
return stream->push_headers[num];
}
@@ -413,7 +417,7 @@ char *curl_pushheader_byname(struct curl_pushheaders *h, const char *header)
!strcmp(header, ":") || strchr(header + 1, ':'))
return NULL;
else {
- struct HTTP *stream = h->data->req.protop;
+ struct HTTP *stream = h->data->req.p.http;
size_t len = strlen(header);
size_t i;
for(i = 0; i<stream->push_headers_used; i++) {
@@ -460,7 +464,7 @@ static struct Curl_easy *duphandle(struct Curl_easy *data)
(void)Curl_close(&second);
}
else {
- second->req.protop = http;
+ second->req.p.http = http;
Curl_dyn_init(&http->header_recvbuf, DYN_H2_HEADERS);
Curl_http2_setup_req(second);
second->state.stream_weight = data->state.stream_weight;
@@ -537,9 +541,9 @@ static int push_promise(struct Curl_easy *data,
/* ask the application */
H2BUGF(infof(data, "Got PUSH_PROMISE, ask application!\n"));
- stream = data->req.protop;
+ stream = data->req.p.http;
if(!stream) {
- failf(data, "Internal NULL stream!\n");
+ failf(data, "Internal NULL stream!");
(void)Curl_close(&newhandle);
rv = CURL_PUSH_DENY;
goto fail;
@@ -567,13 +571,13 @@ static int push_promise(struct Curl_easy *data,
if(rv) {
DEBUGASSERT((rv > CURL_PUSH_OK) && (rv <= CURL_PUSH_ERROROUT));
/* denied, kill off the new handle again */
- http2_stream_free(newhandle->req.protop);
- newhandle->req.protop = NULL;
+ http2_stream_free(newhandle->req.p.http);
+ newhandle->req.p.http = NULL;
(void)Curl_close(&newhandle);
goto fail;
}
- newstream = newhandle->req.protop;
+ newstream = newhandle->req.p.http;
newstream->stream_id = frame->promised_stream_id;
newhandle->req.maxdownload = -1;
newhandle->req.size = -1;
@@ -583,8 +587,8 @@ static int push_promise(struct Curl_easy *data,
rc = Curl_multi_add_perform(data->multi, newhandle, conn);
if(rc) {
infof(data, "failed to add handle to multi\n");
- http2_stream_free(newhandle->req.protop);
- newhandle->req.protop = NULL;
+ http2_stream_free(newhandle->req.p.http);
+ newhandle->req.p.http = NULL;
Curl_close(&newhandle);
rv = CURL_PUSH_DENY;
goto fail;
@@ -667,7 +671,7 @@ static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame,
return 0;
}
- stream = data_s->req.protop;
+ stream = data_s->req.p.http;
if(!stream) {
H2BUGF(infof(data_s, "No proto pointer for stream: %x\n",
stream_id));
@@ -783,7 +787,7 @@ static int on_data_chunk_recv(nghttp2_session *session, uint8_t flags,
internal error more than anything else! */
return NGHTTP2_ERR_CALLBACK_FAILURE;
- stream = data_s->req.protop;
+ stream = data_s->req.p.http;
if(!stream)
return NGHTTP2_ERR_CALLBACK_FAILURE;
@@ -849,7 +853,7 @@ static int on_stream_close(nghttp2_session *session, int32_t stream_id,
}
H2BUGF(infof(data_s, "on_stream_close(), %s (err %d), stream %u\n",
nghttp2_http2_strerror(error_code), error_code, stream_id));
- stream = data_s->req.protop;
+ stream = data_s->req.p.http;
if(!stream)
return NGHTTP2_ERR_CALLBACK_FAILURE;
@@ -894,7 +898,7 @@ static int on_begin_headers(nghttp2_session *session,
return 0;
}
- stream = data_s->req.protop;
+ stream = data_s->req.p.http;
if(!stream || !stream->bodystarted) {
return 0;
}
@@ -952,9 +956,9 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame,
internal error more than anything else! */
return NGHTTP2_ERR_CALLBACK_FAILURE;
- stream = data_s->req.protop;
+ stream = data_s->req.p.http;
if(!stream) {
- failf(data_s, "Internal NULL stream! 5\n");
+ failf(data_s, "Internal NULL stream!");
return NGHTTP2_ERR_CALLBACK_FAILURE;
}
@@ -1100,7 +1104,7 @@ static ssize_t data_source_read_callback(nghttp2_session *session,
internal error more than anything else! */
return NGHTTP2_ERR_CALLBACK_FAILURE;
- stream = data_s->req.protop;
+ stream = data_s->req.p.http;
if(!stream)
return NGHTTP2_ERR_CALLBACK_FAILURE;
}
@@ -1161,7 +1165,7 @@ static void populate_settings(struct connectdata *conn,
void Curl_http2_done(struct Curl_easy *data, bool premature)
{
- struct HTTP *http = data->req.protop;
+ struct HTTP *http = data->req.p.http;
struct http_conn *httpc = &data->conn->proto.httpc;
/* there might be allocated resources done before this got the 'h2' pointer
@@ -1207,19 +1211,12 @@ void Curl_http2_done(struct Curl_easy *data, bool premature)
}
http->stream_id = 0;
}
-
- if(0 == nghttp2_session_check_request_allowed(httpc->h2)) {
- /* No more requests are allowed in the current session, so the connection
- may not be reused. This is set when a GOAWAY frame has been received or
- when the limit of stream identifiers has been reached. */
- connclose(data->conn, "http/2: No new requests allowed");
- }
}
/*
* Initialize nghttp2 for a Curl connection
*/
-static CURLcode http2_init(struct connectdata *conn)
+static CURLcode http2_init(struct Curl_easy *data, struct connectdata *conn)
{
if(!conn->proto.httpc.h2) {
int rc;
@@ -1232,7 +1229,7 @@ static CURLcode http2_init(struct connectdata *conn)
rc = nghttp2_session_callbacks_new(&callbacks);
if(rc) {
- failf(conn->data, "Couldn't initialize nghttp2 callbacks!");
+ failf(data, "Couldn't initialize nghttp2 callbacks!");
return CURLE_OUT_OF_MEMORY; /* most likely at least */
}
@@ -1261,7 +1258,7 @@ static CURLcode http2_init(struct connectdata *conn)
nghttp2_session_callbacks_del(callbacks);
if(rc) {
- failf(conn->data, "Couldn't initialize nghttp2!");
+ failf(data, "Couldn't initialize nghttp2!");
return CURLE_OUT_OF_MEMORY; /* most likely at least */
}
}
@@ -1278,7 +1275,8 @@ CURLcode Curl_http2_request_upgrade(struct dynbuf *req,
ssize_t binlen;
char *base64;
size_t blen;
- struct SingleRequest *k = &conn->data->req;
+ struct Curl_easy *data = conn->data;
+ struct SingleRequest *k = &data->req;
uint8_t *binsettings = conn->proto.httpc.binsettings;
struct http_conn *httpc = &conn->proto.httpc;
@@ -1288,14 +1286,14 @@ CURLcode Curl_http2_request_upgrade(struct dynbuf *req,
binlen = nghttp2_pack_settings_payload(binsettings, H2_BINSETTINGS_LEN,
httpc->local_settings,
httpc->local_settings_num);
- if(!binlen) {
- failf(conn->data, "nghttp2 unexpectedly failed on pack_settings_payload");
+ if(binlen <= 0) {
+ failf(data, "nghttp2 unexpectedly failed on pack_settings_payload");
Curl_dyn_free(req);
return CURLE_FAILED_INIT;
}
conn->proto.httpc.binlen = binlen;
- result = Curl_base64url_encode(conn->data, (const char *)binsettings, binlen,
+ result = Curl_base64url_encode(data, (const char *)binsettings, binlen,
&base64, &blen);
if(result) {
Curl_dyn_free(req);
@@ -1329,14 +1327,13 @@ static int should_close_session(struct http_conn *httpc)
* This function returns 0 if it succeeds, or -1 and error code will
* be assigned to *err.
*/
-static int h2_process_pending_input(struct connectdata *conn,
+static int h2_process_pending_input(struct Curl_easy *data,
struct http_conn *httpc,
CURLcode *err)
{
ssize_t nread;
char *inbuf;
ssize_t rv;
- struct Curl_easy *data = conn->data;
nread = httpc->inbuflen - httpc->nread_inbuf;
inbuf = httpc->inbuf + httpc->nread_inbuf;
@@ -1345,7 +1342,7 @@ static int h2_process_pending_input(struct connectdata *conn,
if(rv < 0) {
failf(data,
"h2_process_pending_input: nghttp2_session_mem_recv() returned "
- "%zd:%s\n", rv, nghttp2_strerror((int)rv));
+ "%zd:%s", rv, nghttp2_strerror((int)rv));
*err = CURLE_RECV_ERROR;
return -1;
}
@@ -1371,6 +1368,14 @@ static int h2_process_pending_input(struct connectdata *conn,
return -1;
}
+ if(nghttp2_session_check_request_allowed(httpc->h2) == 0) {
+ /* No more requests are allowed in the current session, so
+ the connection may not be reused. This is set when a
+ GOAWAY frame has been received or when the limit of stream
+ identifiers has been reached. */
+ connclose(data->conn, "http/2: No new requests allowed");
+ }
+
if(should_close_session(httpc)) {
H2BUGF(infof(data,
"h2_process_pending_input: nothing to do in this session\n"));
@@ -1378,19 +1383,19 @@ static int h2_process_pending_input(struct connectdata *conn,
*err = CURLE_HTTP2;
else {
/* not an error per se, but should still close the connection */
- connclose(conn, "GOAWAY received");
+ connclose(data->conn, "GOAWAY received");
*err = CURLE_OK;
}
return -1;
}
-
return 0;
}
/*
* Called from transfer.c:done_sending when we stop uploading.
*/
-CURLcode Curl_http2_done_sending(struct connectdata *conn)
+CURLcode Curl_http2_done_sending(struct Curl_easy *data,
+ struct connectdata *conn)
{
CURLcode result = CURLE_OK;
@@ -1398,7 +1403,7 @@ CURLcode Curl_http2_done_sending(struct connectdata *conn)
(conn->handler == &Curl_handler_http2)) {
/* make sure this is only attempted for HTTP/2 transfers */
- struct HTTP *stream = conn->data->req.protop;
+ struct HTTP *stream = data->req.p.http;
struct http_conn *httpc = &conn->proto.httpc;
nghttp2_session *h2 = httpc->h2;
@@ -1411,13 +1416,11 @@ CURLcode Curl_http2_done_sending(struct connectdata *conn)
/* resume sending here to trigger the callback to get called again so
that it can signal EOF to nghttp2 */
(void)nghttp2_session_resume_data(h2, stream->stream_id);
-
- (void)h2_process_pending_input(conn, httpc, &result);
+ (void)h2_process_pending_input(data, httpc, &result);
}
/* If nghttp2 still has pending frames unsent */
if(nghttp2_session_want_write(h2)) {
- struct Curl_easy *data = conn->data;
struct SingleRequest *k = &data->req;
int rv;
@@ -1448,7 +1451,7 @@ static ssize_t http2_handle_stream_close(struct connectdata *conn,
drained_transfer(data, httpc);
if(httpc->pause_stream_id == 0) {
- if(h2_process_pending_input(conn, httpc, err) != 0) {
+ if(h2_process_pending_input(data, httpc, err) != 0) {
return -1;
}
}
@@ -1494,10 +1497,9 @@ static ssize_t http2_handle_stream_close(struct connectdata *conn,
break;
len = lf + 1 - trailp;
- if(data->set.verbose)
- Curl_debug(data, CURLINFO_HEADER_IN, trailp, len);
+ Curl_debug(data, CURLINFO_HEADER_IN, trailp, len);
/* pass the trailers one by one to the callback */
- result = Curl_client_write(conn, CLIENTWRITE_HEADER, trailp, len);
+ result = Curl_client_write(data, CLIENTWRITE_HEADER, trailp, len);
if(result) {
*err = result;
return -1;
@@ -1522,7 +1524,7 @@ static void h2_pri_spec(struct Curl_easy *data,
nghttp2_priority_spec *pri_spec)
{
struct HTTP *depstream = (data->set.stream_depends_on?
- data->set.stream_depends_on->req.protop:NULL);
+ data->set.stream_depends_on->req.p.http:NULL);
int32_t depstream_id = depstream? depstream->stream_id:0;
nghttp2_priority_spec_init(pri_spec, depstream_id, data->set.stream_weight,
data->set.stream_depends_e);
@@ -1539,7 +1541,7 @@ static void h2_pri_spec(struct Curl_easy *data,
static int h2_session_send(struct Curl_easy *data,
nghttp2_session *h2)
{
- struct HTTP *stream = data->req.protop;
+ struct HTTP *stream = data->req.p.http;
if((data->set.stream_weight != data->state.stream_weight) ||
(data->set.stream_depends_e != data->state.stream_depends_e) ||
(data->set.stream_depends_on != data->state.stream_depends_on) ) {
@@ -1561,15 +1563,13 @@ static int h2_session_send(struct Curl_easy *data,
return nghttp2_session_send(h2);
}
-static ssize_t http2_recv(struct connectdata *conn, int sockindex,
+static ssize_t http2_recv(struct Curl_easy *data, int sockindex,
char *mem, size_t len, CURLcode *err)
{
- CURLcode result = CURLE_OK;
- ssize_t rv;
ssize_t nread;
+ struct connectdata *conn = data->conn;
struct http_conn *httpc = &conn->proto.httpc;
- struct Curl_easy *data = conn->data;
- struct HTTP *stream = data->req.protop;
+ struct HTTP *stream = data->req.p.http;
(void)sockindex; /* we always do HTTP2 on sockindex 0 */
@@ -1632,8 +1632,7 @@ static ssize_t http2_recv(struct connectdata *conn, int sockindex,
/* We have paused nghttp2, but we have no pause data (see
on_data_chunk_recv). */
httpc->pause_stream_id = 0;
- if(h2_process_pending_input(conn, httpc, &result) != 0) {
- *err = result;
+ if(h2_process_pending_input(data, httpc, err) != 0) {
return -1;
}
}
@@ -1661,8 +1660,7 @@ static ssize_t http2_recv(struct connectdata *conn, int sockindex,
frames, then we have to call it again with 0-length data.
Without this, on_stream_close callback will not be called,
and stream could be hanged. */
- if(h2_process_pending_input(conn, httpc, &result) != 0) {
- *err = result;
+ if(h2_process_pending_input(data, httpc, err) != 0) {
return -1;
}
}
@@ -1688,7 +1686,6 @@ static ssize_t http2_recv(struct connectdata *conn, int sockindex,
return -1;
}
else {
- char *inbuf;
/* remember where to store incoming data for this stream and how big the
buffer is */
stream->mem = mem;
@@ -1697,16 +1694,15 @@ static ssize_t http2_recv(struct connectdata *conn, int sockindex,
if(httpc->inbuflen == 0) {
nread = ((Curl_recv *)httpc->recv_underlying)(
- conn, FIRSTSOCKET, httpc->inbuf, H2_BUFSIZE, &result);
+ data, FIRSTSOCKET, httpc->inbuf, H2_BUFSIZE, err);
if(nread == -1) {
- if(result != CURLE_AGAIN)
+ if(*err != CURLE_AGAIN)
failf(data, "Failed receiving HTTP2 data");
else if(stream->closed)
/* received when the stream was already closed! */
return http2_handle_stream_close(conn, data, stream, err);
- *err = result;
return -1;
}
@@ -1719,47 +1715,18 @@ static ssize_t http2_recv(struct connectdata *conn, int sockindex,
H2BUGF(infof(data, "nread=%zd\n", nread));
httpc->inbuflen = nread;
- inbuf = httpc->inbuf;
+
+ DEBUGASSERT(httpc->nread_inbuf == 0);
}
else {
nread = httpc->inbuflen - httpc->nread_inbuf;
- inbuf = httpc->inbuf + httpc->nread_inbuf;
-
+ (void)nread; /* silence warning, used in debug */
H2BUGF(infof(data, "Use data left in connection buffer, nread=%zd\n",
nread));
}
- rv = nghttp2_session_mem_recv(httpc->h2, (const uint8_t *)inbuf, nread);
- if(nghttp2_is_fatal((int)rv)) {
- failf(data, "nghttp2_session_mem_recv() returned %zd:%s\n",
- rv, nghttp2_strerror((int)rv));
- *err = CURLE_RECV_ERROR;
- return -1;
- }
- H2BUGF(infof(data, "nghttp2_session_mem_recv() returns %zd\n", rv));
- if(nread == rv) {
- H2BUGF(infof(data, "All data in connection buffer processed\n"));
- httpc->inbuflen = 0;
- httpc->nread_inbuf = 0;
- }
- else {
- httpc->nread_inbuf += rv;
- H2BUGF(infof(data, "%zu bytes left in connection buffer\n",
- httpc->inbuflen - httpc->nread_inbuf));
- }
- /* Always send pending frames in nghttp2 session, because
- nghttp2_session_mem_recv() may queue new frame */
- rv = h2_session_send(data, httpc->h2);
- if(rv != 0) {
- *err = CURLE_SEND_ERROR;
+ if(h2_process_pending_input(data, httpc, err) != 0)
return -1;
- }
-
- if(should_close_session(httpc)) {
- H2BUGF(infof(data, "http2_recv: nothing to do in this session\n"));
- *err = CURLE_HTTP2;
- return -1;
- }
}
if(stream->memlen) {
ssize_t retlen = stream->memlen;
@@ -1864,7 +1831,7 @@ static header_instruction inspect_header(const char *name, size_t namelen,
}
}
-static ssize_t http2_send(struct connectdata *conn, int sockindex,
+static ssize_t http2_send(struct Curl_easy *data, int sockindex,
const void *mem, size_t len, CURLcode *err)
{
/*
@@ -1873,8 +1840,9 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex,
* request.
*/
int rv;
+ struct connectdata *conn = data->conn;
struct http_conn *httpc = &conn->proto.httpc;
- struct HTTP *stream = conn->data->req.protop;
+ struct HTTP *stream = data->req.p.http;
nghttp2_nv *nva = NULL;
size_t nheader;
size_t i;
@@ -1888,16 +1856,16 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex,
(void)sockindex;
- H2BUGF(infof(conn->data, "http2_send len=%zu\n", len));
+ H2BUGF(infof(data, "http2_send len=%zu\n", len));
if(stream->stream_id != -1) {
if(stream->close_handled) {
- infof(conn->data, "stream %d closed\n", stream->stream_id);
+ infof(data, "stream %d closed\n", stream->stream_id);
*err = CURLE_HTTP2_STREAM;
return -1;
}
else if(stream->closed) {
- return http2_handle_stream_close(conn, conn->data, stream, err);
+ return http2_handle_stream_close(conn, data, stream, err);
}
/* If stream_id != -1, we have dispatched request HEADERS, and now
are going to send or sending request body in DATA frame */
@@ -1908,7 +1876,7 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex,
*err = CURLE_SEND_ERROR;
return -1;
}
- rv = h2_session_send(conn->data, h2);
+ rv = h2_session_send(data, h2);
if(nghttp2_is_fatal(rv)) {
*err = CURLE_SEND_ERROR;
return -1;
@@ -1921,7 +1889,7 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex,
stream->upload_len = 0;
if(should_close_session(httpc)) {
- H2BUGF(infof(conn->data, "http2_send: nothing to do in this session\n"));
+ H2BUGF(infof(data, "http2_send: nothing to do in this session\n"));
*err = CURLE_HTTP2;
return -1;
}
@@ -1934,7 +1902,7 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex,
nghttp2_session_resume_data(h2, stream->stream_id);
}
- H2BUGF(infof(conn->data, "http2_send returns %zu for stream %u\n", len,
+ H2BUGF(infof(data, "http2_send returns %zu for stream %u\n", len,
stream->stream_id));
return len;
}
@@ -1978,7 +1946,7 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex,
nva[0].valuelen = (size_t)(end - hdbuf);
nva[0].flags = NGHTTP2_NV_FLAG_NONE;
if(HEADER_OVERFLOW(nva[0])) {
- failf(conn->data, "Failed sending HTTP request: Header overflow");
+ failf(data, "Failed sending HTTP request: Header overflow");
goto fail;
}
@@ -2000,7 +1968,7 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex,
nva[1].valuelen = (size_t)(end - hdbuf);
nva[1].flags = NGHTTP2_NV_FLAG_NONE;
if(HEADER_OVERFLOW(nva[1])) {
- failf(conn->data, "Failed sending HTTP request: Header overflow");
+ failf(data, "Failed sending HTTP request: Header overflow");
goto fail;
}
@@ -2013,7 +1981,7 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex,
nva[2].valuelen = strlen((char *)nva[2].value);
nva[2].flags = NGHTTP2_NV_FLAG_NONE;
if(HEADER_OVERFLOW(nva[2])) {
- failf(conn->data, "Failed sending HTTP request: Header overflow");
+ failf(data, "Failed sending HTTP request: Header overflow");
goto fail;
}
@@ -2073,7 +2041,7 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex,
nva[i].flags = NGHTTP2_NV_FLAG_NONE;
if(HEADER_OVERFLOW(nva[i])) {
- failf(conn->data, "Failed sending HTTP request: Header overflow");
+ failf(data, "Failed sending HTTP request: Header overflow");
goto fail;
}
++i;
@@ -2097,30 +2065,30 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex,
for(i = 0; i < nheader; ++i) {
acc += nva[i].namelen + nva[i].valuelen;
- H2BUGF(infof(conn->data, "h2 header: %.*s:%.*s\n",
+ H2BUGF(infof(data, "h2 header: %.*s:%.*s\n",
nva[i].namelen, nva[i].name,
nva[i].valuelen, nva[i].value));
}
if(acc > MAX_ACC) {
- infof(conn->data, "http2_send: Warning: The cumulative length of all "
- "headers exceeds %zu bytes and that could cause the "
+ infof(data, "http2_send: Warning: The cumulative length of all "
+ "headers exceeds %d bytes and that could cause the "
"stream to be rejected.\n", MAX_ACC);
}
}
- h2_pri_spec(conn->data, &pri_spec);
+ h2_pri_spec(data, &pri_spec);
- H2BUGF(infof(conn->data, "http2_send request allowed %d (easy handle %p)\n",
- nghttp2_session_check_request_allowed(h2), (void *)conn->data));
+ H2BUGF(infof(data, "http2_send request allowed %d (easy handle %p)\n",
+ nghttp2_session_check_request_allowed(h2), (void *)data));
- switch(conn->data->state.httpreq) {
+ switch(data->state.httpreq) {
case HTTPREQ_POST:
case HTTPREQ_POST_FORM:
case HTTPREQ_POST_MIME:
case HTTPREQ_PUT:
- if(conn->data->state.infilesize != -1)
- stream->upload_left = conn->data->state.infilesize;
+ if(data->state.infilesize != -1)
+ stream->upload_left = data->state.infilesize;
else
/* data sending without specifying the data amount up front */
stream->upload_left = -1; /* unknown, but not zero */
@@ -2128,36 +2096,41 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex,
data_prd.read_callback = data_source_read_callback;
data_prd.source.ptr = NULL;
stream_id = nghttp2_submit_request(h2, &pri_spec, nva, nheader,
- &data_prd, conn->data);
+ &data_prd, data);
break;
default:
stream_id = nghttp2_submit_request(h2, &pri_spec, nva, nheader,
- NULL, conn->data);
+ NULL, data);
}
Curl_safefree(nva);
if(stream_id < 0) {
- H2BUGF(infof(conn->data, "http2_send() send error\n"));
+ H2BUGF(infof(data,
+ "http2_send() nghttp2_submit_request error (%s)%d\n",
+ nghttp2_strerror(stream_id), stream_id));
*err = CURLE_SEND_ERROR;
return -1;
}
- infof(conn->data, "Using Stream ID: %x (easy handle %p)\n",
- stream_id, (void *)conn->data);
+ infof(data, "Using Stream ID: %x (easy handle %p)\n",
+ stream_id, (void *)data);
stream->stream_id = stream_id;
/* this does not call h2_session_send() since there can not have been any
- * priority upodate since the nghttp2_submit_request() call above */
+ * priority update since the nghttp2_submit_request() call above */
rv = nghttp2_session_send(h2);
-
if(rv != 0) {
+ H2BUGF(infof(data,
+ "http2_send() nghttp2_session_send error (%s)%d\n",
+ nghttp2_strerror(rv), rv));
+
*err = CURLE_SEND_ERROR;
return -1;
}
if(should_close_session(httpc)) {
- H2BUGF(infof(conn->data, "http2_send: nothing to do in this session\n"));
+ H2BUGF(infof(data, "http2_send: nothing to do in this session\n"));
*err = CURLE_HTTP2;
return -1;
}
@@ -2179,13 +2152,14 @@ fail:
return -1;
}
-CURLcode Curl_http2_setup(struct connectdata *conn)
+CURLcode Curl_http2_setup(struct Curl_easy *data,
+ struct connectdata *conn)
{
CURLcode result;
struct http_conn *httpc = &conn->proto.httpc;
- struct HTTP *stream = conn->data->req.protop;
+ struct HTTP *stream = data->req.p.http;
- DEBUGASSERT(conn->data->state.buffer);
+ DEBUGASSERT(data->state.buffer);
stream->stream_id = -1;
@@ -2201,18 +2175,18 @@ CURLcode Curl_http2_setup(struct connectdata *conn)
else
conn->handler = &Curl_handler_http2;
- result = http2_init(conn);
+ result = http2_init(data, conn);
if(result) {
Curl_dyn_free(&stream->header_recvbuf);
return result;
}
- infof(conn->data, "Using HTTP2, server supports multi-use\n");
+ infof(data, "Using HTTP2, server supports multi-use\n");
stream->upload_left = 0;
stream->upload_mem = NULL;
stream->upload_len = 0;
- stream->mem = conn->data->state.buffer;
- stream->len = conn->data->set.buffer_size;
+ stream->mem = data->state.buffer;
+ stream->len = data->set.buffer_size;
httpc->inbuflen = 0;
httpc->nread_inbuf = 0;
@@ -2224,23 +2198,22 @@ CURLcode Curl_http2_setup(struct connectdata *conn)
conn->httpversion = 20;
conn->bundle->multiuse = BUNDLE_MULTIPLEX;
- infof(conn->data, "Connection state changed (HTTP/2 confirmed)\n");
- multi_connchanged(conn->data->multi);
+ infof(data, "Connection state changed (HTTP/2 confirmed)\n");
+ multi_connchanged(data->multi);
return CURLE_OK;
}
-CURLcode Curl_http2_switched(struct connectdata *conn,
+CURLcode Curl_http2_switched(struct Curl_easy *data,
const char *mem, size_t nread)
{
CURLcode result;
+ struct connectdata *conn = data->conn;
struct http_conn *httpc = &conn->proto.httpc;
int rv;
- ssize_t nproc;
- struct Curl_easy *data = conn->data;
- struct HTTP *stream = conn->data->req.protop;
+ struct HTTP *stream = data->req.p.http;
- result = Curl_http2_setup(conn);
+ result = Curl_http2_setup(data, conn);
if(result)
return result;
@@ -2249,7 +2222,7 @@ CURLcode Curl_http2_switched(struct connectdata *conn,
conn->recv[FIRSTSOCKET] = http2_recv;
conn->send[FIRSTSOCKET] = http2_send;
- if(conn->data->req.upgr101 == UPGR101_RECEIVED) {
+ if(data->req.upgr101 == UPGR101_RECEIVED) {
/* stream 1 is opened implicitly on upgrade */
stream->stream_id = 1;
/* queue SETTINGS frame (again) */
@@ -2299,52 +2272,24 @@ CURLcode Curl_http2_switched(struct connectdata *conn,
data into stream->mem, overwriting data already there. */
if(H2_BUFSIZE < nread) {
failf(data, "connection buffer size is too small to store data following "
- "HTTP Upgrade response header: buflen=%zu, datalen=%zu",
+ "HTTP Upgrade response header: buflen=%d, datalen=%zu",
H2_BUFSIZE, nread);
return CURLE_HTTP2;
}
- infof(conn->data, "Copying HTTP/2 data in stream buffer to connection buffer"
- " after upgrade: len=%zu\n",
+ infof(data, "Copying HTTP/2 data in stream buffer to connection buffer"
+ " after upgrade: len=%zu\n",
nread);
if(nread)
memcpy(httpc->inbuf, mem, nread);
- httpc->inbuflen = nread;
-
- nproc = nghttp2_session_mem_recv(httpc->h2, (const uint8_t *)httpc->inbuf,
- httpc->inbuflen);
-
- if(nghttp2_is_fatal((int)nproc)) {
- failf(data, "nghttp2_session_mem_recv() failed: %s(%d)",
- nghttp2_strerror((int)nproc), (int)nproc);
- return CURLE_HTTP2;
- }
- H2BUGF(infof(data, "nghttp2_session_mem_recv() returns %zd\n", nproc));
-
- if((ssize_t)nread == nproc) {
- httpc->inbuflen = 0;
- httpc->nread_inbuf = 0;
- }
- else {
- httpc->nread_inbuf += nproc;
- }
-
- /* Try to send some frames since we may read SETTINGS already. */
- rv = h2_session_send(data, httpc->h2);
+ httpc->inbuflen = nread;
- if(rv != 0) {
- failf(data, "nghttp2_session_send() failed: %s(%d)",
- nghttp2_strerror(rv), rv);
- return CURLE_HTTP2;
- }
+ DEBUGASSERT(httpc->nread_inbuf == 0);
- if(should_close_session(httpc)) {
- H2BUGF(infof(data,
- "nghttp2_session_send(): nothing to do in this session\n"));
+ if(-1 == h2_process_pending_input(data, httpc, &result))
return CURLE_HTTP2;
- }
return CURLE_OK;
}
@@ -2358,7 +2303,7 @@ CURLcode Curl_http2_stream_pause(struct Curl_easy *data, bool pause)
return CURLE_OK;
#ifdef NGHTTP2_HAS_SET_LOCAL_WINDOW_SIZE
else {
- struct HTTP *stream = data->req.protop;
+ struct HTTP *stream = data->req.p.http;
struct http_conn *httpc = &data->conn->proto.httpc;
uint32_t window = !pause * HTTP2_HUGE_WINDOW_SIZE;
int rv = nghttp2_session_set_local_window_size(httpc->h2,
diff --git a/Utilities/cmcurl/lib/http2.h b/Utilities/cmcurl/lib/http2.h
index e82b21280..119e584a8 100644
--- a/Utilities/cmcurl/lib/http2.h
+++ b/Utilities/cmcurl/lib/http2.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -44,14 +44,15 @@ void Curl_http2_init_state(struct UrlState *state);
void Curl_http2_init_userset(struct UserDefined *set);
CURLcode Curl_http2_request_upgrade(struct dynbuf *req,
struct connectdata *conn);
-CURLcode Curl_http2_setup(struct connectdata *conn);
-CURLcode Curl_http2_switched(struct connectdata *conn,
- const char *data, size_t nread);
+CURLcode Curl_http2_setup(struct Curl_easy *data, struct connectdata *conn);
+CURLcode Curl_http2_switched(struct Curl_easy *data,
+ const char *ptr, size_t nread);
/* called from http_setup_conn */
void Curl_http2_setup_conn(struct connectdata *conn);
void Curl_http2_setup_req(struct Curl_easy *data);
void Curl_http2_done(struct Curl_easy *data, bool premature);
-CURLcode Curl_http2_done_sending(struct connectdata *conn);
+CURLcode Curl_http2_done_sending(struct Curl_easy *data,
+ struct connectdata *conn);
CURLcode Curl_http2_add_child(struct Curl_easy *parent,
struct Curl_easy *child,
bool exclusive);
@@ -64,14 +65,14 @@ CURLcode Curl_http2_stream_pause(struct Curl_easy *data, bool pause);
bool Curl_h2_http_1_1_error(struct connectdata *conn);
#else /* USE_NGHTTP2 */
#define Curl_http2_request_upgrade(x,y) CURLE_UNSUPPORTED_PROTOCOL
-#define Curl_http2_setup(x) CURLE_UNSUPPORTED_PROTOCOL
+#define Curl_http2_setup(x,y) CURLE_UNSUPPORTED_PROTOCOL
#define Curl_http2_switched(x,y,z) CURLE_UNSUPPORTED_PROTOCOL
#define Curl_http2_setup_conn(x) Curl_nop_stmt
#define Curl_http2_setup_req(x)
#define Curl_http2_init_state(x)
#define Curl_http2_init_userset(x)
#define Curl_http2_done(x,y)
-#define Curl_http2_done_sending(x)
+#define Curl_http2_done_sending(x,y)
#define Curl_http2_add_child(x, y, z)
#define Curl_http2_remove_child(x, y)
#define Curl_http2_cleanup_dependencies(x)
diff --git a/Utilities/cmcurl/lib/http_aws_sigv4.c b/Utilities/cmcurl/lib/http_aws_sigv4.c
new file mode 100644
index 000000000..8fd1c77e6
--- /dev/null
+++ b/Utilities/cmcurl/lib/http_aws_sigv4.c
@@ -0,0 +1,394 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_CRYPTO_AUTH)
+
+#include "urldata.h"
+#include "strcase.h"
+#include "strdup.h"
+#include "vauth/vauth.h"
+#include "vauth/digest.h"
+#include "http_aws_sigv4.h"
+#include "curl_sha256.h"
+#include "transfer.h"
+
+#include "strcase.h"
+#include "parsedate.h"
+#include "sendf.h"
+
+#include <time.h>
+
+/* The last 3 #include files should be in this order */
+#include "curl_printf.h"
+#include "curl_memory.h"
+#include "memdebug.h"
+
+#define HMAC_SHA256(k, kl, d, dl, o) \
+ do { \
+ ret = Curl_hmacit(Curl_HMAC_SHA256, \
+ (unsigned char *)k, \
+ (unsigned int)kl, \
+ (unsigned char *)d, \
+ (unsigned int)dl, o); \
+ if(ret != CURLE_OK) { \
+ goto fail; \
+ } \
+ } while(0)
+
+static void sha256_to_hex(char *dst, unsigned char *sha, size_t dst_l)
+{
+ int i;
+
+ DEBUGASSERT(dst_l >= 65);
+ for(i = 0; i < 32; ++i) {
+ curl_msnprintf(dst + (i * 2), dst_l - (i * 2), "%02x", sha[i]);
+ }
+}
+
+CURLcode Curl_output_aws_sigv4(struct Curl_easy *data, bool proxy)
+{
+ CURLcode ret = CURLE_OUT_OF_MEMORY;
+ struct connectdata *conn = data->conn;
+ size_t len;
+ const char *tmp0;
+ const char *tmp1;
+ char *provider0_low = NULL;
+ char *provider0_up = NULL;
+ char *provider1_low = NULL;
+ char *provider1_mid = NULL;
+ char *region = NULL;
+ char *service = NULL;
+ const char *hostname = conn->host.name;
+#ifdef DEBUGBUILD
+ char *force_timestamp;
+#endif
+ time_t clock;
+ struct tm tm;
+ char timestamp[17];
+ char date[9];
+ const char *content_type = Curl_checkheaders(data, "Content-Type");
+ char *canonical_headers = NULL;
+ char *signed_headers = NULL;
+ Curl_HttpReq httpreq;
+ const char *method;
+ const char *post_data = data->set.postfields ? data->set.postfields : "";
+ unsigned char sha_hash[32];
+ char sha_hex[65];
+ char *canonical_request = NULL;
+ char *request_type = NULL;
+ char *credential_scope = NULL;
+ char *str_to_sign = NULL;
+ const char *user = conn->user ? conn->user : "";
+ const char *passwd = conn->passwd ? conn->passwd : "";
+ char *secret = NULL;
+ unsigned char tmp_sign0[32] = {0};
+ unsigned char tmp_sign1[32] = {0};
+ char *auth_headers = NULL;
+
+ DEBUGASSERT(!proxy);
+ (void)proxy;
+
+ if(Curl_checkheaders(data, "Authorization")) {
+ /* Authorization already present, Bailing out */
+ return CURLE_OK;
+ }
+
+ /*
+ * Parameters parsing
+ * Google and Outscale use the same OSC or GOOG,
+ * but Amazon uses AWS and AMZ for header arguments.
+ * AWS is the default because most of non-amazon providers
+ * are still using aws:amz as a prefix.
+ */
+ tmp0 = data->set.str[STRING_AWS_SIGV4] ?
+ data->set.str[STRING_AWS_SIGV4] : "aws:amz";
+ tmp1 = strchr(tmp0, ':');
+ len = tmp1 ? (size_t)(tmp1 - tmp0) : strlen(tmp0);
+ if(len < 1) {
+ infof(data, "first provider can't be empty\n");
+ ret = CURLE_BAD_FUNCTION_ARGUMENT;
+ goto fail;
+ }
+ provider0_low = malloc(len + 1);
+ provider0_up = malloc(len + 1);
+ if(!provider0_low || !provider0_up) {
+ goto fail;
+ }
+ Curl_strntolower(provider0_low, tmp0, len);
+ provider0_low[len] = '\0';
+ Curl_strntoupper(provider0_up, tmp0, len);
+ provider0_up[len] = '\0';
+
+ if(tmp1) {
+ tmp0 = tmp1 + 1;
+ tmp1 = strchr(tmp0, ':');
+ len = tmp1 ? (size_t)(tmp1 - tmp0) : strlen(tmp0);
+ if(len < 1) {
+ infof(data, "second provider can't be empty\n");
+ ret = CURLE_BAD_FUNCTION_ARGUMENT;
+ goto fail;
+ }
+ provider1_low = malloc(len + 1);
+ provider1_mid = malloc(len + 1);
+ if(!provider1_low || !provider1_mid) {
+ goto fail;
+ }
+ Curl_strntolower(provider1_low, tmp0, len);
+ provider1_low[len] = '\0';
+ Curl_strntolower(provider1_mid, tmp0, len);
+ provider1_mid[0] = Curl_raw_toupper(provider1_mid[0]);
+ provider1_mid[len] = '\0';
+
+ if(tmp1) {
+ tmp0 = tmp1 + 1;
+ tmp1 = strchr(tmp0, ':');
+ len = tmp1 ? (size_t)(tmp1 - tmp0) : strlen(tmp0);
+ if(len < 1) {
+ infof(data, "region can't be empty\n");
+ ret = CURLE_BAD_FUNCTION_ARGUMENT;
+ goto fail;
+ }
+ region = Curl_memdup(tmp0, len + 1);
+ if(!region) {
+ goto fail;
+ }
+ region[len] = '\0';
+
+ if(tmp1) {
+ tmp0 = tmp1 + 1;
+ service = strdup(tmp0);
+ if(!service) {
+ goto fail;
+ }
+ if(strlen(service) < 1) {
+ infof(data, "service can't be empty\n");
+ ret = CURLE_BAD_FUNCTION_ARGUMENT;
+ goto fail;
+ }
+ }
+ }
+ }
+ else {
+ provider1_low = Curl_memdup(provider0_low, len + 1);
+ provider1_mid = Curl_memdup(provider0_low, len + 1);
+ if(!provider1_low || !provider1_mid) {
+ goto fail;
+ }
+ provider1_mid[0] = Curl_raw_toupper(provider1_mid[0]);
+ }
+
+ if(!service) {
+ tmp0 = hostname;
+ tmp1 = strchr(tmp0, '.');
+ len = tmp1 - tmp0;
+ if(!tmp1 || len < 1) {
+ infof(data, "service missing in parameters or hostname\n");
+ ret = CURLE_URL_MALFORMAT;
+ goto fail;
+ }
+ service = Curl_memdup(tmp0, len + 1);
+ if(!service) {
+ goto fail;
+ }
+ service[len] = '\0';
+
+ if(!region) {
+ tmp0 = tmp1 + 1;
+ tmp1 = strchr(tmp0, '.');
+ len = tmp1 - tmp0;
+ if(!tmp1 || len < 1) {
+ infof(data, "region missing in parameters or hostname\n");
+ ret = CURLE_URL_MALFORMAT;
+ goto fail;
+ }
+ region = Curl_memdup(tmp0, len + 1);
+ if(!region) {
+ goto fail;
+ }
+ region[len] = '\0';
+ }
+ }
+
+#ifdef DEBUGBUILD
+ force_timestamp = getenv("CURL_FORCETIME");
+ if(force_timestamp)
+ clock = 0;
+ else
+ time(&clock);
+#else
+ time(&clock);
+#endif
+ ret = Curl_gmtime(clock, &tm);
+ if(ret != CURLE_OK) {
+ goto fail;
+ }
+ if(!strftime(timestamp, sizeof(timestamp), "%Y%m%dT%H%M%SZ", &tm)) {
+ goto fail;
+ }
+ memcpy(date, timestamp, sizeof(date));
+ date[sizeof(date) - 1] = 0;
+
+ if(content_type) {
+ content_type = strchr(content_type, ':');
+ if(!content_type) {
+ ret = CURLE_FAILED_INIT;
+ goto fail;
+ }
+ content_type++;
+ /* Skip whitespace now */
+ while(*content_type == ' ' || *content_type == '\t')
+ ++content_type;
+
+ canonical_headers = curl_maprintf("content-type:%s\n"
+ "host:%s\n"
+ "x-%s-date:%s\n",
+ content_type,
+ hostname,
+ provider1_low, timestamp);
+ signed_headers = curl_maprintf("content-type;host;x-%s-date",
+ provider1_low);
+ }
+ else {
+ canonical_headers = curl_maprintf("host:%s\n"
+ "x-%s-date:%s\n",
+ hostname,
+ provider1_low, timestamp);
+ signed_headers = curl_maprintf("host;x-%s-date", provider1_low);
+ }
+
+ if(!canonical_headers || !signed_headers) {
+ goto fail;
+ }
+
+ Curl_sha256it(sha_hash,
+ (const unsigned char *) post_data, strlen(post_data));
+ sha256_to_hex(sha_hex, sha_hash, sizeof(sha_hex));
+
+ Curl_http_method(data, conn, &method, &httpreq);
+
+ canonical_request =
+ curl_maprintf("%s\n" /* HTTPRequestMethod */
+ "%s\n" /* CanonicalURI */
+ "%s\n" /* CanonicalQueryString */
+ "%s\n" /* CanonicalHeaders */
+ "%s\n" /* SignedHeaders */
+ "%s", /* HashedRequestPayload in hex */
+ method,
+ data->state.up.path,
+ data->state.up.query ? data->state.up.query : "",
+ canonical_headers,
+ signed_headers,
+ sha_hex);
+ if(!canonical_request) {
+ goto fail;
+ }
+
+ request_type = curl_maprintf("%s4_request", provider0_low);
+ if(!request_type) {
+ goto fail;
+ }
+
+ credential_scope = curl_maprintf("%s/%s/%s/%s",
+ date, region, service, request_type);
+ if(!credential_scope) {
+ goto fail;
+ }
+
+ Curl_sha256it(sha_hash, (unsigned char *) canonical_request,
+ strlen(canonical_request));
+ sha256_to_hex(sha_hex, sha_hash, sizeof(sha_hex));
+
+ /*
+ * Google allow to use rsa key instead of HMAC, so this code might change
+ * In the furure, but for now we support only HMAC version
+ */
+ str_to_sign = curl_maprintf("%s4-HMAC-SHA256\n" /* Algorithm */
+ "%s\n" /* RequestDateTime */
+ "%s\n" /* CredentialScope */
+ "%s", /* HashedCanonicalRequest in hex */
+ provider0_up,
+ timestamp,
+ credential_scope,
+ sha_hex);
+ if(!str_to_sign) {
+ goto fail;
+ }
+
+ secret = curl_maprintf("%s4%s", provider0_up, passwd);
+ if(!secret) {
+ goto fail;
+ }
+
+ HMAC_SHA256(secret, strlen(secret),
+ date, strlen(date), tmp_sign0);
+ HMAC_SHA256(tmp_sign0, sizeof(tmp_sign0),
+ region, strlen(region), tmp_sign1);
+ HMAC_SHA256(tmp_sign1, sizeof(tmp_sign1),
+ service, strlen(service), tmp_sign0);
+ HMAC_SHA256(tmp_sign0, sizeof(tmp_sign0),
+ request_type, strlen(request_type), tmp_sign1);
+ HMAC_SHA256(tmp_sign1, sizeof(tmp_sign1),
+ str_to_sign, strlen(str_to_sign), tmp_sign0);
+
+ sha256_to_hex(sha_hex, tmp_sign0, sizeof(sha_hex));
+
+ auth_headers = curl_maprintf("Authorization: %s4-HMAC-SHA256 "
+ "Credential=%s/%s, "
+ "SignedHeaders=%s, "
+ "Signature=%s\r\n"
+ "X-%s-Date: %s\r\n",
+ provider0_up,
+ user,
+ credential_scope,
+ signed_headers,
+ sha_hex,
+ provider1_mid,
+ timestamp);
+ if(!auth_headers) {
+ goto fail;
+ }
+
+ Curl_safefree(data->state.aptr.userpwd);
+ data->state.aptr.userpwd = auth_headers;
+ data->state.authhost.done = TRUE;
+ ret = CURLE_OK;
+
+fail:
+ free(provider0_low);
+ free(provider0_up);
+ free(provider1_low);
+ free(provider1_mid);
+ free(region);
+ free(service);
+ free(canonical_headers);
+ free(signed_headers);
+ free(canonical_request);
+ free(request_type);
+ free(credential_scope);
+ free(str_to_sign);
+ free(secret);
+ return ret;
+}
+
+#endif /* !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_CRYPTO_AUTH) */
diff --git a/Utilities/cmcurl/lib/http_aws_sigv4.h b/Utilities/cmcurl/lib/http_aws_sigv4.h
new file mode 100644
index 000000000..886b31440
--- /dev/null
+++ b/Utilities/cmcurl/lib/http_aws_sigv4.h
@@ -0,0 +1,29 @@
+#ifndef HEADER_CURL_HTTP_AWS_SIGV4_H
+#define HEADER_CURL_HTTP_AWS_SIGV4_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "curl_setup.h"
+
+/* this is for creating aws_sigv4 header output */
+CURLcode Curl_output_aws_sigv4(struct Curl_easy *data, bool proxy);
+
+#endif /* HEADER_CURL_HTTP_AWS_SIGV4_H */
diff --git a/Utilities/cmcurl/lib/http_chunks.c b/Utilities/cmcurl/lib/http_chunks.c
index 767f806c8..beb969588 100644
--- a/Utilities/cmcurl/lib/http_chunks.c
+++ b/Utilities/cmcurl/lib/http_chunks.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -77,21 +77,21 @@
#ifdef CURL_DOES_CONVERSIONS
/* Check for an ASCII hex digit.
We avoid the use of ISXDIGIT to accommodate non-ASCII hosts. */
-static bool Curl_isxdigit_ascii(char digit)
+static bool isxdigit_ascii(char digit)
{
return (digit >= 0x30 && digit <= 0x39) /* 0-9 */
- || (digit >= 0x41 && digit <= 0x46) /* A-F */
- || (digit >= 0x61 && digit <= 0x66); /* a-f */
+ || (digit >= 0x41 && digit <= 0x46) /* A-F */
+ || (digit >= 0x61 && digit <= 0x66); /* a-f */
}
#else
-#define Curl_isxdigit_ascii(x) Curl_isxdigit(x)
+#define isxdigit_ascii(x) Curl_isxdigit(x)
#endif
-void Curl_httpchunk_init(struct connectdata *conn)
+void Curl_httpchunk_init(struct Curl_easy *data)
{
+ struct connectdata *conn = data->conn;
struct Curl_chunker *chunk = &conn->chunk;
chunk->hexindex = 0; /* start at 0 */
- chunk->dataleft = 0; /* no data left yet! */
chunk->state = CHUNK_HEX; /* we get hex first! */
Curl_dyn_init(&conn->trailer, DYN_H1_TRAILER);
}
@@ -107,14 +107,14 @@ void Curl_httpchunk_init(struct connectdata *conn)
* This function always uses ASCII hex values to accommodate non-ASCII hosts.
* For example, 0x0d and 0x0a are used instead of '\r' and '\n'.
*/
-CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
+CHUNKcode Curl_httpchunk_read(struct Curl_easy *data,
char *datap,
ssize_t datalen,
ssize_t *wrotep,
CURLcode *extrap)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
+ struct connectdata *conn = data->conn;
struct Curl_chunker *ch = &conn->chunk;
struct SingleRequest *k = &data->req;
size_t piece;
@@ -126,7 +126,7 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
/* the original data is written to the client, but we go on with the
chunk read process, to properly calculate the content length*/
if(data->set.http_te_skip && !k->ignorebody) {
- result = Curl_client_write(conn, CLIENTWRITE_BODY, datap, datalen);
+ result = Curl_client_write(data, CLIENTWRITE_BODY, datap, datalen);
if(result) {
*extrap = result;
return CHUNKE_PASSTHRU_ERROR;
@@ -136,8 +136,8 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
while(length) {
switch(ch->state) {
case CHUNK_HEX:
- if(Curl_isxdigit_ascii(*datap)) {
- if(ch->hexindex < MAXNUM_SIZE) {
+ if(isxdigit_ascii(*datap)) {
+ if(ch->hexindex < CHUNK_MAXNUM_LEN) {
ch->hexbuffer[ch->hexindex] = *datap;
datap++;
length--;
@@ -158,8 +158,7 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
ch->hexbuffer[ch->hexindex] = 0;
/* convert to host encoding before calling strtoul */
- result = Curl_convert_from_network(conn->data, ch->hexbuffer,
- ch->hexindex);
+ result = Curl_convert_from_network(data, ch->hexbuffer, ch->hexindex);
if(result) {
/* Curl_convert_from_network calls failf if unsuccessful */
/* Treat it as a bad hex character */
@@ -194,11 +193,11 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
piece = curlx_sotouz((ch->datasize >= length)?length:ch->datasize);
/* Write the data portion available */
- if(!conn->data->set.http_te_skip && !k->ignorebody) {
- if(!conn->data->set.http_ce_skip && k->writer_stack)
- result = Curl_unencode_write(conn, k->writer_stack, datap, piece);
+ if(!data->set.http_te_skip && !k->ignorebody) {
+ if(!data->set.http_ce_skip && k->writer_stack)
+ result = Curl_unencode_write(data, k->writer_stack, datap, piece);
else
- result = Curl_client_write(conn, CLIENTWRITE_BODY, datap, piece);
+ result = Curl_client_write(data, CLIENTWRITE_BODY, datap, piece);
if(result) {
*extrap = result;
@@ -219,7 +218,7 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
case CHUNK_POSTLF:
if(*datap == 0x0a) {
/* The last one before we go back to hex state and start all over. */
- Curl_httpchunk_init(conn); /* sets state back to CHUNK_HEX */
+ Curl_httpchunk_init(data); /* sets state back to CHUNK_HEX */
}
else if(*datap != 0x0d)
return CHUNKE_BAD_CHUNK;
@@ -242,14 +241,14 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
tr = Curl_dyn_ptr(&conn->trailer);
trlen = Curl_dyn_len(&conn->trailer);
/* Convert to host encoding before calling Curl_client_write */
- result = Curl_convert_from_network(conn->data, tr, trlen);
+ result = Curl_convert_from_network(data, tr, trlen);
if(result)
/* Curl_convert_from_network calls failf if unsuccessful */
/* Treat it as a bad chunk */
return CHUNKE_BAD_CHUNK;
if(!data->set.http_te_skip) {
- result = Curl_client_write(conn, CLIENTWRITE_HEADER, tr, trlen);
+ result = Curl_client_write(data, CLIENTWRITE_HEADER, tr, trlen);
if(result) {
*extrap = result;
return CHUNKE_PASSTHRU_ERROR;
@@ -309,7 +308,7 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
/* Record the length of any data left in the end of the buffer
even if there's no more chunks to read */
- ch->dataleft = curlx_sotouz(length);
+ ch->datasize = curlx_sotouz(length);
return CHUNKE_STOP; /* return stop */
}
diff --git a/Utilities/cmcurl/lib/http_chunks.h b/Utilities/cmcurl/lib/http_chunks.h
index 8f4a33c8e..741a9a3bc 100644
--- a/Utilities/cmcurl/lib/http_chunks.h
+++ b/Utilities/cmcurl/lib/http_chunks.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -26,10 +26,10 @@ struct connectdata;
/*
* The longest possible hexadecimal number we support in a chunked transfer.
- * Weird enough, RFC2616 doesn't set a maximum size! Since we use strtoul()
- * to convert it, we "only" support 2^32 bytes chunk data.
+ * Neither RFC2616 nor the later HTTP specs define a maximum chunk size.
+ * For 64 bit curl_off_t we support 16 digits. For 32 bit, 8 digits.
*/
-#define MAXNUM_SIZE 16
+#define CHUNK_MAXNUM_LEN (SIZEOF_CURL_OFF_T * 2)
typedef enum {
/* await and buffer all hexadecimal digits until we get one that isn't a
@@ -48,7 +48,7 @@ typedef enum {
big deal. */
CHUNK_POSTLF,
- /* Used to mark that we're out of the game. NOTE: that there's a 'dataleft'
+ /* Used to mark that we're out of the game. NOTE: that there's a 'datasize'
field in the struct that will tell how many bytes that were not passed to
the client in the end of the last buffer! */
CHUNK_STOP,
@@ -83,16 +83,15 @@ typedef enum {
const char *Curl_chunked_strerror(CHUNKcode code);
struct Curl_chunker {
- char hexbuffer[ MAXNUM_SIZE + 1];
- int hexindex;
- ChunkyState state;
curl_off_t datasize;
- size_t dataleft; /* untouched data amount at the end of the last buffer */
+ ChunkyState state;
+ unsigned char hexindex;
+ char hexbuffer[ CHUNK_MAXNUM_LEN + 1]; /* +1 for null-terminator */
};
/* The following functions are defined in http_chunks.c */
-void Curl_httpchunk_init(struct connectdata *conn);
-CHUNKcode Curl_httpchunk_read(struct connectdata *conn, char *datap,
+void Curl_httpchunk_init(struct Curl_easy *data);
+CHUNKcode Curl_httpchunk_read(struct Curl_easy *data, char *datap,
ssize_t length, ssize_t *wrote,
CURLcode *passthru);
diff --git a/Utilities/cmcurl/lib/http_digest.c b/Utilities/cmcurl/lib/http_digest.c
index b06dc0d82..596b215db 100644
--- a/Utilities/cmcurl/lib/http_digest.c
+++ b/Utilities/cmcurl/lib/http_digest.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -41,13 +41,11 @@ Proxy-Authenticate: Digest realm="testrealm", nonce="1053604598"
*/
-CURLcode Curl_input_digest(struct connectdata *conn,
+CURLcode Curl_input_digest(struct Curl_easy *data,
bool proxy,
const char *header) /* rest of the *-authenticate:
header */
{
- struct Curl_easy *data = conn->data;
-
/* Point to the correct struct with this */
struct digestdata *digest;
@@ -68,13 +66,13 @@ CURLcode Curl_input_digest(struct connectdata *conn,
return Curl_auth_decode_digest_http_message(header, digest);
}
-CURLcode Curl_output_digest(struct connectdata *conn,
+CURLcode Curl_output_digest(struct Curl_easy *data,
+ struct connectdata *conn,
bool proxy,
const unsigned char *request,
const unsigned char *uripath)
{
CURLcode result;
- struct Curl_easy *data = conn->data;
unsigned char *path = NULL;
char *tmp = NULL;
char *response;
diff --git a/Utilities/cmcurl/lib/http_digest.h b/Utilities/cmcurl/lib/http_digest.h
index 96e39a7dc..106caa7c4 100644
--- a/Utilities/cmcurl/lib/http_digest.h
+++ b/Utilities/cmcurl/lib/http_digest.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -26,11 +26,12 @@
#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_CRYPTO_AUTH)
/* this is for digest header input */
-CURLcode Curl_input_digest(struct connectdata *conn,
+CURLcode Curl_input_digest(struct Curl_easy *data,
bool proxy, const char *header);
/* this is for creating digest header output */
-CURLcode Curl_output_digest(struct connectdata *conn,
+CURLcode Curl_output_digest(struct Curl_easy *data,
+ struct connectdata *conn,
bool proxy,
const unsigned char *request,
const unsigned char *uripath);
diff --git a/Utilities/cmcurl/lib/http_negotiate.c b/Utilities/cmcurl/lib/http_negotiate.c
index 0a19ec2af..d759748f2 100644
--- a/Utilities/cmcurl/lib/http_negotiate.c
+++ b/Utilities/cmcurl/lib/http_negotiate.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -34,11 +34,10 @@
#include "curl_memory.h"
#include "memdebug.h"
-CURLcode Curl_input_negotiate(struct connectdata *conn, bool proxy,
- const char *header)
+CURLcode Curl_input_negotiate(struct Curl_easy *data, struct connectdata *conn,
+ bool proxy, const char *header)
{
CURLcode result;
- struct Curl_easy *data = conn->data;
size_t len;
/* Point to the username, password, service and host */
@@ -90,7 +89,7 @@ CURLcode Curl_input_negotiate(struct connectdata *conn, bool proxy,
neg_ctx->havenegdata = len != 0;
if(!len) {
if(state == GSS_AUTHSUCC) {
- infof(conn->data, "Negotiate auth restarted\n");
+ infof(data, "Negotiate auth restarted\n");
Curl_http_auth_cleanup_negotiate(conn);
}
else if(state != GSS_AUTHNONE) {
@@ -116,15 +115,14 @@ CURLcode Curl_input_negotiate(struct connectdata *conn, bool proxy,
return result;
}
-CURLcode Curl_output_negotiate(struct connectdata *conn, bool proxy)
+CURLcode Curl_output_negotiate(struct Curl_easy *data,
+ struct connectdata *conn, bool proxy)
{
struct negotiatedata *neg_ctx = proxy ? &conn->proxyneg :
&conn->negotiate;
- struct auth *authp = proxy ? &conn->data->state.authproxy :
- &conn->data->state.authhost;
+ struct auth *authp = proxy ? &data->state.authproxy : &data->state.authhost;
curlnegotiate *state = proxy ? &conn->proxy_negotiate_state :
&conn->http_negotiate_state;
- struct Curl_easy *data = conn->data;
char *base64 = NULL;
size_t len = 0;
char *userp;
@@ -147,12 +145,12 @@ CURLcode Curl_output_negotiate(struct connectdata *conn, bool proxy)
(*state != GSS_AUTHDONE && *state != GSS_AUTHSUCC)) {
if(neg_ctx->noauthpersist && *state == GSS_AUTHSUCC) {
- infof(conn->data, "Curl_output_negotiate, "
+ infof(data, "Curl_output_negotiate, "
"no persistent authentication: cleanup existing context");
Curl_http_auth_cleanup_negotiate(conn);
}
if(!neg_ctx->context) {
- result = Curl_input_negotiate(conn, proxy, "Negotiate");
+ result = Curl_input_negotiate(data, conn, proxy, "Negotiate");
if(result == CURLE_AUTH_ERROR) {
/* negotiate auth failed, let's continue unauthenticated to stay
* compatible with the behavior before curl-7_64_0-158-g6c6035532 */
@@ -163,8 +161,7 @@ CURLcode Curl_output_negotiate(struct connectdata *conn, bool proxy)
return result;
}
- result = Curl_auth_create_spnego_message(conn->data,
- neg_ctx, &base64, &len);
+ result = Curl_auth_create_spnego_message(data, neg_ctx, &base64, &len);
if(result)
return result;
diff --git a/Utilities/cmcurl/lib/http_negotiate.h b/Utilities/cmcurl/lib/http_negotiate.h
index a737f6f78..2640a3ee0 100644
--- a/Utilities/cmcurl/lib/http_negotiate.h
+++ b/Utilities/cmcurl/lib/http_negotiate.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -25,11 +25,12 @@
#if !defined(CURL_DISABLE_HTTP) && defined(USE_SPNEGO)
/* this is for Negotiate header input */
-CURLcode Curl_input_negotiate(struct connectdata *conn, bool proxy,
- const char *header);
+CURLcode Curl_input_negotiate(struct Curl_easy *data, struct connectdata *conn,
+ bool proxy, const char *header);
/* this is for creating Negotiate header output */
-CURLcode Curl_output_negotiate(struct connectdata *conn, bool proxy);
+CURLcode Curl_output_negotiate(struct Curl_easy *data,
+ struct connectdata *conn, bool proxy);
void Curl_http_auth_cleanup_negotiate(struct connectdata *conn);
diff --git a/Utilities/cmcurl/lib/http_ntlm.c b/Utilities/cmcurl/lib/http_ntlm.c
index cab543c75..6cb829edf 100644
--- a/Utilities/cmcurl/lib/http_ntlm.c
+++ b/Utilities/cmcurl/lib/http_ntlm.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -59,7 +59,7 @@
# define DEBUG_OUT(x) Curl_nop_stmt
#endif
-CURLcode Curl_input_ntlm(struct connectdata *conn,
+CURLcode Curl_input_ntlm(struct Curl_easy *data,
bool proxy, /* if proxy or not */
const char *header) /* rest of the www-authenticate:
header */
@@ -68,6 +68,7 @@ CURLcode Curl_input_ntlm(struct connectdata *conn,
struct ntlmdata *ntlm;
curlntlm *state;
CURLcode result = CURLE_OK;
+ struct connectdata *conn = data->conn;
ntlm = proxy ? &conn->proxyntlm : &conn->ntlm;
state = proxy ? &conn->proxy_ntlm_state : &conn->http_ntlm_state;
@@ -79,7 +80,7 @@ CURLcode Curl_input_ntlm(struct connectdata *conn,
header++;
if(*header) {
- result = Curl_auth_decode_ntlm_type2_message(conn->data, header, ntlm);
+ result = Curl_auth_decode_ntlm_type2_message(data, header, ntlm);
if(result)
return result;
@@ -87,17 +88,17 @@ CURLcode Curl_input_ntlm(struct connectdata *conn,
}
else {
if(*state == NTLMSTATE_LAST) {
- infof(conn->data, "NTLM auth restarted\n");
+ infof(data, "NTLM auth restarted\n");
Curl_http_auth_cleanup_ntlm(conn);
}
else if(*state == NTLMSTATE_TYPE3) {
- infof(conn->data, "NTLM handshake rejected\n");
+ infof(data, "NTLM handshake rejected\n");
Curl_http_auth_cleanup_ntlm(conn);
*state = NTLMSTATE_NONE;
return CURLE_REMOTE_ACCESS_DENIED;
}
else if(*state >= NTLMSTATE_TYPE1) {
- infof(conn->data, "NTLM handshake failure (internal error)\n");
+ infof(data, "NTLM handshake failure (internal error)\n");
return CURLE_REMOTE_ACCESS_DENIED;
}
@@ -111,7 +112,7 @@ CURLcode Curl_input_ntlm(struct connectdata *conn,
/*
* This is for creating ntlm header output
*/
-CURLcode Curl_output_ntlm(struct connectdata *conn, bool proxy)
+CURLcode Curl_output_ntlm(struct Curl_easy *data, bool proxy)
{
char *base64 = NULL;
size_t len = 0;
@@ -131,8 +132,7 @@ CURLcode Curl_output_ntlm(struct connectdata *conn, bool proxy)
struct ntlmdata *ntlm;
curlntlm *state;
struct auth *authp;
- struct Curl_easy *data = conn->data;
-
+ struct connectdata *conn = data->conn;
DEBUGASSERT(conn);
DEBUGASSERT(data);
@@ -142,12 +142,12 @@ CURLcode Curl_output_ntlm(struct connectdata *conn, bool proxy)
allocuserpwd = &data->state.aptr.proxyuserpwd;
userp = conn->http_proxy.user;
passwdp = conn->http_proxy.passwd;
- service = conn->data->set.str[STRING_PROXY_SERVICE_NAME] ?
- conn->data->set.str[STRING_PROXY_SERVICE_NAME] : "HTTP";
+ service = data->set.str[STRING_PROXY_SERVICE_NAME] ?
+ data->set.str[STRING_PROXY_SERVICE_NAME] : "HTTP";
hostname = conn->http_proxy.host.name;
ntlm = &conn->proxyntlm;
state = &conn->proxy_ntlm_state;
- authp = &conn->data->state.authproxy;
+ authp = &data->state.authproxy;
#else
return CURLE_NOT_BUILT_IN;
#endif
@@ -156,12 +156,12 @@ CURLcode Curl_output_ntlm(struct connectdata *conn, bool proxy)
allocuserpwd = &data->state.aptr.userpwd;
userp = conn->user;
passwdp = conn->passwd;
- service = conn->data->set.str[STRING_SERVICE_NAME] ?
- conn->data->set.str[STRING_SERVICE_NAME] : "HTTP";
+ service = data->set.str[STRING_SERVICE_NAME] ?
+ data->set.str[STRING_SERVICE_NAME] : "HTTP";
hostname = conn->host.name;
ntlm = &conn->ntlm;
state = &conn->http_ntlm_state;
- authp = &conn->data->state.authhost;
+ authp = &data->state.authhost;
}
authp->done = FALSE;
@@ -188,7 +188,7 @@ CURLcode Curl_output_ntlm(struct connectdata *conn, bool proxy)
case NTLMSTATE_TYPE1:
default: /* for the weird cases we (re)start here */
/* Create a type-1 message */
- result = Curl_auth_create_ntlm_type1_message(conn->data, userp, passwdp,
+ result = Curl_auth_create_ntlm_type1_message(data, userp, passwdp,
service, hostname,
ntlm, &base64,
&len);
@@ -210,7 +210,7 @@ CURLcode Curl_output_ntlm(struct connectdata *conn, bool proxy)
case NTLMSTATE_TYPE2:
/* We already received the type-2 message, create a type-3 message */
- result = Curl_auth_create_ntlm_type3_message(conn->data, userp, passwdp,
+ result = Curl_auth_create_ntlm_type3_message(data, userp, passwdp,
ntlm, &base64, &len);
if(result)
return result;
diff --git a/Utilities/cmcurl/lib/http_ntlm.h b/Utilities/cmcurl/lib/http_ntlm.h
index 3ebdf979e..5b4fa00ba 100644
--- a/Utilities/cmcurl/lib/http_ntlm.h
+++ b/Utilities/cmcurl/lib/http_ntlm.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -27,11 +27,11 @@
#if !defined(CURL_DISABLE_HTTP) && defined(USE_NTLM)
/* this is for ntlm header input */
-CURLcode Curl_input_ntlm(struct connectdata *conn, bool proxy,
+CURLcode Curl_input_ntlm(struct Curl_easy *data, bool proxy,
const char *header);
/* this is for creating ntlm header output */
-CURLcode Curl_output_ntlm(struct connectdata *conn, bool proxy);
+CURLcode Curl_output_ntlm(struct Curl_easy *data, bool proxy);
void Curl_http_auth_cleanup_ntlm(struct connectdata *conn);
diff --git a/Utilities/cmcurl/lib/http_proxy.c b/Utilities/cmcurl/lib/http_proxy.c
index f188cbfc6..a03a27fdc 100644
--- a/Utilities/cmcurl/lib/http_proxy.c
+++ b/Utilities/cmcurl/lib/http_proxy.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -27,6 +27,9 @@
#if !defined(CURL_DISABLE_PROXY) && !defined(CURL_DISABLE_HTTP)
#include <curl/curl.h>
+#ifdef USE_HYPER
+#include <hyper.h>
+#endif
#include "sendf.h"
#include "http.h"
#include "url.h"
@@ -47,15 +50,16 @@
* proxy_ssl_connected connection bit when complete. Can be
* called multiple times.
*/
-static CURLcode https_proxy_connect(struct connectdata *conn, int sockindex)
+static CURLcode https_proxy_connect(struct Curl_easy *data, int sockindex)
{
#ifdef USE_SSL
+ struct connectdata *conn = data->conn;
CURLcode result = CURLE_OK;
DEBUGASSERT(conn->http_proxy.proxytype == CURLPROXY_HTTPS);
if(!conn->bits.proxy_ssl_connected[sockindex]) {
/* perform SSL initialization for this socket */
result =
- Curl_ssl_connect_nonblocking(conn, sockindex,
+ Curl_ssl_connect_nonblocking(data, conn, sockindex,
&conn->bits.proxy_ssl_connected[sockindex]);
if(result)
/* a failed connection is marked for closure to prevent (bad) re-use or
@@ -64,17 +68,17 @@ static CURLcode https_proxy_connect(struct connectdata *conn, int sockindex)
}
return result;
#else
- (void) conn;
+ (void) data;
(void) sockindex;
return CURLE_NOT_BUILT_IN;
#endif
}
-CURLcode Curl_proxy_connect(struct connectdata *conn, int sockindex)
+CURLcode Curl_proxy_connect(struct Curl_easy *data, int sockindex)
{
- struct Curl_easy *data = conn->data;
+ struct connectdata *conn = data->conn;
if(conn->http_proxy.proxytype == CURLPROXY_HTTPS) {
- const CURLcode result = https_proxy_connect(conn, sockindex);
+ const CURLcode result = https_proxy_connect(data, sockindex);
if(result)
return result;
if(!conn->bits.proxy_ssl_connected[sockindex])
@@ -102,9 +106,9 @@ CURLcode Curl_proxy_connect(struct connectdata *conn, int sockindex)
* This function might be called several times in the multi interface case
* if the proxy's CONNECT response is not instant.
*/
- prot_save = conn->data->req.protop;
+ prot_save = data->req.p.http;
memset(&http_proxy, 0, sizeof(http_proxy));
- conn->data->req.protop = &http_proxy;
+ data->req.p.http = &http_proxy;
connkeep(conn, "HTTP proxy CONNECT");
/* for the secondary socket (FTP), use the "connect to host"
@@ -124,8 +128,8 @@ CURLcode Curl_proxy_connect(struct connectdata *conn, int sockindex)
remote_port = conn->conn_to_port;
else
remote_port = conn->remote_port;
- result = Curl_proxyCONNECT(conn, sockindex, hostname, remote_port);
- conn->data->req.protop = prot_save;
+ result = Curl_proxyCONNECT(data, sockindex, hostname, remote_port);
+ data->req.p.http = prot_save;
if(CURLE_OK != result)
return result;
Curl_safefree(data->state.aptr.proxyuserpwd);
@@ -149,15 +153,16 @@ bool Curl_connect_ongoing(struct connectdata *conn)
(conn->connect_state->tunnel_state != TUNNEL_COMPLETE);
}
-static CURLcode connect_init(struct connectdata *conn, bool reinit)
+static CURLcode connect_init(struct Curl_easy *data, bool reinit)
{
struct http_connect_state *s;
+ struct connectdata *conn = data->conn;
if(!reinit) {
DEBUGASSERT(!conn->connect_state);
s = calloc(1, sizeof(struct http_connect_state));
if(!s)
return CURLE_OUT_OF_MEMORY;
- infof(conn->data, "allocate connect buffer!\n");
+ infof(data, "allocate connect buffer!\n");
conn->connect_state = s;
Curl_dyn_init(&s->rcvbuf, DYN_PROXY_CONNECT_HEADERS);
}
@@ -167,29 +172,63 @@ static CURLcode connect_init(struct connectdata *conn, bool reinit)
Curl_dyn_reset(&s->rcvbuf);
}
s->tunnel_state = TUNNEL_INIT;
- s->keepon = TRUE;
+ s->keepon = KEEPON_CONNECT;
s->cl = 0;
s->close_connection = FALSE;
return CURLE_OK;
}
-static void connect_done(struct connectdata *conn)
+static void connect_done(struct Curl_easy *data)
{
+ struct connectdata *conn = data->conn;
struct http_connect_state *s = conn->connect_state;
s->tunnel_state = TUNNEL_COMPLETE;
Curl_dyn_free(&s->rcvbuf);
- infof(conn->data, "CONNECT phase completed!\n");
+ infof(data, "CONNECT phase completed!\n");
+}
+
+static CURLcode CONNECT_host(struct Curl_easy *data,
+ struct connectdata *conn,
+ const char *hostname,
+ int remote_port,
+ char **connecthostp,
+ char **hostp)
+{
+ char *hostheader; /* for CONNECT */
+ char *host = NULL; /* Host: */
+ bool ipv6_ip = conn->bits.ipv6_ip;
+
+ /* the hostname may be different */
+ if(hostname != conn->host.name)
+ ipv6_ip = (strchr(hostname, ':') != NULL);
+ hostheader = /* host:port with IPv6 support */
+ aprintf("%s%s%s:%d", ipv6_ip?"[":"", hostname, ipv6_ip?"]":"",
+ remote_port);
+ if(!hostheader)
+ return CURLE_OUT_OF_MEMORY;
+
+ if(!Curl_checkProxyheaders(data, conn, "Host")) {
+ host = aprintf("Host: %s\r\n", hostheader);
+ if(!host) {
+ free(hostheader);
+ return CURLE_OUT_OF_MEMORY;
+ }
+ }
+ *connecthostp = hostheader;
+ *hostp = host;
+ return CURLE_OK;
}
-static CURLcode CONNECT(struct connectdata *conn,
+static CURLcode CONNECT(struct Curl_easy *data,
int sockindex,
const char *hostname,
int remote_port)
+#ifndef USE_HYPER
{
int subversion = 0;
- struct Curl_easy *data = conn->data;
struct SingleRequest *k = &data->req;
CURLcode result;
+ struct connectdata *conn = data->conn;
curl_socket_t tunnelsocket = conn->sock[sockindex];
struct http_connect_state *s = conn->connect_state;
char *linep;
@@ -207,8 +246,9 @@ static CURLcode CONNECT(struct connectdata *conn,
timediff_t check;
if(TUNNEL_INIT == s->tunnel_state) {
/* BEGIN CONNECT PHASE */
- char *host_port;
struct dynbuf req;
+ char *hostheader = NULL;
+ char *host = NULL;
infof(data, "Establish HTTP proxy tunnel to %s:%d\n",
hostname, remote_port);
@@ -219,50 +259,28 @@ static CURLcode CONNECT(struct connectdata *conn,
free(data->req.newurl);
data->req.newurl = NULL;
- host_port = aprintf("%s:%d", hostname, remote_port);
- if(!host_port)
- return CURLE_OUT_OF_MEMORY;
-
/* initialize a dynamic send-buffer */
Curl_dyn_init(&req, DYN_HTTP_REQUEST);
- /* Setup the proxy-authorization header, if any */
- result = Curl_http_output_auth(conn, "CONNECT", host_port, TRUE);
+ result = CONNECT_host(data, conn,
+ hostname, remote_port, &hostheader, &host);
+ if(result)
+ return result;
- free(host_port);
+ /* Setup the proxy-authorization header, if any */
+ result = Curl_http_output_auth(data, conn, "CONNECT", HTTPREQ_GET,
+ hostheader, TRUE);
if(!result) {
- char *host = NULL;
const char *proxyconn = "";
const char *useragent = "";
const char *httpv =
(conn->http_proxy.proxytype == CURLPROXY_HTTP_1_0) ? "1.0" : "1.1";
- bool ipv6_ip = conn->bits.ipv6_ip;
- char *hostheader;
-
- /* the hostname may be different */
- if(hostname != conn->host.name)
- ipv6_ip = (strchr(hostname, ':') != NULL);
- hostheader = /* host:port with IPv6 support */
- aprintf("%s%s%s:%d", ipv6_ip?"[":"", hostname, ipv6_ip?"]":"",
- remote_port);
- if(!hostheader) {
- Curl_dyn_free(&req);
- return CURLE_OUT_OF_MEMORY;
- }
- if(!Curl_checkProxyheaders(conn, "Host")) {
- host = aprintf("Host: %s\r\n", hostheader);
- if(!host) {
- free(hostheader);
- Curl_dyn_free(&req);
- return CURLE_OUT_OF_MEMORY;
- }
- }
- if(!Curl_checkProxyheaders(conn, "Proxy-Connection"))
+ if(!Curl_checkProxyheaders(data, conn, "Proxy-Connection"))
proxyconn = "Proxy-Connection: Keep-Alive\r\n";
- if(!Curl_checkProxyheaders(conn, "User-Agent") &&
+ if(!Curl_checkProxyheaders(data, conn, "User-Agent") &&
data->set.str[STRING_USERAGENT])
useragent = data->state.aptr.uagent;
@@ -281,12 +299,8 @@ static CURLcode CONNECT(struct connectdata *conn,
useragent,
proxyconn);
- if(host)
- free(host);
- free(hostheader);
-
if(!result)
- result = Curl_add_custom_headers(conn, TRUE, &req);
+ result = Curl_add_custom_headers(data, TRUE, &req);
if(!result)
/* CRLF terminate the request */
@@ -295,13 +309,14 @@ static CURLcode CONNECT(struct connectdata *conn,
if(!result) {
/* Send the connect request to the proxy */
/* BLOCKING */
- result = Curl_buffer_send(&req, conn, &data->info.request_size, 0,
+ result = Curl_buffer_send(&req, data, &data->info.request_size, 0,
sockindex);
}
if(result)
failf(data, "Failed sending CONNECT to proxy");
}
-
+ free(host);
+ free(hostheader);
Curl_dyn_free(&req);
if(result)
return result;
@@ -330,16 +345,16 @@ static CURLcode CONNECT(struct connectdata *conn,
/* Read one byte at a time to avoid a race condition. Wait at most one
second before looping to ensure continuous pgrsUpdates. */
- result = Curl_read(conn, tunnelsocket, &byte, 1, &gotbytes);
+ result = Curl_read(data, tunnelsocket, &byte, 1, &gotbytes);
if(result == CURLE_AGAIN)
/* socket buffer drained, return */
return CURLE_OK;
- if(Curl_pgrsUpdate(conn))
+ if(Curl_pgrsUpdate(data))
return CURLE_ABORTED_BY_CALLBACK;
if(result) {
- s->keepon = FALSE;
+ s->keepon = KEEPON_DONE;
break;
}
else if(gotbytes <= 0) {
@@ -353,11 +368,11 @@ static CURLcode CONNECT(struct connectdata *conn,
error = SELECT_ERROR;
failf(data, "Proxy CONNECT aborted");
}
- s->keepon = FALSE;
+ s->keepon = KEEPON_DONE;
break;
}
- if(s->keepon > TRUE) {
+ if(s->keepon == KEEPON_IGNORE) {
/* This means we are currently ignoring a response-body */
if(s->cl) {
@@ -365,7 +380,7 @@ static CURLcode CONNECT(struct connectdata *conn,
and make sure to break out of the loop when we're done! */
s->cl--;
if(s->cl <= 0) {
- s->keepon = FALSE;
+ s->keepon = KEEPON_DONE;
s->tunnel_state = TUNNEL_COMPLETE;
break;
}
@@ -379,11 +394,11 @@ static CURLcode CONNECT(struct connectdata *conn,
/* now parse the chunked piece of data so that we can
properly tell when the stream ends */
- r = Curl_httpchunk_read(conn, &byte, 1, &tookcareof, &extra);
+ r = Curl_httpchunk_read(data, &byte, 1, &tookcareof, &extra);
if(r == CHUNKE_STOP) {
/* we're done reading chunks! */
infof(data, "chunk reading DONE\n");
- s->keepon = FALSE;
+ s->keepon = KEEPON_DONE;
/* we did the full CONNECT treatment, go COMPLETE */
s->tunnel_state = TUNNEL_COMPLETE;
}
@@ -410,8 +425,7 @@ static CURLcode CONNECT(struct connectdata *conn,
return result;
/* output debug if that is requested */
- if(data->set.verbose)
- Curl_debug(data, CURLINFO_HEADER_IN, linep, perline);
+ Curl_debug(data, CURLINFO_HEADER_IN, linep, perline);
if(!data->set.suppress_connect_headers) {
/* send the header to the callback */
@@ -419,13 +433,12 @@ static CURLcode CONNECT(struct connectdata *conn,
if(data->set.include_header)
writetype |= CLIENTWRITE_BODY;
- result = Curl_client_write(conn, writetype, linep, perline);
+ result = Curl_client_write(data, writetype, linep, perline);
if(result)
return result;
}
data->info.header_size += (long)perline;
- data->req.headerbytecount += (long)perline;
/* Newlines are CRLF, so the CR is ignored as the line isn't
really terminated until the LF comes. Treat a following CR
@@ -439,7 +452,7 @@ static CURLcode CONNECT(struct connectdata *conn,
/* If we get a 407 response code with content length
when we have no auth problem, we must ignore the
whole response-body */
- s->keepon = 2;
+ s->keepon = KEEPON_IGNORE;
if(s->cl) {
infof(data, "Ignore %" CURL_FORMAT_CURL_OFF_T
@@ -462,12 +475,12 @@ static CURLcode CONNECT(struct connectdata *conn,
/* now parse the chunked piece of data so that we can properly
tell when the stream ends */
- r = Curl_httpchunk_read(conn, linep + 1, 1, &gotbytes,
+ r = Curl_httpchunk_read(data, linep + 1, 1, &gotbytes,
&extra);
if(r == CHUNKE_STOP) {
/* we're done reading chunks! */
infof(data, "chunk reading DONE\n");
- s->keepon = FALSE;
+ s->keepon = KEEPON_DONE;
/* we did the full CONNECT treatment, go to COMPLETE */
s->tunnel_state = TUNNEL_COMPLETE;
}
@@ -476,14 +489,17 @@ static CURLcode CONNECT(struct connectdata *conn,
/* without content-length or chunked encoding, we
can't keep the connection alive since the close is
the end signal so we bail out at once instead */
- s->keepon = FALSE;
+ s->keepon = KEEPON_DONE;
}
}
else
- s->keepon = FALSE;
- if(!s->cl)
+ s->keepon = KEEPON_DONE;
+
+ if(s->keepon == KEEPON_DONE && !s->cl)
/* we did the full CONNECT treatment, go to COMPLETE */
s->tunnel_state = TUNNEL_COMPLETE;
+
+ DEBUGASSERT(s->keepon == KEEPON_IGNORE || s->keepon == KEEPON_DONE);
continue;
}
@@ -497,7 +513,7 @@ static CURLcode CONNECT(struct connectdata *conn,
if(!auth)
return CURLE_OUT_OF_MEMORY;
- result = Curl_http_input_auth(conn, proxy, auth);
+ result = Curl_http_input_auth(data, proxy, auth);
free(auth);
@@ -532,7 +548,7 @@ static CURLcode CONNECT(struct connectdata *conn,
infof(data, "CONNECT responded chunked\n");
s->chunked_encoding = TRUE;
/* init our chunky engine */
- Curl_httpchunk_init(conn);
+ Curl_httpchunk_init(data);
}
}
else if(Curl_compareheader(linep, "Proxy-Connection:", "close"))
@@ -547,7 +563,7 @@ static CURLcode CONNECT(struct connectdata *conn,
Curl_dyn_reset(&s->rcvbuf);
} /* while there's buffer left and loop is requested */
- if(Curl_pgrsUpdate(conn))
+ if(Curl_pgrsUpdate(data))
return CURLE_ABORTED_BY_CALLBACK;
if(error)
@@ -556,7 +572,7 @@ static CURLcode CONNECT(struct connectdata *conn,
if(data->info.httpproxycode/100 != 2) {
/* Deal with the possibly already received authenticate
headers. 'newurl' is set to a new URL if we must loop. */
- result = Curl_http_auth_act(conn);
+ result = Curl_http_auth_act(data);
if(result)
return result;
@@ -569,7 +585,7 @@ static CURLcode CONNECT(struct connectdata *conn,
if(s->close_connection && data->req.newurl) {
/* Connection closed by server. Don't use it anymore */
- Curl_closesocket(conn, conn->sock[sockindex]);
+ Curl_closesocket(data, conn, conn->sock[sockindex]);
conn->sock[sockindex] = CURL_SOCKET_BAD;
break;
}
@@ -579,7 +595,7 @@ static CURLcode CONNECT(struct connectdata *conn,
* means the HTTP authentication is still going on so if the tunnel
* is complete we start over in INIT state */
if(data->req.newurl && (TUNNEL_COMPLETE == s->tunnel_state)) {
- connect_init(conn, TRUE); /* reinit */
+ connect_init(data, TRUE); /* reinit */
}
} while(data->req.newurl);
@@ -588,14 +604,14 @@ static CURLcode CONNECT(struct connectdata *conn,
if(s->close_connection && data->req.newurl) {
conn->bits.proxy_connect_closed = TRUE;
infof(data, "Connect me again please\n");
- connect_done(conn);
+ connect_done(data);
}
else {
free(data->req.newurl);
data->req.newurl = NULL;
/* failure, close this connection to avoid re-use */
streamclose(conn, "proxy CONNECT failure");
- Curl_closesocket(conn, conn->sock[sockindex]);
+ Curl_closesocket(data, conn, conn->sock[sockindex]);
conn->sock[sockindex] = CURL_SOCKET_BAD;
}
@@ -630,6 +646,225 @@ static CURLcode CONNECT(struct connectdata *conn,
Curl_dyn_free(&s->rcvbuf);
return CURLE_OK;
}
+#else
+/* The Hyper version of CONNECT */
+{
+ struct connectdata *conn = data->conn;
+ struct hyptransfer *h = &data->hyp;
+ curl_socket_t tunnelsocket = conn->sock[sockindex];
+ struct http_connect_state *s = conn->connect_state;
+ CURLcode result = CURLE_OUT_OF_MEMORY;
+ hyper_io *io = NULL;
+ hyper_request *req = NULL;
+ hyper_headers *headers = NULL;
+ hyper_clientconn_options *options = NULL;
+ hyper_task *handshake = NULL;
+ hyper_task *task = NULL; /* for the handshake */
+ hyper_task *sendtask = NULL; /* for the send */
+ hyper_clientconn *client = NULL;
+ hyper_error *hypererr = NULL;
+ char *hostheader = NULL; /* for CONNECT */
+ char *host = NULL; /* Host: */
+
+ if(Curl_connect_complete(conn))
+ return CURLE_OK; /* CONNECT is already completed */
+
+ conn->bits.proxy_connect_closed = FALSE;
+
+ do {
+ switch(s->tunnel_state) {
+ case TUNNEL_INIT:
+ /* BEGIN CONNECT PHASE */
+ io = hyper_io_new();
+ if(!io) {
+ failf(data, "Couldn't create hyper IO");
+ goto error;
+ }
+ /* tell Hyper how to read/write network data */
+ hyper_io_set_userdata(io, data);
+ hyper_io_set_read(io, Curl_hyper_recv);
+ hyper_io_set_write(io, Curl_hyper_send);
+ conn->sockfd = tunnelsocket;
+
+ /* create an executor to poll futures */
+ if(!h->exec) {
+ h->exec = hyper_executor_new();
+ if(!h->exec) {
+ failf(data, "Couldn't create hyper executor");
+ goto error;
+ }
+ }
+
+ options = hyper_clientconn_options_new();
+ if(!options) {
+ failf(data, "Couldn't create hyper client options");
+ goto error;
+ }
+
+ hyper_clientconn_options_exec(options, h->exec);
+
+ /* "Both the `io` and the `options` are consumed in this function
+ call" */
+ handshake = hyper_clientconn_handshake(io, options);
+ if(!handshake) {
+ failf(data, "Couldn't create hyper client handshake");
+ goto error;
+ }
+ io = NULL;
+ options = NULL;
+
+ if(HYPERE_OK != hyper_executor_push(h->exec, handshake)) {
+ failf(data, "Couldn't hyper_executor_push the handshake");
+ goto error;
+ }
+ handshake = NULL; /* ownership passed on */
+
+ task = hyper_executor_poll(h->exec);
+ if(!task) {
+ failf(data, "Couldn't hyper_executor_poll the handshake");
+ goto error;
+ }
+
+ client = hyper_task_value(task);
+ hyper_task_free(task);
+ req = hyper_request_new();
+ if(!req) {
+ failf(data, "Couldn't hyper_request_new");
+ goto error;
+ }
+ if(hyper_request_set_method(req, (uint8_t *)"CONNECT",
+ strlen("CONNECT"))) {
+ failf(data, "error setting method");
+ goto error;
+ }
+
+ result = CONNECT_host(data, conn, hostname, remote_port,
+ &hostheader, &host);
+ if(result)
+ goto error;
+
+ if(hyper_request_set_uri(req, (uint8_t *)hostheader,
+ strlen(hostheader))) {
+ failf(data, "error setting path");
+ result = CURLE_OUT_OF_MEMORY;
+ }
+ /* Setup the proxy-authorization header, if any */
+ result = Curl_http_output_auth(data, conn, "CONNECT", HTTPREQ_GET,
+ hostheader, TRUE);
+ if(result)
+ goto error;
+ Curl_safefree(hostheader);
+
+ /* default is 1.1 */
+ if((conn->http_proxy.proxytype == CURLPROXY_HTTP_1_0) &&
+ (HYPERE_OK != hyper_request_set_version(req,
+ HYPER_HTTP_VERSION_1_0))) {
+ failf(data, "error settting HTTP version");
+ goto error;
+ }
+
+ headers = hyper_request_headers(req);
+ if(!headers) {
+ failf(data, "hyper_request_headers");
+ goto error;
+ }
+ if(host && Curl_hyper_header(data, headers, host))
+ goto error;
+ Curl_safefree(host);
+
+ if(data->state.aptr.proxyuserpwd &&
+ Curl_hyper_header(data, headers, data->state.aptr.proxyuserpwd))
+ goto error;
+
+ if(data->set.str[STRING_USERAGENT] &&
+ *data->set.str[STRING_USERAGENT] &&
+ data->state.aptr.uagent &&
+ Curl_hyper_header(data, headers, data->state.aptr.uagent))
+ goto error;
+
+ if(!Curl_checkProxyheaders(data, conn, "Proxy-Connection") &&
+ Curl_hyper_header(data, headers, "Proxy-Connection: Keep-Alive"))
+ goto error;
+
+ sendtask = hyper_clientconn_send(client, req);
+ if(!sendtask) {
+ failf(data, "hyper_clientconn_send");
+ goto error;
+ }
+
+ if(HYPERE_OK != hyper_executor_push(h->exec, sendtask)) {
+ failf(data, "Couldn't hyper_executor_push the send");
+ goto error;
+ }
+
+ hyper_clientconn_free(client);
+
+ do {
+ task = hyper_executor_poll(h->exec);
+ if(task) {
+ bool error = hyper_task_type(task) == HYPER_TASK_ERROR;
+ if(error)
+ hypererr = hyper_task_value(task);
+ hyper_task_free(task);
+ if(error)
+ goto error;
+ }
+ } while(task);
+ s->tunnel_state = TUNNEL_CONNECT;
+ /* FALLTHROUGH */
+ case TUNNEL_CONNECT: {
+ int didwhat;
+ bool done = FALSE;
+ result = Curl_hyper_stream(data, conn, &didwhat, &done,
+ CURL_CSELECT_IN | CURL_CSELECT_OUT);
+ if(result)
+ goto error;
+ if(!done)
+ break;
+ fprintf(stderr, "done\n");
+ s->tunnel_state = TUNNEL_COMPLETE;
+ if(h->exec) {
+ hyper_executor_free(h->exec);
+ h->exec = NULL;
+ }
+ if(h->read_waker) {
+ hyper_waker_free(h->read_waker);
+ h->read_waker = NULL;
+ }
+ if(h->write_waker) {
+ hyper_waker_free(h->write_waker);
+ h->write_waker = NULL;
+ }
+ }
+ /* FALLTHROUGH */
+ default:
+ break;
+ }
+ } while(data->req.newurl);
+
+ result = CURLE_OK;
+ error:
+ free(host);
+ free(hostheader);
+ if(io)
+ hyper_io_free(io);
+
+ if(options)
+ hyper_clientconn_options_free(options);
+
+ if(handshake)
+ hyper_task_free(handshake);
+
+ if(hypererr) {
+ uint8_t errbuf[256];
+ size_t errlen = hyper_error_print(hypererr, errbuf, sizeof(errbuf));
+ failf(data, "Hyper: %.*s", (int)errlen, errbuf);
+ hyper_error_free(hypererr);
+ }
+ return result;
+}
+
+#endif
void Curl_connect_free(struct Curl_easy *data)
{
@@ -647,21 +882,22 @@ void Curl_connect_free(struct Curl_easy *data)
* this proxy. After that, the socket can be used just as a normal socket.
*/
-CURLcode Curl_proxyCONNECT(struct connectdata *conn,
+CURLcode Curl_proxyCONNECT(struct Curl_easy *data,
int sockindex,
const char *hostname,
int remote_port)
{
CURLcode result;
+ struct connectdata *conn = data->conn;
if(!conn->connect_state) {
- result = connect_init(conn, FALSE);
+ result = connect_init(data, FALSE);
if(result)
return result;
}
- result = CONNECT(conn, sockindex, hostname, remote_port);
+ result = CONNECT(data, sockindex, hostname, remote_port);
if(result || Curl_connect_complete(conn))
- connect_done(conn);
+ connect_done(data);
return result;
}
diff --git a/Utilities/cmcurl/lib/http_proxy.h b/Utilities/cmcurl/lib/http_proxy.h
index 29988a696..a78db0d04 100644
--- a/Utilities/cmcurl/lib/http_proxy.h
+++ b/Utilities/cmcurl/lib/http_proxy.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -27,14 +27,14 @@
#if !defined(CURL_DISABLE_PROXY) && !defined(CURL_DISABLE_HTTP)
/* ftp can use this as well */
-CURLcode Curl_proxyCONNECT(struct connectdata *conn,
+CURLcode Curl_proxyCONNECT(struct Curl_easy *data,
int tunnelsocket,
const char *hostname, int remote_port);
/* Default proxy timeout in milliseconds */
#define PROXY_TIMEOUT (3600*1000)
-CURLcode Curl_proxy_connect(struct connectdata *conn, int sockindex);
+CURLcode Curl_proxy_connect(struct Curl_easy *data, int sockindex);
bool Curl_connect_complete(struct connectdata *conn);
bool Curl_connect_ongoing(struct connectdata *conn);
diff --git a/Utilities/cmcurl/lib/idn_win32.c b/Utilities/cmcurl/lib/idn_win32.c
index 2f5850dd0..1d475a4ef 100644
--- a/Utilities/cmcurl/lib/idn_win32.c
+++ b/Utilities/cmcurl/lib/idn_win32.c
@@ -9,7 +9,7 @@
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/if2ip.c b/Utilities/cmcurl/lib/if2ip.c
index 39388692e..21e00b1f1 100644
--- a/Utilities/cmcurl/lib/if2ip.c
+++ b/Utilities/cmcurl/lib/if2ip.c
@@ -9,7 +9,7 @@
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/if2ip.h b/Utilities/cmcurl/lib/if2ip.h
index f193d4257..e074e476d 100644
--- a/Utilities/cmcurl/lib/if2ip.h
+++ b/Utilities/cmcurl/lib/if2ip.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
diff --git a/Utilities/cmcurl/lib/imap.c b/Utilities/cmcurl/lib/imap.c
index cad0e5908..2d8069921 100644
--- a/Utilities/cmcurl/lib/imap.c
+++ b/Utilities/cmcurl/lib/imap.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -88,25 +88,31 @@
#include "memdebug.h"
/* Local API functions */
-static CURLcode imap_regular_transfer(struct connectdata *conn, bool *done);
-static CURLcode imap_do(struct connectdata *conn, bool *done);
-static CURLcode imap_done(struct connectdata *conn, CURLcode status,
+static CURLcode imap_regular_transfer(struct Curl_easy *data, bool *done);
+static CURLcode imap_do(struct Curl_easy *data, bool *done);
+static CURLcode imap_done(struct Curl_easy *data, CURLcode status,
bool premature);
-static CURLcode imap_connect(struct connectdata *conn, bool *done);
-static CURLcode imap_disconnect(struct connectdata *conn, bool dead);
-static CURLcode imap_multi_statemach(struct connectdata *conn, bool *done);
-static int imap_getsock(struct connectdata *conn, curl_socket_t *socks);
-static CURLcode imap_doing(struct connectdata *conn, bool *dophase_done);
-static CURLcode imap_setup_connection(struct connectdata *conn);
+static CURLcode imap_connect(struct Curl_easy *data, bool *done);
+static CURLcode imap_disconnect(struct Curl_easy *data,
+ struct connectdata *conn, bool dead);
+static CURLcode imap_multi_statemach(struct Curl_easy *data, bool *done);
+static int imap_getsock(struct Curl_easy *data, struct connectdata *conn,
+ curl_socket_t *socks);
+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 connectdata *conn, const char *fmt, ...);
+static CURLcode imap_sendf(struct Curl_easy *data,
+ struct connectdata *conn, const char *fmt, ...);
static CURLcode imap_parse_url_options(struct connectdata *conn);
-static CURLcode imap_parse_url_path(struct connectdata *conn);
-static CURLcode imap_parse_custom_request(struct connectdata *conn);
-static CURLcode imap_perform_authenticate(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_perform_authenticate(struct Curl_easy *data,
+ struct connectdata *conn,
const char *mech,
const char *initresp);
-static CURLcode imap_continue_authenticate(struct connectdata *conn,
+static CURLcode imap_continue_authenticate(struct Curl_easy *data,
+ struct connectdata *conn,
const char *resp);
static void imap_get_message(char *buffer, char **outptr);
@@ -132,6 +138,7 @@ const struct Curl_handler Curl_handler_imap = {
ZERO_NULL, /* connection_check */
PORT_IMAP, /* defport */
CURLPROTO_IMAP, /* protocol */
+ CURLPROTO_IMAP, /* family */
PROTOPT_CLOSEACTION| /* flags */
PROTOPT_URLOPTIONS
};
@@ -159,6 +166,7 @@ const struct Curl_handler Curl_handler_imaps = {
ZERO_NULL, /* connection_check */
PORT_IMAPS, /* defport */
CURLPROTO_IMAPS, /* protocol */
+ CURLPROTO_IMAP, /* family */
PROTOPT_CLOSEACTION | PROTOPT_SSL | /* flags */
PROTOPT_URLOPTIONS
};
@@ -241,10 +249,10 @@ static bool imap_matchresp(const char *line, size_t len, const char *cmd)
* Checks whether the given string is a valid tagged, untagged or continuation
* response which can be processed by the response handler.
*/
-static bool imap_endofresp(struct connectdata *conn, char *line, size_t len,
- int *resp)
+static bool imap_endofresp(struct Curl_easy *data, struct connectdata *conn,
+ char *line, size_t len, int *resp)
{
- struct IMAP *imap = conn->data->req.protop;
+ 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);
@@ -326,7 +334,7 @@ static bool imap_endofresp(struct connectdata *conn, char *line, size_t len,
break;
default:
- failf(conn->data, "Unexpected continuation response");
+ failf(data, "Unexpected continuation response");
*resp = -1;
break;
}
@@ -379,9 +387,9 @@ static void imap_get_message(char *buffer, char **outptr)
*
* This is the ONLY way to change IMAP state!
*/
-static void state(struct connectdata *conn, imapstate newstate)
+static void state(struct Curl_easy *data, imapstate newstate)
{
- struct imap_conn *imapc = &conn->proto.imapc;
+ struct imap_conn *imapc = &data->conn->proto.imapc;
#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
/* for debug purposes */
static const char * const names[]={
@@ -404,7 +412,7 @@ static void state(struct connectdata *conn, imapstate newstate)
};
if(imapc->state != newstate)
- infof(conn->data, "IMAP %p state change from %s to %s\n",
+ infof(data, "IMAP %p state change from %s to %s\n",
(void *)imapc, names[imapc->state], names[newstate]);
#endif
@@ -418,7 +426,8 @@ static void state(struct connectdata *conn, imapstate newstate)
* Sends the CAPABILITY command in order to obtain a list of server side
* supported capabilities.
*/
-static CURLcode imap_perform_capability(struct connectdata *conn)
+static CURLcode imap_perform_capability(struct Curl_easy *data,
+ struct connectdata *conn)
{
CURLcode result = CURLE_OK;
struct imap_conn *imapc = &conn->proto.imapc;
@@ -427,10 +436,10 @@ static CURLcode imap_perform_capability(struct connectdata *conn)
imapc->tls_supported = FALSE; /* Clear the TLS capability */
/* Send the CAPABILITY command */
- result = imap_sendf(conn, "CAPABILITY");
+ result = imap_sendf(data, conn, "CAPABILITY");
if(!result)
- state(conn, IMAP_CAPABILITY);
+ state(data, IMAP_CAPABILITY);
return result;
}
@@ -441,13 +450,14 @@ static CURLcode imap_perform_capability(struct connectdata *conn)
*
* Sends the STARTTLS command to start the upgrade to TLS.
*/
-static CURLcode imap_perform_starttls(struct connectdata *conn)
+static CURLcode imap_perform_starttls(struct Curl_easy *data,
+ struct connectdata *conn)
{
/* Send the STARTTLS command */
- CURLcode result = imap_sendf(conn, "STARTTLS");
+ CURLcode result = imap_sendf(data, conn, "STARTTLS");
if(!result)
- state(conn, IMAP_STARTTLS);
+ state(data, IMAP_STARTTLS);
return result;
}
@@ -458,20 +468,21 @@ static CURLcode imap_perform_starttls(struct connectdata *conn)
*
* Performs the upgrade to TLS.
*/
-static CURLcode imap_perform_upgrade_tls(struct connectdata *conn)
+static CURLcode imap_perform_upgrade_tls(struct Curl_easy *data,
+ struct connectdata *conn)
{
/* Start the SSL connection */
struct imap_conn *imapc = &conn->proto.imapc;
- CURLcode result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET,
+ CURLcode result = Curl_ssl_connect_nonblocking(data, conn, FIRSTSOCKET,
&imapc->ssldone);
if(!result) {
if(imapc->state != IMAP_UPGRADETLS)
- state(conn, IMAP_UPGRADETLS);
+ state(data, IMAP_UPGRADETLS);
if(imapc->ssldone) {
imap_to_imaps(conn);
- result = imap_perform_capability(conn);
+ result = imap_perform_capability(data, conn);
}
}
@@ -484,7 +495,8 @@ static CURLcode imap_perform_upgrade_tls(struct connectdata *conn)
*
* Sends a clear text LOGIN command to authenticate with.
*/
-static CURLcode imap_perform_login(struct connectdata *conn)
+static CURLcode imap_perform_login(struct Curl_easy *data,
+ struct connectdata *conn)
{
CURLcode result = CURLE_OK;
char *user;
@@ -493,7 +505,7 @@ static CURLcode imap_perform_login(struct connectdata *conn)
/* Check we have a username and password to authenticate with and end the
connect phase if we don't */
if(!conn->bits.user_passwd) {
- state(conn, IMAP_STOP);
+ state(data, IMAP_STOP);
return result;
}
@@ -503,14 +515,14 @@ static CURLcode imap_perform_login(struct connectdata *conn)
passwd = imap_atom(conn->passwd, false);
/* Send the LOGIN command */
- result = imap_sendf(conn, "LOGIN %s %s", user ? user : "",
+ result = imap_sendf(data, conn, "LOGIN %s %s", user ? user : "",
passwd ? passwd : "");
free(user);
free(passwd);
if(!result)
- state(conn, IMAP_LOGIN);
+ state(data, IMAP_LOGIN);
return result;
}
@@ -522,19 +534,21 @@ static CURLcode imap_perform_login(struct connectdata *conn)
* Sends an AUTHENTICATE command allowing the client to login with the given
* SASL authentication mechanism.
*/
-static CURLcode imap_perform_authenticate(struct connectdata *conn,
+static CURLcode imap_perform_authenticate(struct Curl_easy *data,
+ struct connectdata *conn,
const char *mech,
const char *initresp)
{
CURLcode result = CURLE_OK;
+ (void)data;
if(initresp) {
/* Send the AUTHENTICATE command with the initial response */
- result = imap_sendf(conn, "AUTHENTICATE %s %s", mech, initresp);
+ result = imap_sendf(data, conn, "AUTHENTICATE %s %s", mech, initresp);
}
else {
/* Send the AUTHENTICATE command */
- result = imap_sendf(conn, "AUTHENTICATE %s", mech);
+ result = imap_sendf(data, conn, "AUTHENTICATE %s", mech);
}
return result;
@@ -546,12 +560,13 @@ static CURLcode imap_perform_authenticate(struct connectdata *conn,
*
* Sends SASL continuation data or cancellation.
*/
-static CURLcode imap_continue_authenticate(struct connectdata *conn,
+static CURLcode imap_continue_authenticate(struct Curl_easy *data,
+ struct connectdata *conn,
const char *resp)
{
struct imap_conn *imapc = &conn->proto.imapc;
- return Curl_pp_sendf(&imapc->pp, "%s", resp);
+ return Curl_pp_sendf(data, &imapc->pp, "%s", resp);
}
/***********************************************************************
@@ -562,7 +577,8 @@ static CURLcode imap_continue_authenticate(struct connectdata *conn,
* authentication mechanism, falling back to clear text should a common
* mechanism not be available between the client and server.
*/
-static CURLcode imap_perform_authentication(struct connectdata *conn)
+static CURLcode imap_perform_authentication(struct Curl_easy *data,
+ struct connectdata *conn)
{
CURLcode result = CURLE_OK;
struct imap_conn *imapc = &conn->proto.imapc;
@@ -572,22 +588,23 @@ static CURLcode imap_perform_authentication(struct connectdata *conn)
with and end the connect phase if we don't */
if(imapc->preauth ||
!Curl_sasl_can_authenticate(&imapc->sasl, conn)) {
- state(conn, IMAP_STOP);
+ state(data, IMAP_STOP);
return result;
}
/* Calculate the SASL login details */
- result = Curl_sasl_start(&imapc->sasl, conn, imapc->ir_supported, &progress);
+ result = Curl_sasl_start(&imapc->sasl, data, conn,
+ imapc->ir_supported, &progress);
if(!result) {
if(progress == SASL_INPROGRESS)
- state(conn, IMAP_AUTHENTICATE);
+ state(data, IMAP_AUTHENTICATE);
else if(!imapc->login_disabled && (imapc->preftype & IMAP_TYPE_CLEARTEXT))
/* Perform clear text authentication */
- result = imap_perform_login(conn);
+ result = imap_perform_login(data, conn);
else {
/* Other mechanisms not supported */
- infof(conn->data, "No known authentication mechanisms supported!\n");
+ infof(data, "No known authentication mechanisms supported!\n");
result = CURLE_LOGIN_DENIED;
}
}
@@ -601,15 +618,15 @@ static CURLcode imap_perform_authentication(struct connectdata *conn)
*
* Sends a LIST command or an alternative custom request.
*/
-static CURLcode imap_perform_list(struct connectdata *conn)
+static CURLcode imap_perform_list(struct Curl_easy *data)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
- struct IMAP *imap = data->req.protop;
+ struct connectdata *conn = data->conn;
+ struct IMAP *imap = data->req.p.imap;
if(imap->custom)
/* Send the custom request */
- result = imap_sendf(conn, "%s%s", imap->custom,
+ result = imap_sendf(data, conn, "%s%s", imap->custom,
imap->custom_params ? imap->custom_params : "");
else {
/* Make sure the mailbox is in the correct atom format if necessary */
@@ -619,13 +636,13 @@ static CURLcode imap_perform_list(struct connectdata *conn)
return CURLE_OUT_OF_MEMORY;
/* Send the LIST command */
- result = imap_sendf(conn, "LIST \"%s\" *", mailbox);
+ result = imap_sendf(data, conn, "LIST \"%s\" *", mailbox);
free(mailbox);
}
if(!result)
- state(conn, IMAP_LIST);
+ state(data, IMAP_LIST);
return result;
}
@@ -636,11 +653,11 @@ static CURLcode imap_perform_list(struct connectdata *conn)
*
* Sends a SELECT command to ask the server to change the selected mailbox.
*/
-static CURLcode imap_perform_select(struct connectdata *conn)
+static CURLcode imap_perform_select(struct Curl_easy *data)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
- struct IMAP *imap = data->req.protop;
+ struct connectdata *conn = data->conn;
+ struct IMAP *imap = data->req.p.imap;
struct imap_conn *imapc = &conn->proto.imapc;
char *mailbox;
@@ -650,7 +667,7 @@ static CURLcode imap_perform_select(struct connectdata *conn)
/* Check we have a mailbox */
if(!imap->mailbox) {
- failf(conn->data, "Cannot SELECT without a mailbox.");
+ failf(data, "Cannot SELECT without a mailbox.");
return CURLE_URL_MALFORMAT;
}
@@ -660,12 +677,12 @@ static CURLcode imap_perform_select(struct connectdata *conn)
return CURLE_OUT_OF_MEMORY;
/* Send the SELECT command */
- result = imap_sendf(conn, "SELECT %s", mailbox);
+ result = imap_sendf(data, conn, "SELECT %s", mailbox);
free(mailbox);
if(!result)
- state(conn, IMAP_SELECT);
+ state(data, IMAP_SELECT);
return result;
}
@@ -676,43 +693,39 @@ static CURLcode imap_perform_select(struct connectdata *conn)
*
* Sends a FETCH command to initiate the download of a message.
*/
-static CURLcode imap_perform_fetch(struct connectdata *conn)
+static CURLcode imap_perform_fetch(struct Curl_easy *data,
+ struct connectdata *conn)
{
CURLcode result = CURLE_OK;
- struct IMAP *imap = conn->data->req.protop;
+ 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(conn, "UID FETCH %s BODY[%s]<%s>",
- imap->uid,
- imap->section ? imap->section : "",
- imap->partial);
+ result = imap_sendf(data, conn, "UID FETCH %s BODY[%s]<%s>",
+ imap->uid, imap->section ? imap->section : "",
+ imap->partial);
else
- result = imap_sendf(conn, "UID FETCH %s BODY[%s]",
- imap->uid,
- imap->section ? imap->section : "");
+ result = imap_sendf(data, conn, "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(conn, "FETCH %s BODY[%s]<%s>",
- imap->mindex,
- imap->section ? imap->section : "",
- imap->partial);
+ result = imap_sendf(data, conn, "FETCH %s BODY[%s]<%s>",
+ imap->mindex, imap->section ? imap->section : "",
+ imap->partial);
else
- result = imap_sendf(conn, "FETCH %s BODY[%s]",
- imap->mindex,
- imap->section ? imap->section : "");
+ result = imap_sendf(data, conn, "FETCH %s BODY[%s]",
+ imap->mindex, imap->section ? imap->section : "");
}
else {
- failf(conn->data, "Cannot FETCH without a UID.");
- return CURLE_URL_MALFORMAT;
+ failf(data, "Cannot FETCH without a UID.");
+ return CURLE_URL_MALFORMAT;
}
if(!result)
- state(conn, IMAP_FETCH);
+ state(data, IMAP_FETCH);
return result;
}
@@ -723,11 +736,11 @@ static CURLcode imap_perform_fetch(struct connectdata *conn)
*
* Sends an APPEND command to initiate the upload of a message.
*/
-static CURLcode imap_perform_append(struct connectdata *conn)
+static CURLcode imap_perform_append(struct Curl_easy *data)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
- struct IMAP *imap = data->req.protop;
+ struct connectdata *conn = data->conn;
+ struct IMAP *imap = data->req.p.imap;
char *mailbox;
/* Check we have a mailbox */
@@ -747,7 +760,7 @@ static CURLcode imap_perform_append(struct connectdata *conn)
NULL, MIMESTRATEGY_MAIL);
if(!result)
- if(!Curl_checkheaders(conn, "Mime-Version"))
+ if(!Curl_checkheaders(data, "Mime-Version"))
result = Curl_mime_add_header(&data->set.mimepost.curlheaders,
"Mime-Version: 1.0");
@@ -767,7 +780,7 @@ static CURLcode imap_perform_append(struct connectdata *conn)
/* Check we know the size of the upload */
if(data->state.infilesize < 0) {
- failf(data, "Cannot APPEND with unknown input file size\n");
+ failf(data, "Cannot APPEND with unknown input file size");
return CURLE_UPLOAD_FAILED;
}
@@ -777,13 +790,14 @@ static CURLcode imap_perform_append(struct connectdata *conn)
return CURLE_OUT_OF_MEMORY;
/* Send the APPEND command */
- result = imap_sendf(conn, "APPEND %s (\\Seen) {%" CURL_FORMAT_CURL_OFF_T "}",
+ result = imap_sendf(data, conn,
+ "APPEND %s (\\Seen) {%" CURL_FORMAT_CURL_OFF_T "}",
mailbox, data->state.infilesize);
free(mailbox);
if(!result)
- state(conn, IMAP_APPEND);
+ state(data, IMAP_APPEND);
return result;
}
@@ -794,22 +808,23 @@ static CURLcode imap_perform_append(struct connectdata *conn)
*
* Sends a SEARCH command.
*/
-static CURLcode imap_perform_search(struct connectdata *conn)
+static CURLcode imap_perform_search(struct Curl_easy *data,
+ struct connectdata *conn)
{
CURLcode result = CURLE_OK;
- struct IMAP *imap = conn->data->req.protop;
+ struct IMAP *imap = data->req.p.imap;
/* Check we have a query string */
if(!imap->query) {
- failf(conn->data, "Cannot SEARCH without a query string.");
+ failf(data, "Cannot SEARCH without a query string.");
return CURLE_URL_MALFORMAT;
}
/* Send the SEARCH command */
- result = imap_sendf(conn, "SEARCH %s", imap->query);
+ result = imap_sendf(data, conn, "SEARCH %s", imap->query);
if(!result)
- state(conn, IMAP_SEARCH);
+ state(data, IMAP_SEARCH);
return result;
}
@@ -820,23 +835,24 @@ static CURLcode imap_perform_search(struct connectdata *conn)
*
* Performs the logout action prior to sclose() being called.
*/
-static CURLcode imap_perform_logout(struct connectdata *conn)
+static CURLcode imap_perform_logout(struct Curl_easy *data,
+ struct connectdata *conn)
{
/* Send the LOGOUT command */
- CURLcode result = imap_sendf(conn, "LOGOUT");
+ CURLcode result = imap_sendf(data, conn, "LOGOUT");
if(!result)
- state(conn, IMAP_LOGOUT);
+ state(data, IMAP_LOGOUT);
return result;
}
/* For the initial server greeting */
-static CURLcode imap_state_servergreet_resp(struct connectdata *conn,
+static CURLcode imap_state_servergreet_resp(struct Curl_easy *data,
int imapcode,
imapstate instate)
{
- struct Curl_easy *data = conn->data;
+ struct connectdata *conn = data->conn;
(void)instate; /* no use for this yet */
if(imapcode == IMAP_RESP_PREAUTH) {
@@ -850,16 +866,16 @@ static CURLcode imap_state_servergreet_resp(struct connectdata *conn,
return CURLE_WEIRD_SERVER_REPLY;
}
- return imap_perform_capability(conn);
+ return imap_perform_capability(data, conn);
}
/* For CAPABILITY responses */
-static CURLcode imap_state_capability_resp(struct connectdata *conn,
+static CURLcode imap_state_capability_resp(struct Curl_easy *data,
int imapcode,
imapstate instate)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
+ struct connectdata *conn = data->conn;
struct imap_conn *imapc = &conn->proto.imapc;
const char *line = data->state.buffer;
@@ -922,31 +938,31 @@ static CURLcode imap_state_capability_resp(struct connectdata *conn,
/* We don't have a SSL/TLS connection yet, but SSL is requested */
if(imapc->tls_supported)
/* Switch to TLS connection now */
- result = imap_perform_starttls(conn);
+ result = imap_perform_starttls(data, conn);
else if(data->set.use_ssl == CURLUSESSL_TRY)
/* Fallback and carry on with authentication */
- result = imap_perform_authentication(conn);
+ result = imap_perform_authentication(data, conn);
else {
failf(data, "STARTTLS not supported.");
result = CURLE_USE_SSL_FAILED;
}
}
else
- result = imap_perform_authentication(conn);
+ result = imap_perform_authentication(data, conn);
}
else
- result = imap_perform_authentication(conn);
+ result = imap_perform_authentication(data, conn);
return result;
}
/* For STARTTLS responses */
-static CURLcode imap_state_starttls_resp(struct connectdata *conn,
+static CURLcode imap_state_starttls_resp(struct Curl_easy *data,
int imapcode,
imapstate instate)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
+ struct connectdata *conn = data->conn;
(void)instate; /* no use for this yet */
@@ -956,36 +972,36 @@ static CURLcode imap_state_starttls_resp(struct connectdata *conn,
result = CURLE_USE_SSL_FAILED;
}
else
- result = imap_perform_authentication(conn);
+ result = imap_perform_authentication(data, conn);
}
else
- result = imap_perform_upgrade_tls(conn);
+ result = imap_perform_upgrade_tls(data, conn);
return result;
}
/* For SASL authentication responses */
-static CURLcode imap_state_auth_resp(struct connectdata *conn,
+static CURLcode imap_state_auth_resp(struct Curl_easy *data,
+ struct connectdata *conn,
int imapcode,
imapstate instate)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
struct imap_conn *imapc = &conn->proto.imapc;
saslprogress progress;
(void)instate; /* no use for this yet */
- result = Curl_sasl_continue(&imapc->sasl, conn, imapcode, &progress);
+ result = Curl_sasl_continue(&imapc->sasl, data, conn, imapcode, &progress);
if(!result)
switch(progress) {
case SASL_DONE:
- state(conn, IMAP_STOP); /* Authenticated */
+ state(data, 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(conn);
+ result = imap_perform_login(data, conn);
else {
failf(data, "Authentication cancelled");
result = CURLE_LOGIN_DENIED;
@@ -999,13 +1015,11 @@ static CURLcode imap_state_auth_resp(struct connectdata *conn,
}
/* For LOGIN responses */
-static CURLcode imap_state_login_resp(struct connectdata *conn,
+static CURLcode imap_state_login_resp(struct Curl_easy *data,
int imapcode,
imapstate instate)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
-
(void)instate; /* no use for this yet */
if(imapcode != IMAP_RESP_OK) {
@@ -1014,18 +1028,18 @@ static CURLcode imap_state_login_resp(struct connectdata *conn,
}
else
/* End of connect phase */
- state(conn, IMAP_STOP);
+ state(data, IMAP_STOP);
return result;
}
/* For LIST and SEARCH responses */
-static CURLcode imap_state_listsearch_resp(struct connectdata *conn,
+static CURLcode imap_state_listsearch_resp(struct Curl_easy *data,
int imapcode,
imapstate instate)
{
CURLcode result = CURLE_OK;
- char *line = conn->data->state.buffer;
+ char *line = data->state.buffer;
size_t len = strlen(line);
(void)instate; /* No use for this yet */
@@ -1033,25 +1047,25 @@ static CURLcode imap_state_listsearch_resp(struct connectdata *conn,
if(imapcode == '*') {
/* Temporarily add the LF character back and send as body to the client */
line[len] = '\n';
- result = Curl_client_write(conn, CLIENTWRITE_BODY, line, len + 1);
+ result = Curl_client_write(data, CLIENTWRITE_BODY, line, len + 1);
line[len] = '\0';
}
else if(imapcode != IMAP_RESP_OK)
result = CURLE_QUOTE_ERROR;
else
/* End of DO phase */
- state(conn, IMAP_STOP);
+ state(data, IMAP_STOP);
return result;
}
/* For SELECT responses */
-static CURLcode imap_state_select_resp(struct connectdata *conn, int imapcode,
+static CURLcode imap_state_select_resp(struct Curl_easy *data, int imapcode,
imapstate instate)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
- struct IMAP *imap = conn->data->req.protop;
+ struct connectdata *conn = data->conn;
+ struct IMAP *imap = data->req.p.imap;
struct imap_conn *imapc = &conn->proto.imapc;
const char *line = data->state.buffer;
@@ -1069,7 +1083,7 @@ static CURLcode imap_state_select_resp(struct connectdata *conn, int imapcode,
/* Check if the UIDVALIDITY has been specified and matches */
if(imap->uidvalidity && imapc->mailbox_uidvalidity &&
!strcasecompare(imap->uidvalidity, imapc->mailbox_uidvalidity)) {
- failf(conn->data, "Mailbox UIDVALIDITY has changed");
+ failf(data, "Mailbox UIDVALIDITY has changed");
result = CURLE_REMOTE_FILE_NOT_FOUND;
}
else {
@@ -1077,11 +1091,11 @@ static CURLcode imap_state_select_resp(struct connectdata *conn, int imapcode,
imapc->mailbox = strdup(imap->mailbox);
if(imap->custom)
- result = imap_perform_list(conn);
+ result = imap_perform_list(data);
else if(imap->query)
- result = imap_perform_search(conn);
+ result = imap_perform_search(data, conn);
else
- result = imap_perform_fetch(conn);
+ result = imap_perform_fetch(data, conn);
}
}
else {
@@ -1093,11 +1107,11 @@ static CURLcode imap_state_select_resp(struct connectdata *conn, int imapcode,
}
/* For the (first line of the) FETCH responses */
-static CURLcode imap_state_fetch_resp(struct connectdata *conn, int imapcode,
+static CURLcode imap_state_fetch_resp(struct Curl_easy *data,
+ struct connectdata *conn, int imapcode,
imapstate instate)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
struct imap_conn *imapc = &conn->proto.imapc;
struct pingpong *pp = &imapc->pp;
const char *ptr = data->state.buffer;
@@ -1108,7 +1122,7 @@ static CURLcode imap_state_fetch_resp(struct connectdata *conn, int imapcode,
if(imapcode != '*') {
Curl_pgrsSetDownloadSize(data, -1);
- state(conn, IMAP_STOP);
+ state(data, IMAP_STOP);
return CURLE_REMOTE_FILE_NOT_FOUND;
}
@@ -1143,10 +1157,10 @@ static CURLcode imap_state_fetch_resp(struct connectdata *conn, int imapcode,
if(!chunk) {
/* no size, we're done with the data */
- state(conn, IMAP_STOP);
+ state(data, IMAP_STOP);
return CURLE_OK;
}
- result = Curl_client_write(conn, CLIENTWRITE_BODY, pp->cache, chunk);
+ result = Curl_client_write(data, CLIENTWRITE_BODY, pp->cache, chunk);
if(result)
return result;
@@ -1176,23 +1190,26 @@ static CURLcode imap_state_fetch_resp(struct connectdata *conn, int imapcode,
else {
/* IMAP download */
data->req.maxdownload = size;
+ /* force a recv/send check of this connection, as the data might've been
+ read off the socket already */
+ data->conn->cselect_bits = CURL_CSELECT_IN;
Curl_setup_transfer(data, FIRSTSOCKET, size, FALSE, -1);
}
}
else {
/* We don't know how to parse this line */
- failf(pp->conn->data, "Failed to parse FETCH response.");
+ failf(data, "Failed to parse FETCH response.");
result = CURLE_WEIRD_SERVER_REPLY;
}
/* End of DO phase */
- state(conn, IMAP_STOP);
+ state(data, IMAP_STOP);
return result;
}
/* For final FETCH responses performed after the download */
-static CURLcode imap_state_fetch_final_resp(struct connectdata *conn,
+static CURLcode imap_state_fetch_final_resp(struct Curl_easy *data,
int imapcode,
imapstate instate)
{
@@ -1204,18 +1221,16 @@ static CURLcode imap_state_fetch_final_resp(struct connectdata *conn,
result = CURLE_WEIRD_SERVER_REPLY;
else
/* End of DONE phase */
- state(conn, IMAP_STOP);
+ state(data, IMAP_STOP);
return result;
}
/* For APPEND responses */
-static CURLcode imap_state_append_resp(struct connectdata *conn, int imapcode,
+static CURLcode imap_state_append_resp(struct Curl_easy *data, int imapcode,
imapstate instate)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
-
(void)instate; /* No use for this yet */
if(imapcode != '+') {
@@ -1229,14 +1244,14 @@ static CURLcode imap_state_append_resp(struct connectdata *conn, int imapcode,
Curl_setup_transfer(data, -1, -1, FALSE, FIRSTSOCKET);
/* End of DO phase */
- state(conn, IMAP_STOP);
+ state(data, IMAP_STOP);
}
return result;
}
/* For final APPEND responses performed after the upload */
-static CURLcode imap_state_append_final_resp(struct connectdata *conn,
+static CURLcode imap_state_append_final_resp(struct Curl_easy *data,
int imapcode,
imapstate instate)
{
@@ -1248,12 +1263,13 @@ static CURLcode imap_state_append_final_resp(struct connectdata *conn,
result = CURLE_UPLOAD_FAILED;
else
/* End of DONE phase */
- state(conn, IMAP_STOP);
+ state(data, IMAP_STOP);
return result;
}
-static CURLcode imap_statemach_act(struct connectdata *conn)
+static CURLcode imap_statemachine(struct Curl_easy *data,
+ struct connectdata *conn)
{
CURLcode result = CURLE_OK;
curl_socket_t sock = conn->sock[FIRSTSOCKET];
@@ -1261,18 +1277,19 @@ static CURLcode imap_statemach_act(struct connectdata *conn)
struct imap_conn *imapc = &conn->proto.imapc;
struct pingpong *pp = &imapc->pp;
size_t nread = 0;
+ (void)data;
/* Busy upgrading the connection; right now all I/O is SSL/TLS, not IMAP */
if(imapc->state == IMAP_UPGRADETLS)
- return imap_perform_upgrade_tls(conn);
+ return imap_perform_upgrade_tls(data, conn);
/* Flush any data that needs to be sent */
if(pp->sendleft)
- return Curl_pp_flushsend(pp);
+ return Curl_pp_flushsend(data, pp);
do {
/* Read the response from the server */
- result = Curl_pp_readresp(sock, pp, &imapcode, &nread);
+ result = Curl_pp_readresp(data, sock, pp, &imapcode, &nread);
if(result)
return result;
@@ -1286,55 +1303,55 @@ static CURLcode imap_statemach_act(struct connectdata *conn)
/* We have now received a full IMAP server response */
switch(imapc->state) {
case IMAP_SERVERGREET:
- result = imap_state_servergreet_resp(conn, imapcode, imapc->state);
+ result = imap_state_servergreet_resp(data, imapcode, imapc->state);
break;
case IMAP_CAPABILITY:
- result = imap_state_capability_resp(conn, imapcode, imapc->state);
+ result = imap_state_capability_resp(data, imapcode, imapc->state);
break;
case IMAP_STARTTLS:
- result = imap_state_starttls_resp(conn, imapcode, imapc->state);
+ result = imap_state_starttls_resp(data, imapcode, imapc->state);
break;
case IMAP_AUTHENTICATE:
- result = imap_state_auth_resp(conn, imapcode, imapc->state);
+ result = imap_state_auth_resp(data, conn, imapcode, imapc->state);
break;
case IMAP_LOGIN:
- result = imap_state_login_resp(conn, imapcode, imapc->state);
+ result = imap_state_login_resp(data, imapcode, imapc->state);
break;
case IMAP_LIST:
case IMAP_SEARCH:
- result = imap_state_listsearch_resp(conn, imapcode, imapc->state);
+ result = imap_state_listsearch_resp(data, imapcode, imapc->state);
break;
case IMAP_SELECT:
- result = imap_state_select_resp(conn, imapcode, imapc->state);
+ result = imap_state_select_resp(data, imapcode, imapc->state);
break;
case IMAP_FETCH:
- result = imap_state_fetch_resp(conn, imapcode, imapc->state);
+ result = imap_state_fetch_resp(data, conn, imapcode, imapc->state);
break;
case IMAP_FETCH_FINAL:
- result = imap_state_fetch_final_resp(conn, imapcode, imapc->state);
+ result = imap_state_fetch_final_resp(data, imapcode, imapc->state);
break;
case IMAP_APPEND:
- result = imap_state_append_resp(conn, imapcode, imapc->state);
+ result = imap_state_append_resp(data, imapcode, imapc->state);
break;
case IMAP_APPEND_FINAL:
- result = imap_state_append_final_resp(conn, imapcode, imapc->state);
+ result = imap_state_append_final_resp(data, imapcode, imapc->state);
break;
case IMAP_LOGOUT:
/* fallthrough, just stop! */
default:
/* internal error */
- state(conn, IMAP_STOP);
+ state(data, IMAP_STOP);
break;
}
} while(!result && imapc->state != IMAP_STOP && Curl_pp_moredata(pp));
@@ -1343,44 +1360,46 @@ static CURLcode imap_statemach_act(struct connectdata *conn)
}
/* Called repeatedly until done from multi.c */
-static CURLcode imap_multi_statemach(struct connectdata *conn, bool *done)
+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;
if((conn->handler->flags & PROTOPT_SSL) && !imapc->ssldone) {
- result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, &imapc->ssldone);
+ result = Curl_ssl_connect_nonblocking(data, conn,
+ FIRSTSOCKET, &imapc->ssldone);
if(result || !imapc->ssldone)
return result;
}
- result = Curl_pp_statemach(&imapc->pp, FALSE, FALSE);
+ result = Curl_pp_statemach(data, &imapc->pp, FALSE, FALSE);
*done = (imapc->state == IMAP_STOP) ? TRUE : FALSE;
return result;
}
-static CURLcode imap_block_statemach(struct connectdata *conn,
+static CURLcode imap_block_statemach(struct Curl_easy *data,
+ struct connectdata *conn,
bool disconnecting)
{
CURLcode result = CURLE_OK;
struct imap_conn *imapc = &conn->proto.imapc;
while(imapc->state != IMAP_STOP && !result)
- result = Curl_pp_statemach(&imapc->pp, TRUE, disconnecting);
+ result = Curl_pp_statemach(data, &imapc->pp, TRUE, disconnecting);
return result;
}
/* Allocate and initialize the struct IMAP for the current Curl_easy if
required */
-static CURLcode imap_init(struct connectdata *conn)
+static CURLcode imap_init(struct Curl_easy *data)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
struct IMAP *imap;
- imap = data->req.protop = calloc(sizeof(struct IMAP), 1);
+ imap = data->req.p.imap = calloc(sizeof(struct IMAP), 1);
if(!imap)
result = CURLE_OUT_OF_MEMORY;
@@ -1388,9 +1407,11 @@ static CURLcode imap_init(struct connectdata *conn)
}
/* For the IMAP "protocol connect" and "doing" phases only */
-static int imap_getsock(struct connectdata *conn, curl_socket_t *socks)
+static int imap_getsock(struct Curl_easy *data,
+ struct connectdata *conn,
+ curl_socket_t *socks)
{
- return Curl_pp_getsock(&conn->proto.imapc.pp, socks);
+ return Curl_pp_getsock(data, &conn->proto.imapc.pp, socks);
}
/***********************************************************************
@@ -1403,9 +1424,10 @@ static int imap_getsock(struct connectdata *conn, curl_socket_t *socks)
* The variable 'done' points to will be TRUE if the protocol-layer connect
* phase is done when this function returns, or FALSE if not.
*/
-static CURLcode imap_connect(struct connectdata *conn, bool *done)
+static CURLcode imap_connect(struct Curl_easy *data, bool *done)
{
CURLcode result = CURLE_OK;
+ struct connectdata *conn = data->conn;
struct imap_conn *imapc = &conn->proto.imapc;
struct pingpong *pp = &imapc->pp;
@@ -1414,18 +1436,16 @@ static CURLcode imap_connect(struct connectdata *conn, bool *done)
/* We always support persistent connections in IMAP */
connkeep(conn, "IMAP default");
- /* Set the default response time-out */
- pp->response_time = RESP_TIMEOUT;
- pp->statemach_act = imap_statemach_act;
- pp->endofresp = imap_endofresp;
- pp->conn = conn;
+ 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, &saslimap);
+ Curl_dyn_init(&imapc->dyn, DYN_IMAP_CMD);
/* Initialise the pingpong layer */
- Curl_pp_init(pp);
+ Curl_pp_setup(pp);
+ Curl_pp_init(data, pp);
/* Parse the URL options */
result = imap_parse_url_options(conn);
@@ -1433,12 +1453,12 @@ static CURLcode imap_connect(struct connectdata *conn, bool *done)
return result;
/* Start off waiting for the server greeting response */
- state(conn, IMAP_SERVERGREET);
+ state(data, IMAP_SERVERGREET);
/* Start off with an response id of '*' */
strcpy(imapc->resptag, "*");
- result = imap_multi_statemach(conn, done);
+ result = imap_multi_statemach(data, done);
return result;
}
@@ -1452,12 +1472,12 @@ static CURLcode imap_connect(struct connectdata *conn, bool *done)
*
* Input argument is already checked for validity.
*/
-static CURLcode imap_done(struct connectdata *conn, CURLcode status,
+static CURLcode imap_done(struct Curl_easy *data, CURLcode status,
bool premature)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
- struct IMAP *imap = data->req.protop;
+ struct connectdata *conn = data->conn;
+ struct IMAP *imap = data->req.p.imap;
(void)premature;
@@ -1474,17 +1494,17 @@ static CURLcode imap_done(struct connectdata *conn, CURLcode status,
/* Handle responses after FETCH or APPEND transfer has finished */
if(!data->set.upload && data->set.mimepost.kind == MIMEKIND_NONE)
- state(conn, IMAP_FETCH_FINAL);
+ state(data, IMAP_FETCH_FINAL);
else {
/* End the APPEND command first by sending an empty line */
- result = Curl_pp_sendf(&conn->proto.imapc.pp, "%s", "");
+ result = Curl_pp_sendf(data, &conn->proto.imapc.pp, "%s", "");
if(!result)
- state(conn, IMAP_APPEND_FINAL);
+ state(data, IMAP_APPEND_FINAL);
}
/* Run the state-machine */
if(!result)
- result = imap_block_statemach(conn, FALSE);
+ result = imap_block_statemach(data, conn, FALSE);
}
/* Cleanup our per-request based variables */
@@ -1511,19 +1531,19 @@ static CURLcode imap_done(struct connectdata *conn, CURLcode status,
* This is the actual DO function for IMAP. Fetch or append a message, or do
* other things according to the options previously setup.
*/
-static CURLcode imap_perform(struct connectdata *conn, bool *connected,
+static CURLcode imap_perform(struct Curl_easy *data, bool *connected,
bool *dophase_done)
{
/* This is IMAP and no proxy */
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
- struct IMAP *imap = data->req.protop;
+ struct connectdata *conn = data->conn;
+ struct IMAP *imap = data->req.p.imap;
struct imap_conn *imapc = &conn->proto.imapc;
bool selected = FALSE;
- DEBUGF(infof(conn->data, "DO phase starts\n"));
+ DEBUGF(infof(data, "DO phase starts\n"));
- if(conn->data->set.opt_no_body) {
+ if(data->set.opt_no_body) {
/* Requested no body means no transfer */
imap->transfer = FTPTRANSFER_INFO;
}
@@ -1539,36 +1559,36 @@ static CURLcode imap_perform(struct connectdata *conn, bool *connected,
selected = TRUE;
/* Start the first command in the DO phase */
- if(conn->data->set.upload || data->set.mimepost.kind != MIMEKIND_NONE)
+ if(data->set.upload || data->set.mimepost.kind != MIMEKIND_NONE)
/* APPEND can be executed directly */
- result = imap_perform_append(conn);
+ result = imap_perform_append(data);
else if(imap->custom && (selected || !imap->mailbox))
/* Custom command using the same mailbox or no mailbox */
- result = imap_perform_list(conn);
+ result = imap_perform_list(data);
else if(!imap->custom && selected && (imap->uid || imap->mindex))
/* FETCH from the same mailbox */
- result = imap_perform_fetch(conn);
+ result = imap_perform_fetch(data, conn);
else if(!imap->custom && selected && imap->query)
/* SEARCH the current mailbox */
- result = imap_perform_search(conn);
+ result = imap_perform_search(data, conn);
else if(imap->mailbox && !selected &&
(imap->custom || imap->uid || imap->mindex || imap->query))
/* SELECT the mailbox */
- result = imap_perform_select(conn);
+ result = imap_perform_select(data);
else
/* LIST */
- result = imap_perform_list(conn);
+ result = imap_perform_list(data);
if(result)
return result;
/* Run the state-machine */
- result = imap_multi_statemach(conn, dophase_done);
+ result = imap_multi_statemach(data, dophase_done);
*connected = conn->bits.tcpconnect[FIRSTSOCKET];
if(*dophase_done)
- DEBUGF(infof(conn->data, "DO phase is complete\n"));
+ DEBUGF(infof(data, "DO phase is complete\n"));
return result;
}
@@ -1582,23 +1602,22 @@ static CURLcode imap_perform(struct connectdata *conn, bool *connected,
*
* The input argument is already checked for validity.
*/
-static CURLcode imap_do(struct connectdata *conn, bool *done)
+static CURLcode imap_do(struct Curl_easy *data, bool *done)
{
CURLcode result = CURLE_OK;
-
*done = FALSE; /* default to false */
/* Parse the URL path */
- result = imap_parse_url_path(conn);
+ result = imap_parse_url_path(data);
if(result)
return result;
/* Parse the custom request */
- result = imap_parse_custom_request(conn);
+ result = imap_parse_custom_request(data);
if(result)
return result;
- result = imap_regular_transfer(conn, done);
+ result = imap_regular_transfer(data, done);
return result;
}
@@ -1610,9 +1629,11 @@ static CURLcode imap_do(struct connectdata *conn, bool *done)
* Disconnect from an IMAP server. Cleanup protocol-specific per-connection
* resources. BLOCKING.
*/
-static CURLcode imap_disconnect(struct connectdata *conn, bool dead_connection)
+static CURLcode imap_disconnect(struct Curl_easy *data,
+ struct connectdata *conn, bool dead_connection)
{
struct imap_conn *imapc = &conn->proto.imapc;
+ (void)data;
/* We cannot send quit unconditionally. If this connection is stale or
bad in any way, sending quit and waiting around here will make the
@@ -1620,12 +1641,14 @@ static CURLcode imap_disconnect(struct connectdata *conn, bool dead_connection)
/* The IMAP session may or may not have been allocated/setup at this
point! */
- if(!dead_connection && imapc->pp.conn && imapc->pp.conn->bits.protoconnstart)
- if(!imap_perform_logout(conn))
- (void)imap_block_statemach(conn, TRUE); /* ignore errors on LOGOUT */
+ if(!dead_connection && conn->bits.protoconnstart) {
+ if(!imap_perform_logout(data, conn))
+ (void)imap_block_statemach(data, conn, 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);
@@ -1638,30 +1661,30 @@ static CURLcode imap_disconnect(struct connectdata *conn, bool dead_connection)
}
/* Call this when the DO phase has completed */
-static CURLcode imap_dophase_done(struct connectdata *conn, bool connected)
+static CURLcode imap_dophase_done(struct Curl_easy *data, bool connected)
{
- struct IMAP *imap = conn->data->req.protop;
+ struct IMAP *imap = data->req.p.imap;
(void)connected;
if(imap->transfer != FTPTRANSFER_BODY)
/* no data to transfer */
- Curl_setup_transfer(conn->data, -1, -1, FALSE, -1);
+ Curl_setup_transfer(data, -1, -1, FALSE, -1);
return CURLE_OK;
}
/* Called from multi.c while DOing */
-static CURLcode imap_doing(struct connectdata *conn, bool *dophase_done)
+static CURLcode imap_doing(struct Curl_easy *data, bool *dophase_done)
{
- CURLcode result = imap_multi_statemach(conn, dophase_done);
+ CURLcode result = imap_multi_statemach(data, dophase_done);
if(result)
- DEBUGF(infof(conn->data, "DO phase failed\n"));
+ DEBUGF(infof(data, "DO phase failed\n"));
else if(*dophase_done) {
- result = imap_dophase_done(conn, FALSE /* not connected */);
+ result = imap_dophase_done(data, FALSE /* not connected */);
- DEBUGF(infof(conn->data, "DO phase is complete\n"));
+ DEBUGF(infof(data, "DO phase is complete\n"));
}
return result;
@@ -1676,12 +1699,11 @@ static CURLcode imap_doing(struct connectdata *conn, bool *dophase_done)
* Performs all commands done before a regular transfer between a local and a
* remote host.
*/
-static CURLcode imap_regular_transfer(struct connectdata *conn,
+static CURLcode imap_regular_transfer(struct Curl_easy *data,
bool *dophase_done)
{
CURLcode result = CURLE_OK;
bool connected = FALSE;
- struct Curl_easy *data = conn->data;
/* Make sure size is unknown at this point */
data->req.size = -1;
@@ -1693,19 +1715,20 @@ static CURLcode imap_regular_transfer(struct connectdata *conn,
Curl_pgrsSetDownloadSize(data, -1);
/* Carry out the perform */
- result = imap_perform(conn, &connected, dophase_done);
+ result = imap_perform(data, &connected, dophase_done);
/* Perform post DO phase operations if necessary */
if(!result && *dophase_done)
- result = imap_dophase_done(conn, connected);
+ result = imap_dophase_done(data, connected);
return result;
}
-static CURLcode imap_setup_connection(struct connectdata *conn)
+static CURLcode imap_setup_connection(struct Curl_easy *data,
+ struct connectdata *conn)
{
/* Initialise the IMAP layer */
- CURLcode result = imap_init(conn);
+ CURLcode result = imap_init(data);
if(result)
return result;
@@ -1723,34 +1746,30 @@ static CURLcode imap_setup_connection(struct connectdata *conn)
*
* Designed to never block.
*/
-static CURLcode imap_sendf(struct connectdata *conn, const char *fmt, ...)
+static CURLcode imap_sendf(struct Curl_easy *data,
+ struct connectdata *conn, const char *fmt, ...)
{
CURLcode result = CURLE_OK;
struct imap_conn *imapc = &conn->proto.imapc;
- char *taggedfmt;
- va_list ap;
DEBUGASSERT(fmt);
- /* Calculate the next command ID wrapping at 3 digits */
- imapc->cmdid = (imapc->cmdid + 1) % 1000;
-
/* Calculate the tag based on the connection ID and command ID */
msnprintf(imapc->resptag, sizeof(imapc->resptag), "%c%03d",
- 'A' + curlx_sltosi(conn->connection_id % 26), imapc->cmdid);
-
- /* Prefix the format with the tag */
- taggedfmt = aprintf("%s %s", imapc->resptag, fmt);
- if(!taggedfmt)
- return CURLE_OUT_OF_MEMORY;
+ 'A' + curlx_sltosi(conn->connection_id % 26),
+ (++imapc->cmdid)%1000);
- /* Send the data with the tag */
- va_start(ap, fmt);
- result = Curl_pp_vsendf(&imapc->pp, taggedfmt, ap);
- va_end(ap);
-
- free(taggedfmt);
+ /* start with a blank buffer */
+ Curl_dyn_reset(&imapc->dyn);
+ /* append tag + space + fmt */
+ result = Curl_dyn_addf(&imapc->dyn, "%s %s", imapc->resptag, fmt);
+ if(!result) {
+ va_list ap;
+ va_start(ap, fmt);
+ result = Curl_pp_vsendf(data, &imapc->pp, Curl_dyn_ptr(&imapc->dyn), ap);
+ va_end(ap);
+ }
return result;
}
@@ -1937,12 +1956,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 connectdata *conn)
+static CURLcode imap_parse_url_path(struct Curl_easy *data)
{
/* The imap struct is already initialised in imap_connect() */
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
- struct IMAP *imap = data->req.protop;
+ struct IMAP *imap = data->req.p.imap;
const char *begin = &data->state.up.path[1]; /* skip leading slash */
const char *ptr = begin;
@@ -1997,7 +2015,7 @@ static CURLcode imap_parse_url_path(struct connectdata *conn)
return result;
}
- DEBUGF(infof(conn->data, "IMAP URL parameter '%s' = '%s'\n", name, value));
+ DEBUGF(infof(data, "IMAP URL parameter '%s' = '%s'\n", name, value));
/* Process the known hierarchical parameters (UIDVALIDITY, UID, SECTION and
PARTIAL) stripping of the trailing slash character if it is present.
@@ -2070,11 +2088,10 @@ static CURLcode imap_parse_url_path(struct connectdata *conn)
*
* Parse the custom request.
*/
-static CURLcode imap_parse_custom_request(struct connectdata *conn)
+static CURLcode imap_parse_custom_request(struct Curl_easy *data)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
- struct IMAP *imap = data->req.protop;
+ struct IMAP *imap = data->req.p.imap;
const char *custom = data->set.str[STRING_CUSTOMREQUEST];
if(custom) {
diff --git a/Utilities/cmcurl/lib/imap.h b/Utilities/cmcurl/lib/imap.h
index 4786f5624..ef6515d8c 100644
--- a/Utilities/cmcurl/lib/imap.h
+++ b/Utilities/cmcurl/lib/imap.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2009 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2009 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -75,13 +75,14 @@ struct imap_conn {
bool preauth; /* Is this connection PREAUTH? */
struct SASL sasl; /* SASL-related parameters */
unsigned int preftype; /* Preferred authentication type */
- int cmdid; /* Last used command ID */
+ unsigned int cmdid; /* Last used command ID */
char resptag[5]; /* Response tag to wait for */
bool tls_supported; /* StartTLS capability supported by server */
bool login_disabled; /* LOGIN command disabled by server */
bool ir_supported; /* Initial response supported by server */
char *mailbox; /* The last selected mailbox */
char *mailbox_uidvalidity; /* UIDVALIDITY parsed from select response */
+ struct dynbuf dyn; /* for the IMAP commands */
};
extern const struct Curl_handler Curl_handler_imap;
diff --git a/Utilities/cmcurl/lib/inet_ntop.h b/Utilities/cmcurl/lib/inet_ntop.h
index 9d3f237f3..067632aae 100644
--- a/Utilities/cmcurl/lib/inet_ntop.h
+++ b/Utilities/cmcurl/lib/inet_ntop.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
diff --git a/Utilities/cmcurl/lib/inet_pton.c b/Utilities/cmcurl/lib/inet_pton.c
index 9c87a0562..4923cae24 100644
--- a/Utilities/cmcurl/lib/inet_pton.c
+++ b/Utilities/cmcurl/lib/inet_pton.c
@@ -1,6 +1,6 @@
/* This is from the BIND 4.9.4 release, modified to compile by itself */
-/* Copyright (c) 1996 - 2019 by Internet Software Consortium.
+/* Copyright (c) 1996 - 2020 by Internet Software Consortium.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -112,7 +112,7 @@ inet_pton4(const char *src, unsigned char *dst)
if(val > 255)
return (0);
*tp = (unsigned char)val;
- if(! saw_digit) {
+ if(!saw_digit) {
if(++octets > 4)
return (0);
saw_digit = 1;
diff --git a/Utilities/cmcurl/lib/inet_pton.h b/Utilities/cmcurl/lib/inet_pton.h
index e695af9c6..ec1237309 100644
--- a/Utilities/cmcurl/lib/inet_pton.h
+++ b/Utilities/cmcurl/lib/inet_pton.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
diff --git a/Utilities/cmcurl/lib/krb5.c b/Utilities/cmcurl/lib/krb5.c
index 5bd8e7181..46116ce59 100644
--- a/Utilities/cmcurl/lib/krb5.c
+++ b/Utilities/cmcurl/lib/krb5.c
@@ -2,7 +2,7 @@
*
* Copyright (c) 1995, 1996, 1997, 1998, 1999 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
- * Copyright (c) 2004 - 2019 Daniel Stenberg
+ * Copyright (c) 2004 - 2021 Daniel Stenberg
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -45,14 +45,74 @@
#include "ftp.h"
#include "curl_gssapi.h"
#include "sendf.h"
-#include "curl_sec.h"
+#include "curl_krb5.h"
#include "warnless.h"
+#include "non-ascii.h"
+#include "strcase.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"
+static CURLcode ftpsend(struct Curl_easy *data, struct connectdata *conn,
+ const char *cmd)
+{
+ ssize_t bytes_written;
+#define SBUF_SIZE 1024
+ char s[SBUF_SIZE];
+ size_t write_len;
+ char *sptr = s;
+ CURLcode result = CURLE_OK;
+#ifdef HAVE_GSSAPI
+ enum protection_level data_sec = conn->data_prot;
+#endif
+
+ if(!cmd)
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+
+ write_len = strlen(cmd);
+ if(!write_len || write_len > (sizeof(s) -3))
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+
+ memcpy(&s, cmd, write_len);
+ strcpy(&s[write_len], "\r\n"); /* append a trailing CRLF */
+ write_len += 2;
+ bytes_written = 0;
+
+ result = Curl_convert_to_network(data, s, write_len);
+ /* Curl_convert_to_network calls failf if unsuccessful */
+ if(result)
+ return result;
+
+ for(;;) {
+#ifdef HAVE_GSSAPI
+ conn->data_prot = PROT_CMD;
+#endif
+ result = Curl_write(data, conn->sock[FIRSTSOCKET], sptr, write_len,
+ &bytes_written);
+#ifdef HAVE_GSSAPI
+ DEBUGASSERT(data_sec > PROT_NONE && data_sec < PROT_LAST);
+ conn->data_prot = data_sec;
+#endif
+
+ if(result)
+ break;
+
+ Curl_debug(data, CURLINFO_HEADER_OUT, sptr, (size_t)bytes_written);
+
+ if(bytes_written != (ssize_t)write_len) {
+ write_len -= bytes_written;
+ sptr += bytes_written;
+ }
+ else
+ break;
+ }
+
+ return result;
+}
+
static int
krb5_init(void *app_data)
{
@@ -143,14 +203,13 @@ krb5_encode(void *app_data, const void *from, int length, int level, void **to)
}
static int
-krb5_auth(void *app_data, struct connectdata *conn)
+krb5_auth(void *app_data, struct Curl_easy *data, struct connectdata *conn)
{
int ret = AUTH_OK;
char *p;
const char *host = conn->host.name;
ssize_t nread;
curl_socklen_t l = sizeof(conn->local_addr);
- struct Curl_easy *data = conn->data;
CURLcode result;
const char *service = data->set.str[STRING_SERVICE_NAME] ?
data->set.str[STRING_SERVICE_NAME] :
@@ -183,11 +242,11 @@ krb5_auth(void *app_data, struct connectdata *conn)
for(;;) {
/* this really shouldn't be repeated here, but can't help it */
if(service == srv_host) {
- result = Curl_ftpsend(conn, "AUTH GSSAPI");
+ result = ftpsend(data, conn, "AUTH GSSAPI");
if(result)
return -2;
- if(Curl_GetFTPResponse(&nread, conn, NULL))
+ if(Curl_GetFTPResponse(data, &nread, NULL))
return -1;
if(data->state.buffer[0] != '3')
@@ -260,7 +319,7 @@ krb5_auth(void *app_data, struct connectdata *conn)
cmd = aprintf("ADAT %s", p);
if(cmd)
- result = Curl_ftpsend(conn, cmd);
+ result = ftpsend(data, conn, cmd);
else
result = CURLE_OUT_OF_MEMORY;
@@ -272,7 +331,7 @@ krb5_auth(void *app_data, struct connectdata *conn)
break;
}
- if(Curl_GetFTPResponse(&nread, conn, NULL)) {
+ if(Curl_GetFTPResponse(data, &nread, NULL)) {
ret = -1;
break;
}
@@ -326,16 +385,528 @@ static void krb5_end(void *app_data)
}
}
-struct Curl_sec_client_mech Curl_krb5_client_mech = {
- "GSSAPI",
- sizeof(gss_ctx_id_t),
- krb5_init,
- krb5_auth,
- krb5_end,
- krb5_check_prot,
- krb5_overhead,
- krb5_encode,
- krb5_decode
+static struct Curl_sec_client_mech Curl_krb5_client_mech = {
+ "GSSAPI",
+ sizeof(gss_ctx_id_t),
+ krb5_init,
+ krb5_auth,
+ krb5_end,
+ krb5_check_prot,
+ krb5_overhead,
+ krb5_encode,
+ krb5_decode
+};
+
+static const struct {
+ enum protection_level level;
+ const char *name;
+} level_names[] = {
+ { PROT_CLEAR, "clear" },
+ { PROT_SAFE, "safe" },
+ { PROT_CONFIDENTIAL, "confidential" },
+ { PROT_PRIVATE, "private" }
};
+static enum protection_level
+name_to_level(const char *name)
+{
+ int i;
+ for(i = 0; i < (int)sizeof(level_names)/(int)sizeof(level_names[0]); i++)
+ if(checkprefix(name, level_names[i].name))
+ return level_names[i].level;
+ return PROT_NONE;
+}
+
+/* Convert a protocol |level| to its char representation.
+ We take an int to catch programming mistakes. */
+static char level_to_char(int level)
+{
+ switch(level) {
+ case PROT_CLEAR:
+ return 'C';
+ case PROT_SAFE:
+ return 'S';
+ case PROT_CONFIDENTIAL:
+ return 'E';
+ case PROT_PRIVATE:
+ return 'P';
+ case PROT_CMD:
+ /* Fall through */
+ default:
+ /* Those 2 cases should not be reached! */
+ break;
+ }
+ DEBUGASSERT(0);
+ /* Default to the most secure alternative. */
+ return 'P';
+}
+
+/* Send an FTP command defined by |message| and the optional arguments. The
+ function returns the ftp_code. If an error occurs, -1 is returned. */
+static int ftp_send_command(struct Curl_easy *data, const char *message, ...)
+{
+ int ftp_code;
+ ssize_t nread = 0;
+ va_list args;
+ char print_buffer[50];
+
+ va_start(args, message);
+ mvsnprintf(print_buffer, sizeof(print_buffer), message, args);
+ va_end(args);
+
+ if(ftpsend(data, data->conn, print_buffer)) {
+ ftp_code = -1;
+ }
+ else {
+ if(Curl_GetFTPResponse(data, &nread, &ftp_code))
+ ftp_code = -1;
+ }
+
+ (void)nread; /* Unused */
+ return ftp_code;
+}
+
+/* Read |len| from the socket |fd| and store it in |to|. Return a CURLcode
+ saying whether an error occurred or CURLE_OK if |len| was read. */
+static CURLcode
+socket_read(curl_socket_t fd, void *to, size_t len)
+{
+ char *to_p = to;
+ CURLcode result;
+ ssize_t nread = 0;
+
+ while(len > 0) {
+ result = Curl_read_plain(fd, to_p, len, &nread);
+ if(!result) {
+ len -= nread;
+ to_p += nread;
+ }
+ else {
+ if(result == CURLE_AGAIN)
+ continue;
+ return result;
+ }
+ }
+ return CURLE_OK;
+}
+
+
+/* Write |len| bytes from the buffer |to| to the socket |fd|. Return a
+ CURLcode saying whether an error occurred or CURLE_OK if |len| was
+ written. */
+static CURLcode
+socket_write(struct Curl_easy *data, curl_socket_t fd, const void *to,
+ size_t len)
+{
+ const char *to_p = to;
+ CURLcode result;
+ ssize_t written;
+
+ while(len > 0) {
+ result = Curl_write_plain(data, fd, to_p, len, &written);
+ if(!result) {
+ len -= written;
+ to_p += written;
+ }
+ else {
+ if(result == CURLE_AGAIN)
+ continue;
+ return result;
+ }
+ }
+ return CURLE_OK;
+}
+
+static CURLcode read_data(struct connectdata *conn,
+ curl_socket_t fd,
+ struct krb5buffer *buf)
+{
+ int len;
+ CURLcode result;
+
+ result = socket_read(fd, &len, sizeof(len));
+ if(result)
+ return result;
+
+ if(len) {
+ /* only realloc if there was a length */
+ len = ntohl(len);
+ buf->data = Curl_saferealloc(buf->data, len);
+ }
+ if(!len || !buf->data)
+ return CURLE_OUT_OF_MEMORY;
+
+ result = socket_read(fd, buf->data, len);
+ if(result)
+ return result;
+ buf->size = conn->mech->decode(conn->app_data, buf->data, len,
+ conn->data_prot, conn);
+ buf->index = 0;
+ return CURLE_OK;
+}
+
+static size_t
+buffer_read(struct krb5buffer *buf, void *data, size_t len)
+{
+ if(buf->size - buf->index < len)
+ len = buf->size - buf->index;
+ memcpy(data, (char *)buf->data + buf->index, len);
+ buf->index += len;
+ return len;
+}
+
+/* Matches Curl_recv signature */
+static ssize_t sec_recv(struct Curl_easy *data, int sockindex,
+ char *buffer, size_t len, CURLcode *err)
+{
+ size_t bytes_read;
+ size_t total_read = 0;
+ struct connectdata *conn = data->conn;
+ curl_socket_t fd = conn->sock[sockindex];
+
+ *err = CURLE_OK;
+
+ /* Handle clear text response. */
+ if(conn->sec_complete == 0 || conn->data_prot == PROT_CLEAR)
+ return sread(fd, buffer, len);
+
+ if(conn->in_buffer.eof_flag) {
+ conn->in_buffer.eof_flag = 0;
+ return 0;
+ }
+
+ bytes_read = buffer_read(&conn->in_buffer, buffer, len);
+ len -= bytes_read;
+ total_read += bytes_read;
+ buffer += bytes_read;
+
+ while(len > 0) {
+ if(read_data(conn, fd, &conn->in_buffer))
+ return -1;
+ if(conn->in_buffer.size == 0) {
+ if(bytes_read > 0)
+ conn->in_buffer.eof_flag = 1;
+ return bytes_read;
+ }
+ bytes_read = buffer_read(&conn->in_buffer, buffer, len);
+ len -= bytes_read;
+ total_read += bytes_read;
+ buffer += bytes_read;
+ }
+ return total_read;
+}
+
+/* Send |length| bytes from |from| to the |fd| socket taking care of encoding
+ and negotiating with the server. |from| can be NULL. */
+static void do_sec_send(struct Curl_easy *data, struct connectdata *conn,
+ curl_socket_t fd, const char *from, int length)
+{
+ int bytes, htonl_bytes; /* 32-bit integers for htonl */
+ char *buffer = NULL;
+ char *cmd_buffer;
+ size_t cmd_size = 0;
+ CURLcode error;
+ enum protection_level prot_level = conn->data_prot;
+ bool iscmd = (prot_level == PROT_CMD)?TRUE:FALSE;
+
+ DEBUGASSERT(prot_level > PROT_NONE && prot_level < PROT_LAST);
+
+ if(iscmd) {
+ if(!strncmp(from, "PASS ", 5) || !strncmp(from, "ACCT ", 5))
+ prot_level = PROT_PRIVATE;
+ else
+ prot_level = conn->command_prot;
+ }
+ bytes = conn->mech->encode(conn->app_data, from, length, prot_level,
+ (void **)&buffer);
+ if(!buffer || bytes <= 0)
+ return; /* error */
+
+ if(iscmd) {
+ error = Curl_base64_encode(data, buffer, curlx_sitouz(bytes),
+ &cmd_buffer, &cmd_size);
+ if(error) {
+ free(buffer);
+ return; /* error */
+ }
+ if(cmd_size > 0) {
+ static const char *enc = "ENC ";
+ static const char *mic = "MIC ";
+ if(prot_level == PROT_PRIVATE)
+ socket_write(data, fd, enc, 4);
+ else
+ socket_write(data, fd, mic, 4);
+
+ socket_write(data, fd, cmd_buffer, cmd_size);
+ socket_write(data, fd, "\r\n", 2);
+ infof(data, "Send: %s%s\n", prot_level == PROT_PRIVATE?enc:mic,
+ cmd_buffer);
+ free(cmd_buffer);
+ }
+ }
+ else {
+ htonl_bytes = htonl(bytes);
+ socket_write(data, fd, &htonl_bytes, sizeof(htonl_bytes));
+ socket_write(data, fd, buffer, curlx_sitouz(bytes));
+ }
+ free(buffer);
+}
+
+static ssize_t sec_write(struct Curl_easy *data, struct connectdata *conn,
+ curl_socket_t fd, const char *buffer, size_t length)
+{
+ ssize_t tx = 0, len = conn->buffer_size;
+
+ len -= conn->mech->overhead(conn->app_data, conn->data_prot,
+ curlx_sztosi(len));
+ if(len <= 0)
+ len = length;
+ while(length) {
+ if(length < (size_t)len)
+ len = length;
+
+ do_sec_send(data, conn, fd, buffer, curlx_sztosi(len));
+ length -= len;
+ buffer += len;
+ tx += len;
+ }
+ return tx;
+}
+
+/* Matches Curl_send signature */
+static ssize_t sec_send(struct Curl_easy *data, int sockindex,
+ const void *buffer, size_t len, CURLcode *err)
+{
+ struct connectdata *conn = data->conn;
+ curl_socket_t fd = conn->sock[sockindex];
+ *err = CURLE_OK;
+ return sec_write(data, conn, fd, buffer, len);
+}
+
+int Curl_sec_read_msg(struct Curl_easy *data, struct connectdata *conn,
+ char *buffer, enum protection_level level)
+{
+ /* decoded_len should be size_t or ssize_t but conn->mech->decode returns an
+ int */
+ int decoded_len;
+ char *buf;
+ int ret_code = 0;
+ size_t decoded_sz = 0;
+ CURLcode error;
+
+ (void) data;
+
+ if(!conn->mech)
+ /* not inititalized, return error */
+ return -1;
+
+ DEBUGASSERT(level > PROT_NONE && level < PROT_LAST);
+
+ error = Curl_base64_decode(buffer + 4, (unsigned char **)&buf, &decoded_sz);
+ if(error || decoded_sz == 0)
+ return -1;
+
+ if(decoded_sz > (size_t)INT_MAX) {
+ free(buf);
+ return -1;
+ }
+ decoded_len = curlx_uztosi(decoded_sz);
+
+ decoded_len = conn->mech->decode(conn->app_data, buf, decoded_len,
+ level, conn);
+ if(decoded_len <= 0) {
+ free(buf);
+ return -1;
+ }
+
+ {
+ buf[decoded_len] = '\n';
+ Curl_debug(data, CURLINFO_HEADER_IN, buf, decoded_len + 1);
+ }
+
+ buf[decoded_len] = '\0';
+ if(decoded_len <= 3)
+ /* suspiciously short */
+ return 0;
+
+ if(buf[3] != '-')
+ /* safe to ignore return code */
+ (void)sscanf(buf, "%d", &ret_code);
+
+ if(buf[decoded_len - 1] == '\n')
+ buf[decoded_len - 1] = '\0';
+ strcpy(buffer, buf);
+ free(buf);
+ return ret_code;
+}
+
+static int sec_set_protection_level(struct Curl_easy *data)
+{
+ int code;
+ struct connectdata *conn = data->conn;
+ enum protection_level level = conn->request_data_prot;
+
+ DEBUGASSERT(level > PROT_NONE && level < PROT_LAST);
+
+ if(!conn->sec_complete) {
+ infof(data, "Trying to change the protection level after the"
+ " completion of the data exchange.\n");
+ return -1;
+ }
+
+ /* Bail out if we try to set up the same level */
+ if(conn->data_prot == level)
+ return 0;
+
+ if(level) {
+ char *pbsz;
+ static unsigned int buffer_size = 1 << 20; /* 1048576 */
+
+ code = ftp_send_command(data, "PBSZ %u", buffer_size);
+ if(code < 0)
+ return -1;
+
+ if(code/100 != 2) {
+ failf(data, "Failed to set the protection's buffer size.");
+ return -1;
+ }
+ conn->buffer_size = buffer_size;
+
+ pbsz = strstr(data->state.buffer, "PBSZ=");
+ if(pbsz) {
+ /* ignore return code, use default value if it fails */
+ (void)sscanf(pbsz, "PBSZ=%u", &buffer_size);
+ if(buffer_size < conn->buffer_size)
+ conn->buffer_size = buffer_size;
+ }
+ }
+
+ /* Now try to negiociate the protection level. */
+ code = ftp_send_command(data, "PROT %c", level_to_char(level));
+
+ if(code < 0)
+ return -1;
+
+ if(code/100 != 2) {
+ failf(data, "Failed to set the protection level.");
+ return -1;
+ }
+
+ conn->data_prot = level;
+ if(level == PROT_PRIVATE)
+ conn->command_prot = level;
+
+ return 0;
+}
+
+int
+Curl_sec_request_prot(struct connectdata *conn, const char *level)
+{
+ enum protection_level l = name_to_level(level);
+ if(l == PROT_NONE)
+ return -1;
+ DEBUGASSERT(l > PROT_NONE && l < PROT_LAST);
+ conn->request_data_prot = l;
+ return 0;
+}
+
+static CURLcode choose_mech(struct Curl_easy *data, struct connectdata *conn)
+{
+ int ret;
+ void *tmp_allocation;
+ const struct Curl_sec_client_mech *mech = &Curl_krb5_client_mech;
+
+ tmp_allocation = realloc(conn->app_data, mech->size);
+ if(tmp_allocation == NULL) {
+ failf(data, "Failed realloc of size %zu", mech->size);
+ mech = NULL;
+ return CURLE_OUT_OF_MEMORY;
+ }
+ conn->app_data = tmp_allocation;
+
+ if(mech->init) {
+ ret = mech->init(conn->app_data);
+ if(ret) {
+ infof(data, "Failed initialization for %s. Skipping it.\n",
+ mech->name);
+ return CURLE_FAILED_INIT;
+ }
+ }
+
+ infof(data, "Trying mechanism %s...\n", mech->name);
+ ret = ftp_send_command(data, "AUTH %s", mech->name);
+ if(ret < 0)
+ return CURLE_COULDNT_CONNECT;
+
+ if(ret/100 != 3) {
+ switch(ret) {
+ case 504:
+ infof(data, "Mechanism %s is not supported by the server (server "
+ "returned ftp code: 504).\n", mech->name);
+ break;
+ case 534:
+ infof(data, "Mechanism %s was rejected by the server (server returned "
+ "ftp code: 534).\n", mech->name);
+ break;
+ default:
+ if(ret/100 == 5) {
+ infof(data, "server does not support the security extensions\n");
+ return CURLE_USE_SSL_FAILED;
+ }
+ break;
+ }
+ return CURLE_LOGIN_DENIED;
+ }
+
+ /* Authenticate */
+ ret = mech->auth(conn->app_data, data, conn);
+
+ if(ret != AUTH_CONTINUE) {
+ if(ret != AUTH_OK) {
+ /* Mechanism has dumped the error to stderr, don't error here. */
+ return CURLE_USE_SSL_FAILED;
+ }
+ DEBUGASSERT(ret == AUTH_OK);
+
+ conn->mech = mech;
+ conn->sec_complete = 1;
+ conn->recv[FIRSTSOCKET] = sec_recv;
+ conn->send[FIRSTSOCKET] = sec_send;
+ conn->recv[SECONDARYSOCKET] = sec_recv;
+ conn->send[SECONDARYSOCKET] = sec_send;
+ conn->command_prot = PROT_SAFE;
+ /* Set the requested protection level */
+ /* BLOCKING */
+ (void)sec_set_protection_level(data);
+ }
+
+ return CURLE_OK;
+}
+
+CURLcode
+Curl_sec_login(struct Curl_easy *data, struct connectdata *conn)
+{
+ return choose_mech(data, conn);
+}
+
+
+void
+Curl_sec_end(struct connectdata *conn)
+{
+ if(conn->mech != NULL && conn->mech->end)
+ conn->mech->end(conn->app_data);
+ free(conn->app_data);
+ conn->app_data = NULL;
+ if(conn->in_buffer.data) {
+ free(conn->in_buffer.data);
+ conn->in_buffer.data = NULL;
+ conn->in_buffer.size = 0;
+ conn->in_buffer.index = 0;
+ conn->in_buffer.eof_flag = 0;
+ }
+ conn->sec_complete = 0;
+ conn->data_prot = PROT_CLEAR;
+ conn->mech = NULL;
+}
+
#endif /* HAVE_GSSAPI && !CURL_DISABLE_FTP */
diff --git a/Utilities/cmcurl/lib/ldap.c b/Utilities/cmcurl/lib/ldap.c
index 512def659..307ebebaf 100644
--- a/Utilities/cmcurl/lib/ldap.c
+++ b/Utilities/cmcurl/lib/ldap.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -100,7 +100,8 @@ struct ldap_urldesc {
#undef LDAPURLDesc
#define LDAPURLDesc struct ldap_urldesc
-static int _ldap_url_parse(const struct connectdata *conn,
+static int _ldap_url_parse(struct Curl_easy *data,
+ const struct connectdata *conn,
LDAPURLDesc **ludp);
static void _ldap_free_urldesc(LDAPURLDesc *ludp);
@@ -126,7 +127,7 @@ static void _ldap_free_urldesc(LDAPURLDesc *ludp);
#endif
-static CURLcode Curl_ldap(struct connectdata *conn, bool *done);
+static CURLcode ldap_do(struct Curl_easy *data, bool *done);
/*
* LDAP protocol handler.
@@ -135,7 +136,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done);
const struct Curl_handler Curl_handler_ldap = {
"LDAP", /* scheme */
ZERO_NULL, /* setup_connection */
- Curl_ldap, /* do_it */
+ ldap_do, /* do_it */
ZERO_NULL, /* done */
ZERO_NULL, /* do_more */
ZERO_NULL, /* connect_it */
@@ -150,6 +151,7 @@ const struct Curl_handler Curl_handler_ldap = {
ZERO_NULL, /* connection_check */
PORT_LDAP, /* defport */
CURLPROTO_LDAP, /* protocol */
+ CURLPROTO_LDAP, /* family */
PROTOPT_NONE /* flags */
};
@@ -161,7 +163,7 @@ const struct Curl_handler Curl_handler_ldap = {
const struct Curl_handler Curl_handler_ldaps = {
"LDAPS", /* scheme */
ZERO_NULL, /* setup_connection */
- Curl_ldap, /* do_it */
+ ldap_do, /* do_it */
ZERO_NULL, /* done */
ZERO_NULL, /* do_more */
ZERO_NULL, /* connect_it */
@@ -176,6 +178,7 @@ const struct Curl_handler Curl_handler_ldaps = {
ZERO_NULL, /* connection_check */
PORT_LDAPS, /* defport */
CURLPROTO_LDAPS, /* protocol */
+ CURLPROTO_LDAP, /* family */
PROTOPT_SSL /* flags */
};
#endif
@@ -230,7 +233,7 @@ static int ldap_win_bind_auth(LDAP *server, const char *user,
}
#endif /* #if defined(USE_WINDOWS_SSPI) */
-static int ldap_win_bind(struct connectdata *conn, LDAP *server,
+static int ldap_win_bind(struct Curl_easy *data, LDAP *server,
const char *user, const char *passwd)
{
int rc = LDAP_INVALID_CREDENTIALS;
@@ -238,7 +241,7 @@ static int ldap_win_bind(struct connectdata *conn, LDAP *server,
PTCHAR inuser = NULL;
PTCHAR inpass = NULL;
- if(user && passwd && (conn->data->set.httpauth & CURLAUTH_BASIC)) {
+ if(user && passwd && (data->set.httpauth & CURLAUTH_BASIC)) {
inuser = curlx_convert_UTF8_to_tchar((char *) user);
inpass = curlx_convert_UTF8_to_tchar((char *) passwd);
@@ -249,7 +252,7 @@ static int ldap_win_bind(struct connectdata *conn, LDAP *server,
}
#if defined(USE_WINDOWS_SSPI)
else {
- rc = ldap_win_bind_auth(server, user, passwd, conn->data->set.httpauth);
+ rc = ldap_win_bind_auth(server, user, passwd, data->set.httpauth);
}
#endif
@@ -257,7 +260,14 @@ static int ldap_win_bind(struct connectdata *conn, LDAP *server,
}
#endif /* #if defined(USE_WIN32_LDAP) */
-static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
+#if defined(USE_WIN32_LDAP)
+#define FREE_ON_WINLDAP(x) curlx_unicodefree(x)
+#else
+#define FREE_ON_WINLDAP(x)
+#endif
+
+
+static CURLcode ldap_do(struct Curl_easy *data, bool *done)
{
CURLcode result = CURLE_OK;
int rc = 0;
@@ -266,7 +276,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
LDAPMessage *ldapmsg = NULL;
LDAPMessage *entryIterator;
int num = 0;
- struct Curl_easy *data = conn->data;
+ struct connectdata *conn = data->conn;
int ldap_proto = LDAP_VERSION3;
int ldap_ssl = 0;
char *val_b64 = NULL;
@@ -291,7 +301,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
#ifdef HAVE_LDAP_URL_PARSE
rc = ldap_url_parse(data->change.url, &ludp);
#else
- rc = _ldap_url_parse(conn, &ludp);
+ rc = _ldap_url_parse(data, conn, &ludp);
#endif
if(rc != 0) {
failf(data, "LDAP local: %s", ldap_err2string(rc));
@@ -463,10 +473,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
}
#ifdef USE_WIN32_LDAP
ldap_set_option(server, LDAP_OPT_PROTOCOL_VERSION, &ldap_proto);
-#endif
-
-#ifdef USE_WIN32_LDAP
- rc = ldap_win_bind(conn, server, user, passwd);
+ rc = ldap_win_bind(data, server, user, passwd);
#else
rc = ldap_simple_bind_s(server, user, passwd);
#endif
@@ -474,7 +481,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
ldap_proto = LDAP_VERSION2;
ldap_set_option(server, LDAP_OPT_PROTOCOL_VERSION, &ldap_proto);
#ifdef USE_WIN32_LDAP
- rc = ldap_win_bind(conn, server, user, passwd);
+ rc = ldap_win_bind(data, server, user, passwd);
#else
rc = ldap_simple_bind_s(server, user, passwd);
#endif
@@ -507,7 +514,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
#if defined(USE_WIN32_LDAP)
TCHAR *attribute;
#else
- char *attribute; /*! suspicious that this isn't 'const' */
+ char *attribute;
#endif
int i;
@@ -530,32 +537,24 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
#endif
name_len = strlen(name);
- result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"DN: ", 4);
+ result = Curl_client_write(data, CLIENTWRITE_BODY, (char *)"DN: ", 4);
if(result) {
-#if defined(USE_WIN32_LDAP)
- curlx_unicodefree(name);
-#endif
+ FREE_ON_WINLDAP(name);
ldap_memfree(dn);
-
goto quit;
}
- result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *) name,
+ result = Curl_client_write(data, CLIENTWRITE_BODY, (char *) name,
name_len);
if(result) {
-#if defined(USE_WIN32_LDAP)
- curlx_unicodefree(name);
-#endif
+ FREE_ON_WINLDAP(name);
ldap_memfree(dn);
-
goto quit;
}
- result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 1);
+ result = Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\n", 1);
if(result) {
-#if defined(USE_WIN32_LDAP)
- curlx_unicodefree(name);
-#endif
+ FREE_ON_WINLDAP(name);
ldap_memfree(dn);
goto quit;
@@ -563,9 +562,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
dlsize += name_len + 5;
-#if defined(USE_WIN32_LDAP)
- curlx_unicodefree(name);
-#endif
+ FREE_ON_WINLDAP(name);
ldap_memfree(dn);
}
@@ -593,12 +590,10 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
vals = ldap_get_values_len(server, entryIterator, attribute);
if(vals != NULL) {
for(i = 0; (vals[i] != NULL); i++) {
- result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\t", 1);
+ result = Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\t", 1);
if(result) {
ldap_value_free_len(vals);
-#if defined(USE_WIN32_LDAP)
- curlx_unicodefree(attr);
-#endif
+ FREE_ON_WINLDAP(attr);
ldap_memfree(attribute);
if(ber)
ber_free(ber, 0);
@@ -606,13 +601,11 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
goto quit;
}
- result = Curl_client_write(conn, CLIENTWRITE_BODY,
+ result = Curl_client_write(data, CLIENTWRITE_BODY,
(char *) attr, attr_len);
if(result) {
ldap_value_free_len(vals);
-#if defined(USE_WIN32_LDAP)
- curlx_unicodefree(attr);
-#endif
+ FREE_ON_WINLDAP(attr);
ldap_memfree(attribute);
if(ber)
ber_free(ber, 0);
@@ -620,12 +613,10 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
goto quit;
}
- result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)": ", 2);
+ result = Curl_client_write(data, CLIENTWRITE_BODY, (char *)": ", 2);
if(result) {
ldap_value_free_len(vals);
-#if defined(USE_WIN32_LDAP)
- curlx_unicodefree(attr);
-#endif
+ FREE_ON_WINLDAP(attr);
ldap_memfree(attribute);
if(ber)
ber_free(ber, 0);
@@ -645,9 +636,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
&val_b64_sz);
if(result) {
ldap_value_free_len(vals);
-#if defined(USE_WIN32_LDAP)
- curlx_unicodefree(attr);
-#endif
+ FREE_ON_WINLDAP(attr);
ldap_memfree(attribute);
if(ber)
ber_free(ber, 0);
@@ -656,14 +645,12 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
}
if(val_b64_sz > 0) {
- result = Curl_client_write(conn, CLIENTWRITE_BODY, val_b64,
+ result = Curl_client_write(data, CLIENTWRITE_BODY, val_b64,
val_b64_sz);
free(val_b64);
if(result) {
ldap_value_free_len(vals);
-#if defined(USE_WIN32_LDAP)
- curlx_unicodefree(attr);
-#endif
+ FREE_ON_WINLDAP(attr);
ldap_memfree(attribute);
if(ber)
ber_free(ber, 0);
@@ -675,13 +662,11 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
}
}
else {
- result = Curl_client_write(conn, CLIENTWRITE_BODY, vals[i]->bv_val,
+ result = Curl_client_write(data, CLIENTWRITE_BODY, vals[i]->bv_val,
vals[i]->bv_len);
if(result) {
ldap_value_free_len(vals);
-#if defined(USE_WIN32_LDAP)
- curlx_unicodefree(attr);
-#endif
+ FREE_ON_WINLDAP(attr);
ldap_memfree(attribute);
if(ber)
ber_free(ber, 0);
@@ -692,12 +677,10 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
dlsize += vals[i]->bv_len;
}
- result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 1);
+ result = Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\n", 1);
if(result) {
ldap_value_free_len(vals);
-#if defined(USE_WIN32_LDAP)
- curlx_unicodefree(attr);
-#endif
+ FREE_ON_WINLDAP(attr);
ldap_memfree(attribute);
if(ber)
ber_free(ber, 0);
@@ -713,12 +696,10 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
}
/* Free the attribute as we are done with it */
-#if defined(USE_WIN32_LDAP)
- curlx_unicodefree(attr);
-#endif
+ FREE_ON_WINLDAP(attr);
ldap_memfree(attribute);
- result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 1);
+ result = Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\n", 1);
if(result)
goto quit;
dlsize++;
@@ -745,9 +726,7 @@ quit:
ldapssl_client_deinit();
#endif /* HAVE_LDAP_SSL && CURL_HAS_NOVELL_LDAPSDK */
-#if defined(USE_WIN32_LDAP)
- curlx_unicodefree(host);
-#endif
+ FREE_ON_WINLDAP(host);
/* no data to transfer */
Curl_setup_transfer(data, -1, -1, FALSE, -1);
@@ -834,14 +813,15 @@ static bool split_str(char *str, char ***out, size_t *count)
*
* <hostname> already known from 'conn->host.name'.
* <port> already known from 'conn->remote_port'.
- * extract the rest from 'conn->data->state.path+1'. All fields are optional.
+ * extract the rest from 'data->state.path+1'. All fields are optional.
* e.g.
* ldap://<hostname>:<port>/?<attributes>?<scope>?<filter>
* yields ludp->lud_dn = "".
*
* Defined in RFC4516 section 2.
*/
-static int _ldap_url_parse2(const struct connectdata *conn, LDAPURLDesc *ludp)
+static int _ldap_url_parse2(struct Curl_easy *data,
+ const struct connectdata *conn, LDAPURLDesc *ludp)
{
int rc = LDAP_SUCCESS;
char *p;
@@ -850,10 +830,10 @@ static int _ldap_url_parse2(const struct connectdata *conn, LDAPURLDesc *ludp)
char *query = NULL;
size_t i;
- if(!conn->data ||
- !conn->data->state.up.path ||
- conn->data->state.up.path[0] != '/' ||
- !strncasecompare("LDAP", conn->data->state.up.scheme, 4))
+ if(!data ||
+ !data->state.up.path ||
+ data->state.up.path[0] != '/' ||
+ !strncasecompare("LDAP", data->state.up.scheme, 4))
return LDAP_INVALID_SYNTAX;
ludp->lud_scope = LDAP_SCOPE_BASE;
@@ -861,13 +841,13 @@ static int _ldap_url_parse2(const struct connectdata *conn, LDAPURLDesc *ludp)
ludp->lud_host = conn->host.name;
/* Duplicate the path */
- p = path = strdup(conn->data->state.up.path + 1);
+ p = path = strdup(data->state.up.path + 1);
if(!path)
return LDAP_NO_MEMORY;
/* Duplicate the query if present */
- if(conn->data->state.up.query) {
- q = query = strdup(conn->data->state.up.query);
+ if(data->state.up.query) {
+ q = query = strdup(data->state.up.query);
if(!query) {
free(path);
return LDAP_NO_MEMORY;
@@ -883,7 +863,7 @@ static int _ldap_url_parse2(const struct connectdata *conn, LDAPURLDesc *ludp)
LDAP_TRACE(("DN '%s'\n", dn));
/* Unescape the DN */
- result = Curl_urldecode(conn->data, dn, 0, &unescaped, NULL, REJECT_ZERO);
+ result = Curl_urldecode(data, dn, 0, &unescaped, NULL, REJECT_ZERO);
if(result) {
rc = LDAP_NO_MEMORY;
@@ -945,10 +925,10 @@ static int _ldap_url_parse2(const struct connectdata *conn, LDAPURLDesc *ludp)
char *unescaped;
CURLcode result;
- LDAP_TRACE(("attr[%d] '%s'\n", i, attributes[i]));
+ LDAP_TRACE(("attr[%zu] '%s'\n", i, attributes[i]));
/* Unescape the attribute */
- result = Curl_urldecode(conn->data, attributes[i], 0, &unescaped, NULL,
+ result = Curl_urldecode(data, attributes[i], 0, &unescaped, NULL,
REJECT_ZERO);
if(result) {
free(attributes);
@@ -1018,8 +998,7 @@ static int _ldap_url_parse2(const struct connectdata *conn, LDAPURLDesc *ludp)
LDAP_TRACE(("filter '%s'\n", filter));
/* Unescape the filter */
- result = Curl_urldecode(conn->data, filter, 0, &unescaped, NULL,
- REJECT_ZERO);
+ result = Curl_urldecode(data, filter, 0, &unescaped, NULL, REJECT_ZERO);
if(result) {
rc = LDAP_NO_MEMORY;
@@ -1057,7 +1036,8 @@ quit:
return rc;
}
-static int _ldap_url_parse(const struct connectdata *conn,
+static int _ldap_url_parse(struct Curl_easy *data,
+ const struct connectdata *conn,
LDAPURLDesc **ludpp)
{
LDAPURLDesc *ludp = calloc(1, sizeof(*ludp));
@@ -1067,7 +1047,7 @@ static int _ldap_url_parse(const struct connectdata *conn,
if(!ludp)
return LDAP_NO_MEMORY;
- rc = _ldap_url_parse2(conn, ludp);
+ rc = _ldap_url_parse2(data, conn, ludp);
if(rc != LDAP_SUCCESS) {
_ldap_free_urldesc(ludp);
ludp = NULL;
diff --git a/Utilities/cmcurl/lib/libcurl.rc b/Utilities/cmcurl/lib/libcurl.rc
index 4839d0a65..3f7ae1603 100644
--- a/Utilities/cmcurl/lib/libcurl.rc
+++ b/Utilities/cmcurl/lib/libcurl.rc
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
@@ -44,7 +44,7 @@ BEGIN
BEGIN
BLOCK "040904b0"
BEGIN
- VALUE "CompanyName", "The curl library, https://curl.haxx.se/\0"
+ VALUE "CompanyName", "The curl library, https://curl.se/\0"
VALUE "FileDescription", "libcurl Shared Library\0"
VALUE "FileVersion", LIBCURL_VERSION "\0"
VALUE "InternalName", "libcurl\0"
@@ -52,7 +52,7 @@ BEGIN
VALUE "ProductName", "The curl library\0"
VALUE "ProductVersion", LIBCURL_VERSION "\0"
VALUE "LegalCopyright", "\xa9 " LIBCURL_COPYRIGHT "\0" /* a9: Copyright symbol */
- VALUE "License", "https://curl.haxx.se/docs/copyright.html\0"
+ VALUE "License", "https://curl.se/docs/copyright.html\0"
END
END
diff --git a/Utilities/cmcurl/lib/llist.c b/Utilities/cmcurl/lib/llist.c
index e7c6f51dc..17a7be166 100644
--- a/Utilities/cmcurl/lib/llist.c
+++ b/Utilities/cmcurl/lib/llist.c
@@ -9,7 +9,7 @@
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -34,7 +34,7 @@
* @unittest: 1300
*/
void
-Curl_llist_init(struct curl_llist *l, curl_llist_dtor dtor)
+Curl_llist_init(struct Curl_llist *l, Curl_llist_dtor dtor)
{
l->size = 0;
l->dtor = dtor;
@@ -54,9 +54,9 @@ Curl_llist_init(struct curl_llist *l, curl_llist_dtor dtor)
* @unittest: 1300
*/
void
-Curl_llist_insert_next(struct curl_llist *list, struct curl_llist_element *e,
+Curl_llist_insert_next(struct Curl_llist *list, struct Curl_llist_element *e,
const void *p,
- struct curl_llist_element *ne)
+ struct Curl_llist_element *ne)
{
ne->ptr = (void *) p;
if(list->size == 0) {
@@ -90,7 +90,7 @@ Curl_llist_insert_next(struct curl_llist *list, struct curl_llist_element *e,
* @unittest: 1300
*/
void
-Curl_llist_remove(struct curl_llist *list, struct curl_llist_element *e,
+Curl_llist_remove(struct Curl_llist *list, struct Curl_llist_element *e,
void *user)
{
void *ptr;
@@ -131,7 +131,7 @@ Curl_llist_remove(struct curl_llist *list, struct curl_llist_element *e,
}
void
-Curl_llist_destroy(struct curl_llist *list, void *user)
+Curl_llist_destroy(struct Curl_llist *list, void *user)
{
if(list) {
while(list->size > 0)
@@ -140,7 +140,7 @@ Curl_llist_destroy(struct curl_llist *list, void *user)
}
size_t
-Curl_llist_count(struct curl_llist *list)
+Curl_llist_count(struct Curl_llist *list)
{
return list->size;
}
diff --git a/Utilities/cmcurl/lib/llist.h b/Utilities/cmcurl/lib/llist.h
index 0178c4259..ceae2dd1b 100644
--- a/Utilities/cmcurl/lib/llist.h
+++ b/Utilities/cmcurl/lib/llist.h
@@ -11,7 +11,7 @@
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -25,26 +25,26 @@
#include "curl_setup.h"
#include <stddef.h>
-typedef void (*curl_llist_dtor)(void *, void *);
+typedef void (*Curl_llist_dtor)(void *, void *);
-struct curl_llist_element {
+struct Curl_llist_element {
void *ptr;
- struct curl_llist_element *prev;
- struct curl_llist_element *next;
+ struct Curl_llist_element *prev;
+ struct Curl_llist_element *next;
};
-struct curl_llist {
- struct curl_llist_element *head;
- struct curl_llist_element *tail;
- curl_llist_dtor dtor;
+struct Curl_llist {
+ struct Curl_llist_element *head;
+ struct Curl_llist_element *tail;
+ Curl_llist_dtor dtor;
size_t size;
};
-void Curl_llist_init(struct curl_llist *, curl_llist_dtor);
-void Curl_llist_insert_next(struct curl_llist *, struct curl_llist_element *,
- const void *, struct curl_llist_element *node);
-void Curl_llist_remove(struct curl_llist *, struct curl_llist_element *,
+void Curl_llist_init(struct Curl_llist *, Curl_llist_dtor);
+void Curl_llist_insert_next(struct Curl_llist *, struct Curl_llist_element *,
+ const void *, struct Curl_llist_element *node);
+void Curl_llist_remove(struct Curl_llist *, struct Curl_llist_element *,
void *);
-size_t Curl_llist_count(struct curl_llist *);
-void Curl_llist_destroy(struct curl_llist *, void *);
+size_t Curl_llist_count(struct Curl_llist *);
+void Curl_llist_destroy(struct Curl_llist *, void *);
#endif /* HEADER_CURL_LLIST_H */
diff --git a/Utilities/cmcurl/lib/md4.c b/Utilities/cmcurl/lib/md4.c
index 67119cda5..8ae6ac3fa 100644
--- a/Utilities/cmcurl/lib/md4.c
+++ b/Utilities/cmcurl/lib/md4.c
@@ -9,7 +9,7 @@
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/md5.c b/Utilities/cmcurl/lib/md5.c
index d21625f6b..513ffb2fb 100644
--- a/Utilities/cmcurl/lib/md5.c
+++ b/Utilities/cmcurl/lib/md5.c
@@ -9,7 +9,7 @@
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/memdebug.c b/Utilities/cmcurl/lib/memdebug.c
index da75c9f5d..881ee85c3 100644
--- a/Utilities/cmcurl/lib/memdebug.c
+++ b/Utilities/cmcurl/lib/memdebug.c
@@ -9,7 +9,7 @@
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -35,52 +35,6 @@
#include "curl_memory.h"
#include "memdebug.h"
-/*
- * Until 2011-08-17 libcurl's Memory Tracking feature also performed
- * automatic malloc and free filling operations using 0xA5 and 0x13
- * values. Our own preinitialization of dynamically allocated memory
- * might be useful when not using third party memory debuggers, but
- * on the other hand this would fool memory debuggers into thinking
- * that all dynamically allocated memory is properly initialized.
- *
- * As a default setting, libcurl's Memory Tracking feature no longer
- * performs preinitialization of dynamically allocated memory on its
- * own. If you know what you are doing, and really want to retain old
- * behavior, you can achieve this compiling with preprocessor symbols
- * CURL_MT_MALLOC_FILL and CURL_MT_FREE_FILL defined with appropriate
- * values.
- */
-
-#ifdef CURL_MT_MALLOC_FILL
-# if (CURL_MT_MALLOC_FILL < 0) || (CURL_MT_MALLOC_FILL > 0xff)
-# error "invalid CURL_MT_MALLOC_FILL or out of range"
-# endif
-#endif
-
-#ifdef CURL_MT_FREE_FILL
-# if (CURL_MT_FREE_FILL < 0) || (CURL_MT_FREE_FILL > 0xff)
-# error "invalid CURL_MT_FREE_FILL or out of range"
-# endif
-#endif
-
-#if defined(CURL_MT_MALLOC_FILL) && defined(CURL_MT_FREE_FILL)
-# if (CURL_MT_MALLOC_FILL == CURL_MT_FREE_FILL)
-# error "CURL_MT_MALLOC_FILL same as CURL_MT_FREE_FILL"
-# endif
-#endif
-
-#ifdef CURL_MT_MALLOC_FILL
-# define mt_malloc_fill(buf,len) memset((buf), CURL_MT_MALLOC_FILL, (len))
-#else
-# define mt_malloc_fill(buf,len) Curl_nop_stmt
-#endif
-
-#ifdef CURL_MT_FREE_FILL
-# define mt_free_fill(buf,len) memset((buf), CURL_MT_FREE_FILL, (len))
-#else
-# define mt_free_fill(buf,len) Curl_nop_stmt
-#endif
-
struct memdebug {
size_t size;
union {
@@ -173,8 +127,6 @@ void *curl_dbg_malloc(size_t wantedsize, int line, const char *source)
mem = (Curl_cmalloc)(size);
if(mem) {
- /* fill memory with junk */
- mt_malloc_fill(mem->mem, wantedsize);
mem->size = wantedsize;
}
@@ -321,9 +273,6 @@ void curl_dbg_free(void *ptr, int line, const char *source)
# pragma warning(pop)
#endif
- /* destroy */
- mt_free_fill(mem->mem, mem->size);
-
/* free for real */
(Curl_cfree)(mem);
}
diff --git a/Utilities/cmcurl/lib/memdebug.h b/Utilities/cmcurl/lib/memdebug.h
index 4edafdfb5..8e88cea58 100644
--- a/Utilities/cmcurl/lib/memdebug.h
+++ b/Utilities/cmcurl/lib/memdebug.h
@@ -12,7 +12,7 @@
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/mime.c b/Utilities/cmcurl/lib/mime.c
index 6a9b64a2d..abadcb02c 100644
--- a/Utilities/cmcurl/lib/mime.c
+++ b/Utilities/cmcurl/lib/mime.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -1168,6 +1168,7 @@ static void cleanup_part_content(curl_mimepart *part)
part->kind = MIMEKIND_NONE;
part->flags &= ~MIME_FAST_READ;
part->lastreadstatus = 1; /* Successful read status. */
+ part->state.state = MIMESTATE_BEGIN;
}
static void mime_subparts_free(void *ptr)
diff --git a/Utilities/cmcurl/lib/mime.h b/Utilities/cmcurl/lib/mime.h
index 50b7ea6b0..56642ae66 100644
--- a/Utilities/cmcurl/lib/mime.h
+++ b/Utilities/cmcurl/lib/mime.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -110,6 +110,7 @@ struct curl_mimepart {
curl_mime *parent; /* Parent mime structure. */
curl_mimepart *nextpart; /* Forward linked list. */
enum mimekind kind; /* The part kind. */
+ unsigned int flags; /* Flags. */
char *data; /* Memory data or file name. */
curl_read_callback readfunc; /* Read function. */
curl_seek_callback seekfunc; /* Seek function. */
@@ -122,7 +123,6 @@ struct curl_mimepart {
char *filename; /* Remote file name. */
char *name; /* Data name. */
curl_off_t datasize; /* Expected data size. */
- unsigned int flags; /* Flags. */
struct mime_state state; /* Current readback state. */
const struct mime_encoder *encoder; /* Content data encoder. */
struct mime_encoder_state encstate; /* Data encoder state. */
diff --git a/Utilities/cmcurl/lib/mprintf.c b/Utilities/cmcurl/lib/mprintf.c
index 80735be51..c681248de 100644
--- a/Utilities/cmcurl/lib/mprintf.c
+++ b/Utilities/cmcurl/lib/mprintf.c
@@ -9,7 +9,7 @@
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -99,12 +99,12 @@ static const char lower_digits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
/* Upper-case digits. */
static const char upper_digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
-#define OUTCHAR(x) \
- do{ \
+#define OUTCHAR(x) \
+ do { \
if(stream((unsigned char)(x), (FILE *)data) != -1) \
- done++; \
- else \
- return done; /* return immediately on failure */ \
+ done++; \
+ else \
+ return done; /* return immediately on failure */ \
} while(0)
/* Data type to read from the arglist */
@@ -169,7 +169,7 @@ struct nsprintf {
};
struct asprintf {
- struct dynbuf b;
+ struct dynbuf *b;
bool fail; /* if an alloc has failed and thus the output is not the complete
data */
};
@@ -878,7 +878,7 @@ static int dprintf_formatf(
OUTCHAR(' ');
for(point = strnil; *point != '\0'; ++point)
OUTCHAR(*point);
- if(! (p->flags & FLAGS_LEFT))
+ if(!(p->flags & FLAGS_LEFT))
while(width-- > 0)
OUTCHAR(' ');
}
@@ -1042,50 +1042,61 @@ static int alloc_addbyter(int output, FILE *data)
struct asprintf *infop = (struct asprintf *)data;
unsigned char outc = (unsigned char)output;
- if(Curl_dyn_addn(&infop->b, &outc, 1)) {
+ if(Curl_dyn_addn(infop->b, &outc, 1)) {
infop->fail = 1;
return -1; /* fail */
}
return outc; /* fputc() returns like this on success */
}
-char *curl_maprintf(const char *format, ...)
+extern int Curl_dyn_vprintf(struct dynbuf *dyn,
+ const char *format, va_list ap_save);
+
+/* appends the formatted string, returns 0 on success, 1 on error */
+int Curl_dyn_vprintf(struct dynbuf *dyn, const char *format, va_list ap_save)
{
- va_list ap_save; /* argument pointer */
int retcode;
struct asprintf info;
- Curl_dyn_init(&info.b, DYN_APRINTF);
+ info.b = dyn;
info.fail = 0;
- va_start(ap_save, format);
retcode = dprintf_formatf(&info, alloc_addbyter, format, ap_save);
- va_end(ap_save);
if((-1 == retcode) || info.fail) {
- Curl_dyn_free(&info.b);
- return NULL;
+ Curl_dyn_free(info.b);
+ return 1;
}
- if(Curl_dyn_len(&info.b))
- return Curl_dyn_ptr(&info.b);
- return strdup("");
+ return 0;
}
char *curl_mvaprintf(const char *format, va_list ap_save)
{
int retcode;
struct asprintf info;
- Curl_dyn_init(&info.b, DYN_APRINTF);
+ struct dynbuf dyn;
+ info.b = &dyn;
+ Curl_dyn_init(info.b, DYN_APRINTF);
info.fail = 0;
retcode = dprintf_formatf(&info, alloc_addbyter, format, ap_save);
if((-1 == retcode) || info.fail) {
- Curl_dyn_free(&info.b);
+ Curl_dyn_free(info.b);
return NULL;
}
- if(Curl_dyn_len(&info.b))
- return Curl_dyn_ptr(&info.b);
+ if(Curl_dyn_len(info.b))
+ return Curl_dyn_ptr(info.b);
return strdup("");
}
+char *curl_maprintf(const char *format, ...)
+{
+ va_list ap_save;
+ char *s;
+ va_start(ap_save, format);
+ s = curl_mvaprintf(format, ap_save);
+ va_end(ap_save);
+ return s;
+}
+
static int storebuffer(int output, FILE *data)
{
char **buffer = (char **)data;
diff --git a/Utilities/cmcurl/lib/mqtt.c b/Utilities/cmcurl/lib/mqtt.c
index f6f441614..2134409cd 100644
--- a/Utilities/cmcurl/lib/mqtt.c
+++ b/Utilities/cmcurl/lib/mqtt.c
@@ -5,12 +5,12 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2020 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 2019, Björn Stenberg, <bjorn@haxx.se>
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -23,7 +23,7 @@
#include "curl_setup.h"
-#ifdef CURL_ENABLE_MQTT
+#ifndef CURL_DISABLE_MQTT
#include "urldata.h"
#include <curl/curl.h>
@@ -59,10 +59,12 @@
* Forward declarations.
*/
-static CURLcode mqtt_do(struct connectdata *conn, bool *done);
-static CURLcode mqtt_doing(struct connectdata *conn, bool *done);
-static int mqtt_getsock(struct connectdata *conn, curl_socket_t *sock);
-static CURLcode mqtt_setup_conn(struct connectdata *conn);
+static CURLcode mqtt_do(struct Curl_easy *data, bool *done);
+static CURLcode mqtt_doing(struct Curl_easy *data, bool *done);
+static int mqtt_getsock(struct Curl_easy *data, struct connectdata *conn,
+ curl_socket_t *sock);
+static CURLcode mqtt_setup_conn(struct Curl_easy *data,
+ struct connectdata *conn);
/*
* MQTT protocol handler.
@@ -86,34 +88,36 @@ const struct Curl_handler Curl_handler_mqtt = {
ZERO_NULL, /* connection_check */
PORT_MQTT, /* defport */
CURLPROTO_MQTT, /* protocol */
+ CURLPROTO_MQTT, /* family */
PROTOPT_NONE /* flags */
};
-static CURLcode mqtt_setup_conn(struct connectdata *conn)
+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 */
struct MQTT *mq;
- struct Curl_easy *data = conn->data;
- DEBUGASSERT(data->req.protop == NULL);
+ (void)conn;
+ DEBUGASSERT(data->req.p.mqtt == NULL);
mq = calloc(1, sizeof(struct MQTT));
if(!mq)
return CURLE_OUT_OF_MEMORY;
- data->req.protop = mq;
+ data->req.p.mqtt = mq;
return CURLE_OK;
}
-static CURLcode mqtt_send(struct connectdata *conn,
+static CURLcode mqtt_send(struct Curl_easy *data,
char *buf, size_t len)
{
CURLcode result = CURLE_OK;
+ struct connectdata *conn = data->conn;
curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
- struct Curl_easy *data = conn->data;
- struct MQTT *mq = data->req.protop;
+ struct MQTT *mq = data->req.p.mqtt;
ssize_t n;
- result = Curl_write(conn, sockfd, buf, len, &n);
- if(!result && data->set.verbose)
+ result = Curl_write(data, sockfd, buf, len, &n);
+ if(!result)
Curl_debug(data, CURLINFO_HEADER_OUT, buf, (size_t)n);
if(len != (size_t)n) {
size_t nsend = len - n;
@@ -129,20 +133,22 @@ static CURLcode mqtt_send(struct connectdata *conn,
/* Generic function called by the multi interface to figure out what socket(s)
to wait for and for what actions during the DOING and PROTOCONNECT
states */
-static int mqtt_getsock(struct connectdata *conn,
+static int mqtt_getsock(struct Curl_easy *data,
+ struct connectdata *conn,
curl_socket_t *sock)
{
+ (void)data;
sock[0] = conn->sock[FIRSTSOCKET];
return GETSOCK_READSOCK(FIRSTSOCKET);
}
-static CURLcode mqtt_connect(struct connectdata *conn)
+static CURLcode mqtt_connect(struct Curl_easy *data)
{
CURLcode result = CURLE_OK;
const size_t client_id_offset = 14;
const size_t packetlen = client_id_offset + MQTT_CLIENTID_LEN;
char client_id[MQTT_CLIENTID_LEN + 1] = "curl";
- const size_t curl_len = strlen("curl");
+ const size_t clen = strlen("curl");
char packet[32] = {
MQTT_MSG_CONNECT, /* packet type */
0x00, /* remaining length */
@@ -156,36 +162,35 @@ static CURLcode mqtt_connect(struct connectdata *conn)
packet[1] = (packetlen - 2) & 0x7f;
packet[client_id_offset - 1] = MQTT_CLIENTID_LEN;
- result = Curl_rand_hex(conn->data, (unsigned char *)&client_id[curl_len],
- MQTT_CLIENTID_LEN - curl_len + 1);
+ result = Curl_rand_hex(data, (unsigned char *)&client_id[clen],
+ MQTT_CLIENTID_LEN - clen + 1);
memcpy(&packet[client_id_offset], client_id, MQTT_CLIENTID_LEN);
- infof(conn->data, "Using client id '%s'\n", client_id);
+ infof(data, "Using client id '%s'\n", client_id);
if(!result)
- result = mqtt_send(conn, packet, packetlen);
+ result = mqtt_send(data, packet, packetlen);
return result;
}
-static CURLcode mqtt_disconnect(struct connectdata *conn)
+static CURLcode mqtt_disconnect(struct Curl_easy *data)
{
CURLcode result = CURLE_OK;
- result = mqtt_send(conn, (char *)"\xe0\x00", 2);
+ result = mqtt_send(data, (char *)"\xe0\x00", 2);
return result;
}
-static CURLcode mqtt_verify_connack(struct connectdata *conn)
+static CURLcode mqtt_verify_connack(struct Curl_easy *data)
{
CURLcode result;
+ struct connectdata *conn = data->conn;
curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
unsigned char readbuf[MQTT_CONNACK_LEN];
ssize_t nread;
- struct Curl_easy *data = conn->data;
- result = Curl_read(conn, sockfd, (char *)readbuf, MQTT_CONNACK_LEN, &nread);
+ result = Curl_read(data, sockfd, (char *)readbuf, MQTT_CONNACK_LEN, &nread);
if(result)
goto fail;
- if(data->set.verbose)
- Curl_debug(data, CURLINFO_HEADER_IN, (char *)readbuf, (size_t)nread);
+ Curl_debug(data, CURLINFO_HEADER_IN, (char *)readbuf, (size_t)nread);
/* fixme */
if(nread < MQTT_CONNACK_LEN) {
@@ -204,18 +209,18 @@ fail:
return result;
}
-static CURLcode mqtt_get_topic(struct connectdata *conn,
+static CURLcode mqtt_get_topic(struct Curl_easy *data,
char **topic, size_t *topiclen)
{
CURLcode result = CURLE_OK;
- char *path = conn->data->state.up.path;
+ char *path = data->state.up.path;
if(strlen(path) > 1) {
- result = Curl_urldecode(conn->data, path + 1, 0, topic, topiclen,
+ result = Curl_urldecode(data, path + 1, 0, topic, topiclen,
REJECT_NADA);
}
else {
- failf(conn->data, "Error: No topic specified.");
+ failf(data, "Error: No topic specified.");
result = CURLE_URL_MALFORMAT;
}
return result;
@@ -238,7 +243,7 @@ static int mqtt_encode_len(char *buf, size_t len)
return i;
}
-static CURLcode mqtt_subscribe(struct connectdata *conn)
+static CURLcode mqtt_subscribe(struct Curl_easy *data)
{
CURLcode result = CURLE_OK;
char *topic = NULL;
@@ -247,8 +252,9 @@ static CURLcode mqtt_subscribe(struct connectdata *conn)
size_t packetlen;
char encodedsize[4];
size_t n;
+ struct connectdata *conn = data->conn;
- result = mqtt_get_topic(conn, &topic, &topiclen);
+ result = mqtt_get_topic(data, &topic, &topiclen);
if(result)
goto fail;
@@ -274,7 +280,7 @@ static CURLcode mqtt_subscribe(struct connectdata *conn)
memcpy(&packet[5 + n], topic, topiclen);
packet[5 + n + topiclen] = 0; /* QoS zero */
- result = mqtt_send(conn, (char *)packet, packetlen);
+ result = mqtt_send(data, (char *)packet, packetlen);
fail:
free(topic);
@@ -285,20 +291,20 @@ fail:
/*
* Called when the first byte was already read.
*/
-static CURLcode mqtt_verify_suback(struct connectdata *conn)
+static CURLcode mqtt_verify_suback(struct Curl_easy *data)
{
CURLcode result;
+ struct connectdata *conn = data->conn;
curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
unsigned char readbuf[MQTT_SUBACK_LEN];
ssize_t nread;
struct mqtt_conn *mqtt = &conn->proto.mqtt;
- result = Curl_read(conn, sockfd, (char *)readbuf, MQTT_SUBACK_LEN, &nread);
+ result = Curl_read(data, sockfd, (char *)readbuf, MQTT_SUBACK_LEN, &nread);
if(result)
goto fail;
- if(conn->data->set.verbose)
- Curl_debug(conn->data, CURLINFO_HEADER_IN, (char *)readbuf, (size_t)nread);
+ Curl_debug(data, CURLINFO_HEADER_IN, (char *)readbuf, (size_t)nread);
/* fixme */
if(nread < MQTT_SUBACK_LEN) {
@@ -316,11 +322,11 @@ fail:
return result;
}
-static CURLcode mqtt_publish(struct connectdata *conn)
+static CURLcode mqtt_publish(struct Curl_easy *data)
{
CURLcode result;
- char *payload = conn->data->set.postfields;
- size_t payloadlen = (size_t)conn->data->set.postfieldsize;
+ char *payload = data->set.postfields;
+ size_t payloadlen;
char *topic = NULL;
size_t topiclen;
unsigned char *pkt = NULL;
@@ -328,8 +334,16 @@ static CURLcode mqtt_publish(struct connectdata *conn)
size_t remaininglength;
size_t encodelen;
char encodedbytes[4];
+ curl_off_t postfieldsize = data->set.postfieldsize;
+
+ if(!payload)
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ if(postfieldsize < 0)
+ payloadlen = strlen(payload);
+ else
+ payloadlen = (size_t)postfieldsize;
- result = mqtt_get_topic(conn, &topic, &topiclen);
+ result = mqtt_get_topic(data, &topic, &topiclen);
if(result)
goto fail;
@@ -353,7 +367,7 @@ static CURLcode mqtt_publish(struct connectdata *conn)
i += topiclen;
memcpy(&pkt[i], payload, payloadlen);
i += payloadlen;
- result = mqtt_send(conn, (char *)pkt, i);
+ result = mqtt_send(data, (char *)pkt, i);
fail:
free(pkt);
@@ -396,13 +410,14 @@ static const char *statenames[]={
#endif
/* The only way to change state */
-static void mqstate(struct connectdata *conn,
+static void mqstate(struct Curl_easy *data,
enum mqttstate state,
enum mqttstate nextstate) /* used if state == FIRST */
{
+ struct connectdata *conn = data->conn;
struct mqtt_conn *mqtt = &conn->proto.mqtt;
#ifdef CURLDEBUG
- infof(conn->data, "%s (from %s) (next is %s)\n",
+ infof(data, "%s (from %s) (next is %s)\n",
statenames[state],
statenames[mqtt->state],
(state == MQTT_FIRST)? statenames[nextstate] : "");
@@ -416,27 +431,26 @@ static void mqstate(struct connectdata *conn,
/* for the publish packet */
#define MQTT_HEADER_LEN 5 /* max 5 bytes */
-static CURLcode mqtt_read_publish(struct connectdata *conn,
- bool *done)
+static CURLcode mqtt_read_publish(struct Curl_easy *data, bool *done)
{
CURLcode result = CURLE_OK;
+ struct connectdata *conn = data->conn;
curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
ssize_t nread;
- struct Curl_easy *data = conn->data;
unsigned char *pkt = (unsigned char *)data->state.buffer;
size_t remlen;
struct mqtt_conn *mqtt = &conn->proto.mqtt;
- struct MQTT *mq = data->req.protop;
+ struct MQTT *mq = data->req.p.mqtt;
unsigned char packet;
switch(mqtt->state) {
MQTT_SUBACK_COMING:
case MQTT_SUBACK_COMING:
- result = mqtt_verify_suback(conn);
+ result = mqtt_verify_suback(data);
if(result)
break;
- mqstate(conn, MQTT_FIRST, MQTT_PUBWAIT);
+ mqstate(data, MQTT_FIRST, MQTT_PUBWAIT);
break;
case MQTT_SUBACK:
@@ -444,9 +458,9 @@ static CURLcode mqtt_read_publish(struct connectdata *conn,
/* we are expecting PUBLISH or SUBACK */
packet = mq->firstbyte & 0xf0;
if(packet == MQTT_MSG_PUBLISH)
- mqstate(conn, MQTT_PUB_REMAIN, MQTT_NOSTATE);
+ mqstate(data, MQTT_PUB_REMAIN, MQTT_NOSTATE);
else if(packet == MQTT_MSG_SUBACK) {
- mqstate(conn, MQTT_SUBACK_COMING, MQTT_NOSTATE);
+ mqstate(data, MQTT_SUBACK_COMING, MQTT_NOSTATE);
goto MQTT_SUBACK_COMING;
}
else if(packet == MQTT_MSG_DISCONNECT) {
@@ -473,7 +487,7 @@ static CURLcode mqtt_read_publish(struct connectdata *conn,
size_t rest = mq->npacket;
if(rest > (size_t)data->set.buffer_size)
rest = (size_t)data->set.buffer_size;
- result = Curl_read(conn, sockfd, (char *)pkt, rest, &nread);
+ result = Curl_read(data, sockfd, (char *)pkt, rest, &nread);
if(result) {
if(CURLE_AGAIN == result) {
infof(data, "EEEE AAAAGAIN\n");
@@ -485,8 +499,7 @@ static CURLcode mqtt_read_publish(struct connectdata *conn,
result = CURLE_PARTIAL_FILE;
goto end;
}
- if(data->set.verbose)
- Curl_debug(data, CURLINFO_DATA_IN, (char *)pkt, (size_t)nread);
+ Curl_debug(data, CURLINFO_DATA_IN, (char *)pkt, (size_t)nread);
mq->npacket -= nread;
k->bytecount += nread;
@@ -494,13 +507,13 @@ static CURLcode mqtt_read_publish(struct connectdata *conn,
/* if QoS is set, message contains packet id */
- result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)pkt, nread);
+ result = Curl_client_write(data, CLIENTWRITE_BODY, (char *)pkt, nread);
if(result)
goto end;
if(!mq->npacket)
/* no more PUBLISH payload, back to subscribe wait state */
- mqstate(conn, MQTT_FIRST, MQTT_PUBWAIT);
+ mqstate(data, MQTT_FIRST, MQTT_PUBWAIT);
break;
}
default:
@@ -512,28 +525,26 @@ static CURLcode mqtt_read_publish(struct connectdata *conn,
return result;
}
-static CURLcode mqtt_do(struct connectdata *conn, bool *done)
+static CURLcode mqtt_do(struct Curl_easy *data, bool *done)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
-
*done = FALSE; /* unconditionally */
- result = mqtt_connect(conn);
+ result = mqtt_connect(data);
if(result) {
failf(data, "Error %d sending MQTT CONN request", result);
return result;
}
- mqstate(conn, MQTT_FIRST, MQTT_CONNACK);
+ mqstate(data, MQTT_FIRST, MQTT_CONNACK);
return CURLE_OK;
}
-static CURLcode mqtt_doing(struct connectdata *conn, bool *done)
+static CURLcode mqtt_doing(struct Curl_easy *data, bool *done)
{
CURLcode result = CURLE_OK;
+ struct connectdata *conn = data->conn;
struct mqtt_conn *mqtt = &conn->proto.mqtt;
- struct Curl_easy *data = conn->data;
- struct MQTT *mq = data->req.protop;
+ struct MQTT *mq = data->req.p.mqtt;
ssize_t nread;
curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
unsigned char *pkt = (unsigned char *)data->state.buffer;
@@ -544,7 +555,7 @@ static CURLcode mqtt_doing(struct connectdata *conn, bool *done)
if(mq->nsend) {
/* send the remainder of an outgoing packet */
char *ptr = mq->sendleftovers;
- result = mqtt_send(conn, mq->sendleftovers, mq->nsend);
+ result = mqtt_send(data, mq->sendleftovers, mq->nsend);
free(ptr);
if(result)
return result;
@@ -554,22 +565,20 @@ static CURLcode mqtt_doing(struct connectdata *conn, bool *done)
switch(mqtt->state) {
case MQTT_FIRST:
/* Read the initial byte only */
- result = Curl_read(conn, sockfd, (char *)&mq->firstbyte, 1, &nread);
- if(result)
+ result = Curl_read(data, sockfd, (char *)&mq->firstbyte, 1, &nread);
+ if(!nread)
break;
- if(data->set.verbose)
- Curl_debug(data, CURLINFO_HEADER_IN, (char *)&mq->firstbyte, 1);
+ Curl_debug(data, CURLINFO_HEADER_IN, (char *)&mq->firstbyte, 1);
/* remember the first byte */
mq->npacket = 0;
- mqstate(conn, MQTT_REMAINING_LENGTH, MQTT_NOSTATE);
+ mqstate(data, MQTT_REMAINING_LENGTH, MQTT_NOSTATE);
/* FALLTHROUGH */
case MQTT_REMAINING_LENGTH:
do {
- result = Curl_read(conn, sockfd, (char *)&byte, 1, &nread);
- if(result)
+ result = Curl_read(data, sockfd, (char *)&byte, 1, &nread);
+ if(!nread)
break;
- if(data->set.verbose)
- Curl_debug(data, CURLINFO_HEADER_IN, (char *)&byte, 1);
+ Curl_debug(data, CURLINFO_HEADER_IN, (char *)&byte, 1);
pkt[mq->npacket++] = byte;
} while((byte & 0x80) && (mq->npacket < 4));
if(result)
@@ -577,10 +586,10 @@ static CURLcode mqtt_doing(struct connectdata *conn, bool *done)
mq->remaining_length = mqtt_decode_len(&pkt[0], mq->npacket, NULL);
mq->npacket = 0;
if(mq->remaining_length) {
- mqstate(conn, mqtt->nextstate, MQTT_NOSTATE);
+ mqstate(data, mqtt->nextstate, MQTT_NOSTATE);
break;
}
- mqstate(conn, MQTT_FIRST, MQTT_FIRST);
+ mqstate(data, MQTT_FIRST, MQTT_FIRST);
if(mq->firstbyte == MQTT_MSG_DISCONNECT) {
infof(data, "Got DISCONNECT\n");
@@ -588,22 +597,22 @@ static CURLcode mqtt_doing(struct connectdata *conn, bool *done)
}
break;
case MQTT_CONNACK:
- result = mqtt_verify_connack(conn);
+ result = mqtt_verify_connack(data);
if(result)
break;
- if(conn->data->state.httpreq == HTTPREQ_POST) {
- result = mqtt_publish(conn);
+ if(data->state.httpreq == HTTPREQ_POST) {
+ result = mqtt_publish(data);
if(!result) {
- result = mqtt_disconnect(conn);
+ result = mqtt_disconnect(data);
*done = TRUE;
}
mqtt->nextstate = MQTT_FIRST;
}
else {
- result = mqtt_subscribe(conn);
+ result = mqtt_subscribe(data);
if(!result) {
- mqstate(conn, MQTT_FIRST, MQTT_SUBACK);
+ mqstate(data, MQTT_FIRST, MQTT_SUBACK);
}
}
break;
@@ -611,11 +620,11 @@ static CURLcode mqtt_doing(struct connectdata *conn, bool *done)
case MQTT_SUBACK:
case MQTT_PUBWAIT:
case MQTT_PUB_REMAIN:
- result = mqtt_read_publish(conn, done);
+ result = mqtt_read_publish(data, done);
break;
default:
- failf(conn->data, "State not handled yet");
+ failf(data, "State not handled yet");
*done = TRUE;
break;
}
@@ -625,4 +634,4 @@ static CURLcode mqtt_doing(struct connectdata *conn, bool *done)
return result;
}
-#endif /* CURL_ENABLE_MQTT */
+#endif /* CURL_DISABLE_MQTT */
diff --git a/Utilities/cmcurl/lib/mqtt.h b/Utilities/cmcurl/lib/mqtt.h
index 37463d58a..fb52c7232 100644
--- a/Utilities/cmcurl/lib/mqtt.h
+++ b/Utilities/cmcurl/lib/mqtt.h
@@ -11,7 +11,7 @@
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -22,7 +22,7 @@
*
***************************************************************************/
-#ifdef CURL_ENABLE_MQTT
+#ifndef CURL_DISABLE_MQTT
extern const struct Curl_handler Curl_handler_mqtt;
#endif
diff --git a/Utilities/cmcurl/lib/multi.c b/Utilities/cmcurl/lib/multi.c
index 3c7fb85ed..85707a1af 100644
--- a/Utilities/cmcurl/lib/multi.c
+++ b/Utilities/cmcurl/lib/multi.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -69,7 +69,7 @@
#define CURL_MULTI_HANDLE 0x000bab1e
#define GOOD_MULTI_HANDLE(x) \
- ((x) && (x)->type == CURL_MULTI_HANDLE)
+ ((x) && (x)->magic == CURL_MULTI_HANDLE)
static CURLMcode singlesocket(struct Curl_multi *multi,
struct Curl_easy *data);
@@ -105,7 +105,14 @@ static const char * const statename[]={
/* function pointer called once when switching TO a state */
typedef void (*init_multistate_func)(struct Curl_easy *data);
-static void Curl_init_completed(struct Curl_easy *data)
+/* called when the PERFORM state starts */
+static void init_perform(struct Curl_easy *data)
+{
+ data->req.chunk = FALSE;
+ Curl_pgrsTime(data, TIMER_PRETRANSFER);
+}
+
+static void init_completed(struct Curl_easy *data)
{
/* this is a completed transfer */
@@ -136,10 +143,10 @@ static void mstate(struct Curl_easy *data, CURLMstate state
NULL, /* DOING */
NULL, /* DO_MORE */
NULL, /* DO_DONE */
- NULL, /* PERFORM */
+ init_perform, /* PERFORM */
NULL, /* TOOFAST */
NULL, /* DONE */
- Curl_init_completed, /* COMPLETED */
+ init_completed, /* COMPLETED */
NULL /* MSGSENT */
};
@@ -190,11 +197,11 @@ static void mstate(struct Curl_easy *data, CURLMstate state
*/
struct Curl_sh_entry {
- struct curl_hash transfers; /* hash of transfers using this socket */
+ struct Curl_hash transfers; /* hash of transfers using this socket */
unsigned int action; /* what combined action READ/WRITE this socket waits
for */
- void *socketp; /* settable by users with curl_multi_assign() */
unsigned int users; /* number of transfers using this */
+ void *socketp; /* settable by users with curl_multi_assign() */
unsigned int readers; /* this many transfers want to read */
unsigned int writers; /* this many transfers want to write */
};
@@ -204,7 +211,7 @@ struct Curl_sh_entry {
#define SH_WRITE 2
/* look up a given socket in the socket hash, skip invalid sockets */
-static struct Curl_sh_entry *sh_getentry(struct curl_hash *sh,
+static struct Curl_sh_entry *sh_getentry(struct Curl_hash *sh,
curl_socket_t s)
{
if(s != CURL_SOCKET_BAD) {
@@ -238,7 +245,7 @@ static void trhash_dtor(void *nada)
/* make sure this socket is present in the hash for this handle */
-static struct Curl_sh_entry *sh_addentry(struct curl_hash *sh,
+static struct Curl_sh_entry *sh_addentry(struct Curl_hash *sh,
curl_socket_t s)
{
struct Curl_sh_entry *there = sh_getentry(sh, s);
@@ -273,7 +280,7 @@ static struct Curl_sh_entry *sh_addentry(struct curl_hash *sh,
/* delete the given socket + handle from the hash */
static void sh_delentry(struct Curl_sh_entry *entry,
- struct curl_hash *sh, curl_socket_t s)
+ struct Curl_hash *sh, curl_socket_t s)
{
Curl_hash_destroy(&entry->transfers);
@@ -325,7 +332,7 @@ static size_t hash_fd(void *key, size_t key_length, size_t slots_num)
* per call."
*
*/
-static int sh_init(struct curl_hash *hash, int hashsize)
+static int sh_init(struct Curl_hash *hash, int hashsize)
{
return Curl_hash_init(hash, hashsize, hash_fd, fd_key_compare,
sh_freeentry);
@@ -353,7 +360,7 @@ struct Curl_multi *Curl_multi_handle(int hashsize, /* socket hash */
if(!multi)
return NULL;
- multi->type = CURL_MULTI_HANDLE;
+ multi->magic = CURL_MULTI_HANDLE;
if(Curl_mk_dnscache(&multi->hostcache))
goto error;
@@ -558,7 +565,7 @@ static CURLcode multi_done(struct Curl_easy *data,
conn->data = data; /* ensure the connection uses this transfer now */
/* Stop the resolver and free its own resources (but not dns_entry yet). */
- Curl_resolver_kill(conn);
+ Curl_resolver_kill(data);
/* Cleanup possible redirect junk */
Curl_safefree(data->req.newurl);
@@ -579,14 +586,14 @@ static CURLcode multi_done(struct Curl_easy *data,
/* this calls the protocol-specific function pointer previously set */
if(conn->handler->done)
- result = conn->handler->done(conn, status, premature);
+ result = conn->handler->done(data, status, premature);
else
result = status;
if(CURLE_ABORTED_BY_CALLBACK != result) {
/* avoid this if we already aborted by callback to avoid this calling
another callback */
- CURLcode rc = Curl_pgrsDone(conn);
+ CURLcode rc = Curl_pgrsDone(data);
if(!result && rc)
result = CURLE_ABORTED_BY_CALLBACK;
}
@@ -690,17 +697,13 @@ static CURLcode multi_done(struct Curl_easy *data,
return result;
}
-static int close_connect_only(struct connectdata *conn, void *param)
+static int close_connect_only(struct Curl_easy *data,
+ struct connectdata *conn, void *param)
{
- struct Curl_easy *data = param;
-
+ (void)param;
if(data->state.lastconnect_id != conn->connection_id)
return 0;
- if(conn->data != data)
- return 1;
- conn->data = NULL;
-
if(!conn->bits.connect_only)
return 1;
@@ -716,7 +719,7 @@ CURLMcode curl_multi_remove_handle(struct Curl_multi *multi,
struct Curl_easy *easy = data;
bool premature;
bool easy_owns_conn;
- struct curl_llist_element *e;
+ struct Curl_llist_element *e;
/* First, make some basic checks that the CURLM handle is a good handle */
if(!GOOD_MULTI_HANDLE(multi))
@@ -809,7 +812,7 @@ CURLMcode curl_multi_remove_handle(struct Curl_multi *multi,
if(data->state.lastconnect_id != -1) {
/* Mark any connect-only connection for closure */
Curl_conncache_foreach(data, data->state.conn_cache,
- data, &close_connect_only);
+ NULL, close_connect_only);
}
#ifdef USE_LIBPSL
@@ -938,27 +941,30 @@ static int waitproxyconnect_getsock(struct connectdata *conn,
return GETSOCK_WRITESOCK(0);
}
-static int domore_getsock(struct connectdata *conn,
+static int domore_getsock(struct Curl_easy *data,
+ struct connectdata *conn,
curl_socket_t *socks)
{
if(conn && conn->handler->domore_getsock)
- return conn->handler->domore_getsock(conn, socks);
+ return conn->handler->domore_getsock(data, conn, socks);
return GETSOCK_BLANK;
}
-static int doing_getsock(struct connectdata *conn,
+static int doing_getsock(struct Curl_easy *data,
+ struct connectdata *conn,
curl_socket_t *socks)
{
if(conn && conn->handler->doing_getsock)
- return conn->handler->doing_getsock(conn, socks);
+ return conn->handler->doing_getsock(data, conn, socks);
return GETSOCK_BLANK;
}
-static int protocol_getsock(struct connectdata *conn,
+static int protocol_getsock(struct Curl_easy *data,
+ struct connectdata *conn,
curl_socket_t *socks)
{
if(conn->handler->proto_getsock)
- return conn->handler->proto_getsock(conn, socks);
+ return conn->handler->proto_getsock(data, conn, socks);
/* Backup getsock logic. Since there is a live socket in use, we must wait
for it or it will be removed from watching when the multi_socket API is
used. */
@@ -971,10 +977,11 @@ static int protocol_getsock(struct connectdata *conn,
static int multi_getsock(struct Curl_easy *data,
curl_socket_t *socks)
{
+ struct connectdata *conn = data->conn;
/* The no connection case can happen when this is called from
curl_multi_remove_handle() => singlesocket() => multi_getsock().
*/
- if(!data->conn)
+ if(!conn)
return 0;
if(data->mstate > CURLM_STATE_CONNECT &&
@@ -988,30 +995,30 @@ static int multi_getsock(struct Curl_easy *data,
return 0;
case CURLM_STATE_WAITRESOLVE:
- return Curl_resolv_getsock(data->conn, socks);
+ return Curl_resolv_getsock(data, socks);
case CURLM_STATE_PROTOCONNECT:
case CURLM_STATE_SENDPROTOCONNECT:
- return protocol_getsock(data->conn, socks);
+ return protocol_getsock(data, conn, socks);
case CURLM_STATE_DO:
case CURLM_STATE_DOING:
- return doing_getsock(data->conn, socks);
+ return doing_getsock(data, conn, socks);
case CURLM_STATE_WAITPROXYCONNECT:
- return waitproxyconnect_getsock(data->conn, socks);
+ return waitproxyconnect_getsock(conn, socks);
case CURLM_STATE_WAITCONNECT:
- return waitconnect_getsock(data->conn, socks);
+ return waitconnect_getsock(conn, socks);
case CURLM_STATE_DO_MORE:
- return domore_getsock(data->conn, socks);
+ return domore_getsock(data, conn, socks);
case CURLM_STATE_DO_DONE: /* since is set after DO is completed, we switch
to waiting for the same as the *PERFORM
states */
case CURLM_STATE_PERFORM:
- return Curl_single_getsock(data->conn, socks);
+ return Curl_single_getsock(data, conn, socks);
}
}
@@ -1067,13 +1074,13 @@ CURLMcode curl_multi_fdset(struct Curl_multi *multi,
#define NUM_POLLS_ON_STACK 10
-static CURLMcode Curl_multi_wait(struct Curl_multi *multi,
- struct curl_waitfd extra_fds[],
- unsigned int extra_nfds,
- int timeout_ms,
- int *ret,
- bool extrawait, /* when no socket, wait */
- bool use_wakeup)
+static CURLMcode multi_wait(struct Curl_multi *multi,
+ struct curl_waitfd extra_fds[],
+ unsigned int extra_nfds,
+ int timeout_ms,
+ int *ret,
+ bool extrawait, /* when no socket, wait */
+ bool use_wakeup)
{
struct Curl_easy *data;
curl_socket_t sockbunch[MAX_SOCKSPEREASYHANDLE];
@@ -1081,11 +1088,11 @@ static CURLMcode Curl_multi_wait(struct Curl_multi *multi,
unsigned int i;
unsigned int nfds = 0;
unsigned int curlfds;
- bool ufds_malloc = FALSE;
long timeout_internal;
int retcode = 0;
struct pollfd a_few_on_stack[NUM_POLLS_ON_STACK];
struct pollfd *ufds = &a_few_on_stack[0];
+ bool ufds_malloc = FALSE;
if(!GOOD_MULTI_HANDLE(multi))
return CURLM_BAD_HANDLE;
@@ -1157,7 +1164,7 @@ static CURLMcode Curl_multi_wait(struct Curl_multi *multi,
while(data) {
bitmap = multi_getsock(data, sockbunch);
- for(i = 0; i< MAX_SOCKSPEREASYHANDLE; i++) {
+ for(i = 0; i < MAX_SOCKSPEREASYHANDLE; i++) {
curl_socket_t s = CURL_SOCKET_BAD;
if(bitmap & GETSOCK_READSOCK(i)) {
@@ -1203,10 +1210,8 @@ static CURLMcode Curl_multi_wait(struct Curl_multi *multi,
#endif
if(nfds) {
- int pollrc;
/* wait... */
- pollrc = Curl_poll(ufds, nfds, timeout_ms);
-
+ int pollrc = Curl_poll(ufds, nfds, timeout_ms);
if(pollrc > 0) {
retcode = pollrc;
/* copy revents results from the poll to the curl_multi_wait poll
@@ -1222,7 +1227,6 @@ static CURLMcode Curl_multi_wait(struct Curl_multi *multi,
mask |= CURL_WAIT_POLLOUT;
if(r & POLLPRI)
mask |= CURL_WAIT_POLLPRI;
-
extra_fds[i].revents = mask;
}
@@ -1284,8 +1288,8 @@ CURLMcode curl_multi_wait(struct Curl_multi *multi,
int timeout_ms,
int *ret)
{
- return Curl_multi_wait(multi, extra_fds, extra_nfds, timeout_ms, ret, FALSE,
- FALSE);
+ return multi_wait(multi, extra_fds, extra_nfds, timeout_ms, ret, FALSE,
+ FALSE);
}
CURLMcode curl_multi_poll(struct Curl_multi *multi,
@@ -1294,8 +1298,8 @@ CURLMcode curl_multi_poll(struct Curl_multi *multi,
int timeout_ms,
int *ret)
{
- return Curl_multi_wait(multi, extra_fds, extra_nfds, timeout_ms, ret, TRUE,
- TRUE);
+ return multi_wait(multi, extra_fds, extra_nfds, timeout_ms, ret, TRUE,
+ TRUE);
}
CURLMcode curl_multi_wakeup(struct Curl_multi *multi)
@@ -1322,7 +1326,7 @@ CURLMcode curl_multi_wakeup(struct Curl_multi *multi)
The write socket is set to non-blocking, this way this function
cannot block, making it safe to call even from the same thread
- that will call Curl_multi_wait(). If swrite() returns that it
+ that will call curl_multi_wait(). If swrite() returns that it
would block, it's considered successful because it means that
previous calls to this function will wake up the poll(). */
if(swrite(multi->wakeup_pair[1], buf, sizeof(buf)) < 0) {
@@ -1386,18 +1390,6 @@ CURLMcode Curl_multi_add_perform(struct Curl_multi *multi,
return rc;
}
-/*
- * do_complete is called when the DO actions are complete.
- *
- * We init chunking and trailer bits to their default values here immediately
- * before receiving any header data for the current request.
- */
-static void do_complete(struct connectdata *conn)
-{
- conn->data->req.chunk = FALSE;
- Curl_pgrsTime(conn->data, TIMER_PRETRANSFER);
-}
-
static CURLcode multi_do(struct Curl_easy *data, bool *done)
{
CURLcode result = CURLE_OK;
@@ -1407,14 +1399,10 @@ static CURLcode multi_do(struct Curl_easy *data, bool *done)
DEBUGASSERT(conn->handler);
DEBUGASSERT(conn->data == data);
- if(conn->handler->do_it) {
+ if(conn->handler->do_it)
/* generic protocol-specific function pointer set in curl_connect() */
- result = conn->handler->do_it(conn, done);
+ result = conn->handler->do_it(data, done);
- if(!result && *done)
- /* do_complete must be called after the protocol-specific DO function */
- do_complete(conn);
- }
return result;
}
@@ -1427,18 +1415,15 @@ static CURLcode multi_do(struct Curl_easy *data, bool *done)
* DOING state there's more work to do!
*/
-static CURLcode multi_do_more(struct connectdata *conn, int *complete)
+static CURLcode multi_do_more(struct Curl_easy *data, int *complete)
{
CURLcode result = CURLE_OK;
+ struct connectdata *conn = data->conn;
*complete = 0;
if(conn->handler->do_more)
- result = conn->handler->do_more(conn, complete);
-
- if(!result && (*complete == 1))
- /* do_complete must be called after the protocol-specific DO function */
- do_complete(conn);
+ result = conn->handler->do_more(data, complete);
return result;
}
@@ -1449,14 +1434,14 @@ static CURLcode multi_do_more(struct connectdata *conn, int *complete)
* protocol layer.
*/
-static CURLcode protocol_connecting(struct connectdata *conn,
- bool *done)
+static CURLcode protocol_connecting(struct Curl_easy *data, bool *done)
{
CURLcode result = CURLE_OK;
+ struct connectdata *conn = data->conn;
if(conn && conn->handler->connecting) {
*done = FALSE;
- result = conn->handler->connecting(conn, done);
+ result = conn->handler->connecting(data, done);
}
else
*done = TRUE;
@@ -1469,13 +1454,14 @@ static CURLcode protocol_connecting(struct connectdata *conn,
* until the DOING phase is done on protocol layer.
*/
-static CURLcode protocol_doing(struct connectdata *conn, bool *done)
+static CURLcode protocol_doing(struct Curl_easy *data, bool *done)
{
CURLcode result = CURLE_OK;
+ struct connectdata *conn = data->conn;
if(conn && conn->handler->doing) {
*done = FALSE;
- result = conn->handler->doing(conn, done);
+ result = conn->handler->doing(data, done);
}
else
*done = TRUE;
@@ -1488,11 +1474,11 @@ static CURLcode protocol_doing(struct connectdata *conn, bool *done)
* proceed with some action.
*
*/
-static CURLcode protocol_connect(struct connectdata *conn,
+static CURLcode protocol_connect(struct Curl_easy *data,
bool *protocol_done)
{
CURLcode result = CURLE_OK;
-
+ struct connectdata *conn = data->conn;
DEBUGASSERT(conn);
DEBUGASSERT(protocol_done);
@@ -1513,7 +1499,7 @@ static CURLcode protocol_connect(struct connectdata *conn,
if(!conn->bits.protoconnstart) {
#ifndef CURL_DISABLE_PROXY
- result = Curl_proxy_connect(conn, FIRSTSOCKET);
+ result = Curl_proxy_connect(data, FIRSTSOCKET);
if(result)
return result;
@@ -1531,7 +1517,7 @@ static CURLcode protocol_connect(struct connectdata *conn,
/* is there a protocol-specific connect() procedure? */
/* Call the protocol-specific connect function */
- result = conn->handler->connect_it(conn, protocol_done);
+ result = conn->handler->connect_it(data, protocol_done);
}
else
*protocol_done = TRUE;
@@ -1562,7 +1548,7 @@ CURLcode Curl_preconnect(struct Curl_easy *data)
static CURLMcode multi_runsingle(struct Curl_multi *multi,
- struct curltime now,
+ struct curltime *nowp,
struct Curl_easy *data)
{
struct Curl_message *msg = NULL;
@@ -1592,9 +1578,12 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
process_pending_handles(multi); /* multiplexed */
}
- if(data->conn && data->mstate > CURLM_STATE_CONNECT &&
+ if(data->mstate > CURLM_STATE_CONNECT &&
data->mstate < CURLM_STATE_COMPLETED) {
/* Make sure we set the connection's current owner */
+ DEBUGASSERT(data->conn);
+ if(!data->conn)
+ return CURLM_INTERNAL_ERROR;
data->conn->data = data;
}
@@ -1603,7 +1592,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
(data->mstate < CURLM_STATE_COMPLETED)) {
/* we need to wait for the connect state as only then is the start time
stored, but we must not check already completed handles */
- timeout_ms = Curl_timeleft(data, &now,
+ timeout_ms = Curl_timeleft(data, nowp,
(data->mstate <= CURLM_STATE_DO)?
TRUE:FALSE);
@@ -1612,25 +1601,25 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
if(data->mstate == CURLM_STATE_WAITRESOLVE)
failf(data, "Resolving timed out after %" CURL_FORMAT_TIMEDIFF_T
" milliseconds",
- Curl_timediff(now, data->progress.t_startsingle));
+ Curl_timediff(*nowp, data->progress.t_startsingle));
else if(data->mstate == CURLM_STATE_WAITCONNECT)
failf(data, "Connection timed out after %" CURL_FORMAT_TIMEDIFF_T
" milliseconds",
- Curl_timediff(now, data->progress.t_startsingle));
+ Curl_timediff(*nowp, data->progress.t_startsingle));
else {
struct SingleRequest *k = &data->req;
if(k->size != -1) {
failf(data, "Operation timed out after %" CURL_FORMAT_TIMEDIFF_T
" milliseconds with %" CURL_FORMAT_CURL_OFF_T " out of %"
CURL_FORMAT_CURL_OFF_T " bytes received",
- Curl_timediff(now, data->progress.t_startsingle),
+ Curl_timediff(*nowp, data->progress.t_startsingle),
k->bytecount, k->size);
}
else {
failf(data, "Operation timed out after %" CURL_FORMAT_TIMEDIFF_T
" milliseconds with %" CURL_FORMAT_CURL_OFF_T
" bytes received",
- Curl_timediff(now, data->progress.t_startsingle),
+ Curl_timediff(*nowp, data->progress.t_startsingle),
k->bytecount);
}
}
@@ -1655,7 +1644,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
if(!result) {
/* after init, go CONNECT */
multistate(data, CURLM_STATE_CONNECT);
- Curl_pgrsTime(data, TIMER_STARTOP);
+ *nowp = Curl_pgrsTime(data, TIMER_STARTOP);
rc = CURLM_CALL_MULTI_PERFORM;
}
break;
@@ -1672,7 +1661,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
if(result)
break;
- Curl_pgrsTime(data, TIMER_STARTSINGLE);
+ *nowp = Curl_pgrsTime(data, TIMER_STARTSINGLE);
if(data->set.timeout)
Curl_expire(data, data->set.timeout, EXPIRE_TIMEOUT);
@@ -1740,19 +1729,19 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
hostname = conn->host.name;
/* check if we have the name resolved by now */
- dns = Curl_fetch_addr(conn, hostname, (int)conn->port);
+ dns = Curl_fetch_addr(data, hostname, (int)conn->port);
if(dns) {
#ifdef CURLRES_ASYNCH
- conn->async.dns = dns;
- conn->async.done = TRUE;
+ data->state.async.dns = dns;
+ data->state.async.done = TRUE;
#endif
result = CURLE_OK;
infof(data, "Hostname '%s' was found in DNS cache\n", hostname);
}
if(!dns)
- result = Curl_resolv_check(data->conn, &dns);
+ result = Curl_resolv_check(data, &dns);
/* Update sockets here, because the socket(s) may have been
closed and the application thus needs to be told, even if it
@@ -1765,7 +1754,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
if(dns) {
/* Perform the next step in the connection phase, and then move on
to the WAITCONNECT state */
- result = Curl_once_resolved(data->conn, &protocol_connected);
+ result = Curl_once_resolved(data, &protocol_connected);
if(result)
/* if Curl_once_resolved() returns failure, the connection struct
@@ -1799,7 +1788,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
case CURLM_STATE_WAITPROXYCONNECT:
/* this is HTTP-specific, but sending CONNECT to a proxy is HTTP... */
DEBUGASSERT(data->conn);
- result = Curl_http_connect(data->conn, &protocol_connected);
+ result = Curl_http_connect(data, &protocol_connected);
#ifndef CURL_DISABLE_PROXY
if(data->conn->bits.proxy_connect_closed) {
rc = CURLM_CALL_MULTI_PERFORM;
@@ -1830,7 +1819,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
case CURLM_STATE_WAITCONNECT:
/* awaiting a completion of an asynch TCP connect */
DEBUGASSERT(data->conn);
- result = Curl_is_connected(data->conn, FIRSTSOCKET, &connected);
+ result = Curl_is_connected(data, data->conn, FIRSTSOCKET, &connected);
if(connected && !result) {
#ifndef CURL_DISABLE_HTTP
if(
@@ -1863,7 +1852,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
break;
case CURLM_STATE_SENDPROTOCONNECT:
- result = protocol_connect(data->conn, &protocol_connected);
+ result = protocol_connect(data, &protocol_connected);
if(!result && !protocol_connected)
/* switch to waiting state */
multistate(data, CURLM_STATE_PROTOCONNECT);
@@ -1882,7 +1871,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
case CURLM_STATE_PROTOCONNECT:
/* protocol-specific connect phase */
- result = protocol_connecting(data->conn, &protocol_connected);
+ result = protocol_connecting(data, &protocol_connected);
if(!result && protocol_connected) {
/* after the connect has completed, go WAITDO or DO */
multistate(data, CURLM_STATE_DO);
@@ -1919,7 +1908,10 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
if(wc->state == CURLWC_DONE || wc->state == CURLWC_SKIP) {
/* skip some states if it is important */
multi_done(data, CURLE_OK, FALSE);
- multistate(data, CURLM_STATE_DONE);
+
+ /* if there's no connection left, skip the DONE state */
+ multistate(data, data->conn ?
+ CURLM_STATE_DONE : CURLM_STATE_COMPLETED);
rc = CURLM_CALL_MULTI_PERFORM;
break;
}
@@ -1955,7 +1947,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
followtype follow = FOLLOW_NONE;
CURLcode drc;
- drc = Curl_retry_request(data->conn, &newurl);
+ drc = Curl_retry_request(data, &newurl);
if(drc) {
/* a failure here pretty much implies an out of memory */
result = drc;
@@ -2005,7 +1997,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
case CURLM_STATE_DOING:
/* we continue DOING until the DO phase is complete */
DEBUGASSERT(data->conn);
- result = protocol_doing(data->conn, &dophase_done);
+ result = protocol_doing(data, &dophase_done);
if(!result) {
if(dophase_done) {
/* after DO, go DO_DONE or DO_MORE */
@@ -2028,7 +2020,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
* When we are connected, DO MORE and then go DO_DONE
*/
DEBUGASSERT(data->conn);
- result = multi_do_more(data->conn, &control);
+ result = multi_do_more(data, &control);
if(!result) {
if(control) {
@@ -2077,12 +2069,20 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
case CURLM_STATE_TOOFAST: /* limit-rate exceeded in either direction */
DEBUGASSERT(data->conn);
/* if both rates are within spec, resume transfer */
- if(Curl_pgrsUpdate(data->conn))
+ if(Curl_pgrsUpdate(data))
result = CURLE_ABORTED_BY_CALLBACK;
else
- result = Curl_speedcheck(data, now);
+ result = Curl_speedcheck(data, *nowp);
- if(!result) {
+ if(result) {
+ if(!(data->conn->handler->flags & PROTOPT_DUAL) &&
+ result != CURLE_HTTP2_STREAM)
+ streamclose(data->conn, "Transfer returned error");
+
+ Curl_posttransfer(data);
+ multi_done(data, result, TRUE);
+ }
+ else {
send_timeout_ms = 0;
if(data->set.max_send_speed > 0)
send_timeout_ms =
@@ -2090,7 +2090,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
data->progress.ul_limit_size,
data->set.max_send_speed,
data->progress.ul_limit_start,
- now);
+ *nowp);
recv_timeout_ms = 0;
if(data->set.max_recv_speed > 0)
@@ -2099,11 +2099,11 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
data->progress.dl_limit_size,
data->set.max_recv_speed,
data->progress.dl_limit_start,
- now);
+ *nowp);
if(!send_timeout_ms && !recv_timeout_ms) {
multistate(data, CURLM_STATE_PERFORM);
- Curl_ratelimit(data, now);
+ Curl_ratelimit(data, *nowp);
}
else if(send_timeout_ms >= recv_timeout_ms)
Curl_expire(data, send_timeout_ms, EXPIRE_TOOFAST);
@@ -2125,7 +2125,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
data->progress.ul_limit_size,
data->set.max_send_speed,
data->progress.ul_limit_start,
- now);
+ *nowp);
/* check if over recv speed */
recv_timeout_ms = 0;
@@ -2134,10 +2134,10 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
data->progress.dl_limit_size,
data->set.max_recv_speed,
data->progress.dl_limit_start,
- now);
+ *nowp);
if(send_timeout_ms || recv_timeout_ms) {
- Curl_ratelimit(data, now);
+ Curl_ratelimit(data, *nowp);
multistate(data, CURLM_STATE_TOOFAST);
if(send_timeout_ms >= recv_timeout_ms)
Curl_expire(data, send_timeout_ms, EXPIRE_TOOFAST);
@@ -2154,7 +2154,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
* condition and the server closed the re-used connection exactly when
* we wanted to use it, so figure out if that is indeed the case.
*/
- CURLcode ret = Curl_retry_request(data->conn, &newurl);
+ CURLcode ret = Curl_retry_request(data, &newurl);
if(!ret)
retry = (newurl)?TRUE:FALSE;
else if(!result)
@@ -2169,7 +2169,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
}
else if((CURLE_HTTP2_STREAM == result) &&
Curl_h2_http_1_1_error(data->conn)) {
- CURLcode ret = Curl_retry_request(data->conn, &newurl);
+ CURLcode ret = Curl_retry_request(data, &newurl);
if(!ret) {
infof(data, "Downgrades to HTTP/1.1!\n");
@@ -2206,7 +2206,6 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
multi_done(data, result, TRUE);
}
else if(done) {
- followtype follow = FOLLOW_NONE;
/* call this even if the readwrite function returned error */
Curl_posttransfer(data);
@@ -2214,6 +2213,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
/* When we follow redirects or is set to retry the connection, we must
to go back to the CONNECT state */
if(data->req.newurl || retry) {
+ followtype follow = FOLLOW_NONE;
if(!retry) {
/* if the URL is a follow-location and not just a retried request
then figure out the URL here */
@@ -2283,14 +2283,6 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
/* allow a previously set error code take precedence */
if(!result)
result = res;
-
- /*
- * If there are other handles on the connection, multi_done won't set
- * conn to NULL. In such a case, curl_multi_remove_handle() can
- * access free'd data, if the connection is free'd and the handle
- * removed before we perform the processing in CURLM_STATE_COMPLETED
- */
- Curl_detach_connnection(data);
}
#ifndef CURL_DISABLE_FTP
@@ -2360,7 +2352,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
rc = CURLM_CALL_MULTI_PERFORM;
}
/* if there's still a connection to use, call the progress function */
- else if(data->conn && Curl_pgrsUpdate(data->conn)) {
+ else if(data->conn && Curl_pgrsUpdate(data)) {
/* aborted due to progress callback return code must close the
connection */
result = CURLE_ABORTED_BY_CALLBACK;
@@ -2417,7 +2409,7 @@ CURLMcode curl_multi_perform(struct Curl_multi *multi, int *running_handles)
SIGPIPE_VARIABLE(pipe_st);
sigpipe_ignore(data, &pipe_st);
- result = multi_runsingle(multi, now, data);
+ result = multi_runsingle(multi, &now, data);
sigpipe_restore(&pipe_st);
if(result)
@@ -2461,7 +2453,7 @@ CURLMcode curl_multi_cleanup(struct Curl_multi *multi)
if(multi->in_callback)
return CURLM_RECURSIVE_API_CALL;
- multi->type = 0; /* not good anymore */
+ multi->magic = 0; /* not good anymore */
/* Firsrt remove all remaining easy handles */
data = multi->easyp;
@@ -2531,7 +2523,7 @@ CURLMsg *curl_multi_info_read(struct Curl_multi *multi, int *msgs_in_queue)
!multi->in_callback &&
Curl_llist_count(&multi->msglist)) {
/* there is one or more messages in the list */
- struct curl_llist_element *e;
+ struct Curl_llist_element *e;
/* extract the head of the list to return */
e = multi->msglist.head;
@@ -2761,15 +2753,15 @@ static CURLMcode add_next_timeout(struct curltime now,
struct Curl_easy *d)
{
struct curltime *tv = &d->state.expiretime;
- struct curl_llist *list = &d->state.timeoutlist;
- struct curl_llist_element *e;
+ struct Curl_llist *list = &d->state.timeoutlist;
+ struct Curl_llist_element *e;
struct time_node *node = NULL;
/* move over the timeout list for this specific handle and remove all
timeouts that are now passed tense and store the next pending
timeout in *tv */
for(e = list->head; e;) {
- struct curl_llist_element *n = e->next;
+ struct Curl_llist_element *n = e->next;
timediff_t diff;
node = (struct time_node *)e->ptr;
diff = Curl_timediff(node->time, now);
@@ -2839,8 +2831,8 @@ static CURLMcode multi_socket(struct Curl_multi *multi,
and just move on. */
;
else {
- struct curl_hash_iterator iter;
- struct curl_hash_element *he;
+ struct Curl_hash_iterator iter;
+ struct Curl_hash_element *he;
/* the socket can be shared by many transfers, iterate */
Curl_hash_start_iterate(&entry->transfers, &iter);
@@ -2887,7 +2879,7 @@ static CURLMcode multi_socket(struct Curl_multi *multi,
SIGPIPE_VARIABLE(pipe_st);
sigpipe_ignore(data, &pipe_st);
- result = multi_runsingle(multi, now, data);
+ result = multi_runsingle(multi, &now, data);
sigpipe_restore(&pipe_st);
if(CURLM_OK >= result) {
@@ -3015,7 +3007,6 @@ CURLMcode curl_multi_socket_action(struct Curl_multi *multi, curl_socket_t s,
}
CURLMcode curl_multi_socket_all(struct Curl_multi *multi, int *running_handles)
-
{
CURLMcode result;
if(multi->in_callback)
@@ -3123,8 +3114,8 @@ void Curl_update_timer(struct Curl_multi *multi)
static void
multi_deltimeout(struct Curl_easy *data, expire_id eid)
{
- struct curl_llist_element *e;
- struct curl_llist *timeoutlist = &data->state.timeoutlist;
+ struct Curl_llist_element *e;
+ struct Curl_llist *timeoutlist = &data->state.timeoutlist;
/* find and remove the specific node from the list */
for(e = timeoutlist->head; e; e = e->next) {
struct time_node *n = (struct time_node *)e->ptr;
@@ -3147,11 +3138,11 @@ multi_addtimeout(struct Curl_easy *data,
struct curltime *stamp,
expire_id eid)
{
- struct curl_llist_element *e;
+ struct Curl_llist_element *e;
struct time_node *node;
- struct curl_llist_element *prev = NULL;
+ struct Curl_llist_element *prev = NULL;
size_t n;
- struct curl_llist *timeoutlist = &data->state.timeoutlist;
+ struct Curl_llist *timeoutlist = &data->state.timeoutlist;
node = &data->state.expires[eid];
@@ -3233,9 +3224,8 @@ void Curl_expire(struct Curl_easy *data, timediff_t milli, expire_id id)
/* Since this is an updated time, we must remove the previous entry from
the splay tree first and then re-add the new value */
- rc = Curl_splayremovebyaddr(multi->timetree,
- &data->state.timenode,
- &multi->timetree);
+ rc = Curl_splayremove(multi->timetree, &data->state.timenode,
+ &multi->timetree);
if(rc)
infof(data, "Internal error removing splay node = %d\n", rc);
}
@@ -3278,12 +3268,11 @@ void Curl_expire_clear(struct Curl_easy *data)
if(nowp->tv_sec || nowp->tv_usec) {
/* Since this is an cleared time, we must remove the previous entry from
the splay tree */
- struct curl_llist *list = &data->state.timeoutlist;
+ struct Curl_llist *list = &data->state.timeoutlist;
int rc;
- rc = Curl_splayremovebyaddr(multi->timetree,
- &data->state.timenode,
- &multi->timetree);
+ rc = Curl_splayremove(multi->timetree, &data->state.timenode,
+ &multi->timetree);
if(rc)
infof(data, "Internal error clearing splay node = %d\n", rc);
@@ -3335,21 +3324,23 @@ size_t Curl_multi_max_total_connections(struct Curl_multi *multi)
* When information about a connection has appeared, call this!
*/
-void Curl_multiuse_state(struct connectdata *conn,
+void Curl_multiuse_state(struct Curl_easy *data,
int bundlestate) /* use BUNDLE_* defines */
{
+ struct connectdata *conn;
+ DEBUGASSERT(data);
+ DEBUGASSERT(data->multi);
+ conn = data->conn;
DEBUGASSERT(conn);
DEBUGASSERT(conn->bundle);
- DEBUGASSERT(conn->data);
- DEBUGASSERT(conn->data->multi);
conn->bundle->multiuse = bundlestate;
- process_pending_handles(conn->data->multi);
+ process_pending_handles(data->multi);
}
static void process_pending_handles(struct Curl_multi *multi)
{
- struct curl_llist_element *e = multi->pending.head;
+ struct Curl_llist_element *e = multi->pending.head;
if(e) {
struct Curl_easy *data = e->ptr;
diff --git a/Utilities/cmcurl/lib/multihandle.h b/Utilities/cmcurl/lib/multihandle.h
index 9d73df081..f28c5899b 100644
--- a/Utilities/cmcurl/lib/multihandle.h
+++ b/Utilities/cmcurl/lib/multihandle.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -22,12 +22,16 @@
*
***************************************************************************/
+#include "llist.h"
+#include "hash.h"
#include "conncache.h"
#include "psl.h"
#include "socketpair.h"
+struct connectdata;
+
struct Curl_message {
- struct curl_llist_element list;
+ struct Curl_llist_element list;
/* the 'CURLMsg' is the part that is visible to the external user */
struct CURLMsg extmsg;
};
@@ -67,11 +71,11 @@ typedef enum {
#define CURLPIPE_ANY (CURLPIPE_MULTIPLEX)
-#if defined(USE_SOCKETPAIR) && !defined(USE_BLOCKING_SOCKETS)
+#if defined(USE_SOCKETPAIR) && !defined(USE_BLOCKING_SOCKETS) && \
+ !defined(CURL_DISABLE_SOCKETPAIR)
#define ENABLE_WAKEUP
#endif
-
/* value for MAXIMUM CONCURRENT STREAMS upper limit */
#define INITIAL_MAX_CONCURRENT_STREAMS ((1U << 31) - 1)
@@ -79,7 +83,7 @@ typedef enum {
struct Curl_multi {
/* First a simple identifier to easier detect if a user mix up
this multi handle with an easy handle. Set this to CURL_MULTI_HANDLE. */
- long type;
+ unsigned int magic;
/* We have a doubly-linked list with easy handles */
struct Curl_easy *easyp;
@@ -89,9 +93,9 @@ struct Curl_multi {
int num_alive; /* amount of easy handles that are added but have not yet
reached COMPLETE state */
- struct curl_llist msglist; /* a list of messages from completed transfers */
+ struct Curl_llist msglist; /* a list of messages from completed transfers */
- struct curl_llist pending; /* Curl_easys that are in the
+ struct Curl_llist pending; /* Curl_easys that are in the
CURLM_STATE_CONNECT_PEND state */
/* callback function and user data pointer for the *socket() API */
@@ -103,7 +107,7 @@ struct Curl_multi {
void *push_userp;
/* Hostname cache */
- struct curl_hash hostcache;
+ struct Curl_hash hostcache;
#ifdef USE_LIBPSL
/* PSL cache. */
@@ -117,7 +121,7 @@ struct Curl_multi {
/* 'sockhash' is the lookup hash for socket descriptor => easy handles (note
the pluralis form, there can be more than one easy handle waiting on the
same actual socket) */
- struct curl_hash sockhash;
+ struct Curl_hash sockhash;
/* Shared connection cache (bundles)*/
struct conncache conn_cache;
diff --git a/Utilities/cmcurl/lib/multiif.h b/Utilities/cmcurl/lib/multiif.h
index 7d574df92..2fbef53c4 100644
--- a/Utilities/cmcurl/lib/multiif.h
+++ b/Utilities/cmcurl/lib/multiif.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -69,7 +69,7 @@ size_t Curl_multi_max_host_connections(struct Curl_multi *multi);
/* Return the value of the CURLMOPT_MAX_TOTAL_CONNECTIONS option */
size_t Curl_multi_max_total_connections(struct Curl_multi *multi);
-void Curl_multiuse_state(struct connectdata *conn,
+void Curl_multiuse_state(struct Curl_easy *data,
int bundlestate); /* use BUNDLE_* defines */
/*
diff --git a/Utilities/cmcurl/lib/netrc.c b/Utilities/cmcurl/lib/netrc.c
index 1c9da3199..13610bb07 100644
--- a/Utilities/cmcurl/lib/netrc.c
+++ b/Utilities/cmcurl/lib/netrc.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
diff --git a/Utilities/cmcurl/lib/netrc.h b/Utilities/cmcurl/lib/netrc.h
index 7f56c4b4d..4938a5916 100644
--- a/Utilities/cmcurl/lib/netrc.h
+++ b/Utilities/cmcurl/lib/netrc.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
diff --git a/Utilities/cmcurl/lib/non-ascii.c b/Utilities/cmcurl/lib/non-ascii.c
index a48e67db4..30c240b63 100644
--- a/Utilities/cmcurl/lib/non-ascii.c
+++ b/Utilities/cmcurl/lib/non-ascii.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
diff --git a/Utilities/cmcurl/lib/non-ascii.h b/Utilities/cmcurl/lib/non-ascii.h
index 5fb5771e0..458e8ef09 100644
--- a/Utilities/cmcurl/lib/non-ascii.h
+++ b/Utilities/cmcurl/lib/non-ascii.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
diff --git a/Utilities/cmcurl/lib/nonblock.c b/Utilities/cmcurl/lib/nonblock.c
index abeb6598c..4a7bde504 100644
--- a/Utilities/cmcurl/lib/nonblock.c
+++ b/Utilities/cmcurl/lib/nonblock.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
diff --git a/Utilities/cmcurl/lib/nonblock.h b/Utilities/cmcurl/lib/nonblock.h
index d50d31594..761dab4f6 100644
--- a/Utilities/cmcurl/lib/nonblock.h
+++ b/Utilities/cmcurl/lib/nonblock.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
diff --git a/Utilities/cmcurl/lib/nwlib.c b/Utilities/cmcurl/lib/nwlib.c
index beec0b388..769326892 100644
--- a/Utilities/cmcurl/lib/nwlib.c
+++ b/Utilities/cmcurl/lib/nwlib.c
@@ -9,7 +9,7 @@
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/nwos.c b/Utilities/cmcurl/lib/nwos.c
index c6c22ccbb..889403132 100644
--- a/Utilities/cmcurl/lib/nwos.c
+++ b/Utilities/cmcurl/lib/nwos.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
diff --git a/Utilities/cmcurl/lib/openldap.c b/Utilities/cmcurl/lib/openldap.c
index 782d6a08e..4070bbf88 100644
--- a/Utilities/cmcurl/lib/openldap.c
+++ b/Utilities/cmcurl/lib/openldap.c
@@ -5,12 +5,12 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
+ * Copyright (C) 2011 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 2010, Howard Chu, <hyc@openldap.org>
- * Copyright (C) 2011 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -76,12 +76,14 @@ extern int ldap_init_fd(ber_socket_t fd, int proto, const char *url,
LDAP **ld);
#endif
-static CURLcode ldap_setup_connection(struct connectdata *conn);
-static CURLcode ldap_do(struct connectdata *conn, bool *done);
-static CURLcode ldap_done(struct connectdata *conn, CURLcode, bool);
-static CURLcode ldap_connect(struct connectdata *conn, bool *done);
-static CURLcode ldap_connecting(struct connectdata *conn, bool *done);
-static CURLcode ldap_disconnect(struct connectdata *conn, bool dead);
+static CURLcode ldap_setup_connection(struct Curl_easy *data,
+ struct connectdata *conn);
+static CURLcode ldap_do(struct Curl_easy *data, bool *done);
+static CURLcode ldap_done(struct Curl_easy *data, CURLcode, bool);
+static CURLcode ldap_connect(struct Curl_easy *data, bool *done);
+static CURLcode ldap_connecting(struct Curl_easy *data, bool *done);
+static CURLcode ldap_disconnect(struct Curl_easy *data,
+ struct connectdata *conn, bool dead);
static Curl_recv ldap_recv;
@@ -107,6 +109,7 @@ const struct Curl_handler Curl_handler_ldap = {
ZERO_NULL, /* connection_check */
PORT_LDAP, /* defport */
CURLPROTO_LDAP, /* protocol */
+ CURLPROTO_LDAP, /* family */
PROTOPT_NONE /* flags */
};
@@ -132,7 +135,8 @@ const struct Curl_handler Curl_handler_ldaps = {
ZERO_NULL, /* readwrite */
ZERO_NULL, /* connection_check */
PORT_LDAPS, /* defport */
- CURLPROTO_LDAP, /* protocol */
+ CURLPROTO_LDAPS, /* protocol */
+ CURLPROTO_LDAP, /* family */
PROTOPT_SSL /* flags */
};
#endif
@@ -167,11 +171,11 @@ struct ldapreqinfo {
int nument;
};
-static CURLcode ldap_setup_connection(struct connectdata *conn)
+static CURLcode ldap_setup_connection(struct Curl_easy *data,
+ struct connectdata *conn)
{
struct ldapconninfo *li;
LDAPURLDesc *lud;
- struct Curl_easy *data = conn->data;
int rc, proto;
CURLcode status;
@@ -184,7 +188,7 @@ static CURLcode ldap_setup_connection(struct connectdata *conn)
status = CURLE_OUT_OF_MEMORY;
msg = url_errs[rc];
}
- failf(conn->data, "LDAP local: %s", msg);
+ failf(data, "LDAP local: %s", msg);
return status;
}
proto = ldap_pvt_url_scheme2proto(lud->lud_scheme);
@@ -203,10 +207,10 @@ static CURLcode ldap_setup_connection(struct connectdata *conn)
static Sockbuf_IO ldapsb_tls;
#endif
-static CURLcode ldap_connect(struct connectdata *conn, bool *done)
+static CURLcode ldap_connect(struct Curl_easy *data, bool *done)
{
+ struct connectdata *conn = data->conn;
struct ldapconninfo *li = conn->proto.ldapc;
- struct Curl_easy *data = conn->data;
int rc, proto = LDAP_VERSION3;
char hosturl[1024];
char *ptr;
@@ -241,7 +245,8 @@ static CURLcode ldap_connect(struct connectdata *conn, bool *done)
#ifdef USE_SSL
if(conn->handler->flags & PROTOPT_SSL) {
CURLcode result;
- result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, &li->ssldone);
+ result = Curl_ssl_connect_nonblocking(data, conn,
+ FIRSTSOCKET, &li->ssldone);
if(result)
return result;
}
@@ -250,10 +255,10 @@ static CURLcode ldap_connect(struct connectdata *conn, bool *done)
return CURLE_OK;
}
-static CURLcode ldap_connecting(struct connectdata *conn, bool *done)
+static CURLcode ldap_connecting(struct Curl_easy *data, bool *done)
{
+ struct connectdata *conn = data->conn;
struct ldapconninfo *li = conn->proto.ldapc;
- struct Curl_easy *data = conn->data;
LDAPMessage *msg = NULL;
struct timeval tv = {0, 1}, *tvp;
int rc, err;
@@ -263,7 +268,7 @@ static CURLcode ldap_connecting(struct connectdata *conn, bool *done)
if(conn->handler->flags & PROTOPT_SSL) {
/* Is the SSL handshake complete yet? */
if(!li->ssldone) {
- CURLcode result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET,
+ CURLcode result = Curl_ssl_connect_nonblocking(data, conn, FIRSTSOCKET,
&li->ssldone);
if(result || !li->ssldone)
return result;
@@ -355,10 +360,12 @@ static CURLcode ldap_connecting(struct connectdata *conn, bool *done)
return CURLE_OK;
}
-static CURLcode ldap_disconnect(struct connectdata *conn, bool dead_connection)
+static CURLcode ldap_disconnect(struct Curl_easy *data,
+ struct connectdata *conn, bool dead_connection)
{
struct ldapconninfo *li = conn->proto.ldapc;
(void) dead_connection;
+ (void) data;
if(li) {
if(li->ld) {
@@ -371,15 +378,15 @@ static CURLcode ldap_disconnect(struct connectdata *conn, bool dead_connection)
return CURLE_OK;
}
-static CURLcode ldap_do(struct connectdata *conn, bool *done)
+static CURLcode ldap_do(struct Curl_easy *data, bool *done)
{
+ struct connectdata *conn = data->conn;
struct ldapconninfo *li = conn->proto.ldapc;
struct ldapreqinfo *lr;
CURLcode status = CURLE_OK;
int rc = 0;
LDAPURLDesc *ludp = NULL;
int msgid;
- struct Curl_easy *data = conn->data;
connkeep(conn, "OpenLDAP do");
@@ -394,7 +401,7 @@ static CURLcode ldap_do(struct connectdata *conn, bool *done)
status = CURLE_OUT_OF_MEMORY;
msg = url_errs[rc];
}
- failf(conn->data, "LDAP local: %s", msg);
+ failf(data, "LDAP local: %s", msg);
return status;
}
@@ -410,16 +417,17 @@ static CURLcode ldap_do(struct connectdata *conn, bool *done)
if(!lr)
return CURLE_OUT_OF_MEMORY;
lr->msgid = msgid;
- data->req.protop = lr;
+ data->req.p.ldap = lr;
Curl_setup_transfer(data, FIRSTSOCKET, -1, FALSE, -1);
*done = TRUE;
return CURLE_OK;
}
-static CURLcode ldap_done(struct connectdata *conn, CURLcode res,
+static CURLcode ldap_done(struct Curl_easy *data, CURLcode res,
bool premature)
{
- struct ldapreqinfo *lr = conn->data->req.protop;
+ struct connectdata *conn = data->conn;
+ struct ldapreqinfo *lr = data->req.p.ldap;
(void)res;
(void)premature;
@@ -431,19 +439,19 @@ static CURLcode ldap_done(struct connectdata *conn, CURLcode res,
ldap_abandon_ext(li->ld, lr->msgid, NULL, NULL);
lr->msgid = 0;
}
- conn->data->req.protop = NULL;
+ data->req.p.ldap = NULL;
free(lr);
}
return CURLE_OK;
}
-static ssize_t ldap_recv(struct connectdata *conn, int sockindex, char *buf,
+static ssize_t ldap_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 Curl_easy *data = conn->data;
- struct ldapreqinfo *lr = data->req.protop;
+ struct ldapreqinfo *lr = data->req.p.ldap;
int rc, ret;
LDAPMessage *msg = NULL;
LDAPMessage *ent;
@@ -510,20 +518,20 @@ static ssize_t ldap_recv(struct connectdata *conn, int sockindex, char *buf,
*err = CURLE_RECV_ERROR;
return -1;
}
- writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"DN: ", 4);
+ writeerr = Curl_client_write(data, CLIENTWRITE_BODY, (char *)"DN: ", 4);
if(writeerr) {
*err = writeerr;
return -1;
}
- writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)bv.bv_val,
+ writeerr = Curl_client_write(data, CLIENTWRITE_BODY, (char *)bv.bv_val,
bv.bv_len);
if(writeerr) {
*err = writeerr;
return -1;
}
- writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 1);
+ writeerr = Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\n", 1);
if(writeerr) {
*err = writeerr;
return -1;
@@ -544,18 +552,18 @@ static ssize_t ldap_recv(struct connectdata *conn, int sockindex, char *buf,
binary = 0;
if(bvals == NULL) {
- writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\t", 1);
+ writeerr = Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\t", 1);
if(writeerr) {
*err = writeerr;
return -1;
}
- writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)bv.bv_val,
+ writeerr = Curl_client_write(data, CLIENTWRITE_BODY, (char *)bv.bv_val,
bv.bv_len);
if(writeerr) {
*err = writeerr;
return -1;
}
- writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)":\n", 2);
+ writeerr = Curl_client_write(data, CLIENTWRITE_BODY, (char *)":\n", 2);
if(writeerr) {
*err = writeerr;
return -1;
@@ -566,20 +574,20 @@ static ssize_t ldap_recv(struct connectdata *conn, int sockindex, char *buf,
for(i = 0; bvals[i].bv_val != NULL; i++) {
int binval = 0;
- writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\t", 1);
+ writeerr = Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\t", 1);
if(writeerr) {
*err = writeerr;
return -1;
}
- writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)bv.bv_val,
+ writeerr = Curl_client_write(data, CLIENTWRITE_BODY, (char *)bv.bv_val,
bv.bv_len);
if(writeerr) {
*err = writeerr;
return -1;
}
- writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)":", 1);
+ writeerr = Curl_client_write(data, CLIENTWRITE_BODY, (char *)":", 1);
if(writeerr) {
*err = writeerr;
return -1;
@@ -617,7 +625,7 @@ static ssize_t ldap_recv(struct connectdata *conn, int sockindex, char *buf,
*err = error;
return -1;
}
- writeerr = Curl_client_write(conn, CLIENTWRITE_BODY,
+ writeerr = Curl_client_write(data, CLIENTWRITE_BODY,
(char *)": ", 2);
if(writeerr) {
*err = writeerr;
@@ -626,7 +634,7 @@ static ssize_t ldap_recv(struct connectdata *conn, int sockindex, char *buf,
data->req.bytecount += 2;
if(val_b64_sz > 0) {
- writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, val_b64,
+ writeerr = Curl_client_write(data, CLIENTWRITE_BODY, val_b64,
val_b64_sz);
if(writeerr) {
*err = writeerr;
@@ -637,13 +645,13 @@ static ssize_t ldap_recv(struct connectdata *conn, int sockindex, char *buf,
}
}
else {
- writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)" ", 1);
+ writeerr = Curl_client_write(data, CLIENTWRITE_BODY, (char *)" ", 1);
if(writeerr) {
*err = writeerr;
return -1;
}
- writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, bvals[i].bv_val,
+ writeerr = Curl_client_write(data, CLIENTWRITE_BODY, bvals[i].bv_val,
bvals[i].bv_len);
if(writeerr) {
*err = writeerr;
@@ -652,7 +660,7 @@ static ssize_t ldap_recv(struct connectdata *conn, int sockindex, char *buf,
data->req.bytecount += bvals[i].bv_len + 1;
}
- writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 0);
+ writeerr = Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\n", 0);
if(writeerr) {
*err = writeerr;
return -1;
@@ -661,14 +669,14 @@ static ssize_t ldap_recv(struct connectdata *conn, int sockindex, char *buf,
data->req.bytecount++;
}
ber_memfree(bvals);
- writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 0);
+ writeerr = Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\n", 0);
if(writeerr) {
*err = writeerr;
return -1;
}
data->req.bytecount++;
}
- writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 0);
+ writeerr = Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\n", 0);
if(writeerr) {
*err = writeerr;
return -1;
@@ -722,7 +730,7 @@ ldapsb_tls_read(Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len)
ber_slen_t ret;
CURLcode err = CURLE_RECV_ERROR;
- ret = (li->recv)(conn, FIRSTSOCKET, buf, len, &err);
+ ret = (li->recv)(conn->data, FIRSTSOCKET, buf, len, &err);
if(ret < 0 && err == CURLE_AGAIN) {
SET_SOCKERRNO(EWOULDBLOCK);
}
@@ -737,7 +745,7 @@ ldapsb_tls_write(Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len)
ber_slen_t ret;
CURLcode err = CURLE_SEND_ERROR;
- ret = (li->send)(conn, FIRSTSOCKET, buf, len, &err);
+ ret = (li->send)(conn->data, FIRSTSOCKET, buf, len, &err);
if(ret < 0 && err == CURLE_AGAIN) {
SET_SOCKERRNO(EWOULDBLOCK);
}
diff --git a/Utilities/cmcurl/lib/parsedate.c b/Utilities/cmcurl/lib/parsedate.c
index 4c7a40c4c..3c38f2c4c 100644
--- a/Utilities/cmcurl/lib/parsedate.c
+++ b/Utilities/cmcurl/lib/parsedate.c
@@ -9,7 +9,7 @@
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -275,48 +275,21 @@ enum assume {
DATE_TIME
};
-/* this is a clone of 'struct tm' but with all fields we don't need or use
- cut out */
-struct my_tm {
- int tm_sec;
- int tm_min;
- int tm_hour;
- int tm_mday;
- int tm_mon;
- int tm_year; /* full year */
-};
-
-/* struct tm to time since epoch in GMT time zone.
- * This is similar to the standard mktime function but for GMT only, and
- * doesn't suffer from the various bugs and portability problems that
- * some systems' implementations have.
- *
- * Returns 0 on success, otherwise non-zero.
+/*
+ * time2epoch: time stamp to seconds since epoch in GMT time zone. Similar to
+ * mktime but for GMT only.
*/
-static void my_timegm(struct my_tm *tm, time_t *t)
+static time_t time2epoch(int sec, int min, int hour,
+ int mday, int mon, int year)
{
static const int month_days_cumulative [12] =
{ 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
- int month, year, leap_days;
-
- year = tm->tm_year;
- month = tm->tm_mon;
- if(month < 0) {
- year += (11 - month) / 12;
- month = 11 - (11 - month) % 12;
- }
- else if(month >= 12) {
- year -= month / 12;
- month = month % 12;
- }
-
- leap_days = year - (tm->tm_mon <= 1);
+ int leap_days = year - (mon <= 1);
leap_days = ((leap_days / 4) - (leap_days / 100) + (leap_days / 400)
- (1969 / 4) + (1969 / 100) - (1969 / 400));
-
- *t = ((((time_t) (year - 1970) * 365
- + leap_days + month_days_cumulative[month] + tm->tm_mday - 1) * 24
- + tm->tm_hour) * 60 + tm->tm_min) * 60 + tm->tm_sec;
+ return ((((time_t) (year - 1970) * 365
+ + leap_days + month_days_cumulative[mon] + mday - 1) * 24
+ + hour) * 60 + min) * 60 + sec;
}
/*
@@ -341,7 +314,6 @@ static int parsedate(const char *date, time_t *output)
int secnum = -1;
int yearnum = -1;
int tzoff = -1;
- struct my_tm tm;
enum assume dignext = DATE_MDAY;
const char *indate = date; /* save the original pointer */
int part = 0; /* max 6 parts */
@@ -533,18 +505,11 @@ static int parsedate(const char *date, time_t *output)
(hournum > 23) || (minnum > 59) || (secnum > 60))
return PARSEDATE_FAIL; /* clearly an illegal date */
- tm.tm_sec = secnum;
- tm.tm_min = minnum;
- tm.tm_hour = hournum;
- tm.tm_mday = mdaynum;
- tm.tm_mon = monnum;
- tm.tm_year = yearnum;
-
- /* my_timegm() returns a time_t. time_t is often 32 bits, sometimes even on
+ /* time2epoch() returns a time_t. time_t is often 32 bits, sometimes even on
architectures that feature 64 bit 'long' but ultimately time_t is the
correct data type to use.
*/
- my_timegm(&tm, &t);
+ t = time2epoch(secnum, minnum, hournum, mdaynum, monnum, yearnum);
/* Add the time zone diff between local time zone and GMT. */
if(tzoff == -1)
diff --git a/Utilities/cmcurl/lib/parsedate.h b/Utilities/cmcurl/lib/parsedate.h
index 8c7ae94e4..a99faf9e3 100644
--- a/Utilities/cmcurl/lib/parsedate.h
+++ b/Utilities/cmcurl/lib/parsedate.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
diff --git a/Utilities/cmcurl/lib/pingpong.c b/Utilities/cmcurl/lib/pingpong.c
index 314331521..481173995 100644
--- a/Utilities/cmcurl/lib/pingpong.c
+++ b/Utilities/cmcurl/lib/pingpong.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -44,10 +44,10 @@
/* Returns timeout in ms. 0 or negative number means the timeout has already
triggered */
-timediff_t Curl_pp_state_timeout(struct pingpong *pp, bool disconnecting)
+timediff_t Curl_pp_state_timeout(struct Curl_easy *data,
+ struct pingpong *pp, bool disconnecting)
{
- struct connectdata *conn = pp->conn;
- struct Curl_easy *data = conn->data;
+ struct connectdata *conn = data->conn;
timediff_t timeout_ms; /* in milliseconds */
timediff_t response_time = (data->set.server_response_timeout)?
data->set.server_response_timeout: pp->response_time;
@@ -77,15 +77,15 @@ timediff_t Curl_pp_state_timeout(struct pingpong *pp, bool disconnecting)
/*
* Curl_pp_statemach()
*/
-CURLcode Curl_pp_statemach(struct pingpong *pp, bool block,
+CURLcode Curl_pp_statemach(struct Curl_easy *data,
+ struct pingpong *pp, bool block,
bool disconnecting)
{
- struct connectdata *conn = pp->conn;
+ struct connectdata *conn = data->conn;
curl_socket_t sock = conn->sock[FIRSTSOCKET];
int rc;
timediff_t interval_ms;
- timediff_t timeout_ms = Curl_pp_state_timeout(pp, disconnecting);
- struct Curl_easy *data = conn->data;
+ timediff_t timeout_ms = Curl_pp_state_timeout(data, pp, disconnecting);
CURLcode result = CURLE_OK;
if(timeout_ms <= 0) {
@@ -117,7 +117,7 @@ CURLcode Curl_pp_statemach(struct pingpong *pp, bool block,
if(block) {
/* if we didn't wait, we don't have to spend time on this now */
- if(Curl_pgrsUpdate(conn))
+ if(Curl_pgrsUpdate(data))
result = CURLE_ABORTED_BY_CALLBACK;
else
result = Curl_speedcheck(data, Curl_now());
@@ -131,22 +131,26 @@ CURLcode Curl_pp_statemach(struct pingpong *pp, bool block,
result = CURLE_OUT_OF_MEMORY;
}
else if(rc)
- result = pp->statemach_act(conn);
+ result = pp->statemachine(data, data->conn);
return result;
}
/* initialize stuff to prepare for reading a fresh new response */
-void Curl_pp_init(struct pingpong *pp)
+void Curl_pp_init(struct Curl_easy *data, struct pingpong *pp)
{
- struct connectdata *conn = pp->conn;
+ DEBUGASSERT(data);
pp->nread_resp = 0;
- pp->linestart_resp = conn->data->state.buffer;
+ pp->linestart_resp = data->state.buffer;
pp->pending_resp = TRUE;
pp->response = Curl_now(); /* start response time-out now! */
}
-
+/* setup for the coming transfer */
+void Curl_pp_setup(struct pingpong *pp)
+{
+ Curl_dyn_init(&pp->sendbuf, DYN_PINGPPONG_CMD);
+}
/***********************************************************************
*
@@ -158,17 +162,16 @@ void Curl_pp_init(struct pingpong *pp)
*
* made to never block
*/
-CURLcode Curl_pp_vsendf(struct pingpong *pp,
+CURLcode Curl_pp_vsendf(struct Curl_easy *data,
+ struct pingpong *pp,
const char *fmt,
va_list args)
{
- ssize_t bytes_written;
+ ssize_t bytes_written = 0;
size_t write_len;
- char *fmt_crlf;
char *s;
CURLcode result;
- struct connectdata *conn = pp->conn;
- struct Curl_easy *data;
+ struct connectdata *conn = data->conn;
#ifdef HAVE_GSSAPI
enum protection_level data_sec;
@@ -182,47 +185,39 @@ CURLcode Curl_pp_vsendf(struct pingpong *pp,
/* can't send without a connection! */
return CURLE_SEND_ERROR;
- data = conn->data;
-
- fmt_crlf = aprintf("%s\r\n", fmt); /* append a trailing CRLF */
- if(!fmt_crlf)
- return CURLE_OUT_OF_MEMORY;
-
- s = vaprintf(fmt_crlf, args); /* trailing CRLF appended */
- free(fmt_crlf);
- if(!s)
- return CURLE_OUT_OF_MEMORY;
+ Curl_dyn_reset(&pp->sendbuf);
+ result = Curl_dyn_vaddf(&pp->sendbuf, fmt, args);
+ if(result)
+ return result;
- bytes_written = 0;
- write_len = strlen(s);
+ /* append CRLF */
+ result = Curl_dyn_addn(&pp->sendbuf, "\r\n", 2);
+ if(result)
+ return result;
- Curl_pp_init(pp);
+ write_len = Curl_dyn_len(&pp->sendbuf);
+ s = Curl_dyn_ptr(&pp->sendbuf);
+ Curl_pp_init(data, pp);
result = Curl_convert_to_network(data, s, write_len);
/* Curl_convert_to_network calls failf if unsuccessful */
- if(result) {
- free(s);
+ if(result)
return result;
- }
#ifdef HAVE_GSSAPI
conn->data_prot = PROT_CMD;
#endif
- result = Curl_write(conn, conn->sock[FIRSTSOCKET], s, write_len,
- &bytes_written);
+ result = Curl_write(data, conn->sock[FIRSTSOCKET], s, write_len,
+ &bytes_written);
+ if(result)
+ return result;
#ifdef HAVE_GSSAPI
data_sec = conn->data_prot;
DEBUGASSERT(data_sec > PROT_NONE && data_sec < PROT_LAST);
conn->data_prot = data_sec;
#endif
- if(result) {
- free(s);
- return result;
- }
-
- if(conn->data->set.verbose)
- Curl_debug(conn->data, CURLINFO_HEADER_OUT, s, (size_t)bytes_written);
+ Curl_debug(data, CURLINFO_HEADER_OUT, s, (size_t)bytes_written);
if(bytes_written != (ssize_t)write_len) {
/* the whole chunk was not sent, keep it around and adjust sizes */
@@ -231,7 +226,6 @@ CURLcode Curl_pp_vsendf(struct pingpong *pp,
pp->sendleft = write_len - bytes_written;
}
else {
- free(s);
pp->sendthis = NULL;
pp->sendleft = pp->sendsize = 0;
pp->response = Curl_now();
@@ -251,14 +245,14 @@ CURLcode Curl_pp_vsendf(struct pingpong *pp,
*
* made to never block
*/
-CURLcode Curl_pp_sendf(struct pingpong *pp,
+CURLcode Curl_pp_sendf(struct Curl_easy *data, struct pingpong *pp,
const char *fmt, ...)
{
CURLcode result;
va_list ap;
va_start(ap, fmt);
- result = Curl_pp_vsendf(pp, fmt, ap);
+ result = Curl_pp_vsendf(data, pp, fmt, ap);
va_end(ap);
@@ -270,7 +264,8 @@ CURLcode Curl_pp_sendf(struct pingpong *pp,
*
* Reads a piece of a server response.
*/
-CURLcode Curl_pp_readresp(curl_socket_t sockfd,
+CURLcode Curl_pp_readresp(struct Curl_easy *data,
+ curl_socket_t sockfd,
struct pingpong *pp,
int *code, /* return the server code if done */
size_t *size) /* size of the response */
@@ -279,8 +274,7 @@ CURLcode Curl_pp_readresp(curl_socket_t sockfd,
bool keepon = TRUE;
ssize_t gotbytes;
char *ptr;
- struct connectdata *conn = pp->conn;
- struct Curl_easy *data = conn->data;
+ struct connectdata *conn = data->conn;
char * const buf = data->state.buffer;
CURLcode result = CURLE_OK;
@@ -320,7 +314,7 @@ CURLcode Curl_pp_readresp(curl_socket_t sockfd,
#endif
DEBUGASSERT((ptr + data->set.buffer_size - pp->nread_resp) <=
(buf + data->set.buffer_size + 1));
- result = Curl_read(conn, sockfd, ptr,
+ result = Curl_read(data, sockfd, ptr,
data->set.buffer_size - pp->nread_resp,
&gotbytes);
#ifdef HAVE_GSSAPI
@@ -368,21 +362,20 @@ CURLcode Curl_pp_readresp(curl_socket_t sockfd,
#ifdef HAVE_GSSAPI
if(!conn->sec_complete)
#endif
- if(data->set.verbose)
- Curl_debug(data, CURLINFO_HEADER_IN,
- pp->linestart_resp, (size_t)perline);
+ Curl_debug(data, CURLINFO_HEADER_IN,
+ pp->linestart_resp, (size_t)perline);
/*
* We pass all response-lines to the callback function registered
* for "headers". The response lines can be seen as a kind of
* headers.
*/
- result = Curl_client_write(conn, CLIENTWRITE_HEADER,
+ result = Curl_client_write(data, CLIENTWRITE_HEADER,
pp->linestart_resp, perline);
if(result)
return result;
- if(pp->endofresp(conn, pp->linestart_resp, perline, code)) {
+ if(pp->endofresp(data, conn, pp->linestart_resp, perline, code)) {
/* This is the end of the last line, copy the last line to the
start of the buffer and null-terminate, for old times sake */
size_t n = ptr - pp->linestart_resp;
@@ -462,10 +455,10 @@ CURLcode Curl_pp_readresp(curl_socket_t sockfd,
return result;
}
-int Curl_pp_getsock(struct pingpong *pp,
- curl_socket_t *socks)
+int Curl_pp_getsock(struct Curl_easy *data,
+ struct pingpong *pp, curl_socket_t *socks)
{
- struct connectdata *conn = pp->conn;
+ struct connectdata *conn = data->conn;
socks[0] = conn->sock[FIRSTSOCKET];
if(pp->sendleft) {
@@ -477,13 +470,14 @@ int Curl_pp_getsock(struct pingpong *pp,
return GETSOCK_READSOCK(0);
}
-CURLcode Curl_pp_flushsend(struct pingpong *pp)
+CURLcode Curl_pp_flushsend(struct Curl_easy *data,
+ struct pingpong *pp)
{
/* we have a piece of a command still left to send */
- struct connectdata *conn = pp->conn;
+ struct connectdata *conn = data->conn;
ssize_t written;
curl_socket_t sock = conn->sock[FIRSTSOCKET];
- CURLcode result = Curl_write(conn, sock, pp->sendthis + pp->sendsize -
+ CURLcode result = Curl_write(data, sock, pp->sendthis + pp->sendsize -
pp->sendleft, pp->sendleft, &written);
if(result)
return result;
@@ -493,7 +487,6 @@ CURLcode Curl_pp_flushsend(struct pingpong *pp)
pp->sendleft -= written;
}
else {
- free(pp->sendthis);
pp->sendthis = NULL;
pp->sendleft = pp->sendsize = 0;
pp->response = Curl_now();
@@ -503,15 +496,15 @@ CURLcode Curl_pp_flushsend(struct pingpong *pp)
CURLcode Curl_pp_disconnect(struct pingpong *pp)
{
- free(pp->cache);
- pp->cache = NULL;
+ Curl_dyn_free(&pp->sendbuf);
+ Curl_safefree(pp->cache);
return CURLE_OK;
}
bool Curl_pp_moredata(struct pingpong *pp)
{
return (!pp->sendleft && pp->cache && pp->nread_resp < pp->cache_size) ?
- TRUE : FALSE;
+ TRUE : FALSE;
}
#endif
diff --git a/Utilities/cmcurl/lib/pingpong.h b/Utilities/cmcurl/lib/pingpong.h
index e874799d4..4f7d7ea6b 100644
--- a/Utilities/cmcurl/lib/pingpong.h
+++ b/Utilities/cmcurl/lib/pingpong.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -62,33 +62,42 @@ struct pingpong {
off, used to time-out response reading */
timediff_t response_time; /* When no timeout is given, this is the amount of
milliseconds we await for a server response. */
- struct connectdata *conn; /* points to the connectdata struct that this
- belongs to */
+ struct dynbuf sendbuf;
/* Function pointers the protocols MUST implement and provide for the
pingpong layer to function */
- CURLcode (*statemach_act)(struct connectdata *conn);
-
- bool (*endofresp)(struct connectdata *conn, char *ptr, size_t len,
- int *code);
+ CURLcode (*statemachine)(struct Curl_easy *data, struct connectdata *conn);
+ bool (*endofresp)(struct Curl_easy *data, struct connectdata *conn,
+ char *ptr, size_t len, int *code);
};
+#define PINGPONG_SETUP(pp,s,e) \
+ do { \
+ pp->response_time = RESP_TIMEOUT; \
+ pp->statemachine = s; \
+ pp->endofresp = e; \
+ } while(0)
+
/*
* Curl_pp_statemach()
*
* called repeatedly until done. Set 'wait' to make it wait a while on the
* socket if there's no traffic.
*/
-CURLcode Curl_pp_statemach(struct pingpong *pp, bool block,
- bool disconnecting);
+CURLcode Curl_pp_statemach(struct Curl_easy *data, struct pingpong *pp,
+ bool block, bool disconnecting);
/* initialize stuff to prepare for reading a fresh new response */
-void Curl_pp_init(struct pingpong *pp);
+void Curl_pp_init(struct Curl_easy *data, struct pingpong *pp);
+
+/* setup for the transfer */
+void Curl_pp_setup(struct pingpong *pp);
/* Returns timeout in ms. 0 or negative number means the timeout has already
triggered */
-timediff_t Curl_pp_state_timeout(struct pingpong *pp, bool disconnecting);
+timediff_t Curl_pp_state_timeout(struct Curl_easy *data,
+ struct pingpong *pp, bool disconnecting);
/***********************************************************************
@@ -101,7 +110,8 @@ timediff_t Curl_pp_state_timeout(struct pingpong *pp, bool disconnecting);
*
* made to never block
*/
-CURLcode Curl_pp_sendf(struct pingpong *pp,
+CURLcode Curl_pp_sendf(struct Curl_easy *data,
+ struct pingpong *pp,
const char *fmt, ...);
/***********************************************************************
@@ -114,7 +124,8 @@ CURLcode Curl_pp_sendf(struct pingpong *pp,
*
* made to never block
*/
-CURLcode Curl_pp_vsendf(struct pingpong *pp,
+CURLcode Curl_pp_vsendf(struct Curl_easy *data,
+ struct pingpong *pp,
const char *fmt,
va_list args);
@@ -123,18 +134,21 @@ CURLcode Curl_pp_vsendf(struct pingpong *pp,
*
* Reads a piece of a server response.
*/
-CURLcode Curl_pp_readresp(curl_socket_t sockfd,
+CURLcode Curl_pp_readresp(struct Curl_easy *data,
+ curl_socket_t sockfd,
struct pingpong *pp,
int *code, /* return the server code if done */
size_t *size); /* size of the response */
-CURLcode Curl_pp_flushsend(struct pingpong *pp);
+CURLcode Curl_pp_flushsend(struct Curl_easy *data,
+ struct pingpong *pp);
/* call this when a pingpong connection is disconnected */
CURLcode Curl_pp_disconnect(struct pingpong *pp);
-int Curl_pp_getsock(struct pingpong *pp, curl_socket_t *socks);
+int Curl_pp_getsock(struct Curl_easy *data, struct pingpong *pp,
+ curl_socket_t *socks);
/***********************************************************************
diff --git a/Utilities/cmcurl/lib/pop3.c b/Utilities/cmcurl/lib/pop3.c
index 9ff5c78fd..0ed3d3ee1 100644
--- a/Utilities/cmcurl/lib/pop3.c
+++ b/Utilities/cmcurl/lib/pop3.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -88,22 +88,27 @@
#include "memdebug.h"
/* Local API functions */
-static CURLcode pop3_regular_transfer(struct connectdata *conn, bool *done);
-static CURLcode pop3_do(struct connectdata *conn, bool *done);
-static CURLcode pop3_done(struct connectdata *conn, CURLcode status,
+static CURLcode pop3_regular_transfer(struct Curl_easy *data, bool *done);
+static CURLcode pop3_do(struct Curl_easy *data, bool *done);
+static CURLcode pop3_done(struct Curl_easy *data, CURLcode status,
bool premature);
-static CURLcode pop3_connect(struct connectdata *conn, bool *done);
-static CURLcode pop3_disconnect(struct connectdata *conn, bool dead);
-static CURLcode pop3_multi_statemach(struct connectdata *conn, bool *done);
-static int pop3_getsock(struct connectdata *conn, curl_socket_t *socks);
-static CURLcode pop3_doing(struct connectdata *conn, bool *dophase_done);
-static CURLcode pop3_setup_connection(struct connectdata *conn);
+static CURLcode pop3_connect(struct Curl_easy *data, bool *done);
+static CURLcode pop3_disconnect(struct Curl_easy *data,
+ struct connectdata *conn, bool dead);
+static CURLcode pop3_multi_statemach(struct Curl_easy *data, bool *done);
+static int pop3_getsock(struct Curl_easy *data,
+ struct connectdata *conn, curl_socket_t *socks);
+static CURLcode pop3_doing(struct Curl_easy *data, bool *dophase_done);
+static CURLcode pop3_setup_connection(struct Curl_easy *data,
+ struct connectdata *conn);
static CURLcode pop3_parse_url_options(struct connectdata *conn);
-static CURLcode pop3_parse_url_path(struct connectdata *conn);
-static CURLcode pop3_parse_custom_request(struct connectdata *conn);
-static CURLcode pop3_perform_auth(struct connectdata *conn, const char *mech,
+static CURLcode pop3_parse_url_path(struct Curl_easy *data);
+static CURLcode pop3_parse_custom_request(struct Curl_easy *data);
+static CURLcode pop3_perform_auth(struct Curl_easy *data,
+ struct connectdata *conn, const char *mech,
const char *initresp);
-static CURLcode pop3_continue_auth(struct connectdata *conn, const char *resp);
+static CURLcode pop3_continue_auth(struct Curl_easy *data,
+ struct connectdata *conn, const char *resp);
static void pop3_get_message(char *buffer, char **outptr);
/*
@@ -128,6 +133,7 @@ const struct Curl_handler Curl_handler_pop3 = {
ZERO_NULL, /* connection_check */
PORT_POP3, /* defport */
CURLPROTO_POP3, /* protocol */
+ CURLPROTO_POP3, /* family */
PROTOPT_CLOSEACTION | PROTOPT_NOURLQUERY | /* flags */
PROTOPT_URLOPTIONS
};
@@ -155,6 +161,7 @@ const struct Curl_handler Curl_handler_pop3s = {
ZERO_NULL, /* connection_check */
PORT_POP3S, /* defport */
CURLPROTO_POP3S, /* protocol */
+ CURLPROTO_POP3, /* family */
PROTOPT_CLOSEACTION | PROTOPT_SSL
| PROTOPT_NOURLQUERY | PROTOPT_URLOPTIONS /* flags */
};
@@ -193,10 +200,11 @@ static void pop3_to_pop3s(struct connectdata *conn)
* capabilities from the CAPA response including the supported authentication
* types and allowed SASL mechanisms.
*/
-static bool pop3_endofresp(struct connectdata *conn, char *line, size_t len,
- int *resp)
+static bool pop3_endofresp(struct Curl_easy *data, struct connectdata *conn,
+ char *line, size_t len, int *resp)
{
struct pop3_conn *pop3c = &conn->proto.pop3c;
+ (void)data;
/* Do we have an error response? */
if(len >= 4 && !memcmp("-ERR", line, 4)) {
@@ -277,9 +285,9 @@ static void pop3_get_message(char *buffer, char **outptr)
*
* This is the ONLY way to change POP3 state!
*/
-static void state(struct connectdata *conn, pop3state newstate)
+static void state(struct Curl_easy *data, pop3state newstate)
{
- struct pop3_conn *pop3c = &conn->proto.pop3c;
+ struct pop3_conn *pop3c = &data->conn->proto.pop3c;
#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
/* for debug purposes */
static const char * const names[] = {
@@ -298,7 +306,7 @@ static void state(struct connectdata *conn, pop3state newstate)
};
if(pop3c->state != newstate)
- infof(conn->data, "POP3 %p state change from %s to %s\n",
+ infof(data, "POP3 %p state change from %s to %s\n",
(void *)pop3c, names[pop3c->state], names[newstate]);
#endif
@@ -312,7 +320,8 @@ static void state(struct connectdata *conn, pop3state newstate)
* Sends the CAPA command in order to obtain a list of server side supported
* capabilities.
*/
-static CURLcode pop3_perform_capa(struct connectdata *conn)
+static CURLcode pop3_perform_capa(struct Curl_easy *data,
+ struct connectdata *conn)
{
CURLcode result = CURLE_OK;
struct pop3_conn *pop3c = &conn->proto.pop3c;
@@ -322,10 +331,10 @@ static CURLcode pop3_perform_capa(struct connectdata *conn)
pop3c->tls_supported = FALSE; /* Clear the TLS capability */
/* Send the CAPA command */
- result = Curl_pp_sendf(&pop3c->pp, "%s", "CAPA");
+ result = Curl_pp_sendf(data, &pop3c->pp, "%s", "CAPA");
if(!result)
- state(conn, POP3_CAPA);
+ state(data, POP3_CAPA);
return result;
}
@@ -336,13 +345,14 @@ static CURLcode pop3_perform_capa(struct connectdata *conn)
*
* Sends the STLS command to start the upgrade to TLS.
*/
-static CURLcode pop3_perform_starttls(struct connectdata *conn)
+static CURLcode pop3_perform_starttls(struct Curl_easy *data,
+ struct connectdata *conn)
{
/* Send the STLS command */
- CURLcode result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s", "STLS");
+ CURLcode result = Curl_pp_sendf(data, &conn->proto.pop3c.pp, "%s", "STLS");
if(!result)
- state(conn, POP3_STARTTLS);
+ state(data, POP3_STARTTLS);
return result;
}
@@ -353,20 +363,21 @@ static CURLcode pop3_perform_starttls(struct connectdata *conn)
*
* Performs the upgrade to TLS.
*/
-static CURLcode pop3_perform_upgrade_tls(struct connectdata *conn)
+static CURLcode pop3_perform_upgrade_tls(struct Curl_easy *data,
+ struct connectdata *conn)
{
/* Start the SSL connection */
struct pop3_conn *pop3c = &conn->proto.pop3c;
- CURLcode result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET,
+ CURLcode result = Curl_ssl_connect_nonblocking(data, conn, FIRSTSOCKET,
&pop3c->ssldone);
if(!result) {
if(pop3c->state != POP3_UPGRADETLS)
- state(conn, POP3_UPGRADETLS);
+ state(data, POP3_UPGRADETLS);
if(pop3c->ssldone) {
pop3_to_pop3s(conn);
- result = pop3_perform_capa(conn);
+ result = pop3_perform_capa(data, conn);
}
}
@@ -379,23 +390,24 @@ static CURLcode pop3_perform_upgrade_tls(struct connectdata *conn)
*
* Sends a clear text USER command to authenticate with.
*/
-static CURLcode pop3_perform_user(struct connectdata *conn)
+static CURLcode pop3_perform_user(struct Curl_easy *data,
+ struct connectdata *conn)
{
CURLcode result = CURLE_OK;
/* Check we have a username and password to authenticate with and end the
connect phase if we don't */
if(!conn->bits.user_passwd) {
- state(conn, POP3_STOP);
+ state(data, POP3_STOP);
return result;
}
/* Send the USER command */
- result = Curl_pp_sendf(&conn->proto.pop3c.pp, "USER %s",
+ result = Curl_pp_sendf(data, &conn->proto.pop3c.pp, "USER %s",
conn->user ? conn->user : "");
if(!result)
- state(conn, POP3_USER);
+ state(data, POP3_USER);
return result;
}
@@ -407,7 +419,8 @@ static CURLcode pop3_perform_user(struct connectdata *conn)
*
* Sends an APOP command to authenticate with.
*/
-static CURLcode pop3_perform_apop(struct connectdata *conn)
+static CURLcode pop3_perform_apop(struct Curl_easy *data,
+ struct connectdata *conn)
{
CURLcode result = CURLE_OK;
struct pop3_conn *pop3c = &conn->proto.pop3c;
@@ -419,7 +432,7 @@ static CURLcode pop3_perform_apop(struct connectdata *conn)
/* Check we have a username and password to authenticate with and end the
connect phase if we don't */
if(!conn->bits.user_passwd) {
- state(conn, POP3_STOP);
+ state(data, POP3_STOP);
return result;
}
@@ -442,10 +455,10 @@ static CURLcode pop3_perform_apop(struct connectdata *conn)
for(i = 0; i < MD5_DIGEST_LEN; i++)
msnprintf(&secret[2 * i], 3, "%02x", digest[i]);
- result = Curl_pp_sendf(&pop3c->pp, "APOP %s %s", conn->user, secret);
+ result = Curl_pp_sendf(data, &pop3c->pp, "APOP %s %s", conn->user, secret);
if(!result)
- state(conn, POP3_APOP);
+ state(data, POP3_APOP);
return result;
}
@@ -458,7 +471,8 @@ static CURLcode pop3_perform_apop(struct connectdata *conn)
* Sends an AUTH command allowing the client to login with the given SASL
* authentication mechanism.
*/
-static CURLcode pop3_perform_auth(struct connectdata *conn,
+static CURLcode pop3_perform_auth(struct Curl_easy *data,
+ struct connectdata *conn,
const char *mech,
const char *initresp)
{
@@ -467,11 +481,11 @@ static CURLcode pop3_perform_auth(struct connectdata *conn,
if(initresp) { /* AUTH <mech> ...<crlf> */
/* Send the AUTH command with the initial response */
- result = Curl_pp_sendf(&pop3c->pp, "AUTH %s %s", mech, initresp);
+ result = Curl_pp_sendf(data, &pop3c->pp, "AUTH %s %s", mech, initresp);
}
else {
/* Send the AUTH command */
- result = Curl_pp_sendf(&pop3c->pp, "AUTH %s", mech);
+ result = Curl_pp_sendf(data, &pop3c->pp, "AUTH %s", mech);
}
return result;
@@ -483,12 +497,13 @@ static CURLcode pop3_perform_auth(struct connectdata *conn,
*
* Sends SASL continuation data or cancellation.
*/
-static CURLcode pop3_continue_auth(struct connectdata *conn,
+static CURLcode pop3_continue_auth(struct Curl_easy *data,
+ struct connectdata *conn,
const char *resp)
{
struct pop3_conn *pop3c = &conn->proto.pop3c;
- return Curl_pp_sendf(&pop3c->pp, "%s", resp);
+ return Curl_pp_sendf(data, &pop3c->pp, "%s", resp);
}
/***********************************************************************
@@ -499,7 +514,8 @@ static CURLcode pop3_continue_auth(struct connectdata *conn,
* authentication mechanism, falling back to APOP and clear text should a
* common mechanism not be available between the client and server.
*/
-static CURLcode pop3_perform_authentication(struct connectdata *conn)
+static CURLcode pop3_perform_authentication(struct Curl_easy *data,
+ struct connectdata *conn)
{
CURLcode result = CURLE_OK;
struct pop3_conn *pop3c = &conn->proto.pop3c;
@@ -508,32 +524,32 @@ static CURLcode pop3_perform_authentication(struct connectdata *conn)
/* Check we have enough data to authenticate with and end the
connect phase if we don't */
if(!Curl_sasl_can_authenticate(&pop3c->sasl, conn)) {
- state(conn, POP3_STOP);
+ state(data, POP3_STOP);
return result;
}
if(pop3c->authtypes & pop3c->preftype & POP3_TYPE_SASL) {
/* Calculate the SASL login details */
- result = Curl_sasl_start(&pop3c->sasl, conn, FALSE, &progress);
+ result = Curl_sasl_start(&pop3c->sasl, data, conn, FALSE, &progress);
if(!result)
if(progress == SASL_INPROGRESS)
- state(conn, POP3_AUTH);
+ state(data, POP3_AUTH);
}
if(!result && progress == SASL_IDLE) {
#ifndef CURL_DISABLE_CRYPTO_AUTH
if(pop3c->authtypes & pop3c->preftype & POP3_TYPE_APOP)
/* Perform APOP authentication */
- result = pop3_perform_apop(conn);
+ result = pop3_perform_apop(data, conn);
else
#endif
if(pop3c->authtypes & pop3c->preftype & POP3_TYPE_CLEARTEXT)
/* Perform clear text authentication */
- result = pop3_perform_user(conn);
+ result = pop3_perform_user(data, conn);
else {
/* Other mechanisms not supported */
- infof(conn->data, "No known authentication mechanisms supported!\n");
+ infof(data, "No known authentication mechanisms supported!\n");
result = CURLE_LOGIN_DENIED;
}
}
@@ -547,15 +563,15 @@ static CURLcode pop3_perform_authentication(struct connectdata *conn)
*
* Sends a POP3 based command.
*/
-static CURLcode pop3_perform_command(struct connectdata *conn)
+static CURLcode pop3_perform_command(struct Curl_easy *data)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
- struct POP3 *pop3 = data->req.protop;
+ struct connectdata *conn = data->conn;
+ struct POP3 *pop3 = data->req.p.pop3;
const char *command = NULL;
/* Calculate the default command */
- if(pop3->id[0] == '\0' || conn->data->set.ftp_list_only) {
+ if(pop3->id[0] == '\0' || data->set.ftp_list_only) {
command = "LIST";
if(pop3->id[0] != '\0')
@@ -567,16 +583,16 @@ static CURLcode pop3_perform_command(struct connectdata *conn)
/* Send the command */
if(pop3->id[0] != '\0')
- result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s %s",
+ result = Curl_pp_sendf(data, &conn->proto.pop3c.pp, "%s %s",
(pop3->custom && pop3->custom[0] != '\0' ?
pop3->custom : command), pop3->id);
else
- result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s",
+ result = Curl_pp_sendf(data, &conn->proto.pop3c.pp, "%s",
(pop3->custom && pop3->custom[0] != '\0' ?
pop3->custom : command));
if(!result)
- state(conn, POP3_COMMAND);
+ state(data, POP3_COMMAND);
return result;
}
@@ -587,24 +603,25 @@ static CURLcode pop3_perform_command(struct connectdata *conn)
*
* Performs the quit action prior to sclose() be called.
*/
-static CURLcode pop3_perform_quit(struct connectdata *conn)
+static CURLcode pop3_perform_quit(struct Curl_easy *data,
+ struct connectdata *conn)
{
/* Send the QUIT command */
- CURLcode result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s", "QUIT");
+ CURLcode result = Curl_pp_sendf(data, &conn->proto.pop3c.pp, "%s", "QUIT");
if(!result)
- state(conn, POP3_QUIT);
+ state(data, POP3_QUIT);
return result;
}
/* For the initial server greeting */
-static CURLcode pop3_state_servergreet_resp(struct connectdata *conn,
+static CURLcode pop3_state_servergreet_resp(struct Curl_easy *data,
int pop3code,
pop3state instate)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
+ struct connectdata *conn = data->conn;
struct pop3_conn *pop3c = &conn->proto.pop3c;
const char *line = data->state.buffer;
size_t len = strlen(line);
@@ -652,18 +669,18 @@ static CURLcode pop3_state_servergreet_resp(struct connectdata *conn,
}
}
- result = pop3_perform_capa(conn);
+ result = pop3_perform_capa(data, conn);
}
return result;
}
/* For CAPA responses */
-static CURLcode pop3_state_capa_resp(struct connectdata *conn, int pop3code,
+static CURLcode pop3_state_capa_resp(struct Curl_easy *data, int pop3code,
pop3state instate)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
+ struct connectdata *conn = data->conn;
struct pop3_conn *pop3c = &conn->proto.pop3c;
const char *line = data->state.buffer;
size_t len = strlen(line);
@@ -726,36 +743,35 @@ static CURLcode pop3_state_capa_resp(struct connectdata *conn, int pop3code,
/* We don't have a SSL/TLS connection yet, but SSL is requested */
if(pop3c->tls_supported)
/* Switch to TLS connection now */
- result = pop3_perform_starttls(conn);
+ result = pop3_perform_starttls(data, conn);
else if(data->set.use_ssl == CURLUSESSL_TRY)
/* Fallback and carry on with authentication */
- result = pop3_perform_authentication(conn);
+ result = pop3_perform_authentication(data, conn);
else {
failf(data, "STLS not supported.");
result = CURLE_USE_SSL_FAILED;
}
}
else
- result = pop3_perform_authentication(conn);
+ result = pop3_perform_authentication(data, conn);
}
else {
/* Clear text is supported when CAPA isn't recognised */
pop3c->authtypes |= POP3_TYPE_CLEARTEXT;
- result = pop3_perform_authentication(conn);
+ result = pop3_perform_authentication(data, conn);
}
return result;
}
/* For STARTTLS responses */
-static CURLcode pop3_state_starttls_resp(struct connectdata *conn,
+static CURLcode pop3_state_starttls_resp(struct Curl_easy *data,
+ struct connectdata *conn,
int pop3code,
pop3state instate)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
-
(void)instate; /* no use for this yet */
if(pop3code != '+') {
@@ -764,42 +780,42 @@ static CURLcode pop3_state_starttls_resp(struct connectdata *conn,
result = CURLE_USE_SSL_FAILED;
}
else
- result = pop3_perform_authentication(conn);
+ result = pop3_perform_authentication(data, conn);
}
else
- result = pop3_perform_upgrade_tls(conn);
+ result = pop3_perform_upgrade_tls(data, conn);
return result;
}
/* For SASL authentication responses */
-static CURLcode pop3_state_auth_resp(struct connectdata *conn,
+static CURLcode pop3_state_auth_resp(struct Curl_easy *data,
int pop3code,
pop3state instate)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
+ struct connectdata *conn = data->conn;
struct pop3_conn *pop3c = &conn->proto.pop3c;
saslprogress progress;
(void)instate; /* no use for this yet */
- result = Curl_sasl_continue(&pop3c->sasl, conn, pop3code, &progress);
+ result = Curl_sasl_continue(&pop3c->sasl, data, conn, pop3code, &progress);
if(!result)
switch(progress) {
case SASL_DONE:
- state(conn, POP3_STOP); /* Authenticated */
+ state(data, POP3_STOP); /* Authenticated */
break;
case SASL_IDLE: /* No mechanism left after cancellation */
#ifndef CURL_DISABLE_CRYPTO_AUTH
if(pop3c->authtypes & pop3c->preftype & POP3_TYPE_APOP)
/* Perform APOP authentication */
- result = pop3_perform_apop(conn);
+ result = pop3_perform_apop(data, conn);
else
#endif
if(pop3c->authtypes & pop3c->preftype & POP3_TYPE_CLEARTEXT)
/* Perform clear text authentication */
- result = pop3_perform_user(conn);
+ result = pop3_perform_user(data, conn);
else {
failf(data, "Authentication cancelled");
result = CURLE_LOGIN_DENIED;
@@ -814,12 +830,10 @@ static CURLcode pop3_state_auth_resp(struct connectdata *conn,
#ifndef CURL_DISABLE_CRYPTO_AUTH
/* For APOP responses */
-static CURLcode pop3_state_apop_resp(struct connectdata *conn, int pop3code,
+static CURLcode pop3_state_apop_resp(struct Curl_easy *data, int pop3code,
pop3state instate)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
-
(void)instate; /* no use for this yet */
if(pop3code != '+') {
@@ -828,19 +842,18 @@ static CURLcode pop3_state_apop_resp(struct connectdata *conn, int pop3code,
}
else
/* End of connect phase */
- state(conn, POP3_STOP);
+ state(data, POP3_STOP);
return result;
}
#endif
/* For USER responses */
-static CURLcode pop3_state_user_resp(struct connectdata *conn, int pop3code,
+static CURLcode pop3_state_user_resp(struct Curl_easy *data, int pop3code,
pop3state instate)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
-
+ struct connectdata *conn = data->conn;
(void)instate; /* no use for this yet */
if(pop3code != '+') {
@@ -849,21 +862,19 @@ static CURLcode pop3_state_user_resp(struct connectdata *conn, int pop3code,
}
else
/* Send the PASS command */
- result = Curl_pp_sendf(&conn->proto.pop3c.pp, "PASS %s",
+ result = Curl_pp_sendf(data, &conn->proto.pop3c.pp, "PASS %s",
conn->passwd ? conn->passwd : "");
if(!result)
- state(conn, POP3_PASS);
+ state(data, POP3_PASS);
return result;
}
/* For PASS responses */
-static CURLcode pop3_state_pass_resp(struct connectdata *conn, int pop3code,
+static CURLcode pop3_state_pass_resp(struct Curl_easy *data, int pop3code,
pop3state instate)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
-
(void)instate; /* no use for this yet */
if(pop3code != '+') {
@@ -872,26 +883,26 @@ static CURLcode pop3_state_pass_resp(struct connectdata *conn, int pop3code,
}
else
/* End of connect phase */
- state(conn, POP3_STOP);
+ state(data, POP3_STOP);
return result;
}
/* For command responses */
-static CURLcode pop3_state_command_resp(struct connectdata *conn,
+static CURLcode pop3_state_command_resp(struct Curl_easy *data,
int pop3code,
pop3state instate)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
- struct POP3 *pop3 = data->req.protop;
+ struct connectdata *conn = data->conn;
+ struct POP3 *pop3 = data->req.p.pop3;
struct pop3_conn *pop3c = &conn->proto.pop3c;
struct pingpong *pp = &pop3c->pp;
(void)instate; /* no use for this yet */
if(pop3code != '+') {
- state(conn, POP3_STOP);
+ state(data, POP3_STOP);
return CURLE_RECV_ERROR;
}
@@ -915,7 +926,7 @@ static CURLcode pop3_state_command_resp(struct connectdata *conn,
"headers" after the body */
if(!data->set.opt_no_body) {
- result = Curl_pop3_write(conn, pp->cache, pp->cache_size);
+ result = Curl_pop3_write(data, pp->cache, pp->cache_size);
if(result)
return result;
}
@@ -929,12 +940,13 @@ static CURLcode pop3_state_command_resp(struct connectdata *conn,
}
/* End of DO phase */
- state(conn, POP3_STOP);
+ state(data, POP3_STOP);
return result;
}
-static CURLcode pop3_statemach_act(struct connectdata *conn)
+static CURLcode pop3_statemachine(struct Curl_easy *data,
+ struct connectdata *conn)
{
CURLcode result = CURLE_OK;
curl_socket_t sock = conn->sock[FIRSTSOCKET];
@@ -942,20 +954,21 @@ static CURLcode pop3_statemach_act(struct connectdata *conn)
struct pop3_conn *pop3c = &conn->proto.pop3c;
struct pingpong *pp = &pop3c->pp;
size_t nread = 0;
+ (void)data;
/* Busy upgrading the connection; right now all I/O is SSL/TLS, not POP3 */
if(pop3c->state == POP3_UPGRADETLS)
- return pop3_perform_upgrade_tls(conn);
+ return pop3_perform_upgrade_tls(data, conn);
/* Flush any data that needs to be sent */
if(pp->sendleft)
- return Curl_pp_flushsend(pp);
+ return Curl_pp_flushsend(data, pp);
do {
/* Read the response from the server */
- result = Curl_pp_readresp(sock, pp, &pop3code, &nread);
- if(result)
- return result;
+ result = Curl_pp_readresp(data, sock, pp, &pop3code, &nread);
+ if(result)
+ return result;
if(!pop3code)
break;
@@ -963,44 +976,44 @@ static CURLcode pop3_statemach_act(struct connectdata *conn)
/* We have now received a full POP3 server response */
switch(pop3c->state) {
case POP3_SERVERGREET:
- result = pop3_state_servergreet_resp(conn, pop3code, pop3c->state);
+ result = pop3_state_servergreet_resp(data, pop3code, pop3c->state);
break;
case POP3_CAPA:
- result = pop3_state_capa_resp(conn, pop3code, pop3c->state);
+ result = pop3_state_capa_resp(data, pop3code, pop3c->state);
break;
case POP3_STARTTLS:
- result = pop3_state_starttls_resp(conn, pop3code, pop3c->state);
+ result = pop3_state_starttls_resp(data, conn, pop3code, pop3c->state);
break;
case POP3_AUTH:
- result = pop3_state_auth_resp(conn, pop3code, pop3c->state);
+ result = pop3_state_auth_resp(data, pop3code, pop3c->state);
break;
#ifndef CURL_DISABLE_CRYPTO_AUTH
case POP3_APOP:
- result = pop3_state_apop_resp(conn, pop3code, pop3c->state);
+ result = pop3_state_apop_resp(data, pop3code, pop3c->state);
break;
#endif
case POP3_USER:
- result = pop3_state_user_resp(conn, pop3code, pop3c->state);
+ result = pop3_state_user_resp(data, pop3code, pop3c->state);
break;
case POP3_PASS:
- result = pop3_state_pass_resp(conn, pop3code, pop3c->state);
+ result = pop3_state_pass_resp(data, pop3code, pop3c->state);
break;
case POP3_COMMAND:
- result = pop3_state_command_resp(conn, pop3code, pop3c->state);
+ result = pop3_state_command_resp(data, pop3code, pop3c->state);
break;
case POP3_QUIT:
/* fallthrough, just stop! */
default:
/* internal error */
- state(conn, POP3_STOP);
+ state(data, POP3_STOP);
break;
}
} while(!result && pop3c->state != POP3_STOP && Curl_pp_moredata(pp));
@@ -1009,44 +1022,46 @@ static CURLcode pop3_statemach_act(struct connectdata *conn)
}
/* Called repeatedly until done from multi.c */
-static CURLcode pop3_multi_statemach(struct connectdata *conn, bool *done)
+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;
if((conn->handler->flags & PROTOPT_SSL) && !pop3c->ssldone) {
- result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, &pop3c->ssldone);
+ result = Curl_ssl_connect_nonblocking(data, conn,
+ FIRSTSOCKET, &pop3c->ssldone);
if(result || !pop3c->ssldone)
return result;
}
- result = Curl_pp_statemach(&pop3c->pp, FALSE, FALSE);
+ result = Curl_pp_statemach(data, &pop3c->pp, FALSE, FALSE);
*done = (pop3c->state == POP3_STOP) ? TRUE : FALSE;
return result;
}
-static CURLcode pop3_block_statemach(struct connectdata *conn,
+static CURLcode pop3_block_statemach(struct Curl_easy *data,
+ struct connectdata *conn,
bool disconnecting)
{
CURLcode result = CURLE_OK;
struct pop3_conn *pop3c = &conn->proto.pop3c;
while(pop3c->state != POP3_STOP && !result)
- result = Curl_pp_statemach(&pop3c->pp, TRUE, disconnecting);
+ result = Curl_pp_statemach(data, &pop3c->pp, TRUE, disconnecting);
return result;
}
/* Allocate and initialize the POP3 struct for the current Curl_easy if
required */
-static CURLcode pop3_init(struct connectdata *conn)
+static CURLcode pop3_init(struct Curl_easy *data)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
struct POP3 *pop3;
- pop3 = data->req.protop = calloc(sizeof(struct POP3), 1);
+ pop3 = data->req.p.pop3 = calloc(sizeof(struct POP3), 1);
if(!pop3)
result = CURLE_OUT_OF_MEMORY;
@@ -1054,9 +1069,10 @@ static CURLcode pop3_init(struct connectdata *conn)
}
/* For the POP3 "protocol connect" and "doing" phases only */
-static int pop3_getsock(struct connectdata *conn, curl_socket_t *socks)
+static int pop3_getsock(struct Curl_easy *data,
+ struct connectdata *conn, curl_socket_t *socks)
{
- return Curl_pp_getsock(&conn->proto.pop3c.pp, socks);
+ return Curl_pp_getsock(data, &conn->proto.pop3c.pp, socks);
}
/***********************************************************************
@@ -1069,9 +1085,10 @@ static int pop3_getsock(struct connectdata *conn, curl_socket_t *socks)
* The variable 'done' points to will be TRUE if the protocol-layer connect
* phase is done when this function returns, or FALSE if not.
*/
-static CURLcode pop3_connect(struct connectdata *conn, bool *done)
+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;
@@ -1080,18 +1097,15 @@ static CURLcode pop3_connect(struct connectdata *conn, bool *done)
/* We always support persistent connections in POP3 */
connkeep(conn, "POP3 default");
- /* Set the default response time-out */
- pp->response_time = RESP_TIMEOUT;
- pp->statemach_act = pop3_statemach_act;
- pp->endofresp = pop3_endofresp;
- pp->conn = conn;
+ PINGPONG_SETUP(pp, pop3_statemachine, pop3_endofresp);
/* Set the default preferred authentication type and mechanism */
pop3c->preftype = POP3_TYPE_ANY;
Curl_sasl_init(&pop3c->sasl, &saslpop3);
/* Initialise the pingpong layer */
- Curl_pp_init(pp);
+ Curl_pp_setup(pp);
+ Curl_pp_init(data, pp);
/* Parse the URL options */
result = pop3_parse_url_options(conn);
@@ -1099,9 +1113,9 @@ static CURLcode pop3_connect(struct connectdata *conn, bool *done)
return result;
/* Start off waiting for the server greeting response */
- state(conn, POP3_SERVERGREET);
+ state(data, POP3_SERVERGREET);
- result = pop3_multi_statemach(conn, done);
+ result = pop3_multi_statemach(data, done);
return result;
}
@@ -1115,12 +1129,11 @@ static CURLcode pop3_connect(struct connectdata *conn, bool *done)
*
* Input argument is already checked for validity.
*/
-static CURLcode pop3_done(struct connectdata *conn, CURLcode status,
+static CURLcode pop3_done(struct Curl_easy *data, CURLcode status,
bool premature)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
- struct POP3 *pop3 = data->req.protop;
+ struct POP3 *pop3 = data->req.p.pop3;
(void)premature;
@@ -1128,7 +1141,7 @@ static CURLcode pop3_done(struct connectdata *conn, CURLcode status,
return CURLE_OK;
if(status) {
- connclose(conn, "POP3 done with bad status");
+ connclose(data->conn, "POP3 done with bad status");
result = status; /* use the already set error code */
}
@@ -1149,16 +1162,17 @@ static CURLcode pop3_done(struct connectdata *conn, CURLcode status,
* This is the actual DO function for POP3. Get a message/listing according to
* the options previously setup.
*/
-static CURLcode pop3_perform(struct connectdata *conn, bool *connected,
+static CURLcode pop3_perform(struct Curl_easy *data, bool *connected,
bool *dophase_done)
{
/* This is POP3 and no proxy */
CURLcode result = CURLE_OK;
- struct POP3 *pop3 = conn->data->req.protop;
+ struct connectdata *conn = data->conn;
+ struct POP3 *pop3 = data->req.p.pop3;
- DEBUGF(infof(conn->data, "DO phase starts\n"));
+ DEBUGF(infof(data, "DO phase starts\n"));
- if(conn->data->set.opt_no_body) {
+ if(data->set.opt_no_body) {
/* Requested no body means no transfer */
pop3->transfer = FTPTRANSFER_INFO;
}
@@ -1166,17 +1180,16 @@ static CURLcode pop3_perform(struct connectdata *conn, bool *connected,
*dophase_done = FALSE; /* not done yet */
/* Start the first command in the DO phase */
- result = pop3_perform_command(conn);
+ result = pop3_perform_command(data);
if(result)
return result;
/* Run the state-machine */
- result = pop3_multi_statemach(conn, dophase_done);
-
+ result = pop3_multi_statemach(data, dophase_done);
*connected = conn->bits.tcpconnect[FIRSTSOCKET];
if(*dophase_done)
- DEBUGF(infof(conn->data, "DO phase is complete\n"));
+ DEBUGF(infof(data, "DO phase is complete\n"));
return result;
}
@@ -1190,23 +1203,22 @@ static CURLcode pop3_perform(struct connectdata *conn, bool *connected,
*
* The input argument is already checked for validity.
*/
-static CURLcode pop3_do(struct connectdata *conn, bool *done)
+static CURLcode pop3_do(struct Curl_easy *data, bool *done)
{
CURLcode result = CURLE_OK;
-
*done = FALSE; /* default to false */
/* Parse the URL path */
- result = pop3_parse_url_path(conn);
+ result = pop3_parse_url_path(data);
if(result)
return result;
/* Parse the custom request */
- result = pop3_parse_custom_request(conn);
+ result = pop3_parse_custom_request(data);
if(result)
return result;
- result = pop3_regular_transfer(conn, done);
+ result = pop3_regular_transfer(data, done);
return result;
}
@@ -1218,19 +1230,20 @@ static CURLcode pop3_do(struct connectdata *conn, bool *done)
* Disconnect from an POP3 server. Cleanup protocol-specific per-connection
* resources. BLOCKING.
*/
-static CURLcode pop3_disconnect(struct connectdata *conn, bool dead_connection)
+static CURLcode pop3_disconnect(struct Curl_easy *data,
+ struct connectdata *conn, bool dead_connection)
{
struct pop3_conn *pop3c = &conn->proto.pop3c;
+ (void)data;
/* 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. */
- /* The POP3 session may or may not have been allocated/setup at this
- point! */
- if(!dead_connection && pop3c->pp.conn && pop3c->pp.conn->bits.protoconnstart)
- if(!pop3_perform_quit(conn))
- (void)pop3_block_statemach(conn, TRUE); /* ignore errors on QUIT */
+ if(!dead_connection && conn->bits.protoconnstart) {
+ if(!pop3_perform_quit(data, conn))
+ (void)pop3_block_statemach(data, conn, TRUE); /* ignore errors on QUIT */
+ }
/* Disconnect from the server */
Curl_pp_disconnect(&pop3c->pp);
@@ -1245,25 +1258,25 @@ static CURLcode pop3_disconnect(struct connectdata *conn, bool dead_connection)
}
/* Call this when the DO phase has completed */
-static CURLcode pop3_dophase_done(struct connectdata *conn, bool connected)
+static CURLcode pop3_dophase_done(struct Curl_easy *data, bool connected)
{
- (void)conn;
+ (void)data;
(void)connected;
return CURLE_OK;
}
/* Called from multi.c while DOing */
-static CURLcode pop3_doing(struct connectdata *conn, bool *dophase_done)
+static CURLcode pop3_doing(struct Curl_easy *data, bool *dophase_done)
{
- CURLcode result = pop3_multi_statemach(conn, dophase_done);
+ CURLcode result = pop3_multi_statemach(data, dophase_done);
if(result)
- DEBUGF(infof(conn->data, "DO phase failed\n"));
+ DEBUGF(infof(data, "DO phase failed\n"));
else if(*dophase_done) {
- result = pop3_dophase_done(conn, FALSE /* not connected */);
+ result = pop3_dophase_done(data, FALSE /* not connected */);
- DEBUGF(infof(conn->data, "DO phase is complete\n"));
+ DEBUGF(infof(data, "DO phase is complete\n"));
}
return result;
@@ -1278,12 +1291,11 @@ static CURLcode pop3_doing(struct connectdata *conn, bool *dophase_done)
* Performs all commands done before a regular transfer between a local and a
* remote host.
*/
-static CURLcode pop3_regular_transfer(struct connectdata *conn,
+static CURLcode pop3_regular_transfer(struct Curl_easy *data,
bool *dophase_done)
{
CURLcode result = CURLE_OK;
bool connected = FALSE;
- struct Curl_easy *data = conn->data;
/* Make sure size is unknown at this point */
data->req.size = -1;
@@ -1295,19 +1307,20 @@ static CURLcode pop3_regular_transfer(struct connectdata *conn,
Curl_pgrsSetDownloadSize(data, -1);
/* Carry out the perform */
- result = pop3_perform(conn, &connected, dophase_done);
+ result = pop3_perform(data, &connected, dophase_done);
/* Perform post DO phase operations if necessary */
if(!result && *dophase_done)
- result = pop3_dophase_done(conn, connected);
+ result = pop3_dophase_done(data, connected);
return result;
}
-static CURLcode pop3_setup_connection(struct connectdata *conn)
+static CURLcode pop3_setup_connection(struct Curl_easy *data,
+ struct connectdata *conn)
{
/* Initialise the POP3 layer */
- CURLcode result = pop3_init(conn);
+ CURLcode result = pop3_init(data);
if(result)
return result;
@@ -1382,11 +1395,10 @@ static CURLcode pop3_parse_url_options(struct connectdata *conn)
*
* Parse the URL path into separate path components.
*/
-static CURLcode pop3_parse_url_path(struct connectdata *conn)
+static CURLcode pop3_parse_url_path(struct Curl_easy *data)
{
/* The POP3 struct is already initialised in pop3_connect() */
- struct Curl_easy *data = conn->data;
- struct POP3 *pop3 = data->req.protop;
+ struct POP3 *pop3 = data->req.p.pop3;
const char *path = &data->state.up.path[1]; /* skip leading path */
/* URL decode the path for the message ID */
@@ -1399,11 +1411,10 @@ static CURLcode pop3_parse_url_path(struct connectdata *conn)
*
* Parse the custom request.
*/
-static CURLcode pop3_parse_custom_request(struct connectdata *conn)
+static CURLcode pop3_parse_custom_request(struct Curl_easy *data)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
- struct POP3 *pop3 = data->req.protop;
+ struct POP3 *pop3 = data->req.p.pop3;
const char *custom = data->set.str[STRING_CUSTOMREQUEST];
/* URL decode the custom request */
@@ -1420,13 +1431,12 @@ static CURLcode pop3_parse_custom_request(struct connectdata *conn)
* This function scans the body after the end-of-body and writes everything
* until the end is found.
*/
-CURLcode Curl_pop3_write(struct connectdata *conn, char *str, size_t nread)
+CURLcode Curl_pop3_write(struct Curl_easy *data, char *str, size_t nread)
{
/* This code could be made into a special function in the handler struct */
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
struct SingleRequest *k = &data->req;
-
+ struct connectdata *conn = data->conn;
struct pop3_conn *pop3c = &conn->proto.pop3c;
bool strip_dot = FALSE;
size_t last = 0;
@@ -1447,7 +1457,7 @@ CURLcode Curl_pop3_write(struct connectdata *conn, char *str, size_t nread)
if(i) {
/* Write out the body part that didn't match */
- result = Curl_client_write(conn, CLIENTWRITE_BODY, &str[last],
+ result = Curl_client_write(data, CLIENTWRITE_BODY, &str[last],
i - last);
if(result)
@@ -1505,7 +1515,7 @@ CURLcode Curl_pop3_write(struct connectdata *conn, char *str, size_t nread)
if(prev) {
/* If the partial match was the CRLF and dot then only write the CRLF
as the server would have inserted the dot */
- result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)POP3_EOB,
+ result = Curl_client_write(data, CLIENTWRITE_BODY, (char *)POP3_EOB,
strip_dot ? prev - 1 : prev);
if(result)
@@ -1521,7 +1531,7 @@ CURLcode Curl_pop3_write(struct connectdata *conn, char *str, size_t nread)
/* We have a full match so the transfer is done, however we must transfer
the CRLF at the start of the EOB as this is considered to be part of the
message as per RFC-1939, sect. 3 */
- result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)POP3_EOB, 2);
+ result = Curl_client_write(data, CLIENTWRITE_BODY, (char *)POP3_EOB, 2);
k->keepon &= ~KEEP_RECV;
pop3c->eob = 0;
@@ -1534,7 +1544,7 @@ CURLcode Curl_pop3_write(struct connectdata *conn, char *str, size_t nread)
return CURLE_OK;
if(nread - last) {
- result = Curl_client_write(conn, CLIENTWRITE_BODY, &str[last],
+ result = Curl_client_write(data, CLIENTWRITE_BODY, &str[last],
nread - last);
}
diff --git a/Utilities/cmcurl/lib/pop3.h b/Utilities/cmcurl/lib/pop3.h
index 3ba799977..17629ee2d 100644
--- a/Utilities/cmcurl/lib/pop3.h
+++ b/Utilities/cmcurl/lib/pop3.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2009 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2009 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -61,6 +61,7 @@ struct pop3_conn {
struct pingpong pp;
pop3state state; /* Always use pop3.c:state() to change state! */
bool ssldone; /* Is connect() over SSL done? */
+ bool tls_supported; /* StartTLS capability supported by server */
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
@@ -69,7 +70,6 @@ struct pop3_conn {
unsigned int authtypes; /* Accepted authentication types */
unsigned int preftype; /* Preferred authentication type */
char *apoptimestamp; /* APOP timestamp from the server greeting */
- bool tls_supported; /* StartTLS capability supported by server */
};
extern const struct Curl_handler Curl_handler_pop3;
@@ -90,6 +90,6 @@ extern const struct Curl_handler Curl_handler_pop3s;
/* This function scans the body after the end-of-body and writes everything
* until the end is found */
-CURLcode Curl_pop3_write(struct connectdata *conn, char *str, size_t nread);
+CURLcode Curl_pop3_write(struct Curl_easy *data, char *str, size_t nread);
#endif /* HEADER_CURL_POP3_H */
diff --git a/Utilities/cmcurl/lib/progress.c b/Utilities/cmcurl/lib/progress.c
index 895138448..55e8ded04 100644
--- a/Utilities/cmcurl/lib/progress.c
+++ b/Utilities/cmcurl/lib/progress.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -137,12 +137,11 @@ static char *max5data(curl_off_t bytes, char *max5)
*/
-int Curl_pgrsDone(struct connectdata *conn)
+int Curl_pgrsDone(struct Curl_easy *data)
{
int rc;
- struct Curl_easy *data = conn->data;
data->progress.lastshow = 0;
- rc = Curl_pgrsUpdate(conn); /* the final (forced) update */
+ rc = Curl_pgrsUpdate(data); /* the final (forced) update */
if(rc)
return rc;
@@ -164,9 +163,13 @@ void Curl_pgrsResetTransferSizes(struct Curl_easy *data)
}
/*
+ *
+ * Curl_pgrsTime(). Store the current time at the given label. This fetches a
+ * fresh "now" and returns it.
+ *
* @unittest: 1399
*/
-void Curl_pgrsTime(struct Curl_easy *data, timerid timer)
+struct curltime Curl_pgrsTime(struct Curl_easy *data, timerid timer)
{
struct curltime now = Curl_now();
timediff_t *delta = NULL;
@@ -209,7 +212,7 @@ void Curl_pgrsTime(struct Curl_easy *data, timerid timer)
* changing the t_starttransfer time.
*/
if(data->progress.is_t_startransfer_set) {
- return;
+ return now;
}
else {
data->progress.is_t_startransfer_set = true;
@@ -228,6 +231,7 @@ void Curl_pgrsTime(struct Curl_easy *data, timerid timer)
us = 1; /* make sure at least one microsecond passed */
*delta += us;
}
+ return now;
}
void Curl_pgrsStartNow(struct Curl_easy *data)
@@ -235,10 +239,8 @@ 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.tv_sec = 0;
- data->progress.ul_limit_start.tv_usec = 0;
- data->progress.dl_limit_start.tv_sec = 0;
- data->progress.dl_limit_start.tv_usec = 0;
+ data->progress.ul_limit_start = data->progress.start;
+ data->progress.dl_limit_start = data->progress.start;
data->progress.downloaded = 0;
data->progress.uploaded = 0;
/* clear all bits except HIDE and HEADERS_OUT */
@@ -368,11 +370,10 @@ void Curl_pgrsSetUploadSize(struct Curl_easy *data, curl_off_t size)
}
/* returns TRUE if it's time to show the progress meter */
-static bool progress_calc(struct connectdata *conn, struct curltime now)
+static bool progress_calc(struct Curl_easy *data, struct curltime now)
{
curl_off_t timespent;
curl_off_t timespent_ms; /* milliseconds */
- struct Curl_easy *data = conn->data;
curl_off_t dl = data->progress.downloaded;
curl_off_t ul = data->progress.uploaded;
bool timetoshow = FALSE;
@@ -462,9 +463,8 @@ static bool progress_calc(struct connectdata *conn, struct curltime now)
}
#ifndef CURL_DISABLE_PROGRESS_METER
-static void progress_meter(struct connectdata *conn)
+static void progress_meter(struct Curl_easy *data)
{
- struct Curl_easy *data = conn->data;
char max5[6][10];
curl_off_t dlpercen = 0;
curl_off_t ulpercen = 0;
@@ -578,11 +578,10 @@ static void progress_meter(struct connectdata *conn)
* Curl_pgrsUpdate() returns 0 for success or the value returned by the
* progress callback!
*/
-int Curl_pgrsUpdate(struct connectdata *conn)
+int Curl_pgrsUpdate(struct Curl_easy *data)
{
- struct Curl_easy *data = conn->data;
struct curltime now = Curl_now(); /* what time is it */
- bool showprogress = progress_calc(conn, now);
+ bool showprogress = progress_calc(data, now);
if(!(data->progress.flags & PGRS_HIDE)) {
if(data->set.fxferinfo) {
int result;
@@ -618,7 +617,7 @@ int Curl_pgrsUpdate(struct connectdata *conn)
}
if(showprogress)
- progress_meter(conn);
+ progress_meter(data);
}
return 0;
diff --git a/Utilities/cmcurl/lib/progress.h b/Utilities/cmcurl/lib/progress.h
index 3515ac6d5..ac4ebc098 100644
--- a/Utilities/cmcurl/lib/progress.h
+++ b/Utilities/cmcurl/lib/progress.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -40,16 +40,16 @@ typedef enum {
TIMER_LAST /* must be last */
} timerid;
-int Curl_pgrsDone(struct connectdata *);
+int Curl_pgrsDone(struct Curl_easy *data);
void Curl_pgrsStartNow(struct Curl_easy *data);
void Curl_pgrsSetDownloadSize(struct Curl_easy *data, curl_off_t size);
void Curl_pgrsSetUploadSize(struct Curl_easy *data, curl_off_t size);
void Curl_pgrsSetDownloadCounter(struct Curl_easy *data, curl_off_t size);
void Curl_pgrsSetUploadCounter(struct Curl_easy *data, curl_off_t size);
void Curl_ratelimit(struct Curl_easy *data, struct curltime now);
-int Curl_pgrsUpdate(struct connectdata *);
+int Curl_pgrsUpdate(struct Curl_easy *data);
void Curl_pgrsResetTransferSizes(struct Curl_easy *data);
-void Curl_pgrsTime(struct Curl_easy *data, timerid timer);
+struct curltime Curl_pgrsTime(struct Curl_easy *data, timerid timer);
timediff_t Curl_pgrsLimitWaitTime(curl_off_t cursize,
curl_off_t startsize,
curl_off_t limit,
diff --git a/Utilities/cmcurl/lib/psl.c b/Utilities/cmcurl/lib/psl.c
index 568baff03..e46091863 100644
--- a/Utilities/cmcurl/lib/psl.c
+++ b/Utilities/cmcurl/lib/psl.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
diff --git a/Utilities/cmcurl/lib/psl.h b/Utilities/cmcurl/lib/psl.h
index e9f99d03e..c10367471 100644
--- a/Utilities/cmcurl/lib/psl.h
+++ b/Utilities/cmcurl/lib/psl.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
diff --git a/Utilities/cmcurl/lib/quic.h b/Utilities/cmcurl/lib/quic.h
index 8e7df90ea..947f13edc 100644
--- a/Utilities/cmcurl/lib/quic.h
+++ b/Utilities/cmcurl/lib/quic.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -35,25 +35,28 @@
#include "urldata.h"
/* functions provided by the specific backends */
-CURLcode Curl_quic_connect(struct connectdata *conn,
+CURLcode Curl_quic_connect(struct Curl_easy *data,
+ struct connectdata *conn,
curl_socket_t sockfd,
int sockindex,
const struct sockaddr *addr,
socklen_t addrlen);
-CURLcode Curl_quic_is_connected(struct connectdata *conn,
- curl_socket_t sockfd,
+CURLcode Curl_quic_is_connected(struct Curl_easy *data,
+ struct connectdata *conn,
+ int sockindex,
bool *connected);
int Curl_quic_ver(char *p, size_t len);
-CURLcode Curl_quic_done_sending(struct connectdata *conn);
+CURLcode Curl_quic_done_sending(struct Curl_easy *data);
void Curl_quic_done(struct Curl_easy *data, bool premature);
bool Curl_quic_data_pending(const struct Curl_easy *data);
-void Curl_quic_disconnect(struct connectdata *conn, int tempindex);
+void Curl_quic_disconnect(struct Curl_easy *data,
+ struct connectdata *conn, int tempindex);
#else /* ENABLE_QUIC */
#define Curl_quic_done_sending(x)
#define Curl_quic_done(x,y)
#define Curl_quic_data_pending(x)
-#define Curl_quic_disconnect(x,y)
+#define Curl_quic_disconnect(x,y,z)
#endif /* !ENABLE_QUIC */
#endif /* HEADER_CURL_QUIC_H */
diff --git a/Utilities/cmcurl/lib/rand.c b/Utilities/cmcurl/lib/rand.c
index c415048ec..951fedb0a 100644
--- a/Utilities/cmcurl/lib/rand.c
+++ b/Utilities/cmcurl/lib/rand.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
diff --git a/Utilities/cmcurl/lib/rand.h b/Utilities/cmcurl/lib/rand.h
index 3c8e2b81d..02d95d8e6 100644
--- a/Utilities/cmcurl/lib/rand.h
+++ b/Utilities/cmcurl/lib/rand.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
diff --git a/Utilities/cmcurl/lib/rename.c b/Utilities/cmcurl/lib/rename.c
index fe5f95d0d..f858d4369 100644
--- a/Utilities/cmcurl/lib/rename.c
+++ b/Utilities/cmcurl/lib/rename.c
@@ -9,7 +9,7 @@
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -24,8 +24,8 @@
#include "curl_setup.h"
-#if (!defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)) || \
- defined(USE_ALTSVC)
+#if (!defined(CURL_DISABLE_HTTP) || !defined(CURL_DISABLE_COOKIES)) || \
+ !defined(CURL_DISABLE_ALTSVC)
#include "curl_multibyte.h"
#include "timeval.h"
diff --git a/Utilities/cmcurl/lib/rename.h b/Utilities/cmcurl/lib/rename.h
index d7442c844..534f7471c 100644
--- a/Utilities/cmcurl/lib/rename.h
+++ b/Utilities/cmcurl/lib/rename.h
@@ -11,7 +11,7 @@
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/rtsp.c b/Utilities/cmcurl/lib/rtsp.c
index dbd7dc6a6..55766757a 100644
--- a/Utilities/cmcurl/lib/rtsp.c
+++ b/Utilities/cmcurl/lib/rtsp.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -22,7 +22,7 @@
#include "curl_setup.h"
-#ifndef CURL_DISABLE_RTSP
+#if !defined(CURL_DISABLE_RTSP) && !defined(USE_HYPER)
#include "urldata.h"
#include <curl/curl.h>
@@ -48,11 +48,13 @@
((int)((unsigned char)((p)[3]))))
/* protocol-specific functions set up to be called by the main engine */
-static CURLcode rtsp_do(struct connectdata *conn, bool *done);
-static CURLcode rtsp_done(struct connectdata *conn, CURLcode, bool premature);
-static CURLcode rtsp_connect(struct connectdata *conn, bool *done);
-static CURLcode rtsp_disconnect(struct connectdata *conn, bool dead);
-static int rtsp_getsock_do(struct connectdata *conn, curl_socket_t *socks);
+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);
/*
* Parse and write out any available RTP data.
@@ -66,23 +68,26 @@ static CURLcode rtsp_rtp_readwrite(struct Curl_easy *data,
ssize_t *nread,
bool *readmore);
-static CURLcode rtsp_setup_connection(struct connectdata *conn);
-static unsigned int rtsp_conncheck(struct connectdata *check,
+static CURLcode rtsp_setup_connection(struct Curl_easy *data,
+ struct connectdata *conn);
+static unsigned int rtsp_conncheck(struct Curl_easy *data,
+ struct connectdata *check,
unsigned int checks_to_perform);
/* this returns the socket to wait for in the DO and DOING state for the multi
interface and then we're always _sending_ a request and thus we wait for
the single socket to become writable only */
-static int rtsp_getsock_do(struct connectdata *conn,
+static int rtsp_getsock_do(struct Curl_easy *data, struct connectdata *conn,
curl_socket_t *socks)
{
/* write mode */
+ (void)data;
socks[0] = conn->sock[FIRSTSOCKET];
return GETSOCK_WRITESOCK(0);
}
static
-CURLcode rtp_client_write(struct connectdata *conn, char *ptr, size_t len);
+CURLcode rtp_client_write(struct Curl_easy *data, char *ptr, size_t len);
/*
@@ -106,15 +111,18 @@ const struct Curl_handler Curl_handler_rtsp = {
rtsp_conncheck, /* connection_check */
PORT_RTSP, /* defport */
CURLPROTO_RTSP, /* protocol */
+ CURLPROTO_RTSP, /* family */
PROTOPT_NONE /* flags */
};
-static CURLcode rtsp_setup_connection(struct connectdata *conn)
+static CURLcode rtsp_setup_connection(struct Curl_easy *data,
+ struct connectdata *conn)
{
struct RTSP *rtsp;
+ (void)conn;
- conn->data->req.protop = rtsp = calloc(1, sizeof(struct RTSP));
+ data->req.p.rtsp = rtsp = calloc(1, sizeof(struct RTSP));
if(!rtsp)
return CURLE_OUT_OF_MEMORY;
@@ -155,13 +163,15 @@ static bool rtsp_connisdead(struct connectdata *check)
/*
* Function to check on various aspects of a connection.
*/
-static unsigned int rtsp_conncheck(struct connectdata *check,
+static unsigned int rtsp_conncheck(struct Curl_easy *data,
+ struct connectdata *conn,
unsigned int checks_to_perform)
{
unsigned int ret_val = CONNRESULT_NONE;
+ (void)data;
if(checks_to_perform & CONNCHECK_ISDEAD) {
- if(rtsp_connisdead(check))
+ if(rtsp_connisdead(conn))
ret_val |= CONNRESULT_DEAD;
}
@@ -169,12 +179,11 @@ static unsigned int rtsp_conncheck(struct connectdata *check,
}
-static CURLcode rtsp_connect(struct connectdata *conn, bool *done)
+static CURLcode rtsp_connect(struct Curl_easy *data, bool *done)
{
CURLcode httpStatus;
- struct Curl_easy *data = conn->data;
- httpStatus = Curl_http_connect(conn, done);
+ httpStatus = Curl_http_connect(data, done);
/* Initialize the CSeq if not already done */
if(data->state.rtsp_next_client_CSeq == 0)
@@ -182,31 +191,32 @@ static CURLcode rtsp_connect(struct connectdata *conn, bool *done)
if(data->state.rtsp_next_server_CSeq == 0)
data->state.rtsp_next_server_CSeq = 1;
- conn->proto.rtspc.rtp_channel = -1;
+ data->conn->proto.rtspc.rtp_channel = -1;
return httpStatus;
}
-static CURLcode rtsp_disconnect(struct connectdata *conn, bool dead)
+static CURLcode rtsp_disconnect(struct Curl_easy *data,
+ struct connectdata *conn, bool dead)
{
(void) dead;
+ (void) data;
Curl_safefree(conn->proto.rtspc.rtp_buf);
return CURLE_OK;
}
-static CURLcode rtsp_done(struct connectdata *conn,
+static CURLcode rtsp_done(struct Curl_easy *data,
CURLcode status, bool premature)
{
- struct Curl_easy *data = conn->data;
- struct RTSP *rtsp = data->req.protop;
+ struct RTSP *rtsp = data->req.p.rtsp;
CURLcode httpStatus;
/* Bypass HTTP empty-reply checks on receive */
if(data->set.rtspreq == RTSPREQ_RECEIVE)
premature = TRUE;
- httpStatus = Curl_http_done(conn, status, premature);
+ httpStatus = Curl_http_done(data, status, premature);
if(rtsp) {
/* Check the sequence numbers */
@@ -219,7 +229,7 @@ static CURLcode rtsp_done(struct connectdata *conn,
return CURLE_RTSP_CSEQ_ERROR;
}
if(data->set.rtspreq == RTSPREQ_RECEIVE &&
- (conn->proto.rtspc.rtp_channel == -1)) {
+ (data->conn->proto.rtspc.rtp_channel == -1)) {
infof(data, "Got an RTP Receive with a CSeq of %ld\n", CSeq_recv);
}
}
@@ -227,12 +237,12 @@ static CURLcode rtsp_done(struct connectdata *conn,
return httpStatus;
}
-static CURLcode rtsp_do(struct connectdata *conn, bool *done)
+static CURLcode rtsp_do(struct Curl_easy *data, bool *done)
{
- struct Curl_easy *data = conn->data;
+ struct connectdata *conn = data->conn;
CURLcode result = CURLE_OK;
Curl_RtspReq rtspreq = data->set.rtspreq;
- struct RTSP *rtsp = data->req.protop;
+ struct RTSP *rtsp = data->req.p.rtsp;
struct dynbuf req_buffer;
curl_off_t postsize = 0; /* for ANNOUNCE and SET_PARAMETER */
curl_off_t putsize = 0; /* for ANNOUNCE and SET_PARAMETER */
@@ -329,7 +339,7 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
}
/* Transport Header for SETUP requests */
- p_transport = Curl_checkheaders(conn, "Transport");
+ p_transport = Curl_checkheaders(data, "Transport");
if(rtspreq == RTSPREQ_SETUP && !p_transport) {
/* New Transport: setting? */
if(data->set.str[STRING_RTSP_TRANSPORT]) {
@@ -353,11 +363,11 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
/* Accept Headers for DESCRIBE requests */
if(rtspreq == RTSPREQ_DESCRIBE) {
/* Accept Header */
- p_accept = Curl_checkheaders(conn, "Accept")?
+ p_accept = Curl_checkheaders(data, "Accept")?
NULL:"Accept: application/sdp\r\n";
/* Accept-Encoding header */
- if(!Curl_checkheaders(conn, "Accept-Encoding") &&
+ if(!Curl_checkheaders(data, "Accept-Encoding") &&
data->set.str[STRING_ENCODING]) {
Curl_safefree(data->state.aptr.accept_encoding);
data->state.aptr.accept_encoding =
@@ -374,17 +384,18 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
it might have been used in the proxy connect, but if we have got a header
with the user-agent string specified, we erase the previously made string
here. */
- if(Curl_checkheaders(conn, "User-Agent") && data->state.aptr.uagent) {
+ if(Curl_checkheaders(data, "User-Agent") && data->state.aptr.uagent) {
Curl_safefree(data->state.aptr.uagent);
data->state.aptr.uagent = NULL;
}
- else if(!Curl_checkheaders(conn, "User-Agent") &&
+ else if(!Curl_checkheaders(data, "User-Agent") &&
data->set.str[STRING_USERAGENT]) {
p_uagent = data->state.aptr.uagent;
}
/* setup the authentication headers */
- result = Curl_http_output_auth(conn, p_request, p_stream_uri, FALSE);
+ result = Curl_http_output_auth(data, conn, p_request, HTTPREQ_GET,
+ p_stream_uri, FALSE);
if(result)
return result;
@@ -393,7 +404,7 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
/* Referrer */
Curl_safefree(data->state.aptr.ref);
- if(data->change.referer && !Curl_checkheaders(conn, "Referer"))
+ if(data->change.referer && !Curl_checkheaders(data, "Referer"))
data->state.aptr.ref = aprintf("Referer: %s\r\n", data->change.referer);
else
data->state.aptr.ref = NULL;
@@ -410,7 +421,7 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
(rtspreq & (RTSPREQ_PLAY | RTSPREQ_PAUSE | RTSPREQ_RECORD))) {
/* Check to see if there is a range set in the custom headers */
- if(!Curl_checkheaders(conn, "Range") && data->state.range) {
+ if(!Curl_checkheaders(data, "Range") && data->state.range) {
Curl_safefree(data->state.aptr.rangeline);
data->state.aptr.rangeline = aprintf("Range: %s\r\n", data->state.range);
p_range = data->state.aptr.rangeline;
@@ -420,11 +431,11 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
/*
* Sanity check the custom headers
*/
- if(Curl_checkheaders(conn, "CSeq")) {
+ if(Curl_checkheaders(data, "CSeq")) {
failf(data, "CSeq cannot be set as a custom header.");
return CURLE_RTSP_CSEQ_ERROR;
}
- if(Curl_checkheaders(conn, "Session")) {
+ if(Curl_checkheaders(data, "Session")) {
failf(data, "Session ID cannot be set as a custom header.");
return CURLE_BAD_FUNCTION_ARGUMENT;
}
@@ -483,12 +494,12 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
return result;
if((rtspreq == RTSPREQ_SETUP) || (rtspreq == RTSPREQ_DESCRIBE)) {
- result = Curl_add_timecondition(conn, &req_buffer);
+ result = Curl_add_timecondition(data, &req_buffer);
if(result)
return result;
}
- result = Curl_add_custom_headers(conn, FALSE, &req_buffer);
+ result = Curl_add_custom_headers(data, FALSE, &req_buffer);
if(result)
return result;
@@ -511,7 +522,7 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
if(putsize > 0 || postsize > 0) {
/* As stated in the http comments, it is probably not wise to
* actually set a custom Content-Length in the headers */
- if(!Curl_checkheaders(conn, "Content-Length")) {
+ if(!Curl_checkheaders(data, "Content-Length")) {
result =
Curl_dyn_addf(&req_buffer,
"Content-Length: %" CURL_FORMAT_CURL_OFF_T"\r\n",
@@ -522,7 +533,7 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
if(rtspreq == RTSPREQ_SET_PARAMETER ||
rtspreq == RTSPREQ_GET_PARAMETER) {
- if(!Curl_checkheaders(conn, "Content-Type")) {
+ if(!Curl_checkheaders(data, "Content-Type")) {
result = Curl_dyn_addf(&req_buffer,
"Content-Type: text/parameters\r\n");
if(result)
@@ -531,7 +542,7 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
}
if(rtspreq == RTSPREQ_ANNOUNCE) {
- if(!Curl_checkheaders(conn, "Content-Type")) {
+ if(!Curl_checkheaders(data, "Content-Type")) {
result = Curl_dyn_addf(&req_buffer,
"Content-Type: application/sdp\r\n");
if(result)
@@ -563,7 +574,7 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
}
/* issue the request */
- result = Curl_buffer_send(&req_buffer, conn,
+ result = Curl_buffer_send(&req_buffer, data,
&data->info.request_size, 0, FIRSTSOCKET);
if(result) {
failf(data, "Failed sending RTSP request");
@@ -579,7 +590,7 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
/* if a request-body has been sent off, we make sure this progress is
noted properly */
Curl_pgrsSetUploadCounter(data, data->req.writebytecount);
- if(Curl_pgrsUpdate(conn))
+ if(Curl_pgrsUpdate(data))
result = CURLE_ABORTED_BY_CALLBACK;
}
@@ -641,7 +652,7 @@ static CURLcode rtsp_rtp_readwrite(struct Curl_easy *data,
* Write out the header including the leading '$' */
DEBUGF(infof(data, "RTP write channel %d rtp_length %d\n",
rtspc->rtp_channel, rtp_length));
- result = rtp_client_write(conn, &rtp[0], rtp_length + 4);
+ result = rtp_client_write(data, &rtp[0], rtp_length + 4);
if(result) {
failf(data, "Got an error writing an RTP packet");
*readmore = FALSE;
@@ -712,9 +723,8 @@ static CURLcode rtsp_rtp_readwrite(struct Curl_easy *data,
}
static
-CURLcode rtp_client_write(struct connectdata *conn, char *ptr, size_t len)
+CURLcode rtp_client_write(struct Curl_easy *data, char *ptr, size_t len)
{
- struct Curl_easy *data = conn->data;
size_t wrote;
curl_write_callback writeit;
void *user_ptr;
@@ -754,17 +764,15 @@ CURLcode rtp_client_write(struct connectdata *conn, char *ptr, size_t len)
return CURLE_OK;
}
-CURLcode Curl_rtsp_parseheader(struct connectdata *conn,
- char *header)
+CURLcode Curl_rtsp_parseheader(struct Curl_easy *data, char *header)
{
- struct Curl_easy *data = conn->data;
long CSeq = 0;
if(checkprefix("CSeq:", header)) {
/* Store the received CSeq. Match is verified in rtsp_done */
int nc = sscanf(&header[4], ": %ld", &CSeq);
if(nc == 1) {
- struct RTSP *rtsp = data->req.protop;
+ struct RTSP *rtsp = data->req.p.rtsp;
rtsp->CSeq_recv = CSeq; /* mark the request */
data->state.rtsp_CSeq_recv = CSeq; /* update the handle */
}
@@ -775,6 +783,8 @@ CURLcode Curl_rtsp_parseheader(struct connectdata *conn,
}
else if(checkprefix("Session:", header)) {
char *start;
+ char *end;
+ size_t idlen;
/* Find the first non-space letter */
start = header + 8;
@@ -783,11 +793,25 @@ CURLcode Curl_rtsp_parseheader(struct connectdata *conn,
if(!*start) {
failf(data, "Got a blank Session ID");
+ return CURLE_RTSP_SESSION_ERROR;
}
- else if(data->set.str[STRING_RTSP_SESSION_ID]) {
+
+ /* Find the end of Session ID
+ *
+ * Allow any non whitespace content, up to the field separator or end of
+ * line. RFC 2326 isn't 100% clear on the session ID and for example
+ * gstreamer does url-encoded session ID's not covered by the standard.
+ */
+ end = start;
+ while(*end && *end != ';' && !ISSPACE(*end))
+ end++;
+ idlen = end - start;
+
+ if(data->set.str[STRING_RTSP_SESSION_ID]) {
+
/* If the Session ID is set, then compare */
- if(strncmp(start, data->set.str[STRING_RTSP_SESSION_ID],
- strlen(data->set.str[STRING_RTSP_SESSION_ID])) != 0) {
+ if(strlen(data->set.str[STRING_RTSP_SESSION_ID]) != idlen ||
+ strncmp(start, data->set.str[STRING_RTSP_SESSION_ID], idlen) != 0) {
failf(data, "Got RTSP Session ID Line [%s], but wanted ID [%s]",
start, data->set.str[STRING_RTSP_SESSION_ID]);
return CURLE_RTSP_SESSION_ERROR;
@@ -796,24 +820,17 @@ CURLcode Curl_rtsp_parseheader(struct connectdata *conn,
else {
/* If the Session ID is not set, and we find it in a response, then set
* it.
- *
- * Allow any non whitespace content, up to the field separator or end of
- * line. RFC 2326 isn't 100% clear on the session ID and for example
- * gstreamer does url-encoded session ID's not covered by the standard.
*/
- char *end = start;
- while(*end && *end != ';' && !ISSPACE(*end))
- end++;
/* Copy the id substring into a new buffer */
- data->set.str[STRING_RTSP_SESSION_ID] = malloc(end - start + 1);
+ data->set.str[STRING_RTSP_SESSION_ID] = malloc(idlen + 1);
if(data->set.str[STRING_RTSP_SESSION_ID] == NULL)
return CURLE_OUT_OF_MEMORY;
- memcpy(data->set.str[STRING_RTSP_SESSION_ID], start, end - start);
- (data->set.str[STRING_RTSP_SESSION_ID])[end - start] = '\0';
+ memcpy(data->set.str[STRING_RTSP_SESSION_ID], start, idlen);
+ (data->set.str[STRING_RTSP_SESSION_ID])[idlen] = '\0';
}
}
return CURLE_OK;
}
-#endif /* CURL_DISABLE_RTSP */
+#endif /* CURL_DISABLE_RTSP or using Hyper */
diff --git a/Utilities/cmcurl/lib/rtsp.h b/Utilities/cmcurl/lib/rtsp.h
index 1aae86456..1e9cb7d2c 100644
--- a/Utilities/cmcurl/lib/rtsp.h
+++ b/Utilities/cmcurl/lib/rtsp.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -21,11 +21,15 @@
* KIND, either express or implied.
*
***************************************************************************/
+#ifdef USE_HYPER
+#define CURL_DISABLE_RTSP
+#endif
+
#ifndef CURL_DISABLE_RTSP
extern const struct Curl_handler Curl_handler_rtsp;
-CURLcode Curl_rtsp_parseheader(struct connectdata *conn, char *header);
+CURLcode Curl_rtsp_parseheader(struct Curl_easy *data, char *header);
#else
/* disabled */
diff --git a/Utilities/cmcurl/lib/security.c b/Utilities/cmcurl/lib/security.c
deleted file mode 100644
index 3b9c20a73..000000000
--- a/Utilities/cmcurl/lib/security.c
+++ /dev/null
@@ -1,579 +0,0 @@
-/* This source code was modified by Martin Hedenfalk <mhe@stacken.kth.se> for
- * use in Curl. His latest changes were done 2000-09-18.
- *
- * It has since been patched and modified a lot by Daniel Stenberg
- * <daniel@haxx.se> to make it better applied to curl conditions, and to make
- * it not use globals, pollute name space and more. This source code awaits a
- * rewrite to work around the paragraph 2 in the BSD licenses as explained
- * below.
- *
- * Copyright (c) 1998, 1999, 2017 Kungliga Tekniska Högskolan
- * (Royal Institute of Technology, Stockholm, Sweden).
- *
- * Copyright (C) 2001 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * 3. Neither the name of the Institute nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE. */
-
-#include "curl_setup.h"
-
-#ifndef CURL_DISABLE_FTP
-#ifdef HAVE_GSSAPI
-
-#ifdef HAVE_NETDB_H
-#include <netdb.h>
-#endif
-
-#include <limits.h>
-
-#include "urldata.h"
-#include "curl_base64.h"
-#include "curl_memory.h"
-#include "curl_sec.h"
-#include "ftp.h"
-#include "sendf.h"
-#include "strcase.h"
-#include "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"
-
-static const struct {
- enum protection_level level;
- const char *name;
-} level_names[] = {
- { PROT_CLEAR, "clear" },
- { PROT_SAFE, "safe" },
- { PROT_CONFIDENTIAL, "confidential" },
- { PROT_PRIVATE, "private" }
-};
-
-static enum protection_level
-name_to_level(const char *name)
-{
- int i;
- for(i = 0; i < (int)sizeof(level_names)/(int)sizeof(level_names[0]); i++)
- if(checkprefix(name, level_names[i].name))
- return level_names[i].level;
- return PROT_NONE;
-}
-
-/* Convert a protocol |level| to its char representation.
- We take an int to catch programming mistakes. */
-static char level_to_char(int level)
-{
- switch(level) {
- case PROT_CLEAR:
- return 'C';
- case PROT_SAFE:
- return 'S';
- case PROT_CONFIDENTIAL:
- return 'E';
- case PROT_PRIVATE:
- return 'P';
- case PROT_CMD:
- /* Fall through */
- default:
- /* Those 2 cases should not be reached! */
- break;
- }
- DEBUGASSERT(0);
- /* Default to the most secure alternative. */
- return 'P';
-}
-
-/* Send an FTP command defined by |message| and the optional arguments. The
- function returns the ftp_code. If an error occurs, -1 is returned. */
-static int ftp_send_command(struct connectdata *conn, const char *message, ...)
-{
- int ftp_code;
- ssize_t nread = 0;
- va_list args;
- char print_buffer[50];
-
- va_start(args, message);
- mvsnprintf(print_buffer, sizeof(print_buffer), message, args);
- va_end(args);
-
- if(Curl_ftpsend(conn, print_buffer)) {
- ftp_code = -1;
- }
- else {
- if(Curl_GetFTPResponse(&nread, conn, &ftp_code))
- ftp_code = -1;
- }
-
- (void)nread; /* Unused */
- return ftp_code;
-}
-
-/* Read |len| from the socket |fd| and store it in |to|. Return a CURLcode
- saying whether an error occurred or CURLE_OK if |len| was read. */
-static CURLcode
-socket_read(curl_socket_t fd, void *to, size_t len)
-{
- char *to_p = to;
- CURLcode result;
- ssize_t nread = 0;
-
- while(len > 0) {
- result = Curl_read_plain(fd, to_p, len, &nread);
- if(!result) {
- len -= nread;
- to_p += nread;
- }
- else {
- if(result == CURLE_AGAIN)
- continue;
- return result;
- }
- }
- return CURLE_OK;
-}
-
-
-/* Write |len| bytes from the buffer |to| to the socket |fd|. Return a
- CURLcode saying whether an error occurred or CURLE_OK if |len| was
- written. */
-static CURLcode
-socket_write(struct connectdata *conn, curl_socket_t fd, const void *to,
- size_t len)
-{
- const char *to_p = to;
- CURLcode result;
- ssize_t written;
-
- while(len > 0) {
- result = Curl_write_plain(conn, fd, to_p, len, &written);
- if(!result) {
- len -= written;
- to_p += written;
- }
- else {
- if(result == CURLE_AGAIN)
- continue;
- return result;
- }
- }
- return CURLE_OK;
-}
-
-static CURLcode read_data(struct connectdata *conn,
- curl_socket_t fd,
- struct krb5buffer *buf)
-{
- int len;
- CURLcode result;
-
- result = socket_read(fd, &len, sizeof(len));
- if(result)
- return result;
-
- if(len) {
- /* only realloc if there was a length */
- len = ntohl(len);
- buf->data = Curl_saferealloc(buf->data, len);
- }
- if(!len || !buf->data)
- return CURLE_OUT_OF_MEMORY;
-
- result = socket_read(fd, buf->data, len);
- if(result)
- return result;
- buf->size = conn->mech->decode(conn->app_data, buf->data, len,
- conn->data_prot, conn);
- buf->index = 0;
- return CURLE_OK;
-}
-
-static size_t
-buffer_read(struct krb5buffer *buf, void *data, size_t len)
-{
- if(buf->size - buf->index < len)
- len = buf->size - buf->index;
- memcpy(data, (char *)buf->data + buf->index, len);
- buf->index += len;
- return len;
-}
-
-/* Matches Curl_recv signature */
-static ssize_t sec_recv(struct connectdata *conn, int sockindex,
- char *buffer, size_t len, CURLcode *err)
-{
- size_t bytes_read;
- size_t total_read = 0;
- curl_socket_t fd = conn->sock[sockindex];
-
- *err = CURLE_OK;
-
- /* Handle clear text response. */
- if(conn->sec_complete == 0 || conn->data_prot == PROT_CLEAR)
- return sread(fd, buffer, len);
-
- if(conn->in_buffer.eof_flag) {
- conn->in_buffer.eof_flag = 0;
- return 0;
- }
-
- bytes_read = buffer_read(&conn->in_buffer, buffer, len);
- len -= bytes_read;
- total_read += bytes_read;
- buffer += bytes_read;
-
- while(len > 0) {
- if(read_data(conn, fd, &conn->in_buffer))
- return -1;
- if(conn->in_buffer.size == 0) {
- if(bytes_read > 0)
- conn->in_buffer.eof_flag = 1;
- return bytes_read;
- }
- bytes_read = buffer_read(&conn->in_buffer, buffer, len);
- len -= bytes_read;
- total_read += bytes_read;
- buffer += bytes_read;
- }
- return total_read;
-}
-
-/* Send |length| bytes from |from| to the |fd| socket taking care of encoding
- and negotiating with the server. |from| can be NULL. */
-static void do_sec_send(struct connectdata *conn, curl_socket_t fd,
- const char *from, int length)
-{
- int bytes, htonl_bytes; /* 32-bit integers for htonl */
- char *buffer = NULL;
- char *cmd_buffer;
- size_t cmd_size = 0;
- CURLcode error;
- enum protection_level prot_level = conn->data_prot;
- bool iscmd = (prot_level == PROT_CMD)?TRUE:FALSE;
-
- DEBUGASSERT(prot_level > PROT_NONE && prot_level < PROT_LAST);
-
- if(iscmd) {
- if(!strncmp(from, "PASS ", 5) || !strncmp(from, "ACCT ", 5))
- prot_level = PROT_PRIVATE;
- else
- prot_level = conn->command_prot;
- }
- bytes = conn->mech->encode(conn->app_data, from, length, prot_level,
- (void **)&buffer);
- if(!buffer || bytes <= 0)
- return; /* error */
-
- if(iscmd) {
- error = Curl_base64_encode(conn->data, buffer, curlx_sitouz(bytes),
- &cmd_buffer, &cmd_size);
- if(error) {
- free(buffer);
- return; /* error */
- }
- if(cmd_size > 0) {
- static const char *enc = "ENC ";
- static const char *mic = "MIC ";
- if(prot_level == PROT_PRIVATE)
- socket_write(conn, fd, enc, 4);
- else
- socket_write(conn, fd, mic, 4);
-
- socket_write(conn, fd, cmd_buffer, cmd_size);
- socket_write(conn, fd, "\r\n", 2);
- infof(conn->data, "Send: %s%s\n", prot_level == PROT_PRIVATE?enc:mic,
- cmd_buffer);
- free(cmd_buffer);
- }
- }
- else {
- htonl_bytes = htonl(bytes);
- socket_write(conn, fd, &htonl_bytes, sizeof(htonl_bytes));
- socket_write(conn, fd, buffer, curlx_sitouz(bytes));
- }
- free(buffer);
-}
-
-static ssize_t sec_write(struct connectdata *conn, curl_socket_t fd,
- const char *buffer, size_t length)
-{
- ssize_t tx = 0, len = conn->buffer_size;
-
- len -= conn->mech->overhead(conn->app_data, conn->data_prot,
- curlx_sztosi(len));
- if(len <= 0)
- len = length;
- while(length) {
- if(length < (size_t)len)
- len = length;
-
- do_sec_send(conn, fd, buffer, curlx_sztosi(len));
- length -= len;
- buffer += len;
- tx += len;
- }
- return tx;
-}
-
-/* Matches Curl_send signature */
-static ssize_t sec_send(struct connectdata *conn, int sockindex,
- const void *buffer, size_t len, CURLcode *err)
-{
- curl_socket_t fd = conn->sock[sockindex];
- *err = CURLE_OK;
- return sec_write(conn, fd, buffer, len);
-}
-
-int Curl_sec_read_msg(struct connectdata *conn, char *buffer,
- enum protection_level level)
-{
- /* decoded_len should be size_t or ssize_t but conn->mech->decode returns an
- int */
- int decoded_len;
- char *buf;
- int ret_code = 0;
- size_t decoded_sz = 0;
- CURLcode error;
-
- if(!conn->mech)
- /* not inititalized, return error */
- return -1;
-
- DEBUGASSERT(level > PROT_NONE && level < PROT_LAST);
-
- error = Curl_base64_decode(buffer + 4, (unsigned char **)&buf, &decoded_sz);
- if(error || decoded_sz == 0)
- return -1;
-
- if(decoded_sz > (size_t)INT_MAX) {
- free(buf);
- return -1;
- }
- decoded_len = curlx_uztosi(decoded_sz);
-
- decoded_len = conn->mech->decode(conn->app_data, buf, decoded_len,
- level, conn);
- if(decoded_len <= 0) {
- free(buf);
- return -1;
- }
-
- if(conn->data->set.verbose) {
- buf[decoded_len] = '\n';
- Curl_debug(conn->data, CURLINFO_HEADER_IN, buf, decoded_len + 1);
- }
-
- buf[decoded_len] = '\0';
- if(decoded_len <= 3)
- /* suspiciously short */
- return 0;
-
- if(buf[3] != '-')
- /* safe to ignore return code */
- (void)sscanf(buf, "%d", &ret_code);
-
- if(buf[decoded_len - 1] == '\n')
- buf[decoded_len - 1] = '\0';
- strcpy(buffer, buf);
- free(buf);
- return ret_code;
-}
-
-static int sec_set_protection_level(struct connectdata *conn)
-{
- int code;
- enum protection_level level = conn->request_data_prot;
-
- DEBUGASSERT(level > PROT_NONE && level < PROT_LAST);
-
- if(!conn->sec_complete) {
- infof(conn->data, "Trying to change the protection level after the"
- " completion of the data exchange.\n");
- return -1;
- }
-
- /* Bail out if we try to set up the same level */
- if(conn->data_prot == level)
- return 0;
-
- if(level) {
- char *pbsz;
- static unsigned int buffer_size = 1 << 20; /* 1048576 */
-
- code = ftp_send_command(conn, "PBSZ %u", buffer_size);
- if(code < 0)
- return -1;
-
- if(code/100 != 2) {
- failf(conn->data, "Failed to set the protection's buffer size.");
- return -1;
- }
- conn->buffer_size = buffer_size;
-
- pbsz = strstr(conn->data->state.buffer, "PBSZ=");
- if(pbsz) {
- /* ignore return code, use default value if it fails */
- (void)sscanf(pbsz, "PBSZ=%u", &buffer_size);
- if(buffer_size < conn->buffer_size)
- conn->buffer_size = buffer_size;
- }
- }
-
- /* Now try to negiociate the protection level. */
- code = ftp_send_command(conn, "PROT %c", level_to_char(level));
-
- if(code < 0)
- return -1;
-
- if(code/100 != 2) {
- failf(conn->data, "Failed to set the protection level.");
- return -1;
- }
-
- conn->data_prot = level;
- if(level == PROT_PRIVATE)
- conn->command_prot = level;
-
- return 0;
-}
-
-int
-Curl_sec_request_prot(struct connectdata *conn, const char *level)
-{
- enum protection_level l = name_to_level(level);
- if(l == PROT_NONE)
- return -1;
- DEBUGASSERT(l > PROT_NONE && l < PROT_LAST);
- conn->request_data_prot = l;
- return 0;
-}
-
-static CURLcode choose_mech(struct connectdata *conn)
-{
- int ret;
- struct Curl_easy *data = conn->data;
- void *tmp_allocation;
- const struct Curl_sec_client_mech *mech = &Curl_krb5_client_mech;
-
- tmp_allocation = realloc(conn->app_data, mech->size);
- if(tmp_allocation == NULL) {
- failf(data, "Failed realloc of size %zu", mech->size);
- mech = NULL;
- return CURLE_OUT_OF_MEMORY;
- }
- conn->app_data = tmp_allocation;
-
- if(mech->init) {
- ret = mech->init(conn->app_data);
- if(ret) {
- infof(data, "Failed initialization for %s. Skipping it.\n",
- mech->name);
- return CURLE_FAILED_INIT;
- }
- }
-
- infof(data, "Trying mechanism %s...\n", mech->name);
- ret = ftp_send_command(conn, "AUTH %s", mech->name);
- if(ret < 0)
- return CURLE_COULDNT_CONNECT;
-
- if(ret/100 != 3) {
- switch(ret) {
- case 504:
- infof(data, "Mechanism %s is not supported by the server (server "
- "returned ftp code: 504).\n", mech->name);
- break;
- case 534:
- infof(data, "Mechanism %s was rejected by the server (server returned "
- "ftp code: 534).\n", mech->name);
- break;
- default:
- if(ret/100 == 5) {
- infof(data, "server does not support the security extensions\n");
- return CURLE_USE_SSL_FAILED;
- }
- break;
- }
- return CURLE_LOGIN_DENIED;
- }
-
- /* Authenticate */
- ret = mech->auth(conn->app_data, conn);
-
- if(ret != AUTH_CONTINUE) {
- if(ret != AUTH_OK) {
- /* Mechanism has dumped the error to stderr, don't error here. */
- return -1;
- }
- DEBUGASSERT(ret == AUTH_OK);
-
- conn->mech = mech;
- conn->sec_complete = 1;
- conn->recv[FIRSTSOCKET] = sec_recv;
- conn->send[FIRSTSOCKET] = sec_send;
- conn->recv[SECONDARYSOCKET] = sec_recv;
- conn->send[SECONDARYSOCKET] = sec_send;
- conn->command_prot = PROT_SAFE;
- /* Set the requested protection level */
- /* BLOCKING */
- (void)sec_set_protection_level(conn);
- }
-
- return CURLE_OK;
-}
-
-CURLcode
-Curl_sec_login(struct connectdata *conn)
-{
- return choose_mech(conn);
-}
-
-
-void
-Curl_sec_end(struct connectdata *conn)
-{
- if(conn->mech != NULL && conn->mech->end)
- conn->mech->end(conn->app_data);
- free(conn->app_data);
- conn->app_data = NULL;
- if(conn->in_buffer.data) {
- free(conn->in_buffer.data);
- conn->in_buffer.data = NULL;
- conn->in_buffer.size = 0;
- conn->in_buffer.index = 0;
- conn->in_buffer.eof_flag = 0;
- }
- conn->sec_complete = 0;
- conn->data_prot = PROT_CLEAR;
- conn->mech = NULL;
-}
-
-#endif /* HAVE_GSSAPI */
-
-#endif /* CURL_DISABLE_FTP */
diff --git a/Utilities/cmcurl/lib/select.c b/Utilities/cmcurl/lib/select.c
index 6832b428e..44fe22924 100644
--- a/Utilities/cmcurl/lib/select.c
+++ b/Utilities/cmcurl/lib/select.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -130,6 +130,7 @@ int Curl_wait_ms(timediff_t timeout_ms)
return r;
}
+#ifndef HAVE_POLL_FINE
/*
* This is a wrapper around select() to aid in Windows compatibility.
* A negative timeout value makes this function wait indefinitely,
@@ -141,23 +142,22 @@ int Curl_wait_ms(timediff_t timeout_ms)
* 0 = timeout
* N = number of signalled file descriptors
*/
-int Curl_select(curl_socket_t maxfd, /* highest socket number */
- fd_set *fds_read, /* sockets ready for reading */
- fd_set *fds_write, /* sockets ready for writing */
- fd_set *fds_err, /* sockets with errors */
- timediff_t timeout_ms) /* milliseconds to wait */
+static int our_select(curl_socket_t maxfd, /* highest socket number */
+ fd_set *fds_read, /* sockets ready for reading */
+ fd_set *fds_write, /* sockets ready for writing */
+ fd_set *fds_err, /* sockets with errors */
+ timediff_t timeout_ms) /* milliseconds to wait */
{
struct timeval pending_tv;
struct timeval *ptimeout;
- int r;
#ifdef USE_WINSOCK
/* WinSock select() can't handle zero events. See the comment below. */
if((!fds_read || fds_read->fd_count == 0) &&
(!fds_write || fds_write->fd_count == 0) &&
(!fds_err || fds_err->fd_count == 0)) {
- r = Curl_wait_ms(timeout_ms);
- return r;
+ /* no sockets, just wait */
+ return Curl_wait_ms(timeout_ms);
}
#endif
@@ -209,19 +209,20 @@ int Curl_select(curl_socket_t maxfd, /* highest socket number */
descriptor set must contain at least one handle to a socket.
It is unclear why WinSock doesn't just handle this for us instead of
- calling this an error.
+ calling this an error. Luckily, with WinSock, we can _also_ ask how
+ many bits are set on an fd_set. So, let's just check it beforehand.
*/
- r = select((int)maxfd + 1,
- fds_read && fds_read->fd_count ? fds_read : NULL,
- fds_write && fds_write->fd_count ? fds_write : NULL,
- fds_err && fds_err->fd_count ? fds_err : NULL, ptimeout);
+ return select((int)maxfd + 1,
+ fds_read && fds_read->fd_count ? fds_read : NULL,
+ fds_write && fds_write->fd_count ? fds_write : NULL,
+ fds_err && fds_err->fd_count ? fds_err : NULL, ptimeout);
#else
- r = select((int)maxfd + 1, fds_read, fds_write, fds_err, ptimeout);
+ return select((int)maxfd + 1, fds_read, fds_write, fds_err, ptimeout);
#endif
-
- return r;
}
+#endif
+
/*
* Wait for read or write events on a set of file descriptors. It uses poll()
* when a fine poll() is available, in order to avoid limits with FD_SETSIZE,
@@ -247,23 +248,14 @@ int Curl_socket_check(curl_socket_t readfd0, /* two sockets to read from */
curl_socket_t writefd, /* socket to write to */
timediff_t timeout_ms) /* milliseconds to wait */
{
-#ifdef HAVE_POLL_FINE
struct pollfd pfd[3];
int num;
-#else
- fd_set fds_read;
- fd_set fds_write;
- fd_set fds_err;
- curl_socket_t maxfd;
-#endif
int r;
- int ret;
if((readfd0 == CURL_SOCKET_BAD) && (readfd1 == CURL_SOCKET_BAD) &&
(writefd == CURL_SOCKET_BAD)) {
/* no sockets, just wait */
- r = Curl_wait_ms(timeout_ms);
- return r;
+ return Curl_wait_ms(timeout_ms);
}
/* Avoid initial timestamp, avoid Curl_now() call, when elapsed
@@ -271,8 +263,6 @@ int Curl_socket_check(curl_socket_t readfd0, /* two sockets to read from */
when function is called with a zero timeout or a negative timeout
value indicating a blocking call should be performed. */
-#ifdef HAVE_POLL_FINE
-
num = 0;
if(readfd0 != CURL_SOCKET_BAD) {
pfd[num].fd = readfd0;
@@ -288,7 +278,7 @@ int Curl_socket_check(curl_socket_t readfd0, /* two sockets to read from */
}
if(writefd != CURL_SOCKET_BAD) {
pfd[num].fd = writefd;
- pfd[num].events = POLLWRNORM|POLLOUT;
+ pfd[num].events = POLLWRNORM|POLLOUT|POLLPRI;
pfd[num].revents = 0;
num++;
}
@@ -297,101 +287,30 @@ int Curl_socket_check(curl_socket_t readfd0, /* two sockets to read from */
if(r <= 0)
return r;
- ret = 0;
+ r = 0;
num = 0;
if(readfd0 != CURL_SOCKET_BAD) {
if(pfd[num].revents & (POLLRDNORM|POLLIN|POLLERR|POLLHUP))
- ret |= CURL_CSELECT_IN;
+ r |= CURL_CSELECT_IN;
if(pfd[num].revents & (POLLRDBAND|POLLPRI|POLLNVAL))
- ret |= CURL_CSELECT_ERR;
+ r |= CURL_CSELECT_ERR;
num++;
}
if(readfd1 != CURL_SOCKET_BAD) {
if(pfd[num].revents & (POLLRDNORM|POLLIN|POLLERR|POLLHUP))
- ret |= CURL_CSELECT_IN2;
+ r |= CURL_CSELECT_IN2;
if(pfd[num].revents & (POLLRDBAND|POLLPRI|POLLNVAL))
- ret |= CURL_CSELECT_ERR;
+ r |= CURL_CSELECT_ERR;
num++;
}
if(writefd != CURL_SOCKET_BAD) {
if(pfd[num].revents & (POLLWRNORM|POLLOUT))
- ret |= CURL_CSELECT_OUT;
- if(pfd[num].revents & (POLLERR|POLLHUP|POLLNVAL))
- ret |= CURL_CSELECT_ERR;
- }
-
- return ret;
-
-#else /* HAVE_POLL_FINE */
-
- FD_ZERO(&fds_err);
- maxfd = (curl_socket_t)-1;
-
- FD_ZERO(&fds_read);
- if(readfd0 != CURL_SOCKET_BAD) {
- VERIFY_SOCK(readfd0);
- FD_SET(readfd0, &fds_read);
- FD_SET(readfd0, &fds_err);
- maxfd = readfd0;
- }
- if(readfd1 != CURL_SOCKET_BAD) {
- VERIFY_SOCK(readfd1);
- FD_SET(readfd1, &fds_read);
- FD_SET(readfd1, &fds_err);
- if(readfd1 > maxfd)
- maxfd = readfd1;
- }
-
- FD_ZERO(&fds_write);
- if(writefd != CURL_SOCKET_BAD) {
- VERIFY_SOCK(writefd);
- FD_SET(writefd, &fds_write);
- FD_SET(writefd, &fds_err);
- if(writefd > maxfd)
- maxfd = writefd;
- }
-
- /* We know that we have at least one bit set in at least two fd_sets in
- this case, but we may have no bits set in either fds_read or fd_write,
- so check for that and handle it. Luckily, with WinSock, we can _also_
- ask how many bits are set on an fd_set.
-
- Note also that WinSock ignores the first argument, so we don't worry
- about the fact that maxfd is computed incorrectly with WinSock (since
- curl_socket_t is unsigned in such cases and thus -1 is the largest
- value).
- */
- r = Curl_select(maxfd, &fds_read, &fds_write, &fds_err, timeout_ms);
-
- if(r < 0)
- return -1;
- if(r == 0)
- return 0;
-
- ret = 0;
- if(readfd0 != CURL_SOCKET_BAD) {
- if(FD_ISSET(readfd0, &fds_read))
- ret |= CURL_CSELECT_IN;
- if(FD_ISSET(readfd0, &fds_err))
- ret |= CURL_CSELECT_ERR;
+ r |= CURL_CSELECT_OUT;
+ if(pfd[num].revents & (POLLERR|POLLHUP|POLLPRI|POLLNVAL))
+ r |= CURL_CSELECT_ERR;
}
- if(readfd1 != CURL_SOCKET_BAD) {
- if(FD_ISSET(readfd1, &fds_read))
- ret |= CURL_CSELECT_IN2;
- if(FD_ISSET(readfd1, &fds_err))
- ret |= CURL_CSELECT_ERR;
- }
- if(writefd != CURL_SOCKET_BAD) {
- if(FD_ISSET(writefd, &fds_write))
- ret |= CURL_CSELECT_OUT;
- if(FD_ISSET(writefd, &fds_err))
- ret |= CURL_CSELECT_ERR;
- }
-
- return ret;
-
-#endif /* HAVE_POLL_FINE */
+ return r;
}
/*
@@ -431,8 +350,7 @@ int Curl_poll(struct pollfd ufds[], unsigned int nfds, timediff_t timeout_ms)
}
if(fds_none) {
/* no sockets, just wait */
- r = Curl_wait_ms(timeout_ms);
- return r;
+ return Curl_wait_ms(timeout_ms);
}
/* Avoid initial timestamp, avoid Curl_now() call, when elapsed
@@ -454,11 +372,8 @@ int Curl_poll(struct pollfd ufds[], unsigned int nfds, timediff_t timeout_ms)
else
pending_ms = 0;
r = poll(ufds, nfds, pending_ms);
-
- if(r < 0)
- return -1;
- if(r == 0)
- return 0;
+ if(r <= 0)
+ return r;
for(i = 0; i < nfds; i++) {
if(ufds[i].fd == CURL_SOCKET_BAD)
@@ -466,7 +381,7 @@ int Curl_poll(struct pollfd ufds[], unsigned int nfds, timediff_t timeout_ms)
if(ufds[i].revents & POLLHUP)
ufds[i].revents |= POLLIN;
if(ufds[i].revents & POLLERR)
- ufds[i].revents |= (POLLIN|POLLOUT);
+ ufds[i].revents |= POLLIN|POLLOUT;
}
#else /* HAVE_POLL_FINE */
@@ -482,7 +397,7 @@ int Curl_poll(struct pollfd ufds[], unsigned int nfds, timediff_t timeout_ms)
continue;
VERIFY_SOCK(ufds[i].fd);
if(ufds[i].events & (POLLIN|POLLOUT|POLLPRI|
- POLLRDNORM|POLLWRNORM|POLLRDBAND)) {
+ POLLRDNORM|POLLWRNORM|POLLRDBAND)) {
if(ufds[i].fd > maxfd)
maxfd = ufds[i].fd;
if(ufds[i].events & (POLLRDNORM|POLLIN))
@@ -494,24 +409,39 @@ int Curl_poll(struct pollfd ufds[], unsigned int nfds, timediff_t timeout_ms)
}
}
- r = Curl_select(maxfd, &fds_read, &fds_write, &fds_err, timeout_ms);
-
- if(r < 0)
- return -1;
- if(r == 0)
- return 0;
+ /*
+ Note also that WinSock ignores the first argument, so we don't worry
+ about the fact that maxfd is computed incorrectly with WinSock (since
+ curl_socket_t is unsigned in such cases and thus -1 is the largest
+ value).
+ */
+ r = our_select(maxfd, &fds_read, &fds_write, &fds_err, timeout_ms);
+ if(r <= 0)
+ return r;
r = 0;
for(i = 0; i < nfds; i++) {
ufds[i].revents = 0;
if(ufds[i].fd == CURL_SOCKET_BAD)
continue;
- if(FD_ISSET(ufds[i].fd, &fds_read))
- ufds[i].revents |= POLLIN;
- if(FD_ISSET(ufds[i].fd, &fds_write))
- ufds[i].revents |= POLLOUT;
- if(FD_ISSET(ufds[i].fd, &fds_err))
- ufds[i].revents |= POLLPRI;
+ if(FD_ISSET(ufds[i].fd, &fds_read)) {
+ if(ufds[i].events & POLLRDNORM)
+ ufds[i].revents |= POLLRDNORM;
+ if(ufds[i].events & POLLIN)
+ ufds[i].revents |= POLLIN;
+ }
+ if(FD_ISSET(ufds[i].fd, &fds_write)) {
+ if(ufds[i].events & POLLWRNORM)
+ ufds[i].revents |= POLLWRNORM;
+ if(ufds[i].events & POLLOUT)
+ ufds[i].revents |= POLLOUT;
+ }
+ if(FD_ISSET(ufds[i].fd, &fds_err)) {
+ if(ufds[i].events & POLLRDBAND)
+ ufds[i].revents |= POLLRDBAND;
+ if(ufds[i].events & POLLPRI)
+ ufds[i].revents |= POLLPRI;
+ }
if(ufds[i].revents != 0)
r++;
}
diff --git a/Utilities/cmcurl/lib/select.h b/Utilities/cmcurl/lib/select.h
index 95181f467..4db64877b 100644
--- a/Utilities/cmcurl/lib/select.h
+++ b/Utilities/cmcurl/lib/select.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -72,12 +72,6 @@ struct pollfd
therefore defined here */
#define CURL_CSELECT_IN2 (CURL_CSELECT_ERR << 1)
-int Curl_select(curl_socket_t maxfd,
- fd_set *fds_read,
- fd_set *fds_write,
- fd_set *fds_err,
- timediff_t timeout_ms);
-
int Curl_socket_check(curl_socket_t readfd, curl_socket_t readfd2,
curl_socket_t writefd,
timediff_t timeout_ms);
@@ -94,12 +88,23 @@ int tpf_select_libcurl(int maxfds, fd_set* reads, fd_set* writes,
fd_set* excepts, struct timeval *tv);
#endif
-/* Winsock and TPF sockets are not in range [0..FD_SETSIZE-1], which
+/* TPF sockets are not in range [0..FD_SETSIZE-1], which
unfortunately makes it impossible for us to easily check if they're valid
+
+ With Winsock the valid range is [0..INVALID_SOCKET-1] according to
+ https://docs.microsoft.com/en-us/windows/win32/winsock/socket-data-type-2
*/
-#if defined(USE_WINSOCK) || defined(TPF)
+#if defined(TPF)
#define VALID_SOCK(x) 1
#define VERIFY_SOCK(x) Curl_nop_stmt
+#elif defined(USE_WINSOCK)
+#define VALID_SOCK(s) ((s) < INVALID_SOCKET)
+#define VERIFY_SOCK(x) do { \
+ if(!VALID_SOCK(x)) { \
+ SET_SOCKERRNO(WSAEINVAL); \
+ return -1; \
+ } \
+} while(0)
#else
#define VALID_SOCK(s) (((s) >= 0) && ((s) < FD_SETSIZE))
#define VERIFY_SOCK(x) do { \
diff --git a/Utilities/cmcurl/lib/sendf.c b/Utilities/cmcurl/lib/sendf.c
index 6943fa84e..b3c7fe33d 100644
--- a/Utilities/cmcurl/lib/sendf.c
+++ b/Utilities/cmcurl/lib/sendf.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -28,6 +28,8 @@
#ifdef HAVE_LINUX_TCP_H
#include <linux/tcp.h>
+#elif defined(HAVE_NETINET_TCP_H)
+#include <netinet/tcp.h>
#endif
#include <curl/curl.h>
@@ -140,7 +142,8 @@ bool Curl_recv_has_postponed_data(struct connectdata *conn, int sockindex)
psnd->recv_size > psnd->recv_processed;
}
-static void pre_receive_plain(struct connectdata *conn, int num)
+static CURLcode pre_receive_plain(struct Curl_easy *data,
+ struct connectdata *conn, int num)
{
const curl_socket_t sockfd = conn->sock[num];
struct postponed_data * const psnd = &(conn->postponed[num]);
@@ -159,8 +162,10 @@ static void pre_receive_plain(struct connectdata *conn, int num)
/* Have some incoming data */
if(!psnd->buffer) {
/* Use buffer double default size for intermediate buffer */
- psnd->allocated_size = 2 * conn->data->set.buffer_size;
+ psnd->allocated_size = 2 * data->set.buffer_size;
psnd->buffer = malloc(psnd->allocated_size);
+ if(!psnd->buffer)
+ return CURLE_OUT_OF_MEMORY;
psnd->recv_size = 0;
psnd->recv_processed = 0;
#ifdef DEBUGBUILD
@@ -180,6 +185,7 @@ static void pre_receive_plain(struct connectdata *conn, int num)
psnd->allocated_size = 0;
}
}
+ return CURLE_OK;
}
static ssize_t get_pre_recved(struct connectdata *conn, int num, char *buf,
@@ -225,7 +231,7 @@ bool Curl_recv_has_postponed_data(struct connectdata *conn, int sockindex)
(void)sockindex;
return false;
}
-#define pre_receive_plain(c,n) do {} while(0)
+#define pre_receive_plain(d,c,n) CURLE_OK
#define get_pre_recved(c,n,b,l) 0
#endif /* ! USE_RECV_BEFORE_SEND_WORKAROUND */
@@ -262,6 +268,7 @@ void Curl_infof(struct Curl_easy *data, const char *fmt, ...)
void Curl_failf(struct Curl_easy *data, const char *fmt, ...)
{
+ DEBUGASSERT(!strchr(fmt, '\n'));
if(data->set.verbose || data->set.errorbuffer) {
va_list ap;
size_t len;
@@ -274,61 +281,12 @@ void Curl_failf(struct Curl_easy *data, const char *fmt, ...)
strcpy(data->set.errorbuffer, error);
data->state.errorbuf = TRUE; /* wrote error string */
}
- if(data->set.verbose) {
- error[len] = '\n';
- error[++len] = '\0';
- Curl_debug(data, CURLINFO_TEXT, error, len);
- }
+ error[len++] = '\n';
+ Curl_debug(data, CURLINFO_TEXT, error, len);
va_end(ap);
}
}
-/* Curl_sendf() sends formatted data to the server */
-CURLcode Curl_sendf(curl_socket_t sockfd, struct connectdata *conn,
- const char *fmt, ...)
-{
- struct Curl_easy *data = conn->data;
- ssize_t bytes_written;
- size_t write_len;
- CURLcode result = CURLE_OK;
- char *s;
- char *sptr;
- va_list ap;
- va_start(ap, fmt);
- s = vaprintf(fmt, ap); /* returns an allocated string */
- va_end(ap);
- if(!s)
- return CURLE_OUT_OF_MEMORY; /* failure */
-
- bytes_written = 0;
- write_len = strlen(s);
- sptr = s;
-
- for(;;) {
- /* Write the buffer to the socket */
- result = Curl_write(conn, sockfd, sptr, write_len, &bytes_written);
-
- if(result)
- break;
-
- if(data->set.verbose)
- Curl_debug(data, CURLINFO_DATA_OUT, sptr, (size_t)bytes_written);
-
- if((size_t)bytes_written != write_len) {
- /* if not all was written at once, we must advance the pointer, decrease
- the size left and try again! */
- write_len -= bytes_written;
- sptr += bytes_written;
- }
- else
- break;
- }
-
- free(s); /* free the output string */
-
- return result;
-}
-
/*
* Curl_write() is an internal write function that sends data to the
* server. Works with plain sockets, SCP, SSL or kerberos.
@@ -336,7 +294,7 @@ CURLcode Curl_sendf(curl_socket_t sockfd, struct connectdata *conn,
* If the write would block (CURLE_AGAIN), we return CURLE_OK and
* (*written == 0). Otherwise we return regular CURLcode value.
*/
-CURLcode Curl_write(struct connectdata *conn,
+CURLcode Curl_write(struct Curl_easy *data,
curl_socket_t sockfd,
const void *mem,
size_t len,
@@ -344,9 +302,14 @@ CURLcode Curl_write(struct connectdata *conn,
{
ssize_t bytes_written;
CURLcode result = CURLE_OK;
- int num = (sockfd == conn->sock[SECONDARYSOCKET]);
+ struct connectdata *conn;
+ int num;
+ DEBUGASSERT(data);
+ DEBUGASSERT(data->conn);
+ conn = data->conn;
+ num = (sockfd == conn->sock[SECONDARYSOCKET]);
- bytes_written = conn->send[num](conn, num, mem, len, &result);
+ bytes_written = conn->send[num](data, num, mem, len, &result);
*written = bytes_written;
if(bytes_written >= 0)
@@ -369,17 +332,26 @@ CURLcode Curl_write(struct connectdata *conn,
}
}
-ssize_t Curl_send_plain(struct connectdata *conn, int num,
+ssize_t Curl_send_plain(struct Curl_easy *data, int num,
const void *mem, size_t len, CURLcode *code)
{
- curl_socket_t sockfd = conn->sock[num];
+ struct connectdata *conn;
+ curl_socket_t sockfd;
ssize_t bytes_written;
+
+ DEBUGASSERT(data);
+ DEBUGASSERT(data->conn);
+ conn = data->conn;
+ sockfd = conn->sock[num];
/* WinSock will destroy unread received data if send() is
failed.
To avoid lossage of received data, recv() must be
performed before every send() if any incoming data is
available. */
- pre_receive_plain(conn, num);
+ if(pre_receive_plain(data, conn, num)) {
+ *code = CURLE_OUT_OF_MEMORY;
+ return -1;
+ }
#if defined(MSG_FASTOPEN) && !defined(TCP_FASTOPEN_CONNECT) /* Linux */
if(conn->bits.tcp_fastopen) {
@@ -413,9 +385,9 @@ ssize_t Curl_send_plain(struct connectdata *conn, int num,
}
else {
char buffer[STRERROR_LEN];
- failf(conn->data, "Send failure: %s",
+ failf(data, "Send failure: %s",
Curl_strerror(err, buffer, sizeof(buffer)));
- conn->data->state.os_errno = err;
+ data->state.os_errno = err;
*code = CURLE_SEND_ERROR;
}
}
@@ -427,28 +399,33 @@ ssize_t Curl_send_plain(struct connectdata *conn, int num,
* server using plain sockets only. Otherwise meant to have the exact same
* proto as Curl_write()
*/
-CURLcode Curl_write_plain(struct connectdata *conn,
+CURLcode Curl_write_plain(struct Curl_easy *data,
curl_socket_t sockfd,
const void *mem,
size_t len,
ssize_t *written)
{
- ssize_t bytes_written;
CURLcode result;
- int num = (sockfd == conn->sock[SECONDARYSOCKET]);
+ struct connectdata *conn = data->conn;
+ int num;
+ DEBUGASSERT(conn);
+ num = (sockfd == conn->sock[SECONDARYSOCKET]);
- bytes_written = Curl_send_plain(conn, num, mem, len, &result);
-
- *written = bytes_written;
+ *written = Curl_send_plain(data, num, mem, len, &result);
return result;
}
-ssize_t Curl_recv_plain(struct connectdata *conn, int num, char *buf,
+ssize_t Curl_recv_plain(struct Curl_easy *data, int num, char *buf,
size_t len, CURLcode *code)
{
- curl_socket_t sockfd = conn->sock[num];
+ struct connectdata *conn;
+ curl_socket_t sockfd;
ssize_t nread;
+ DEBUGASSERT(data);
+ DEBUGASSERT(data->conn);
+ conn = data->conn;
+ sockfd = conn->sock[num];
/* Check and return data that already received and storied in internal
intermediate buffer */
nread = get_pre_recved(conn, num, buf, len);
@@ -479,9 +456,9 @@ ssize_t Curl_recv_plain(struct connectdata *conn, int num, char *buf,
}
else {
char buffer[STRERROR_LEN];
- failf(conn->data, "Recv failure: %s",
+ failf(data, "Recv failure: %s",
Curl_strerror(err, buffer, sizeof(buffer)));
- conn->data->state.os_errno = err;
+ data->state.os_errno = err;
*code = CURLE_RECV_ERROR;
}
}
@@ -540,12 +517,12 @@ static CURLcode pausewrite(struct Curl_easy *data,
* client write callback(s) and takes care of pause requests from the
* callbacks.
*/
-static CURLcode chop_write(struct connectdata *conn,
+static CURLcode chop_write(struct Curl_easy *data,
int type,
char *optr,
size_t olen)
{
- struct Curl_easy *data = conn->data;
+ struct connectdata *conn = data->conn;
curl_write_callback writeheader = NULL;
curl_write_callback writebody = NULL;
char *ptr = optr;
@@ -635,13 +612,12 @@ static CURLcode chop_write(struct connectdata *conn,
local character encoding. This is a problem and should be changed in
the future to leave the original data alone.
*/
-CURLcode Curl_client_write(struct connectdata *conn,
+CURLcode Curl_client_write(struct Curl_easy *data,
int type,
char *ptr,
size_t len)
{
- struct Curl_easy *data = conn->data;
-
+ struct connectdata *conn = data->conn;
if(0 == len)
len = strlen(ptr);
@@ -663,7 +639,7 @@ CURLcode Curl_client_write(struct connectdata *conn,
#endif /* CURL_DO_LINEEND_CONV */
}
- return chop_write(conn, type, ptr, len);
+ return chop_write(data, type, ptr, len);
}
CURLcode Curl_read_plain(curl_socket_t sockfd,
@@ -698,7 +674,7 @@ CURLcode Curl_read_plain(curl_socket_t sockfd,
*
* Returns a regular CURLcode value.
*/
-CURLcode Curl_read(struct connectdata *conn, /* connection data */
+CURLcode Curl_read(struct Curl_easy *data, /* transfer */
curl_socket_t sockfd, /* read from this socket */
char *buf, /* store read data here */
size_t sizerequested, /* max amount to read */
@@ -708,7 +684,7 @@ CURLcode Curl_read(struct connectdata *conn, /* connection data */
ssize_t nread = 0;
size_t bytesfromsocket = 0;
char *buffertofill = NULL;
- struct Curl_easy *data = conn->data;
+ struct connectdata *conn = data->conn;
/* Set 'num' to 0 or 1, depending on which socket that has been sent here.
If it is the second socket, we set num to 1. Otherwise to 0. This lets
@@ -720,7 +696,7 @@ CURLcode Curl_read(struct connectdata *conn, /* connection data */
bytesfromsocket = CURLMIN(sizerequested, (size_t)data->set.buffer_size);
buffertofill = buf;
- nread = conn->recv[num](conn, num, buffertofill, bytesfromsocket, &result);
+ nread = conn->recv[num](data, num, buffertofill, bytesfromsocket, &result);
if(nread < 0)
return result;
@@ -733,72 +709,74 @@ CURLcode Curl_read(struct connectdata *conn, /* connection data */
int Curl_debug(struct Curl_easy *data, curl_infotype type,
char *ptr, size_t size)
{
- static const char s_infotype[CURLINFO_END][3] = {
- "* ", "< ", "> ", "{ ", "} ", "{ ", "} " };
int rc = 0;
+ if(data->set.verbose) {
+ static const char s_infotype[CURLINFO_END][3] = {
+ "* ", "< ", "> ", "{ ", "} ", "{ ", "} " };
#ifdef CURL_DOES_CONVERSIONS
- char *buf = NULL;
- size_t conv_size = 0;
-
- switch(type) {
- case CURLINFO_HEADER_OUT:
- buf = Curl_memdup(ptr, size);
- if(!buf)
- return 1;
- conv_size = size;
-
- /* Special processing is needed for this block if it
- * contains both headers and data (separated by CRLFCRLF).
- * We want to convert just the headers, leaving the data as-is.
- */
- if(size > 4) {
- size_t i;
- for(i = 0; i < size-4; i++) {
- if(memcmp(&buf[i], "\x0d\x0a\x0d\x0a", 4) == 0) {
- /* convert everything through this CRLFCRLF but no further */
- conv_size = i + 4;
- break;
+ char *buf = NULL;
+ size_t conv_size = 0;
+
+ switch(type) {
+ case CURLINFO_HEADER_OUT:
+ buf = Curl_memdup(ptr, size);
+ if(!buf)
+ return 1;
+ conv_size = size;
+
+ /* Special processing is needed for this block if it
+ * contains both headers and data (separated by CRLFCRLF).
+ * We want to convert just the headers, leaving the data as-is.
+ */
+ if(size > 4) {
+ size_t i;
+ for(i = 0; i < size-4; i++) {
+ if(memcmp(&buf[i], "\x0d\x0a\x0d\x0a", 4) == 0) {
+ /* convert everything through this CRLFCRLF but no further */
+ conv_size = i + 4;
+ break;
+ }
}
}
- }
- Curl_convert_from_network(data, buf, conv_size);
- /* Curl_convert_from_network calls failf if unsuccessful */
- /* we might as well continue even if it fails... */
- ptr = buf; /* switch pointer to use my buffer instead */
- break;
- default:
- /* leave everything else as-is */
- break;
- }
+ Curl_convert_from_network(data, buf, conv_size);
+ /* Curl_convert_from_network calls failf if unsuccessful */
+ /* we might as well continue even if it fails... */
+ ptr = buf; /* switch pointer to use my buffer instead */
+ break;
+ default:
+ /* leave everything else as-is */
+ break;
+ }
#endif /* CURL_DOES_CONVERSIONS */
- if(data->set.fdebug) {
- Curl_set_in_callback(data, true);
- rc = (*data->set.fdebug)(data, type, ptr, size, data->set.debugdata);
- Curl_set_in_callback(data, false);
- }
- else {
- switch(type) {
- case CURLINFO_TEXT:
- case CURLINFO_HEADER_OUT:
- case CURLINFO_HEADER_IN:
- fwrite(s_infotype[type], 2, 1, data->set.err);
- fwrite(ptr, size, 1, data->set.err);
+ if(data->set.fdebug) {
+ Curl_set_in_callback(data, true);
+ rc = (*data->set.fdebug)(data, type, ptr, size, data->set.debugdata);
+ Curl_set_in_callback(data, false);
+ }
+ else {
+ switch(type) {
+ case CURLINFO_TEXT:
+ case CURLINFO_HEADER_OUT:
+ case CURLINFO_HEADER_IN:
+ fwrite(s_infotype[type], 2, 1, data->set.err);
+ fwrite(ptr, size, 1, data->set.err);
#ifdef CURL_DOES_CONVERSIONS
- if(size != conv_size) {
- /* we had untranslated data so we need an explicit newline */
- fwrite("\n", 1, 1, data->set.err);
- }
+ if(size != conv_size) {
+ /* we had untranslated data so we need an explicit newline */
+ fwrite("\n", 1, 1, data->set.err);
+ }
#endif
- break;
- default: /* nada */
- break;
+ break;
+ default: /* nada */
+ break;
+ }
}
- }
#ifdef CURL_DOES_CONVERSIONS
- free(buf);
+ free(buf);
#endif
+ }
return rc;
}
diff --git a/Utilities/cmcurl/lib/sendf.h b/Utilities/cmcurl/lib/sendf.h
index c68b017da..108a5e934 100644
--- a/Utilities/cmcurl/lib/sendf.h
+++ b/Utilities/cmcurl/lib/sendf.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -24,8 +24,6 @@
#include "curl_setup.h"
-CURLcode Curl_sendf(curl_socket_t sockfd, struct connectdata *,
- const char *fmt, ...);
void Curl_infof(struct Curl_easy *, const char *fmt, ...);
void Curl_failf(struct Curl_easy *, const char *fmt, ...);
@@ -51,7 +49,7 @@ void Curl_failf(struct Curl_easy *, const char *fmt, ...);
#define CLIENTWRITE_HEADER (1<<1)
#define CLIENTWRITE_BOTH (CLIENTWRITE_BODY|CLIENTWRITE_HEADER)
-CURLcode Curl_client_write(struct connectdata *conn, int type, char *ptr,
+CURLcode Curl_client_write(struct Curl_easy *data, int type, char *ptr,
size_t len) WARN_UNUSED_RESULT;
bool Curl_recv_has_postponed_data(struct connectdata *conn, int sockindex);
@@ -62,23 +60,24 @@ CURLcode Curl_read_plain(curl_socket_t sockfd,
size_t bytesfromsocket,
ssize_t *n);
-ssize_t Curl_recv_plain(struct connectdata *conn, int num, char *buf,
+ssize_t Curl_recv_plain(struct Curl_easy *data, int num, char *buf,
size_t len, CURLcode *code);
-ssize_t Curl_send_plain(struct connectdata *conn, int num,
+ssize_t Curl_send_plain(struct Curl_easy *data, int num,
const void *mem, size_t len, CURLcode *code);
/* internal read-function, does plain socket, SSL and krb4 */
-CURLcode Curl_read(struct connectdata *conn, curl_socket_t sockfd,
+CURLcode Curl_read(struct Curl_easy *data, curl_socket_t sockfd,
char *buf, size_t buffersize,
ssize_t *n);
+
/* internal write-function, does plain socket, SSL, SCP, SFTP and krb4 */
-CURLcode Curl_write(struct connectdata *conn,
+CURLcode Curl_write(struct Curl_easy *data,
curl_socket_t sockfd,
const void *mem, size_t len,
ssize_t *written);
/* internal write-function, does plain sockets ONLY */
-CURLcode Curl_write_plain(struct connectdata *conn,
+CURLcode Curl_write_plain(struct Curl_easy *data,
curl_socket_t sockfd,
const void *mem, size_t len,
ssize_t *written);
diff --git a/Utilities/cmcurl/lib/setopt.c b/Utilities/cmcurl/lib/setopt.c
index d6213357c..ce73a34a7 100644
--- a/Utilities/cmcurl/lib/setopt.c
+++ b/Utilities/cmcurl/lib/setopt.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -30,6 +30,8 @@
#ifdef HAVE_LINUX_TCP_H
#include <linux/tcp.h>
+#elif defined(HAVE_NETINET_TCP_H)
+#include <netinet/tcp.h>
#endif
#include "urldata.h"
@@ -45,6 +47,7 @@
#include "setopt.h"
#include "multiif.h"
#include "altsvc.h"
+#include "hsts.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
@@ -271,11 +274,13 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
* Do not include the body part in the output data stream.
*/
data->set.opt_no_body = (0 != va_arg(param, long)) ? TRUE : FALSE;
+#ifndef CURL_DISABLE_HTTP
if(data->set.opt_no_body)
/* in HTTP lingo, no body means using the HEAD request... */
data->set.method = HTTPREQ_HEAD;
else if(data->set.method == HTTPREQ_HEAD)
data->set.method = HTTPREQ_GET;
+#endif
break;
case CURLOPT_FAILONERROR:
/*
@@ -430,104 +435,12 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
primary->version_max = version_max;
}
#else
- result = CURLE_UNKNOWN_OPTION;
+ result = CURLE_NOT_BUILT_IN;
#endif
break;
-#ifndef CURL_DISABLE_HTTP
- case CURLOPT_AUTOREFERER:
- /*
- * Switch on automatic referer that gets set if curl follows locations.
- */
- data->set.http_auto_referer = (0 != va_arg(param, long)) ? TRUE : FALSE;
- break;
-
- case CURLOPT_ACCEPT_ENCODING:
- /*
- * String to use at the value of Accept-Encoding header.
- *
- * If the encoding is set to "" we use an Accept-Encoding header that
- * encompasses all the encodings we support.
- * If the encoding is set to NULL we don't send an Accept-Encoding header
- * and ignore an received Content-Encoding header.
- *
- */
- argptr = va_arg(param, char *);
- if(argptr && !*argptr) {
- argptr = Curl_all_content_encodings();
- if(!argptr)
- result = CURLE_OUT_OF_MEMORY;
- else {
- result = Curl_setstropt(&data->set.str[STRING_ENCODING], argptr);
- free(argptr);
- }
- }
- else
- result = Curl_setstropt(&data->set.str[STRING_ENCODING], argptr);
- break;
-
- case CURLOPT_TRANSFER_ENCODING:
- data->set.http_transfer_encoding = (0 != va_arg(param, long)) ?
- TRUE : FALSE;
- break;
-
- case CURLOPT_FOLLOWLOCATION:
- /*
- * Follow Location: header hints on a HTTP-server.
- */
- data->set.http_follow_location = (0 != va_arg(param, long)) ? TRUE : FALSE;
- break;
-
- case CURLOPT_UNRESTRICTED_AUTH:
- /*
- * Send authentication (user+password) when following locations, even when
- * hostname changed.
- */
- data->set.allow_auth_to_other_hosts =
- (0 != va_arg(param, long)) ? TRUE : FALSE;
- break;
-
- case CURLOPT_MAXREDIRS:
- /*
- * The maximum amount of hops you allow curl to follow Location:
- * headers. This should mostly be used to detect never-ending loops.
- */
- arg = va_arg(param, long);
- if(arg < -1)
- return CURLE_BAD_FUNCTION_ARGUMENT;
- data->set.maxredirs = arg;
- break;
-
- case CURLOPT_POSTREDIR:
- /*
- * Set the behaviour of POST when redirecting
- * CURL_REDIR_GET_ALL - POST is changed to GET after 301 and 302
- * CURL_REDIR_POST_301 - POST is kept as POST after 301
- * CURL_REDIR_POST_302 - POST is kept as POST after 302
- * CURL_REDIR_POST_303 - POST is kept as POST after 303
- * CURL_REDIR_POST_ALL - POST is kept as POST after 301, 302 and 303
- * other - POST is kept as POST after 301 and 302
- */
- arg = va_arg(param, long);
- if(arg < CURL_REDIR_GET_ALL)
- /* no return error on too high numbers since the bitmask could be
- extended in a future */
- return CURLE_BAD_FUNCTION_ARGUMENT;
- data->set.keep_post = arg & CURL_REDIR_POST_ALL;
- break;
-
- case CURLOPT_POST:
- /* Does this option serve a purpose anymore? Yes it does, when
- CURLOPT_POSTFIELDS isn't used and the POST data is read off the
- callback! */
- if(va_arg(param, long)) {
- data->set.method = HTTPREQ_POST;
- data->set.opt_no_body = FALSE; /* this is implied */
- }
- else
- data->set.method = HTTPREQ_GET;
- break;
-
+ /* MQTT "borrows" some of the HTTP options */
+#if !defined(CURL_DISABLE_HTTP) || !defined(CURL_DISABLE_MQTT)
case CURLOPT_COPYPOSTFIELDS:
/*
* A string with POST data. Makes curl HTTP POST. Even if it is NULL.
@@ -622,6 +535,100 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
data->set.postfieldsize = bigsize;
break;
+#endif
+#ifndef CURL_DISABLE_HTTP
+ case CURLOPT_AUTOREFERER:
+ /*
+ * Switch on automatic referer that gets set if curl follows locations.
+ */
+ data->set.http_auto_referer = (0 != va_arg(param, long)) ? TRUE : FALSE;
+ break;
+
+ case CURLOPT_ACCEPT_ENCODING:
+ /*
+ * String to use at the value of Accept-Encoding header.
+ *
+ * If the encoding is set to "" we use an Accept-Encoding header that
+ * encompasses all the encodings we support.
+ * If the encoding is set to NULL we don't send an Accept-Encoding header
+ * and ignore an received Content-Encoding header.
+ *
+ */
+ argptr = va_arg(param, char *);
+ if(argptr && !*argptr) {
+ argptr = Curl_all_content_encodings();
+ if(!argptr)
+ result = CURLE_OUT_OF_MEMORY;
+ else {
+ result = Curl_setstropt(&data->set.str[STRING_ENCODING], argptr);
+ free(argptr);
+ }
+ }
+ else
+ result = Curl_setstropt(&data->set.str[STRING_ENCODING], argptr);
+ break;
+
+ case CURLOPT_TRANSFER_ENCODING:
+ data->set.http_transfer_encoding = (0 != va_arg(param, long)) ?
+ TRUE : FALSE;
+ break;
+
+ case CURLOPT_FOLLOWLOCATION:
+ /*
+ * Follow Location: header hints on a HTTP-server.
+ */
+ data->set.http_follow_location = (0 != va_arg(param, long)) ? TRUE : FALSE;
+ break;
+
+ case CURLOPT_UNRESTRICTED_AUTH:
+ /*
+ * Send authentication (user+password) when following locations, even when
+ * hostname changed.
+ */
+ data->set.allow_auth_to_other_hosts =
+ (0 != va_arg(param, long)) ? TRUE : FALSE;
+ break;
+
+ case CURLOPT_MAXREDIRS:
+ /*
+ * The maximum amount of hops you allow curl to follow Location:
+ * headers. This should mostly be used to detect never-ending loops.
+ */
+ arg = va_arg(param, long);
+ if(arg < -1)
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ data->set.maxredirs = arg;
+ break;
+
+ case CURLOPT_POSTREDIR:
+ /*
+ * Set the behavior of POST when redirecting
+ * CURL_REDIR_GET_ALL - POST is changed to GET after 301 and 302
+ * CURL_REDIR_POST_301 - POST is kept as POST after 301
+ * CURL_REDIR_POST_302 - POST is kept as POST after 302
+ * CURL_REDIR_POST_303 - POST is kept as POST after 303
+ * CURL_REDIR_POST_ALL - POST is kept as POST after 301, 302 and 303
+ * other - POST is kept as POST after 301 and 302
+ */
+ arg = va_arg(param, long);
+ if(arg < CURL_REDIR_GET_ALL)
+ /* no return error on too high numbers since the bitmask could be
+ extended in a future */
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ data->set.keep_post = arg & CURL_REDIR_POST_ALL;
+ break;
+
+ case CURLOPT_POST:
+ /* Does this option serve a purpose anymore? Yes it does, when
+ CURLOPT_POSTFIELDS isn't used and the POST data is read off the
+ callback! */
+ if(va_arg(param, long)) {
+ data->set.method = HTTPREQ_POST;
+ data->set.opt_no_body = FALSE; /* this is implied */
+ }
+ else
+ data->set.method = HTTPREQ_GET;
+ break;
case CURLOPT_HTTPPOST:
/*
@@ -631,6 +638,21 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
data->set.method = HTTPREQ_POST_FORM;
data->set.opt_no_body = FALSE; /* this is implied */
break;
+
+ case CURLOPT_AWS_SIGV4:
+ /*
+ * String that is merged to some authentication
+ * parameters are used by the algorithm.
+ */
+ result = Curl_setstropt(&data->set.str[STRING_AWS_SIGV4],
+ va_arg(param, char *));
+ /*
+ * Basic been set by default it need to be unset here
+ */
+ if(data->set.str[STRING_AWS_SIGV4])
+ data->set.httpauth = CURLAUTH_AWS_SIGV4;
+ break;
+
#endif /* CURL_DISABLE_HTTP */
case CURLOPT_MIMEPOST:
@@ -720,6 +742,9 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
argptr = (char *)va_arg(param, void *);
if(argptr) {
struct curl_slist *cl;
+ /* general protection against mistakes and abuse */
+ if(strlen(argptr) > CURL_MAX_INPUT_LENGTH)
+ return CURLE_BAD_FUNCTION_ARGUMENT;
/* append the cookie file name to the list of file names, and deal with
them later */
cl = curl_slist_append(data->change.cookielist, argptr);
@@ -804,6 +829,9 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
/* if cookie engine was not running, activate it */
data->cookies = Curl_cookie_init(data, NULL, NULL, TRUE);
+ /* general protection against mistakes and abuse */
+ if(strlen(argptr) > CURL_MAX_INPUT_LENGTH)
+ return CURLE_BAD_FUNCTION_ARGUMENT;
argptr = strdup(argptr);
if(!argptr || !data->cookies) {
result = CURLE_OUT_OF_MEMORY;
@@ -854,7 +882,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
;
else
#endif
-#ifndef USE_NGHTTP2
+#if !defined(USE_NGHTTP2) && !defined(USE_HYPER)
if(arg >= CURL_HTTP_VERSION_2)
return CURLE_UNSUPPORTED_PROTOCOL;
#else
@@ -1069,7 +1097,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
break;
default:
/* reserve other values for future use */
- result = CURLE_UNKNOWN_OPTION;
+ result = CURLE_BAD_FUNCTION_ARGUMENT;
break;
}
break;
@@ -1222,21 +1250,13 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
* An FTP/SFTP option that modifies an upload to create missing
* directories on the server.
*/
- switch(va_arg(param, long)) {
- case 0:
- data->set.ftp_create_missing_dirs = 0;
- break;
- case 1:
- data->set.ftp_create_missing_dirs = 1;
- break;
- case 2:
- data->set.ftp_create_missing_dirs = 2;
- break;
- default:
- /* reserve other values for future use */
- result = CURLE_UNKNOWN_OPTION;
- break;
- }
+ arg = va_arg(param, long);
+ /* reserve other values for future use */
+ if((arg < CURLFTP_CREATE_DIR_NONE) ||
+ (arg > CURLFTP_CREATE_DIR_RETRY))
+ result = CURLE_BAD_FUNCTION_ARGUMENT;
+ else
+ data->set.ftp_create_missing_dirs = (int)arg;
break;
case CURLOPT_READDATA:
/*
@@ -1441,13 +1461,16 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
break;
case CURLOPT_RESOLVE:
/*
- * List of NAME:[address] names to populate the DNS cache with
- * Prefix the NAME with dash (-) to _remove_ the name from the cache.
- *
- * Names added with this API will remain in the cache until explicitly
+ * List of HOST:PORT:[addresses] strings to populate the DNS cache with
+ * Entries added this way will remain in the cache until explicitly
* removed or the handle is cleaned up.
*
- * This API can remove any name from the DNS cache, but only entries
+ * Prefix the HOST with plus sign (+) to have the entry expire just like
+ * automatically added entries.
+ *
+ * Prefix the HOST with dash (-) to _remove_ the entry from the cache.
+ *
+ * This API can remove any entry from the DNS cache, but only entries
* that aren't actually in use right now will be pruned immediately.
*/
data->set.resolve = va_arg(param, struct curl_slist *);
@@ -2075,6 +2098,9 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
* The application kindly asks for a differently sized receive buffer.
* If it seems reasonable, we'll use it.
*/
+ if(data->state.buffer)
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+
arg = va_arg(param, long);
if(arg > READBUFFER_MAX)
@@ -2084,18 +2110,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
else if(arg < READBUFFER_MIN)
arg = READBUFFER_MIN;
- /* Resize if new size */
- if((arg != data->set.buffer_size) && data->state.buffer) {
- char *newbuff = realloc(data->state.buffer, arg + 1);
- if(!newbuff) {
- DEBUGF(fprintf(stderr, "Error: realloc of buffer failed\n"));
- result = CURLE_OUT_OF_MEMORY;
- }
- else
- data->state.buffer = newbuff;
- }
data->set.buffer_size = arg;
-
break;
case CURLOPT_UPLOAD_BUFFERSIZE:
@@ -2155,8 +2170,9 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
data->share = NULL;
}
- /* use new share if it set */
- data->share = set;
+ if(GOOD_SHARE_HANDLE(set))
+ /* use new share if it set */
+ data->share = set;
if(data->share) {
Curl_share_lock(data, CURL_LOCK_DATA_SHARE, CURL_LOCK_ACCESS_SINGLE);
@@ -2243,12 +2259,20 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
break;
#endif
+ case CURLOPT_SSL_EC_CURVES:
+ /*
+ * Set accepted curves in SSL connection setup.
+ * Specify colon-delimited list of curve algorithm names.
+ */
+ result = Curl_setstropt(&data->set.str[STRING_SSL_EC_CURVES],
+ va_arg(param, char *));
+ break;
#endif
case CURLOPT_IPRESOLVE:
arg = va_arg(param, long);
if((arg < CURL_IPRESOLVE_WHATEVER) || (arg > CURL_IPRESOLVE_V6))
return CURLE_BAD_FUNCTION_ARGUMENT;
- data->set.ipver = arg;
+ data->set.ipver = (unsigned char) arg;
break;
case CURLOPT_MAXFILESIZE_LARGE:
@@ -2513,9 +2537,9 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
* Set the RTSP request method (OPTIONS, SETUP, PLAY, etc...)
* Would this be better if the RTSPREQ_* were just moved into here?
*/
- long curl_rtspreq = va_arg(param, long);
+ long in_rtspreq = va_arg(param, long);
Curl_RtspReq rtspreq = RTSPREQ_NONE;
- switch(curl_rtspreq) {
+ switch(in_rtspreq) {
case CURL_RTSPREQ_OPTIONS:
rtspreq = RTSPREQ_OPTIONS;
break;
@@ -2839,7 +2863,46 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
data->set.trailer_data = va_arg(param, void *);
#endif
break;
-#ifdef USE_ALTSVC
+#ifdef USE_HSTS
+ case CURLOPT_HSTSREADFUNCTION:
+ data->set.hsts_read = va_arg(param, curl_hstsread_callback);
+ break;
+ case CURLOPT_HSTSREADDATA:
+ data->set.hsts_read_userp = va_arg(param, void *);
+ break;
+ case CURLOPT_HSTSWRITEFUNCTION:
+ data->set.hsts_write = va_arg(param, curl_hstswrite_callback);
+ break;
+ case CURLOPT_HSTSWRITEDATA:
+ data->set.hsts_write_userp = va_arg(param, void *);
+ break;
+ case CURLOPT_HSTS:
+ if(!data->hsts) {
+ data->hsts = Curl_hsts_init();
+ if(!data->hsts)
+ return CURLE_OUT_OF_MEMORY;
+ }
+ argptr = va_arg(param, char *);
+ result = Curl_setstropt(&data->set.str[STRING_HSTS], argptr);
+ if(result)
+ return result;
+ if(argptr)
+ (void)Curl_hsts_loadfile(data, data->hsts, argptr);
+ break;
+ case CURLOPT_HSTS_CTRL:
+ arg = va_arg(param, long);
+ if(arg & CURLHSTS_ENABLE) {
+ if(!data->hsts) {
+ data->hsts = Curl_hsts_init();
+ if(!data->hsts)
+ return CURLE_OUT_OF_MEMORY;
+ }
+ }
+ else
+ Curl_hsts_cleanup(&data->hsts);
+ break;
+#endif
+#ifndef CURL_DISABLE_ALTSVC
case CURLOPT_ALTSVC:
if(!data->asi) {
data->asi = Curl_altsvc_init();
diff --git a/Utilities/cmcurl/lib/setopt.h b/Utilities/cmcurl/lib/setopt.h
index 5fc4368dc..affbfd996 100644
--- a/Utilities/cmcurl/lib/setopt.h
+++ b/Utilities/cmcurl/lib/setopt.h
@@ -11,7 +11,7 @@
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/setup-os400.h b/Utilities/cmcurl/lib/setup-os400.h
index b693cb3b3..8c97371e4 100644
--- a/Utilities/cmcurl/lib/setup-os400.h
+++ b/Utilities/cmcurl/lib/setup-os400.h
@@ -11,7 +11,7 @@
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/setup-vms.h b/Utilities/cmcurl/lib/setup-vms.h
index 0e39c9f6b..ba75dc295 100644
--- a/Utilities/cmcurl/lib/setup-vms.h
+++ b/Utilities/cmcurl/lib/setup-vms.h
@@ -11,7 +11,7 @@
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/setup-win32.h b/Utilities/cmcurl/lib/setup-win32.h
index 45b584766..c35dec88c 100644
--- a/Utilities/cmcurl/lib/setup-win32.h
+++ b/Utilities/cmcurl/lib/setup-win32.h
@@ -11,7 +11,7 @@
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -60,7 +60,6 @@
/*
* Define USE_WINSOCK to 2 if we have and use WINSOCK2 API, else
- * define USE_WINSOCK to 1 if we have and use WINSOCK API, else
* undefine USE_WINSOCK.
*/
@@ -70,7 +69,7 @@
# define USE_WINSOCK 2
#else
# ifdef HAVE_WINSOCK_H
-# define USE_WINSOCK 1
+# error "WinSock version 1 is no longer supported, version 2 is required!"
# endif
#endif
diff --git a/Utilities/cmcurl/lib/sha256.c b/Utilities/cmcurl/lib/sha256.c
index ee5d273c4..d91511791 100644
--- a/Utilities/cmcurl/lib/sha256.c
+++ b/Utilities/cmcurl/lib/sha256.c
@@ -10,7 +10,7 @@
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -27,6 +27,7 @@
#include "warnless.h"
#include "curl_sha256.h"
+#include "curl_hmac.h"
#if defined(USE_OPENSSL)
@@ -343,11 +344,14 @@ static int sha256_compress(struct sha256_state *md,
}
/* Compress */
-#define RND(a,b,c,d,e,f,g,h,i) \
- unsigned long t0 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i]; \
- unsigned long t1 = Sigma0(a) + Maj(a, b, c); \
- d += t0; \
- h = t0 + t1;
+#define RND(a,b,c,d,e,f,g,h,i) \
+ do { \
+ unsigned long t0 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i]; \
+ unsigned long t1 = Sigma0(a) + Maj(a, b, c); \
+ d += t0; \
+ h = t0 + t1; \
+ } while(0)
+
for(i = 0; i < 64; ++i) {
unsigned long t;
RND(S[0], S[1], S[2], S[3], S[4], S[5], S[6], S[7], i);
@@ -491,4 +495,23 @@ void Curl_sha256it(unsigned char *output, const unsigned char *input,
SHA256_Final(output, &ctx);
}
+
+const struct HMAC_params Curl_HMAC_SHA256[] = {
+ {
+ /* Hash initialization function. */
+ CURLX_FUNCTION_CAST(HMAC_hinit_func, SHA256_Init),
+ /* Hash update function. */
+ CURLX_FUNCTION_CAST(HMAC_hupdate_func, SHA256_Update),
+ /* Hash computation end function. */
+ CURLX_FUNCTION_CAST(HMAC_hfinal_func, SHA256_Final),
+ /* Size of hash context structure. */
+ sizeof(SHA256_CTX),
+ /* Maximum key length. */
+ 64,
+ /* Result size. */
+ 32
+ }
+};
+
+
#endif /* CURL_DISABLE_CRYPTO_AUTH */
diff --git a/Utilities/cmcurl/lib/share.c b/Utilities/cmcurl/lib/share.c
index a2d896042..4f1804dbd 100644
--- a/Utilities/cmcurl/lib/share.c
+++ b/Utilities/cmcurl/lib/share.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -37,6 +37,7 @@ curl_share_init(void)
{
struct Curl_share *share = calloc(1, sizeof(struct Curl_share));
if(share) {
+ share->magic = CURL_GOOD_SHARE;
share->specifier |= (1<<CURL_LOCK_DATA_SHARE);
if(Curl_mk_dnscache(&share->hostcache)) {
@@ -59,6 +60,9 @@ curl_share_setopt(struct Curl_share *share, CURLSHoption option, ...)
void *ptr;
CURLSHcode res = CURLSHE_OK;
+ if(!GOOD_SHARE_HANDLE(share))
+ return CURLSHE_INVALID;
+
if(share->dirty)
/* don't allow setting options while one or more handles are already
using this share */
@@ -92,7 +96,7 @@ curl_share_setopt(struct Curl_share *share, CURLSHoption option, ...)
if(!share->sslsession) {
share->max_ssl_sessions = 8;
share->sslsession = calloc(share->max_ssl_sessions,
- sizeof(struct curl_ssl_session));
+ sizeof(struct Curl_ssl_session));
share->sessionage = 0;
if(!share->sslsession)
res = CURLSHE_NOMEM;
@@ -184,7 +188,7 @@ curl_share_setopt(struct Curl_share *share, CURLSHoption option, ...)
CURLSHcode
curl_share_cleanup(struct Curl_share *share)
{
- if(share == NULL)
+ if(!GOOD_SHARE_HANDLE(share))
return CURLSHE_INVALID;
if(share->lockfunc)
@@ -218,6 +222,7 @@ curl_share_cleanup(struct Curl_share *share)
if(share->unlockfunc)
share->unlockfunc(NULL, CURL_LOCK_DATA_SHARE, share->clientdata);
+ share->magic = 0;
free(share);
return CURLSHE_OK;
diff --git a/Utilities/cmcurl/lib/share.h b/Utilities/cmcurl/lib/share.h
index a7dea41ad..222e34ba6 100644
--- a/Utilities/cmcurl/lib/share.h
+++ b/Utilities/cmcurl/lib/share.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -37,8 +37,12 @@
#define CURL_VOLATILE volatile
#endif
+#define CURL_GOOD_SHARE 0x7e117a1e
+#define GOOD_SHARE_HANDLE(x) ((x) && (x)->magic == CURL_GOOD_SHARE)
+
/* this struct is libcurl-private, don't export details */
struct Curl_share {
+ unsigned int magic; /* CURL_GOOD_SHARE */
unsigned int specifier;
CURL_VOLATILE unsigned int dirty;
@@ -46,7 +50,7 @@ struct Curl_share {
curl_unlock_function unlockfunc;
void *clientdata;
struct conncache conn_cache;
- struct curl_hash hostcache;
+ struct Curl_hash hostcache;
#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
struct CookieInfo *cookies;
#endif
@@ -54,7 +58,7 @@ struct Curl_share {
struct PslCache psl;
#endif
- struct curl_ssl_session *sslsession;
+ struct Curl_ssl_session *sslsession;
size_t max_ssl_sessions;
long sessionage;
};
diff --git a/Utilities/cmcurl/lib/sigpipe.h b/Utilities/cmcurl/lib/sigpipe.h
index 3960a139d..430cfc648 100644
--- a/Utilities/cmcurl/lib/sigpipe.h
+++ b/Utilities/cmcurl/lib/sigpipe.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
diff --git a/Utilities/cmcurl/lib/slist.c b/Utilities/cmcurl/lib/slist.c
index d27fbe19b..907c203f3 100644
--- a/Utilities/cmcurl/lib/slist.c
+++ b/Utilities/cmcurl/lib/slist.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
diff --git a/Utilities/cmcurl/lib/slist.h b/Utilities/cmcurl/lib/slist.h
index 799b3c060..3114259cf 100644
--- a/Utilities/cmcurl/lib/slist.h
+++ b/Utilities/cmcurl/lib/slist.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
diff --git a/Utilities/cmcurl/lib/smb.c b/Utilities/cmcurl/lib/smb.c
index d493adcc0..dd4e4fdbf 100644
--- a/Utilities/cmcurl/lib/smb.c
+++ b/Utilities/cmcurl/lib/smb.c
@@ -5,12 +5,12 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
+ * Copyright (C) 2016 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 2014, Bill Nagel <wnagel@tycoint.com>, Exacq Technologies
- * Copyright (C) 2016-2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -23,11 +23,9 @@
#include "curl_setup.h"
-#if !defined(CURL_DISABLE_SMB) && defined(USE_NTLM) && \
+#if !defined(CURL_DISABLE_SMB) && defined(USE_CURL_NTLM_CORE) && \
(CURL_SIZEOF_CURL_OFF_T > 4)
-#if !defined(USE_WINDOWS_SSPI) || defined(USE_WIN32_CRYPTO)
-
#define BUILDING_CURL_SMB_C
#ifdef HAVE_PROCESS_H
@@ -56,16 +54,20 @@
#include "memdebug.h"
/* Local API functions */
-static CURLcode smb_setup_connection(struct connectdata *conn);
-static CURLcode smb_connect(struct connectdata *conn, bool *done);
-static CURLcode smb_connection_state(struct connectdata *conn, bool *done);
-static CURLcode smb_do(struct connectdata *conn, bool *done);
-static CURLcode smb_request_state(struct connectdata *conn, bool *done);
-static CURLcode smb_done(struct connectdata *conn, CURLcode status,
+static CURLcode smb_setup_connection(struct Curl_easy *data,
+ struct connectdata *conn);
+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_done(struct Curl_easy *data, CURLcode status,
bool premature);
-static CURLcode smb_disconnect(struct connectdata *conn, bool dead);
-static int smb_getsock(struct connectdata *conn, curl_socket_t *socks);
-static CURLcode smb_parse_url_path(struct connectdata *conn);
+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);
/*
* SMB handler interface
@@ -88,6 +90,7 @@ const struct Curl_handler Curl_handler_smb = {
ZERO_NULL, /* connection_check */
PORT_SMB, /* defport */
CURLPROTO_SMB, /* protocol */
+ CURLPROTO_SMB, /* family */
PROTOPT_NONE /* flags */
};
@@ -113,6 +116,7 @@ const struct Curl_handler Curl_handler_smbs = {
ZERO_NULL, /* connection_check */
PORT_SMBS, /* defport */
CURLPROTO_SMBS, /* protocol */
+ CURLPROTO_SMB, /* family */
PROTOPT_SSL /* flags */
};
#endif
@@ -124,13 +128,17 @@ const struct Curl_handler Curl_handler_smbs = {
/* Append a string to an SMB message */
#define MSGCAT(str) \
- strcpy(p, (str)); \
- p += strlen(str);
+ do { \
+ strcpy(p, (str)); \
+ p += strlen(str); \
+ } while(0)
/* Append a null-terminated string to an SMB message */
#define MSGCATNULL(str) \
- strcpy(p, (str)); \
- p += strlen(str) + 1;
+ do { \
+ strcpy(p, (str)); \
+ p += strlen(str) + 1; \
+ } while(0)
/* SMB is mostly little endian */
#if (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) || \
@@ -179,9 +187,9 @@ struct smb_request {
CURLcode result;
};
-static void conn_state(struct connectdata *conn, enum smb_conn_state newstate)
+static void conn_state(struct Curl_easy *data, enum smb_conn_state newstate)
{
- struct smb_conn *smbc = &conn->proto.smbc;
+ struct smb_conn *smbc = &data->conn->proto.smbc;
#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
/* For debug purposes */
static const char * const names[] = {
@@ -194,17 +202,17 @@ static void conn_state(struct connectdata *conn, enum smb_conn_state newstate)
};
if(smbc->state != newstate)
- infof(conn->data, "SMB conn %p state change from %s to %s\n",
+ infof(data, "SMB conn %p state change from %s to %s\n",
(void *)smbc, names[smbc->state], names[newstate]);
#endif
smbc->state = newstate;
}
-static void request_state(struct connectdata *conn,
+static void request_state(struct Curl_easy *data,
enum smb_req_state newstate)
{
- struct smb_request *req = conn->data->req.protop;
+ struct smb_request *req = data->req.p.smb;
#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
/* For debug purposes */
static const char * const names[] = {
@@ -220,7 +228,7 @@ static void request_state(struct connectdata *conn,
};
if(req->state != newstate)
- infof(conn->data, "SMB request %p state change from %s to %s\n",
+ infof(data, "SMB request %p state change from %s to %s\n",
(void *)req, names[req->state], names[newstate]);
#endif
@@ -229,21 +237,23 @@ static void request_state(struct connectdata *conn,
/* this should setup things in the connection, not in the easy
handle */
-static CURLcode smb_setup_connection(struct connectdata *conn)
+static CURLcode smb_setup_connection(struct Curl_easy *data,
+ struct connectdata *conn)
{
struct smb_request *req;
/* Initialize the request state */
- conn->data->req.protop = req = calloc(1, sizeof(struct smb_request));
+ data->req.p.smb = req = calloc(1, sizeof(struct smb_request));
if(!req)
return CURLE_OUT_OF_MEMORY;
/* Parse the URL path */
- return smb_parse_url_path(conn);
+ return smb_parse_url_path(data, conn);
}
-static CURLcode smb_connect(struct connectdata *conn, bool *done)
+static CURLcode smb_connect(struct Curl_easy *data, bool *done)
{
+ struct connectdata *conn = data->conn;
struct smb_conn *smbc = &conn->proto.smbc;
char *slash;
@@ -284,8 +294,9 @@ static CURLcode smb_connect(struct connectdata *conn, bool *done)
return CURLE_OK;
}
-static CURLcode smb_recv_message(struct connectdata *conn, void **msg)
+static CURLcode smb_recv_message(struct Curl_easy *data, void **msg)
{
+ struct connectdata *conn = data->conn;
struct smb_conn *smbc = &conn->proto.smbc;
char *buf = smbc->recv_buf;
ssize_t bytes_read;
@@ -294,7 +305,7 @@ static CURLcode smb_recv_message(struct connectdata *conn, void **msg)
size_t len = MAX_MESSAGE_SIZE - smbc->got;
CURLcode result;
- result = Curl_read(conn, FIRSTSOCKET, buf + smbc->got, len, &bytes_read);
+ result = Curl_read(data, FIRSTSOCKET, buf + smbc->got, len, &bytes_read);
if(result)
return result;
@@ -338,11 +349,12 @@ static void smb_pop_message(struct connectdata *conn)
smbc->got = 0;
}
-static void smb_format_message(struct connectdata *conn, struct smb_header *h,
+static void smb_format_message(struct Curl_easy *data, 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 = conn->data->req.protop;
+ struct smb_request *req = data->req.p.smb;
unsigned int pid;
memset(h, 0, sizeof(*h));
@@ -359,14 +371,15 @@ static void smb_format_message(struct connectdata *conn, struct smb_header *h,
h->pid = smb_swap16((unsigned short) pid);
}
-static CURLcode smb_send(struct connectdata *conn, ssize_t len,
+static CURLcode smb_send(struct Curl_easy *data, ssize_t len,
size_t upload_size)
{
+ struct connectdata *conn = data->conn;
struct smb_conn *smbc = &conn->proto.smbc;
ssize_t bytes_written;
CURLcode result;
- result = Curl_write(conn, FIRSTSOCKET, conn->data->state.ulbuf,
+ result = Curl_write(data, FIRSTSOCKET, data->state.ulbuf,
len, &bytes_written);
if(result)
return result;
@@ -381,8 +394,9 @@ static CURLcode smb_send(struct connectdata *conn, ssize_t len,
return CURLE_OK;
}
-static CURLcode smb_flush(struct connectdata *conn)
+static CURLcode smb_flush(struct Curl_easy *data)
{
+ struct connectdata *conn = data->conn;
struct smb_conn *smbc = &conn->proto.smbc;
ssize_t bytes_written;
ssize_t len = smbc->send_size - smbc->sent;
@@ -391,8 +405,8 @@ static CURLcode smb_flush(struct connectdata *conn)
if(!smbc->send_size)
return CURLE_OK;
- result = Curl_write(conn, FIRSTSOCKET,
- conn->data->state.ulbuf + smbc->sent,
+ result = Curl_write(data, FIRSTSOCKET,
+ data->state.ulbuf + smbc->sent,
len, &bytes_written);
if(result)
return result;
@@ -405,29 +419,30 @@ static CURLcode smb_flush(struct connectdata *conn)
return CURLE_OK;
}
-static CURLcode smb_send_message(struct connectdata *conn, unsigned char cmd,
+static CURLcode smb_send_message(struct Curl_easy *data, unsigned char cmd,
const void *msg, size_t msg_len)
{
- CURLcode result = Curl_get_upload_buffer(conn->data);
+ CURLcode result = Curl_get_upload_buffer(data);
if(result)
return result;
- smb_format_message(conn, (struct smb_header *)conn->data->state.ulbuf,
+ smb_format_message(data, (struct smb_header *)data->state.ulbuf,
cmd, msg_len);
- memcpy(conn->data->state.ulbuf + sizeof(struct smb_header),
+ memcpy(data->state.ulbuf + sizeof(struct smb_header),
msg, msg_len);
- return smb_send(conn, sizeof(struct smb_header) + msg_len, 0);
+ return smb_send(data, sizeof(struct smb_header) + msg_len, 0);
}
-static CURLcode smb_send_negotiate(struct connectdata *conn)
+static CURLcode smb_send_negotiate(struct Curl_easy *data)
{
const char *msg = "\x00\x0c\x00\x02NT LM 0.12";
- return smb_send_message(conn, SMB_COM_NEGOTIATE, msg, 15);
+ return smb_send_message(data, SMB_COM_NEGOTIATE, msg, 15);
}
-static CURLcode smb_send_setup(struct connectdata *conn)
+static CURLcode smb_send_setup(struct Curl_easy *data)
{
+ struct connectdata *conn = data->conn;
struct smb_conn *smbc = &conn->proto.smbc;
struct smb_setup msg;
char *p = msg.bytes;
@@ -442,10 +457,10 @@ static CURLcode smb_send_setup(struct connectdata *conn)
if(byte_count > sizeof(msg.bytes))
return CURLE_FILESIZE_EXCEEDED;
- Curl_ntlm_core_mk_lm_hash(conn->data, conn->passwd, lm_hash);
+ Curl_ntlm_core_mk_lm_hash(data, conn->passwd, lm_hash);
Curl_ntlm_core_lm_resp(lm_hash, smbc->challenge, lm);
#ifdef USE_NTRESPONSES
- Curl_ntlm_core_mk_nt_hash(conn->data, conn->passwd, nt_hash);
+ Curl_ntlm_core_mk_nt_hash(data, conn->passwd, nt_hash);
Curl_ntlm_core_lm_resp(nt_hash, smbc->challenge, nt);
#else
memset(nt, 0, sizeof(nt));
@@ -472,13 +487,14 @@ static CURLcode smb_send_setup(struct connectdata *conn)
byte_count = p - msg.bytes;
msg.byte_count = smb_swap16((unsigned short)byte_count);
- return smb_send_message(conn, SMB_COM_SETUP_ANDX, &msg,
+ return smb_send_message(data, SMB_COM_SETUP_ANDX, &msg,
sizeof(msg) - sizeof(msg.bytes) + byte_count);
}
-static CURLcode smb_send_tree_connect(struct connectdata *conn)
+static CURLcode smb_send_tree_connect(struct Curl_easy *data)
{
struct smb_tree_connect msg;
+ struct connectdata *conn = data->conn;
struct smb_conn *smbc = &conn->proto.smbc;
char *p = msg.bytes;
@@ -499,13 +515,13 @@ static CURLcode smb_send_tree_connect(struct connectdata *conn)
byte_count = p - msg.bytes;
msg.byte_count = smb_swap16((unsigned short)byte_count);
- return smb_send_message(conn, SMB_COM_TREE_CONNECT_ANDX, &msg,
+ return smb_send_message(data, SMB_COM_TREE_CONNECT_ANDX, &msg,
sizeof(msg) - sizeof(msg.bytes) + byte_count);
}
-static CURLcode smb_send_open(struct connectdata *conn)
+static CURLcode smb_send_open(struct Curl_easy *data)
{
- struct smb_request *req = conn->data->req.protop;
+ struct smb_request *req = data->req.p.smb;
struct smb_nt_create msg;
size_t byte_count;
@@ -518,7 +534,7 @@ static CURLcode smb_send_open(struct connectdata *conn)
byte_count = strlen(req->path);
msg.name_length = smb_swap16((unsigned short)byte_count);
msg.share_access = smb_swap32(SMB_FILE_SHARE_ALL);
- if(conn->data->set.upload) {
+ if(data->set.upload) {
msg.access = smb_swap32(SMB_GENERIC_READ | SMB_GENERIC_WRITE);
msg.create_disposition = smb_swap32(SMB_FILE_OVERWRITE_IF);
}
@@ -529,35 +545,35 @@ static CURLcode smb_send_open(struct connectdata *conn)
msg.byte_count = smb_swap16((unsigned short) ++byte_count);
strcpy(msg.bytes, req->path);
- return smb_send_message(conn, SMB_COM_NT_CREATE_ANDX, &msg,
+ return smb_send_message(data, SMB_COM_NT_CREATE_ANDX, &msg,
sizeof(msg) - sizeof(msg.bytes) + byte_count);
}
-static CURLcode smb_send_close(struct connectdata *conn)
+static CURLcode smb_send_close(struct Curl_easy *data)
{
- struct smb_request *req = conn->data->req.protop;
+ 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(conn, SMB_COM_CLOSE, &msg, sizeof(msg));
+ return smb_send_message(data, SMB_COM_CLOSE, &msg, sizeof(msg));
}
-static CURLcode smb_send_tree_disconnect(struct connectdata *conn)
+static CURLcode smb_send_tree_disconnect(struct Curl_easy *data)
{
struct smb_tree_disconnect msg;
memset(&msg, 0, sizeof(msg));
- return smb_send_message(conn, SMB_COM_TREE_DISCONNECT, &msg, sizeof(msg));
+ return smb_send_message(data, SMB_COM_TREE_DISCONNECT, &msg, sizeof(msg));
}
-static CURLcode smb_send_read(struct connectdata *conn)
+static CURLcode smb_send_read(struct Curl_easy *data)
{
- struct smb_request *req = conn->data->req.protop;
- curl_off_t offset = conn->data->req.offset;
+ struct smb_request *req = data->req.p.smb;
+ curl_off_t offset = data->req.offset;
struct smb_read msg;
memset(&msg, 0, sizeof(msg));
@@ -569,19 +585,19 @@ static CURLcode smb_send_read(struct connectdata *conn)
msg.min_bytes = smb_swap16(MAX_PAYLOAD_SIZE);
msg.max_bytes = smb_swap16(MAX_PAYLOAD_SIZE);
- return smb_send_message(conn, SMB_COM_READ_ANDX, &msg, sizeof(msg));
+ return smb_send_message(data, SMB_COM_READ_ANDX, &msg, sizeof(msg));
}
-static CURLcode smb_send_write(struct connectdata *conn)
+static CURLcode smb_send_write(struct Curl_easy *data)
{
struct smb_write *msg;
- struct smb_request *req = conn->data->req.protop;
- curl_off_t offset = conn->data->req.offset;
- curl_off_t upload_size = conn->data->req.size - conn->data->req.bytecount;
- CURLcode result = Curl_get_upload_buffer(conn->data);
+ 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;
+ CURLcode result = Curl_get_upload_buffer(data);
if(result)
return result;
- msg = (struct smb_write *)conn->data->state.ulbuf;
+ msg = (struct smb_write *)data->state.ulbuf;
if(upload_size >= MAX_PAYLOAD_SIZE - 1) /* There is one byte of padding */
upload_size = MAX_PAYLOAD_SIZE - 1;
@@ -596,25 +612,26 @@ static CURLcode smb_send_write(struct connectdata *conn)
msg->data_offset = smb_swap16(sizeof(*msg) - sizeof(unsigned int));
msg->byte_count = smb_swap16((unsigned short) (upload_size + 1));
- smb_format_message(conn, &msg->h, SMB_COM_WRITE_ANDX,
+ smb_format_message(data, &msg->h, SMB_COM_WRITE_ANDX,
sizeof(*msg) - sizeof(msg->h) + (size_t) upload_size);
- return smb_send(conn, sizeof(*msg), (size_t) upload_size);
+ return smb_send(data, sizeof(*msg), (size_t) upload_size);
}
-static CURLcode smb_send_and_recv(struct connectdata *conn, void **msg)
+static CURLcode smb_send_and_recv(struct Curl_easy *data, void **msg)
{
+ struct connectdata *conn = data->conn;
struct smb_conn *smbc = &conn->proto.smbc;
CURLcode result;
*msg = NULL; /* if it returns early */
/* Check if there is data in the transfer buffer */
if(!smbc->send_size && smbc->upload_size) {
- size_t nread = smbc->upload_size > conn->data->set.upload_buffer_size ?
- conn->data->set.upload_buffer_size :
+ size_t nread = smbc->upload_size > data->set.upload_buffer_size ?
+ data->set.upload_buffer_size :
smbc->upload_size;
- conn->data->req.upload_fromhere = conn->data->state.ulbuf;
- result = Curl_fillreadbuffer(conn, nread, &nread);
+ data->req.upload_fromhere = data->state.ulbuf;
+ result = Curl_fillreadbuffer(data, nread, &nread);
if(result && result != CURLE_AGAIN)
return result;
if(!nread)
@@ -627,7 +644,7 @@ static CURLcode smb_send_and_recv(struct connectdata *conn, void **msg)
/* Check if there is data to send */
if(smbc->send_size) {
- result = smb_flush(conn);
+ result = smb_flush(data);
if(result)
return result;
}
@@ -636,11 +653,12 @@ static CURLcode smb_send_and_recv(struct connectdata *conn, void **msg)
if(smbc->send_size || smbc->upload_size)
return CURLE_AGAIN;
- return smb_recv_message(conn, msg);
+ return smb_recv_message(data, msg);
}
-static CURLcode smb_connection_state(struct connectdata *conn, bool *done)
+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_negotiate_response *nrsp;
struct smb_header *h;
@@ -651,7 +669,8 @@ static CURLcode smb_connection_state(struct connectdata *conn, bool *done)
#ifdef USE_SSL
if((conn->handler->flags & PROTOPT_SSL)) {
bool ssl_done = FALSE;
- result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, &ssl_done);
+ result = Curl_ssl_connect_nonblocking(data, conn,
+ FIRSTSOCKET, &ssl_done);
if(result && result != CURLE_AGAIN)
return result;
if(!ssl_done)
@@ -659,17 +678,17 @@ static CURLcode smb_connection_state(struct connectdata *conn, bool *done)
}
#endif
- result = smb_send_negotiate(conn);
+ result = smb_send_negotiate(data);
if(result) {
connclose(conn, "SMB: failed to send negotiate message");
return result;
}
- conn_state(conn, SMB_NEGOTIATE);
+ conn_state(data, SMB_NEGOTIATE);
}
/* Send the previous message and check for a response */
- result = smb_send_and_recv(conn, &msg);
+ result = smb_send_and_recv(data, &msg);
if(result && result != CURLE_AGAIN) {
connclose(conn, "SMB: failed to communicate");
return result;
@@ -690,12 +709,12 @@ static CURLcode smb_connection_state(struct connectdata *conn, bool *done)
nrsp = msg;
memcpy(smbc->challenge, nrsp->bytes, sizeof(smbc->challenge));
smbc->session_key = smb_swap32(nrsp->session_key);
- result = smb_send_setup(conn);
+ result = smb_send_setup(data);
if(result) {
connclose(conn, "SMB: failed to send setup message");
return result;
}
- conn_state(conn, SMB_SETUP);
+ conn_state(data, SMB_SETUP);
break;
case SMB_SETUP:
@@ -704,7 +723,7 @@ static CURLcode smb_connection_state(struct connectdata *conn, bool *done)
return CURLE_LOGIN_DENIED;
}
smbc->uid = smb_swap16(h->uid);
- conn_state(conn, SMB_CONNECTED);
+ conn_state(data, SMB_CONNECTED);
*done = true;
break;
@@ -736,9 +755,10 @@ static void get_posix_time(time_t *out, curl_off_t timestamp)
*out = (time_t) timestamp;
}
-static CURLcode smb_request_state(struct connectdata *conn, bool *done)
+static CURLcode smb_request_state(struct Curl_easy *data, bool *done)
{
- struct smb_request *req = conn->data->req.protop;
+ struct connectdata *conn = data->conn;
+ struct smb_request *req = data->req.p.smb;
struct smb_header *h;
struct smb_conn *smbc = &conn->proto.smbc;
enum smb_req_state next_state = SMB_DONE;
@@ -750,17 +770,17 @@ static CURLcode smb_request_state(struct connectdata *conn, bool *done)
/* Start the request */
if(req->state == SMB_REQUESTING) {
- result = smb_send_tree_connect(conn);
+ result = smb_send_tree_connect(data);
if(result) {
connclose(conn, "SMB: failed to send tree connect message");
return result;
}
- request_state(conn, SMB_TREE_CONNECT);
+ request_state(data, SMB_TREE_CONNECT);
}
/* Send the previous message and check for a response */
- result = smb_send_and_recv(conn, &msg);
+ result = smb_send_and_recv(data, &msg);
if(result && result != CURLE_AGAIN) {
connclose(conn, "SMB: failed to communicate");
return result;
@@ -793,23 +813,23 @@ static CURLcode smb_request_state(struct connectdata *conn, bool *done)
}
smb_m = (const struct smb_nt_create_response*) msg;
req->fid = smb_swap16(smb_m->fid);
- conn->data->req.offset = 0;
- if(conn->data->set.upload) {
- conn->data->req.size = conn->data->state.infilesize;
- Curl_pgrsSetUploadSize(conn->data, conn->data->req.size);
+ data->req.offset = 0;
+ if(data->set.upload) {
+ data->req.size = data->state.infilesize;
+ Curl_pgrsSetUploadSize(data, data->req.size);
next_state = SMB_UPLOAD;
}
else {
smb_m = (const struct smb_nt_create_response*) msg;
- conn->data->req.size = smb_swap64(smb_m->end_of_file);
- if(conn->data->req.size < 0) {
+ data->req.size = smb_swap64(smb_m->end_of_file);
+ if(data->req.size < 0) {
req->result = CURLE_WEIRD_SERVER_REPLY;
next_state = SMB_CLOSE;
}
else {
- Curl_pgrsSetDownloadSize(conn->data, conn->data->req.size);
- if(conn->data->set.get_filetime)
- get_posix_time(&conn->data->info.filetime, smb_m->last_change_time);
+ Curl_pgrsSetDownloadSize(data, data->req.size);
+ if(data->set.get_filetime)
+ get_posix_time(&data->info.filetime, smb_m->last_change_time);
next_state = SMB_DOWNLOAD;
}
}
@@ -827,11 +847,11 @@ static CURLcode smb_request_state(struct connectdata *conn, bool *done)
sizeof(struct smb_header) + 13);
if(len > 0) {
if(off + sizeof(unsigned int) + len > smbc->got) {
- failf(conn->data, "Invalid input packet");
+ failf(data, "Invalid input packet");
result = CURLE_RECV_ERROR;
}
else
- result = Curl_client_write(conn, CLIENTWRITE_BODY,
+ result = Curl_client_write(data, CLIENTWRITE_BODY,
(char *)msg + off + sizeof(unsigned int),
len);
if(result) {
@@ -840,9 +860,9 @@ static CURLcode smb_request_state(struct connectdata *conn, bool *done)
break;
}
}
- conn->data->req.bytecount += len;
- conn->data->req.offset += len;
- Curl_pgrsSetDownloadCounter(conn->data, conn->data->req.bytecount);
+ data->req.bytecount += len;
+ data->req.offset += len;
+ Curl_pgrsSetDownloadCounter(data, data->req.bytecount);
next_state = (len < MAX_PAYLOAD_SIZE) ? SMB_CLOSE : SMB_DOWNLOAD;
break;
@@ -854,10 +874,10 @@ static CURLcode smb_request_state(struct connectdata *conn, bool *done)
}
len = Curl_read16_le(((const unsigned char *) msg) +
sizeof(struct smb_header) + 5);
- conn->data->req.bytecount += len;
- conn->data->req.offset += len;
- Curl_pgrsSetUploadCounter(conn->data, conn->data->req.bytecount);
- if(conn->data->req.bytecount >= conn->data->req.size)
+ data->req.bytecount += len;
+ data->req.offset += len;
+ Curl_pgrsSetUploadCounter(data, data->req.bytecount);
+ if(data->req.bytecount >= data->req.size)
next_state = SMB_CLOSE;
else
next_state = SMB_UPLOAD;
@@ -881,23 +901,23 @@ static CURLcode smb_request_state(struct connectdata *conn, bool *done)
switch(next_state) {
case SMB_OPEN:
- result = smb_send_open(conn);
+ result = smb_send_open(data);
break;
case SMB_DOWNLOAD:
- result = smb_send_read(conn);
+ result = smb_send_read(data);
break;
case SMB_UPLOAD:
- result = smb_send_write(conn);
+ result = smb_send_write(data);
break;
case SMB_CLOSE:
- result = smb_send_close(conn);
+ result = smb_send_close(data);
break;
case SMB_TREE_DISCONNECT:
- result = smb_send_tree_disconnect(conn);
+ result = smb_send_tree_disconnect(data);
break;
case SMB_DONE:
@@ -914,37 +934,42 @@ static CURLcode smb_request_state(struct connectdata *conn, bool *done)
return result;
}
- request_state(conn, next_state);
+ request_state(data, next_state);
return CURLE_OK;
}
-static CURLcode smb_done(struct connectdata *conn, CURLcode status,
+static CURLcode smb_done(struct Curl_easy *data, CURLcode status,
bool premature)
{
(void) premature;
- Curl_safefree(conn->data->req.protop);
+ Curl_safefree(data->req.p.smb);
return status;
}
-static CURLcode smb_disconnect(struct connectdata *conn, bool dead)
+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);
return CURLE_OK;
}
-static int smb_getsock(struct connectdata *conn, curl_socket_t *socks)
+static int smb_getsock(struct Curl_easy *data,
+ struct connectdata *conn, curl_socket_t *socks)
{
+ (void)data;
socks[0] = conn->sock[FIRSTSOCKET];
return GETSOCK_READSOCK(0) | GETSOCK_WRITESOCK(0);
}
-static CURLcode smb_do(struct connectdata *conn, bool *done)
+static CURLcode smb_do(struct Curl_easy *data, bool *done)
{
+ struct connectdata *conn = data->conn;
struct smb_conn *smbc = &conn->proto.smbc;
*done = FALSE;
@@ -954,10 +979,10 @@ static CURLcode smb_do(struct connectdata *conn, bool *done)
return CURLE_URL_MALFORMAT;
}
-static CURLcode smb_parse_url_path(struct connectdata *conn)
+static CURLcode smb_parse_url_path(struct Curl_easy *data,
+ struct connectdata *conn)
{
- struct Curl_easy *data = conn->data;
- struct smb_request *req = data->req.protop;
+ struct smb_request *req = data->req.p.smb;
struct smb_conn *smbc = &conn->proto.smbc;
char *path;
char *slash;
@@ -996,6 +1021,5 @@ static CURLcode smb_parse_url_path(struct connectdata *conn)
return CURLE_OK;
}
-#endif /* !USE_WINDOWS_SSPI || USE_WIN32_CRYPTO */
-
-#endif /* CURL_DISABLE_SMB && USE_NTLM && CURL_SIZEOF_CURL_OFF_T > 4 */
+#endif /* CURL_DISABLE_SMB && USE_CURL_NTLM_CORE &&
+ CURL_SIZEOF_CURL_OFF_T > 4 */
diff --git a/Utilities/cmcurl/lib/smb.h b/Utilities/cmcurl/lib/smb.h
index 136a89ce9..907cf0c8e 100644
--- a/Utilities/cmcurl/lib/smb.h
+++ b/Utilities/cmcurl/lib/smb.h
@@ -12,7 +12,7 @@
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -243,16 +243,13 @@ struct smb_tree_disconnect {
#endif /* BUILDING_CURL_SMB_C */
-#if !defined(CURL_DISABLE_SMB) && defined(USE_NTLM) && \
+#if !defined(CURL_DISABLE_SMB) && defined(USE_CURL_NTLM_CORE) && \
(CURL_SIZEOF_CURL_OFF_T > 4)
-#if !defined(USE_WINDOWS_SSPI) || defined(USE_WIN32_CRYPTO)
-
extern const struct Curl_handler Curl_handler_smb;
extern const struct Curl_handler Curl_handler_smbs;
-#endif /* !USE_WINDOWS_SSPI || USE_WIN32_CRYPTO */
-
-#endif /* CURL_DISABLE_SMB && USE_NTLM && CURL_SIZEOF_CURL_OFF_T > 4 */
+#endif /* CURL_DISABLE_SMB && USE_CURL_NTLM_CORE &&
+ CURL_SIZEOF_CURL_OFF_T > 4 */
#endif /* HEADER_CURL_SMB_H */
diff --git a/Utilities/cmcurl/lib/smtp.c b/Utilities/cmcurl/lib/smtp.c
index aea41bb4e..1fc880065 100644
--- a/Utilities/cmcurl/lib/smtp.c
+++ b/Utilities/cmcurl/lib/smtp.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -91,24 +91,29 @@
#include "memdebug.h"
/* Local API functions */
-static CURLcode smtp_regular_transfer(struct connectdata *conn, bool *done);
-static CURLcode smtp_do(struct connectdata *conn, bool *done);
-static CURLcode smtp_done(struct connectdata *conn, CURLcode status,
+static CURLcode smtp_regular_transfer(struct Curl_easy *data, bool *done);
+static CURLcode smtp_do(struct Curl_easy *data, bool *done);
+static CURLcode smtp_done(struct Curl_easy *data, CURLcode status,
bool premature);
-static CURLcode smtp_connect(struct connectdata *conn, bool *done);
-static CURLcode smtp_disconnect(struct connectdata *conn, bool dead);
-static CURLcode smtp_multi_statemach(struct connectdata *conn, bool *done);
-static int smtp_getsock(struct connectdata *conn, curl_socket_t *socks);
-static CURLcode smtp_doing(struct connectdata *conn, bool *dophase_done);
-static CURLcode smtp_setup_connection(struct connectdata *conn);
+static CURLcode smtp_connect(struct Curl_easy *data, bool *done);
+static CURLcode smtp_disconnect(struct Curl_easy *data,
+ struct connectdata *conn, bool dead);
+static CURLcode smtp_multi_statemach(struct Curl_easy *data, bool *done);
+static int smtp_getsock(struct Curl_easy *data,
+ struct connectdata *conn, curl_socket_t *socks);
+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 connectdata *conn);
-static CURLcode smtp_parse_custom_request(struct connectdata *conn);
-static CURLcode smtp_parse_address(struct connectdata *conn, const char *fqma,
+static CURLcode smtp_parse_url_path(struct Curl_easy *data);
+static CURLcode smtp_parse_custom_request(struct Curl_easy *data);
+static CURLcode smtp_parse_address(struct Curl_easy *data, const char *fqma,
char **address, struct hostname *host);
-static CURLcode smtp_perform_auth(struct connectdata *conn, const char *mech,
+static CURLcode smtp_perform_auth(struct Curl_easy *data,
+ struct connectdata *conn, const char *mech,
const char *initresp);
-static CURLcode smtp_continue_auth(struct connectdata *conn, const char *resp);
+static CURLcode smtp_continue_auth(struct Curl_easy *data,
+ struct connectdata *conn, const char *resp);
static void smtp_get_message(char *buffer, char **outptr);
/*
@@ -133,6 +138,7 @@ const struct Curl_handler Curl_handler_smtp = {
ZERO_NULL, /* connection_check */
PORT_SMTP, /* defport */
CURLPROTO_SMTP, /* protocol */
+ CURLPROTO_SMTP, /* family */
PROTOPT_CLOSEACTION | PROTOPT_NOURLQUERY | /* flags */
PROTOPT_URLOPTIONS
};
@@ -160,6 +166,7 @@ const struct Curl_handler Curl_handler_smtps = {
ZERO_NULL, /* connection_check */
PORT_SMTPS, /* defport */
CURLPROTO_SMTPS, /* protocol */
+ CURLPROTO_SMTP, /* family */
PROTOPT_CLOSEACTION | PROTOPT_SSL
| PROTOPT_NOURLQUERY | PROTOPT_URLOPTIONS /* flags */
};
@@ -197,11 +204,12 @@ static void smtp_to_smtps(struct connectdata *conn)
* also detects various capabilities from the EHLO response including the
* supported authentication mechanisms.
*/
-static bool smtp_endofresp(struct connectdata *conn, char *line, size_t len,
- int *resp)
+static bool smtp_endofresp(struct Curl_easy *data, struct connectdata *conn,
+ char *line, size_t len, int *resp)
{
struct smtp_conn *smtpc = &conn->proto.smtpc;
bool result = FALSE;
+ (void)data;
/* Nothing for us */
if(len < 4 || !ISDIGIT(line[0]) || !ISDIGIT(line[1]) || !ISDIGIT(line[2]))
@@ -275,9 +283,9 @@ static void smtp_get_message(char *buffer, char **outptr)
*
* This is the ONLY way to change SMTP state!
*/
-static void state(struct connectdata *conn, smtpstate newstate)
+static void state(struct Curl_easy *data, smtpstate newstate)
{
- struct smtp_conn *smtpc = &conn->proto.smtpc;
+ struct smtp_conn *smtpc = &data->conn->proto.smtpc;
#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
/* for debug purposes */
static const char * const names[] = {
@@ -298,7 +306,7 @@ static void state(struct connectdata *conn, smtpstate newstate)
};
if(smtpc->state != newstate)
- infof(conn->data, "SMTP %p state change from %s to %s\n",
+ infof(data, "SMTP %p state change from %s to %s\n",
(void *)smtpc, names[smtpc->state], names[newstate]);
#endif
@@ -312,9 +320,10 @@ static void state(struct connectdata *conn, 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 connectdata *conn)
+static CURLcode smtp_perform_ehlo(struct Curl_easy *data)
{
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 */
@@ -324,10 +333,10 @@ static CURLcode smtp_perform_ehlo(struct connectdata *conn)
smtpc->auth_supported = FALSE; /* Clear the AUTH capability */
/* Send the EHLO command */
- result = Curl_pp_sendf(&smtpc->pp, "EHLO %s", smtpc->domain);
+ result = Curl_pp_sendf(data, &smtpc->pp, "EHLO %s", smtpc->domain);
if(!result)
- state(conn, SMTP_EHLO);
+ state(data, SMTP_EHLO);
return result;
}
@@ -338,7 +347,8 @@ static CURLcode smtp_perform_ehlo(struct connectdata *conn)
*
* Sends the HELO command to initialise communication with the SMTP server.
*/
-static CURLcode smtp_perform_helo(struct connectdata *conn)
+static CURLcode smtp_perform_helo(struct Curl_easy *data,
+ struct connectdata *conn)
{
CURLcode result = CURLE_OK;
struct smtp_conn *smtpc = &conn->proto.smtpc;
@@ -347,10 +357,10 @@ static CURLcode smtp_perform_helo(struct connectdata *conn)
in smtp connections */
/* Send the HELO command */
- result = Curl_pp_sendf(&smtpc->pp, "HELO %s", smtpc->domain);
+ result = Curl_pp_sendf(data, &smtpc->pp, "HELO %s", smtpc->domain);
if(!result)
- state(conn, SMTP_HELO);
+ state(data, SMTP_HELO);
return result;
}
@@ -361,13 +371,15 @@ static CURLcode smtp_perform_helo(struct connectdata *conn)
*
* Sends the STLS command to start the upgrade to TLS.
*/
-static CURLcode smtp_perform_starttls(struct connectdata *conn)
+static CURLcode smtp_perform_starttls(struct Curl_easy *data,
+ struct connectdata *conn)
{
/* Send the STARTTLS command */
- CURLcode result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", "STARTTLS");
+ CURLcode result = Curl_pp_sendf(data, &conn->proto.smtpc.pp,
+ "%s", "STARTTLS");
if(!result)
- state(conn, SMTP_STARTTLS);
+ state(data, SMTP_STARTTLS);
return result;
}
@@ -378,20 +390,21 @@ static CURLcode smtp_perform_starttls(struct connectdata *conn)
*
* Performs the upgrade to TLS.
*/
-static CURLcode smtp_perform_upgrade_tls(struct connectdata *conn)
+static CURLcode smtp_perform_upgrade_tls(struct Curl_easy *data)
{
/* Start the SSL connection */
+ struct connectdata *conn = data->conn;
struct smtp_conn *smtpc = &conn->proto.smtpc;
- CURLcode result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET,
+ CURLcode result = Curl_ssl_connect_nonblocking(data, conn, FIRSTSOCKET,
&smtpc->ssldone);
if(!result) {
if(smtpc->state != SMTP_UPGRADETLS)
- state(conn, SMTP_UPGRADETLS);
+ state(data, SMTP_UPGRADETLS);
if(smtpc->ssldone) {
smtp_to_smtps(conn);
- result = smtp_perform_ehlo(conn);
+ result = smtp_perform_ehlo(data);
}
}
@@ -405,7 +418,8 @@ static CURLcode smtp_perform_upgrade_tls(struct connectdata *conn)
* Sends an AUTH command allowing the client to login with the given SASL
* authentication mechanism.
*/
-static CURLcode smtp_perform_auth(struct connectdata *conn,
+static CURLcode smtp_perform_auth(struct Curl_easy *data,
+ struct connectdata *conn,
const char *mech,
const char *initresp)
{
@@ -414,11 +428,11 @@ static CURLcode smtp_perform_auth(struct connectdata *conn,
if(initresp) { /* AUTH <mech> ...<crlf> */
/* Send the AUTH command with the initial response */
- result = Curl_pp_sendf(&smtpc->pp, "AUTH %s %s", mech, initresp);
+ result = Curl_pp_sendf(data, &smtpc->pp, "AUTH %s %s", mech, initresp);
}
else {
/* Send the AUTH command */
- result = Curl_pp_sendf(&smtpc->pp, "AUTH %s", mech);
+ result = Curl_pp_sendf(data, &smtpc->pp, "AUTH %s", mech);
}
return result;
@@ -430,11 +444,12 @@ static CURLcode smtp_perform_auth(struct connectdata *conn,
*
* Sends SASL continuation data or cancellation.
*/
-static CURLcode smtp_continue_auth(struct connectdata *conn, const char *resp)
+static CURLcode smtp_continue_auth(struct Curl_easy *data,
+ struct connectdata *conn, const char *resp)
{
struct smtp_conn *smtpc = &conn->proto.smtpc;
- return Curl_pp_sendf(&smtpc->pp, "%s", resp);
+ return Curl_pp_sendf(data, &smtpc->pp, "%s", resp);
}
/***********************************************************************
@@ -444,9 +459,10 @@ static CURLcode smtp_continue_auth(struct connectdata *conn, const char *resp)
* Initiates the authentication sequence, with the appropriate SASL
* authentication mechanism.
*/
-static CURLcode smtp_perform_authentication(struct connectdata *conn)
+static CURLcode smtp_perform_authentication(struct Curl_easy *data)
{
CURLcode result = CURLE_OK;
+ struct connectdata *conn = data->conn;
struct smtp_conn *smtpc = &conn->proto.smtpc;
saslprogress progress;
@@ -454,19 +470,19 @@ static CURLcode smtp_perform_authentication(struct connectdata *conn)
server supports authentiation, and end the connect phase if not */
if(!smtpc->auth_supported ||
!Curl_sasl_can_authenticate(&smtpc->sasl, conn)) {
- state(conn, SMTP_STOP);
+ state(data, SMTP_STOP);
return result;
}
/* Calculate the SASL login details */
- result = Curl_sasl_start(&smtpc->sasl, conn, FALSE, &progress);
+ result = Curl_sasl_start(&smtpc->sasl, data, conn, FALSE, &progress);
if(!result) {
if(progress == SASL_INPROGRESS)
- state(conn, SMTP_AUTH);
+ state(data, SMTP_AUTH);
else {
/* Other mechanisms not supported */
- infof(conn->data, "No known authentication mechanisms supported!\n");
+ infof(data, "No known authentication mechanisms supported!\n");
result = CURLE_LOGIN_DENIED;
}
}
@@ -480,11 +496,11 @@ static CURLcode smtp_perform_authentication(struct connectdata *conn)
*
* Sends a SMTP based command.
*/
-static CURLcode smtp_perform_command(struct connectdata *conn)
+static CURLcode smtp_perform_command(struct Curl_easy *data)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
- struct SMTP *smtp = data->req.protop;
+ 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
@@ -499,7 +515,7 @@ static CURLcode smtp_perform_command(struct connectdata *conn)
/* Parse the mailbox to verify into the local address and host name
parts, converting the host name to an IDN A-label if necessary */
- result = smtp_parse_address(conn, smtp->rcpt->data,
+ result = smtp_parse_address(data, smtp->rcpt->data,
&address, &host);
if(result)
return result;
@@ -512,7 +528,7 @@ static CURLcode smtp_perform_command(struct connectdata *conn)
/* Send the VRFY command (Note: The host name part may be absent when the
host is a local system) */
- result = Curl_pp_sendf(&conn->proto.smtpc.pp, "VRFY %s%s%s%s",
+ result = Curl_pp_sendf(data, &conn->proto.smtpc.pp, "VRFY %s%s%s%s",
address,
host.name ? "@" : "",
host.name ? host.name : "",
@@ -528,19 +544,20 @@ static CURLcode smtp_perform_command(struct connectdata *conn)
(!strcmp(smtp->custom, "EXPN"));
/* Send the custom recipient based command such as the EXPN command */
- result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s %s%s", smtp->custom,
+ result = Curl_pp_sendf(data, &conn->proto.smtpc.pp,
+ "%s %s%s", smtp->custom,
smtp->rcpt->data,
utf8 ? " SMTPUTF8" : "");
}
}
else
/* Send the non-recipient based command such as HELP */
- result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s",
+ result = Curl_pp_sendf(data, &conn->proto.smtpc.pp, "%s",
smtp->custom && smtp->custom[0] != '\0' ?
smtp->custom : "HELP");
if(!result)
- state(conn, SMTP_COMMAND);
+ state(data, SMTP_COMMAND);
return result;
}
@@ -551,13 +568,13 @@ static CURLcode smtp_perform_command(struct connectdata *conn)
*
* Sends an MAIL command to initiate the upload of a message.
*/
-static CURLcode smtp_perform_mail(struct connectdata *conn)
+static CURLcode smtp_perform_mail(struct Curl_easy *data)
{
char *from = NULL;
char *auth = NULL;
char *size = NULL;
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
+ 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 charaacters, in
@@ -572,7 +589,7 @@ static CURLcode smtp_perform_mail(struct connectdata *conn)
/* Parse the FROM mailbox into the local address and host name parts,
converting the host name to an IDN A-label if necessary */
- result = smtp_parse_address(conn, data->set.str[STRING_MAIL_FROM],
+ result = smtp_parse_address(data, data->set.str[STRING_MAIL_FROM],
&address, &host);
if(result)
return result;
@@ -610,7 +627,7 @@ static CURLcode smtp_perform_mail(struct connectdata *conn)
/* Parse the AUTH mailbox into the local address and host name parts,
converting the host name to an IDN A-label if necessary */
- result = smtp_parse_address(conn, data->set.str[STRING_MAIL_AUTH],
+ result = smtp_parse_address(data, data->set.str[STRING_MAIL_AUTH],
&address, &host);
if(result) {
free(from);
@@ -658,7 +675,7 @@ static CURLcode smtp_perform_mail(struct connectdata *conn)
NULL, MIMESTRATEGY_MAIL);
if(!result)
- if(!Curl_checkheaders(conn, "Mime-Version"))
+ if(!Curl_checkheaders(data, "Mime-Version"))
result = Curl_mime_add_header(&data->set.mimepost.curlheaders,
"Mime-Version: 1.0");
@@ -697,7 +714,7 @@ static CURLcode smtp_perform_mail(struct connectdata *conn)
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.protop;
+ struct SMTP *smtp = data->req.p.smtp;
struct curl_slist *rcpt = smtp->rcpt;
while(rcpt && !utf8) {
@@ -710,7 +727,7 @@ static CURLcode smtp_perform_mail(struct connectdata *conn)
}
/* Send the MAIL command */
- result = Curl_pp_sendf(&conn->proto.smtpc.pp,
+ result = Curl_pp_sendf(data, &conn->proto.smtpc.pp,
"MAIL FROM:%s%s%s%s%s%s",
from, /* Mandatory */
auth ? " AUTH=" : "", /* Optional on AUTH support */
@@ -725,7 +742,7 @@ static CURLcode smtp_perform_mail(struct connectdata *conn)
free(size);
if(!result)
- state(conn, SMTP_MAIL);
+ state(data, SMTP_MAIL);
return result;
}
@@ -737,35 +754,36 @@ static CURLcode smtp_perform_mail(struct connectdata *conn)
* Sends a RCPT TO command for a given recipient as part of the message upload
* process.
*/
-static CURLcode smtp_perform_rcpt_to(struct connectdata *conn)
+static CURLcode smtp_perform_rcpt_to(struct Curl_easy *data)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
- struct SMTP *smtp = data->req.protop;
+ struct connectdata *conn = data->conn;
+ struct SMTP *smtp = data->req.p.smtp;
char *address = NULL;
struct hostname host = { NULL, NULL, NULL, NULL };
/* Parse the recipient mailbox into the local address and host name parts,
converting the host name to an IDN A-label if necessary */
- result = smtp_parse_address(conn, smtp->rcpt->data,
+ result = smtp_parse_address(data, smtp->rcpt->data,
&address, &host);
if(result)
return result;
/* Send the RCPT TO command */
if(host.name)
- result = Curl_pp_sendf(&conn->proto.smtpc.pp, "RCPT TO:<%s@%s>", address,
- host.name);
+ result = Curl_pp_sendf(data, &conn->proto.smtpc.pp, "RCPT TO:<%s@%s>",
+ address, host.name);
else
/* An invalid mailbox was provided but we'll simply let the server worry
about that and reply with a 501 error */
- result = Curl_pp_sendf(&conn->proto.smtpc.pp, "RCPT TO:<%s>", address);
+ result = Curl_pp_sendf(data, &conn->proto.smtpc.pp, "RCPT TO:<%s>",
+ address);
Curl_free_idnconverted_hostname(&host);
free(address);
if(!result)
- state(conn, SMTP_RCPT);
+ state(data, SMTP_RCPT);
return result;
}
@@ -776,25 +794,24 @@ static CURLcode smtp_perform_rcpt_to(struct connectdata *conn)
*
* Performs the quit action prior to sclose() being called.
*/
-static CURLcode smtp_perform_quit(struct connectdata *conn)
+static CURLcode smtp_perform_quit(struct Curl_easy *data,
+ struct connectdata *conn)
{
/* Send the QUIT command */
- CURLcode result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", "QUIT");
+ CURLcode result = Curl_pp_sendf(data, &conn->proto.smtpc.pp, "%s", "QUIT");
if(!result)
- state(conn, SMTP_QUIT);
+ state(data, SMTP_QUIT);
return result;
}
/* For the initial server greeting */
-static CURLcode smtp_state_servergreet_resp(struct connectdata *conn,
+static CURLcode smtp_state_servergreet_resp(struct Curl_easy *data,
int smtpcode,
smtpstate instate)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
-
(void)instate; /* no use for this yet */
if(smtpcode/100 != 2) {
@@ -802,19 +819,17 @@ static CURLcode smtp_state_servergreet_resp(struct connectdata *conn,
result = CURLE_WEIRD_SERVER_REPLY;
}
else
- result = smtp_perform_ehlo(conn);
+ result = smtp_perform_ehlo(data);
return result;
}
/* For STARTTLS responses */
-static CURLcode smtp_state_starttls_resp(struct connectdata *conn,
+static CURLcode smtp_state_starttls_resp(struct Curl_easy *data,
int smtpcode,
smtpstate instate)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
-
(void)instate; /* no use for this yet */
if(smtpcode != 220) {
@@ -823,20 +838,20 @@ static CURLcode smtp_state_starttls_resp(struct connectdata *conn,
result = CURLE_USE_SSL_FAILED;
}
else
- result = smtp_perform_authentication(conn);
+ result = smtp_perform_authentication(data);
}
else
- result = smtp_perform_upgrade_tls(conn);
+ result = smtp_perform_upgrade_tls(data);
return result;
}
/* For EHLO responses */
-static CURLcode smtp_state_ehlo_resp(struct connectdata *conn, int smtpcode,
+static CURLcode smtp_state_ehlo_resp(struct Curl_easy *data,
+ struct connectdata *conn, int smtpcode,
smtpstate instate)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
struct smtp_conn *smtpc = &conn->proto.smtpc;
const char *line = data->state.buffer;
size_t len = strlen(line);
@@ -845,7 +860,7 @@ static CURLcode smtp_state_ehlo_resp(struct connectdata *conn, int smtpcode,
if(smtpcode/100 != 2 && smtpcode != 1) {
if(data->set.use_ssl <= CURLUSESSL_TRY || conn->ssl[FIRSTSOCKET].use)
- result = smtp_perform_helo(conn);
+ result = smtp_perform_helo(data, conn);
else {
failf(data, "Remote access denied: %d", smtpcode);
result = CURLE_REMOTE_ACCESS_DENIED;
@@ -913,17 +928,17 @@ static CURLcode smtp_state_ehlo_resp(struct connectdata *conn, int smtpcode,
/* We don't have a SSL/TLS connection yet, but SSL is requested */
if(smtpc->tls_supported)
/* Switch to TLS connection now */
- result = smtp_perform_starttls(conn);
+ result = smtp_perform_starttls(data, conn);
else if(data->set.use_ssl == CURLUSESSL_TRY)
/* Fallback and carry on with authentication */
- result = smtp_perform_authentication(conn);
+ result = smtp_perform_authentication(data);
else {
failf(data, "STARTTLS not supported.");
result = CURLE_USE_SSL_FAILED;
}
}
else
- result = smtp_perform_authentication(conn);
+ result = smtp_perform_authentication(data);
}
}
else {
@@ -935,12 +950,10 @@ static CURLcode smtp_state_ehlo_resp(struct connectdata *conn, int smtpcode,
}
/* For HELO responses */
-static CURLcode smtp_state_helo_resp(struct connectdata *conn, int smtpcode,
+static CURLcode smtp_state_helo_resp(struct Curl_easy *data, int smtpcode,
smtpstate instate)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
-
(void)instate; /* no use for this yet */
if(smtpcode/100 != 2) {
@@ -949,28 +962,28 @@ static CURLcode smtp_state_helo_resp(struct connectdata *conn, int smtpcode,
}
else
/* End of connect phase */
- state(conn, SMTP_STOP);
+ state(data, SMTP_STOP);
return result;
}
/* For SASL authentication responses */
-static CURLcode smtp_state_auth_resp(struct connectdata *conn,
+static CURLcode smtp_state_auth_resp(struct Curl_easy *data,
int smtpcode,
smtpstate instate)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
+ struct connectdata *conn = data->conn;
struct smtp_conn *smtpc = &conn->proto.smtpc;
saslprogress progress;
(void)instate; /* no use for this yet */
- result = Curl_sasl_continue(&smtpc->sasl, conn, smtpcode, &progress);
+ result = Curl_sasl_continue(&smtpc->sasl, data, conn, smtpcode, &progress);
if(!result)
switch(progress) {
case SASL_DONE:
- state(conn, SMTP_STOP); /* Authenticated */
+ state(data, SMTP_STOP); /* Authenticated */
break;
case SASL_IDLE: /* No mechanism left after cancellation */
failf(data, "Authentication cancelled");
@@ -984,12 +997,11 @@ static CURLcode smtp_state_auth_resp(struct connectdata *conn,
}
/* For command responses */
-static CURLcode smtp_state_command_resp(struct connectdata *conn, int smtpcode,
+static CURLcode smtp_state_command_resp(struct Curl_easy *data, int smtpcode,
smtpstate instate)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
- struct SMTP *smtp = data->req.protop;
+ struct SMTP *smtp = data->req.p.smtp;
char *line = data->state.buffer;
size_t len = strlen(line);
@@ -1004,7 +1016,7 @@ static CURLcode smtp_state_command_resp(struct connectdata *conn, int smtpcode,
/* Temporarily add the LF character back and send as body to the client */
if(!data->set.opt_no_body) {
line[len] = '\n';
- result = Curl_client_write(conn, CLIENTWRITE_BODY, line, len + 1);
+ result = Curl_client_write(data, CLIENTWRITE_BODY, line, len + 1);
line[len] = '\0';
}
@@ -1014,15 +1026,15 @@ static CURLcode smtp_state_command_resp(struct connectdata *conn, int smtpcode,
if(smtp->rcpt) {
/* Send the next command */
- result = smtp_perform_command(conn);
+ result = smtp_perform_command(data);
}
else
/* End of DO phase */
- state(conn, SMTP_STOP);
+ state(data, SMTP_STOP);
}
else
/* End of DO phase */
- state(conn, SMTP_STOP);
+ state(data, SMTP_STOP);
}
}
@@ -1030,12 +1042,10 @@ static CURLcode smtp_state_command_resp(struct connectdata *conn, int smtpcode,
}
/* For MAIL responses */
-static CURLcode smtp_state_mail_resp(struct connectdata *conn, int smtpcode,
+static CURLcode smtp_state_mail_resp(struct Curl_easy *data, int smtpcode,
smtpstate instate)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
-
(void)instate; /* no use for this yet */
if(smtpcode/100 != 2) {
@@ -1044,18 +1054,18 @@ static CURLcode smtp_state_mail_resp(struct connectdata *conn, int smtpcode,
}
else
/* Start the RCPT TO command */
- result = smtp_perform_rcpt_to(conn);
+ result = smtp_perform_rcpt_to(data);
return result;
}
/* For RCPT responses */
-static CURLcode smtp_state_rcpt_resp(struct connectdata *conn, int smtpcode,
+static CURLcode smtp_state_rcpt_resp(struct Curl_easy *data,
+ struct connectdata *conn, int smtpcode,
smtpstate instate)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
- struct SMTP *smtp = data->req.protop;
+ struct SMTP *smtp = data->req.p.smtp;
bool is_smtp_err = FALSE;
bool is_smtp_blocking_err = FALSE;
@@ -1088,7 +1098,7 @@ static CURLcode smtp_state_rcpt_resp(struct connectdata *conn, int smtpcode,
if(smtp->rcpt)
/* Send the next RCPT TO command */
- result = smtp_perform_rcpt_to(conn);
+ result = smtp_perform_rcpt_to(data);
else {
/* We weren't able to issue a successful RCPT TO command while going
over recipients (potentially multiple). Sending back last error. */
@@ -1098,10 +1108,10 @@ static CURLcode smtp_state_rcpt_resp(struct connectdata *conn, int smtpcode,
}
else {
/* Send the DATA command */
- result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", "DATA");
+ result = Curl_pp_sendf(data, &conn->proto.smtpc.pp, "%s", "DATA");
if(!result)
- state(conn, SMTP_DATA);
+ state(data, SMTP_DATA);
}
}
}
@@ -1110,12 +1120,10 @@ static CURLcode smtp_state_rcpt_resp(struct connectdata *conn, int smtpcode,
}
/* For DATA response */
-static CURLcode smtp_state_data_resp(struct connectdata *conn, int smtpcode,
+static CURLcode smtp_state_data_resp(struct Curl_easy *data, int smtpcode,
smtpstate instate)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
-
(void)instate; /* no use for this yet */
if(smtpcode != 354) {
@@ -1130,7 +1138,7 @@ static CURLcode smtp_state_data_resp(struct connectdata *conn, int smtpcode,
Curl_setup_transfer(data, -1, -1, FALSE, FIRSTSOCKET);
/* End of DO phase */
- state(conn, SMTP_STOP);
+ state(data, SMTP_STOP);
}
return result;
@@ -1138,7 +1146,7 @@ static CURLcode smtp_state_data_resp(struct connectdata *conn, 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 connectdata *conn,
+static CURLcode smtp_state_postdata_resp(struct Curl_easy *data,
int smtpcode,
smtpstate instate)
{
@@ -1150,16 +1158,16 @@ static CURLcode smtp_state_postdata_resp(struct connectdata *conn,
result = CURLE_RECV_ERROR;
/* End of DONE phase */
- state(conn, SMTP_STOP);
+ state(data, SMTP_STOP);
return result;
}
-static CURLcode smtp_statemach_act(struct connectdata *conn)
+static CURLcode smtp_statemachine(struct Curl_easy *data,
+ struct connectdata *conn)
{
CURLcode result = CURLE_OK;
curl_socket_t sock = conn->sock[FIRSTSOCKET];
- struct Curl_easy *data = conn->data;
int smtpcode;
struct smtp_conn *smtpc = &conn->proto.smtpc;
struct pingpong *pp = &smtpc->pp;
@@ -1167,15 +1175,15 @@ static CURLcode smtp_statemach_act(struct connectdata *conn)
/* Busy upgrading the connection; right now all I/O is SSL/TLS, not SMTP */
if(smtpc->state == SMTP_UPGRADETLS)
- return smtp_perform_upgrade_tls(conn);
+ return smtp_perform_upgrade_tls(data);
/* Flush any data that needs to be sent */
if(pp->sendleft)
- return Curl_pp_flushsend(pp);
+ return Curl_pp_flushsend(data, pp);
do {
/* Read the response from the server */
- result = Curl_pp_readresp(sock, pp, &smtpcode, &nread);
+ result = Curl_pp_readresp(data, sock, pp, &smtpcode, &nread);
if(result)
return result;
@@ -1189,50 +1197,50 @@ static CURLcode smtp_statemach_act(struct connectdata *conn)
/* We have now received a full SMTP server response */
switch(smtpc->state) {
case SMTP_SERVERGREET:
- result = smtp_state_servergreet_resp(conn, smtpcode, smtpc->state);
+ result = smtp_state_servergreet_resp(data, smtpcode, smtpc->state);
break;
case SMTP_EHLO:
- result = smtp_state_ehlo_resp(conn, smtpcode, smtpc->state);
+ result = smtp_state_ehlo_resp(data, conn, smtpcode, smtpc->state);
break;
case SMTP_HELO:
- result = smtp_state_helo_resp(conn, smtpcode, smtpc->state);
+ result = smtp_state_helo_resp(data, smtpcode, smtpc->state);
break;
case SMTP_STARTTLS:
- result = smtp_state_starttls_resp(conn, smtpcode, smtpc->state);
+ result = smtp_state_starttls_resp(data, smtpcode, smtpc->state);
break;
case SMTP_AUTH:
- result = smtp_state_auth_resp(conn, smtpcode, smtpc->state);
+ result = smtp_state_auth_resp(data, smtpcode, smtpc->state);
break;
case SMTP_COMMAND:
- result = smtp_state_command_resp(conn, smtpcode, smtpc->state);
+ result = smtp_state_command_resp(data, smtpcode, smtpc->state);
break;
case SMTP_MAIL:
- result = smtp_state_mail_resp(conn, smtpcode, smtpc->state);
+ result = smtp_state_mail_resp(data, smtpcode, smtpc->state);
break;
case SMTP_RCPT:
- result = smtp_state_rcpt_resp(conn, smtpcode, smtpc->state);
+ result = smtp_state_rcpt_resp(data, conn, smtpcode, smtpc->state);
break;
case SMTP_DATA:
- result = smtp_state_data_resp(conn, smtpcode, smtpc->state);
+ result = smtp_state_data_resp(data, smtpcode, smtpc->state);
break;
case SMTP_POSTDATA:
- result = smtp_state_postdata_resp(conn, smtpcode, smtpc->state);
+ result = smtp_state_postdata_resp(data, smtpcode, smtpc->state);
break;
case SMTP_QUIT:
/* fallthrough, just stop! */
default:
/* internal error */
- state(conn, SMTP_STOP);
+ state(data, SMTP_STOP);
break;
}
} while(!result && smtpc->state != SMTP_STOP && Curl_pp_moredata(pp));
@@ -1241,44 +1249,46 @@ static CURLcode smtp_statemach_act(struct connectdata *conn)
}
/* Called repeatedly until done from multi.c */
-static CURLcode smtp_multi_statemach(struct connectdata *conn, bool *done)
+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;
if((conn->handler->flags & PROTOPT_SSL) && !smtpc->ssldone) {
- result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, &smtpc->ssldone);
+ result = Curl_ssl_connect_nonblocking(data, conn,
+ FIRSTSOCKET, &smtpc->ssldone);
if(result || !smtpc->ssldone)
return result;
}
- result = Curl_pp_statemach(&smtpc->pp, FALSE, FALSE);
+ result = Curl_pp_statemach(data, &smtpc->pp, FALSE, FALSE);
*done = (smtpc->state == SMTP_STOP) ? TRUE : FALSE;
return result;
}
-static CURLcode smtp_block_statemach(struct connectdata *conn,
+static CURLcode smtp_block_statemach(struct Curl_easy *data,
+ struct connectdata *conn,
bool disconnecting)
{
CURLcode result = CURLE_OK;
struct smtp_conn *smtpc = &conn->proto.smtpc;
while(smtpc->state != SMTP_STOP && !result)
- result = Curl_pp_statemach(&smtpc->pp, TRUE, disconnecting);
+ result = Curl_pp_statemach(data, &smtpc->pp, TRUE, disconnecting);
return result;
}
/* Allocate and initialize the SMTP struct for the current Curl_easy if
required */
-static CURLcode smtp_init(struct connectdata *conn)
+static CURLcode smtp_init(struct Curl_easy *data)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
struct SMTP *smtp;
- smtp = data->req.protop = calloc(sizeof(struct SMTP), 1);
+ smtp = data->req.p.smtp = calloc(sizeof(struct SMTP), 1);
if(!smtp)
result = CURLE_OUT_OF_MEMORY;
@@ -1286,9 +1296,10 @@ static CURLcode smtp_init(struct connectdata *conn)
}
/* For the SMTP "protocol connect" and "doing" phases only */
-static int smtp_getsock(struct connectdata *conn, curl_socket_t *socks)
+static int smtp_getsock(struct Curl_easy *data,
+ struct connectdata *conn, curl_socket_t *socks)
{
- return Curl_pp_getsock(&conn->proto.smtpc.pp, socks);
+ return Curl_pp_getsock(data, &conn->proto.smtpc.pp, socks);
}
/***********************************************************************
@@ -1301,9 +1312,10 @@ static int smtp_getsock(struct connectdata *conn, curl_socket_t *socks)
* The variable pointed to by 'done' will be TRUE if the protocol-layer
* connect phase is done when this function returns, or FALSE if not.
*/
-static CURLcode smtp_connect(struct connectdata *conn, bool *done)
+static CURLcode smtp_connect(struct Curl_easy *data, bool *done)
{
CURLcode result = CURLE_OK;
+ struct connectdata *conn = data->conn;
struct smtp_conn *smtpc = &conn->proto.smtpc;
struct pingpong *pp = &smtpc->pp;
@@ -1312,17 +1324,14 @@ static CURLcode smtp_connect(struct connectdata *conn, bool *done)
/* We always support persistent connections in SMTP */
connkeep(conn, "SMTP default");
- /* Set the default response time-out */
- pp->response_time = RESP_TIMEOUT;
- pp->statemach_act = smtp_statemach_act;
- pp->endofresp = smtp_endofresp;
- pp->conn = conn;
+ PINGPONG_SETUP(pp, smtp_statemachine, smtp_endofresp);
/* Initialize the SASL storage */
Curl_sasl_init(&smtpc->sasl, &saslsmtp);
/* Initialise the pingpong layer */
- Curl_pp_init(pp);
+ Curl_pp_setup(pp);
+ Curl_pp_init(data, pp);
/* Parse the URL options */
result = smtp_parse_url_options(conn);
@@ -1330,14 +1339,14 @@ static CURLcode smtp_connect(struct connectdata *conn, bool *done)
return result;
/* Parse the URL path */
- result = smtp_parse_url_path(conn);
+ result = smtp_parse_url_path(data);
if(result)
return result;
/* Start off waiting for the server greeting response */
- state(conn, SMTP_SERVERGREET);
+ state(data, SMTP_SERVERGREET);
- result = smtp_multi_statemach(conn, done);
+ result = smtp_multi_statemach(data, done);
return result;
}
@@ -1351,12 +1360,12 @@ static CURLcode smtp_connect(struct connectdata *conn, bool *done)
*
* Input argument is already checked for validity.
*/
-static CURLcode smtp_done(struct connectdata *conn, CURLcode status,
+static CURLcode smtp_done(struct Curl_easy *data, CURLcode status,
bool premature)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
- struct SMTP *smtp = data->req.protop;
+ struct connectdata *conn = data->conn;
+ struct SMTP *smtp = data->req.p.smtp;
struct pingpong *pp = &conn->proto.smtpc.pp;
char *eob;
ssize_t len;
@@ -1364,7 +1373,7 @@ static CURLcode smtp_done(struct connectdata *conn, CURLcode status,
(void)premature;
- if(!smtp || !pp->conn)
+ if(!smtp)
return CURLE_OK;
/* Cleanup our per-request based variables */
@@ -1384,7 +1393,7 @@ static CURLcode smtp_done(struct connectdata *conn, CURLcode status,
fail when using a different pointer following a previous write, that
returned CURLE_AGAIN, we duplicate the EOB now rather than when the
bytes written doesn't equal len. */
- if(smtp->trailing_crlf || !conn->data->state.infilesize) {
+ if(smtp->trailing_crlf || !data->state.infilesize) {
eob = strdup(&SMTP_EOB[2]);
len = SMTP_EOB_LEN - 2;
}
@@ -1397,7 +1406,7 @@ static CURLcode smtp_done(struct connectdata *conn, CURLcode status,
return CURLE_OUT_OF_MEMORY;
/* Send the end of block data */
- result = Curl_write(conn, conn->writesockfd, eob, len, &bytes_written);
+ result = Curl_write(data, conn->writesockfd, eob, len, &bytes_written);
if(result) {
free(eob);
return result;
@@ -1417,10 +1426,10 @@ static CURLcode smtp_done(struct connectdata *conn, CURLcode status,
free(eob);
}
- state(conn, SMTP_POSTDATA);
+ state(data, SMTP_POSTDATA);
/* Run the state-machine */
- result = smtp_block_statemach(conn, FALSE);
+ result = smtp_block_statemach(data, conn, FALSE);
}
/* Clear the transfer mode for the next request */
@@ -1436,15 +1445,15 @@ static CURLcode smtp_done(struct connectdata *conn, 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 connectdata *conn, bool *connected,
+static CURLcode smtp_perform(struct Curl_easy *data, bool *connected,
bool *dophase_done)
{
/* This is SMTP and no proxy */
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
- struct SMTP *smtp = data->req.protop;
+ struct connectdata *conn = data->conn;
+ struct SMTP *smtp = data->req.p.smtp;
- DEBUGF(infof(conn->data, "DO phase starts\n"));
+ DEBUGF(infof(data, "DO phase starts\n"));
if(data->set.opt_no_body) {
/* Requested no body means no transfer */
@@ -1470,21 +1479,21 @@ static CURLcode smtp_perform(struct connectdata *conn, bool *connected,
/* Start the first command in the DO phase */
if((data->set.upload || data->set.mimepost.kind) && data->set.mail_rcpt)
/* MAIL transfer */
- result = smtp_perform_mail(conn);
+ result = smtp_perform_mail(data);
else
/* SMTP based command (VRFY, EXPN, NOOP, RSET or HELP) */
- result = smtp_perform_command(conn);
+ result = smtp_perform_command(data);
if(result)
return result;
/* Run the state-machine */
- result = smtp_multi_statemach(conn, dophase_done);
+ result = smtp_multi_statemach(data, dophase_done);
*connected = conn->bits.tcpconnect[FIRSTSOCKET];
if(*dophase_done)
- DEBUGF(infof(conn->data, "DO phase is complete\n"));
+ DEBUGF(infof(data, "DO phase is complete\n"));
return result;
}
@@ -1498,18 +1507,17 @@ static CURLcode smtp_perform(struct connectdata *conn, bool *connected,
*
* The input argument is already checked for validity.
*/
-static CURLcode smtp_do(struct connectdata *conn, bool *done)
+static CURLcode smtp_do(struct Curl_easy *data, bool *done)
{
CURLcode result = CURLE_OK;
-
*done = FALSE; /* default to false */
/* Parse the custom request */
- result = smtp_parse_custom_request(conn);
+ result = smtp_parse_custom_request(data);
if(result)
return result;
- result = smtp_regular_transfer(conn, done);
+ result = smtp_regular_transfer(data, done);
return result;
}
@@ -1521,19 +1529,21 @@ static CURLcode smtp_do(struct connectdata *conn, bool *done)
* Disconnect from an SMTP server. Cleanup protocol-specific per-connection
* resources. BLOCKING.
*/
-static CURLcode smtp_disconnect(struct connectdata *conn, bool dead_connection)
+static CURLcode smtp_disconnect(struct Curl_easy *data,
+ struct connectdata *conn,
+ bool dead_connection)
{
struct smtp_conn *smtpc = &conn->proto.smtpc;
+ (void)data;
/* 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. */
- /* The SMTP session may or may not have been allocated/setup at this
- point! */
- if(!dead_connection && smtpc->pp.conn && smtpc->pp.conn->bits.protoconnstart)
- if(!smtp_perform_quit(conn))
- (void)smtp_block_statemach(conn, TRUE); /* ignore errors on QUIT */
+ if(!dead_connection && conn->bits.protoconnstart) {
+ if(!smtp_perform_quit(data, conn))
+ (void)smtp_block_statemach(data, conn, TRUE); /* ignore errors on QUIT */
+ }
/* Disconnect from the server */
Curl_pp_disconnect(&smtpc->pp);
@@ -1548,30 +1558,30 @@ static CURLcode smtp_disconnect(struct connectdata *conn, bool dead_connection)
}
/* Call this when the DO phase has completed */
-static CURLcode smtp_dophase_done(struct connectdata *conn, bool connected)
+static CURLcode smtp_dophase_done(struct Curl_easy *data, bool connected)
{
- struct SMTP *smtp = conn->data->req.protop;
+ struct SMTP *smtp = data->req.p.smtp;
(void)connected;
if(smtp->transfer != FTPTRANSFER_BODY)
/* no data to transfer */
- Curl_setup_transfer(conn->data, -1, -1, FALSE, -1);
+ Curl_setup_transfer(data, -1, -1, FALSE, -1);
return CURLE_OK;
}
/* Called from multi.c while DOing */
-static CURLcode smtp_doing(struct connectdata *conn, bool *dophase_done)
+static CURLcode smtp_doing(struct Curl_easy *data, bool *dophase_done)
{
- CURLcode result = smtp_multi_statemach(conn, dophase_done);
+ CURLcode result = smtp_multi_statemach(data, dophase_done);
if(result)
- DEBUGF(infof(conn->data, "DO phase failed\n"));
+ DEBUGF(infof(data, "DO phase failed\n"));
else if(*dophase_done) {
- result = smtp_dophase_done(conn, FALSE /* not connected */);
+ result = smtp_dophase_done(data, FALSE /* not connected */);
- DEBUGF(infof(conn->data, "DO phase is complete\n"));
+ DEBUGF(infof(data, "DO phase is complete\n"));
}
return result;
@@ -1586,12 +1596,11 @@ static CURLcode smtp_doing(struct connectdata *conn, bool *dophase_done)
* Performs all commands done before a regular transfer between a local and a
* remote host.
*/
-static CURLcode smtp_regular_transfer(struct connectdata *conn,
+static CURLcode smtp_regular_transfer(struct Curl_easy *data,
bool *dophase_done)
{
CURLcode result = CURLE_OK;
bool connected = FALSE;
- struct Curl_easy *data = conn->data;
/* Make sure size is unknown at this point */
data->req.size = -1;
@@ -1603,16 +1612,17 @@ static CURLcode smtp_regular_transfer(struct connectdata *conn,
Curl_pgrsSetDownloadSize(data, -1);
/* Carry out the perform */
- result = smtp_perform(conn, &connected, dophase_done);
+ result = smtp_perform(data, &connected, dophase_done);
/* Perform post DO phase operations if necessary */
if(!result && *dophase_done)
- result = smtp_dophase_done(conn, connected);
+ result = smtp_dophase_done(data, connected);
return result;
}
-static CURLcode smtp_setup_connection(struct connectdata *conn)
+static CURLcode smtp_setup_connection(struct Curl_easy *data,
+ struct connectdata *conn)
{
CURLcode result;
@@ -1620,7 +1630,7 @@ static CURLcode smtp_setup_connection(struct connectdata *conn)
conn->bits.tls_upgraded = FALSE;
/* Initialise the SMTP layer */
- result = smtp_init(conn);
+ result = smtp_init(data);
if(result)
return result;
@@ -1672,10 +1682,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 connectdata *conn)
+static CURLcode smtp_parse_url_path(struct Curl_easy *data)
{
/* The SMTP struct is already initialised in smtp_connect() */
- struct Curl_easy *data = conn->data;
+ 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,7 +1699,7 @@ static CURLcode smtp_parse_url_path(struct connectdata *conn)
}
/* URL decode the path and use it as the domain in our EHLO */
- return Curl_urldecode(conn->data, path, 0, &smtpc->domain, NULL,
+ return Curl_urldecode(data, path, 0, &smtpc->domain, NULL,
REJECT_CTRL);
}
@@ -1699,11 +1709,10 @@ static CURLcode smtp_parse_url_path(struct connectdata *conn)
*
* Parse the custom request.
*/
-static CURLcode smtp_parse_custom_request(struct connectdata *conn)
+static CURLcode smtp_parse_custom_request(struct Curl_easy *data)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
- struct SMTP *smtp = data->req.protop;
+ struct SMTP *smtp = data->req.p.smtp;
const char *custom = data->set.str[STRING_CUSTOMREQUEST];
/* URL decode the custom request */
@@ -1747,7 +1756,7 @@ static CURLcode smtp_parse_custom_request(struct connectdata *conn)
* calling function deems it to be) then the input will simply be returned in
* the address part with the host name being NULL.
*/
-static CURLcode smtp_parse_address(struct connectdata *conn, const char *fqma,
+static CURLcode smtp_parse_address(struct Curl_easy *data, const char *fqma,
char **address, struct hostname *host)
{
CURLcode result = CURLE_OK;
@@ -1772,7 +1781,7 @@ static CURLcode smtp_parse_address(struct connectdata *conn, const char *fqma,
host->name = host->name + 1;
/* Attempt to convert the host name to IDN ACE */
- (void) Curl_idnconvert_hostname(conn, host);
+ (void) Curl_idnconvert_hostname(data, host);
/* If Curl_idnconvert_hostname() fails then we shall attempt to continue
and send the host name using UTF-8 rather than as 7-bit ACE (which is
@@ -1785,7 +1794,7 @@ static CURLcode smtp_parse_address(struct connectdata *conn, const char *fqma,
return result;
}
-CURLcode Curl_smtp_escape_eob(struct connectdata *conn, const ssize_t nread)
+CURLcode Curl_smtp_escape_eob(struct Curl_easy *data, const ssize_t nread)
{
/* When sending a SMTP payload we must detect CRLF. sequences making sure
they are sent as CRLF.. instead, as a . on the beginning of a line will
@@ -1795,8 +1804,7 @@ CURLcode Curl_smtp_escape_eob(struct connectdata *conn, const ssize_t nread)
*/
ssize_t i;
ssize_t si;
- struct Curl_easy *data = conn->data;
- struct SMTP *smtp = data->req.protop;
+ struct SMTP *smtp = data->req.p.smtp;
char *scratch = data->state.scratch;
char *newscratch = NULL;
char *oldscratch = NULL;
diff --git a/Utilities/cmcurl/lib/smtp.h b/Utilities/cmcurl/lib/smtp.h
index 164a175d7..1fe45346e 100644
--- a/Utilities/cmcurl/lib/smtp.h
+++ b/Utilities/cmcurl/lib/smtp.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2009 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2009 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -57,10 +57,10 @@ struct SMTP {
struct curl_slist *rcpt; /* Recipient list */
bool rcpt_had_ok; /* Whether any of RCPT TO commands (depends on
total number of recipients) succeeded so far */
+ bool trailing_crlf; /* Specifies if the trailing CRLF is present */
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 */
- bool trailing_crlf; /* Specifies if the tailing CRLF is present */
};
/* smtp_conn is used for struct connection-oriented data in the connectdata
@@ -91,6 +91,6 @@ extern const struct Curl_handler Curl_handler_smtps;
#define SMTP_EOB_REPL "\x0d\x0a\x2e\x2e"
#define SMTP_EOB_REPL_LEN 4
-CURLcode Curl_smtp_escape_eob(struct connectdata *conn, const ssize_t nread);
+CURLcode Curl_smtp_escape_eob(struct Curl_easy *data, const ssize_t nread);
#endif /* HEADER_CURL_SMTP_H */
diff --git a/Utilities/cmcurl/lib/sockaddr.h b/Utilities/cmcurl/lib/sockaddr.h
index b037ee06c..84c08d9bb 100644
--- a/Utilities/cmcurl/lib/sockaddr.h
+++ b/Utilities/cmcurl/lib/sockaddr.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
diff --git a/Utilities/cmcurl/lib/socketpair.c b/Utilities/cmcurl/lib/socketpair.c
index 1ec0d75a4..2c580ad2d 100644
--- a/Utilities/cmcurl/lib/socketpair.c
+++ b/Utilities/cmcurl/lib/socketpair.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2019 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -23,7 +23,7 @@
#include "curl_setup.h"
#include "socketpair.h"
-#ifndef HAVE_SOCKETPAIR
+#if !defined(HAVE_SOCKETPAIR) && !defined(CURL_DISABLE_SOCKETPAIR)
#ifdef WIN32
/*
* This is a socketpair() implementation for Windows.
diff --git a/Utilities/cmcurl/lib/socketpair.h b/Utilities/cmcurl/lib/socketpair.h
index be9fb24f9..033a235aa 100644
--- a/Utilities/cmcurl/lib/socketpair.h
+++ b/Utilities/cmcurl/lib/socketpair.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2019 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/socks.c b/Utilities/cmcurl/lib/socks.c
index 44783d015..d1c2a2ed1 100644
--- a/Utilities/cmcurl/lib/socks.c
+++ b/Utilities/cmcurl/lib/socks.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -51,7 +51,7 @@
*
* This is STUPID BLOCKING behavior. Only used by the SOCKS GSSAPI functions.
*/
-int Curl_blockread_all(struct connectdata *conn, /* connection data */
+int Curl_blockread_all(struct Curl_easy *data, /* transfer */
curl_socket_t sockfd, /* read from this socket */
char *buf, /* store read data here */
ssize_t buffersize, /* max amount to read */
@@ -62,7 +62,7 @@ int Curl_blockread_all(struct connectdata *conn, /* connection data */
int result;
*n = 0;
for(;;) {
- timediff_t timeout_ms = Curl_timeleft(conn->data, NULL, TRUE);
+ timediff_t timeout_ms = Curl_timeleft(data, NULL, TRUE);
if(timeout_ms < 0) {
/* we already got the timeout */
result = CURLE_OPERATION_TIMEDOUT;
@@ -107,13 +107,14 @@ int Curl_blockread_all(struct connectdata *conn, /* connection data */
/* always use this function to change state, to make debugging easier */
-static void socksstate(struct connectdata *conn,
+static void socksstate(struct Curl_easy *data,
enum connect_t state
#ifdef DEBUGBUILD
, int lineno
#endif
)
{
+ struct connectdata *conn = data->conn;
enum connect_t oldstate = conn->cnnct.state;
#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
/* synced with the state list in urldata.h */
@@ -146,7 +147,7 @@ static void socksstate(struct connectdata *conn,
conn->cnnct.state = state;
#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
- infof(conn->data,
+ infof(data,
"SXSTATE: %s => %s conn %p; line %d\n",
statename[oldstate], statename[conn->cnnct.state], conn,
lineno);
@@ -184,33 +185,36 @@ int Curl_SOCKS_getsock(struct connectdata *conn, curl_socket_t *sock,
* Set protocol4a=true for "SOCKS 4A (Simple Extension to SOCKS 4 Protocol)"
* Nonsupport "Identification Protocol (RFC1413)"
*/
-CURLcode Curl_SOCKS4(const char *proxy_user,
- const char *hostname,
- int remote_port,
- int sockindex,
- struct connectdata *conn,
- bool *done)
+CURLproxycode Curl_SOCKS4(const char *proxy_user,
+ const char *hostname,
+ int remote_port,
+ int sockindex,
+ struct Curl_easy *data,
+ bool *done)
{
+ struct connectdata *conn = data->conn;
const bool protocol4a =
(conn->socks_proxy.proxytype == CURLPROXY_SOCKS4A) ? TRUE : FALSE;
- unsigned char *socksreq = &conn->cnnct.socksreq[0];
+ unsigned char *socksreq = (unsigned char *)data->state.buffer;
CURLcode result;
curl_socket_t sockfd = conn->sock[sockindex];
- struct Curl_easy *data = conn->data;
struct connstate *sx = &conn->cnnct;
struct Curl_dns_entry *dns = NULL;
ssize_t actualread;
ssize_t written;
+ /* make sure that the buffer is at least 600 bytes */
+ DEBUGASSERT(READBUFFER_MIN >= 600);
+
if(!SOCKS_STATE(sx->state) && !*done)
- sxstate(conn, CONNECT_SOCKS_INIT);
+ sxstate(data, CONNECT_SOCKS_INIT);
switch(sx->state) {
case CONNECT_SOCKS_INIT:
/* SOCKS4 can only do IPv4, insist! */
conn->ip_version = CURL_IPRESOLVE_V4;
if(conn->bits.httpproxy)
- infof(conn->data, "SOCKS4%s: connecting to HTTP proxy %s port %d\n",
+ infof(data, "SOCKS4%s: connecting to HTTP proxy %s port %d\n",
protocol4a ? "a" : "", hostname, remote_port);
infof(data, "SOCKS4 communication to %s:%d\n", hostname, remote_port);
@@ -234,39 +238,42 @@ CURLcode Curl_SOCKS4(const char *proxy_user,
/* DNS resolve only for SOCKS4, not SOCKS4a */
if(!protocol4a) {
enum resolve_t rc =
- Curl_resolv(conn, hostname, remote_port, FALSE, &dns);
+ Curl_resolv(data, hostname, remote_port, FALSE, &dns);
if(rc == CURLRESOLV_ERROR)
- return CURLE_COULDNT_RESOLVE_PROXY;
+ return CURLPX_RESOLVE_HOST;
else if(rc == CURLRESOLV_PENDING) {
- sxstate(conn, CONNECT_RESOLVING);
+ sxstate(data, CONNECT_RESOLVING);
infof(data, "SOCKS4 non-blocking resolve of %s\n", hostname);
- return CURLE_OK;
+ return CURLPX_OK;
}
- sxstate(conn, CONNECT_RESOLVED);
+ sxstate(data, CONNECT_RESOLVED);
goto CONNECT_RESOLVED;
}
/* socks4a doesn't resolve anything locally */
- sxstate(conn, CONNECT_REQ_INIT);
+ sxstate(data, CONNECT_REQ_INIT);
goto CONNECT_REQ_INIT;
case CONNECT_RESOLVING:
/* check if we have the name resolved by now */
- dns = Curl_fetch_addr(conn, hostname, (int)conn->port);
+ dns = Curl_fetch_addr(data, hostname, (int)conn->port);
if(dns) {
#ifdef CURLRES_ASYNCH
- conn->async.dns = dns;
- conn->async.done = TRUE;
+ data->state.async.dns = dns;
+ data->state.async.done = TRUE;
#endif
infof(data, "Hostname '%s' was found\n", hostname);
- sxstate(conn, CONNECT_RESOLVED);
+ sxstate(data, CONNECT_RESOLVED);
}
else {
- result = Curl_resolv_check(data->conn, &dns);
- if(!dns)
- return result;
+ result = Curl_resolv_check(data, &dns);
+ if(!dns) {
+ if(result)
+ return CURLPX_RESOLVE_HOST;
+ return CURLPX_OK;
+ }
}
/* FALLTHROUGH */
CONNECT_RESOLVED:
@@ -295,7 +302,7 @@ CURLcode Curl_SOCKS4(const char *proxy_user,
}
else {
hp = NULL; /* fail! */
- failf(data, "SOCKS4 connection to %s not supported\n", buf);
+ failf(data, "SOCKS4 connection to %s not supported", buf);
}
Curl_resolv_unlock(data, dns); /* not used anymore from now on */
@@ -303,7 +310,7 @@ CURLcode Curl_SOCKS4(const char *proxy_user,
if(!hp) {
failf(data, "Failed to resolve \"%s\" for SOCKS4 connect.",
hostname);
- return CURLE_COULDNT_RESOLVE_HOST;
+ return CURLPX_RESOLVE_HOST;
}
}
/* FALLTHROUGH */
@@ -315,9 +322,9 @@ CURLcode Curl_SOCKS4(const char *proxy_user,
socksreq[8] = 0; /* ensure empty userid is NUL-terminated */
if(proxy_user) {
size_t plen = strlen(proxy_user);
- if(plen >= sizeof(sx->socksreq) - 8) {
- failf(data, "Too long SOCKS proxy name, can't use!\n");
- return CURLE_COULDNT_CONNECT;
+ if(plen >= (size_t)data->set.buffer_size - 8) {
+ failf(data, "Too long SOCKS proxy user name, can't use!");
+ return CURLPX_LONG_USER;
}
/* copy the proxy name WITH trailing zero */
memcpy(socksreq + 8, proxy_user, plen + 1);
@@ -343,34 +350,34 @@ CURLcode Curl_SOCKS4(const char *proxy_user,
strcpy((char *)socksreq + packetsize, hostname);
else {
failf(data, "SOCKS4: too long host name");
- return CURLE_COULDNT_CONNECT;
+ return CURLPX_LONG_HOSTNAME;
}
packetsize += hostnamelen;
}
sx->outp = socksreq;
sx->outstanding = packetsize;
- sxstate(conn, CONNECT_REQ_SENDING);
+ sxstate(data, CONNECT_REQ_SENDING);
}
/* FALLTHROUGH */
case CONNECT_REQ_SENDING:
/* Send request */
- result = Curl_write_plain(conn, sockfd, (char *)sx->outp,
+ result = Curl_write_plain(data, sockfd, (char *)sx->outp,
sx->outstanding, &written);
if(result && (CURLE_AGAIN != result)) {
failf(data, "Failed to send SOCKS4 connect request.");
- return CURLE_COULDNT_CONNECT;
+ return CURLPX_SEND_CONNECT;
}
if(written != sx->outstanding) {
/* not done, remain in state */
sx->outstanding -= written;
sx->outp += written;
- return CURLE_OK;
+ return CURLPX_OK;
}
/* done sending! */
sx->outstanding = 8; /* receive data size */
sx->outp = socksreq;
- sxstate(conn, CONNECT_SOCKS_READ);
+ sxstate(data, CONNECT_SOCKS_READ);
/* FALLTHROUGH */
case CONNECT_SOCKS_READ:
@@ -380,20 +387,20 @@ CURLcode Curl_SOCKS4(const char *proxy_user,
if(result && (CURLE_AGAIN != result)) {
failf(data, "SOCKS4: Failed receiving connect request ack: %s",
curl_easy_strerror(result));
- return CURLE_COULDNT_CONNECT;
+ return CURLPX_RECV_CONNECT;
}
else if(!result && !actualread) {
/* connection closed */
failf(data, "connection to proxy closed");
- return CURLE_COULDNT_CONNECT;
+ return CURLPX_CLOSED;
}
else if(actualread != sx->outstanding) {
/* remain in reading state */
sx->outstanding -= actualread;
sx->outp += actualread;
- return CURLE_OK;
+ return CURLPX_OK;
}
- sxstate(conn, CONNECT_DONE);
+ sxstate(data, CONNECT_DONE);
break;
default: /* lots of unused states in SOCKS4 */
break;
@@ -422,7 +429,7 @@ CURLcode Curl_SOCKS4(const char *proxy_user,
if(socksreq[0] != 0) {
failf(data,
"SOCKS4 reply has wrong version, version should be 0.");
- return CURLE_COULDNT_CONNECT;
+ return CURLPX_BAD_VERSION;
}
/* Result */
@@ -434,57 +441,53 @@ CURLcode Curl_SOCKS4(const char *proxy_user,
failf(data,
"Can't complete SOCKS4 connection to %d.%d.%d.%d:%d. (%d)"
", request rejected or failed.",
- (unsigned char)socksreq[4], (unsigned char)socksreq[5],
- (unsigned char)socksreq[6], (unsigned char)socksreq[7],
+ socksreq[4], socksreq[5], socksreq[6], socksreq[7],
(((unsigned char)socksreq[2] << 8) | (unsigned char)socksreq[3]),
(unsigned char)socksreq[1]);
- return CURLE_COULDNT_CONNECT;
+ return CURLPX_REQUEST_FAILED;
case 92:
failf(data,
"Can't complete SOCKS4 connection to %d.%d.%d.%d:%d. (%d)"
", request rejected because SOCKS server cannot connect to "
"identd on the client.",
- (unsigned char)socksreq[4], (unsigned char)socksreq[5],
- (unsigned char)socksreq[6], (unsigned char)socksreq[7],
+ socksreq[4], socksreq[5], socksreq[6], socksreq[7],
(((unsigned char)socksreq[2] << 8) | (unsigned char)socksreq[3]),
(unsigned char)socksreq[1]);
- return CURLE_COULDNT_CONNECT;
+ return CURLPX_IDENTD;
case 93:
failf(data,
"Can't complete SOCKS4 connection to %d.%d.%d.%d:%d. (%d)"
", request rejected because the client program and identd "
"report different user-ids.",
- (unsigned char)socksreq[4], (unsigned char)socksreq[5],
- (unsigned char)socksreq[6], (unsigned char)socksreq[7],
+ socksreq[4], socksreq[5], socksreq[6], socksreq[7],
(((unsigned char)socksreq[2] << 8) | (unsigned char)socksreq[3]),
(unsigned char)socksreq[1]);
- return CURLE_COULDNT_CONNECT;
+ return CURLPX_IDENTD_DIFFER;
default:
failf(data,
"Can't complete SOCKS4 connection to %d.%d.%d.%d:%d. (%d)"
", Unknown.",
- (unsigned char)socksreq[4], (unsigned char)socksreq[5],
- (unsigned char)socksreq[6], (unsigned char)socksreq[7],
+ socksreq[4], socksreq[5], socksreq[6], socksreq[7],
(((unsigned char)socksreq[2] << 8) | (unsigned char)socksreq[3]),
(unsigned char)socksreq[1]);
- return CURLE_COULDNT_CONNECT;
+ return CURLPX_UNKNOWN_FAIL;
}
*done = TRUE;
- return CURLE_OK; /* Proxy was successful! */
+ return CURLPX_OK; /* Proxy was successful! */
}
/*
* This function logs in to a SOCKS5 proxy and sends the specifics to the final
* destination server.
*/
-CURLcode Curl_SOCKS5(const char *proxy_user,
- const char *proxy_password,
- const char *hostname,
- int remote_port,
- int sockindex,
- struct connectdata *conn,
- bool *done)
+CURLproxycode Curl_SOCKS5(const char *proxy_user,
+ const char *proxy_password,
+ const char *hostname,
+ int remote_port,
+ int sockindex,
+ struct Curl_easy *data,
+ bool *done)
{
/*
According to the RFC1928, section "6. Replies". This is what a SOCK5
@@ -502,14 +505,14 @@ CURLcode Curl_SOCKS5(const char *proxy_user,
o REP Reply field:
o X'00' succeeded
*/
- unsigned char *socksreq = &conn->cnnct.socksreq[0];
+ struct connectdata *conn = data->conn;
+ unsigned char *socksreq = (unsigned char *)data->state.buffer;
char dest[256] = "unknown"; /* printable hostname:port */
int idx;
ssize_t actualread;
ssize_t written;
CURLcode result;
curl_socket_t sockfd = conn->sock[sockindex];
- struct Curl_easy *data = conn->data;
bool socks5_resolve_local =
(conn->socks_proxy.proxytype == CURLPROXY_SOCKS5) ? TRUE : FALSE;
const size_t hostname_len = strlen(hostname);
@@ -520,23 +523,23 @@ CURLcode Curl_SOCKS5(const char *proxy_user,
struct Curl_dns_entry *dns = NULL;
if(!SOCKS_STATE(sx->state) && !*done)
- sxstate(conn, CONNECT_SOCKS_INIT);
+ sxstate(data, CONNECT_SOCKS_INIT);
switch(sx->state) {
case CONNECT_SOCKS_INIT:
if(conn->bits.httpproxy)
- infof(conn->data, "SOCKS5: connecting to HTTP proxy %s port %d\n",
+ infof(data, "SOCKS5: connecting to HTTP proxy %s port %d\n",
hostname, remote_port);
/* RFC1928 chapter 5 specifies max 255 chars for domain name in packet */
if(!socks5_resolve_local && hostname_len > 255) {
- infof(conn->data, "SOCKS5: server resolving disabled for hostnames of "
+ infof(data, "SOCKS5: server resolving disabled for hostnames of "
"length > 255 [actual len=%zu]\n", hostname_len);
socks5_resolve_local = TRUE;
}
if(auth & ~(CURLAUTH_BASIC | CURLAUTH_GSSAPI))
- infof(conn->data,
+ infof(data,
"warning: unsupported value passed to CURLOPT_SOCKS5_AUTH: %lu\n",
auth);
if(!(auth & CURLAUTH_BASIC))
@@ -558,31 +561,31 @@ CURLcode Curl_SOCKS5(const char *proxy_user,
/* write the number of authentication methods */
socksreq[1] = (unsigned char) (idx - 2);
- result = Curl_write_plain(conn, sockfd, (char *)socksreq, idx, &written);
+ result = Curl_write_plain(data, sockfd, (char *)socksreq, idx, &written);
if(result && (CURLE_AGAIN != result)) {
failf(data, "Unable to send initial SOCKS5 request.");
- return CURLE_COULDNT_CONNECT;
+ return CURLPX_SEND_CONNECT;
}
if(written != idx) {
- sxstate(conn, CONNECT_SOCKS_SEND);
+ sxstate(data, CONNECT_SOCKS_SEND);
sx->outstanding = idx - written;
sx->outp = &socksreq[written];
- return CURLE_OK;
+ return CURLPX_OK;
}
- sxstate(conn, CONNECT_SOCKS_READ);
+ sxstate(data, CONNECT_SOCKS_READ);
goto CONNECT_SOCKS_READ_INIT;
case CONNECT_SOCKS_SEND:
- result = Curl_write_plain(conn, sockfd, (char *)sx->outp,
+ result = Curl_write_plain(data, sockfd, (char *)sx->outp,
sx->outstanding, &written);
if(result && (CURLE_AGAIN != result)) {
failf(data, "Unable to send initial SOCKS5 request.");
- return CURLE_COULDNT_CONNECT;
+ return CURLPX_SEND_CONNECT;
}
if(written != sx->outstanding) {
/* not done, remain in state */
sx->outstanding -= written;
sx->outp += written;
- return CURLE_OK;
+ return CURLPX_OK;
}
/* FALLTHROUGH */
CONNECT_SOCKS_READ_INIT:
@@ -595,40 +598,40 @@ CURLcode Curl_SOCKS5(const char *proxy_user,
sx->outstanding, &actualread);
if(result && (CURLE_AGAIN != result)) {
failf(data, "Unable to receive initial SOCKS5 response.");
- return CURLE_COULDNT_CONNECT;
+ return CURLPX_RECV_CONNECT;
}
else if(!result && !actualread) {
/* connection closed */
failf(data, "Connection to proxy closed");
- return CURLE_COULDNT_CONNECT;
+ return CURLPX_CLOSED;
}
else if(actualread != sx->outstanding) {
/* remain in reading state */
sx->outstanding -= actualread;
sx->outp += actualread;
- return CURLE_OK;
+ return CURLPX_OK;
}
else if(socksreq[0] != 5) {
failf(data, "Received invalid version in initial SOCKS5 response.");
- return CURLE_COULDNT_CONNECT;
+ return CURLPX_BAD_VERSION;
}
else if(socksreq[1] == 0) {
/* DONE! No authentication needed. Send request. */
- sxstate(conn, CONNECT_REQ_INIT);
+ sxstate(data, CONNECT_REQ_INIT);
goto CONNECT_REQ_INIT;
}
else if(socksreq[1] == 2) {
/* regular name + password authentication */
- sxstate(conn, CONNECT_AUTH_INIT);
+ sxstate(data, CONNECT_AUTH_INIT);
goto CONNECT_AUTH_INIT;
}
#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
else if(allow_gssapi && (socksreq[1] == 1)) {
- sxstate(conn, CONNECT_GSSAPI_INIT);
- result = Curl_SOCKS5_gssapi_negotiate(sockindex, conn);
+ sxstate(data, CONNECT_GSSAPI_INIT);
+ result = Curl_SOCKS5_gssapi_negotiate(sockindex, data);
if(result) {
failf(data, "Unable to negotiate SOCKS5 GSS-API context.");
- return CURLE_COULDNT_CONNECT;
+ return CURLPX_GSSAPI;
}
}
#endif
@@ -637,16 +640,16 @@ CURLcode Curl_SOCKS5(const char *proxy_user,
if(!allow_gssapi && (socksreq[1] == 1)) {
failf(data,
"SOCKS5 GSSAPI per-message authentication is not supported.");
- return CURLE_COULDNT_CONNECT;
+ return CURLPX_GSSAPI_PERMSG;
}
else if(socksreq[1] == 255) {
failf(data, "No authentication method was acceptable.");
- return CURLE_COULDNT_CONNECT;
+ return CURLPX_NO_AUTH;
}
}
failf(data,
"Undocumented SOCKS5 mode attempted to be used by server.");
- return CURLE_COULDNT_CONNECT;
+ return CURLPX_UNKNOWN_MODE;
#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
case CONNECT_GSSAPI_INIT:
/* GSSAPI stuff done non-blocking */
@@ -683,7 +686,7 @@ CURLcode Curl_SOCKS5(const char *proxy_user,
/* the length must fit in a single byte */
if(proxy_user_len >= 255) {
failf(data, "Excessive user name length for proxy auth");
- return CURLE_BAD_FUNCTION_ARGUMENT;
+ return CURLPX_LONG_USER;
}
memcpy(socksreq + len, proxy_user, proxy_user_len);
}
@@ -693,95 +696,98 @@ CURLcode Curl_SOCKS5(const char *proxy_user,
/* the length must fit in a single byte */
if(proxy_password_len > 255) {
failf(data, "Excessive password length for proxy auth");
- return CURLE_BAD_FUNCTION_ARGUMENT;
+ return CURLPX_LONG_PASSWD;
}
memcpy(socksreq + len, proxy_password, proxy_password_len);
}
len += proxy_password_len;
- sxstate(conn, CONNECT_AUTH_SEND);
+ sxstate(data, CONNECT_AUTH_SEND);
sx->outstanding = len;
sx->outp = socksreq;
}
/* FALLTHROUGH */
case CONNECT_AUTH_SEND:
- result = Curl_write_plain(conn, sockfd, (char *)sx->outp,
+ result = Curl_write_plain(data, sockfd, (char *)sx->outp,
sx->outstanding, &written);
if(result && (CURLE_AGAIN != result)) {
failf(data, "Failed to send SOCKS5 sub-negotiation request.");
- return CURLE_COULDNT_CONNECT;
+ return CURLPX_SEND_AUTH;
}
if(sx->outstanding != written) {
/* remain in state */
sx->outstanding -= written;
sx->outp += written;
- return CURLE_OK;
+ return CURLPX_OK;
}
sx->outp = socksreq;
sx->outstanding = 2;
- sxstate(conn, CONNECT_AUTH_READ);
+ sxstate(data, CONNECT_AUTH_READ);
/* FALLTHROUGH */
case CONNECT_AUTH_READ:
result = Curl_read_plain(sockfd, (char *)sx->outp,
sx->outstanding, &actualread);
if(result && (CURLE_AGAIN != result)) {
failf(data, "Unable to receive SOCKS5 sub-negotiation response.");
- return CURLE_COULDNT_CONNECT;
+ return CURLPX_RECV_AUTH;
}
else if(!result && !actualread) {
/* connection closed */
failf(data, "connection to proxy closed");
- return CURLE_COULDNT_CONNECT;
+ return CURLPX_CLOSED;
}
else if(actualread != sx->outstanding) {
/* remain in state */
sx->outstanding -= actualread;
sx->outp += actualread;
- return CURLE_OK;
+ return CURLPX_OK;
}
/* ignore the first (VER) byte */
else if(socksreq[1] != 0) { /* status */
failf(data, "User was rejected by the SOCKS5 server (%d %d).",
socksreq[0], socksreq[1]);
- return CURLE_COULDNT_CONNECT;
+ return CURLPX_USER_REJECTED;
}
/* Everything is good so far, user was authenticated! */
- sxstate(conn, CONNECT_REQ_INIT);
+ sxstate(data, CONNECT_REQ_INIT);
/* FALLTHROUGH */
CONNECT_REQ_INIT:
case CONNECT_REQ_INIT:
if(socks5_resolve_local) {
- enum resolve_t rc = Curl_resolv(conn, hostname, remote_port,
+ enum resolve_t rc = Curl_resolv(data, hostname, remote_port,
FALSE, &dns);
if(rc == CURLRESOLV_ERROR)
- return CURLE_COULDNT_RESOLVE_HOST;
+ return CURLPX_RESOLVE_HOST;
if(rc == CURLRESOLV_PENDING) {
- sxstate(conn, CONNECT_RESOLVING);
- return CURLE_OK;
+ sxstate(data, CONNECT_RESOLVING);
+ return CURLPX_OK;
}
- sxstate(conn, CONNECT_RESOLVED);
+ sxstate(data, CONNECT_RESOLVED);
goto CONNECT_RESOLVED;
}
goto CONNECT_RESOLVE_REMOTE;
case CONNECT_RESOLVING:
/* check if we have the name resolved by now */
- dns = Curl_fetch_addr(conn, hostname, (int)conn->port);
+ dns = Curl_fetch_addr(data, hostname, remote_port);
if(dns) {
#ifdef CURLRES_ASYNCH
- conn->async.dns = dns;
- conn->async.done = TRUE;
+ data->state.async.dns = dns;
+ data->state.async.done = TRUE;
#endif
infof(data, "SOCKS5: hostname '%s' found\n", hostname);
}
if(!dns) {
- result = Curl_resolv_check(data->conn, &dns);
- if(!dns)
- return result;
+ result = Curl_resolv_check(data, &dns);
+ if(!dns) {
+ if(result)
+ return CURLPX_RESOLVE_HOST;
+ return CURLPX_OK;
+ }
}
/* FALLTHROUGH */
CONNECT_RESOLVED:
@@ -793,7 +799,7 @@ CURLcode Curl_SOCKS5(const char *proxy_user,
if(!hp) {
failf(data, "Failed to resolve \"%s\" for SOCKS5 connect.",
hostname);
- return CURLE_COULDNT_RESOLVE_HOST;
+ return CURLPX_RESOLVE_HOST;
}
Curl_printable_address(hp, dest, sizeof(dest));
@@ -833,7 +839,7 @@ CURLcode Curl_SOCKS5(const char *proxy_user,
#endif
else {
hp = NULL; /* fail! */
- failf(data, "SOCKS5 connection to %s not supported\n", dest);
+ failf(data, "SOCKS5 connection to %s not supported", dest);
}
Curl_resolv_unlock(data, dns); /* not used anymore from now on */
@@ -867,64 +873,81 @@ CURLcode Curl_SOCKS5(const char *proxy_user,
#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
if(conn->socks5_gssapi_enctype) {
failf(data, "SOCKS5 GSS-API protection not yet implemented.");
- return CURLE_COULDNT_CONNECT;
+ return CURLPX_GSSAPI_PROTECTION;
}
#endif
sx->outp = socksreq;
sx->outstanding = len;
- sxstate(conn, CONNECT_REQ_SENDING);
+ sxstate(data, CONNECT_REQ_SENDING);
/* FALLTHROUGH */
case CONNECT_REQ_SENDING:
- result = Curl_write_plain(conn, sockfd, (char *)sx->outp,
+ result = Curl_write_plain(data, sockfd, (char *)sx->outp,
sx->outstanding, &written);
if(result && (CURLE_AGAIN != result)) {
failf(data, "Failed to send SOCKS5 connect request.");
- return CURLE_COULDNT_CONNECT;
+ return CURLPX_SEND_REQUEST;
}
if(sx->outstanding != written) {
/* remain in state */
sx->outstanding -= written;
sx->outp += written;
- return CURLE_OK;
+ return CURLPX_OK;
}
#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
if(conn->socks5_gssapi_enctype) {
failf(data, "SOCKS5 GSS-API protection not yet implemented.");
- return CURLE_COULDNT_CONNECT;
+ return CURLPX_GSSAPI_PROTECTION;
}
#endif
sx->outstanding = 10; /* minimum packet size is 10 */
sx->outp = socksreq;
- sxstate(conn, CONNECT_REQ_READ);
+ sxstate(data, CONNECT_REQ_READ);
/* FALLTHROUGH */
case CONNECT_REQ_READ:
result = Curl_read_plain(sockfd, (char *)sx->outp,
sx->outstanding, &actualread);
if(result && (CURLE_AGAIN != result)) {
failf(data, "Failed to receive SOCKS5 connect request ack.");
- return CURLE_COULDNT_CONNECT;
+ return CURLPX_RECV_REQACK;
}
else if(!result && !actualread) {
/* connection closed */
failf(data, "connection to proxy closed");
- return CURLE_COULDNT_CONNECT;
+ return CURLPX_CLOSED;
}
else if(actualread != sx->outstanding) {
/* remain in state */
sx->outstanding -= actualread;
sx->outp += actualread;
- return CURLE_OK;
+ return CURLPX_OK;
}
if(socksreq[0] != 5) { /* version */
failf(data,
"SOCKS5 reply has wrong version, version should be 5.");
- return CURLE_COULDNT_CONNECT;
+ return CURLPX_BAD_VERSION;
}
else if(socksreq[1] != 0) { /* Anything besides 0 is an error */
+ CURLproxycode rc = CURLPX_REPLY_UNASSIGNED;
+ int code = socksreq[1];
failf(data, "Can't complete SOCKS5 connection to %s. (%d)",
hostname, (unsigned char)socksreq[1]);
- return CURLE_COULDNT_CONNECT;
+ if(code < 9) {
+ /* RFC 1928 section 6 lists: */
+ static const CURLproxycode lookup[] = {
+ CURLPX_OK,
+ CURLPX_REPLY_GENERAL_SERVER_FAILURE,
+ CURLPX_REPLY_NOT_ALLOWED,
+ CURLPX_REPLY_NETWORK_UNREACHABLE,
+ CURLPX_REPLY_HOST_UNREACHABLE,
+ CURLPX_REPLY_CONNECTION_REFUSED,
+ CURLPX_REPLY_TTL_EXPIRED,
+ CURLPX_REPLY_COMMAND_NOT_SUPPORTED,
+ CURLPX_REPLY_ADDRESS_TYPE_NOT_SUPPORTED,
+ };
+ rc = lookup[code];
+ }
+ return rc;
}
/* Fix: in general, returned BND.ADDR is variable length parameter by RFC
@@ -958,7 +981,7 @@ CURLcode Curl_SOCKS5(const char *proxy_user,
}
else {
failf(data, "SOCKS5 reply has wrong address type.");
- return CURLE_COULDNT_CONNECT;
+ return CURLPX_BAD_ADDRESS_TYPE;
}
/* At this point we already read first 10 bytes */
@@ -969,10 +992,10 @@ CURLcode Curl_SOCKS5(const char *proxy_user,
if(len > 10) {
sx->outstanding = len - 10; /* get the rest */
sx->outp = &socksreq[10];
- sxstate(conn, CONNECT_REQ_READ_MORE);
+ sxstate(data, CONNECT_REQ_READ_MORE);
}
else {
- sxstate(conn, CONNECT_DONE);
+ sxstate(data, CONNECT_DONE);
break;
}
#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
@@ -984,25 +1007,25 @@ CURLcode Curl_SOCKS5(const char *proxy_user,
sx->outstanding, &actualread);
if(result && (CURLE_AGAIN != result)) {
failf(data, "Failed to receive SOCKS5 connect request ack.");
- return CURLE_COULDNT_CONNECT;
+ return CURLPX_RECV_ADDRESS;
}
else if(!result && !actualread) {
/* connection closed */
failf(data, "connection to proxy closed");
- return CURLE_COULDNT_CONNECT;
+ return CURLPX_CLOSED;
}
else if(actualread != sx->outstanding) {
/* remain in state */
sx->outstanding -= actualread;
sx->outp += actualread;
- return CURLE_OK;
+ return CURLPX_OK;
}
- sxstate(conn, CONNECT_DONE);
+ sxstate(data, CONNECT_DONE);
}
infof(data, "SOCKS5 request granted.\n");
*done = TRUE;
- return CURLE_OK; /* Proxy was successful! */
+ return CURLPX_OK; /* Proxy was successful! */
}
#endif /* CURL_DISABLE_PROXY */
diff --git a/Utilities/cmcurl/lib/socks.h b/Utilities/cmcurl/lib/socks.h
index 64a756337..b0c7f9b26 100644
--- a/Utilities/cmcurl/lib/socks.h
+++ b/Utilities/cmcurl/lib/socks.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -35,7 +35,7 @@
*
* This is STUPID BLOCKING behavior
*/
-int Curl_blockread_all(struct connectdata *conn,
+int Curl_blockread_all(struct Curl_easy *data,
curl_socket_t sockfd,
char *buf,
ssize_t buffersize,
@@ -48,31 +48,31 @@ int Curl_SOCKS_getsock(struct connectdata *conn,
* This function logs in to a SOCKS4(a) proxy and sends the specifics to the
* final destination server.
*/
-CURLcode Curl_SOCKS4(const char *proxy_name,
- const char *hostname,
- int remote_port,
- int sockindex,
- struct connectdata *conn,
- bool *done);
+CURLproxycode Curl_SOCKS4(const char *proxy_name,
+ const char *hostname,
+ int remote_port,
+ int sockindex,
+ struct Curl_easy *data,
+ bool *done);
/*
* This function logs in to a SOCKS5 proxy and sends the specifics to the
* final destination server.
*/
-CURLcode Curl_SOCKS5(const char *proxy_name,
- const char *proxy_password,
- const char *hostname,
- int remote_port,
- int sockindex,
- struct connectdata *conn,
- bool *done);
+CURLproxycode Curl_SOCKS5(const char *proxy_name,
+ const char *proxy_password,
+ const char *hostname,
+ int remote_port,
+ int sockindex,
+ struct Curl_easy *data,
+ bool *done);
#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
/*
* This function handles the SOCKS5 GSS-API negotiation and initialisation
*/
CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
- struct connectdata *conn);
+ struct Curl_easy *data);
#endif
#endif /* CURL_DISABLE_PROXY */
diff --git a/Utilities/cmcurl/lib/socks_gssapi.c b/Utilities/cmcurl/lib/socks_gssapi.c
index 2e36b9940..3ab786d0b 100644
--- a/Utilities/cmcurl/lib/socks_gssapi.c
+++ b/Utilities/cmcurl/lib/socks_gssapi.c
@@ -5,12 +5,12 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2012 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2012 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 2009, Markus Moeller, <markus_moeller@compuserve.com>
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -92,7 +92,7 @@ static int check_gss_err(struct Curl_easy *data,
}
gss_release_buffer(&min_stat, &status_string);
}
- failf(data, "GSS-API error: %s failed:\n%s", function, buf);
+ failf(data, "GSS-API error: %s failed: %s", function, buf);
return 1;
}
@@ -100,9 +100,9 @@ static int check_gss_err(struct Curl_easy *data,
}
CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
- struct connectdata *conn)
+ struct Curl_easy *data)
{
- struct Curl_easy *data = conn->data;
+ struct connectdata *conn = data->conn;
curl_socket_t sock = conn->sock[sockindex];
CURLcode code;
ssize_t actualread;
@@ -201,7 +201,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
us_length = htons((short)gss_send_token.length);
memcpy(socksreq + 2, &us_length, sizeof(short));
- code = Curl_write_plain(conn, sock, (char *)socksreq, 4, &written);
+ code = Curl_write_plain(data, sock, (char *)socksreq, 4, &written);
if(code || (4 != written)) {
failf(data, "Failed to send GSS-API authentication request.");
gss_release_name(&gss_status, &server);
@@ -211,7 +211,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
return CURLE_COULDNT_CONNECT;
}
- code = Curl_write_plain(conn, sock, (char *)gss_send_token.value,
+ code = Curl_write_plain(data, sock, (char *)gss_send_token.value,
gss_send_token.length, &written);
if(code || ((ssize_t)gss_send_token.length != written)) {
@@ -240,7 +240,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
* +----+------+-----+----------------+
*/
- result = Curl_blockread_all(conn, sock, (char *)socksreq, 4, &actualread);
+ result = Curl_blockread_all(data, sock, (char *)socksreq, 4, &actualread);
if(result || (actualread != 4)) {
failf(data, "Failed to receive GSS-API authentication response.");
gss_release_name(&gss_status, &server);
@@ -279,7 +279,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
return CURLE_OUT_OF_MEMORY;
}
- result = Curl_blockread_all(conn, sock, (char *)gss_recv_token.value,
+ result = Curl_blockread_all(data, sock, (char *)gss_recv_token.value,
gss_recv_token.length, &actualread);
if(result || (actualread != us_length)) {
@@ -408,7 +408,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
memcpy(socksreq + 2, &us_length, sizeof(short));
}
- code = Curl_write_plain(conn, sock, (char *)socksreq, 4, &written);
+ code = Curl_write_plain(data, sock, (char *)socksreq, 4, &written);
if(code || (4 != written)) {
failf(data, "Failed to send GSS-API encryption request.");
gss_release_buffer(&gss_status, &gss_w_token);
@@ -418,7 +418,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
if(data->set.socks5_gssapi_nec) {
memcpy(socksreq, &gss_enc, 1);
- code = Curl_write_plain(conn, sock, socksreq, 1, &written);
+ code = Curl_write_plain(data, sock, socksreq, 1, &written);
if(code || ( 1 != written)) {
failf(data, "Failed to send GSS-API encryption type.");
gss_delete_sec_context(&gss_status, &gss_context, NULL);
@@ -426,7 +426,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
}
}
else {
- code = Curl_write_plain(conn, sock, (char *)gss_w_token.value,
+ code = Curl_write_plain(data, sock, (char *)gss_w_token.value,
gss_w_token.length, &written);
if(code || ((ssize_t)gss_w_token.length != written)) {
failf(data, "Failed to send GSS-API encryption type.");
@@ -437,7 +437,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
gss_release_buffer(&gss_status, &gss_w_token);
}
- result = Curl_blockread_all(conn, sock, (char *)socksreq, 4, &actualread);
+ result = Curl_blockread_all(data, sock, (char *)socksreq, 4, &actualread);
if(result || (actualread != 4)) {
failf(data, "Failed to receive GSS-API encryption response.");
gss_delete_sec_context(&gss_status, &gss_context, NULL);
@@ -468,7 +468,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
gss_delete_sec_context(&gss_status, &gss_context, NULL);
return CURLE_OUT_OF_MEMORY;
}
- result = Curl_blockread_all(conn, sock, (char *)gss_recv_token.value,
+ result = Curl_blockread_all(data, sock, (char *)gss_recv_token.value,
gss_recv_token.length, &actualread);
if(result || (actualread != us_length)) {
@@ -493,7 +493,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
gss_release_buffer(&gss_status, &gss_recv_token);
if(gss_w_token.length != 1) {
- failf(data, "Invalid GSS-API encryption response length (%d).",
+ failf(data, "Invalid GSS-API encryption response length (%zu).",
gss_w_token.length);
gss_release_buffer(&gss_status, &gss_w_token);
gss_delete_sec_context(&gss_status, &gss_context, NULL);
@@ -505,7 +505,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
}
else {
if(gss_recv_token.length != 1) {
- failf(data, "Invalid GSS-API encryption response length (%d).",
+ failf(data, "Invalid GSS-API encryption response length (%zu).",
gss_recv_token.length);
gss_release_buffer(&gss_status, &gss_recv_token);
gss_delete_sec_context(&gss_status, &gss_context, NULL);
diff --git a/Utilities/cmcurl/lib/socks_sspi.c b/Utilities/cmcurl/lib/socks_sspi.c
index 2f1fd36fa..b343538f0 100644
--- a/Utilities/cmcurl/lib/socks_sspi.c
+++ b/Utilities/cmcurl/lib/socks_sspi.c
@@ -5,12 +5,12 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2012 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2012 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 2009, 2011, Markus Moeller, <markus_moeller@compuserve.com>
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -43,7 +43,7 @@
/*
* Helper sspi error functions.
*/
-static int check_sspi_err(struct connectdata *conn,
+static int check_sspi_err(struct Curl_easy *data,
SECURITY_STATUS status,
const char *function)
{
@@ -52,7 +52,7 @@ static int check_sspi_err(struct connectdata *conn,
status != SEC_I_COMPLETE_NEEDED &&
status != SEC_I_CONTINUE_NEEDED) {
char buffer[STRERROR_LEN];
- failf(conn->data, "SSPI error: %s failed: %s", function,
+ failf(data, "SSPI error: %s failed: %s", function,
Curl_sspi_strerror(status, buffer, sizeof(buffer)));
return 1;
}
@@ -61,9 +61,9 @@ static int check_sspi_err(struct connectdata *conn,
/* This is the SSPI-using version of this function */
CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
- struct connectdata *conn)
+ struct Curl_easy *data)
{
- struct Curl_easy *data = conn->data;
+ struct connectdata *conn = data->conn;
curl_socket_t sock = conn->sock[sockindex];
CURLcode code;
ssize_t actualread;
@@ -86,7 +86,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
unsigned long qop;
unsigned char socksreq[4]; /* room for GSS-API exchange header only */
const char *service = data->set.str[STRING_PROXY_SERVICE_NAME] ?
- data->set.str[STRING_PROXY_SERVICE_NAME] : "rcmd";
+ data->set.str[STRING_PROXY_SERVICE_NAME] : "rcmd";
const size_t service_length = strlen(service);
/* GSS-API request looks like
@@ -146,7 +146,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
&cred_handle,
&expiry);
- if(check_sspi_err(conn, status, "AcquireCredentialsHandle")) {
+ if(check_sspi_err(data, status, "AcquireCredentialsHandle")) {
failf(data, "Failed to acquire credentials.");
free(service_name);
s_pSecFn->FreeCredentialsHandle(&cred_handle);
@@ -188,7 +188,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
sspi_recv_token.cbBuffer = 0;
}
- if(check_sspi_err(conn, status, "InitializeSecurityContext")) {
+ if(check_sspi_err(data, status, "InitializeSecurityContext")) {
free(service_name);
s_pSecFn->FreeCredentialsHandle(&cred_handle);
s_pSecFn->DeleteSecurityContext(&sspi_context);
@@ -204,7 +204,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
us_length = htons((short)sspi_send_token.cbBuffer);
memcpy(socksreq + 2, &us_length, sizeof(short));
- code = Curl_write_plain(conn, sock, (char *)socksreq, 4, &written);
+ code = Curl_write_plain(data, sock, (char *)socksreq, 4, &written);
if(code || (4 != written)) {
failf(data, "Failed to send SSPI authentication request.");
free(service_name);
@@ -217,7 +217,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
return CURLE_COULDNT_CONNECT;
}
- code = Curl_write_plain(conn, sock, (char *)sspi_send_token.pvBuffer,
+ code = Curl_write_plain(data, sock, (char *)sspi_send_token.pvBuffer,
sspi_send_token.cbBuffer, &written);
if(code || (sspi_send_token.cbBuffer != (size_t)written)) {
failf(data, "Failed to send SSPI authentication token.");
@@ -258,7 +258,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
* +----+------+-----+----------------+
*/
- result = Curl_blockread_all(conn, sock, (char *)socksreq, 4, &actualread);
+ result = Curl_blockread_all(data, sock, (char *)socksreq, 4, &actualread);
if(result || (actualread != 4)) {
failf(data, "Failed to receive SSPI authentication response.");
free(service_name);
@@ -298,7 +298,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
s_pSecFn->DeleteSecurityContext(&sspi_context);
return CURLE_OUT_OF_MEMORY;
}
- result = Curl_blockread_all(conn, sock, (char *)sspi_recv_token.pvBuffer,
+ result = Curl_blockread_all(data, sock, (char *)sspi_recv_token.pvBuffer,
sspi_recv_token.cbBuffer, &actualread);
if(result || (actualread != us_length)) {
@@ -321,7 +321,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
SECPKG_CRED_ATTR_NAMES,
&names);
s_pSecFn->FreeCredentialsHandle(&cred_handle);
- if(check_sspi_err(conn, status, "QueryCredentialAttributes")) {
+ if(check_sspi_err(data, status, "QueryCredentialAttributes")) {
s_pSecFn->DeleteSecurityContext(&sspi_context);
s_pSecFn->FreeContextBuffer(names.sUserName);
failf(data, "Failed to determine user name.");
@@ -386,7 +386,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
status = s_pSecFn->QueryContextAttributes(&sspi_context,
SECPKG_ATTR_SIZES,
&sspi_sizes);
- if(check_sspi_err(conn, status, "QueryContextAttributes")) {
+ if(check_sspi_err(data, status, "QueryContextAttributes")) {
s_pSecFn->DeleteSecurityContext(&sspi_context);
failf(data, "Failed to query security context attributes.");
return CURLE_COULDNT_CONNECT;
@@ -423,7 +423,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
KERB_WRAP_NO_ENCRYPT,
&wrap_desc,
0);
- if(check_sspi_err(conn, status, "EncryptMessage")) {
+ if(check_sspi_err(data, status, "EncryptMessage")) {
s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer);
s_pSecFn->FreeContextBuffer(sspi_w_token[1].pvBuffer);
s_pSecFn->FreeContextBuffer(sspi_w_token[2].pvBuffer);
@@ -466,7 +466,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
memcpy(socksreq + 2, &us_length, sizeof(short));
}
- code = Curl_write_plain(conn, sock, (char *)socksreq, 4, &written);
+ code = Curl_write_plain(data, sock, (char *)socksreq, 4, &written);
if(code || (4 != written)) {
failf(data, "Failed to send SSPI encryption request.");
if(sspi_send_token.pvBuffer)
@@ -477,7 +477,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
if(data->set.socks5_gssapi_nec) {
memcpy(socksreq, &gss_enc, 1);
- code = Curl_write_plain(conn, sock, (char *)socksreq, 1, &written);
+ code = Curl_write_plain(data, sock, (char *)socksreq, 1, &written);
if(code || (1 != written)) {
failf(data, "Failed to send SSPI encryption type.");
s_pSecFn->DeleteSecurityContext(&sspi_context);
@@ -485,7 +485,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
}
}
else {
- code = Curl_write_plain(conn, sock, (char *)sspi_send_token.pvBuffer,
+ code = Curl_write_plain(data, sock, (char *)sspi_send_token.pvBuffer,
sspi_send_token.cbBuffer, &written);
if(code || (sspi_send_token.cbBuffer != (size_t)written)) {
failf(data, "Failed to send SSPI encryption type.");
@@ -498,7 +498,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
s_pSecFn->FreeContextBuffer(sspi_send_token.pvBuffer);
}
- result = Curl_blockread_all(conn, sock, (char *)socksreq, 4, &actualread);
+ result = Curl_blockread_all(data, sock, (char *)socksreq, 4, &actualread);
if(result || (actualread != 4)) {
failf(data, "Failed to receive SSPI encryption response.");
s_pSecFn->DeleteSecurityContext(&sspi_context);
@@ -530,7 +530,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
return CURLE_OUT_OF_MEMORY;
}
- result = Curl_blockread_all(conn, sock, (char *)sspi_w_token[0].pvBuffer,
+ result = Curl_blockread_all(data, sock, (char *)sspi_w_token[0].pvBuffer,
sspi_w_token[0].cbBuffer, &actualread);
if(result || (actualread != us_length)) {
@@ -553,7 +553,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
0,
&qop);
- if(check_sspi_err(conn, status, "DecryptMessage")) {
+ if(check_sspi_err(data, status, "DecryptMessage")) {
if(sspi_w_token[0].pvBuffer)
s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer);
if(sspi_w_token[1].pvBuffer)
diff --git a/Utilities/cmcurl/lib/speedcheck.c b/Utilities/cmcurl/lib/speedcheck.c
index 3aeea9111..841d256b4 100644
--- a/Utilities/cmcurl/lib/speedcheck.c
+++ b/Utilities/cmcurl/lib/speedcheck.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
@@ -39,6 +39,10 @@ void Curl_speedinit(struct Curl_easy *data)
CURLcode Curl_speedcheck(struct Curl_easy *data,
struct curltime now)
{
+ if(data->req.keepon & KEEP_RECV_PAUSE)
+ /* A paused transfer is not qualified for speed checks */
+ return CURLE_OK;
+
if((data->progress.current_speed >= 0) && data->set.low_speed_time) {
if(data->progress.current_speed < data->set.low_speed_limit) {
if(!data->state.keeps_speed.tv_sec)
diff --git a/Utilities/cmcurl/lib/speedcheck.h b/Utilities/cmcurl/lib/speedcheck.h
index 5c2dc9a22..1d4c7bfef 100644
--- a/Utilities/cmcurl/lib/speedcheck.h
+++ b/Utilities/cmcurl/lib/speedcheck.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
diff --git a/Utilities/cmcurl/lib/splay.c b/Utilities/cmcurl/lib/splay.c
index 0f5fcd1e8..98baf5d87 100644
--- a/Utilities/cmcurl/lib/splay.c
+++ b/Utilities/cmcurl/lib/splay.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1997 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1997 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -206,9 +206,9 @@ struct Curl_tree *Curl_splaygetbest(struct curltime i,
*
* @unittest: 1309
*/
-int Curl_splayremovebyaddr(struct Curl_tree *t,
- struct Curl_tree *removenode,
- struct Curl_tree **newroot)
+int Curl_splayremove(struct Curl_tree *t,
+ struct Curl_tree *removenode,
+ struct Curl_tree **newroot)
{
static const struct curltime KEY_NOTUSED = {
(time_t)-1, (unsigned int)-1
diff --git a/Utilities/cmcurl/lib/splay.h b/Utilities/cmcurl/lib/splay.h
index 9292f349b..eb9f65f1e 100644
--- a/Utilities/cmcurl/lib/splay.h
+++ b/Utilities/cmcurl/lib/splay.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1997 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1997 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -40,19 +40,13 @@ struct Curl_tree *Curl_splayinsert(struct curltime key,
struct Curl_tree *t,
struct Curl_tree *newnode);
-#if 0
-struct Curl_tree *Curl_splayremove(struct curltime key,
- struct Curl_tree *t,
- struct Curl_tree **removed);
-#endif
-
struct Curl_tree *Curl_splaygetbest(struct curltime key,
struct Curl_tree *t,
struct Curl_tree **removed);
-int Curl_splayremovebyaddr(struct Curl_tree *t,
- struct Curl_tree *removenode,
- struct Curl_tree **newroot);
+int Curl_splayremove(struct Curl_tree *t,
+ struct Curl_tree *removenode,
+ struct Curl_tree **newroot);
#define Curl_splaycomparekeys(i,j) ( ((i.tv_sec) < (j.tv_sec)) ? -1 : \
( ((i.tv_sec) > (j.tv_sec)) ? 1 : \
diff --git a/Utilities/cmcurl/lib/strcase.c b/Utilities/cmcurl/lib/strcase.c
index a309e3529..955e3c79e 100644
--- a/Utilities/cmcurl/lib/strcase.c
+++ b/Utilities/cmcurl/lib/strcase.c
@@ -9,7 +9,7 @@
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/strcase.h b/Utilities/cmcurl/lib/strcase.h
index cd4c4191a..10dc69881 100644
--- a/Utilities/cmcurl/lib/strcase.h
+++ b/Utilities/cmcurl/lib/strcase.h
@@ -11,7 +11,7 @@
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/strdup.c b/Utilities/cmcurl/lib/strdup.c
index 7732802b0..9af47ea47 100644
--- a/Utilities/cmcurl/lib/strdup.c
+++ b/Utilities/cmcurl/lib/strdup.c
@@ -9,7 +9,7 @@
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/strdup.h b/Utilities/cmcurl/lib/strdup.h
index ae3d5d011..0936956f8 100644
--- a/Utilities/cmcurl/lib/strdup.h
+++ b/Utilities/cmcurl/lib/strdup.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
diff --git a/Utilities/cmcurl/lib/strerror.c b/Utilities/cmcurl/lib/strerror.c
index 015e588cf..3862aabd6 100644
--- a/Utilities/cmcurl/lib/strerror.c
+++ b/Utilities/cmcurl/lib/strerror.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2004 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2004 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -320,6 +320,9 @@ curl_easy_strerror(CURLcode error)
case CURLE_QUIC_CONNECT_ERROR:
return "QUIC connection error";
+ case CURLE_PROXY:
+ return "proxy handshake error";
+
/* error codes not used by current libcurl */
case CURLE_OBSOLETE20:
case CURLE_OBSOLETE24:
@@ -652,34 +655,27 @@ 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';
-
-#ifdef _WIN32_WCE
- {
- wchar_t wbuf[256];
- wbuf[0] = L'\0';
-
- if(FormatMessage((FORMAT_MESSAGE_FROM_SYSTEM |
- FORMAT_MESSAGE_IGNORE_INSERTS), NULL, err,
- LANG_NEUTRAL, wbuf, sizeof(wbuf)/sizeof(wchar_t), NULL)) {
- size_t written = wcstombs(buf, wbuf, buflen - 1);
- if(written != (size_t)-1)
- buf[written] = '\0';
- else
- *buf = '\0';
- }
- }
-#else
- if(!FormatMessageA((FORMAT_MESSAGE_FROM_SYSTEM |
- FORMAT_MESSAGE_IGNORE_INSERTS), NULL, err,
- LANG_NEUTRAL, buf, (DWORD)buflen, 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, err,
+ LANG_NEUTRAL, wbuf, sizeof(wbuf)/sizeof(wchar_t), NULL)) {
+ size_t written = wcstombs(buf, wbuf, buflen - 1);
+ if(written != (size_t)-1)
+ buf[written] = '\0';
+ else
+ *buf = '\0';
}
-#endif
/* Truncate multiple lines */
p = strchr(buf, '\n');
@@ -725,7 +721,9 @@ const char *Curl_strerror(int err, char *buf, size_t buflen)
if(!buflen)
return NULL;
+#ifndef WIN32
DEBUGASSERT(err >= 0);
+#endif
max = buflen - 1;
*buf = '\0';
@@ -785,7 +783,7 @@ const char *Curl_strerror(int err, char *buf, size_t buflen)
}
#else
{
- char *msg = strerror(err);
+ const char *msg = strerror(err);
if(msg)
strncpy(buf, msg, max);
else
diff --git a/Utilities/cmcurl/lib/strerror.h b/Utilities/cmcurl/lib/strerror.h
index bae8f8974..96a7e27c5 100644
--- a/Utilities/cmcurl/lib/strerror.h
+++ b/Utilities/cmcurl/lib/strerror.h
@@ -11,7 +11,7 @@
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/strtok.c b/Utilities/cmcurl/lib/strtok.c
index ba6e0258a..d53e587ab 100644
--- a/Utilities/cmcurl/lib/strtok.c
+++ b/Utilities/cmcurl/lib/strtok.c
@@ -9,7 +9,7 @@
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/strtok.h b/Utilities/cmcurl/lib/strtok.h
index e221fa680..831ef0c00 100644
--- a/Utilities/cmcurl/lib/strtok.h
+++ b/Utilities/cmcurl/lib/strtok.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
diff --git a/Utilities/cmcurl/lib/strtoofft.c b/Utilities/cmcurl/lib/strtoofft.c
index 96e382060..ac87cfc5b 100644
--- a/Utilities/cmcurl/lib/strtoofft.c
+++ b/Utilities/cmcurl/lib/strtoofft.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
diff --git a/Utilities/cmcurl/lib/strtoofft.h b/Utilities/cmcurl/lib/strtoofft.h
index be19cd716..4d22ba36c 100644
--- a/Utilities/cmcurl/lib/strtoofft.h
+++ b/Utilities/cmcurl/lib/strtoofft.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
diff --git a/Utilities/cmcurl/lib/system_win32.c b/Utilities/cmcurl/lib/system_win32.c
index 2e59e032e..2132f43ef 100644
--- a/Utilities/cmcurl/lib/system_win32.c
+++ b/Utilities/cmcurl/lib/system_win32.c
@@ -9,7 +9,7 @@
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -55,12 +55,7 @@ CURLcode Curl_win32_init(long flags)
WSADATA wsaData;
int res;
-#if defined(ENABLE_IPV6) && (USE_WINSOCK < 2)
-#error IPV6_requires_winsock2
-#endif
-
- wVersionRequested = MAKEWORD(USE_WINSOCK, USE_WINSOCK);
-
+ wVersionRequested = MAKEWORD(2, 2);
res = WSAStartup(wVersionRequested, &wsaData);
if(res != 0)
@@ -83,9 +78,9 @@ CURLcode Curl_win32_init(long flags)
return CURLE_FAILED_INIT;
}
/* The Windows Sockets DLL is acceptable. Proceed. */
- #elif defined(USE_LWIPSOCK)
+#elif defined(USE_LWIPSOCK)
lwip_init();
- #endif
+#endif
} /* CURL_GLOBAL_WIN32 */
#ifdef USE_WINDOWS_SSPI
@@ -201,7 +196,7 @@ HMODULE Curl_load_library(LPCTSTR filename)
pLoadLibraryEx(filename, NULL, LOAD_WITH_ALTERED_SEARCH_PATH) :
LoadLibrary(filename);
}
- /* Detect if KB2533623 is installed, as LOAD_LIBARY_SEARCH_SYSTEM32 is only
+ /* Detect if KB2533623 is installed, as LOAD_LIBRARY_SEARCH_SYSTEM32 is only
supported on Windows Vista, Windows Server 2008, Windows 7 and Windows
Server 2008 R2 with this patch or natively on Windows 8 and above */
else if(pLoadLibraryEx && GetProcAddress(hKernel32, "AddDllDirectory")) {
diff --git a/Utilities/cmcurl/lib/system_win32.h b/Utilities/cmcurl/lib/system_win32.h
index 2547bda95..69e0c812c 100644
--- a/Utilities/cmcurl/lib/system_win32.h
+++ b/Utilities/cmcurl/lib/system_win32.h
@@ -11,7 +11,7 @@
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/telnet.c b/Utilities/cmcurl/lib/telnet.c
index c3b58e54c..f96a4cb4c 100644
--- a/Utilities/cmcurl/lib/telnet.c
+++ b/Utilities/cmcurl/lib/telnet.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -87,14 +87,8 @@
#define printoption(a,b,c,d) Curl_nop_stmt
#endif
-#ifdef USE_WINSOCK
-typedef WSAEVENT (WINAPI *WSOCK2_EVENT)(void);
-typedef FARPROC WSOCK2_FUNC;
-static CURLcode check_wsock2(struct Curl_easy *data);
-#endif
-
static
-CURLcode telrcv(struct connectdata *,
+CURLcode telrcv(struct Curl_easy *data,
const unsigned char *inbuf, /* Data received from socket */
ssize_t count); /* Number of bytes received */
@@ -104,23 +98,23 @@ static void printoption(struct Curl_easy *data,
int cmd, int option);
#endif
-static void negotiate(struct connectdata *);
-static void send_negotiation(struct connectdata *, int cmd, int option);
-static void set_local_option(struct connectdata *conn,
+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 connectdata *conn,
+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 connectdata *);
-static void sendsuboption(struct connectdata *conn, int option);
+static void suboption(struct Curl_easy *data);
+static void sendsuboption(struct Curl_easy *data, int option);
-static CURLcode telnet_do(struct connectdata *conn, bool *done);
-static CURLcode telnet_done(struct connectdata *conn,
+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 connectdata *conn,
+static CURLcode send_telnet_data(struct Curl_easy *data,
char *buffer, ssize_t nread);
/* For negotiation compliant to RFC 1143 */
@@ -162,13 +156,12 @@ struct TELNET {
char subopt_xdisploc[128]; /* Set with suboption XDISPLOC */
unsigned short subopt_wsx; /* Set with suboption NAWS */
unsigned short subopt_wsy; /* Set with suboption NAWS */
+ TelnetReceive telrcv_state;
struct curl_slist *telnet_vars; /* Environment variables */
/* suboptions */
unsigned char subbuffer[SUBBUFSIZE];
unsigned char *subpointer, *subend; /* buffer for sub-options */
-
- TelnetReceive telrcv_state;
};
@@ -194,52 +187,13 @@ const struct Curl_handler Curl_handler_telnet = {
ZERO_NULL, /* connection_check */
PORT_TELNET, /* defport */
CURLPROTO_TELNET, /* protocol */
+ CURLPROTO_TELNET, /* family */
PROTOPT_NONE | PROTOPT_NOURLQUERY /* flags */
};
-#ifdef USE_WINSOCK
-static CURLcode
-check_wsock2(struct Curl_easy *data)
-{
- int err;
- WORD wVersionRequested;
- WSADATA wsaData;
-
- DEBUGASSERT(data);
-
- /* telnet requires at least WinSock 2.0 so ask for it. */
- wVersionRequested = MAKEWORD(2, 0);
-
- err = WSAStartup(wVersionRequested, &wsaData);
-
- /* We must've called this once already, so this call */
- /* should always succeed. But, just in case... */
- if(err != 0) {
- failf(data,"WSAStartup failed (%d)",err);
- return CURLE_FAILED_INIT;
- }
-
- /* We have to have a WSACleanup call for every successful */
- /* WSAStartup call. */
- WSACleanup();
-
- /* Check that our version is supported */
- if(LOBYTE(wsaData.wVersion) != LOBYTE(wVersionRequested) ||
- HIBYTE(wsaData.wVersion) != HIBYTE(wVersionRequested)) {
- /* Our version isn't supported */
- failf(data, "insufficient winsock version to support "
- "telnet");
- return CURLE_FAILED_INIT;
- }
-
- /* Our version is supported */
- return CURLE_OK;
-}
-#endif
-
static
-CURLcode init_telnet(struct connectdata *conn)
+CURLcode init_telnet(struct Curl_easy *data)
{
struct TELNET *tn;
@@ -247,7 +201,7 @@ CURLcode init_telnet(struct connectdata *conn)
if(!tn)
return CURLE_OUT_OF_MEMORY;
- conn->data->req.protop = tn; /* make us known */
+ data->req.p.telnet = tn; /* make us known */
tn->telrcv_state = CURL_TS_DATA;
@@ -259,7 +213,7 @@ CURLcode init_telnet(struct connectdata *conn)
tn->him_preferred[CURL_TELOPT_SGA] = CURL_YES;
/* To be compliant with previous releases of libcurl
- we enable this option by default. This behaviour
+ we enable this option by default. This behavior
can be changed thanks to the "BINARY" option in
CURLOPT_TELNETOPTIONS
*/
@@ -289,20 +243,20 @@ CURLcode init_telnet(struct connectdata *conn)
return CURLE_OK;
}
-static void negotiate(struct connectdata *conn)
+static void negotiate(struct Curl_easy *data)
{
int i;
- struct TELNET *tn = (struct TELNET *) conn->data->req.protop;
+ 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(conn, i, CURL_YES);
+ set_local_option(data, i, CURL_YES);
if(tn->him_preferred[i] == CURL_YES)
- set_remote_option(conn, i, CURL_YES);
+ set_remote_option(data, i, CURL_YES);
}
}
@@ -343,34 +297,34 @@ static void printoption(struct Curl_easy *data,
}
#endif
-static void send_negotiation(struct connectdata *conn, int cmd, int option)
+static void send_negotiation(struct Curl_easy *data, int cmd, int option)
{
- unsigned char buf[3];
- ssize_t bytes_written;
- struct Curl_easy *data = conn->data;
+ unsigned char buf[3];
+ ssize_t bytes_written;
+ struct connectdata *conn = data->conn;
- buf[0] = CURL_IAC;
- buf[1] = (unsigned char)cmd;
- buf[2] = (unsigned char)option;
+ buf[0] = CURL_IAC;
+ buf[1] = (unsigned char)cmd;
+ buf[2] = (unsigned char)option;
- bytes_written = swrite(conn->sock[FIRSTSOCKET], buf, 3);
- if(bytes_written < 0) {
- int err = SOCKERRNO;
- failf(data,"Sending data failed (%d)",err);
- }
+ bytes_written = swrite(conn->sock[FIRSTSOCKET], buf, 3);
+ if(bytes_written < 0) {
+ int err = SOCKERRNO;
+ failf(data,"Sending data failed (%d)",err);
+ }
- printoption(conn->data, "SENT", cmd, option);
+ printoption(data, "SENT", cmd, option);
}
static
-void set_remote_option(struct connectdata *conn, int option, int newstate)
+void set_remote_option(struct Curl_easy *data, int option, int newstate)
{
- struct TELNET *tn = (struct TELNET *)conn->data->req.protop;
+ struct TELNET *tn = data->req.p.telnet;
if(newstate == CURL_YES) {
switch(tn->him[option]) {
case CURL_NO:
tn->him[option] = CURL_WANTYES;
- send_negotiation(conn, CURL_DO, option);
+ send_negotiation(data, CURL_DO, option);
break;
case CURL_YES:
@@ -409,7 +363,7 @@ void set_remote_option(struct connectdata *conn, int option, int newstate)
case CURL_YES:
tn->him[option] = CURL_WANTNO;
- send_negotiation(conn, CURL_DONT, option);
+ send_negotiation(data, CURL_DONT, option);
break;
case CURL_WANTNO:
@@ -437,17 +391,17 @@ void set_remote_option(struct connectdata *conn, int option, int newstate)
}
static
-void rec_will(struct connectdata *conn, int option)
+void rec_will(struct Curl_easy *data, int option)
{
- struct TELNET *tn = (struct TELNET *)conn->data->req.protop;
+ struct TELNET *tn = data->req.p.telnet;
switch(tn->him[option]) {
case CURL_NO:
if(tn->him_preferred[option] == CURL_YES) {
tn->him[option] = CURL_YES;
- send_negotiation(conn, CURL_DO, option);
+ send_negotiation(data, CURL_DO, option);
}
else
- send_negotiation(conn, CURL_DONT, option);
+ send_negotiation(data, CURL_DONT, option);
break;
@@ -477,7 +431,7 @@ void rec_will(struct connectdata *conn, int option)
case CURL_OPPOSITE:
tn->him[option] = CURL_WANTNO;
tn->himq[option] = CURL_EMPTY;
- send_negotiation(conn, CURL_DONT, option);
+ send_negotiation(data, CURL_DONT, option);
break;
}
break;
@@ -485,9 +439,9 @@ void rec_will(struct connectdata *conn, int option)
}
static
-void rec_wont(struct connectdata *conn, int option)
+void rec_wont(struct Curl_easy *data, int option)
{
- struct TELNET *tn = (struct TELNET *)conn->data->req.protop;
+ struct TELNET *tn = data->req.p.telnet;
switch(tn->him[option]) {
case CURL_NO:
/* Already disabled */
@@ -495,7 +449,7 @@ void rec_wont(struct connectdata *conn, int option)
case CURL_YES:
tn->him[option] = CURL_NO;
- send_negotiation(conn, CURL_DONT, option);
+ send_negotiation(data, CURL_DONT, option);
break;
case CURL_WANTNO:
@@ -507,7 +461,7 @@ void rec_wont(struct connectdata *conn, int option)
case CURL_OPPOSITE:
tn->him[option] = CURL_WANTYES;
tn->himq[option] = CURL_EMPTY;
- send_negotiation(conn, CURL_DO, option);
+ send_negotiation(data, CURL_DO, option);
break;
}
break;
@@ -527,14 +481,14 @@ void rec_wont(struct connectdata *conn, int option)
}
static void
-set_local_option(struct connectdata *conn, int option, int newstate)
+set_local_option(struct Curl_easy *data, int option, int newstate)
{
- struct TELNET *tn = (struct TELNET *)conn->data->req.protop;
+ struct TELNET *tn = data->req.p.telnet;
if(newstate == CURL_YES) {
switch(tn->us[option]) {
case CURL_NO:
tn->us[option] = CURL_WANTYES;
- send_negotiation(conn, CURL_WILL, option);
+ send_negotiation(data, CURL_WILL, option);
break;
case CURL_YES:
@@ -573,7 +527,7 @@ set_local_option(struct connectdata *conn, int option, int newstate)
case CURL_YES:
tn->us[option] = CURL_WANTNO;
- send_negotiation(conn, CURL_WONT, option);
+ send_negotiation(data, CURL_WONT, option);
break;
case CURL_WANTNO:
@@ -601,26 +555,26 @@ set_local_option(struct connectdata *conn, int option, int newstate)
}
static
-void rec_do(struct connectdata *conn, int option)
+void rec_do(struct Curl_easy *data, int option)
{
- struct TELNET *tn = (struct TELNET *)conn->data->req.protop;
+ struct TELNET *tn = data->req.p.telnet;
switch(tn->us[option]) {
case CURL_NO:
if(tn->us_preferred[option] == CURL_YES) {
tn->us[option] = CURL_YES;
- send_negotiation(conn, CURL_WILL, option);
+ send_negotiation(data, CURL_WILL, option);
if(tn->subnegotiation[option] == CURL_YES)
/* transmission of data option */
- sendsuboption(conn, option);
+ sendsuboption(data, option);
}
else if(tn->subnegotiation[option] == CURL_YES) {
/* send information to achieve this option*/
tn->us[option] = CURL_YES;
- send_negotiation(conn, CURL_WILL, option);
- sendsuboption(conn, option);
+ send_negotiation(data, CURL_WILL, option);
+ sendsuboption(data, option);
}
else
- send_negotiation(conn, CURL_WONT, option);
+ send_negotiation(data, CURL_WONT, option);
break;
case CURL_YES:
@@ -647,13 +601,13 @@ void rec_do(struct connectdata *conn, int option)
tn->us[option] = CURL_YES;
if(tn->subnegotiation[option] == CURL_YES) {
/* transmission of data option */
- sendsuboption(conn, option);
+ sendsuboption(data, option);
}
break;
case CURL_OPPOSITE:
tn->us[option] = CURL_WANTNO;
tn->himq[option] = CURL_EMPTY;
- send_negotiation(conn, CURL_WONT, option);
+ send_negotiation(data, CURL_WONT, option);
break;
}
break;
@@ -661,9 +615,9 @@ void rec_do(struct connectdata *conn, int option)
}
static
-void rec_dont(struct connectdata *conn, int option)
+void rec_dont(struct Curl_easy *data, int option)
{
- struct TELNET *tn = (struct TELNET *)conn->data->req.protop;
+ struct TELNET *tn = data->req.p.telnet;
switch(tn->us[option]) {
case CURL_NO:
/* Already disabled */
@@ -671,7 +625,7 @@ void rec_dont(struct connectdata *conn, int option)
case CURL_YES:
tn->us[option] = CURL_NO;
- send_negotiation(conn, CURL_WONT, option);
+ send_negotiation(data, CURL_WONT, option);
break;
case CURL_WANTNO:
@@ -683,7 +637,7 @@ void rec_dont(struct connectdata *conn, int option)
case CURL_OPPOSITE:
tn->us[option] = CURL_WANTYES;
tn->usq[option] = CURL_EMPTY;
- send_negotiation(conn, CURL_WILL, option);
+ send_negotiation(data, CURL_WILL, option);
break;
}
break;
@@ -815,14 +769,14 @@ static void printsub(struct Curl_easy *data,
}
}
-static CURLcode check_telnet_options(struct connectdata *conn)
+static CURLcode check_telnet_options(struct Curl_easy *data)
{
struct curl_slist *head;
struct curl_slist *beg;
char option_keyword[128] = "";
char option_arg[256] = "";
- struct Curl_easy *data = conn->data;
- struct TELNET *tn = (struct TELNET *)conn->data->req.protop;
+ struct TELNET *tn = data->req.p.telnet;
+ struct connectdata *conn = data->conn;
CURLcode result = CURLE_OK;
int binary_option;
@@ -919,7 +873,7 @@ static CURLcode check_telnet_options(struct connectdata *conn)
* side.
*/
-static void suboption(struct connectdata *conn)
+static void suboption(struct Curl_easy *data)
{
struct curl_slist *v;
unsigned char temp[2048];
@@ -928,8 +882,8 @@ static void suboption(struct connectdata *conn)
int err;
char varname[128] = "";
char varval[128] = "";
- struct Curl_easy *data = conn->data;
- struct TELNET *tn = (struct TELNET *)data->req.protop;
+ struct TELNET *tn = data->req.p.telnet;
+ struct connectdata *conn = data->conn;
printsub(data, '<', (unsigned char *)tn->subbuffer, CURL_SB_LEN(tn) + 2);
switch(CURL_SB_GET(tn)) {
@@ -996,15 +950,14 @@ static void suboption(struct connectdata *conn)
* Send suboption information to the server side.
*/
-static void sendsuboption(struct connectdata *conn, int option)
+static void sendsuboption(struct Curl_easy *data, int option)
{
ssize_t bytes_written;
int err;
unsigned short x, y;
unsigned char *uc1, *uc2;
-
- struct Curl_easy *data = conn->data;
- struct TELNET *tn = (struct TELNET *)data->req.protop;
+ struct TELNET *tn = data->req.p.telnet;
+ struct connectdata *conn = data->conn;
switch(option) {
case CURL_TELOPT_NAWS:
@@ -1040,7 +993,7 @@ static void sendsuboption(struct connectdata *conn, int option)
}
/* ... then the window size with the send_telnet_data() function
to deal with 0xFF cases ... */
- send_telnet_data(conn, (char *)tn->subbuffer + 3, 4);
+ send_telnet_data(data, (char *)tn->subbuffer + 3, 4);
/* ... and the footer */
bytes_written = swrite(conn->sock[FIRSTSOCKET], tn->subbuffer + 7, 2);
if(bytes_written < 0) {
@@ -1053,7 +1006,7 @@ static void sendsuboption(struct connectdata *conn, int option)
static
-CURLcode telrcv(struct connectdata *conn,
+CURLcode telrcv(struct Curl_easy *data,
const unsigned char *inbuf, /* Data received from socket */
ssize_t count) /* Number of bytes received */
{
@@ -1061,12 +1014,11 @@ CURLcode telrcv(struct connectdata *conn,
CURLcode result;
int in = 0;
int startwrite = -1;
- struct Curl_easy *data = conn->data;
- struct TELNET *tn = (struct TELNET *)data->req.protop;
+ struct TELNET *tn = data->req.p.telnet;
#define startskipping() \
if(startwrite >= 0) { \
- result = Curl_client_write(conn, \
+ result = Curl_client_write(data, \
CLIENTWRITE_BODY, \
(char *)&inbuf[startwrite], \
in-startwrite); \
@@ -1142,28 +1094,28 @@ CURLcode telrcv(struct connectdata *conn,
case CURL_TS_WILL:
printoption(data, "RCVD", CURL_WILL, c);
tn->please_negotiate = 1;
- rec_will(conn, c);
+ rec_will(data, c);
tn->telrcv_state = CURL_TS_DATA;
break;
case CURL_TS_WONT:
printoption(data, "RCVD", CURL_WONT, c);
tn->please_negotiate = 1;
- rec_wont(conn, c);
+ rec_wont(data, c);
tn->telrcv_state = CURL_TS_DATA;
break;
case CURL_TS_DO:
printoption(data, "RCVD", CURL_DO, c);
tn->please_negotiate = 1;
- rec_do(conn, c);
+ rec_do(data, c);
tn->telrcv_state = CURL_TS_DATA;
break;
case CURL_TS_DONT:
printoption(data, "RCVD", CURL_DONT, c);
tn->please_negotiate = 1;
- rec_dont(conn, c);
+ rec_dont(data, c);
tn->telrcv_state = CURL_TS_DATA;
break;
@@ -1192,7 +1144,7 @@ CURLcode telrcv(struct connectdata *conn,
CURL_SB_TERM(tn);
printoption(data, "In SUBOPTION processing, RCVD", CURL_IAC, c);
- suboption(conn); /* handle sub-option */
+ suboption(data); /* handle sub-option */
tn->telrcv_state = CURL_TS_IAC;
goto process_iac;
}
@@ -1204,7 +1156,7 @@ CURLcode telrcv(struct connectdata *conn,
CURL_SB_ACCUM(tn, CURL_SE);
tn->subpointer -= 2;
CURL_SB_TERM(tn);
- suboption(conn); /* handle sub-option */
+ suboption(data); /* handle sub-option */
tn->telrcv_state = CURL_TS_DATA;
}
break;
@@ -1216,13 +1168,14 @@ CURLcode telrcv(struct connectdata *conn,
}
/* Escape and send a telnet data block */
-static CURLcode send_telnet_data(struct connectdata *conn,
+static CURLcode send_telnet_data(struct Curl_easy *data,
char *buffer, ssize_t nread)
{
ssize_t escapes, i, outlen;
unsigned char *outbuf = NULL;
CURLcode result = CURLE_OK;
ssize_t bytes_written, total_written;
+ struct connectdata *conn = data->conn;
/* Determine size of new buffer after escaping */
escapes = 0;
@@ -1261,7 +1214,7 @@ static CURLcode send_telnet_data(struct connectdata *conn,
break;
default: /* write! */
bytes_written = 0;
- result = Curl_write(conn, conn->sock[FIRSTSOCKET],
+ result = Curl_write(data, conn->sock[FIRSTSOCKET],
outbuf + total_written,
outlen - total_written,
&bytes_written);
@@ -1277,10 +1230,10 @@ static CURLcode send_telnet_data(struct connectdata *conn,
return result;
}
-static CURLcode telnet_done(struct connectdata *conn,
- CURLcode status, bool premature)
+static CURLcode telnet_done(struct Curl_easy *data,
+ CURLcode status, bool premature)
{
- struct TELNET *tn = (struct TELNET *)conn->data->req.protop;
+ struct TELNET *tn = data->req.p.telnet;
(void)status; /* unused */
(void)premature; /* not used */
@@ -1290,22 +1243,17 @@ static CURLcode telnet_done(struct connectdata *conn,
curl_slist_free_all(tn->telnet_vars);
tn->telnet_vars = NULL;
- Curl_safefree(conn->data->req.protop);
+ Curl_safefree(data->req.p.telnet);
return CURLE_OK;
}
-static CURLcode telnet_do(struct connectdata *conn, bool *done)
+static CURLcode telnet_do(struct Curl_easy *data, bool *done)
{
CURLcode result;
- struct Curl_easy *data = conn->data;
+ struct connectdata *conn = data->conn;
curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
#ifdef USE_WINSOCK
- HMODULE wsock2;
- WSOCK2_FUNC close_event_func;
- WSOCK2_EVENT create_event_func;
- WSOCK2_FUNC event_select_func;
- WSOCK2_FUNC enum_netevents_func;
WSAEVENT event_handle;
WSANETWORKEVENTS events;
HANDLE stdin_handle;
@@ -1329,86 +1277,32 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done)
*done = TRUE; /* unconditionally */
- result = init_telnet(conn);
+ result = init_telnet(data);
if(result)
return result;
- tn = (struct TELNET *)data->req.protop;
+ tn = data->req.p.telnet;
- result = check_telnet_options(conn);
+ result = check_telnet_options(data);
if(result)
return result;
#ifdef USE_WINSOCK
- /*
- ** This functionality only works with WinSock >= 2.0. So,
- ** make sure we have it.
- */
- result = check_wsock2(data);
- if(result)
- return result;
-
- /* OK, so we have WinSock 2.0. We need to dynamically */
- /* load ws2_32.dll and get the function pointers we need. */
- wsock2 = Curl_load_library(TEXT("WS2_32.DLL"));
- if(wsock2 == NULL) {
- failf(data, "failed to load WS2_32.DLL (%u)", GetLastError());
- return CURLE_FAILED_INIT;
- }
-
- /* Grab a pointer to WSACreateEvent */
- create_event_func =
- CURLX_FUNCTION_CAST(WSOCK2_EVENT,
- (GetProcAddress(wsock2, "WSACreateEvent")));
- if(create_event_func == NULL) {
- failf(data, "failed to find WSACreateEvent function (%u)", GetLastError());
- FreeLibrary(wsock2);
- return CURLE_FAILED_INIT;
- }
-
- /* And WSACloseEvent */
- close_event_func = GetProcAddress(wsock2, "WSACloseEvent");
- if(close_event_func == NULL) {
- failf(data, "failed to find WSACloseEvent function (%u)", GetLastError());
- FreeLibrary(wsock2);
- return CURLE_FAILED_INIT;
- }
-
- /* And WSAEventSelect */
- event_select_func = GetProcAddress(wsock2, "WSAEventSelect");
- if(event_select_func == NULL) {
- failf(data, "failed to find WSAEventSelect function (%u)", GetLastError());
- FreeLibrary(wsock2);
- return CURLE_FAILED_INIT;
- }
-
- /* And WSAEnumNetworkEvents */
- enum_netevents_func = GetProcAddress(wsock2, "WSAEnumNetworkEvents");
- if(enum_netevents_func == NULL) {
- failf(data, "failed to find WSAEnumNetworkEvents function (%u)",
- GetLastError());
- FreeLibrary(wsock2);
- return CURLE_FAILED_INIT;
- }
-
/* We want to wait for both stdin and the socket. Since
** the select() function in winsock only works on sockets
** we have to use the WaitForMultipleObjects() call.
*/
/* First, create a sockets event object */
- event_handle = (WSAEVENT)create_event_func();
+ event_handle = WSACreateEvent();
if(event_handle == WSA_INVALID_EVENT) {
failf(data, "WSACreateEvent failed (%d)", SOCKERRNO);
- FreeLibrary(wsock2);
return CURLE_FAILED_INIT;
}
/* Tell winsock what events we want to listen to */
- if(event_select_func(sockfd, event_handle, FD_READ|FD_CLOSE) ==
- SOCKET_ERROR) {
- close_event_func(event_handle);
- FreeLibrary(wsock2);
+ if(WSAEventSelect(sockfd, event_handle, FD_READ|FD_CLOSE) == SOCKET_ERROR) {
+ WSACloseEvent(event_handle);
return CURLE_OK;
}
@@ -1439,6 +1333,7 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done)
DWORD waitret = WaitForMultipleObjects(obj_count, objs,
FALSE, wait_timeout);
switch(waitret) {
+
case WAIT_TIMEOUT:
{
for(;;) {
@@ -1481,7 +1376,7 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done)
}
}
- result = send_telnet_data(conn, buf, readfile_read);
+ result = send_telnet_data(data, buf, readfile_read);
if(result) {
keepon = FALSE;
break;
@@ -1499,7 +1394,7 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done)
break;
}
- result = send_telnet_data(conn, buf, readfile_read);
+ result = send_telnet_data(data, buf, readfile_read);
if(result) {
keepon = FALSE;
break;
@@ -1508,9 +1403,9 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done)
break;
case WAIT_OBJECT_0:
-
+ {
events.lNetworkEvents = 0;
- if(SOCKET_ERROR == enum_netevents_func(sockfd, event_handle, &events)) {
+ if(WSAEnumNetworkEvents(sockfd, event_handle, &events) == SOCKET_ERROR) {
err = SOCKERRNO;
if(err != EINPROGRESS) {
infof(data, "WSAEnumNetworkEvents failed (%d)", err);
@@ -1521,7 +1416,7 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done)
}
if(events.lNetworkEvents & FD_READ) {
/* read data from network */
- result = Curl_read(conn, sockfd, buf, data->set.buffer_size, &nread);
+ result = Curl_read(data, sockfd, buf, data->set.buffer_size, &nread);
/* read would've blocked. Loop again */
if(result == CURLE_AGAIN)
break;
@@ -1537,7 +1432,7 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done)
break;
}
- result = telrcv(conn, (unsigned char *) buf, nread);
+ result = telrcv(data, (unsigned char *) buf, nread);
if(result) {
keepon = FALSE;
break;
@@ -1547,14 +1442,15 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done)
otherwise don't. We don't want to speak telnet with
non-telnet servers, like POP or SMTP. */
if(tn->please_negotiate && !tn->already_negotiated) {
- negotiate(conn);
+ negotiate(data);
tn->already_negotiated = 1;
}
}
if(events.lNetworkEvents & FD_CLOSE) {
keepon = FALSE;
}
- break;
+ }
+ break;
}
@@ -1569,19 +1465,9 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done)
}
/* We called WSACreateEvent, so call WSACloseEvent */
- if(!close_event_func(event_handle)) {
+ if(!WSACloseEvent(event_handle)) {
infof(data, "WSACloseEvent failed (%d)", SOCKERRNO);
}
-
- /* "Forget" pointers into the library we're about to free */
- create_event_func = NULL;
- close_event_func = NULL;
- event_select_func = NULL;
- enum_netevents_func = NULL;
-
- /* We called LoadLibrary, so call FreeLibrary */
- if(!FreeLibrary(wsock2))
- infof(data, "FreeLibrary(wsock2) failed (%u)", GetLastError());
#else
pfd[0].fd = sockfd;
pfd[0].events = POLLIN;
@@ -1610,7 +1496,7 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done)
default: /* read! */
if(pfd[0].revents & POLLIN) {
/* read data from network */
- result = Curl_read(conn, sockfd, buf, data->set.buffer_size, &nread);
+ result = Curl_read(data, sockfd, buf, data->set.buffer_size, &nread);
/* read would've blocked. Loop again */
if(result == CURLE_AGAIN)
break;
@@ -1628,7 +1514,7 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done)
total_dl += nread;
Curl_pgrsSetDownloadCounter(data, total_dl);
- result = telrcv(conn, (unsigned char *)buf, nread);
+ result = telrcv(data, (unsigned char *)buf, nread);
if(result) {
keepon = FALSE;
break;
@@ -1638,7 +1524,7 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done)
otherwise don't. We don't want to speak telnet with
non-telnet servers, like POP or SMTP. */
if(tn->please_negotiate && !tn->already_negotiated) {
- negotiate(conn);
+ negotiate(data);
tn->already_negotiated = 1;
}
}
@@ -1662,7 +1548,7 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done)
}
if(nread > 0) {
- result = send_telnet_data(conn, buf, nread);
+ result = send_telnet_data(data, buf, nread);
if(result) {
keepon = FALSE;
break;
@@ -1685,7 +1571,7 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done)
}
}
- if(Curl_pgrsUpdate(conn)) {
+ if(Curl_pgrsUpdate(data)) {
result = CURLE_ABORTED_BY_CALLBACK;
break;
}
diff --git a/Utilities/cmcurl/lib/telnet.h b/Utilities/cmcurl/lib/telnet.h
index 431427f39..1427473a9 100644
--- a/Utilities/cmcurl/lib/telnet.h
+++ b/Utilities/cmcurl/lib/telnet.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
diff --git a/Utilities/cmcurl/lib/tftp.c b/Utilities/cmcurl/lib/tftp.c
index 378d95608..3f1d1b51b 100644
--- a/Utilities/cmcurl/lib/tftp.c
+++ b/Utilities/cmcurl/lib/tftp.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -124,7 +124,7 @@ struct tftp_state_data {
tftp_mode_t mode;
tftp_error_t error;
tftp_event_t event;
- struct connectdata *conn;
+ struct Curl_easy *data;
curl_socket_t sockfd;
int retries;
int retry_time;
@@ -132,7 +132,6 @@ struct tftp_state_data {
time_t start_time;
time_t max_time;
time_t rx_time;
- unsigned short block;
struct Curl_sockaddr_storage local_addr;
struct Curl_sockaddr_storage remote_addr;
curl_socklen_t remote_addrlen;
@@ -140,6 +139,7 @@ struct tftp_state_data {
int sbytes;
int blksize;
int requested_blksize;
+ unsigned short block;
struct tftp_packet rpacket;
struct tftp_packet spacket;
};
@@ -148,16 +148,19 @@ 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_connect(struct connectdata *conn, bool *done);
-static CURLcode tftp_disconnect(struct connectdata *conn,
+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 connectdata *conn, bool *done);
-static CURLcode tftp_done(struct connectdata *conn,
+static CURLcode tftp_do(struct Curl_easy *data, bool *done);
+static CURLcode tftp_done(struct Curl_easy *data,
CURLcode, bool premature);
-static CURLcode tftp_setup_connection(struct connectdata *conn);
-static CURLcode tftp_multi_statemach(struct connectdata *conn, bool *done);
-static CURLcode tftp_doing(struct connectdata *conn, bool *dophase_done);
-static int tftp_getsock(struct connectdata *conn, curl_socket_t *socks);
+static CURLcode tftp_setup_connection(struct Curl_easy *data,
+ struct connectdata *conn);
+static CURLcode tftp_multi_statemach(struct Curl_easy *data, bool *done);
+static CURLcode tftp_doing(struct Curl_easy *data, bool *dophase_done);
+static int tftp_getsock(struct Curl_easy *data, struct connectdata *conn,
+ curl_socket_t *socks);
static CURLcode tftp_translate_code(tftp_error_t error);
@@ -183,6 +186,7 @@ const struct Curl_handler Curl_handler_tftp = {
ZERO_NULL, /* connection_check */
PORT_TFTP, /* defport */
CURLPROTO_TFTP, /* protocol */
+ CURLPROTO_TFTP, /* family */
PROTOPT_NONE | PROTOPT_NOURLQUERY /* flags */
};
@@ -205,11 +209,11 @@ static CURLcode tftp_set_timeouts(struct tftp_state_data *state)
time(&state->start_time);
/* Compute drop-dead time */
- timeout_ms = Curl_timeleft(state->conn->data, NULL, start);
+ timeout_ms = Curl_timeleft(state->data, NULL, start);
if(timeout_ms < 0) {
/* time-out, bail out, go home */
- failf(state->conn->data, "Connection time-out");
+ failf(state->data, "Connection time-out");
return CURLE_OPERATION_TIMEDOUT;
}
@@ -260,7 +264,7 @@ static CURLcode tftp_set_timeouts(struct tftp_state_data *state)
if(state->retry_time<1)
state->retry_time = 1;
- infof(state->conn->data,
+ infof(state->data,
"set timeouts for state %d; Total %ld, retry %d maxtry %d\n",
(int)state->state, (long)(state->max_time-state->start_time),
state->retry_time, state->retry_max);
@@ -302,7 +306,7 @@ static unsigned short getrpacketblock(const struct tftp_packet *packet)
return (unsigned short)((packet->data[2] << 8) | packet->data[3]);
}
-static size_t Curl_strnlen(const char *string, size_t maxlen)
+static size_t tftp_strnlen(const char *string, size_t maxlen)
{
const char *end = memchr(string, '\0', maxlen);
return end ? (size_t) (end - string) : maxlen;
@@ -313,14 +317,14 @@ static const char *tftp_option_get(const char *buf, size_t len,
{
size_t loc;
- loc = Curl_strnlen(buf, len);
+ loc = tftp_strnlen(buf, len);
loc++; /* NULL term */
if(loc >= len)
return NULL;
*option = buf;
- loc += Curl_strnlen(buf + loc, len-loc);
+ loc += tftp_strnlen(buf + loc, len-loc);
loc++; /* NULL term */
if(loc > len)
@@ -334,7 +338,7 @@ static CURLcode tftp_parse_option_ack(struct tftp_state_data *state,
const char *ptr, int len)
{
const char *tmp = ptr;
- struct Curl_easy *data = state->conn->data;
+ struct Curl_easy *data = state->data;
/* if OACK doesn't contain blksize option, the default (512) must be used */
state->blksize = TFTP_BLKSIZE_DEFAULT;
@@ -418,7 +422,7 @@ static CURLcode tftp_connect_for_tx(struct tftp_state_data *state,
{
CURLcode result;
#ifndef CURL_DISABLE_VERBOSE_STRINGS
- struct Curl_easy *data = state->conn->data;
+ struct Curl_easy *data = state->data;
infof(data, "%s\n", "Connected for transmit");
#endif
@@ -434,7 +438,7 @@ static CURLcode tftp_connect_for_rx(struct tftp_state_data *state,
{
CURLcode result;
#ifndef CURL_DISABLE_VERBOSE_STRINGS
- struct Curl_easy *data = state->conn->data;
+ struct Curl_easy *data = state->data;
infof(data, "%s\n", "Connected for receive");
#endif
@@ -452,7 +456,7 @@ static CURLcode tftp_send_first(struct tftp_state_data *state,
ssize_t senddata;
const char *mode = "octet";
char *filename;
- struct Curl_easy *data = state->conn->data;
+ struct Curl_easy *data = state->data;
CURLcode result = CURLE_OK;
/* Set ascii mode if -B flag was used */
@@ -474,7 +478,7 @@ static CURLcode tftp_send_first(struct tftp_state_data *state,
if(data->set.upload) {
/* If we are uploading, send an WRQ */
setpacketevent(&state->spacket, TFTP_EVENT_WRQ);
- state->conn->data->req.upload_fromhere =
+ state->data->req.upload_fromhere =
(char *)state->spacket.data + 4;
if(data->state.infilesize != -1)
Curl_pgrsSetUploadSize(data, data->state.infilesize);
@@ -486,13 +490,13 @@ static CURLcode tftp_send_first(struct tftp_state_data *state,
/* As RFC3617 describes the separator slash is not actually part of the
file name so we skip the always-present first letter of the path
string. */
- result = Curl_urldecode(data, &state->conn->data->state.up.path[1], 0,
+ result = Curl_urldecode(data, &state->data->state.up.path[1], 0,
&filename, NULL, REJECT_ZERO);
if(result)
return result;
if(strlen(filename) > (state->blksize - strlen(mode) - 4)) {
- failf(data, "TFTP file name too long\n");
+ failf(data, "TFTP file name too long");
free(filename);
return CURLE_TFTP_ILLEGAL; /* too long file name field */
}
@@ -550,8 +554,8 @@ static CURLcode tftp_send_first(struct tftp_state_data *state,
not have a size_t argument, like older unixes that want an 'int' */
senddata = sendto(state->sockfd, (void *)state->spacket.data,
(SEND_TYPE_ARG3)sbytes, 0,
- state->conn->ip_addr->ai_addr,
- state->conn->ip_addr->ai_addrlen);
+ data->conn->ip_addr->ai_addr,
+ data->conn->ip_addr->ai_addrlen);
if(senddata != (ssize_t)sbytes) {
char buffer[STRERROR_LEN];
failf(data, "%s", Curl_strerror(SOCKERRNO, buffer, sizeof(buffer)));
@@ -581,7 +585,7 @@ static CURLcode tftp_send_first(struct tftp_state_data *state,
break;
default:
- failf(state->conn->data, "tftp_send_first: internal error");
+ failf(state->data, "tftp_send_first: internal error");
break;
}
@@ -604,7 +608,7 @@ static CURLcode tftp_rx(struct tftp_state_data *state,
{
ssize_t sbytes;
int rblock;
- struct Curl_easy *data = state->conn->data;
+ struct Curl_easy *data = state->data;
char buffer[STRERROR_LEN];
switch(event) {
@@ -724,7 +728,7 @@ static CURLcode tftp_rx(struct tftp_state_data *state,
**********************************************************/
static CURLcode tftp_tx(struct tftp_state_data *state, tftp_event_t event)
{
- struct Curl_easy *data = state->conn->data;
+ struct Curl_easy *data = state->data;
ssize_t sbytes;
CURLcode result = CURLE_OK;
struct SingleRequest *k = &data->req;
@@ -793,14 +797,13 @@ static CURLcode tftp_tx(struct tftp_state_data *state, tftp_event_t event)
* data block.
* */
state->sbytes = 0;
- state->conn->data->req.upload_fromhere = (char *)state->spacket.data + 4;
+ state->data->req.upload_fromhere = (char *)state->spacket.data + 4;
do {
- result = Curl_fillreadbuffer(state->conn, state->blksize - state->sbytes,
- &cb);
+ result = Curl_fillreadbuffer(data, state->blksize - state->sbytes, &cb);
if(result)
return result;
state->sbytes += (int)cb;
- state->conn->data->req.upload_fromhere += cb;
+ state->data->req.upload_fromhere += cb;
} while(state->sbytes < state->blksize && cb != 0);
sbytes = sendto(state->sockfd, (void *) state->spacket.data,
@@ -926,7 +929,7 @@ static CURLcode tftp_state_machine(struct tftp_state_data *state,
tftp_event_t event)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = state->conn->data;
+ struct Curl_easy *data = state->data;
switch(state->state) {
case TFTP_STATE_START:
@@ -961,9 +964,11 @@ static CURLcode tftp_state_machine(struct tftp_state_data *state,
* The disconnect callback
*
**********************************************************/
-static CURLcode tftp_disconnect(struct connectdata *conn, bool dead_connection)
+static CURLcode tftp_disconnect(struct Curl_easy *data,
+ struct connectdata *conn, bool dead_connection)
{
struct tftp_state_data *state = conn->proto.tftpc;
+ (void) data;
(void) dead_connection;
/* done, free dynamically allocated pkt buffers */
@@ -983,11 +988,12 @@ static CURLcode tftp_disconnect(struct connectdata *conn, bool dead_connection)
* The connect callback
*
**********************************************************/
-static CURLcode tftp_connect(struct connectdata *conn, bool *done)
+static CURLcode tftp_connect(struct Curl_easy *data, bool *done)
{
struct tftp_state_data *state;
int blksize;
int need_blksize;
+ struct connectdata *conn = data->conn;
blksize = TFTP_BLKSIZE_DEFAULT;
@@ -996,8 +1002,8 @@ static CURLcode tftp_connect(struct connectdata *conn, bool *done)
return CURLE_OUT_OF_MEMORY;
/* alloc pkt buffers based on specified blksize */
- if(conn->data->set.tftp_blksize) {
- blksize = (int)conn->data->set.tftp_blksize;
+ if(data->set.tftp_blksize) {
+ blksize = (int)data->set.tftp_blksize;
if(blksize > TFTP_BLKSIZE_MAX || blksize < TFTP_BLKSIZE_MIN)
return CURLE_TFTP_ILLEGAL;
}
@@ -1025,8 +1031,8 @@ static CURLcode tftp_connect(struct connectdata *conn, bool *done)
* little gain for UDP */
connclose(conn, "TFTP");
- state->conn = conn;
- state->sockfd = state->conn->sock[FIRSTSOCKET];
+ state->data = data;
+ state->sockfd = conn->sock[FIRSTSOCKET];
state->state = TFTP_STATE_START;
state->error = TFTP_ERR_NONE;
state->blksize = TFTP_BLKSIZE_DEFAULT; /* Unless updated by OACK response */
@@ -1055,14 +1061,14 @@ static CURLcode tftp_connect(struct connectdata *conn, bool *done)
conn->ip_addr->ai_addrlen);
if(rc) {
char buffer[STRERROR_LEN];
- failf(conn->data, "bind() failed; %s",
+ failf(data, "bind() failed; %s",
Curl_strerror(SOCKERRNO, buffer, sizeof(buffer)));
return CURLE_COULDNT_CONNECT;
}
conn->bits.bound = TRUE;
}
- Curl_pgrsStartNow(conn->data);
+ Curl_pgrsStartNow(data);
*done = TRUE;
@@ -1076,16 +1082,17 @@ static CURLcode tftp_connect(struct connectdata *conn, bool *done)
* The done callback
*
**********************************************************/
-static CURLcode tftp_done(struct connectdata *conn, CURLcode status,
+static CURLcode tftp_done(struct Curl_easy *data, CURLcode status,
bool premature)
{
CURLcode result = CURLE_OK;
+ struct connectdata *conn = data->conn;
struct tftp_state_data *state = conn->proto.tftpc;
(void)status; /* unused */
(void)premature; /* not used */
- if(Curl_pgrsDone(conn))
+ if(Curl_pgrsDone(data))
return CURLE_ABORTED_BY_CALLBACK;
/* If we have encountered an error */
@@ -1102,8 +1109,10 @@ static CURLcode tftp_done(struct connectdata *conn, CURLcode status,
* The getsock callback
*
**********************************************************/
-static int tftp_getsock(struct connectdata *conn, curl_socket_t *socks)
+static int tftp_getsock(struct Curl_easy *data,
+ struct connectdata *conn, curl_socket_t *socks)
{
+ (void)data;
socks[0] = conn->sock[FIRSTSOCKET];
return GETSOCK_READSOCK(0);
}
@@ -1115,12 +1124,12 @@ static int tftp_getsock(struct connectdata *conn, curl_socket_t *socks)
* Called once select fires and data is ready on the socket
*
**********************************************************/
-static CURLcode tftp_receive_packet(struct connectdata *conn)
+static CURLcode tftp_receive_packet(struct Curl_easy *data)
{
struct Curl_sockaddr_storage fromaddr;
curl_socklen_t fromlen;
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
+ struct connectdata *conn = data->conn;
struct tftp_state_data *state = conn->proto.tftpc;
struct SingleRequest *k = &data->req;
@@ -1153,7 +1162,7 @@ static CURLcode tftp_receive_packet(struct connectdata *conn)
/* Don't pass to the client empty or retransmitted packets */
if(state->rbytes > 4 &&
(NEXT_BLOCKNUM(state->block) == getrpacketblock(&state->rpacket))) {
- result = Curl_client_write(conn, CLIENTWRITE_BODY,
+ result = Curl_client_write(data, CLIENTWRITE_BODY,
(char *)state->rpacket.data + 4,
state->rbytes-4);
if(result) {
@@ -1170,7 +1179,7 @@ static CURLcode tftp_receive_packet(struct connectdata *conn)
char *str = (char *)state->rpacket.data + 4;
size_t strn = state->rbytes - 4;
state->error = (tftp_error_t)error;
- if(Curl_strnlen(str, strn) < strn)
+ if(tftp_strnlen(str, strn) < strn)
infof(data, "TFTP error: %s\n", str);
break;
}
@@ -1191,7 +1200,7 @@ static CURLcode tftp_receive_packet(struct connectdata *conn)
}
/* Update the progress meter */
- if(Curl_pgrsUpdate(conn)) {
+ if(Curl_pgrsUpdate(data)) {
tftp_state_machine(state, TFTP_EVENT_ERROR);
return CURLE_ABORTED_BY_CALLBACK;
}
@@ -1206,9 +1215,10 @@ static CURLcode tftp_receive_packet(struct connectdata *conn)
* Check if timeouts have been reached
*
**********************************************************/
-static long tftp_state_timeout(struct connectdata *conn, tftp_event_t *event)
+static long tftp_state_timeout(struct Curl_easy *data, tftp_event_t *event)
{
time_t current;
+ struct connectdata *conn = data->conn;
struct tftp_state_data *state = conn->proto.tftpc;
if(event)
@@ -1216,7 +1226,7 @@ static long tftp_state_timeout(struct connectdata *conn, tftp_event_t *event)
time(&current);
if(current > state->max_time) {
- DEBUGF(infof(conn->data, "timeout: %ld > %ld\n",
+ DEBUGF(infof(data, "timeout: %ld > %ld\n",
(long)current, (long)state->max_time));
state->error = TFTP_ERR_TIMEOUT;
state->state = TFTP_STATE_FIN;
@@ -1241,13 +1251,13 @@ static long tftp_state_timeout(struct connectdata *conn, tftp_event_t *event)
* Handle single RX socket event and return
*
**********************************************************/
-static CURLcode tftp_multi_statemach(struct connectdata *conn, bool *done)
+static CURLcode tftp_multi_statemach(struct Curl_easy *data, bool *done)
{
- tftp_event_t event;
- CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
+ tftp_event_t event;
+ CURLcode result = CURLE_OK;
+ struct connectdata *conn = data->conn;
struct tftp_state_data *state = conn->proto.tftpc;
- long timeout_ms = tftp_state_timeout(conn, &event);
+ long timeout_ms = tftp_state_timeout(data, &event);
*done = FALSE;
@@ -1276,7 +1286,7 @@ static CURLcode tftp_multi_statemach(struct connectdata *conn, bool *done)
state->event = TFTP_EVENT_ERROR;
}
else if(rc != 0) {
- result = tftp_receive_packet(conn);
+ result = tftp_receive_packet(data);
if(result)
return result;
result = tftp_state_machine(state, state->event);
@@ -1300,22 +1310,22 @@ static CURLcode tftp_multi_statemach(struct connectdata *conn, bool *done)
* Called from multi.c while DOing
*
**********************************************************/
-static CURLcode tftp_doing(struct connectdata *conn, bool *dophase_done)
+static CURLcode tftp_doing(struct Curl_easy *data, bool *dophase_done)
{
CURLcode result;
- result = tftp_multi_statemach(conn, dophase_done);
+ result = tftp_multi_statemach(data, dophase_done);
if(*dophase_done) {
- DEBUGF(infof(conn->data, "DO phase is complete\n"));
+ DEBUGF(infof(data, "DO phase is complete\n"));
}
else if(!result) {
/* The multi code doesn't have this logic for the DOING state so we
provide it for TFTP since it may do the entire transfer in this
state. */
- if(Curl_pgrsUpdate(conn))
+ if(Curl_pgrsUpdate(data))
result = CURLE_ABORTED_BY_CALLBACK;
else
- result = Curl_speedcheck(conn->data, Curl_now());
+ result = Curl_speedcheck(data, Curl_now());
}
return result;
}
@@ -1327,9 +1337,10 @@ static CURLcode tftp_doing(struct connectdata *conn, bool *dophase_done)
* Entry point for transfer from tftp_do, sarts state mach
*
**********************************************************/
-static CURLcode tftp_perform(struct connectdata *conn, bool *dophase_done)
+static CURLcode tftp_perform(struct Curl_easy *data, bool *dophase_done)
{
- CURLcode result = CURLE_OK;
+ CURLcode result = CURLE_OK;
+ struct connectdata *conn = data->conn;
struct tftp_state_data *state = conn->proto.tftpc;
*dophase_done = FALSE;
@@ -1339,10 +1350,10 @@ static CURLcode tftp_perform(struct connectdata *conn, bool *dophase_done)
if((state->state == TFTP_STATE_FIN) || result)
return result;
- tftp_multi_statemach(conn, dophase_done);
+ tftp_multi_statemach(data, dophase_done);
if(*dophase_done)
- DEBUGF(infof(conn->data, "DO phase is complete\n"));
+ DEBUGF(infof(data, "DO phase is complete\n"));
return result;
}
@@ -1358,15 +1369,16 @@ static CURLcode tftp_perform(struct connectdata *conn, bool *dophase_done)
*
**********************************************************/
-static CURLcode tftp_do(struct connectdata *conn, bool *done)
+static CURLcode tftp_do(struct Curl_easy *data, bool *done)
{
struct tftp_state_data *state;
CURLcode result;
+ struct connectdata *conn = data->conn;
*done = FALSE;
if(!conn->proto.tftpc) {
- result = tftp_connect(conn, done);
+ result = tftp_connect(data, done);
if(result)
return result;
}
@@ -1375,7 +1387,7 @@ static CURLcode tftp_do(struct connectdata *conn, bool *done)
if(!state)
return CURLE_TFTP_ILLEGAL;
- result = tftp_perform(conn, done);
+ result = tftp_perform(data, done);
/* If tftp_perform() returned an error, use that for return code. If it
was OK, see if tftp_translate_code() has an error. */
@@ -1386,9 +1398,9 @@ static CURLcode tftp_do(struct connectdata *conn, bool *done)
return result;
}
-static CURLcode tftp_setup_connection(struct connectdata *conn)
+static CURLcode tftp_setup_connection(struct Curl_easy *data,
+ struct connectdata *conn)
{
- struct Curl_easy *data = conn->data;
char *type;
conn->transport = TRNSPRT_UDP;
diff --git a/Utilities/cmcurl/lib/tftp.h b/Utilities/cmcurl/lib/tftp.h
index 33348300f..4b5bea275 100644
--- a/Utilities/cmcurl/lib/tftp.h
+++ b/Utilities/cmcurl/lib/tftp.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
diff --git a/Utilities/cmcurl/lib/timeval.c b/Utilities/cmcurl/lib/timeval.c
index e761966a1..8523dad40 100644
--- a/Utilities/cmcurl/lib/timeval.c
+++ b/Utilities/cmcurl/lib/timeval.c
@@ -9,7 +9,7 @@
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/timeval.h b/Utilities/cmcurl/lib/timeval.h
index 53e063607..685e72961 100644
--- a/Utilities/cmcurl/lib/timeval.h
+++ b/Utilities/cmcurl/lib/timeval.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
diff --git a/Utilities/cmcurl/lib/transfer.c b/Utilities/cmcurl/lib/transfer.c
index a07c7af8c..2f29b29d8 100644
--- a/Utilities/cmcurl/lib/transfer.c
+++ b/Utilities/cmcurl/lib/transfer.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -78,6 +78,7 @@
#include "mime.h"
#include "strcase.h"
#include "urlapi-int.h"
+#include "hsts.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
@@ -92,12 +93,11 @@
*
* Returns a pointer to the first matching header or NULL if none matched.
*/
-char *Curl_checkheaders(const struct connectdata *conn,
+char *Curl_checkheaders(const struct Curl_easy *data,
const char *thisheader)
{
struct curl_slist *head;
size_t thislen = strlen(thisheader);
- struct Curl_easy *data = conn->data;
for(head = data->set.headers; head; head = head->next) {
if(strncasecompare(head->data, thisheader, thislen) &&
@@ -124,8 +124,8 @@ CURLcode Curl_get_upload_buffer(struct Curl_easy *data)
* This function will be called to loop through the trailers buffer
* until no more data is available for sending.
*/
-static size_t Curl_trailers_read(char *buffer, size_t size, size_t nitems,
- void *raw)
+static size_t trailers_read(char *buffer, size_t size, size_t nitems,
+ void *raw)
{
struct Curl_easy *data = (struct Curl_easy *)raw;
struct dynbuf *trailers_buf = &data->state.trailers_buf;
@@ -141,7 +141,7 @@ static size_t Curl_trailers_read(char *buffer, size_t size, size_t nitems,
return to_copy;
}
-static size_t Curl_trailers_left(void *raw)
+static size_t trailers_left(void *raw)
{
struct Curl_easy *data = (struct Curl_easy *)raw;
struct dynbuf *trailers_buf = &data->state.trailers_buf;
@@ -153,10 +153,9 @@ static size_t Curl_trailers_left(void *raw)
* This function will call the read callback to fill our buffer with data
* to upload.
*/
-CURLcode Curl_fillreadbuffer(struct connectdata *conn, size_t bytes,
+CURLcode Curl_fillreadbuffer(struct Curl_easy *data, size_t bytes,
size_t *nreadp)
{
- struct Curl_easy *data = conn->data;
size_t buffersize = bytes;
size_t nread;
@@ -165,9 +164,10 @@ CURLcode Curl_fillreadbuffer(struct connectdata *conn, size_t bytes,
#ifdef CURL_DOES_CONVERSIONS
bool sending_http_headers = FALSE;
+ struct connectdata *conn = data->conn;
if(conn->handler->protocol&(PROTO_FAMILY_HTTP|CURLPROTO_RTSP)) {
- const struct HTTP *http = data->req.protop;
+ const struct HTTP *http = data->req.p.http;
if(http->sending == HTTPSEND_REQUEST)
/* We're sending the HTTP request headers, not the data.
@@ -230,7 +230,7 @@ CURLcode Curl_fillreadbuffer(struct connectdata *conn, size_t bytes,
simply return to the previous point in the state machine as if
nothing happened.
*/
- readfunc = Curl_trailers_read;
+ readfunc = trailers_read;
extra_data = (void *)data;
}
else
@@ -253,7 +253,7 @@ CURLcode Curl_fillreadbuffer(struct connectdata *conn, size_t bytes,
if(nread == CURL_READFUNC_PAUSE) {
struct SingleRequest *k = &data->req;
- if(conn->handler->flags & PROTOPT_NONETWORK) {
+ if(data->conn->handler->flags & PROTOPT_NONETWORK) {
/* protocols that work without network cannot be paused. This is
actually only FILE:// just now, and it can't pause since the transfer
isn't done using the "normal" procedure. */
@@ -366,7 +366,7 @@ CURLcode Curl_fillreadbuffer(struct connectdata *conn, size_t bytes,
#ifndef CURL_DISABLE_HTTP
if(data->state.trailers_state == TRAILERS_SENDING &&
- !Curl_trailers_left(data)) {
+ !trailers_left(data)) {
Curl_dyn_free(&data->state.trailers_buf);
data->state.trailers_state = TRAILERS_DONE;
data->set.trailer_data = NULL;
@@ -409,9 +409,9 @@ CURLcode Curl_fillreadbuffer(struct connectdata *conn, size_t bytes,
* POST/PUT with multi-pass authentication when a sending was denied and a
* resend is necessary.
*/
-CURLcode Curl_readrewind(struct connectdata *conn)
+CURLcode Curl_readrewind(struct Curl_easy *data)
{
- struct Curl_easy *data = conn->data;
+ struct connectdata *conn = data->conn;
curl_mimepart *mimepart = &data->set.mimepost;
conn->bits.rewindaftersend = FALSE; /* we rewind now */
@@ -426,7 +426,7 @@ CURLcode Curl_readrewind(struct connectdata *conn)
CURLOPT_HTTPPOST, call app to rewind
*/
if(conn->handler->protocol & PROTO_FAMILY_HTTP) {
- struct HTTP *http = data->req.protop;
+ struct HTTP *http = data->req.p.http;
if(http->sendit)
mimepart = http->sendit;
@@ -435,9 +435,10 @@ CURLcode Curl_readrewind(struct connectdata *conn)
; /* do nothing */
else if(data->state.httpreq == HTTPREQ_POST_MIME ||
data->state.httpreq == HTTPREQ_POST_FORM) {
- if(Curl_mime_rewind(mimepart)) {
+ CURLcode result = Curl_mime_rewind(mimepart);
+ if(result) {
failf(data, "Cannot rewind mime/post data");
- return CURLE_SEND_FAIL_REWIND;
+ return result;
}
}
else {
@@ -598,7 +599,7 @@ static CURLcode readwrite_data(struct Curl_easy *data,
if(bytestoread) {
/* receive data from the network! */
- result = Curl_read(conn, conn->sockfd, buf, bytestoread, &nread);
+ result = Curl_read(data, conn->sockfd, buf, bytestoread, &nread);
/* read would've blocked */
if(CURLE_AGAIN == result)
@@ -707,64 +708,10 @@ static CURLcode readwrite_data(struct Curl_easy *data,
write a piece of the body */
if(conn->handler->protocol&(PROTO_FAMILY_HTTP|CURLPROTO_RTSP)) {
/* HTTP-only checks */
-
- if(data->req.newurl) {
- if(conn->bits.close) {
- /* Abort after the headers if "follow Location" is set
- and we're set to close anyway. */
- k->keepon &= ~KEEP_RECV;
- *done = TRUE;
- return CURLE_OK;
- }
- /* We have a new url to load, but since we want to be able
- to re-use this connection properly, we read the full
- response in "ignore more" */
- k->ignorebody = TRUE;
- infof(data, "Ignoring the response-body\n");
- }
- if(data->state.resume_from && !k->content_range &&
- (data->state.httpreq == HTTPREQ_GET) &&
- !k->ignorebody) {
-
- if(k->size == data->state.resume_from) {
- /* The resume point is at the end of file, consider this fine
- even if it doesn't allow resume from here. */
- infof(data, "The entire document is already downloaded");
- connclose(conn, "already downloaded");
- /* Abort download */
- k->keepon &= ~KEEP_RECV;
- *done = TRUE;
- return CURLE_OK;
- }
-
- /* we wanted to resume a download, although the server doesn't
- * seem to support this and we did this with a GET (if it
- * wasn't a GET we did a POST or PUT resume) */
- failf(data, "HTTP server doesn't seem to support "
- "byte ranges. Cannot resume.");
- return CURLE_RANGE_ERROR;
- }
-
- if(data->set.timecondition && !data->state.range) {
- /* A time condition has been set AND no ranges have been
- requested. This seems to be what chapter 13.3.4 of
- RFC 2616 defines to be the correct action for a
- HTTP/1.1 client */
-
- if(!Curl_meets_timecondition(data, k->timeofdoc)) {
- *done = TRUE;
- /* We're simulating a http 304 from server so we return
- what should have been returned from the server */
- data->info.httpcode = 304;
- infof(data, "Simulate a HTTP 304 response!\n");
- /* we abort the transfer before it is completed == we ruin the
- re-use ability. Close the connection */
- connclose(conn, "Simulated 304 handling");
- return CURLE_OK;
- }
- } /* we have a time condition */
-
- } /* this is HTTP or RTSP */
+ result = Curl_http_firstwrite(data, conn, done);
+ if(result || *done)
+ return result;
+ }
} /* this is the first time we write a body part */
#endif /* CURL_DISABLE_HTTP */
@@ -795,7 +742,7 @@ static CURLcode readwrite_data(struct Curl_easy *data,
*/
CURLcode extra;
CHUNKcode res =
- Curl_httpchunk_read(conn, k->str, nread, &nread, &extra);
+ Curl_httpchunk_read(data, k->str, nread, &nread, &extra);
if(CHUNKE_OK < res) {
if(CHUNKE_PASSTHRU_ERROR == res) {
@@ -806,18 +753,15 @@ static CURLcode readwrite_data(struct Curl_easy *data,
return CURLE_RECV_ERROR;
}
if(CHUNKE_STOP == res) {
- size_t dataleft;
/* we're done reading chunks! */
k->keepon &= ~KEEP_RECV; /* read no more */
- /* There are now possibly N number of bytes at the end of the
- str buffer that weren't written to the client.
- Push it back to be read on the next pass. */
-
- dataleft = conn->chunk.dataleft;
- if(dataleft != 0) {
- infof(conn->data, "Leftovers after chunking: %zu bytes\n",
- dataleft);
+ /* N number of bytes at the end of the str buffer that weren't
+ written to the client. */
+ if(conn->chunk.datasize) {
+ infof(data, "Leftovers after chunking: % "
+ CURL_FORMAT_CURL_OFF_T "u bytes\n",
+ conn->chunk.datasize);
}
}
/* If it returned OK, we just keep going */
@@ -867,11 +811,11 @@ static CURLcode readwrite_data(struct Curl_easy *data,
/* Don't let excess data pollute body writes */
if(k->maxdownload == -1 || (curl_off_t)headlen <= k->maxdownload)
- result = Curl_client_write(conn, CLIENTWRITE_BODY,
+ result = Curl_client_write(data, CLIENTWRITE_BODY,
Curl_dyn_ptr(&data->state.headerb),
headlen);
else
- result = Curl_client_write(conn, CLIENTWRITE_BODY,
+ result = Curl_client_write(data, CLIENTWRITE_BODY,
Curl_dyn_ptr(&data->state.headerb),
(size_t)k->maxdownload);
@@ -884,19 +828,19 @@ static CURLcode readwrite_data(struct Curl_easy *data,
in http_chunks.c.
Make sure that ALL_CONTENT_ENCODINGS contains all the
encodings handled here. */
- if(conn->data->set.http_ce_skip || !k->writer_stack) {
+ if(data->set.http_ce_skip || !k->writer_stack) {
if(!k->ignorebody) {
#ifndef CURL_DISABLE_POP3
if(conn->handler->protocol & PROTO_FAMILY_POP3)
- result = Curl_pop3_write(conn, k->str, nread);
+ result = Curl_pop3_write(data, k->str, nread);
else
#endif /* CURL_DISABLE_POP3 */
- result = Curl_client_write(conn, CLIENTWRITE_BODY, k->str,
+ result = Curl_client_write(data, CLIENTWRITE_BODY, k->str,
nread);
}
}
else if(!k->ignorebody)
- result = Curl_unencode_write(conn, k->writer_stack, k->str, nread);
+ result = Curl_unencode_write(data, k->writer_stack, k->str, nread);
}
k->badheader = HEADER_NORMAL; /* taken care of now */
@@ -957,17 +901,18 @@ static CURLcode readwrite_data(struct Curl_easy *data,
return CURLE_OK;
}
-CURLcode Curl_done_sending(struct connectdata *conn,
+CURLcode Curl_done_sending(struct Curl_easy *data,
struct SingleRequest *k)
{
+ struct connectdata *conn = data->conn;
k->keepon &= ~KEEP_SEND; /* we're done writing */
/* These functions should be moved into the handler struct! */
- Curl_http2_done_sending(conn);
- Curl_quic_done_sending(conn);
+ Curl_http2_done_sending(data, conn);
+ Curl_quic_done_sending(data);
if(conn->bits.rewindaftersend) {
- CURLcode result = Curl_readrewind(conn);
+ CURLcode result = Curl_readrewind(data);
if(result)
return result;
}
@@ -1015,6 +960,8 @@ static CURLcode readwrite_upload(struct Curl_easy *data,
*didwhat |= KEEP_SEND;
do {
+ curl_off_t nbody;
+
/* only read more data if there's no upload data already
present in the upload buffer */
if(0 == k->upload_present) {
@@ -1028,7 +975,7 @@ static CURLcode readwrite_upload(struct Curl_easy *data,
/* HTTP pollution, this should be written nicer to become more
protocol agnostic. */
size_t fillcount;
- struct HTTP *http = k->protop;
+ struct HTTP *http = k->p.http;
if((k->exp100 == EXP100_SENDING_REQUEST) &&
(http->sending == HTTPSEND_BODY)) {
@@ -1053,7 +1000,7 @@ static CURLcode readwrite_upload(struct Curl_easy *data,
sending_http_headers = FALSE;
}
- result = Curl_fillreadbuffer(conn, data->set.upload_buffer_size,
+ result = Curl_fillreadbuffer(data, data->set.upload_buffer_size,
&fillcount);
if(result)
return result;
@@ -1068,7 +1015,7 @@ static CURLcode readwrite_upload(struct Curl_easy *data,
break;
}
if(nread <= 0) {
- result = Curl_done_sending(conn, k);
+ result = Curl_done_sending(data, k);
if(result)
return result;
break;
@@ -1130,7 +1077,7 @@ static CURLcode readwrite_upload(struct Curl_easy *data,
#ifndef CURL_DISABLE_SMTP
if(conn->handler->protocol & PROTO_FAMILY_SMTP) {
- result = Curl_smtp_escape_eob(conn, nread);
+ result = Curl_smtp_escape_eob(data, nread);
if(result)
return result;
}
@@ -1142,7 +1089,7 @@ static CURLcode readwrite_upload(struct Curl_easy *data,
}
/* write to socket (send away data) */
- result = Curl_write(conn,
+ result = Curl_write(data,
conn->writesockfd, /* socket to send to */
k->upload_fromhere, /* buffer pointer */
k->upload_present, /* buffer size */
@@ -1152,13 +1099,26 @@ static CURLcode readwrite_upload(struct Curl_easy *data,
win_update_buffer_size(conn->writesockfd);
- if(data->set.verbose)
+ if(k->pendingheader) {
+ /* parts of what was sent was header */
+ curl_off_t n = CURLMIN(k->pendingheader, bytes_written);
/* show the data before we change the pointer upload_fromhere */
- Curl_debug(data, CURLINFO_DATA_OUT, k->upload_fromhere,
- (size_t)bytes_written);
+ Curl_debug(data, CURLINFO_HEADER_OUT, k->upload_fromhere, (size_t)n);
+ k->pendingheader -= n;
+ nbody = bytes_written - n; /* size of the written body part */
+ }
+ else
+ nbody = bytes_written;
- k->writebytecount += bytes_written;
- Curl_pgrsSetUploadCounter(data, k->writebytecount);
+ if(nbody) {
+ /* show the data before we change the pointer upload_fromhere */
+ Curl_debug(data, CURLINFO_DATA_OUT,
+ &k->upload_fromhere[bytes_written - nbody],
+ (size_t)nbody);
+
+ k->writebytecount += nbody;
+ Curl_pgrsSetUploadCounter(data, k->writebytecount);
+ }
if((!k->upload_chunky || k->forbidchunk) &&
(k->writebytecount == data->state.infilesize)) {
@@ -1186,7 +1146,7 @@ static CURLcode readwrite_upload(struct Curl_easy *data,
k->upload_present = 0; /* no more bytes left */
if(k->upload_done) {
- result = Curl_done_sending(conn, k);
+ result = Curl_done_sending(data, k);
if(result)
return result;
}
@@ -1233,7 +1193,7 @@ CURLcode Curl_readwrite(struct connectdata *conn,
else
fd_write = CURL_SOCKET_BAD;
- if(conn->data->state.drain) {
+ if(data->state.drain) {
select_res |= CURL_CSELECT_IN;
DEBUGF(infof(data, "Curl_readwrite: forcibly told to drain data\n"));
}
@@ -1247,6 +1207,10 @@ CURLcode Curl_readwrite(struct connectdata *conn,
return CURLE_SEND_ERROR;
}
+#ifdef USE_HYPER
+ if(conn->datastream)
+ return conn->datastream(data, conn, &didwhat, done, select_res);
+#endif
/* We go ahead and do a read if we have a readable socket or if
the stream was rewound (in which case we have data in a
buffer) */
@@ -1266,10 +1230,7 @@ CURLcode Curl_readwrite(struct connectdata *conn,
}
k->now = Curl_now();
- if(didwhat) {
- ;
- }
- else {
+ if(!didwhat) {
/* no read no write, this is a timeout? */
if(k->exp100 == EXP100_AWAITING_CONTINUE) {
/* This should allow some time for the header to arrive, but only a
@@ -1296,7 +1257,7 @@ CURLcode Curl_readwrite(struct connectdata *conn,
}
}
- if(Curl_pgrsUpdate(conn))
+ if(Curl_pgrsUpdate(data))
result = CURLE_ABORTED_BY_CALLBACK;
else
result = Curl_speedcheck(data, k->now);
@@ -1355,7 +1316,7 @@ CURLcode Curl_readwrite(struct connectdata *conn,
failf(data, "transfer closed with outstanding read data remaining");
return CURLE_PARTIAL_FILE;
}
- if(Curl_pgrsUpdate(conn))
+ if(Curl_pgrsUpdate(data))
return CURLE_ABORTED_BY_CALLBACK;
}
@@ -1373,15 +1334,15 @@ CURLcode Curl_readwrite(struct connectdata *conn,
* keeps track of. This function will only be called for connections that are
* in the proper state to have this information available.
*/
-int Curl_single_getsock(const struct connectdata *conn,
+int Curl_single_getsock(struct Curl_easy *data,
+ struct connectdata *conn,
curl_socket_t *sock)
{
- const struct Curl_easy *data = conn->data;
int bitmap = GETSOCK_BLANK;
unsigned sockindex = 0;
if(conn->handler->perform_getsock)
- return conn->handler->perform_getsock(conn, sock);
+ return conn->handler->perform_getsock(data, conn, sock);
/* don't include HOLD and PAUSE connections */
if((data->req.keepon & KEEP_RECVBITS) == KEEP_RECV) {
@@ -1529,8 +1490,23 @@ CURLcode Curl_pretransfer(struct Curl_easy *data)
}
#endif
Curl_http2_init_state(&data->state);
+ Curl_hsts_loadcb(data, data->hsts);
+ }
+
+ /*
+ * Set user-agent. Used for HTTP, but since we can attempt to tunnel
+ * basically anything through a http proxy we can't limit this based on
+ * protocol.
+ */
+ if(data->set.str[STRING_USERAGENT]) {
+ Curl_safefree(data->state.aptr.uagent);
+ data->state.aptr.uagent =
+ aprintf("User-Agent: %s\r\n", data->set.str[STRING_USERAGENT]);
+ if(!data->state.aptr.uagent)
+ return CURLE_OUT_OF_MEMORY;
}
+ data->req.headerbytecount = 0;
return result;
}
@@ -1573,6 +1549,8 @@ CURLcode Curl_follow(struct Curl_easy *data,
bool reachedmax = FALSE;
CURLUcode uc;
+ DEBUGASSERT(type != FOLLOW_NONE);
+
if(type == FOLLOW_REDIR) {
if((data->set.maxredirs != -1) &&
(data->set.followlocation >= data->set.maxredirs)) {
@@ -1604,8 +1582,11 @@ CURLcode Curl_follow(struct Curl_easy *data,
}
}
- if(Curl_is_absolute_url(newurl, NULL, MAX_SCHEME_LEN))
- /* This is an absolute URL, don't allow the custom port number */
+ if((type != FOLLOW_RETRY) &&
+ (data->req.httpcode != 401) && (data->req.httpcode != 407) &&
+ Curl_is_absolute_url(newurl, NULL, MAX_SCHEME_LEN))
+ /* If this is not redirect due to a 401 or 407 response and an absolute
+ URL: don't allow a custom port number */
disallowport = TRUE;
DEBUGASSERT(data->state.uh);
@@ -1686,7 +1667,7 @@ CURLcode Curl_follow(struct Curl_easy *data,
* request with an error page. To be sure that libcurl gets the page that
* most user agents would get, libcurl has to force GET.
*
- * This behaviour is forbidden by RFC1945 and the obsolete RFC2616, and
+ * This behavior is forbidden by RFC1945 and the obsolete RFC2616, and
* can be overridden with CURLOPT_POSTREDIR.
*/
if((data->state.httpreq == HTTPREQ_POST
@@ -1711,7 +1692,7 @@ CURLcode Curl_follow(struct Curl_easy *data,
* request with an error page. To be sure that libcurl gets the page that
* most user agents would get, libcurl has to force GET.
*
- * This behaviour is forbidden by RFC1945 and the obsolete RFC2616, and
+ * This behavior is forbidden by RFC1945 and the obsolete RFC2616, and
* can be overridden with CURLOPT_POSTREDIR.
*/
if((data->state.httpreq == HTTPREQ_POST
@@ -1765,10 +1746,9 @@ CURLcode Curl_follow(struct Curl_easy *data,
/* Returns CURLE_OK *and* sets '*url' if a request retry is wanted.
NOTE: that the *url is malloc()ed. */
-CURLcode Curl_retry_request(struct connectdata *conn,
- char **url)
+CURLcode Curl_retry_request(struct Curl_easy *data, char **url)
{
- struct Curl_easy *data = conn->data;
+ struct connectdata *conn = data->conn;
bool retry = FALSE;
*url = NULL;
@@ -1798,7 +1778,7 @@ CURLcode Curl_retry_request(struct connectdata *conn,
to issue again, but the nghttp2 API can deliver the message to other
streams as well, which is why this adds the check the data counters
too. */
- infof(conn->data, "REFUSED_STREAM, retrying a fresh connect\n");
+ infof(data, "REFUSED_STREAM, retrying a fresh connect\n");
data->state.refused_stream = FALSE; /* clear again */
retry = TRUE;
}
@@ -1810,9 +1790,9 @@ CURLcode Curl_retry_request(struct connectdata *conn,
data->state.retrycount = 0;
return CURLE_SEND_ERROR;
}
- infof(conn->data, "Connection died, retrying a fresh connect\
+ infof(data, "Connection died, retrying a fresh connect\
(retry count: %d)\n", data->state.retrycount);
- *url = strdup(conn->data->change.url);
+ *url = strdup(data->change.url);
if(!*url)
return CURLE_OUT_OF_MEMORY;
@@ -1826,7 +1806,7 @@ CURLcode Curl_retry_request(struct connectdata *conn,
if(conn->handler->protocol&PROTO_FAMILY_HTTP) {
if(data->req.writebytecount) {
- CURLcode result = Curl_readrewind(conn);
+ CURLcode result = Curl_readrewind(data);
if(result) {
Curl_safefree(*url);
return result;
@@ -1853,7 +1833,7 @@ Curl_setup_transfer(
{
struct SingleRequest *k = &data->req;
struct connectdata *conn = data->conn;
- struct HTTP *http = data->req.protop;
+ struct HTTP *http = data->req.p.http;
bool httpsending = ((conn->handler->protocol&PROTO_FAMILY_HTTP) &&
(http->sending == HTTPSEND_REQUEST));
DEBUGASSERT(conn != NULL);
diff --git a/Utilities/cmcurl/lib/transfer.h b/Utilities/cmcurl/lib/transfer.h
index 67fd91f25..0fa3d55e8 100644
--- a/Utilities/cmcurl/lib/transfer.h
+++ b/Utilities/cmcurl/lib/transfer.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -23,7 +23,7 @@
***************************************************************************/
#define Curl_headersep(x) ((((x)==':') || ((x)==';')))
-char *Curl_checkheaders(const struct connectdata *conn,
+char *Curl_checkheaders(const struct Curl_easy *data,
const char *thisheader);
void Curl_init_CONNECT(struct Curl_easy *data);
@@ -36,9 +36,8 @@ typedef enum {
allow initing to this */
FOLLOW_FAKE, /* only records stuff, not actually following */
FOLLOW_RETRY, /* set if this is a request retry as opposed to a real
- redirect following */
- FOLLOW_REDIR, /* a full true redirect */
- FOLLOW_LAST /* never used */
+ redirect following */
+ FOLLOW_REDIR /* a full true redirect */
} followtype;
CURLcode Curl_follow(struct Curl_easy *data, char *newurl,
@@ -46,16 +45,16 @@ CURLcode Curl_follow(struct Curl_easy *data, char *newurl,
CURLcode Curl_readwrite(struct connectdata *conn,
struct Curl_easy *data, bool *done,
bool *comeback);
-int Curl_single_getsock(const struct connectdata *conn,
- curl_socket_t *socks);
-CURLcode Curl_readrewind(struct connectdata *conn);
-CURLcode Curl_fillreadbuffer(struct connectdata *conn, size_t bytes,
+int Curl_single_getsock(struct Curl_easy *data,
+ struct connectdata *conn, curl_socket_t *socks);
+CURLcode Curl_readrewind(struct Curl_easy *data);
+CURLcode Curl_fillreadbuffer(struct Curl_easy *data, size_t bytes,
size_t *nreadp);
-CURLcode Curl_retry_request(struct connectdata *conn, char **url);
+CURLcode Curl_retry_request(struct Curl_easy *data, char **url);
bool Curl_meets_timecondition(struct Curl_easy *data, time_t timeofdoc);
CURLcode Curl_get_upload_buffer(struct Curl_easy *data);
-CURLcode Curl_done_sending(struct connectdata *conn,
+CURLcode Curl_done_sending(struct Curl_easy *data,
struct SingleRequest *k);
/* This sets up a forthcoming transfer */
diff --git a/Utilities/cmcurl/lib/url.c b/Utilities/cmcurl/lib/url.c
index 150667aa9..c02d2c201 100644
--- a/Utilities/cmcurl/lib/url.c
+++ b/Utilities/cmcurl/lib/url.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -96,6 +96,7 @@ bool curl_win32_idn_to_ascii(const char *in, char **out);
#include "getinfo.h"
#include "urlapi-int.h"
#include "system_win32.h"
+#include "hsts.h"
/* And now for the protocols */
#include "ftp.h"
@@ -130,7 +131,6 @@ bool curl_win32_idn_to_ascii(const char *in, char **out);
#include "memdebug.h"
static void conn_free(struct connectdata *conn);
-static unsigned int get_protocol_family(unsigned int protocol);
/* Some parts of the code (e.g. chunked encoding) assume this buffer has at
* more than just a few bytes to play with. Don't let it become too small or
@@ -140,6 +140,24 @@ static unsigned int get_protocol_family(unsigned int protocol);
# error READBUFFER_SIZE is too small
#endif
+/*
+* get_protocol_family()
+*
+* This is used to return the protocol family for a given protocol.
+*
+* Parameters:
+*
+* 'h' [in] - struct Curl_handler pointer.
+*
+* Returns the family as a single bit protocol identifier.
+*/
+static unsigned int get_protocol_family(const struct Curl_handler *h)
+{
+ DEBUGASSERT(h);
+ DEBUGASSERT(h->family);
+ return h->family;
+}
+
/*
* Protocol table. Schemes (roughly) in 2019 popularity order:
@@ -215,9 +233,8 @@ static const struct Curl_handler * const protocols[] = {
#endif
#endif
-#if !defined(CURL_DISABLE_SMB) && defined(USE_NTLM) && \
- (CURL_SIZEOF_CURL_OFF_T > 4) && \
- (!defined(USE_WINDOWS_SSPI) || defined(USE_WIN32_CRYPTO))
+#if !defined(CURL_DISABLE_SMB) && defined(USE_CURL_NTLM_CORE) && \
+ (CURL_SIZEOF_CURL_OFF_T > 4)
&Curl_handler_smb,
#ifdef USE_SSL
&Curl_handler_smbs,
@@ -228,12 +245,15 @@ static const struct Curl_handler * const protocols[] = {
&Curl_handler_rtsp,
#endif
-#ifdef CURL_ENABLE_MQTT
+#ifndef CURL_DISABLE_MQTT
&Curl_handler_mqtt,
#endif
#ifndef CURL_DISABLE_GOPHER
&Curl_handler_gopher,
+#ifdef USE_SSL
+ &Curl_handler_gophers,
+#endif
#endif
#ifdef USE_LIBRTMP
@@ -274,6 +294,7 @@ static const struct Curl_handler Curl_handler_dummy = {
ZERO_NULL, /* connection_check */
0, /* defport */
0, /* protocol */
+ 0, /* family */
PROTOPT_NONE /* flags */
};
@@ -343,6 +364,9 @@ CURLcode Curl_close(struct Curl_easy **datap)
Curl_expire_clear(data); /* shut off timers */
+ /* Detach connection if any is left. This should not be normal, but can be
+ the case for example with CONNECT_ONLY + recv/send (test 556) */
+ Curl_detach_connnection(data);
m = data->multi;
if(m)
/* This handle is still part of a multi handle, take care of this first
@@ -392,11 +416,10 @@ CURLcode Curl_close(struct Curl_easy **datap)
Curl_dyn_free(&data->state.headerb);
Curl_safefree(data->state.ulbuf);
Curl_flush_cookies(data, TRUE);
-#ifdef USE_ALTSVC
Curl_altsvc_save(data, data->asi, data->set.str[STRING_ALTSVC]);
- Curl_altsvc_cleanup(data->asi);
- data->asi = NULL;
-#endif
+ Curl_altsvc_cleanup(&data->asi);
+ Curl_hsts_save(data, data->hsts, data->set.str[STRING_HSTS]);
+ Curl_hsts_cleanup(&data->hsts);
#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_CRYPTO_AUTH)
Curl_http_auth_cleanup_digest(data);
#endif
@@ -404,7 +427,7 @@ CURLcode Curl_close(struct Curl_easy **datap)
Curl_safefree(data->info.wouldredirect);
/* this destroys the channel and we cannot use it anymore after this */
- Curl_resolver_cleanup(data->state.resolver);
+ Curl_resolver_cleanup(data->state.async.resolver);
Curl_http2_cleanup_dependencies(data);
Curl_convert_close(data);
@@ -428,9 +451,12 @@ CURLcode Curl_close(struct Curl_easy **datap)
Curl_safefree(data->state.aptr.rtsp_transport);
#ifndef CURL_DISABLE_DOH
- Curl_dyn_free(&data->req.doh.probe[0].serverdoh);
- Curl_dyn_free(&data->req.doh.probe[1].serverdoh);
- curl_slist_free_all(data->req.doh.headers);
+ if(data->req.doh) {
+ Curl_dyn_free(&data->req.doh->probe[0].serverdoh);
+ Curl_dyn_free(&data->req.doh->probe[1].serverdoh);
+ curl_slist_free_all(data->req.doh->headers);
+ Curl_safefree(data->req.doh);
+ }
#endif
/* destruct wildcard structures if it is needed */
@@ -480,6 +506,7 @@ CURLcode Curl_init_userdefined(struct Curl_easy *data)
set->ftp_use_eprt = TRUE; /* FTP defaults to EPRT operations */
set->ftp_use_pret = FALSE; /* mainly useful for drftpd servers */
set->ftp_filemethod = FTPFILE_MULTICWD;
+ set->ftp_skip_ip = TRUE; /* skip PASV IP by default */
#endif
set->dns_cache_timeout = 60; /* Timeout every 60 seconds by default */
@@ -616,7 +643,7 @@ CURLcode Curl_open(struct Curl_easy **curl)
data->magic = CURLEASY_MAGIC_NUMBER;
- result = Curl_resolver_init(data, &data->state.resolver);
+ result = Curl_resolver_init(data, &data->state.async.resolver);
if(result) {
DEBUGF(fprintf(stderr, "Error: resolver_init failed\n"));
free(data);
@@ -637,7 +664,7 @@ CURLcode Curl_open(struct Curl_easy **curl)
}
if(result) {
- Curl_resolver_cleanup(data->state.resolver);
+ Curl_resolver_cleanup(data->state.async.resolver);
Curl_dyn_free(&data->state.headerb);
Curl_freeset(data);
free(data);
@@ -688,29 +715,29 @@ static void conn_reset_all_postponed_data(struct connectdata *conn)
#endif /* ! USE_RECV_BEFORE_SEND_WORKAROUND */
-static void conn_shutdown(struct connectdata *conn)
+static void conn_shutdown(struct Curl_easy *data, struct connectdata *conn)
{
DEBUGASSERT(conn);
- infof(conn->data, "Closing connection %ld\n", conn->connection_id);
- DEBUGASSERT(conn->data);
+ DEBUGASSERT(data);
+ infof(data, "Closing connection %ld\n", conn->connection_id);
/* possible left-overs from the async name resolvers */
- Curl_resolver_cancel(conn);
+ Curl_resolver_cancel(data);
/* close the SSL stuff before we close any sockets since they will/may
write to the sockets */
- Curl_ssl_close(conn, FIRSTSOCKET);
- Curl_ssl_close(conn, SECONDARYSOCKET);
+ Curl_ssl_close(data, conn, FIRSTSOCKET);
+ Curl_ssl_close(data, conn, SECONDARYSOCKET);
/* close possibly still open sockets */
if(CURL_SOCKET_BAD != conn->sock[SECONDARYSOCKET])
- Curl_closesocket(conn, conn->sock[SECONDARYSOCKET]);
+ Curl_closesocket(data, conn, conn->sock[SECONDARYSOCKET]);
if(CURL_SOCKET_BAD != conn->sock[FIRSTSOCKET])
- Curl_closesocket(conn, conn->sock[FIRSTSOCKET]);
+ Curl_closesocket(data, conn, conn->sock[FIRSTSOCKET]);
if(CURL_SOCKET_BAD != conn->tempsock[0])
- Curl_closesocket(conn, conn->tempsock[0]);
+ Curl_closesocket(data, conn, conn->tempsock[0]);
if(CURL_SOCKET_BAD != conn->tempsock[1])
- Curl_closesocket(conn, conn->tempsock[1]);
+ Curl_closesocket(data, conn, conn->tempsock[1]);
}
static void conn_free(struct connectdata *conn)
@@ -805,19 +832,23 @@ CURLcode Curl_disconnect(struct Curl_easy *data,
/* Cleanup NEGOTIATE connection-related data */
Curl_http_auth_cleanup_negotiate(conn);
- /* the protocol specific disconnect handler and conn_shutdown need a transfer
- for the connection! */
- conn->data = data;
-
if(conn->bits.connect_only)
/* treat the connection as dead in CONNECT_ONLY situations */
dead_connection = TRUE;
+ /* temporarily attach the connection to this transfer handle for the
+ disonnect and shutdown */
+ Curl_attach_connnection(data, conn);
+
if(conn->handler->disconnect)
/* This is set if protocol-specific cleanups should be made */
- conn->handler->disconnect(conn, dead_connection);
+ conn->handler->disconnect(data, conn, dead_connection);
+
+ conn_shutdown(data, conn);
+
+ /* detach it again */
+ Curl_detach_connnection(data);
- conn_shutdown(conn);
conn_free(conn);
return CURLE_OK;
}
@@ -915,15 +946,13 @@ static bool conn_maxage(struct Curl_easy *data,
struct connectdata *conn,
struct curltime now)
{
- if(!conn->data) {
- timediff_t idletime = Curl_timediff(now, conn->lastused);
- idletime /= 1000; /* integer seconds is fine */
+ timediff_t idletime = Curl_timediff(now, conn->lastused);
+ idletime /= 1000; /* integer seconds is fine */
- if(idletime > data->set.maxage_conn) {
- infof(data, "Too old connection (%ld seconds), disconnect it\n",
- idletime);
- return TRUE;
- }
+ if(idletime > data->set.maxage_conn) {
+ infof(data, "Too old connection (%ld seconds), disconnect it\n",
+ idletime);
+ return TRUE;
}
return FALSE;
}
@@ -940,23 +969,29 @@ static bool conn_maxage(struct Curl_easy *data,
static bool extract_if_dead(struct connectdata *conn,
struct Curl_easy *data)
{
- if(!CONN_INUSE(conn) && !conn->data) {
+ if(!CONN_INUSE(conn)) {
/* The check for a dead socket makes sense only if the connection isn't in
use */
bool dead;
struct curltime now = Curl_now();
if(conn_maxage(data, conn, now)) {
+ /* avoid check if already too old */
dead = TRUE;
}
else if(conn->handler->connection_check) {
/* The protocol has a special method for checking the state of the
connection. Use it to check if the connection is dead. */
unsigned int state;
- struct Curl_easy *olddata = conn->data;
- conn->data = data; /* use this transfer for now */
- state = conn->handler->connection_check(conn, CONNCHECK_ISDEAD);
- conn->data = olddata;
+
+ /* briefly attach the connection to this transfer for the purpose of
+ checking it */
+ Curl_attach_connnection(data, conn);
+ conn->data = data; /* find the way back if necessary */
+ state = conn->handler->connection_check(data, conn, CONNCHECK_ISDEAD);
dead = (state & CONNRESULT_DEAD);
+ /* detach the connection again */
+ Curl_detach_connnection(data);
+ conn->data = NULL; /* clear it again */
}
else {
/* Use the general method for determining the death of a connection */
@@ -981,10 +1016,11 @@ struct prunedead {
* Wrapper to use extract_if_dead() function in Curl_conncache_foreach()
*
*/
-static int call_extract_if_dead(struct connectdata *conn, void *param)
+static int call_extract_if_dead(struct Curl_easy *data,
+ struct connectdata *conn, void *param)
{
struct prunedead *p = (struct prunedead *)param;
- if(extract_if_dead(conn, p->data)) {
+ if(extract_if_dead(conn, data)) {
/* stop the iteration here, pass back the connection that was extracted */
p->extracted = conn;
return 1;
@@ -994,14 +1030,16 @@ static int call_extract_if_dead(struct connectdata *conn, void *param)
/*
* This function scans the connection cache for half-open/dead connections,
- * closes and removes them.
- * The cleanup is done at most once per second.
+ * closes and removes them. The cleanup is done at most once per second.
+ *
+ * When called, this transfer has no connection attached.
*/
static void prune_dead_connections(struct Curl_easy *data)
{
struct curltime now = Curl_now();
timediff_t elapsed;
+ DEBUGASSERT(!data->conn); /* no connection */
CONNCACHE_LOCK(data);
elapsed =
Curl_timediff(now, data->state.conn_cache->last_cleanup);
@@ -1019,7 +1057,7 @@ static void prune_dead_connections(struct Curl_easy *data)
Curl_conncache_remove_conn(data, prune.extracted, TRUE);
/* disconnect it */
- (void)Curl_disconnect(data, prune.extracted, /* dead_connection */TRUE);
+ (void)Curl_disconnect(data, prune.extracted, TRUE);
}
CONNCACHE_LOCK(data);
data->state.conn_cache->last_cleanup = now;
@@ -1071,11 +1109,11 @@ ConnectionExists(struct Curl_easy *data,
/* Look up the bundle with all the connections to this particular host.
Locks the connection cache, beware of early returns! */
- bundle = Curl_conncache_find_bundle(needle, data->state.conn_cache,
+ bundle = Curl_conncache_find_bundle(data, needle, data->state.conn_cache,
&hostbundle);
if(bundle) {
/* Max pipe length is zero (unlimited) for multiplexed connections */
- struct curl_llist_element *curr;
+ struct Curl_llist_element *curr;
infof(data, "Found bundle for host %s: %p [%s]\n",
hostbundle, (void *)bundle, (bundle->multiuse == BUNDLE_MULTIPLEX ?
@@ -1121,13 +1159,16 @@ ConnectionExists(struct Curl_easy *data,
/* connect-only or to-be-closed connections will not be reused */
continue;
+ if(extract_if_dead(check, data)) {
+ /* disconnect it */
+ (void)Curl_disconnect(data, check, TRUE);
+ continue;
+ }
+
if(bundle->multiuse == BUNDLE_MULTIPLEX)
multiplexed = CONN_INUSE(check);
- if(canmultiplex) {
- ;
- }
- else {
+ if(!canmultiplex) {
if(multiplexed) {
/* can only happen within multi handles, and means that another easy
handle is using this connection */
@@ -1135,9 +1176,9 @@ ConnectionExists(struct Curl_easy *data,
}
if(Curl_resolver_asynch()) {
- /* ip_addr_str[0] is NUL only if the resolving of the name hasn't
+ /* primary_ip[0] is NUL only if the resolving of the name hasn't
completed yet and until then we don't re-use this connection */
- if(!check->ip_addr_str[0]) {
+ if(!check->primary_ip[0]) {
infof(data,
"Connection #%ld is still name resolving, can't reuse\n",
check->connection_id);
@@ -1171,7 +1212,7 @@ ConnectionExists(struct Curl_easy *data,
if((needle->handler->flags&PROTOPT_SSL) !=
(check->handler->flags&PROTOPT_SSL))
/* don't do mixed SSL and non-SSL connections */
- if(get_protocol_family(check->handler->protocol) !=
+ if(get_protocol_family(check->handler) !=
needle->handler->protocol || !check->bits.tls_upgraded)
/* except protocols that have been upgraded via TLS */
continue;
@@ -1276,7 +1317,7 @@ ConnectionExists(struct Curl_easy *data,
is allowed to be upgraded via TLS */
if((strcasecompare(needle->handler->scheme, check->handler->scheme) ||
- (get_protocol_family(check->handler->protocol) ==
+ (get_protocol_family(check->handler) ==
needle->handler->protocol && check->bits.tls_upgraded)) &&
(!needle->bits.conn_to_host || strcasecompare(
needle->conn_to_host.name, check->conn_to_host.name)) &&
@@ -1439,17 +1480,18 @@ ConnectionExists(struct Curl_easy *data,
* verboseconnect() displays verbose information after a connect
*/
#ifndef CURL_DISABLE_VERBOSE_STRINGS
-void Curl_verboseconnect(struct connectdata *conn)
+void Curl_verboseconnect(struct Curl_easy *data,
+ struct connectdata *conn)
{
- if(conn->data->set.verbose)
- infof(conn->data, "Connected to %s (%s) port %ld (#%ld)\n",
+ if(data->set.verbose)
+ infof(data, "Connected to %s (%s) port %ld (#%ld)\n",
#ifndef CURL_DISABLE_PROXY
conn->bits.socksproxy ? conn->socks_proxy.host.dispname :
conn->bits.httpproxy ? conn->http_proxy.host.dispname :
#endif
conn->bits.conn_to_host ? conn->conn_to_host.dispname :
conn->host.dispname,
- conn->ip_addr_str, conn->port, conn->connection_id);
+ conn->primary_ip, conn->port, conn->connection_id);
}
#endif
@@ -1488,16 +1530,14 @@ static void strip_trailing_dot(struct hostname *host)
/*
* Perform any necessary IDN conversion of hostname
*/
-CURLcode Curl_idnconvert_hostname(struct connectdata *conn,
+CURLcode Curl_idnconvert_hostname(struct Curl_easy *data,
struct hostname *host)
{
- struct Curl_easy *data = conn->data;
-
#ifndef USE_LIBIDN2
(void)data;
- (void)conn;
+ (void)data;
#elif defined(CURL_DISABLE_VERBOSE_STRINGS)
- (void)conn;
+ (void)data;
#endif
/* set the name we use to display the host name */
@@ -1517,13 +1557,18 @@ CURLcode Curl_idnconvert_hostname(struct connectdata *conn,
int flags = IDN2_NFC_INPUT;
#endif
int rc = idn2_lookup_ul((const char *)host->name, &ace_hostname, flags);
+ if(rc != IDN2_OK)
+ /* fallback to TR46 Transitional mode for better IDNA2003
+ compatibility */
+ rc = idn2_lookup_ul((const char *)host->name, &ace_hostname,
+ IDN2_TRANSITIONAL);
if(rc == IDN2_OK) {
host->encalloc = (char *)ace_hostname;
/* change the name pointer to point to the encoded hostname */
host->name = host->encalloc;
}
else {
- failf(data, "Failed to convert %s to ACE; %s\n", host->name,
+ failf(data, "Failed to convert %s to ACE; %s", host->name,
idn2_strerror(rc));
return CURLE_URL_MALFORMAT;
}
@@ -1538,7 +1583,7 @@ CURLcode Curl_idnconvert_hostname(struct connectdata *conn,
}
else {
char buffer[STRERROR_LEN];
- failf(data, "Failed to convert %s to ACE; %s\n", host->name,
+ failf(data, "Failed to convert %s to ACE; %s", host->name,
Curl_winapi_strerror(GetLastError(), buffer, sizeof(buffer)));
return CURLE_URL_MALFORMAT;
}
@@ -1629,9 +1674,6 @@ static struct connectdata *allocate_conn(struct Curl_easy *data)
/* Store current time to give a baseline to keepalive connection times. */
conn->keepalive = Curl_now();
- /* Store off the configured connection upkeep time. */
- conn->upkeep_interval_ms = data->set.upkeep_interval_ms;
-
conn->data = data; /* Setup the association between this connection
and the Curl_easy */
@@ -1787,12 +1829,14 @@ CURLcode Curl_uc_to_curlcode(CURLUcode uc)
* the scope_id based on that!
*/
-static void zonefrom_url(CURLU *uh, struct connectdata *conn)
+static void zonefrom_url(CURLU *uh, struct Curl_easy *data,
+ struct connectdata *conn)
{
char *zoneid;
- CURLUcode uc;
-
- uc = curl_url_get(uh, CURLUPART_ZONEID, &zoneid, 0);
+ CURLUcode uc = curl_url_get(uh, CURLUPART_ZONEID, &zoneid, 0);
+#ifdef CURL_DISABLE_VERBOSE_STRINGS
+ (void)data;
+#endif
if(!uc && zoneid) {
char *endp;
@@ -1815,7 +1859,7 @@ static void zonefrom_url(CURLU *uh, struct connectdata *conn)
scopeidx = if_nametoindex(zoneid);
#endif
if(!scopeidx)
- infof(conn->data, "Invalid zoneid: %s; %s\n", zoneid,
+ infof(data, "Invalid zoneid: %s; %s\n", zoneid,
strerror(errno));
else
conn->scope_id = scopeidx;
@@ -1891,6 +1935,37 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data,
if(uc)
return Curl_uc_to_curlcode(uc);
+ uc = curl_url_get(uh, CURLUPART_HOST, &data->state.up.hostname, 0);
+ if(uc) {
+ if(!strcasecompare("file", data->state.up.scheme))
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+#ifdef USE_HSTS
+ if(data->hsts && strcasecompare("http", data->state.up.scheme)) {
+ if(Curl_hsts(data->hsts, data->state.up.hostname, TRUE)) {
+ char *url;
+ Curl_safefree(data->state.up.scheme);
+ uc = curl_url_set(uh, CURLUPART_SCHEME, "https", 0);
+ if(uc)
+ return Curl_uc_to_curlcode(uc);
+ if(data->change.url_alloc)
+ Curl_safefree(data->change.url);
+ /* after update, get the updated version */
+ uc = curl_url_get(uh, CURLUPART_URL, &url, 0);
+ if(uc)
+ return Curl_uc_to_curlcode(uc);
+ uc = curl_url_get(uh, CURLUPART_SCHEME, &data->state.up.scheme, 0);
+ if(uc)
+ return Curl_uc_to_curlcode(uc);
+ data->change.url = url;
+ data->change.url_alloc = TRUE;
+ infof(data, "Switched from HTTP to HTTPS due to HSTS => %s\n",
+ data->change.url);
+ }
+ }
+#endif
+
result = findprotocol(data, conn, data->state.up.scheme);
if(result)
return result;
@@ -1936,12 +2011,6 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data,
else if(uc != CURLUE_NO_OPTIONS)
return Curl_uc_to_curlcode(uc);
- uc = curl_url_get(uh, CURLUPART_HOST, &data->state.up.hostname, 0);
- if(uc) {
- if(!strcasecompare("file", data->state.up.scheme))
- return CURLE_OUT_OF_MEMORY;
- }
-
uc = curl_url_get(uh, CURLUPART_PATH, &data->state.up.path, 0);
if(uc)
return Curl_uc_to_curlcode(uc);
@@ -1954,7 +2023,9 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data,
}
else {
unsigned long port = strtoul(data->state.up.port, NULL, 10);
- conn->port = conn->remote_port = curlx_ultous(port);
+ conn->port = conn->remote_port =
+ (data->set.use_port && data->state.allow_port) ?
+ (int)data->set.use_port : curlx_ultous(port);
}
(void)curl_url_get(uh, CURLUPART_QUERY, &data->state.up.query, 0);
@@ -1970,7 +2041,7 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data,
hlen = strlen(hostname);
hostname[hlen - 1] = 0;
- zonefrom_url(uh, conn);
+ zonefrom_url(uh, data, conn);
}
/* make sure the connect struct gets its own copy of the host name */
@@ -2028,7 +2099,8 @@ static CURLcode setup_range(struct Curl_easy *data)
*
* This MUST get called after proxy magic has been figured out.
*/
-static CURLcode setup_connection_internals(struct connectdata *conn)
+static CURLcode setup_connection_internals(struct Curl_easy *data,
+ struct connectdata *conn)
{
const struct Curl_handler *p;
CURLcode result;
@@ -2037,7 +2109,7 @@ static CURLcode setup_connection_internals(struct connectdata *conn)
p = conn->handler;
if(p->setup_connection) {
- result = (*p->setup_connection)(conn);
+ result = (*p->setup_connection)(data, conn);
if(result)
return result;
@@ -2060,12 +2132,14 @@ static CURLcode setup_connection_internals(struct connectdata *conn)
void Curl_free_request_state(struct Curl_easy *data)
{
- Curl_safefree(data->req.protop);
+ Curl_safefree(data->req.p.http);
Curl_safefree(data->req.newurl);
#ifndef CURL_DISABLE_DOH
- Curl_close(&data->req.doh.probe[0].easy);
- Curl_close(&data->req.doh.probe[1].easy);
+ if(data->req.doh) {
+ Curl_close(&data->req.doh->probe[0].easy);
+ Curl_close(&data->req.doh->probe[1].easy);
+ }
#endif
}
@@ -2122,7 +2196,7 @@ static bool check_noproxy(const char *name, const char *no_proxy)
/* Look for the end of the token. */
;
- /* To match previous behaviour, where it was necessary to specify
+ /* To match previous behavior, where it was necessary to specify
* ".local.com" to prevent matching "notlocal.com", we will leave
* the '.' off.
*/
@@ -2155,7 +2229,8 @@ static bool check_noproxy(const char *name, const char *no_proxy)
* name and is not limited to HTTP proxies only.
* The returned pointer must be freed by the caller (unless NULL)
****************************************************************/
-static char *detect_proxy(struct connectdata *conn)
+static char *detect_proxy(struct Curl_easy *data,
+ struct connectdata *conn)
{
char *proxy = NULL;
@@ -2180,6 +2255,9 @@ static char *detect_proxy(struct connectdata *conn)
const char *protop = conn->handler->scheme;
char *envp = proxy_env;
char *prox;
+#ifdef CURL_DISABLE_VERBOSE_STRINGS
+ (void)data;
+#endif
/* Now, build <protocol>_proxy and check for such a one to use */
while(*protop)
@@ -2222,7 +2300,7 @@ static char *detect_proxy(struct connectdata *conn)
}
}
if(proxy)
- infof(conn->data, "Uses proxy env variable %s == '%s'\n", envp, proxy);
+ infof(data, "Uses proxy env variable %s == '%s'\n", envp, proxy);
return proxy;
}
@@ -2238,7 +2316,7 @@ static CURLcode parse_proxy(struct Curl_easy *data,
curl_proxytype proxytype)
{
char *portptr = NULL;
- long port = -1;
+ int port = -1;
char *proxyuser = NULL;
char *proxypasswd = NULL;
char *host;
@@ -2327,14 +2405,14 @@ static CURLcode parse_proxy(struct Curl_easy *data,
curl_url_get(uhp, CURLUPART_PORT, &portptr, 0);
if(portptr) {
- port = strtol(portptr, NULL, 10);
+ port = (int)strtol(portptr, NULL, 10);
free(portptr);
}
else {
if(data->set.proxyport)
/* None given in the proxy string, then get the default one if it is
given */
- port = data->set.proxyport;
+ port = (int)data->set.proxyport;
else {
if(proxytype == CURLPROXY_HTTPS)
port = CURL_DEFAULT_HTTPS_PROXY_PORT;
@@ -2361,7 +2439,7 @@ static CURLcode parse_proxy(struct Curl_easy *data,
size_t len = strlen(host);
host[len-1] = 0; /* clear the trailing bracket */
host++;
- zonefrom_url(uhp, conn);
+ zonefrom_url(uhp, data, conn);
}
proxyinfo->host.name = host;
@@ -2377,8 +2455,10 @@ static CURLcode parse_proxy(struct Curl_easy *data,
static CURLcode parse_proxy_auth(struct Curl_easy *data,
struct connectdata *conn)
{
- char *proxyuser = data->set.str[STRING_PROXYUSERNAME];
- char *proxypasswd = data->set.str[STRING_PROXYPASSWORD];
+ const char *proxyuser = data->set.str[STRING_PROXYUSERNAME] ?
+ data->set.str[STRING_PROXYUSERNAME] : "";
+ const char *proxypasswd = data->set.str[STRING_PROXYPASSWORD] ?
+ data->set.str[STRING_PROXYPASSWORD] : "";
CURLcode result = CURLE_OK;
if(proxyuser)
@@ -2392,13 +2472,13 @@ static CURLcode parse_proxy_auth(struct Curl_easy *data,
/* create_conn helper to parse and init proxy values. to be called after unix
socket init but before any proxy vars are evaluated. */
-static CURLcode create_conn_helper_init_proxy(struct connectdata *conn)
+static CURLcode create_conn_helper_init_proxy(struct Curl_easy *data,
+ struct connectdata *conn)
{
char *proxy = NULL;
char *socksproxy = NULL;
char *no_proxy = NULL;
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
/*************************************************************
* Extract the user and password from the authentication string
@@ -2440,7 +2520,7 @@ static CURLcode create_conn_helper_init_proxy(struct connectdata *conn)
no_proxy = curl_getenv(p);
}
if(no_proxy) {
- infof(conn->data, "Uses proxy env variable %s == '%s'\n", p, no_proxy);
+ infof(data, "Uses proxy env variable %s == '%s'\n", p, no_proxy);
}
}
@@ -2452,7 +2532,7 @@ static CURLcode create_conn_helper_init_proxy(struct connectdata *conn)
#ifndef CURL_DISABLE_HTTP
else if(!proxy && !socksproxy)
/* if the host is not in the noproxy list, detect proxy. */
- proxy = detect_proxy(conn);
+ proxy = detect_proxy(data, conn);
#endif /* CURL_DISABLE_HTTP */
Curl_safefree(no_proxy);
@@ -2551,6 +2631,9 @@ static CURLcode create_conn_helper_init_proxy(struct connectdata *conn)
conn->bits.socksproxy = FALSE;
conn->bits.proxy_user_passwd = FALSE;
conn->bits.tunnel_proxy = FALSE;
+ /* CURLPROXY_HTTPS does not have its own flag in conn->bits, yet we need
+ to signal that CURLPROXY_HTTPS is not used for this connection */
+ conn->http_proxy.proxytype = CURLPROXY_HTTP;
}
out:
@@ -3070,7 +3153,7 @@ static CURLcode parse_connect_to_slist(struct Curl_easy *data,
conn_to_host = conn_to_host->next;
}
-#ifdef USE_ALTSVC
+#ifndef CURL_DISABLE_ALTSVC
if(data->asi && !host && (port == -1) &&
((conn->handler->protocol == CURLPROTO_HTTPS) ||
#ifdef CURLDEBUG
@@ -3223,7 +3306,7 @@ static CURLcode resolve_server(struct Curl_easy *data,
conn->hostname_resolve = strdup(connhost->name);
if(!conn->hostname_resolve)
return CURLE_OUT_OF_MEMORY;
- rc = Curl_resolv_timeout(conn, conn->hostname_resolve, (int)conn->port,
+ rc = Curl_resolv_timeout(data, conn->hostname_resolve, (int)conn->port,
&hostaddr, timeout_ms);
if(rc == CURLRESOLV_PENDING)
*async = TRUE;
@@ -3248,7 +3331,7 @@ static CURLcode resolve_server(struct Curl_easy *data,
conn->hostname_resolve = strdup(host->name);
if(!conn->hostname_resolve)
return CURLE_OUT_OF_MEMORY;
- rc = Curl_resolv_timeout(conn, conn->hostname_resolve, (int)conn->port,
+ rc = Curl_resolv_timeout(data, conn->hostname_resolve, (int)conn->port,
&hostaddr, timeout_ms);
if(rc == CURLRESOLV_PENDING)
@@ -3276,9 +3359,15 @@ static CURLcode resolve_server(struct Curl_easy *data,
* previously existing one. All relevant data is copied over and old_conn is
* ready for freeing once this function returns.
*/
-static void reuse_conn(struct connectdata *old_conn,
+static void reuse_conn(struct Curl_easy *data,
+ struct connectdata *old_conn,
struct connectdata *conn)
{
+ /* 'local_ip' and 'local_port' get filled with local's numerical
+ ip address and port number whenever an outgoing connection is
+ **established** from the primary socket to a remote address. */
+ char local_ip[MAX_IPADR_LEN] = "";
+ long local_port = -1;
#ifndef CURL_DISABLE_PROXY
Curl_free_idnconverted_hostname(&old_conn->http_proxy.host);
Curl_free_idnconverted_hostname(&old_conn->socks_proxy.host);
@@ -3291,7 +3380,7 @@ static void reuse_conn(struct connectdata *old_conn,
allocated in vain and is targeted for destruction */
Curl_free_primary_ssl_config(&old_conn->ssl_config);
- conn->data = old_conn->data;
+ conn->data = data;
/* get the user+password information from the old_conn struct since it may
* be new for this request even when we re-use an existing connection */
@@ -3345,7 +3434,11 @@ static void reuse_conn(struct connectdata *old_conn,
old_conn->hostname_resolve = NULL;
/* persist connection info in session handle */
- Curl_persistconninfo(conn);
+ if(conn->transport == TRNSPRT_TCP) {
+ Curl_conninfo_local(data, conn->sock[FIRSTSOCKET],
+ local_ip, &local_port);
+ }
+ Curl_persistconninfo(data, conn, local_ip, local_port);
conn_reset_all_postponed_data(old_conn); /* free buffers */
@@ -3446,7 +3539,7 @@ static CURLcode create_conn(struct Curl_easy *data,
/* After the unix socket init but before the proxy vars are used, parse and
initialize the proxy vars */
#ifndef CURL_DISABLE_PROXY
- result = create_conn_helper_init_proxy(conn);
+ result = create_conn_helper_init_proxy(data, conn);
if(result)
goto out;
@@ -3487,22 +3580,22 @@ static CURLcode create_conn(struct Curl_easy *data,
/*************************************************************
* IDN-convert the hostnames
*************************************************************/
- result = Curl_idnconvert_hostname(conn, &conn->host);
+ result = Curl_idnconvert_hostname(data, &conn->host);
if(result)
goto out;
if(conn->bits.conn_to_host) {
- result = Curl_idnconvert_hostname(conn, &conn->conn_to_host);
+ result = Curl_idnconvert_hostname(data, &conn->conn_to_host);
if(result)
goto out;
}
#ifndef CURL_DISABLE_PROXY
if(conn->bits.httpproxy) {
- result = Curl_idnconvert_hostname(conn, &conn->http_proxy.host);
+ result = Curl_idnconvert_hostname(data, &conn->http_proxy.host);
if(result)
goto out;
}
if(conn->bits.socksproxy) {
- result = Curl_idnconvert_hostname(conn, &conn->socks_proxy.host);
+ result = Curl_idnconvert_hostname(data, &conn->socks_proxy.host);
if(result)
goto out;
}
@@ -3539,7 +3632,7 @@ static CURLcode create_conn(struct Curl_easy *data,
* Setup internals depending on protocol. Needs to be done after
* we figured out what/if proxy to use.
*************************************************************/
- result = setup_connection_internals(conn);
+ result = setup_connection_internals(data, conn);
if(result)
goto out;
@@ -3559,15 +3652,15 @@ static CURLcode create_conn(struct Curl_easy *data,
/* this is supposed to be the connect function so we better at least check
that the file is present here! */
DEBUGASSERT(conn->handler->connect_it);
- Curl_persistconninfo(conn);
- result = conn->handler->connect_it(conn, &done);
+ Curl_persistconninfo(data, conn, NULL, -1);
+ result = conn->handler->connect_it(data, &done);
/* Setup a "faked" transfer that'll do nothing */
if(!result) {
conn->bits.tcpconnect[FIRSTSOCKET] = TRUE; /* we are "connected */
Curl_attach_connnection(data, conn);
- result = Curl_conncache_add_conn(data->state.conn_cache, conn);
+ result = Curl_conncache_add_conn(data);
if(result)
goto out;
@@ -3578,7 +3671,7 @@ static CURLcode create_conn(struct Curl_easy *data,
if(result) {
DEBUGASSERT(conn->handler->done);
/* we ignore the return code for the protocol-specific DONE */
- (void)conn->handler->done(conn, result, FALSE);
+ (void)conn->handler->done(data, result, FALSE);
goto out;
}
Curl_setup_transfer(data, -1, -1, FALSE, -1);
@@ -3611,6 +3704,7 @@ static CURLcode create_conn(struct Curl_easy *data,
data->set.ssl.primary.pinned_key =
data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG];
data->set.ssl.primary.cert_blob = data->set.blobs[BLOB_CERT_ORIG];
+ data->set.ssl.primary.curves = data->set.str[STRING_SSL_EC_CURVES];
#ifndef CURL_DISABLE_PROXY
data->set.proxy_ssl.primary.CApath = data->set.str[STRING_SSL_CAPATH_PROXY];
@@ -3627,18 +3721,15 @@ static CURLcode create_conn(struct Curl_easy *data,
data->set.proxy_ssl.primary.cert_blob = data->set.blobs[BLOB_CERT_PROXY];
data->set.proxy_ssl.CRLfile = data->set.str[STRING_SSL_CRLFILE_PROXY];
data->set.proxy_ssl.issuercert = data->set.str[STRING_SSL_ISSUERCERT_PROXY];
- data->set.proxy_ssl.cert = data->set.str[STRING_CERT_PROXY];
data->set.proxy_ssl.cert_type = data->set.str[STRING_CERT_TYPE_PROXY];
data->set.proxy_ssl.key = data->set.str[STRING_KEY_PROXY];
data->set.proxy_ssl.key_type = data->set.str[STRING_KEY_TYPE_PROXY];
data->set.proxy_ssl.key_passwd = data->set.str[STRING_KEY_PASSWD_PROXY];
data->set.proxy_ssl.primary.clientcert = data->set.str[STRING_CERT_PROXY];
- data->set.proxy_ssl.cert_blob = data->set.blobs[BLOB_CERT_PROXY];
data->set.proxy_ssl.key_blob = data->set.blobs[BLOB_KEY_PROXY];
#endif
data->set.ssl.CRLfile = data->set.str[STRING_SSL_CRLFILE_ORIG];
data->set.ssl.issuercert = data->set.str[STRING_SSL_ISSUERCERT_ORIG];
- data->set.ssl.cert = data->set.str[STRING_CERT_ORIG];
data->set.ssl.cert_type = data->set.str[STRING_CERT_TYPE_ORIG];
data->set.ssl.key = data->set.str[STRING_KEY_ORIG];
data->set.ssl.key_type = data->set.str[STRING_KEY_TYPE_ORIG];
@@ -3653,7 +3744,6 @@ static CURLcode create_conn(struct Curl_easy *data,
#endif
#endif
- data->set.ssl.cert_blob = data->set.blobs[BLOB_CERT_ORIG];
data->set.ssl.key_blob = data->set.blobs[BLOB_KEY_ORIG];
data->set.ssl.issuercert_blob = data->set.blobs[BLOB_SSL_ISSUERCERT_ORIG];
@@ -3694,12 +3784,11 @@ static CURLcode create_conn(struct Curl_easy *data,
if(reuse) {
/*
- * We already have a connection for this, we got the former connection
- * in the conn_temp variable and thus we need to cleanup the one we
- * just allocated before we can move along and use the previously
- * existing one.
+ * We already have a connection for this, we got the former connection in
+ * the conn_temp variable and thus we need to cleanup the one we just
+ * allocated before we can move along and use the previously existing one.
*/
- reuse_conn(conn, conn_temp);
+ reuse_conn(data, conn, conn_temp);
#ifdef USE_SSL
free(conn->ssl_extra);
#endif
@@ -3741,7 +3830,8 @@ static CURLcode create_conn(struct Curl_easy *data,
/* this gets a lock on the conncache */
const char *bundlehost;
struct connectbundle *bundle =
- Curl_conncache_find_bundle(conn, data->state.conn_cache, &bundlehost);
+ Curl_conncache_find_bundle(data, conn, data->state.conn_cache,
+ &bundlehost);
if(max_host_connections > 0 && bundle &&
(bundle->num_connections >= max_host_connections)) {
@@ -3752,8 +3842,7 @@ static CURLcode create_conn(struct Curl_easy *data,
CONNCACHE_UNLOCK(data);
if(conn_candidate)
- (void)Curl_disconnect(data, conn_candidate,
- /* dead_connection */ FALSE);
+ (void)Curl_disconnect(data, conn_candidate, FALSE);
else {
infof(data, "No more connections allowed to host %s: %zu\n",
bundlehost, max_host_connections);
@@ -3773,8 +3862,7 @@ static CURLcode create_conn(struct Curl_easy *data,
/* The cache is full. Let's see if we can kill a connection. */
conn_candidate = Curl_conncache_extract_oldest(data);
if(conn_candidate)
- (void)Curl_disconnect(data, conn_candidate,
- /* dead_connection */ FALSE);
+ (void)Curl_disconnect(data, conn_candidate, FALSE);
else {
infof(data, "No connections available in cache\n");
connections_available = FALSE;
@@ -3796,8 +3884,7 @@ static CURLcode create_conn(struct Curl_easy *data,
* cache of ours!
*/
Curl_attach_connnection(data, conn);
-
- result = Curl_conncache_add_conn(data->state.conn_cache, conn);
+ result = Curl_conncache_add_conn(data);
if(result)
goto out;
}
@@ -3869,11 +3956,11 @@ out:
* conn->data MUST already have been setup fine (in create_conn)
*/
-CURLcode Curl_setup_conn(struct connectdata *conn,
+CURLcode Curl_setup_conn(struct Curl_easy *data,
bool *protocol_done)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
+ struct connectdata *conn = data->conn;
Curl_pgrsTime(data, TIMER_NAMELOOKUP);
@@ -3891,20 +3978,6 @@ CURLcode Curl_setup_conn(struct connectdata *conn,
lingering set from a previous invoke */
conn->bits.proxy_connect_closed = FALSE;
#endif
- /*
- * Set user-agent. Used for HTTP, but since we can attempt to tunnel
- * basically anything through a http proxy we can't limit this based on
- * protocol.
- */
- if(data->set.str[STRING_USERAGENT]) {
- Curl_safefree(data->state.aptr.uagent);
- data->state.aptr.uagent =
- aprintf("User-Agent: %s\r\n", data->set.str[STRING_USERAGENT]);
- if(!data->state.aptr.uagent)
- return CURLE_OUT_OF_MEMORY;
- }
-
- data->req.headerbytecount = 0;
#ifdef CURL_DO_LINEEND_CONV
data->state.crlf_conversions = 0; /* reset CRLF conversion counter */
@@ -3916,7 +3989,7 @@ CURLcode Curl_setup_conn(struct connectdata *conn,
if(CURL_SOCKET_BAD == conn->sock[FIRSTSOCKET]) {
conn->bits.tcpconnect[FIRSTSOCKET] = FALSE;
- result = Curl_connecthost(conn, conn->dns_entry);
+ result = Curl_connecthost(data, conn, conn->dns_entry);
if(result)
return result;
}
@@ -3927,8 +4000,8 @@ CURLcode Curl_setup_conn(struct connectdata *conn,
Curl_pgrsTime(data, TIMER_APPCONNECT); /* we're connected already */
conn->bits.tcpconnect[FIRSTSOCKET] = TRUE;
*protocol_done = TRUE;
- Curl_updateconninfo(conn, conn->sock[FIRSTSOCKET]);
- Curl_verboseconnect(conn);
+ Curl_updateconninfo(data, conn, conn->sock[FIRSTSOCKET]);
+ Curl_verboseconnect(data, conn);
}
conn->now = Curl_now(); /* time this *after* the connect is done, we set
@@ -3961,7 +4034,7 @@ CURLcode Curl_connect(struct Curl_easy *data,
/* DNS resolution is done: that's 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(conn, protocol_done);
+ result = Curl_setup_conn(data, protocol_done);
}
}
@@ -4026,113 +4099,3 @@ CURLcode Curl_init_do(struct Curl_easy *data, struct connectdata *conn)
return CURLE_OK;
}
-
-/*
-* get_protocol_family()
-*
-* This is used to return the protocol family for a given protocol.
-*
-* Parameters:
-*
-* protocol [in] - A single bit protocol identifier such as HTTP or HTTPS.
-*
-* Returns the family as a single bit protocol identifier.
-*/
-
-static unsigned int get_protocol_family(unsigned int protocol)
-{
- unsigned int family;
-
- switch(protocol) {
- case CURLPROTO_HTTP:
- case CURLPROTO_HTTPS:
- family = CURLPROTO_HTTP;
- break;
-
- case CURLPROTO_FTP:
- case CURLPROTO_FTPS:
- family = CURLPROTO_FTP;
- break;
-
- case CURLPROTO_SCP:
- family = CURLPROTO_SCP;
- break;
-
- case CURLPROTO_SFTP:
- family = CURLPROTO_SFTP;
- break;
-
- case CURLPROTO_TELNET:
- family = CURLPROTO_TELNET;
- break;
-
- case CURLPROTO_LDAP:
- case CURLPROTO_LDAPS:
- family = CURLPROTO_LDAP;
- break;
-
- case CURLPROTO_DICT:
- family = CURLPROTO_DICT;
- break;
-
- case CURLPROTO_FILE:
- family = CURLPROTO_FILE;
- break;
-
- case CURLPROTO_TFTP:
- family = CURLPROTO_TFTP;
- break;
-
- case CURLPROTO_IMAP:
- case CURLPROTO_IMAPS:
- family = CURLPROTO_IMAP;
- break;
-
- case CURLPROTO_POP3:
- case CURLPROTO_POP3S:
- family = CURLPROTO_POP3;
- break;
-
- case CURLPROTO_SMTP:
- case CURLPROTO_SMTPS:
- family = CURLPROTO_SMTP;
- break;
-
- case CURLPROTO_RTSP:
- family = CURLPROTO_RTSP;
- break;
-
- case CURLPROTO_RTMP:
- case CURLPROTO_RTMPS:
- family = CURLPROTO_RTMP;
- break;
-
- case CURLPROTO_RTMPT:
- case CURLPROTO_RTMPTS:
- family = CURLPROTO_RTMPT;
- break;
-
- case CURLPROTO_RTMPE:
- family = CURLPROTO_RTMPE;
- break;
-
- case CURLPROTO_RTMPTE:
- family = CURLPROTO_RTMPTE;
- break;
-
- case CURLPROTO_GOPHER:
- family = CURLPROTO_GOPHER;
- break;
-
- case CURLPROTO_SMB:
- case CURLPROTO_SMBS:
- family = CURLPROTO_SMB;
- break;
-
- default:
- family = 0;
- break;
- }
-
- return family;
-}
diff --git a/Utilities/cmcurl/lib/url.h b/Utilities/cmcurl/lib/url.h
index 1941dc6a4..929fc60f2 100644
--- a/Utilities/cmcurl/lib/url.h
+++ b/Utilities/cmcurl/lib/url.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -23,22 +23,6 @@
***************************************************************************/
#include "curl_setup.h"
-#define READBUFFER_SIZE CURL_MAX_WRITE_SIZE
-#define READBUFFER_MAX CURL_MAX_READ_SIZE
-#define READBUFFER_MIN 1024
-
-/* The default upload buffer size, should not be smaller than
- CURL_MAX_WRITE_SIZE, as it needs to hold a full buffer as could be sent in
- a write callback.
-
- The size was 16KB for many years but was bumped to 64KB because it makes
- libcurl able to do significantly faster uploads in some circumstances. Even
- larger buffers can help further, but this is deemed a fair memory/speed
- compromise. */
-#define UPLOADBUFFER_DEFAULT 65536
-#define UPLOADBUFFER_MAX (2*1024*1024)
-#define UPLOADBUFFER_MIN CURL_MAX_WRITE_SIZE
-
/*
* Prototypes for library-wide functions provided by url.c
*/
@@ -53,7 +37,7 @@ CURLcode Curl_close(struct Curl_easy **datap); /* opposite of curl_open() */
CURLcode Curl_connect(struct Curl_easy *, bool *async, bool *protocol_connect);
CURLcode Curl_disconnect(struct Curl_easy *data,
struct connectdata *, bool dead_connection);
-CURLcode Curl_setup_conn(struct connectdata *conn,
+CURLcode Curl_setup_conn(struct Curl_easy *data,
bool *protocol_done);
void Curl_free_request_state(struct Curl_easy *data);
CURLcode Curl_parse_login_details(const char *login, const size_t len,
@@ -63,7 +47,7 @@ CURLcode Curl_parse_login_details(const char *login, const size_t len,
const struct Curl_handler *Curl_builtin_scheme(const char *scheme);
bool Curl_is_ASCII_name(const char *hostname);
-CURLcode Curl_idnconvert_hostname(struct connectdata *conn,
+CURLcode Curl_idnconvert_hostname(struct Curl_easy *data,
struct hostname *host);
void Curl_free_idnconverted_hostname(struct hostname *host);
@@ -72,9 +56,9 @@ void Curl_free_idnconverted_hostname(struct hostname *host);
specified */
#ifdef CURL_DISABLE_VERBOSE_STRINGS
-#define Curl_verboseconnect(x) Curl_nop_stmt
+#define Curl_verboseconnect(x,y) Curl_nop_stmt
#else
-void Curl_verboseconnect(struct connectdata *conn);
+void Curl_verboseconnect(struct Curl_easy *data, struct connectdata *conn);
#endif
#ifdef CURL_DISABLE_PROXY
diff --git a/Utilities/cmcurl/lib/urlapi-int.h b/Utilities/cmcurl/lib/urlapi-int.h
index d14d53d97..425723309 100644
--- a/Utilities/cmcurl/lib/urlapi-int.h
+++ b/Utilities/cmcurl/lib/urlapi-int.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
@@ -28,7 +28,7 @@
bool Curl_is_absolute_url(const char *url, char *scheme, size_t buflen);
#ifdef DEBUGBUILD
-CURLUcode Curl_parse_port(struct Curl_URL *u, char *hostname);
+CURLUcode Curl_parse_port(struct Curl_URL *u, char *hostname, bool);
#endif
#endif /* HEADER_CURL_URLAPI_INT_H */
diff --git a/Utilities/cmcurl/lib/urlapi.c b/Utilities/cmcurl/lib/urlapi.c
index acbfb8287..e3a788221 100644
--- a/Utilities/cmcurl/lib/urlapi.c
+++ b/Utilities/cmcurl/lib/urlapi.c
@@ -9,7 +9,7 @@
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -497,7 +497,8 @@ static CURLUcode parse_hostname_login(struct Curl_URL *u,
return result;
}
-UNITTEST CURLUcode Curl_parse_port(struct Curl_URL *u, char *hostname)
+UNITTEST CURLUcode Curl_parse_port(struct Curl_URL *u, char *hostname,
+ bool has_scheme)
{
char *portptr = NULL;
char endbracket;
@@ -542,10 +543,14 @@ UNITTEST CURLUcode Curl_parse_port(struct Curl_URL *u, char *hostname)
/* Browser behavior adaptation. If there's a colon with no digits after,
just cut off the name there which makes us ignore the colon and just
- use the default port. Firefox, Chrome and Safari all do that. */
+ use the default port. Firefox, Chrome and Safari all do that.
+
+ Don't do it if the URL has no scheme, to make something that looks like
+ a scheme not work!
+ */
if(!portptr[1]) {
*portptr = '\0';
- return CURLUE_OK;
+ return has_scheme ? CURLUE_OK : CURLUE_BAD_PORT_NUMBER;
}
if(!ISDIGIT(portptr[1]))
@@ -904,7 +909,7 @@ static CURLUcode seturl(const char *url, CURLU *u, unsigned int flags)
if(result)
return result;
- result = Curl_parse_port(u, hostname);
+ result = Curl_parse_port(u, hostname, url_has_scheme);
if(result)
return result;
@@ -978,12 +983,14 @@ void curl_url_cleanup(CURLU *u)
}
}
-#define DUP(dest, src, name) \
- if(src->name) { \
- dest->name = strdup(src->name); \
- if(!dest->name) \
- goto fail; \
- }
+#define DUP(dest, src, name) \
+ do { \
+ if(src->name) { \
+ dest->name = strdup(src->name); \
+ if(!dest->name) \
+ goto fail; \
+ } \
+ } while(0)
CURLU *curl_url_dup(CURLU *in)
{
@@ -1255,8 +1262,7 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what,
return CURLUE_UNKNOWN_PART;
}
if(storep && *storep) {
- free(*storep);
- *storep = NULL;
+ Curl_safefree(*storep);
}
return CURLUE_OK;
}
@@ -1284,8 +1290,7 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what,
break;
case CURLUPART_HOST:
storep = &u->host;
- free(u->zoneid);
- u->zoneid = NULL;
+ Curl_safefree(u->zoneid);
break;
case CURLUPART_ZONEID:
storep = &u->zoneid;
@@ -1389,28 +1394,17 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what,
if(urlencode) {
const unsigned char *i;
char *o;
- bool free_part = FALSE;
char *enc = malloc(nalloc * 3 + 1); /* for worst case! */
if(!enc)
return CURLUE_OUT_OF_MEMORY;
- if(plusencode) {
- /* space to plus */
- i = (const unsigned char *)part;
- for(o = enc; *i; ++o, ++i)
- *o = (*i == ' ') ? '+' : *i;
- *o = 0; /* null-terminate */
- part = strdup(enc);
- if(!part) {
- free(enc);
- return CURLUE_OUT_OF_MEMORY;
- }
- free_part = TRUE;
- }
for(i = (const unsigned char *)part, o = enc; *i; i++) {
- if(Curl_isunreserved(*i) ||
- ((*i == '/') && urlskipslash) ||
- ((*i == '=') && equalsencode) ||
- ((*i == '+') && plusencode)) {
+ if((*i == ' ') && plusencode) {
+ *o = '+';
+ o++;
+ }
+ else if(Curl_isunreserved(*i) ||
+ ((*i == '/') && urlskipslash) ||
+ ((*i == '=') && equalsencode)) {
if((*i == '=') && equalsencode)
/* only skip the first equals sign */
equalsencode = FALSE;
@@ -1424,8 +1418,6 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what,
}
*o = 0; /* null-terminate */
newp = enc;
- if(free_part)
- free((char *)part);
}
else {
char *p;
diff --git a/Utilities/cmcurl/lib/urldata.h b/Utilities/cmcurl/lib/urldata.h
index 0ae926927..f7d60b249 100644
--- a/Utilities/cmcurl/lib/urldata.h
+++ b/Utilities/cmcurl/lib/urldata.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -76,9 +76,7 @@
/* length of longest IPv6 address string including the trailing null */
#define MAX_IPADR_LEN sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")
-/* Default FTP/IMAP etc response timeout in milliseconds.
- Symbian OS panics when given a timeout much greater than 1/2 hour.
-*/
+/* Default FTP/IMAP etc response timeout in milliseconds */
#define RESP_TIMEOUT (120*1000)
/* Max string input length is a precaution against abuse and to detect junk
@@ -107,19 +105,27 @@
#include "dynbuf.h"
/* return the count of bytes sent, or -1 on error */
-typedef ssize_t (Curl_send)(struct connectdata *conn, /* connection data */
+typedef ssize_t (Curl_send)(struct Curl_easy *data, /* transfer */
int sockindex, /* socketindex */
const void *buf, /* data to write */
size_t len, /* max amount to write */
CURLcode *err); /* error to return */
/* return the count of bytes read, or -1 on error */
-typedef ssize_t (Curl_recv)(struct connectdata *conn, /* connection data */
+typedef ssize_t (Curl_recv)(struct Curl_easy *data, /* transfer */
int sockindex, /* socketindex */
char *buf, /* store data here */
size_t len, /* max amount to read */
CURLcode *err); /* error to return */
+#ifdef USE_HYPER
+typedef CURLcode (*Curl_datastream)(struct Curl_easy *data,
+ struct connectdata *conn,
+ int *didwhat,
+ bool *done,
+ int select_res);
+#endif
+
#include "mime.h"
#include "imap.h"
#include "pop3.h"
@@ -134,6 +140,7 @@ typedef ssize_t (Curl_recv)(struct connectdata *conn, /* connection data */
#include "wildcard.h"
#include "multihandle.h"
#include "quic.h"
+#include "c-hyper.h"
#ifdef HAVE_GSSAPI
# ifdef HAVE_GSSGNU
@@ -153,6 +160,22 @@ typedef ssize_t (Curl_recv)(struct connectdata *conn, /* connection data */
#include <libssh2_sftp.h>
#endif /* HAVE_LIBSSH2_H */
+#define READBUFFER_SIZE CURL_MAX_WRITE_SIZE
+#define READBUFFER_MAX CURL_MAX_READ_SIZE
+#define READBUFFER_MIN 1024
+
+/* The default upload buffer size, should not be smaller than
+ CURL_MAX_WRITE_SIZE, as it needs to hold a full buffer as could be sent in
+ a write callback.
+
+ The size was 16KB for many years but was bumped to 64KB because it makes
+ libcurl able to do significantly faster uploads in some circumstances. Even
+ larger buffers can help further, but this is deemed a fair memory/speed
+ compromise. */
+#define UPLOADBUFFER_DEFAULT 65536
+#define UPLOADBUFFER_MAX (2*1024*1024)
+#define UPLOADBUFFER_MIN CURL_MAX_WRITE_SIZE
+
#define CURLEASY_MAGIC_NUMBER 0xc0dedbadU
#define GOOD_EASY_HANDLE(x) \
((x) && ((x)->magic == CURLEASY_MAGIC_NUMBER))
@@ -207,14 +230,14 @@ struct ssl_backend_data;
/* struct for data related to each SSL connection */
struct ssl_connect_data {
- /* Use ssl encrypted communications TRUE/FALSE, not necessarily using it atm
- but at least asked to or meaning to use it. See 'state' for the exact
- current state of the connection. */
ssl_connection_state state;
ssl_connect_state connecting_state;
#if defined(USE_SSL)
struct ssl_backend_data *backend;
#endif
+ /* Use ssl encrypted communications TRUE/FALSE. The library is not
+ necessarily using ssl at the moment but at least asked to or means to use
+ it. See 'state' for the exact current state of the connection. */
BIT(use);
};
@@ -230,6 +253,7 @@ struct ssl_primary_config {
char *cipher_list13; /* list of TLS 1.3 cipher suites to use */
char *pinned_key;
struct curl_blob *cert_blob;
+ char *curves; /* list of curves to use */
BIT(verifypeer); /* set TRUE if this is desired */
BIT(verifyhost); /* set TRUE if CN/SAN must match hostname */
BIT(verifystatus); /* set TRUE if certificate status must be checked */
@@ -244,8 +268,6 @@ struct ssl_config_data {
struct curl_blob *issuercert_blob;
curl_ssl_ctx_callback fsslctx; /* function to initialize ssl ctx */
void *fsslctxp; /* parameter for call back */
- char *cert; /* client certificate file name */
- struct curl_blob *cert_blob;
char *cert_type; /* format for certificate (default: PEM)*/
char *key; /* private key file name */
struct curl_blob *key_blob;
@@ -271,7 +293,7 @@ struct ssl_general_config {
};
/* information stored about one single SSL session */
-struct curl_ssl_session {
+struct Curl_ssl_session {
char *name; /* host name for which this ID was used */
char *conn_to_host; /* host name for the connection (may be NULL) */
const char *scheme; /* protocol scheme used */
@@ -371,8 +393,8 @@ struct ntlmdata {
#else
unsigned int flags;
unsigned char nonce[8];
- void *target_info; /* TargetInfo received in the ntlm type-2 message */
unsigned int target_info_len;
+ void *target_info; /* TargetInfo received in the ntlm type-2 message */
#if defined(NTLM_WB_ENABLED)
/* used for communication with Samba's winbind daemon helper ntlm_auth */
@@ -472,6 +494,7 @@ struct ConnectBits {
EPRT doesn't work we disable it for the forthcoming
requests */
BIT(ftp_use_data_ssl); /* Enabled SSL for the data connection */
+ BIT(ftp_use_control_ssl); /* Enabled SSL for the control connection */
#endif
BIT(netrc); /* name+password provided by netrc */
BIT(bound); /* set true if bind() has already been done on this socket/
@@ -516,24 +539,24 @@ struct hostname {
#define KEEP_RECVBITS (KEEP_RECV | KEEP_RECV_HOLD | KEEP_RECV_PAUSE)
#define KEEP_SENDBITS (KEEP_SEND | KEEP_SEND_HOLD | KEEP_SEND_PAUSE)
+#if defined(CURLRES_ASYNCH) || !defined(CURL_DISABLE_DOH)
+#define USE_CURL_ASYNC
struct Curl_async {
char *hostname;
- int port;
struct Curl_dns_entry *dns;
+ struct thread_data *tdata;
+ void *resolver; /* resolver state, if it is used in the URL state -
+ ares_channel f.e. */
+ int port;
int status; /* if done is TRUE, this is the status from the callback */
- void *os_specific; /* 'struct thread_data' for Windows */
BIT(done); /* set TRUE when the lookup is complete */
};
+#endif
+
#define FIRSTSOCKET 0
#define SECONDARYSOCKET 1
-/* These function pointer types are here only to allow easier typecasting
- within the source when we need to cast between data pointers (such as NULL)
- and function pointers. */
-typedef CURLcode (*Curl_do_more_func)(struct connectdata *, int *);
-typedef CURLcode (*Curl_done_func)(struct connectdata *, CURLcode, bool);
-
enum expect100 {
EXP100_SEND_DATA, /* enough waiting, just send the body now */
EXP100_AWAITING_CONTINUE, /* waiting for the 100 Continue header */
@@ -580,8 +603,8 @@ struct dohdata {
struct curl_slist *headers;
struct dnsprobe probe[DOH_PROBE_SLOTS];
unsigned int pending; /* still outstanding requests */
- const char *host;
int port;
+ const char *host;
};
/*
@@ -606,6 +629,8 @@ struct SingleRequest {
following second response code) result in a
CURLE_GOT_NOTHING error code */
+ curl_off_t pendingheader; /* this many bytes left to send is actually
+ header and not body */
struct curltime start; /* transfer started at this time */
struct curltime now; /* current time */
enum {
@@ -622,6 +647,7 @@ struct SingleRequest {
Content-Range: header */
int httpcode; /* error code from the 'HTTP/1.? XXX' or
'RTSP/1.? XXX' line */
+ int keepon;
struct curltime start100; /* time stamp to wait for the 100 code from */
enum expect100 exp100; /* expect 100 continue state */
enum upgrade101 upgr101; /* 101 upgrade state */
@@ -630,7 +656,6 @@ struct SingleRequest {
struct contenc_writer *writer_stack;
time_t timeofdoc;
long bodywrites;
- int keepon;
char *location; /* This points to an allocated version of the Location:
header data */
char *newurl; /* Set to the new URL to use when a redirect or a retry is
@@ -645,10 +670,25 @@ struct SingleRequest {
and the 'upload_present' contains the number of bytes available at this
position */
char *upload_fromhere;
- void *protop; /* Allocated protocol-specific data. Each protocol
- handler makes sure this points to data it needs. */
+
+ /* Allocated protocol-specific data. Each protocol handler makes sure this
+ points to data it needs. */
+ union {
+ struct FILEPROTO *file;
+ struct FTP *ftp;
+ struct HTTP *http;
+ 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 dohdata doh; /* DoH specific data for this request */
+ struct dohdata *doh; /* DoH specific data for this request */
#endif
BIT(header); /* incoming data has HTTP header */
BIT(content_range); /* set TRUE if Content-Range: was found */
@@ -673,18 +713,20 @@ struct SingleRequest {
struct Curl_handler {
const char *scheme; /* URL scheme name. */
- /* Complement to setup_connection_internals(). */
- CURLcode (*setup_connection)(struct connectdata *);
+ /* Complement to setup_connection_internals(). This is done before the
+ transfer "owns" the connection. */
+ CURLcode (*setup_connection)(struct Curl_easy *data,
+ struct connectdata *conn);
/* These two functions MUST be set to be protocol dependent */
- CURLcode (*do_it)(struct connectdata *, bool *done);
- Curl_done_func done;
+ CURLcode (*do_it)(struct Curl_easy *data, bool *done);
+ CURLcode (*done)(struct Curl_easy *, CURLcode, bool);
/* If the curl_do() function is better made in two halves, this
* curl_do_more() function will be called afterwards, if set. For example
* for doing the FTP stuff after the PASV/PORT command.
*/
- Curl_do_more_func do_more;
+ CURLcode (*do_more)(struct Curl_easy *, int *);
/* This function *MAY* be set to a protocol-dependent function that is run
* after the connect() and everything is done, as a step in the connection.
@@ -692,39 +734,41 @@ struct Curl_handler {
* function completes before return. If it doesn't complete, the caller
* should call the curl_connecting() function until it is.
*/
- CURLcode (*connect_it)(struct connectdata *, bool *done);
+ CURLcode (*connect_it)(struct Curl_easy *data, bool *done);
/* See above. */
- CURLcode (*connecting)(struct connectdata *, bool *done);
- CURLcode (*doing)(struct connectdata *, bool *done);
+ CURLcode (*connecting)(struct Curl_easy *data, bool *done);
+ CURLcode (*doing)(struct Curl_easy *data, bool *done);
/* Called from the multi interface during the PROTOCONNECT phase, and it
should then return a proper fd set */
- int (*proto_getsock)(struct connectdata *conn,
- curl_socket_t *socks);
+ int (*proto_getsock)(struct Curl_easy *data,
+ struct connectdata *conn, curl_socket_t *socks);
/* Called from the multi interface during the DOING phase, and it should
then return a proper fd set */
- int (*doing_getsock)(struct connectdata *conn,
- curl_socket_t *socks);
+ int (*doing_getsock)(struct Curl_easy *data,
+ struct connectdata *conn, curl_socket_t *socks);
/* Called from the multi interface during the DO_MORE phase, and it should
then return a proper fd set */
- int (*domore_getsock)(struct connectdata *conn,
- curl_socket_t *socks);
+ int (*domore_getsock)(struct Curl_easy *data,
+ struct connectdata *conn, curl_socket_t *socks);
/* Called from the multi interface during the DO_DONE, PERFORM and
WAITPERFORM phases, and it should then return a proper fd set. Not setting
this will make libcurl use the generic default one. */
- int (*perform_getsock)(const struct connectdata *conn,
- curl_socket_t *socks);
+ int (*perform_getsock)(struct Curl_easy *data,
+ struct connectdata *conn, curl_socket_t *socks);
/* This function *MAY* be set to a protocol-dependent function that is run
* by the curl_disconnect(), as a step in the disconnection. If the handler
- * is called because the connection has been considered dead, dead_connection
- * is set to TRUE.
+ * is called because the connection has been considered dead,
+ * dead_connection is set to TRUE. The connection is already disassociated
+ * from the transfer here.
*/
- CURLcode (*disconnect)(struct connectdata *, bool dead_connection);
+ CURLcode (*disconnect)(struct Curl_easy *, struct connectdata *,
+ bool dead_connection);
/* If used, this function gets called from transfer.c:readwrite_data() to
allow the protocol to do extra reads/writes */
@@ -734,12 +778,15 @@ struct Curl_handler {
/* This function can perform various checks on the connection. See
CONNCHECK_* for more information about the checks that can be performed,
and CONNRESULT_* for the results that can be returned. */
- unsigned int (*connection_check)(struct connectdata *conn,
+ unsigned int (*connection_check)(struct Curl_easy *data,
+ struct connectdata *conn,
unsigned int checks_to_perform);
- long defport; /* Default port. */
+ int defport; /* Default port. */
unsigned int protocol; /* See CURLPROTO_* - this needs to be the single
specific protocol bit */
+ unsigned int family; /* single bit for protocol family; basically the
+ non-TLS name of the protocol this is */
unsigned int flags; /* Extra particular characteristics, see PROTOPT_* */
};
@@ -802,7 +849,11 @@ struct proxy_info {
/* struct for HTTP CONNECT state data */
struct http_connect_state {
struct dynbuf rcvbuf;
- int keepon;
+ enum keeponval {
+ KEEPON_DONE,
+ KEEPON_CONNECT,
+ KEEPON_IGNORE
+ } keepon;
curl_off_t cl; /* size of content to read and ignore */
enum {
TUNNEL_INIT, /* init/default/no tunnel state */
@@ -839,13 +890,9 @@ enum connect_t {
#define SOCKS_STATE(x) (((x) >= CONNECT_SOCKS_INIT) && \
((x) < CONNECT_DONE))
-#define SOCKS_REQUEST_BUFSIZE 600 /* room for large user/pw (255 max each) */
struct connstate {
enum connect_t state;
- unsigned char socksreq[SOCKS_REQUEST_BUFSIZE];
-
- /* CONNECT_SOCKS_SEND */
ssize_t outstanding; /* send this many bytes more */
unsigned char *outp; /* send from this pointer */
};
@@ -860,7 +907,7 @@ struct connectdata {
connection is used! */
struct Curl_easy *data;
struct connstate cnnct;
- struct curl_llist_element bundle_node; /* conncache */
+ struct Curl_llist_element bundle_node; /* conncache */
/* chunk is for HTTP chunked encoding, but is in the general connectdata
struct only because we can do just about any protocol through a HTTP proxy
@@ -892,11 +939,6 @@ struct connectdata {
struct Curl_addrinfo *ip_addr;
struct Curl_addrinfo *tempaddr[2]; /* for happy eyeballs */
- /* 'ip_addr_str' is the ip_addr data as a human readable string.
- It remains available as long as the connection does, which is longer than
- the ip_addr itself. */
- char ip_addr_str[MAX_IPADR_LEN];
-
unsigned int scope_id; /* Scope id for IPv6 */
enum {
@@ -919,7 +961,7 @@ struct connectdata {
struct proxy_info socks_proxy;
struct proxy_info http_proxy;
#endif
- long port; /* which port to use locally */
+ int port; /* which port to use locally - to connect to */
int remote_port; /* the remote port, not the proxy port! */
int conn_to_port; /* the remote port to connect to. valid only if
bits.conn_to_port is set */
@@ -934,14 +976,7 @@ struct connectdata {
these are updated with data which comes directly from the socket. */
char primary_ip[MAX_IPADR_LEN];
- long primary_port;
-
- /* 'local_ip' and 'local_port' get filled with local's numerical
- ip address and port number whenever an outgoing connection is
- **established** from the primary socket to a remote address. */
-
- char local_ip[MAX_IPADR_LEN];
- long local_port;
+ unsigned char ip_version; /* copied from the Curl_easy at creation time */
char *user; /* user name string, allocated */
char *passwd; /* password string, allocated */
@@ -978,13 +1013,14 @@ struct connectdata {
#endif
struct ConnectBits bits; /* various state-flags for this connection */
+ /* The field below gets set in Curl_connecthost */
+ int num_addr; /* number of addresses to try to connect to */
/* connecttime: when connect() is called on the current IP address. Used to
be able to track when to move on to try next IP - but only when the multi
interface is used. */
struct curltime connecttime;
- /* The two fields below get set in Curl_connecthost */
- int num_addr; /* number of addresses to try to connect to */
+ /* The field below gets set in Curl_connecthost */
/* how long time in milliseconds to spend on trying to connect to each IP
address, per family */
timediff_t timeoutms_per_addr[2];
@@ -992,15 +1028,11 @@ struct connectdata {
const struct Curl_handler *handler; /* Connection's protocol handler */
const struct Curl_handler *given; /* The protocol first given */
- long ip_version; /* copied from the Curl_easy at creation time */
-
/* Protocols can use a custom keepalive mechanism to keep connections alive.
This allows those protocols to track the last time the keepalive mechanism
was used on this connection. */
struct curltime keepalive;
- long upkeep_interval_ms; /* Time between calls for connection upkeep. */
-
/**** curl_get() phase fields */
curl_socket_t sockfd; /* socket to read from or CURL_SOCKET_BAD */
@@ -1024,7 +1056,7 @@ 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 Curl_llist easyq; /* List of easy handles using this connection */
curl_seek_callback seek_func; /* function that seeks the input */
void *seek_client; /* pointer to pass to the seek() above */
@@ -1051,9 +1083,6 @@ struct connectdata {
struct negotiatedata proxyneg; /* state data for proxy Negotiate auth */
#endif
- /* data used for the asynch name resolve callback */
- struct Curl_async async;
-
/* for chunked-encoded trailer */
struct dynbuf trailer;
@@ -1072,27 +1101,30 @@ struct connectdata {
struct mqtt_conn mqtt;
} proto;
- int cselect_bits; /* bitmask of socket events */
- int waitfor; /* current READ/WRITE bits to wait for */
-
-#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
- int socks5_gssapi_enctype;
+ struct http_connect_state *connect_state; /* for HTTP CONNECT */
+ struct connectbundle *bundle; /* The bundle we are member of */
+#ifdef USE_UNIX_SOCKETS
+ char *unix_domain_socket;
+#endif
+#ifdef USE_HYPER
+ /* if set, an alternative data transfer function */
+ Curl_datastream datastream;
#endif
-
/* When this connection is created, store the conditions for the local end
bind. This is stored before the actual bind and before any connection is
made and will serve the purpose of being used for comparison reasons so
that subsequent bound-requested connections aren't accidentally re-using
wrong connections. */
char *localdev;
- unsigned short localport;
int localportrange;
- struct http_connect_state *connect_state; /* for HTTP CONNECT */
- struct connectbundle *bundle; /* The bundle we are member of */
+ int cselect_bits; /* bitmask of socket events */
+ int waitfor; /* current READ/WRITE bits to wait for */
int negnpn; /* APLN or NPN TLS negotiated protocol, CURL_HTTP_VERSION* */
-#ifdef USE_UNIX_SOCKETS
- char *unix_domain_socket;
+
+#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
+ int socks5_gssapi_enctype;
#endif
+ unsigned short localport;
};
/* The end of connectdata. */
@@ -1134,6 +1166,7 @@ struct PureInfo {
OpenSSL, GnuTLS, Schannel, NSS and GSKit
builds. Asked for with CURLOPT_CERTINFO
/ CURLINFO_CERTINFO */
+ CURLproxycode pxcode;
BIT(timecond); /* set to TRUE if the time condition didn't match, which
thus made the document NOT get fetched */
};
@@ -1187,17 +1220,6 @@ struct Progress {
};
typedef enum {
- HTTPREQ_NONE, /* first in list */
- HTTPREQ_GET,
- HTTPREQ_POST,
- HTTPREQ_POST_FORM, /* we make a difference internally */
- HTTPREQ_POST_MIME, /* we make a difference internally */
- HTTPREQ_PUT,
- HTTPREQ_HEAD,
- HTTPREQ_LAST /* last in list */
-} Curl_HttpReq;
-
-typedef enum {
RTSPREQ_NONE, /* first in list */
RTSPREQ_OPTIONS,
RTSPREQ_DESCRIBE,
@@ -1274,7 +1296,7 @@ typedef enum {
* One instance for each timeout an easy handle can set.
*/
struct time_node {
- struct curl_llist_element list;
+ struct Curl_llist_element list;
struct curltime time;
expire_id eid;
};
@@ -1294,7 +1316,6 @@ struct urlpieces {
struct UrlState {
/* Points to the connection cache */
struct conncache *conn_cache;
-
int retrycount; /* number of retries on a new connection */
/* buffers to store authentication data in, as parsed from input options */
@@ -1314,12 +1335,12 @@ struct UrlState {
strdup() data.
*/
int first_remote_port; /* remote port of the first (not followed) request */
- struct curl_ssl_session *session; /* array of 'max_ssl_sessions' size */
+ struct Curl_ssl_session *session; /* array of 'max_ssl_sessions' size */
long sessionage; /* number of the most recent session */
- unsigned int tempcount; /* number of entries in use in tempwrite, 0 - 3 */
struct tempbuf tempwrite[3]; /* BOTH, HEADER, BODY */
- char *scratch; /* huge buffer[set.buffer_size*2] for upload CRLF replacing */
+ unsigned int tempcount; /* number of entries in use in tempwrite, 0 - 3 */
int os_errno; /* filled in with errno whenever an error occurs */
+ char *scratch; /* huge buffer[set.buffer_size*2] for upload CRLF replacing */
#ifdef HAVE_SIGNAL
/* storage for the previous bag^H^H^HSIGPIPE signal handler :-) */
void (*prev_signal)(int sig);
@@ -1329,8 +1350,9 @@ struct UrlState {
struct auth authhost; /* auth details for host */
struct auth authproxy; /* auth details for proxy */
- void *resolver; /* resolver state, if it is used in the URL state -
- ares_channel f.e. */
+#ifdef USE_CURL_ASYNC
+ struct Curl_async async; /* asynchronous name resolver data */
+#endif
#if defined(USE_OPENSSL)
/* void instead of ENGINE to avoid bleeding OpenSSL into this header */
@@ -1338,7 +1360,7 @@ struct UrlState {
#endif /* USE_OPENSSL */
struct curltime expiretime; /* set this with Curl_expire() only */
struct Curl_tree timenode; /* for the splay stuff */
- struct curl_llist timeoutlist; /* list of pending timeouts */
+ struct Curl_llist timeoutlist; /* list of pending timeouts */
struct time_node expires[EXPIRE_LAST]; /* nodes for each expire type */
/* a place to store the most recently set FTP entrypath */
@@ -1347,8 +1369,7 @@ struct UrlState {
int httpversion; /* the lowest HTTP version*10 reported by any server
involved in this request */
-#if !defined(WIN32) && !defined(MSDOS) && !defined(__EMX__) && \
- !defined(__SYMBIAN32__)
+#if !defined(WIN32) && !defined(MSDOS) && !defined(__EMX__)
/* do FTP line-end conversions on most platforms */
#define CURL_DO_LINEEND_CONV
/* for FTP downloads: track CRLF sequences that span blocks */
@@ -1379,7 +1400,9 @@ struct UrlState {
int stream_weight;
CURLU *uh; /* URL handle for the current parsed URL */
struct urlpieces up;
+#if !defined(CURL_DISABLE_HTTP) || !defined(CURL_DISABLE_MQTT)
Curl_HttpReq httpreq; /* what kind of HTTP request (if any) is this */
+#endif
#ifndef CURL_DISABLE_HTTP
size_t trailers_bytes_sent;
struct dynbuf trailers_buf; /* a buffer containing the compiled trailing
@@ -1387,6 +1410,9 @@ struct UrlState {
#endif
trailers_state trailers_state; /* whether we are sending trailers
and what stage are we at */
+#ifdef USE_HYPER
+ CURLcode hresult; /* used to pass return codes back from hyper callbacks */
+#endif
/* Dynamically allocated strings, MUST be freed before this struct is
killed. */
@@ -1531,39 +1557,30 @@ enum dupstring {
STRING_RTSP_SESSION_ID, /* Session ID to use */
STRING_RTSP_STREAM_URI, /* Stream URI for this request */
STRING_RTSP_TRANSPORT, /* Transport for this session */
-
STRING_SSH_PRIVATE_KEY, /* path to the private key file for auth */
STRING_SSH_PUBLIC_KEY, /* path to the public key file for auth */
STRING_SSH_HOST_PUBLIC_KEY_MD5, /* md5 of host public key in ascii hex */
STRING_SSH_KNOWNHOSTS, /* file name of knownhosts file */
-
STRING_PROXY_SERVICE_NAME, /* Proxy service name */
STRING_SERVICE_NAME, /* Service name */
STRING_MAIL_FROM,
STRING_MAIL_AUTH,
-
STRING_TLSAUTH_USERNAME_ORIG, /* TLS auth <username> */
STRING_TLSAUTH_USERNAME_PROXY, /* TLS auth <username> */
STRING_TLSAUTH_PASSWORD_ORIG, /* TLS auth <password> */
STRING_TLSAUTH_PASSWORD_PROXY, /* TLS auth <password> */
-
STRING_BEARER, /* <bearer>, if used */
-
STRING_UNIX_SOCKET_PATH, /* path to Unix socket, if used */
-
STRING_TARGET, /* CURLOPT_REQUEST_TARGET */
STRING_DOH, /* CURLOPT_DOH_URL */
-
STRING_ALTSVC, /* CURLOPT_ALTSVC */
-
+ STRING_HSTS, /* CURLOPT_HSTS */
STRING_SASL_AUTHZID, /* CURLOPT_SASL_AUTHZID */
-
- STRING_TEMP_URL, /* temp URL storage for proxy use */
-
STRING_DNS_SERVERS,
STRING_DNS_INTERFACE,
STRING_DNS_LOCAL_IP4,
STRING_DNS_LOCAL_IP6,
+ STRING_SSL_EC_CURVES,
/* -- end of null-terminated strings -- */
@@ -1573,6 +1590,7 @@ enum dupstring {
STRING_COPYPOSTFIELDS, /* if POST, set the fields' values here */
+ STRING_AWS_SIGV4, /* Parameters for V4 signature */
STRING_LAST /* not used, just an end-of-list marker */
};
@@ -1647,7 +1665,12 @@ struct UserDefined {
curl_conv_callback convtonetwork;
/* function to convert from UTF-8 encoding: */
curl_conv_callback convfromutf8;
-
+#ifdef USE_HSTS
+ curl_hstsread_callback hsts_read;
+ void *hsts_read_userp;
+ curl_hstswrite_callback hsts_write;
+ void *hsts_write_userp;
+#endif
void *progress_client; /* pointer to pass to the progress callback */
void *ioctl_client; /* pointer to pass to the ioctl callback */
long timeout; /* in milliseconds, 0 means no timeout */
@@ -1683,8 +1706,11 @@ struct UserDefined {
struct curl_slist *connect_to; /* list of host:port mappings to override
the hostname and port to connect to */
curl_TimeCond timecondition; /* kind of time/date comparison */
+ curl_proxytype proxytype; /* what kind of proxy that is in use */
time_t timevalue; /* what time to compare with */
+#if !defined(CURL_DISABLE_HTTP) || !defined(CURL_DISABLE_MQTT)
Curl_HttpReq method; /* what kind of HTTP request (if any) is this */
+#endif
long httpversion; /* when non-zero, a specific HTTP version requested to
be used in the library's request(s) */
struct ssl_config_data ssl; /* user defined SSL stuff */
@@ -1692,15 +1718,14 @@ struct UserDefined {
struct ssl_config_data proxy_ssl; /* user defined SSL stuff for proxy */
#endif
struct ssl_general_config general_ssl; /* general user defined SSL stuff */
- curl_proxytype proxytype; /* what kind of proxy that is in use */
long dns_cache_timeout; /* DNS cache timeout */
long buffer_size; /* size of receive buffer to use */
size_t upload_buffer_size; /* size of upload buffer to use,
keep it >= CURL_MAX_WRITE_SIZE */
void *private_data; /* application-private data */
struct curl_slist *http200aliases; /* linked list of aliases for http200 */
- long ipver; /* the CURL_IPRESOLVE_* defines in the public header file
- 0 - whatever, 1 - v2, 2 - v6 */
+ unsigned char ipver; /* the CURL_IPRESOLVE_* defines in the public header
+ file 0 - whatever, 1 - v2, 2 - v6 */
curl_off_t max_filesize; /* Maximum file size to download */
#ifndef CURL_DISABLE_FTP
curl_ftpfile ftp_filemethod; /* how to get to a file when FTP is used */
@@ -1839,7 +1864,7 @@ struct UserDefined {
};
struct Names {
- struct curl_hash *hostcache;
+ struct Curl_hash *hostcache;
enum {
HCACHE_NONE, /* not pointing to anything */
HCACHE_MULTI, /* points to a shared one in the multi handle */
@@ -1858,13 +1883,17 @@ struct Names {
*/
struct Curl_easy {
+ /* First a simple identifier to easier detect if a user mix up this easy
+ handle with a multi handle. Set this to CURLEASY_MAGIC_NUMBER */
+ unsigned int magic;
+
/* first, two fields for the linked list of these */
struct Curl_easy *next;
struct Curl_easy *prev;
struct connectdata *conn;
- struct curl_llist_element connect_queue;
- struct curl_llist_element conn_queue; /* list per connectdata */
+ struct Curl_llist_element connect_queue;
+ struct Curl_llist_element conn_queue; /* list per connectdata */
CURLMstate mstate; /* the handle's state */
CURLcode result; /* previous result */
@@ -1898,7 +1927,10 @@ struct Curl_easy {
NOTE that the 'cookie' field in the
UserDefined struct defines if the "engine"
is to be used or not. */
-#ifdef USE_ALTSVC
+#ifdef USE_HSTS
+ struct hsts *hsts;
+#endif
+#ifndef CURL_DISABLE_ALTSVC
struct altsvcinfo *asi; /* the alt-svc cache */
#endif
struct Progress progress; /* for all the progress meter data */
@@ -1915,7 +1947,9 @@ struct Curl_easy {
iconv_t inbound_cd; /* for translating from the network encoding */
iconv_t utf8_cd; /* for translating to UTF8 */
#endif /* CURL_DOES_CONVERSIONS && HAVE_ICONV */
- unsigned int magic; /* set to a CURLEASY_MAGIC_NUMBER */
+#ifdef USE_HYPER
+ struct hyptransfer hyp;
+#endif
};
#define LIBCURL_NAME "libcurl"
diff --git a/Utilities/cmcurl/lib/vauth/cleartext.c b/Utilities/cmcurl/lib/vauth/cleartext.c
index 3a5c9430f..620dba03e 100644
--- a/Utilities/cmcurl/lib/vauth/cleartext.c
+++ b/Utilities/cmcurl/lib/vauth/cleartext.c
@@ -9,7 +9,7 @@
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/vauth/cram.c b/Utilities/cmcurl/lib/vauth/cram.c
index 717d7f093..1a376259a 100644
--- a/Utilities/cmcurl/lib/vauth/cram.c
+++ b/Utilities/cmcurl/lib/vauth/cram.c
@@ -9,7 +9,7 @@
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/vauth/digest.c b/Utilities/cmcurl/lib/vauth/digest.c
index b9210a8fe..559852fcb 100644
--- a/Utilities/cmcurl/lib/vauth/digest.c
+++ b/Utilities/cmcurl/lib/vauth/digest.c
@@ -9,7 +9,7 @@
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -61,12 +61,14 @@
It converts digest text to ASCII so the MD5 will be correct for
what ultimately goes over the network.
*/
-#define CURL_OUTPUT_DIGEST_CONV(a, b) \
- result = Curl_convert_to_network(a, b, strlen(b)); \
- if(result) { \
- free(b); \
- return result; \
- }
+#define CURL_OUTPUT_DIGEST_CONV(a, b) \
+ do { \
+ result = Curl_convert_to_network(a, b, strlen(b)); \
+ if(result) { \
+ free(b); \
+ return result; \
+ } \
+ } while(0)
#endif /* !USE_WINDOWS_SSPI */
bool Curl_auth_digest_get_pair(const char *str, char *value, char *content,
diff --git a/Utilities/cmcurl/lib/vauth/digest.h b/Utilities/cmcurl/lib/vauth/digest.h
index cc05fdb76..ee373cd82 100644
--- a/Utilities/cmcurl/lib/vauth/digest.h
+++ b/Utilities/cmcurl/lib/vauth/digest.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
diff --git a/Utilities/cmcurl/lib/vauth/digest_sspi.c b/Utilities/cmcurl/lib/vauth/digest_sspi.c
index 4998306ce..dad947a37 100644
--- a/Utilities/cmcurl/lib/vauth/digest_sspi.c
+++ b/Utilities/cmcurl/lib/vauth/digest_sspi.c
@@ -10,7 +10,7 @@
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -38,6 +38,7 @@
#include "sendf.h"
#include "strdup.h"
#include "strcase.h"
+#include "strerror.h"
/* The last #include files should be: */
#include "curl_memory.h"
@@ -134,7 +135,7 @@ CURLcode Curl_auth_create_digest_md5_message(struct Curl_easy *data,
if(status != SEC_E_OK) {
free(input_token);
- failf(data, "SSPI: couldn't get auth info\n");
+ failf(data, "SSPI: couldn't get auth info");
return CURLE_AUTH_ERROR;
}
@@ -220,6 +221,8 @@ CURLcode Curl_auth_create_digest_md5_message(struct Curl_easy *data,
status == SEC_I_COMPLETE_AND_CONTINUE)
s_pSecFn->CompleteAuthToken(&credentials, &resp_desc);
else if(status != SEC_E_OK && status != SEC_I_CONTINUE_NEEDED) {
+ char buffer[STRERROR_LEN];
+
s_pSecFn->FreeCredentialsHandle(&credentials);
Curl_sspi_free_identity(p_identity);
free(spn);
@@ -229,6 +232,9 @@ CURLcode Curl_auth_create_digest_md5_message(struct Curl_easy *data,
if(status == SEC_E_INSUFFICIENT_MEMORY)
return CURLE_OUT_OF_MEMORY;
+ infof(data, "schannel: InitializeSecurityContext failed: %s\n",
+ Curl_sspi_strerror(status, buffer, sizeof(buffer)));
+
return CURLE_AUTH_ERROR;
}
@@ -433,7 +439,7 @@ CURLcode Curl_auth_create_digest_http_message(struct Curl_easy *data,
status = s_pSecFn->QuerySecurityPackageInfo((TCHAR *) TEXT(SP_NAME_DIGEST),
&SecurityPackage);
if(status != SEC_E_OK) {
- failf(data, "SSPI: couldn't get auth info\n");
+ failf(data, "SSPI: couldn't get auth info");
return CURLE_AUTH_ERROR;
}
@@ -611,6 +617,8 @@ CURLcode Curl_auth_create_digest_http_message(struct Curl_easy *data,
status == SEC_I_COMPLETE_AND_CONTINUE)
s_pSecFn->CompleteAuthToken(&credentials, &resp_desc);
else if(status != SEC_E_OK && status != SEC_I_CONTINUE_NEEDED) {
+ char buffer[STRERROR_LEN];
+
s_pSecFn->FreeCredentialsHandle(&credentials);
Curl_sspi_free_identity(p_identity);
@@ -621,6 +629,9 @@ CURLcode Curl_auth_create_digest_http_message(struct Curl_easy *data,
if(status == SEC_E_INSUFFICIENT_MEMORY)
return CURLE_OUT_OF_MEMORY;
+ infof(data, "schannel: InitializeSecurityContext failed: %s\n",
+ Curl_sspi_strerror(status, buffer, sizeof(buffer)));
+
return CURLE_AUTH_ERROR;
}
diff --git a/Utilities/cmcurl/lib/vauth/krb5_gssapi.c b/Utilities/cmcurl/lib/vauth/krb5_gssapi.c
index 95bab0e2e..0412815e9 100644
--- a/Utilities/cmcurl/lib/vauth/krb5_gssapi.c
+++ b/Utilities/cmcurl/lib/vauth/krb5_gssapi.c
@@ -6,11 +6,11 @@
* \___|\___/|_| \_\_____|
*
* Copyright (C) 2014 - 2019, Steve Holme, <steve_holme@hotmail.com>.
- * Copyright (C) 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2015 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/vauth/krb5_sspi.c b/Utilities/cmcurl/lib/vauth/krb5_sspi.c
index 1fb6257ea..b2d163534 100644
--- a/Utilities/cmcurl/lib/vauth/krb5_sspi.c
+++ b/Utilities/cmcurl/lib/vauth/krb5_sspi.c
@@ -9,7 +9,7 @@
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -125,7 +125,7 @@ CURLcode Curl_auth_create_gssapi_user_message(struct Curl_easy *data,
TEXT(SP_NAME_KERBEROS),
&SecurityPackage);
if(status != SEC_E_OK) {
- failf(data, "SSPI: couldn't get auth info\n");
+ failf(data, "SSPI: couldn't get auth info");
return CURLE_AUTH_ERROR;
}
diff --git a/Utilities/cmcurl/lib/vauth/ntlm.c b/Utilities/cmcurl/lib/vauth/ntlm.c
index ecfeacb9a..a3117f3fe 100644
--- a/Utilities/cmcurl/lib/vauth/ntlm.c
+++ b/Utilities/cmcurl/lib/vauth/ntlm.c
@@ -9,7 +9,7 @@
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -497,7 +497,6 @@ CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data,
const char *passwdp,
struct ntlmdata *ntlm,
char **outptr, size_t *outlen)
-
{
/* NTLM type-3 message structure:
diff --git a/Utilities/cmcurl/lib/vauth/ntlm.h b/Utilities/cmcurl/lib/vauth/ntlm.h
index 1136b0f8d..8ec23ad4f 100644
--- a/Utilities/cmcurl/lib/vauth/ntlm.h
+++ b/Utilities/cmcurl/lib/vauth/ntlm.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
diff --git a/Utilities/cmcurl/lib/vauth/ntlm_sspi.c b/Utilities/cmcurl/lib/vauth/ntlm_sspi.c
index 84ea51dad..07dc97398 100644
--- a/Utilities/cmcurl/lib/vauth/ntlm_sspi.c
+++ b/Utilities/cmcurl/lib/vauth/ntlm_sspi.c
@@ -9,7 +9,7 @@
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -106,7 +106,7 @@ CURLcode Curl_auth_create_ntlm_type1_message(struct Curl_easy *data,
status = s_pSecFn->QuerySecurityPackageInfo((TCHAR *) TEXT(SP_NAME_NTLM),
&SecurityPackage);
if(status != SEC_E_OK) {
- failf(data, "SSPI: couldn't get auth info\n");
+ failf(data, "SSPI: couldn't get auth info");
return CURLE_AUTH_ERROR;
}
diff --git a/Utilities/cmcurl/lib/vauth/oauth2.c b/Utilities/cmcurl/lib/vauth/oauth2.c
index b4e9f8e70..ca5842a7c 100644
--- a/Utilities/cmcurl/lib/vauth/oauth2.c
+++ b/Utilities/cmcurl/lib/vauth/oauth2.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
diff --git a/Utilities/cmcurl/lib/vauth/spnego_gssapi.c b/Utilities/cmcurl/lib/vauth/spnego_gssapi.c
index ed7ce029e..120925ff3 100644
--- a/Utilities/cmcurl/lib/vauth/spnego_gssapi.c
+++ b/Utilities/cmcurl/lib/vauth/spnego_gssapi.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
diff --git a/Utilities/cmcurl/lib/vauth/spnego_sspi.c b/Utilities/cmcurl/lib/vauth/spnego_sspi.c
index 194f250f8..4aa1ba957 100644
--- a/Utilities/cmcurl/lib/vauth/spnego_sspi.c
+++ b/Utilities/cmcurl/lib/vauth/spnego_sspi.c
@@ -9,7 +9,7 @@
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -130,7 +130,7 @@ CURLcode Curl_auth_decode_spnego_message(struct Curl_easy *data,
TEXT(SP_NAME_NEGOTIATE),
&SecurityPackage);
if(nego->status != SEC_E_OK) {
- failf(data, "SSPI: couldn't get auth info\n");
+ failf(data, "SSPI: couldn't get auth info");
return CURLE_AUTH_ERROR;
}
diff --git a/Utilities/cmcurl/lib/vauth/vauth.c b/Utilities/cmcurl/lib/vauth/vauth.c
index d98e66c68..129b8f8b5 100644
--- a/Utilities/cmcurl/lib/vauth/vauth.c
+++ b/Utilities/cmcurl/lib/vauth/vauth.c
@@ -9,7 +9,7 @@
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/vauth/vauth.h b/Utilities/cmcurl/lib/vauth/vauth.h
index a1a557d2a..f25cfc329 100644
--- a/Utilities/cmcurl/lib/vauth/vauth.h
+++ b/Utilities/cmcurl/lib/vauth/vauth.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2014 - 2019, Steve Holme, <steve_holme@hotmail.com>.
+ * Copyright (C) 2014 - 2020, Steve Holme, <steve_holme@hotmail.com>.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/version.c b/Utilities/cmcurl/lib/version.c
index 4f6dda24f..a9102ec1e 100644
--- a/Utilities/cmcurl/lib/version.c
+++ b/Utilities/cmcurl/lib/version.c
@@ -9,7 +9,7 @@
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -31,8 +31,8 @@
#include "curl_printf.h"
#ifdef USE_ARES
-# if defined(CURL_STATICLIB) && !defined(CARES_STATICLIB) && \
- (defined(WIN32) || defined(__SYMBIAN32__))
+# if defined(CURL_STATICLIB) && !defined(CARES_STATICLIB) && \
+ defined(WIN32)
# define CARES_STATICLIB
# endif
# include <ares.h>
@@ -56,10 +56,6 @@
#ifdef HAVE_ZLIB_H
#include <zlib.h>
-#ifdef __SYMBIAN32__
-/* zlib pollutes the namespace with this definition */
-#undef WIN32
-#endif
#endif
#ifdef HAVE_BROTLI
@@ -104,7 +100,7 @@ static size_t zstd_version(char *buf, size_t bufsz)
* zeros in the data.
*/
-#define VERSION_PARTS 14 /* number of substrings we can concatenate */
+#define VERSION_PARTS 15 /* number of substrings we can concatenate */
char *curl_version(void)
{
@@ -148,6 +144,9 @@ char *curl_version(void)
#ifdef USE_LIBRTMP
char rtmp_version[40];
#endif
+#ifdef USE_HYPER
+ char hyper_buf[30];
+#endif
int i = 0;
int j;
@@ -232,6 +231,10 @@ char *curl_version(void)
src[i++] = rtmp_version;
}
#endif
+#ifdef USE_HYPER
+ msnprintf(hyper_buf, sizeof(hyper_buf), "Hyper/%s", hyper_version());
+ src[i++] = hyper_buf;
+#endif
DEBUGASSERT(i <= VERSION_PARTS);
@@ -278,6 +281,9 @@ static const char * const protocols[] = {
#ifndef CURL_DISABLE_GOPHER
"gopher",
#endif
+#if defined(USE_SSL) && !defined(CURL_DISABLE_GOPHER)
+ "gophers",
+#endif
#ifndef CURL_DISABLE_HTTP
"http",
#endif
@@ -298,7 +304,7 @@ static const char * const protocols[] = {
"ldaps",
#endif
#endif
-#ifdef CURL_ENABLE_MQTT
+#ifndef CURL_DISABLE_MQTT
"mqtt",
#endif
#ifndef CURL_DISABLE_POP3
@@ -319,9 +325,8 @@ static const char * const protocols[] = {
#ifdef USE_SSH
"sftp",
#endif
-#if !defined(CURL_DISABLE_SMB) && defined(USE_NTLM) && \
- (CURL_SIZEOF_CURL_OFF_T > 4) && \
- (!defined(USE_WINDOWS_SSPI) || defined(USE_WIN32_CRYPTO))
+#if !defined(CURL_DISABLE_SMB) && defined(USE_CURL_NTLM_CORE) && \
+ (CURL_SIZEOF_CURL_OFF_T > 4)
"smb",
# ifdef USE_SSL
"smbs",
@@ -399,7 +404,7 @@ static curl_version_info_data version_info = {
#if defined(USE_TLS_SRP)
| CURL_VERSION_TLSAUTH_SRP
#endif
-#if defined(USE_NGHTTP2)
+#if defined(USE_NGHTTP2) || defined(USE_HYPER)
| CURL_VERSION_HTTP2
#endif
#if defined(ENABLE_QUIC)
@@ -420,9 +425,12 @@ static curl_version_info_data version_info = {
#if defined(HAVE_ZSTD)
| CURL_VERSION_ZSTD
#endif
-#if defined(USE_ALTSVC)
+#ifndef CURL_DISABLE_ALTSVC
| CURL_VERSION_ALTSVC
#endif
+#if defined(USE_HSTS)
+ | CURL_VERSION_HSTS
+#endif
,
NULL, /* ssl_version */
0, /* ssl_version_num, this is kept at zero */
@@ -449,7 +457,8 @@ static curl_version_info_data version_info = {
NULL,
#endif
0, /* zstd_ver_num */
- NULL /* zstd version */
+ NULL, /* zstd version */
+ NULL /* Hyper version */
};
curl_version_info_data *curl_version_info(CURLversion stamp)
@@ -471,15 +480,16 @@ curl_version_info_data *curl_version_info(CURLversion stamp)
static char zstd_buffer[80];
#endif
-
#ifdef USE_SSL
Curl_ssl_version(ssl_buffer, sizeof(ssl_buffer));
version_info.ssl_version = ssl_buffer;
+#ifndef CURL_DISABLE_PROXY
if(Curl_ssl->supports & SSLSUPP_HTTPS_PROXY)
version_info.features |= CURL_VERSION_HTTPS_PROXY;
else
version_info.features &= ~CURL_VERSION_HTTPS_PROXY;
#endif
+#endif
#ifdef HAVE_LIBZ
version_info.libz_version = zlibVersion();
@@ -544,6 +554,14 @@ curl_version_info_data *curl_version_info(CURLversion stamp)
}
#endif
+#ifdef USE_HYPER
+ {
+ static char hyper_buffer[30];
+ msnprintf(hyper_buffer, sizeof(hyper_buffer), "Hyper/%s", hyper_version());
+ version_info.hyper_version = hyper_buffer;
+ }
+#endif
+
(void)stamp; /* avoid compiler warnings, we don't use this */
return &version_info;
}
diff --git a/Utilities/cmcurl/lib/version_win32.c b/Utilities/cmcurl/lib/version_win32.c
index 6561d36be..b8157e989 100644
--- a/Utilities/cmcurl/lib/version_win32.c
+++ b/Utilities/cmcurl/lib/version_win32.c
@@ -9,7 +9,7 @@
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/version_win32.h b/Utilities/cmcurl/lib/version_win32.h
index 94cc62667..9b1bd8887 100644
--- a/Utilities/cmcurl/lib/version_win32.h
+++ b/Utilities/cmcurl/lib/version_win32.h
@@ -11,7 +11,7 @@
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/vquic/ngtcp2.c b/Utilities/cmcurl/lib/vquic/ngtcp2.c
index 20ee08dd6..d4d0e8bf4 100644
--- a/Utilities/cmcurl/lib/vquic/ngtcp2.c
+++ b/Utilities/cmcurl/lib/vquic/ngtcp2.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -87,10 +87,10 @@ struct h3out {
"+GROUP-X25519:+GROUP-SECP384R1:+GROUP-SECP521R1"
#endif
-static CURLcode ng_process_ingress(struct connectdata *conn,
+static CURLcode ng_process_ingress(struct Curl_easy *data,
curl_socket_t sockfd,
struct quicsocket *qs);
-static CURLcode ng_flush_egress(struct connectdata *conn, int sockfd,
+static CURLcode ng_flush_egress(struct Curl_easy *data, int sockfd,
struct quicsocket *qs);
static int cb_h3_acked_stream_data(nghttp3_conn *conn, int64_t stream_id,
size_t datalen, void *user_data,
@@ -126,7 +126,7 @@ quic_from_ossl_level(OSSL_ENCRYPTION_LEVEL ossl_level)
case ssl_encryption_handshake:
return NGTCP2_CRYPTO_LEVEL_HANDSHAKE;
case ssl_encryption_application:
- return NGTCP2_CRYPTO_LEVEL_APP;
+ return NGTCP2_CRYPTO_LEVEL_APPLICATION;
default:
assert(0);
}
@@ -143,7 +143,7 @@ quic_from_gtls_level(gnutls_record_encryption_level_t gtls_level)
case GNUTLS_ENCRYPTION_LEVEL_HANDSHAKE:
return NGTCP2_CRYPTO_LEVEL_HANDSHAKE;
case GNUTLS_ENCRYPTION_LEVEL_APPLICATION:
- return NGTCP2_CRYPTO_LEVEL_APP;
+ return NGTCP2_CRYPTO_LEVEL_APPLICATION;
default:
assert(0);
}
@@ -170,20 +170,22 @@ static void quic_settings(struct quicsocket *qs,
uint64_t stream_buffer_size)
{
ngtcp2_settings *s = &qs->settings;
+ ngtcp2_transport_params *t = &qs->transport_params;
ngtcp2_settings_default(s);
+ ngtcp2_transport_params_default(t);
#ifdef DEBUG_NGTCP2
s->log_printf = quic_printf;
#else
s->log_printf = NULL;
#endif
s->initial_ts = timestamp();
- s->transport_params.initial_max_stream_data_bidi_local = stream_buffer_size;
- s->transport_params.initial_max_stream_data_bidi_remote = QUIC_MAX_STREAMS;
- s->transport_params.initial_max_stream_data_uni = QUIC_MAX_STREAMS;
- s->transport_params.initial_max_data = QUIC_MAX_DATA;
- s->transport_params.initial_max_streams_bidi = 1;
- s->transport_params.initial_max_streams_uni = 3;
- s->transport_params.max_idle_timeout = QUIC_IDLE_TIMEOUT;
+ t->initial_max_stream_data_bidi_local = stream_buffer_size;
+ t->initial_max_stream_data_bidi_remote = QUIC_MAX_STREAMS;
+ t->initial_max_stream_data_uni = QUIC_MAX_STREAMS;
+ t->initial_max_data = QUIC_MAX_DATA;
+ t->initial_max_streams_bidi = 1;
+ t->initial_max_streams_uni = 3;
+ t->max_idle_timeout = QUIC_IDLE_TIMEOUT;
if(qs->qlogfd != -1) {
s->qlog.write = qlog_callback;
}
@@ -265,7 +267,7 @@ static int quic_set_encryption_secrets(SSL *ssl,
qs->qconn, NULL, NULL, NULL, level, tx_secret, secretlen) != 0)
return 0;
- if(level == NGTCP2_CRYPTO_LEVEL_APP) {
+ if(level == NGTCP2_CRYPTO_LEVEL_APPLICATION) {
if(init_ngh3_conn(qs) != CURLE_OK)
return 0;
}
@@ -349,14 +351,8 @@ static int quic_init_ssl(struct quicsocket *qs)
SSL_set_app_data(qs->ssl, qs);
SSL_set_connect_state(qs->ssl);
- switch(qs->version) {
-#ifdef NGTCP2_PROTO_VER
- case NGTCP2_PROTO_VER:
- alpn = (const uint8_t *)NGHTTP3_ALPN_H3;
- alpnlen = sizeof(NGHTTP3_ALPN_H3) - 1;
- break;
-#endif
- }
+ alpn = (const uint8_t *)NGHTTP3_ALPN_H3;
+ alpnlen = sizeof(NGHTTP3_ALPN_H3) - 1;
if(alpn)
SSL_set_alpn_protos(qs->ssl, alpn, (int)alpnlen);
@@ -382,7 +378,7 @@ static int secret_func(gnutls_session_t ssl,
qs->qconn, NULL, NULL, NULL, level, tx_secret, secretlen) != 0)
return 0;
- if(level == NGTCP2_CRYPTO_LEVEL_APP) {
+ if(level == NGTCP2_CRYPTO_LEVEL_APPLICATION) {
if(init_ngh3_conn(qs) != CURLE_OK)
return -1;
}
@@ -532,15 +528,9 @@ static int quic_init_ssl(struct quicsocket *qs)
return 1;
}
- switch(qs->version) {
-#ifdef NGTCP2_PROTO_VER
- case NGTCP2_PROTO_VER:
- /* strip the first byte (the length) from NGHTTP3_ALPN_H3 */
- alpn.data = (unsigned char *)NGHTTP3_ALPN_H3 + 1;
- alpn.size = sizeof(NGHTTP3_ALPN_H3) - 2;
- break;
-#endif
- }
+ /* strip the first byte (the length) from NGHTTP3_ALPN_H3 */
+ alpn.data = (unsigned char *)NGHTTP3_ALPN_H3 + 1;
+ alpn.size = sizeof(NGHTTP3_ALPN_H3) - 2;
if(alpn.data)
gnutls_alpn_set_protocols(qs->ssl, &alpn, 1, 0);
@@ -568,10 +558,8 @@ cb_recv_crypto_data(ngtcp2_conn *tconn, ngtcp2_crypto_level crypto_level,
static int cb_handshake_completed(ngtcp2_conn *tconn, void *user_data)
{
- struct quicsocket *qs = (struct quicsocket *)user_data;
+ (void)user_data;
(void)tconn;
- infof(qs->conn->data, "QUIC handshake is completed\n");
-
return 0;
}
@@ -599,8 +587,6 @@ static int cb_recv_stream_data(ngtcp2_conn *tconn, uint32_t flags,
nconsumed =
nghttp3_conn_read_stream(qs->h3conn, stream_id, buf, buflen, fin);
if(nconsumed < 0) {
- failf(qs->conn->data, "nghttp3_conn_read_stream returned error: %s\n",
- nghttp3_strerror((int)nconsumed));
return NGTCP2_ERR_CALLBACK_FAILURE;
}
@@ -628,8 +614,6 @@ cb_acked_stream_data_offset(ngtcp2_conn *tconn, int64_t stream_id,
rv = nghttp3_conn_add_ack_offset(qs->h3conn, stream_id, datalen);
if(rv != 0) {
- failf(qs->conn->data, "nghttp3_conn_add_ack_offset returned error: %s\n",
- nghttp3_strerror(rv));
return NGTCP2_ERR_CALLBACK_FAILURE;
}
@@ -649,8 +633,6 @@ static int cb_stream_close(ngtcp2_conn *tconn, int64_t stream_id,
rv = nghttp3_conn_close_stream(qs->h3conn, stream_id,
app_error_code);
if(rv != 0) {
- failf(qs->conn->data, "nghttp3_conn_close_stream returned error: %s\n",
- nghttp3_strerror(rv));
return NGTCP2_ERR_CALLBACK_FAILURE;
}
@@ -670,8 +652,6 @@ static int cb_stream_reset(ngtcp2_conn *tconn, int64_t stream_id,
rv = nghttp3_conn_reset_stream(qs->h3conn, stream_id);
if(rv != 0) {
- failf(qs->conn->data, "nghttp3_conn_reset_stream returned error: %s\n",
- nghttp3_strerror(rv));
return NGTCP2_ERR_CALLBACK_FAILURE;
}
@@ -701,8 +681,6 @@ static int cb_extend_max_stream_data(ngtcp2_conn *tconn, int64_t stream_id,
rv = nghttp3_conn_unblock_stream(qs->h3conn, stream_id);
if(rv != 0) {
- failf(qs->conn->data, "nghttp3_conn_unblock_stream returned error: %s\n",
- nghttp3_strerror(rv));
return NGTCP2_ERR_CALLBACK_FAILURE;
}
@@ -713,23 +691,23 @@ static int cb_get_new_connection_id(ngtcp2_conn *tconn, ngtcp2_cid *cid,
uint8_t *token, size_t cidlen,
void *user_data)
{
- struct quicsocket *qs = (struct quicsocket *)user_data;
CURLcode result;
(void)tconn;
+ (void)user_data;
- result = Curl_rand(qs->conn->data, cid->data, cidlen);
+ result = Curl_rand(NULL, cid->data, cidlen);
if(result)
return NGTCP2_ERR_CALLBACK_FAILURE;
cid->datalen = cidlen;
- result = Curl_rand(qs->conn->data, token, NGTCP2_STATELESS_RESET_TOKENLEN);
+ result = Curl_rand(NULL, token, NGTCP2_STATELESS_RESET_TOKENLEN);
if(result)
return NGTCP2_ERR_CALLBACK_FAILURE;
return 0;
}
-static ngtcp2_conn_callbacks ng_callbacks = {
+static ngtcp2_callbacks ng_callbacks = {
ngtcp2_crypto_client_initial_cb,
NULL, /* recv_client_initial */
cb_recv_crypto_data,
@@ -767,7 +745,8 @@ static ngtcp2_conn_callbacks ng_callbacks = {
/*
* Might be called twice for happy eyeballs.
*/
-CURLcode Curl_quic_connect(struct connectdata *conn,
+CURLcode Curl_quic_connect(struct Curl_easy *data,
+ struct connectdata *conn,
curl_socket_t sockfd,
int sockindex,
const struct sockaddr *addr,
@@ -777,14 +756,13 @@ CURLcode Curl_quic_connect(struct connectdata *conn,
int rv;
CURLcode result;
ngtcp2_path path; /* TODO: this must be initialized properly */
- struct Curl_easy *data = conn->data;
struct quicsocket *qs = &conn->hequic[sockindex];
char ipbuf[40];
long port;
int qfd;
if(qs->conn)
- Curl_quic_disconnect(conn, sockindex);
+ Curl_quic_disconnect(data, conn, sockindex);
qs->conn = conn;
/* extract the used address as a string */
@@ -798,7 +776,7 @@ CURLcode Curl_quic_connect(struct connectdata *conn,
infof(data, "Connect socket %d over QUIC to %s:%ld\n",
sockfd, ipbuf, port);
- qs->version = NGTCP2_PROTO_VER;
+ qs->version = NGTCP2_PROTO_VER_MAX;
#ifdef USE_OPENSSL
qs->sslctx = quic_ssl_ctx(data);
if(!qs->sslctx)
@@ -828,16 +806,13 @@ CURLcode Curl_quic_connect(struct connectdata *conn,
if(rv == -1)
return CURLE_QUIC_CONNECT_ERROR;
- ngtcp2_addr_init(&path.local, &qs->local_addr, qs->local_addrlen, NULL);
+ ngtcp2_addr_init(&path.local, (struct sockaddr *)&qs->local_addr,
+ qs->local_addrlen, NULL);
ngtcp2_addr_init(&path.remote, addr, addrlen, NULL);
-#ifdef NGTCP2_PROTO_VER
-#define QUICVER NGTCP2_PROTO_VER
-#else
-#error "unsupported ngtcp2 version"
-#endif
- rc = ngtcp2_conn_client_new(&qs->qconn, &qs->dcid, &qs->scid, &path, QUICVER,
- &ng_callbacks, &qs->settings, NULL, qs);
+ rc = ngtcp2_conn_client_new(&qs->qconn, &qs->dcid, &qs->scid, &path,
+ NGTCP2_PROTO_VER_MIN, &ng_callbacks,
+ &qs->settings, &qs->transport_params, NULL, qs);
if(rc)
return CURLE_QUIC_CONNECT_ERROR;
@@ -858,9 +833,10 @@ int Curl_quic_ver(char *p, size_t len)
ng2->version_str, ht3->version_str);
}
-static int ng_getsock(struct connectdata *conn, curl_socket_t *socks)
+static int ng_getsock(struct Curl_easy *data, struct connectdata *conn,
+ curl_socket_t *socks)
{
- struct SingleRequest *k = &conn->data->req;
+ struct SingleRequest *k = &data->req;
int bitmap = GETSOCK_BLANK;
socks[0] = conn->sock[FIRSTSOCKET];
@@ -876,12 +852,6 @@ static int ng_getsock(struct connectdata *conn, curl_socket_t *socks)
return bitmap;
}
-static int ng_perform_getsock(const struct connectdata *conn,
- curl_socket_t *socks)
-{
- return ng_getsock((struct connectdata *)conn, socks);
-}
-
static void qs_disconnect(struct quicsocket *qs)
{
int i;
@@ -912,25 +882,30 @@ static void qs_disconnect(struct quicsocket *qs)
#endif
}
-void Curl_quic_disconnect(struct connectdata *conn,
+void Curl_quic_disconnect(struct Curl_easy *data,
+ struct connectdata *conn,
int tempindex)
{
+ (void)data;
if(conn->transport == TRNSPRT_QUIC)
qs_disconnect(&conn->hequic[tempindex]);
}
-static CURLcode ng_disconnect(struct connectdata *conn,
+static CURLcode ng_disconnect(struct Curl_easy *data,
+ struct connectdata *conn,
bool dead_connection)
{
(void)dead_connection;
- Curl_quic_disconnect(conn, 0);
- Curl_quic_disconnect(conn, 1);
+ Curl_quic_disconnect(data, conn, 0);
+ Curl_quic_disconnect(data, conn, 1);
return CURLE_OK;
}
-static unsigned int ng_conncheck(struct connectdata *conn,
+static unsigned int ng_conncheck(struct Curl_easy *data,
+ struct connectdata *conn,
unsigned int checks_to_perform)
{
+ (void)data;
(void)conn;
(void)checks_to_perform;
return CONNRESULT_NONE;
@@ -948,12 +923,13 @@ static const struct Curl_handler Curl_handler_http3 = {
ng_getsock, /* proto_getsock */
ng_getsock, /* doing_getsock */
ZERO_NULL, /* domore_getsock */
- ng_perform_getsock, /* perform_getsock */
+ ng_getsock, /* perform_getsock */
ng_disconnect, /* disconnect */
ZERO_NULL, /* readwrite */
ng_conncheck, /* connection_check */
PORT_HTTP, /* defport */
CURLPROTO_HTTPS, /* protocol */
+ CURLPROTO_HTTP, /* family */
PROTOPT_SSL | PROTOPT_STREAM /* flags */
};
@@ -962,7 +938,7 @@ static int cb_h3_stream_close(nghttp3_conn *conn, int64_t stream_id,
void *stream_user_data)
{
struct Curl_easy *data = stream_user_data;
- struct HTTP *stream = data->req.protop;
+ struct HTTP *stream = data->req.p.http;
(void)conn;
(void)stream_id;
(void)app_error_code;
@@ -1008,7 +984,7 @@ static int cb_h3_recv_data(nghttp3_conn *conn, int64_t stream_id,
void *user_data, void *stream_user_data)
{
struct Curl_easy *data = stream_user_data;
- struct HTTP *stream = data->req.protop;
+ struct HTTP *stream = data->req.p.http;
CURLcode result = CURLE_OK;
(void)conn;
@@ -1067,7 +1043,7 @@ static int cb_h3_end_headers(nghttp3_conn *conn, int64_t stream_id,
void *user_data, void *stream_user_data)
{
struct Curl_easy *data = stream_user_data;
- struct HTTP *stream = data->req.protop;
+ struct HTTP *stream = data->req.p.http;
CURLcode result = CURLE_OK;
(void)conn;
(void)stream_id;
@@ -1091,7 +1067,7 @@ static int cb_h3_recv_header(nghttp3_conn *conn, int64_t stream_id,
nghttp3_vec h3name = nghttp3_rcbuf_get_buf(name);
nghttp3_vec h3val = nghttp3_rcbuf_get_buf(value);
struct Curl_easy *data = stream_user_data;
- struct HTTP *stream = data->req.protop;
+ struct HTTP *stream = data->req.p.http;
CURLcode result = CURLE_OK;
(void)conn;
(void)stream_id;
@@ -1148,7 +1124,7 @@ static int cb_h3_send_stop_sending(nghttp3_conn *conn, int64_t stream_id,
return 0;
}
-static nghttp3_conn_callbacks ngh3_callbacks = {
+static nghttp3_callbacks ngh3_callbacks = {
cb_h3_acked_stream_data, /* acked_stream_data */
cb_h3_stream_close,
cb_h3_recv_data,
@@ -1166,6 +1142,7 @@ static nghttp3_conn_callbacks ngh3_callbacks = {
cb_h3_send_stop_sending,
NULL, /* push_stream */
NULL, /* end_stream */
+ NULL, /* reset_stream */
};
static int init_ngh3_conn(struct quicsocket *qs)
@@ -1175,11 +1152,10 @@ static int init_ngh3_conn(struct quicsocket *qs)
int64_t ctrl_stream_id, qpack_enc_stream_id, qpack_dec_stream_id;
if(ngtcp2_conn_get_max_local_streams_uni(qs->qconn) < 3) {
- failf(qs->conn->data, "too few available QUIC streams");
return CURLE_QUIC_CONNECT_ERROR;
}
- nghttp3_conn_settings_default(&qs->h3settings);
+ nghttp3_settings_default(&qs->h3settings);
rc = nghttp3_conn_client_new(&qs->h3conn,
&ngh3_callbacks,
@@ -1248,14 +1224,15 @@ static size_t drain_overflow_buffer(struct HTTP *stream)
}
/* incoming data frames on the h3 stream */
-static ssize_t ngh3_stream_recv(struct connectdata *conn,
+static ssize_t ngh3_stream_recv(struct Curl_easy *data,
int sockindex,
char *buf,
size_t buffersize,
CURLcode *curlcode)
{
+ struct connectdata *conn = data->conn;
curl_socket_t sockfd = conn->sock[sockindex];
- struct HTTP *stream = conn->data->req.protop;
+ struct HTTP *stream = data->req.p.http;
struct quicsocket *qs = conn->quic;
if(!stream->memlen) {
@@ -1270,11 +1247,11 @@ static ssize_t ngh3_stream_recv(struct connectdata *conn,
as possible to the receive buffer before receiving more */
drain_overflow_buffer(stream);
- if(ng_process_ingress(conn, sockfd, qs)) {
+ if(ng_process_ingress(data, sockfd, qs)) {
*curlcode = CURLE_RECV_ERROR;
return -1;
}
- if(ng_flush_egress(conn, sockfd, qs)) {
+ if(ng_flush_egress(data, sockfd, qs)) {
*curlcode = CURLE_SEND_ERROR;
return -1;
}
@@ -1290,7 +1267,7 @@ static ssize_t ngh3_stream_recv(struct connectdata *conn,
/* extend the stream window with the data we're consuming and send out
any additional packets to tell the server that we can receive more */
extend_stream_window(qs->qconn, stream);
- if(ng_flush_egress(conn, sockfd, qs)) {
+ if(ng_flush_egress(data, sockfd, qs)) {
*curlcode = CURLE_SEND_ERROR;
return -1;
}
@@ -1302,7 +1279,7 @@ static ssize_t ngh3_stream_recv(struct connectdata *conn,
return 0;
}
- infof(conn->data, "ngh3_stream_recv returns 0 bytes and EAGAIN\n");
+ infof(data, "ngh3_stream_recv returns 0 bytes and EAGAIN\n");
*curlcode = CURLE_AGAIN;
return -1;
}
@@ -1313,9 +1290,8 @@ static int cb_h3_acked_stream_data(nghttp3_conn *conn, int64_t stream_id,
void *stream_user_data)
{
struct Curl_easy *data = stream_user_data;
- struct HTTP *stream = data->req.protop;
- (void)conn;
- (void)stream_id;
+ struct HTTP *stream = data->req.p.http;
+ int rv;
(void)user_data;
if(!data->set.postfields) {
@@ -1324,6 +1300,13 @@ static int cb_h3_acked_stream_data(nghttp3_conn *conn, int64_t stream_id,
"cb_h3_acked_stream_data, %zd bytes, %zd left unacked\n",
datalen, stream->h3out->used));
DEBUGASSERT(stream->h3out->used < H3_SEND_SIZE);
+
+ if(stream->h3out->used == 0) {
+ rv = nghttp3_conn_resume_stream(conn, stream_id);
+ if(rv != 0) {
+ return NGTCP2_ERR_CALLBACK_FAILURE;
+ }
+ }
}
return 0;
}
@@ -1335,7 +1318,7 @@ static ssize_t cb_h3_readfunction(nghttp3_conn *conn, int64_t stream_id,
{
struct Curl_easy *data = stream_user_data;
size_t nread;
- struct HTTP *stream = data->req.protop;
+ struct HTTP *stream = data->req.p.http;
(void)conn;
(void)stream_id;
(void)user_data;
@@ -1359,13 +1342,14 @@ static ssize_t cb_h3_readfunction(nghttp3_conn *conn, int64_t stream_id,
nread = H3_SEND_SIZE - out->windex;
memcpy(&out->buf[out->windex], stream->upload_mem, nread);
- out->windex += nread;
- out->used += nread;
/* that's the chunk we return to nghttp3 */
vec[0].base = &out->buf[out->windex];
vec[0].len = nread;
+ out->windex += nread;
+ out->used += nread;
+
if(out->windex == H3_SEND_SIZE)
out->windex = 0; /* wrap */
stream->upload_mem += nread;
@@ -1383,7 +1367,7 @@ static ssize_t cb_h3_readfunction(nghttp3_conn *conn, int64_t stream_id,
(stream->upload_left <= 0)) {
H3BUGF(infof(data, "!!!!!!!!! cb_h3_readfunction sets EOF\n"));
*pflags = NGHTTP3_DATA_FLAG_EOF;
- return 0;
+ return nread ? 1 : 0;
}
else if(!nread) {
return NGHTTP3_ERR_WOULDBLOCK;
@@ -1395,10 +1379,11 @@ static ssize_t cb_h3_readfunction(nghttp3_conn *conn, int64_t stream_id,
field list. */
#define AUTHORITY_DST_IDX 3
-static CURLcode http_request(struct connectdata *conn, const void *mem,
+static CURLcode http_request(struct Curl_easy *data, const void *mem,
size_t len)
{
- struct HTTP *stream = conn->data->req.protop;
+ struct connectdata *conn = data->conn;
+ struct HTTP *stream = data->req.p.http;
size_t nheader;
size_t i;
size_t authority_idx;
@@ -1406,7 +1391,6 @@ static CURLcode http_request(struct connectdata *conn, const void *mem,
char *end, *line_end;
struct quicsocket *qs = conn->quic;
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
nghttp3_nv *nva = NULL;
int64_t stream3_id;
int rc;
@@ -1414,7 +1398,7 @@ static CURLcode http_request(struct connectdata *conn, const void *mem,
rc = ngtcp2_conn_open_bidi_stream(qs->qconn, &stream3_id, NULL);
if(rc) {
- failf(conn->data, "can get bidi streams");
+ failf(data, "can get bidi streams");
result = CURLE_SEND_ERROR;
goto fail;
}
@@ -1573,7 +1557,7 @@ static CURLcode http_request(struct connectdata *conn, const void *mem,
if(acc > MAX_ACC) {
infof(data, "http_request: Warning: The cumulative length of all "
- "headers exceeds %zu bytes and that could cause the "
+ "headers exceeds %d bytes and that could cause the "
"stream to be rejected.\n", MAX_ACC);
}
}
@@ -1600,8 +1584,7 @@ static CURLcode http_request(struct connectdata *conn, const void *mem,
stream->h3out = h3out;
rc = nghttp3_conn_submit_request(qs->h3conn, stream->stream3_id,
- nva, nheader, &data_reader,
- conn->data);
+ nva, nheader, &data_reader, data);
if(rc) {
result = CURLE_SEND_ERROR;
goto fail;
@@ -1611,9 +1594,7 @@ static CURLcode http_request(struct connectdata *conn, const void *mem,
default:
stream->upload_left = 0; /* nothing left to send */
rc = nghttp3_conn_submit_request(qs->h3conn, stream->stream3_id,
- nva, nheader,
- NULL, /* no body! */
- conn->data);
+ nva, nheader, NULL, data);
if(rc) {
result = CURLE_SEND_ERROR;
goto fail;
@@ -1632,19 +1613,20 @@ fail:
free(nva);
return result;
}
-static ssize_t ngh3_stream_send(struct connectdata *conn,
+static ssize_t ngh3_stream_send(struct Curl_easy *data,
int sockindex,
const void *mem,
size_t len,
CURLcode *curlcode)
{
ssize_t sent;
+ struct connectdata *conn = data->conn;
struct quicsocket *qs = conn->quic;
curl_socket_t sockfd = conn->sock[sockindex];
- struct HTTP *stream = conn->data->req.protop;
+ struct HTTP *stream = data->req.p.http;
if(!stream->h3req) {
- CURLcode result = http_request(conn, mem, len);
+ CURLcode result = http_request(data, mem, len);
if(result) {
*curlcode = CURLE_SEND_ERROR;
return -1;
@@ -1652,7 +1634,7 @@ static ssize_t ngh3_stream_send(struct connectdata *conn,
sent = len;
}
else {
- H3BUGF(infof(conn->data, "ngh3_stream_send() wants to send %zd bytes\n",
+ H3BUGF(infof(data, "ngh3_stream_send() wants to send %zd bytes\n",
len));
if(!stream->upload_len) {
stream->upload_mem = mem;
@@ -1666,7 +1648,7 @@ static ssize_t ngh3_stream_send(struct connectdata *conn,
}
}
- if(ng_flush_egress(conn, sockfd, qs)) {
+ if(ng_flush_egress(data, sockfd, qs)) {
*curlcode = CURLE_SEND_ERROR;
return -1;
}
@@ -1684,13 +1666,13 @@ static void ng_has_connected(struct connectdata *conn, int tempindex)
conn->httpversion = 30;
conn->bundle->multiuse = BUNDLE_MULTIPLEX;
conn->quic = &conn->hequic[tempindex];
- DEBUGF(infof(conn->data, "ngtcp2 established connection!\n"));
}
/*
* There can be multiple connection attempts going on in parallel.
*/
-CURLcode Curl_quic_is_connected(struct connectdata *conn,
+CURLcode Curl_quic_is_connected(struct Curl_easy *data,
+ struct connectdata *conn,
int sockindex,
bool *done)
{
@@ -1698,11 +1680,11 @@ CURLcode Curl_quic_is_connected(struct connectdata *conn,
struct quicsocket *qs = &conn->hequic[sockindex];
curl_socket_t sockfd = conn->tempsock[sockindex];
- result = ng_process_ingress(conn, sockfd, qs);
+ result = ng_process_ingress(data, sockfd, qs);
if(result)
goto error;
- result = ng_flush_egress(conn, sockfd, qs);
+ result = ng_flush_egress(data, sockfd, qs);
if(result)
goto error;
@@ -1718,7 +1700,8 @@ CURLcode Curl_quic_is_connected(struct connectdata *conn,
}
-static CURLcode ng_process_ingress(struct connectdata *conn, int sockfd,
+static CURLcode ng_process_ingress(struct Curl_easy *data,
+ curl_socket_t sockfd,
struct quicsocket *qs)
{
ssize_t recvd;
@@ -1729,10 +1712,11 @@ static CURLcode ng_process_ingress(struct connectdata *conn, int sockfd,
socklen_t remote_addrlen;
ngtcp2_path path;
ngtcp2_tstamp ts = timestamp();
+ ngtcp2_pkt_info pi = { 0 };
for(;;) {
remote_addrlen = sizeof(remote_addr);
- while((recvd = recvfrom(sockfd, buf, bufsize, 0,
+ while((recvd = recvfrom(sockfd, (char *)buf, bufsize, 0,
(struct sockaddr *)&remote_addr,
&remote_addrlen)) == -1 &&
SOCKERRNO == EINTR)
@@ -1741,16 +1725,16 @@ static CURLcode ng_process_ingress(struct connectdata *conn, int sockfd,
if(SOCKERRNO == EAGAIN || SOCKERRNO == EWOULDBLOCK)
break;
- failf(conn->data, "ngtcp2: recvfrom() unexpectedly returned %d", recvd);
+ failf(data, "ngtcp2: recvfrom() unexpectedly returned %zd", recvd);
return CURLE_RECV_ERROR;
}
- ngtcp2_addr_init(&path.local, &qs->local_addr,
+ ngtcp2_addr_init(&path.local, (struct sockaddr *)&qs->local_addr,
qs->local_addrlen, NULL);
ngtcp2_addr_init(&path.remote, (struct sockaddr *)&remote_addr,
remote_addrlen, NULL);
- rv = ngtcp2_conn_read_pkt(qs->qconn, &path, buf, recvd, ts);
+ rv = ngtcp2_conn_read_pkt(qs->qconn, &path, &pi, buf, recvd, ts);
if(rv != 0) {
/* TODO Send CONNECTION_CLOSE if possible */
return CURLE_RECV_ERROR;
@@ -1760,7 +1744,8 @@ static CURLcode ng_process_ingress(struct connectdata *conn, int sockfd,
return CURLE_OK;
}
-static CURLcode ng_flush_egress(struct connectdata *conn, int sockfd,
+static CURLcode ng_flush_egress(struct Curl_easy *data,
+ int sockfd,
struct quicsocket *qs)
{
int rv;
@@ -1778,8 +1763,9 @@ static CURLcode ng_flush_egress(struct connectdata *conn, int sockfd,
int fin;
nghttp3_vec vec[16];
ssize_t ndatalen;
+ uint32_t flags;
- switch(qs->local_addr.sa_family) {
+ switch(qs->local_addr.ss_family) {
case AF_INET:
pktlen = NGTCP2_MAX_PKTLEN_IPV4;
break;
@@ -1794,7 +1780,7 @@ static CURLcode ng_flush_egress(struct connectdata *conn, int sockfd,
rv = ngtcp2_conn_handle_expiry(qs->qconn, ts);
if(rv != 0) {
- failf(conn->data, "ngtcp2_conn_handle_expiry returned error: %s\n",
+ failf(data, "ngtcp2_conn_handle_expiry returned error: %s",
ngtcp2_strerror(rv));
return CURLE_SEND_ERROR;
}
@@ -1803,75 +1789,68 @@ static CURLcode ng_flush_egress(struct connectdata *conn, int sockfd,
for(;;) {
outlen = -1;
+ veccnt = 0;
+ stream_id = -1;
+ fin = 0;
+
if(qs->h3conn && ngtcp2_conn_get_max_data_left(qs->qconn)) {
veccnt = nghttp3_conn_writev_stream(qs->h3conn, &stream_id, &fin, vec,
sizeof(vec) / sizeof(vec[0]));
if(veccnt < 0) {
- failf(conn->data, "nghttp3_conn_writev_stream returned error: %s\n",
+ failf(data, "nghttp3_conn_writev_stream returned error: %s",
nghttp3_strerror((int)veccnt));
return CURLE_SEND_ERROR;
}
- else if(veccnt > 0) {
- uint32_t flags = NGTCP2_WRITE_STREAM_FLAG_MORE |
- (fin ? NGTCP2_WRITE_STREAM_FLAG_FIN : 0);
- outlen =
- ngtcp2_conn_writev_stream(qs->qconn, &ps.path,
- out, pktlen, &ndatalen,
- flags, stream_id,
- (const ngtcp2_vec *)vec, veccnt, ts);
- if(outlen == 0) {
- break;
- }
- if(outlen < 0) {
- if(outlen == NGTCP2_ERR_STREAM_DATA_BLOCKED ||
- outlen == NGTCP2_ERR_STREAM_SHUT_WR) {
- assert(ndatalen == -1);
- rv = nghttp3_conn_block_stream(qs->h3conn, stream_id);
- if(rv != 0) {
- failf(conn->data,
- "nghttp3_conn_block_stream returned error: %s\n",
- nghttp3_strerror(rv));
- return CURLE_SEND_ERROR;
- }
- continue;
- }
- else if(outlen == NGTCP2_ERR_WRITE_MORE) {
- assert(ndatalen > 0);
- rv = nghttp3_conn_add_write_offset(qs->h3conn, stream_id,
- ndatalen);
- if(rv != 0) {
- failf(conn->data,
- "nghttp3_conn_add_write_offset returned error: %s\n",
- nghttp3_strerror(rv));
- return CURLE_SEND_ERROR;
- }
- continue;
- }
- else {
- assert(ndatalen == -1);
- failf(conn->data, "ngtcp2_conn_writev_stream returned error: %s\n",
- ngtcp2_strerror((int)outlen));
- return CURLE_SEND_ERROR;
- }
+ }
+
+ flags = NGTCP2_WRITE_STREAM_FLAG_MORE |
+ (fin ? NGTCP2_WRITE_STREAM_FLAG_FIN : 0);
+ outlen = ngtcp2_conn_writev_stream(qs->qconn, &ps.path, NULL, out, pktlen,
+ &ndatalen, flags, stream_id,
+ (const ngtcp2_vec *)vec, veccnt, ts);
+ if(outlen == 0) {
+ break;
+ }
+ if(outlen < 0) {
+ if(outlen == NGTCP2_ERR_STREAM_DATA_BLOCKED ||
+ outlen == NGTCP2_ERR_STREAM_SHUT_WR) {
+ assert(ndatalen == -1);
+ rv = nghttp3_conn_block_stream(qs->h3conn, stream_id);
+ if(rv != 0) {
+ failf(data, "nghttp3_conn_block_stream returned error: %s\n",
+ nghttp3_strerror(rv));
+ return CURLE_SEND_ERROR;
}
- else {
- assert(ndatalen == -1);
+ continue;
+ }
+ else if(outlen == NGTCP2_ERR_WRITE_MORE) {
+ assert(ndatalen >= 0);
+ rv = nghttp3_conn_add_write_offset(qs->h3conn, stream_id, ndatalen);
+ if(rv != 0) {
+ failf(data, "nghttp3_conn_add_write_offset returned error: %s\n",
+ nghttp3_strerror(rv));
+ return CURLE_SEND_ERROR;
}
+ continue;
}
- }
- if(outlen < 0) {
- outlen = ngtcp2_conn_write_pkt(qs->qconn, &ps.path, out, pktlen, ts);
- if(outlen < 0) {
- failf(conn->data, "ngtcp2_conn_write_pkt returned error: %s\n",
+ else {
+ assert(ndatalen == -1);
+ failf(data, "ngtcp2_conn_writev_stream returned error: %s",
ngtcp2_strerror((int)outlen));
return CURLE_SEND_ERROR;
}
- if(outlen == 0)
- break;
+ }
+ else if(ndatalen >= 0) {
+ rv = nghttp3_conn_add_write_offset(qs->h3conn, stream_id, ndatalen);
+ if(rv != 0) {
+ failf(data, "nghttp3_conn_add_write_offset returned error: %s\n",
+ nghttp3_strerror(rv));
+ return CURLE_SEND_ERROR;
+ }
}
memcpy(&remote_addr, ps.path.remote.addr, ps.path.remote.addrlen);
- while((sent = send(sockfd, out, outlen, 0)) == -1 &&
+ while((sent = send(sockfd, (const char *)out, outlen, 0)) == -1 &&
SOCKERRNO == EINTR)
;
@@ -1881,7 +1860,7 @@ static CURLcode ng_flush_egress(struct connectdata *conn, int sockfd,
break;
}
else {
- failf(conn->data, "send() returned %zd (errno %d)\n", sent,
+ failf(data, "send() returned %zd (errno %d)", sent,
SOCKERRNO);
return CURLE_SEND_ERROR;
}
@@ -1896,7 +1875,7 @@ static CURLcode ng_flush_egress(struct connectdata *conn, int sockfd,
else {
timeout = expiry - ts;
}
- Curl_expire(conn->data, timeout / NGTCP2_MILLISECONDS, EXPIRE_QUIC);
+ Curl_expire(data, timeout / NGTCP2_MILLISECONDS, EXPIRE_QUIC);
}
return CURLE_OK;
@@ -1905,11 +1884,13 @@ static CURLcode ng_flush_egress(struct connectdata *conn, int sockfd,
/*
* Called from transfer.c:done_sending when we stop HTTP/3 uploading.
*/
-CURLcode Curl_quic_done_sending(struct connectdata *conn)
+CURLcode Curl_quic_done_sending(struct Curl_easy *data)
{
+ struct connectdata *conn = data->conn;
+ DEBUGASSERT(conn);
if(conn->handler == &Curl_handler_http3) {
/* only for HTTP/3 transfers */
- struct HTTP *stream = conn->data->req.protop;
+ struct HTTP *stream = data->req.p.http;
struct quicsocket *qs = conn->quic;
stream->upload_done = TRUE;
(void)nghttp3_conn_resume_stream(qs->h3conn, stream->stream3_id);
@@ -1926,7 +1907,7 @@ void Curl_quic_done(struct Curl_easy *data, bool premature)
(void)premature;
if(data->conn->handler == &Curl_handler_http3) {
/* only for HTTP/3 transfers */
- struct HTTP *stream = data->req.protop;
+ struct HTTP *stream = data->req.p.http;
Curl_dyn_free(&stream->overflow);
}
}
@@ -1941,7 +1922,7 @@ bool Curl_quic_data_pending(const struct Curl_easy *data)
buffer and allocated an overflow buffer. Since it's possible that
there's no more data coming on the socket, we need to keep reading
until the overflow buffer is empty. */
- const struct HTTP *stream = data->req.protop;
+ const struct HTTP *stream = data->req.p.http;
return Curl_dyn_len(&stream->overflow) > 0;
}
diff --git a/Utilities/cmcurl/lib/vquic/ngtcp2.h b/Utilities/cmcurl/lib/vquic/ngtcp2.h
index afdd01b7c..cbede4514 100644
--- a/Utilities/cmcurl/lib/vquic/ngtcp2.h
+++ b/Utilities/cmcurl/lib/vquic/ngtcp2.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -48,6 +48,7 @@ struct quicsocket {
ngtcp2_cid scid;
uint32_t version;
ngtcp2_settings settings;
+ ngtcp2_transport_params transport_params;
#ifdef USE_OPENSSL
SSL_CTX *sslctx;
SSL *ssl;
@@ -58,11 +59,11 @@ struct quicsocket {
struct quic_handshake crypto_data[3];
/* the last TLS alert description generated by the local endpoint */
uint8_t tls_alert;
- struct sockaddr local_addr;
+ struct sockaddr_storage local_addr;
socklen_t local_addrlen;
nghttp3_conn *h3conn;
- nghttp3_conn_settings h3settings;
+ nghttp3_settings h3settings;
int qlogfd;
};
diff --git a/Utilities/cmcurl/lib/vquic/quiche.c b/Utilities/cmcurl/lib/vquic/quiche.c
index fd9cb8bd3..d138dd3a2 100644
--- a/Utilities/cmcurl/lib/vquic/quiche.c
+++ b/Utilities/cmcurl/lib/vquic/quiche.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -53,21 +53,22 @@
#define QUIC_MAX_DATA (1*1024*1024)
#define QUIC_IDLE_TIMEOUT (60 * 1000) /* milliseconds */
-static CURLcode process_ingress(struct connectdata *conn,
+static CURLcode process_ingress(struct Curl_easy *data,
curl_socket_t sockfd,
struct quicsocket *qs);
-static CURLcode flush_egress(struct connectdata *conn, curl_socket_t sockfd,
+static CURLcode flush_egress(struct Curl_easy *data, curl_socket_t sockfd,
struct quicsocket *qs);
-static CURLcode http_request(struct connectdata *conn, const void *mem,
+static CURLcode http_request(struct Curl_easy *data, const void *mem,
size_t len);
static Curl_recv h3_stream_recv;
static Curl_send h3_stream_send;
-static int quiche_getsock(struct connectdata *conn, curl_socket_t *socks)
+static int quiche_getsock(struct Curl_easy *data,
+ struct connectdata *conn, curl_socket_t *socks)
{
- struct SingleRequest *k = &conn->data->req;
+ struct SingleRequest *k = &data->req;
int bitmap = GETSOCK_BLANK;
socks[0] = conn->sock[FIRSTSOCKET];
@@ -83,14 +84,18 @@ static int quiche_getsock(struct connectdata *conn, curl_socket_t *socks)
return bitmap;
}
-static int quiche_perform_getsock(const struct connectdata *conn,
- curl_socket_t *socks)
-{
- return quiche_getsock((struct connectdata *)conn, socks);
-}
-
-static CURLcode qs_disconnect(struct quicsocket *qs)
+static CURLcode qs_disconnect(struct Curl_easy *data,
+ struct quicsocket *qs)
{
+ DEBUGASSERT(qs);
+ if(qs->conn) {
+ (void)quiche_conn_close(qs->conn, TRUE, 0, NULL, 0);
+ /* flushing the egress is not a failsafe way to deliver all the
+ outstanding packets, but we also don't want to get stuck here... */
+ (void)flush_egress(data, qs->sockfd, qs);
+ quiche_conn_free(qs->conn);
+ qs->conn = NULL;
+ }
if(qs->h3config)
quiche_h3_config_free(qs->h3config);
if(qs->h3c)
@@ -99,41 +104,41 @@ static CURLcode qs_disconnect(struct quicsocket *qs)
quiche_config_free(qs->cfg);
qs->cfg = NULL;
}
- if(qs->conn) {
- quiche_conn_free(qs->conn);
- qs->conn = NULL;
- }
return CURLE_OK;
}
-static CURLcode quiche_disconnect(struct connectdata *conn,
+static CURLcode quiche_disconnect(struct Curl_easy *data,
+ struct connectdata *conn,
bool dead_connection)
{
struct quicsocket *qs = conn->quic;
(void)dead_connection;
- return qs_disconnect(qs);
+ return qs_disconnect(data, qs);
}
-void Curl_quic_disconnect(struct connectdata *conn,
+void Curl_quic_disconnect(struct Curl_easy *data,
+ struct connectdata *conn,
int tempindex)
{
if(conn->transport == TRNSPRT_QUIC)
- qs_disconnect(&conn->hequic[tempindex]);
+ qs_disconnect(data, &conn->hequic[tempindex]);
}
-static unsigned int quiche_conncheck(struct connectdata *conn,
+static unsigned int quiche_conncheck(struct Curl_easy *data,
+ struct connectdata *conn,
unsigned int checks_to_perform)
{
+ (void)data;
(void)conn;
(void)checks_to_perform;
return CONNRESULT_NONE;
}
-static CURLcode quiche_do(struct connectdata *conn, bool *done)
+static CURLcode quiche_do(struct Curl_easy *data, bool *done)
{
- struct HTTP *stream = conn->data->req.protop;
+ struct HTTP *stream = data->req.p.http;
stream->h3req = FALSE; /* not sent */
- return Curl_http(conn, done);
+ return Curl_http(data, done);
}
static const struct Curl_handler Curl_handler_http3 = {
@@ -148,12 +153,13 @@ static const struct Curl_handler Curl_handler_http3 = {
quiche_getsock, /* proto_getsock */
quiche_getsock, /* doing_getsock */
ZERO_NULL, /* domore_getsock */
- quiche_perform_getsock, /* perform_getsock */
+ quiche_getsock, /* perform_getsock */
quiche_disconnect, /* disconnect */
ZERO_NULL, /* readwrite */
quiche_conncheck, /* connection_check */
PORT_HTTP, /* defport */
CURLPROTO_HTTPS, /* protocol */
+ CURLPROTO_HTTP, /* family */
PROTOPT_SSL | PROTOPT_STREAM /* flags */
};
@@ -165,14 +171,16 @@ static void quiche_debug_log(const char *line, void *argp)
}
#endif
-CURLcode Curl_quic_connect(struct connectdata *conn, curl_socket_t sockfd,
+CURLcode Curl_quic_connect(struct Curl_easy *data,
+ struct connectdata *conn, curl_socket_t sockfd,
int sockindex,
const struct sockaddr *addr, socklen_t addrlen)
{
CURLcode result;
struct quicsocket *qs = &conn->hequic[sockindex];
- struct Curl_easy *data = conn->data;
char *keylog_file = NULL;
+ char ipbuf[40];
+ long port;
#ifdef DEBUG_QUICHE
/* initialize debug log callback only once */
@@ -186,6 +194,7 @@ CURLcode Curl_quic_connect(struct connectdata *conn, curl_socket_t sockfd,
(void)addr;
(void)addrlen;
+ qs->sockfd = sockfd;
qs->cfg = quiche_config_new(QUICHE_PROTOCOL_VERSION);
if(!qs->cfg) {
failf(data, "can't create quiche config");
@@ -236,20 +245,22 @@ CURLcode Curl_quic_connect(struct connectdata *conn, curl_socket_t sockfd,
}
#endif
- result = flush_egress(conn, sockfd, qs);
+ result = flush_egress(data, sockfd, qs);
if(result)
return result;
- /* store the used address as a string */
- if(!Curl_addr2string((struct sockaddr*)addr, addrlen,
- conn->primary_ip, &conn->primary_port)) {
+ /* extract the used address as a string */
+ if(!Curl_addr2string((struct sockaddr*)addr, addrlen, ipbuf, &port)) {
char buffer[STRERROR_LEN];
failf(data, "ssrem inet_ntop() failed with errno %d: %s",
SOCKERRNO, Curl_strerror(SOCKERRNO, buffer, sizeof(buffer)));
return CURLE_BAD_FUNCTION_ARGUMENT;
}
- memcpy(conn->ip_addr_str, conn->primary_ip, MAX_IPADR_LEN);
- Curl_persistconninfo(conn);
+
+ infof(data, "Connect socket %d over QUIC to %s:%ld\n",
+ sockfd, ipbuf, port);
+
+ Curl_persistconninfo(data, conn, NULL, -1);
/* for connection reuse purposes: */
conn->ssl[FIRSTSOCKET].state = ssl_connection_complete;
@@ -313,38 +324,39 @@ static CURLcode quiche_has_connected(struct connectdata *conn,
/*
* This function gets polled to check if this QUIC connection has connected.
*/
-CURLcode Curl_quic_is_connected(struct connectdata *conn, int sockindex,
+CURLcode Curl_quic_is_connected(struct Curl_easy *data,
+ struct connectdata *conn,
+ int sockindex,
bool *done)
{
CURLcode result;
struct quicsocket *qs = &conn->hequic[sockindex];
curl_socket_t sockfd = conn->tempsock[sockindex];
- result = process_ingress(conn, sockfd, qs);
+ result = process_ingress(data, sockfd, qs);
if(result)
goto error;
- result = flush_egress(conn, sockfd, qs);
+ result = flush_egress(data, sockfd, qs);
if(result)
goto error;
if(quiche_conn_is_established(qs->conn)) {
*done = TRUE;
result = quiche_has_connected(conn, 0, sockindex);
- DEBUGF(infof(conn->data, "quiche established connection!\n"));
+ DEBUGF(infof(data, "quiche established connection!\n"));
}
return result;
error:
- qs_disconnect(qs);
+ qs_disconnect(data, qs);
return result;
}
-static CURLcode process_ingress(struct connectdata *conn, int sockfd,
+static CURLcode process_ingress(struct Curl_easy *data, int sockfd,
struct quicsocket *qs)
{
ssize_t recvd;
- struct Curl_easy *data = conn->data;
uint8_t *buf = (uint8_t *)data->state.buffer;
size_t bufsize = data->set.buffer_size;
@@ -357,7 +369,7 @@ static CURLcode process_ingress(struct connectdata *conn, int sockfd,
break;
if(recvd < 0) {
- failf(conn->data, "quiche: recv() unexpectedly returned %d "
+ failf(data, "quiche: recv() unexpectedly returned %zd "
"(errno: %d, socket %d)", recvd, SOCKERRNO, sockfd);
return CURLE_RECV_ERROR;
}
@@ -367,7 +379,7 @@ static CURLcode process_ingress(struct connectdata *conn, int sockfd,
break;
if(recvd < 0) {
- failf(conn->data, "quiche_conn_recv() == %d", recvd);
+ failf(data, "quiche_conn_recv() == %zd", recvd);
return CURLE_RECV_ERROR;
}
} while(1);
@@ -379,11 +391,11 @@ static CURLcode process_ingress(struct connectdata *conn, int sockfd,
* flush_egress drains the buffers and sends off data.
* Calls failf() on errors.
*/
-static CURLcode flush_egress(struct connectdata *conn, int sockfd,
+static CURLcode flush_egress(struct Curl_easy *data, int sockfd,
struct quicsocket *qs)
{
ssize_t sent;
- static uint8_t out[1200];
+ uint8_t out[1200];
int64_t timeout_ns;
do {
@@ -392,14 +404,13 @@ static CURLcode flush_egress(struct connectdata *conn, int sockfd,
break;
if(sent < 0) {
- failf(conn->data, "quiche_conn_send returned %zd\n",
- sent);
+ failf(data, "quiche_conn_send returned %zd", sent);
return CURLE_SEND_ERROR;
}
sent = send(sockfd, out, sent, 0);
if(sent < 0) {
- failf(conn->data, "send() returned %zd\n", sent);
+ failf(data, "send() returned %zd", sent);
return CURLE_SEND_ERROR;
}
} while(1);
@@ -408,7 +419,7 @@ static CURLcode flush_egress(struct connectdata *conn, int sockfd,
timeout_ns = quiche_conn_timeout_as_nanos(qs->conn);
if(timeout_ns)
/* expire uses milliseconds */
- Curl_expire(conn->data, (timeout_ns + 999999) / 1000000, EXPIRE_QUIC);
+ Curl_expire(data, (timeout_ns + 999999) / 1000000, EXPIRE_QUIC);
return CURLE_OK;
}
@@ -446,7 +457,7 @@ static int cb_each_header(uint8_t *name, size_t name_len,
return 0;
}
-static ssize_t h3_stream_recv(struct connectdata *conn,
+static ssize_t h3_stream_recv(struct Curl_easy *data,
int sockindex,
char *buf,
size_t buffersize,
@@ -454,18 +465,18 @@ static ssize_t h3_stream_recv(struct connectdata *conn,
{
ssize_t recvd = -1;
ssize_t rcode;
+ struct connectdata *conn = data->conn;
struct quicsocket *qs = conn->quic;
curl_socket_t sockfd = conn->sock[sockindex];
quiche_h3_event *ev;
int rc;
struct h3h1header headers;
- struct Curl_easy *data = conn->data;
- struct HTTP *stream = data->req.protop;
+ struct HTTP *stream = data->req.p.http;
headers.dest = buf;
headers.destlen = buffersize;
headers.nlen = 0;
- if(process_ingress(conn, sockfd, qs)) {
+ if(process_ingress(data, sockfd, qs)) {
infof(data, "h3_stream_recv returns on ingress\n");
*curlcode = CURLE_RECV_ERROR;
return -1;
@@ -525,7 +536,7 @@ static ssize_t h3_stream_recv(struct connectdata *conn,
quiche_h3_event_free(ev);
}
- if(flush_egress(conn, sockfd, qs)) {
+ if(flush_egress(data, sockfd, qs)) {
*curlcode = CURLE_SEND_ERROR;
return -1;
}
@@ -539,19 +550,20 @@ static ssize_t h3_stream_recv(struct connectdata *conn,
return recvd;
}
-static ssize_t h3_stream_send(struct connectdata *conn,
+static ssize_t h3_stream_send(struct Curl_easy *data,
int sockindex,
const void *mem,
size_t len,
CURLcode *curlcode)
{
ssize_t sent;
+ struct connectdata *conn = data->conn;
struct quicsocket *qs = conn->quic;
curl_socket_t sockfd = conn->sock[sockindex];
- struct HTTP *stream = conn->data->req.protop;
+ struct HTTP *stream = data->req.p.http;
if(!stream->h3req) {
- CURLcode result = http_request(conn, mem, len);
+ CURLcode result = http_request(data, mem, len);
if(result) {
*curlcode = CURLE_SEND_ERROR;
return -1;
@@ -559,8 +571,7 @@ static ssize_t h3_stream_send(struct connectdata *conn,
sent = len;
}
else {
- H3BUGF(infof(conn->data, "Pass on %zd body bytes to quiche\n",
- len));
+ H3BUGF(infof(data, "Pass on %zd body bytes to quiche\n", len));
sent = quiche_h3_send_body(qs->h3c, qs->conn, stream->stream3_id,
(uint8_t *)mem, len, FALSE);
if(sent < 0) {
@@ -569,7 +580,7 @@ static ssize_t h3_stream_send(struct connectdata *conn,
}
}
- if(flush_egress(conn, sockfd, qs)) {
+ if(flush_egress(data, sockfd, qs)) {
*curlcode = CURLE_SEND_ERROR;
return -1;
}
@@ -591,12 +602,13 @@ int Curl_quic_ver(char *p, size_t len)
field list. */
#define AUTHORITY_DST_IDX 3
-static CURLcode http_request(struct connectdata *conn, const void *mem,
+static CURLcode http_request(struct Curl_easy *data, const void *mem,
size_t len)
{
/*
*/
- struct HTTP *stream = conn->data->req.protop;
+ struct connectdata *conn = data->conn;
+ struct HTTP *stream = data->req.p.http;
size_t nheader;
size_t i;
size_t authority_idx;
@@ -606,7 +618,6 @@ static CURLcode http_request(struct connectdata *conn, const void *mem,
quiche_h3_header *nva = NULL;
struct quicsocket *qs = conn->quic;
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
stream->h3req = TRUE; /* senf off! */
@@ -761,7 +772,7 @@ static CURLcode http_request(struct connectdata *conn, const void *mem,
if(acc > MAX_ACC) {
infof(data, "http_request: Warning: The cumulative length of all "
- "headers exceeds %zu bytes and that could cause the "
+ "headers exceeds %d bytes and that could cause the "
"stream to be rejected.\n", MAX_ACC);
}
}
@@ -819,14 +830,15 @@ fail:
/*
* Called from transfer.c:done_sending when we stop HTTP/3 uploading.
*/
-CURLcode Curl_quic_done_sending(struct connectdata *conn)
+CURLcode Curl_quic_done_sending(struct Curl_easy *data)
{
+ struct connectdata *conn = data->conn;
+ DEBUGASSERT(conn);
if(conn->handler == &Curl_handler_http3) {
/* only for HTTP/3 transfers */
ssize_t sent;
- struct HTTP *stream = conn->data->req.protop;
+ struct HTTP *stream = data->req.p.http;
struct quicsocket *qs = conn->quic;
- fprintf(stderr, "!!! Curl_quic_done_sending\n");
stream->upload_done = TRUE;
sent = quiche_h3_send_body(qs->h3c, qs->conn, stream->stream3_id,
NULL, 0, TRUE);
diff --git a/Utilities/cmcurl/lib/vquic/quiche.h b/Utilities/cmcurl/lib/vquic/quiche.h
index c8d1837b5..d311e9988 100644
--- a/Utilities/cmcurl/lib/vquic/quiche.h
+++ b/Utilities/cmcurl/lib/vquic/quiche.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
@@ -41,6 +41,7 @@ struct quicsocket {
quiche_h3_conn *h3c;
quiche_h3_config *h3config;
uint8_t scid[QUICHE_MAX_CONN_ID_LEN];
+ curl_socket_t sockfd;
uint32_t version;
};
diff --git a/Utilities/cmcurl/lib/vquic/vquic.c b/Utilities/cmcurl/lib/vquic/vquic.c
index aae8e0951..7c0cc6df2 100644
--- a/Utilities/cmcurl/lib/vquic/vquic.c
+++ b/Utilities/cmcurl/lib/vquic/vquic.c
@@ -9,7 +9,7 @@
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/vquic/vquic.h b/Utilities/cmcurl/lib/vquic/vquic.h
index ecff0edf4..eb8a893d9 100644
--- a/Utilities/cmcurl/lib/vquic/vquic.h
+++ b/Utilities/cmcurl/lib/vquic/vquic.h
@@ -11,7 +11,7 @@
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/vssh/libssh.c b/Utilities/cmcurl/lib/vssh/libssh.c
index 8988e2392..08896ab5b 100644
--- a/Utilities/cmcurl/lib/vssh/libssh.c
+++ b/Utilities/cmcurl/lib/vssh/libssh.c
@@ -5,14 +5,14 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2017 - 2020 Red Hat, Inc.
+ * Copyright (C) 2017 - 2021 Red Hat, Inc.
*
* Authors: Nikos Mavrogiannopoulos, Tomas Mraz, Stanislav Zidek,
* Robert Kolcun, Andreas Schneider
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -107,34 +107,37 @@
#endif
/* Local functions: */
-static CURLcode myssh_connect(struct connectdata *conn, bool *done);
-static CURLcode myssh_multi_statemach(struct connectdata *conn,
+static CURLcode myssh_connect(struct Curl_easy *data, bool *done);
+static CURLcode myssh_multi_statemach(struct Curl_easy *data,
bool *done);
-static CURLcode myssh_do_it(struct connectdata *conn, bool *done);
+static CURLcode myssh_do_it(struct Curl_easy *data, bool *done);
-static CURLcode scp_done(struct connectdata *conn,
+static CURLcode scp_done(struct Curl_easy *data,
CURLcode, bool premature);
-static CURLcode scp_doing(struct connectdata *conn, bool *dophase_done);
-static CURLcode scp_disconnect(struct connectdata *conn,
+static CURLcode scp_doing(struct Curl_easy *data, bool *dophase_done);
+static CURLcode scp_disconnect(struct Curl_easy *data,
+ struct connectdata *conn,
bool dead_connection);
-static CURLcode sftp_done(struct connectdata *conn,
+static CURLcode sftp_done(struct Curl_easy *data,
CURLcode, bool premature);
-static CURLcode sftp_doing(struct connectdata *conn,
+static CURLcode sftp_doing(struct Curl_easy *data,
bool *dophase_done);
-static CURLcode sftp_disconnect(struct connectdata *conn, bool dead);
+static CURLcode sftp_disconnect(struct Curl_easy *data,
+ struct connectdata *conn,
+ bool dead);
static
-CURLcode sftp_perform(struct connectdata *conn,
+CURLcode sftp_perform(struct Curl_easy *data,
bool *connected,
bool *dophase_done);
-static void sftp_quote(struct connectdata *conn);
-static void sftp_quote_stat(struct connectdata *conn);
-static int myssh_getsock(struct connectdata *conn, curl_socket_t *sock);
-static int myssh_perform_getsock(const struct connectdata *conn,
- curl_socket_t *sock);
+static void sftp_quote(struct Curl_easy *data);
+static void sftp_quote_stat(struct Curl_easy *data);
+static int myssh_getsock(struct Curl_easy *data,
+ struct connectdata *conn, curl_socket_t *sock);
-static CURLcode myssh_setup_connection(struct connectdata *conn);
+static CURLcode myssh_setup_connection(struct Curl_easy *data,
+ struct connectdata *conn);
/*
* SCP protocol handler.
@@ -152,12 +155,13 @@ const struct Curl_handler Curl_handler_scp = {
myssh_getsock, /* proto_getsock */
myssh_getsock, /* doing_getsock */
ZERO_NULL, /* domore_getsock */
- myssh_perform_getsock, /* perform_getsock */
+ myssh_getsock, /* perform_getsock */
scp_disconnect, /* disconnect */
ZERO_NULL, /* readwrite */
ZERO_NULL, /* connection_check */
PORT_SSH, /* defport */
CURLPROTO_SCP, /* protocol */
+ CURLPROTO_SCP, /* family */
PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION | PROTOPT_NOURLQUERY /* flags */
};
@@ -177,12 +181,13 @@ const struct Curl_handler Curl_handler_sftp = {
myssh_getsock, /* proto_getsock */
myssh_getsock, /* doing_getsock */
ZERO_NULL, /* domore_getsock */
- myssh_perform_getsock, /* perform_getsock */
+ myssh_getsock, /* perform_getsock */
sftp_disconnect, /* disconnect */
ZERO_NULL, /* readwrite */
ZERO_NULL, /* connection_check */
PORT_SSH, /* defport */
CURLPROTO_SFTP, /* protocol */
+ CURLPROTO_SFTP, /* family */
PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION
| PROTOPT_NOURLQUERY /* flags */
};
@@ -221,12 +226,13 @@ static CURLcode sftp_error_to_CURLE(int err)
* SSH State machine related code
*/
/* This is the ONLY way to change SSH state! */
-static void mystate(struct connectdata *conn, sshstate nowstate
+static void mystate(struct Curl_easy *data, sshstate nowstate
#ifdef DEBUGBUILD
, 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 */
@@ -295,7 +301,7 @@ static void mystate(struct connectdata *conn, sshstate nowstate
if(sshc->state != nowstate) {
- infof(conn->data, "SSH %p state change from %s to %s (line %d)\n",
+ infof(data, "SSH %p state change from %s to %s (line %d)\n",
(void *) sshc, names[sshc->state], names[nowstate],
lineno);
}
@@ -314,10 +320,10 @@ static void mystate(struct connectdata *conn, sshstate nowstate
*
* Returns SSH_OK or SSH_ERROR.
*/
-static int myssh_is_known(struct connectdata *conn)
+static int myssh_is_known(struct Curl_easy *data)
{
int rc;
- struct Curl_easy *data = conn->data;
+ struct connectdata *conn = data->conn;
struct ssh_conn *sshc = &conn->proto.sshc;
ssh_key pubkey;
size_t hlen;
@@ -527,10 +533,10 @@ static int myssh_is_known(struct connectdata *conn)
cleanup:
if(found_base64) {
- free(found_base64);
+ (free)(found_base64);
}
if(known_base64) {
- free(known_base64);
+ (free)(known_base64);
}
if(hash)
ssh_clean_pubkey_hash(&hash);
@@ -544,14 +550,14 @@ cleanup:
}
#define MOVE_TO_ERROR_STATE(_r) { \
- state(conn, SSH_SESSION_DISCONNECT); \
+ state(data, SSH_SESSION_DISCONNECT); \
sshc->actualcode = _r; \
rc = SSH_ERROR; \
break; \
}
#define MOVE_TO_SFTP_CLOSE_STATE() { \
- state(conn, SSH_SFTP_CLOSE); \
+ state(data, SSH_SFTP_CLOSE); \
sshc->actualcode = sftp_error_to_CURLE(sftp_get_error(sshc->sftp_session)); \
rc = SSH_ERROR; \
break; \
@@ -560,7 +566,7 @@ cleanup:
#define MOVE_TO_LAST_AUTH \
if(sshc->auth_methods & SSH_AUTH_METHOD_PASSWORD) { \
rc = SSH_OK; \
- state(conn, SSH_AUTH_PASS_INIT); \
+ state(data, SSH_AUTH_PASS_INIT); \
break; \
} \
else { \
@@ -570,7 +576,7 @@ cleanup:
#define MOVE_TO_TERTIARY_AUTH \
if(sshc->auth_methods & SSH_AUTH_METHOD_INTERACTIVE) { \
rc = SSH_OK; \
- state(conn, SSH_AUTH_KEY_INIT); \
+ state(data, SSH_AUTH_KEY_INIT); \
break; \
} \
else { \
@@ -580,7 +586,7 @@ cleanup:
#define MOVE_TO_SECONDARY_AUTH \
if(sshc->auth_methods & SSH_AUTH_METHOD_GSSAPI_MIC) { \
rc = SSH_OK; \
- state(conn, SSH_AUTH_GSSAPI); \
+ state(data, SSH_AUTH_GSSAPI); \
break; \
} \
else { \
@@ -658,11 +664,11 @@ restart:
* 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 connectdata *conn, bool *block)
+static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
- struct SSHPROTO *protop = data->req.protop;
+ 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;
@@ -687,7 +693,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
non-blocking */
ssh_set_blocking(sshc->ssh_session, 0);
- state(conn, SSH_S_STARTUP);
+ state(data, SSH_S_STARTUP);
/* FALLTHROUGH */
case SSH_S_STARTUP:
@@ -700,17 +706,17 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
MOVE_TO_ERROR_STATE(CURLE_FAILED_INIT);
}
- state(conn, SSH_HOSTKEY);
+ state(data, SSH_HOSTKEY);
/* FALLTHROUGH */
case SSH_HOSTKEY:
- rc = myssh_is_known(conn);
+ rc = myssh_is_known(data);
if(rc != SSH_OK) {
MOVE_TO_ERROR_STATE(CURLE_PEER_FAILED_VERIFICATION);
}
- state(conn, SSH_AUTHLIST);
+ state(data, SSH_AUTHLIST);
/* FALLTHROUGH */
case SSH_AUTHLIST:{
sshc->authed = FALSE;
@@ -724,7 +730,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
if(rc == SSH_AUTH_SUCCESS) {
sshc->authed = TRUE;
infof(data, "Authenticated with none\n");
- state(conn, SSH_AUTH_DONE);
+ state(data, SSH_AUTH_DONE);
break;
}
else if(rc == SSH_AUTH_ERROR) {
@@ -733,17 +739,17 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
sshc->auth_methods = ssh_userauth_list(sshc->ssh_session, NULL);
if(sshc->auth_methods & SSH_AUTH_METHOD_PUBLICKEY) {
- state(conn, SSH_AUTH_PKEY_INIT);
+ state(data, SSH_AUTH_PKEY_INIT);
infof(data, "Authentication using SSH public key file\n");
}
else if(sshc->auth_methods & SSH_AUTH_METHOD_GSSAPI_MIC) {
- state(conn, SSH_AUTH_GSSAPI);
+ state(data, SSH_AUTH_GSSAPI);
}
else if(sshc->auth_methods & SSH_AUTH_METHOD_INTERACTIVE) {
- state(conn, SSH_AUTH_KEY_INIT);
+ state(data, SSH_AUTH_KEY_INIT);
}
else if(sshc->auth_methods & SSH_AUTH_METHOD_PASSWORD) {
- state(conn, SSH_AUTH_PASS_INIT);
+ state(data, SSH_AUTH_PASS_INIT);
}
else { /* unsupported authentication method */
MOVE_TO_ERROR_STATE(CURLE_LOGIN_DENIED);
@@ -783,7 +789,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
break;
}
- state(conn, SSH_AUTH_PKEY);
+ state(data, SSH_AUTH_PKEY);
break;
}
@@ -798,7 +804,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
rc = SSH_OK;
sshc->authed = TRUE;
infof(data, "Completed public key authentication\n");
- state(conn, SSH_AUTH_DONE);
+ state(data, SSH_AUTH_DONE);
break;
}
@@ -815,7 +821,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
if(rc == SSH_AUTH_SUCCESS) {
sshc->authed = TRUE;
infof(data, "Completed public key authentication\n");
- state(conn, SSH_AUTH_DONE);
+ state(data, SSH_AUTH_DONE);
break;
}
else {
@@ -839,7 +845,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
rc = SSH_OK;
sshc->authed = TRUE;
infof(data, "Completed gssapi authentication\n");
- state(conn, SSH_AUTH_DONE);
+ state(data, SSH_AUTH_DONE);
break;
}
@@ -848,7 +854,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
case SSH_AUTH_KEY_INIT:
if(data->set.ssh_auth_types & CURLSSH_AUTH_KEYBOARD) {
- state(conn, SSH_AUTH_KEY);
+ state(data, SSH_AUTH_KEY);
}
else {
MOVE_TO_LAST_AUTH;
@@ -866,7 +872,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
sshc->authed = TRUE;
infof(data, "completed keyboard interactive authentication\n");
}
- state(conn, SSH_AUTH_DONE);
+ state(data, SSH_AUTH_DONE);
break;
case SSH_AUTH_PASS_INIT:
@@ -874,7 +880,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
/* Host key authentication is intentionally not implemented */
MOVE_TO_ERROR_STATE(CURLE_LOGIN_DENIED);
}
- state(conn, SSH_AUTH_PASS);
+ state(data, SSH_AUTH_PASS);
/* FALLTHROUGH */
case SSH_AUTH_PASS:
@@ -887,7 +893,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
if(rc == SSH_AUTH_SUCCESS) {
sshc->authed = TRUE;
infof(data, "Completed password authentication\n");
- state(conn, SSH_AUTH_DONE);
+ state(data, SSH_AUTH_DONE);
}
else {
MOVE_TO_ERROR_STATE(CURLE_LOGIN_DENIED);
@@ -906,17 +912,17 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
*/
infof(data, "Authentication complete\n");
- Curl_pgrsTime(conn->data, TIMER_APPCONNECT); /* SSH is connected */
+ Curl_pgrsTime(data, TIMER_APPCONNECT); /* SSH is connected */
conn->sockfd = sock;
conn->writesockfd = CURL_SOCKET_BAD;
if(conn->handler->protocol == CURLPROTO_SFTP) {
- state(conn, SSH_SFTP_INIT);
+ state(data, SSH_SFTP_INIT);
break;
}
infof(data, "SSH CONNECT phase done\n");
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
break;
case SSH_SFTP_INIT:
@@ -938,7 +944,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
MOVE_TO_ERROR_STATE(sftp_error_to_CURLE(rc));
break;
}
- state(conn, SSH_SFTP_REALPATH);
+ state(data, SSH_SFTP_REALPATH);
/* FALLTHROUGH */
case SSH_SFTP_REALPATH:
/*
@@ -948,32 +954,31 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
if(sshc->homedir == NULL) {
MOVE_TO_ERROR_STATE(CURLE_COULDNT_CONNECT);
}
- conn->data->state.most_recent_ftp_entrypath = sshc->homedir;
+ data->state.most_recent_ftp_entrypath = sshc->homedir;
/* 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\n"));
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
break;
case SSH_SFTP_QUOTE_INIT:
-
- result = Curl_getworkingpath(conn, sshc->homedir, &protop->path);
+ result = Curl_getworkingpath(data, sshc->homedir, &protop->path);
if(result) {
sshc->actualcode = result;
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
break;
}
if(data->set.quote) {
infof(data, "Sending quote commands\n");
sshc->quote_item = data->set.quote;
- state(conn, SSH_SFTP_QUOTE);
+ state(data, SSH_SFTP_QUOTE);
}
else {
- state(conn, SSH_SFTP_GETINFO);
+ state(data, SSH_SFTP_GETINFO);
}
break;
@@ -981,16 +986,16 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
if(data->set.postquote) {
infof(data, "Sending quote commands\n");
sshc->quote_item = data->set.postquote;
- state(conn, SSH_SFTP_QUOTE);
+ state(data, SSH_SFTP_QUOTE);
}
else {
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
}
break;
case SSH_SFTP_QUOTE:
/* Send any quote commands */
- sftp_quote(conn);
+ sftp_quote(data);
break;
case SSH_SFTP_NEXT_QUOTE:
@@ -1000,21 +1005,21 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
sshc->quote_item = sshc->quote_item->next;
if(sshc->quote_item) {
- state(conn, SSH_SFTP_QUOTE);
+ state(data, SSH_SFTP_QUOTE);
}
else {
if(sshc->nextstate != SSH_NO_STATE) {
- state(conn, sshc->nextstate);
+ state(data, sshc->nextstate);
sshc->nextstate = SSH_NO_STATE;
}
else {
- state(conn, SSH_SFTP_GETINFO);
+ state(data, SSH_SFTP_GETINFO);
}
}
break;
case SSH_SFTP_QUOTE_STAT:
- sftp_quote_stat(conn);
+ sftp_quote_stat(data);
break;
case SSH_SFTP_QUOTE_SETSTAT:
@@ -1025,7 +1030,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
Curl_safefree(sshc->quote_path2);
failf(data, "Attempt to set SFTP stats failed: %s",
ssh_get_error(sshc->ssh_session));
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = CURLE_QUOTE_ERROR;
/* sshc->actualcode = sftp_error_to_CURLE(err);
@@ -1033,7 +1038,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
* the error the libssh2 backend is returning */
break;
}
- state(conn, SSH_SFTP_NEXT_QUOTE);
+ state(data, SSH_SFTP_NEXT_QUOTE);
break;
case SSH_SFTP_QUOTE_SYMLINK:
@@ -1044,12 +1049,12 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
Curl_safefree(sshc->quote_path2);
failf(data, "symlink command failed: %s",
ssh_get_error(sshc->ssh_session));
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = CURLE_QUOTE_ERROR;
break;
}
- state(conn, SSH_SFTP_NEXT_QUOTE);
+ state(data, SSH_SFTP_NEXT_QUOTE);
break;
case SSH_SFTP_QUOTE_MKDIR:
@@ -1059,12 +1064,12 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
Curl_safefree(sshc->quote_path1);
failf(data, "mkdir command failed: %s",
ssh_get_error(sshc->ssh_session));
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = CURLE_QUOTE_ERROR;
break;
}
- state(conn, SSH_SFTP_NEXT_QUOTE);
+ state(data, SSH_SFTP_NEXT_QUOTE);
break;
case SSH_SFTP_QUOTE_RENAME:
@@ -1075,12 +1080,12 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
Curl_safefree(sshc->quote_path2);
failf(data, "rename command failed: %s",
ssh_get_error(sshc->ssh_session));
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = CURLE_QUOTE_ERROR;
break;
}
- state(conn, SSH_SFTP_NEXT_QUOTE);
+ state(data, SSH_SFTP_NEXT_QUOTE);
break;
case SSH_SFTP_QUOTE_RMDIR:
@@ -1089,12 +1094,12 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
Curl_safefree(sshc->quote_path1);
failf(data, "rmdir command failed: %s",
ssh_get_error(sshc->ssh_session));
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = CURLE_QUOTE_ERROR;
break;
}
- state(conn, SSH_SFTP_NEXT_QUOTE);
+ state(data, SSH_SFTP_NEXT_QUOTE);
break;
case SSH_SFTP_QUOTE_UNLINK:
@@ -1103,12 +1108,12 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
Curl_safefree(sshc->quote_path1);
failf(data, "rm command failed: %s",
ssh_get_error(sshc->ssh_session));
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = CURLE_QUOTE_ERROR;
break;
}
- state(conn, SSH_SFTP_NEXT_QUOTE);
+ state(data, SSH_SFTP_NEXT_QUOTE);
break;
case SSH_SFTP_QUOTE_STATVFS:
@@ -1120,7 +1125,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
Curl_safefree(sshc->quote_path1);
failf(data, "statvfs command failed: %s",
ssh_get_error(sshc->ssh_session));
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = CURLE_QUOTE_ERROR;
break;
@@ -1143,29 +1148,29 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
if(!tmp) {
result = CURLE_OUT_OF_MEMORY;
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
break;
}
- result = Curl_client_write(conn, CLIENTWRITE_HEADER, tmp, strlen(tmp));
+ result = Curl_client_write(data, CLIENTWRITE_HEADER, tmp, strlen(tmp));
free(tmp);
if(result) {
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = result;
}
}
- state(conn, SSH_SFTP_NEXT_QUOTE);
+ state(data, SSH_SFTP_NEXT_QUOTE);
break;
}
case SSH_SFTP_GETINFO:
if(data->set.get_filetime) {
- state(conn, SSH_SFTP_FILETIME);
+ state(data, SSH_SFTP_FILETIME);
}
else {
- state(conn, SSH_SFTP_TRANS_INIT);
+ state(data, SSH_SFTP_TRANS_INIT);
}
break;
@@ -1179,18 +1184,18 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
sftp_attributes_free(attrs);
}
- state(conn, SSH_SFTP_TRANS_INIT);
+ state(data, SSH_SFTP_TRANS_INIT);
break;
}
case SSH_SFTP_TRANS_INIT:
if(data->set.upload)
- state(conn, SSH_SFTP_UPLOAD_INIT);
+ state(data, SSH_SFTP_UPLOAD_INIT);
else {
if(protop->path[strlen(protop->path)-1] == '/')
- state(conn, SSH_SFTP_READDIR_INIT);
+ state(data, SSH_SFTP_READDIR_INIT);
else
- state(conn, SSH_SFTP_DOWNLOAD_INIT);
+ state(data, SSH_SFTP_DOWNLOAD_INIT);
}
break;
@@ -1226,7 +1231,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
/* If we have restart position then open for append */
flags = O_WRONLY|O_APPEND;
else
- /* Clear file before writing (normal behaviour) */
+ /* Clear file before writing (normal behavior) */
flags = O_WRONLY|O_CREAT|O_TRUNC;
if(sshc->sftp_file)
@@ -1244,7 +1249,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
/* try to create the path remotely */
rc = 0;
sshc->secondCreateDirs = 1;
- state(conn, SSH_SFTP_CREATE_DIRS_INIT);
+ state(data, SSH_SFTP_CREATE_DIRS_INIT);
break;
}
else {
@@ -1327,17 +1332,17 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
timeout here */
Curl_expire(data, 0, EXPIRE_RUN_NOW);
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
break;
}
case SSH_SFTP_CREATE_DIRS_INIT:
if(strlen(protop->path) > 1) {
sshc->slash_pos = protop->path + 1; /* ignore the leading '/' */
- state(conn, SSH_SFTP_CREATE_DIRS);
+ state(data, SSH_SFTP_CREATE_DIRS);
}
else {
- state(conn, SSH_SFTP_UPLOAD_INIT);
+ state(data, SSH_SFTP_UPLOAD_INIT);
}
break;
@@ -1347,10 +1352,10 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
*sshc->slash_pos = 0;
infof(data, "Creating directory '%s'\n", protop->path);
- state(conn, SSH_SFTP_CREATE_DIRS_MKDIR);
+ state(data, SSH_SFTP_CREATE_DIRS_MKDIR);
break;
}
- state(conn, SSH_SFTP_UPLOAD_INIT);
+ state(data, SSH_SFTP_UPLOAD_INIT);
break;
case SSH_SFTP_CREATE_DIRS_MKDIR:
@@ -1373,13 +1378,13 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
}
rc = 0; /* clear rc and continue */
}
- state(conn, SSH_SFTP_CREATE_DIRS);
+ state(data, SSH_SFTP_CREATE_DIRS);
break;
case SSH_SFTP_READDIR_INIT:
Curl_pgrsSetDownloadSize(data, -1);
if(data->set.opt_no_body) {
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
break;
}
@@ -1394,7 +1399,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
ssh_get_error(sshc->ssh_session));
MOVE_TO_SFTP_CLOSE_STATE();
}
- state(conn, SSH_SFTP_READDIR);
+ state(data, SSH_SFTP_READDIR);
break;
case SSH_SFTP_READDIR:
@@ -1413,16 +1418,16 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
tmpLine = aprintf("%s\n", sshc->readdir_filename);
if(tmpLine == NULL) {
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->actualcode = CURLE_OUT_OF_MEMORY;
break;
}
- result = Curl_client_write(conn, CLIENTWRITE_BODY,
+ result = Curl_client_write(data, CLIENTWRITE_BODY,
tmpLine, sshc->readdir_len + 1);
free(tmpLine);
if(result) {
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
break;
}
/* since this counts what we send to the client, we include the
@@ -1430,18 +1435,15 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
data->req.bytecount += sshc->readdir_len + 1;
/* output debug output if that is requested */
- if(data->set.verbose) {
- Curl_debug(data, CURLINFO_DATA_OUT,
- (char *)sshc->readdir_filename,
- sshc->readdir_len);
- }
+ Curl_debug(data, CURLINFO_DATA_OUT, (char *)sshc->readdir_filename,
+ sshc->readdir_len);
}
else {
sshc->readdir_currLen = strlen(sshc->readdir_longentry);
sshc->readdir_totalLen = 80 + sshc->readdir_currLen;
sshc->readdir_line = calloc(sshc->readdir_totalLen, 1);
if(!sshc->readdir_line) {
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->actualcode = CURLE_OUT_OF_MEMORY;
break;
}
@@ -1453,7 +1455,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
S_IFLNK)) {
sshc->readdir_linkPath = malloc(PATH_MAX + 1);
if(sshc->readdir_linkPath == NULL) {
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->actualcode = CURLE_OUT_OF_MEMORY;
break;
}
@@ -1461,15 +1463,15 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
msnprintf(sshc->readdir_linkPath, PATH_MAX, "%s%s", protop->path,
sshc->readdir_filename);
- state(conn, SSH_SFTP_READDIR_LINK);
+ state(data, SSH_SFTP_READDIR_LINK);
break;
}
- state(conn, SSH_SFTP_READDIR_BOTTOM);
+ state(data, SSH_SFTP_READDIR_BOTTOM);
break;
}
}
else if(sftp_dir_eof(sshc->sftp_dir)) {
- state(conn, SSH_SFTP_READDIR_DONE);
+ state(data, SSH_SFTP_READDIR_DONE);
break;
}
else {
@@ -1516,7 +1518,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
sshc->readdir_totalLen);
if(!new_readdir_line) {
sshc->readdir_line = NULL;
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->actualcode = CURLE_OUT_OF_MEMORY;
break;
}
@@ -1534,24 +1536,21 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
sshc->readdir_filename = NULL;
sshc->readdir_longentry = NULL;
- state(conn, SSH_SFTP_READDIR_BOTTOM);
+ state(data, SSH_SFTP_READDIR_BOTTOM);
/* FALLTHROUGH */
case SSH_SFTP_READDIR_BOTTOM:
sshc->readdir_currLen += msnprintf(sshc->readdir_line +
sshc->readdir_currLen,
sshc->readdir_totalLen -
sshc->readdir_currLen, "\n");
- result = Curl_client_write(conn, CLIENTWRITE_BODY,
+ result = Curl_client_write(data, CLIENTWRITE_BODY,
sshc->readdir_line,
sshc->readdir_currLen);
if(!result) {
-
/* output debug output if that is requested */
- if(data->set.verbose) {
- Curl_debug(data, CURLINFO_DATA_OUT, sshc->readdir_line,
- sshc->readdir_currLen);
- }
+ Curl_debug(data, CURLINFO_DATA_OUT, sshc->readdir_line,
+ sshc->readdir_currLen);
data->req.bytecount += sshc->readdir_currLen;
}
Curl_safefree(sshc->readdir_line);
@@ -1559,10 +1558,10 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
sshc->readdir_tmp = NULL;
if(result) {
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
}
else
- state(conn, SSH_SFTP_READDIR);
+ state(data, SSH_SFTP_READDIR);
break;
case SSH_SFTP_READDIR_DONE:
@@ -1571,7 +1570,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
/* no data to transfer */
Curl_setup_transfer(data, -1, -1, FALSE, -1);
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
break;
case SSH_SFTP_DOWNLOAD_INIT:
@@ -1590,7 +1589,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
MOVE_TO_SFTP_CLOSE_STATE();
}
- state(conn, SSH_SFTP_DOWNLOAD_STAT);
+ state(data, SSH_SFTP_DOWNLOAD_STAT);
break;
case SSH_SFTP_DOWNLOAD_STAT:
@@ -1622,14 +1621,14 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
failf(data, "Bad file size (%" CURL_FORMAT_CURL_OFF_T ")", size);
return CURLE_BAD_DOWNLOAD_RESUME;
}
- if(conn->data->state.use_range) {
+ if(data->state.use_range) {
curl_off_t from, to;
char *ptr;
char *ptr2;
CURLofft to_t;
CURLofft from_t;
- from_t = curlx_strtoofft(conn->data->state.range, &ptr, 0, &from);
+ from_t = curlx_strtoofft(data->state.range, &ptr, 0, &from);
if(from_t == CURL_OFFT_FLOW) {
return CURLE_RANGE_ERROR;
}
@@ -1712,7 +1711,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
/* no data to transfer */
Curl_setup_transfer(data, -1, -1, FALSE, -1);
infof(data, "File already completely downloaded\n");
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
break;
}
Curl_setup_transfer(data, FIRSTSOCKET, data->req.size, FALSE, -1);
@@ -1728,12 +1727,12 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
if(result) {
/* this should never occur; the close state should be entered
at the time the error occurs */
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->actualcode = result;
}
else {
sshc->sftp_recv_state = 0;
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
}
break;
@@ -1751,11 +1750,11 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
SSH_SFTP_CLOSE to pass the correct result back */
if(sshc->nextstate != SSH_NO_STATE &&
sshc->nextstate != SSH_SFTP_CLOSE) {
- state(conn, sshc->nextstate);
+ state(data, sshc->nextstate);
sshc->nextstate = SSH_SFTP_CLOSE;
}
else {
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
result = sshc->actualcode;
}
break;
@@ -1776,17 +1775,16 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
}
SSH_STRING_FREE_CHAR(sshc->homedir);
- conn->data->state.most_recent_ftp_entrypath = NULL;
+ data->state.most_recent_ftp_entrypath = NULL;
- state(conn, SSH_SESSION_DISCONNECT);
+ state(data, SSH_SESSION_DISCONNECT);
break;
-
case SSH_SCP_TRANS_INIT:
- result = Curl_getworkingpath(conn, sshc->homedir, &protop->path);
+ result = Curl_getworkingpath(data, sshc->homedir, &protop->path);
if(result) {
sshc->actualcode = result;
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
break;
}
@@ -1802,17 +1800,17 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
sshc->scp_session =
ssh_scp_new(sshc->ssh_session, SSH_SCP_WRITE, protop->path);
- state(conn, SSH_SCP_UPLOAD_INIT);
+ state(data, SSH_SCP_UPLOAD_INIT);
}
else {
sshc->scp_session =
ssh_scp_new(sshc->ssh_session, SSH_SCP_READ, protop->path);
- state(conn, SSH_SCP_DOWNLOAD_INIT);
+ state(data, SSH_SCP_DOWNLOAD_INIT);
}
if(!sshc->scp_session) {
err_msg = ssh_get_error(sshc->ssh_session);
- failf(conn->data, "%s", err_msg);
+ failf(data, "%s", err_msg);
MOVE_TO_ERROR_STATE(CURLE_UPLOAD_FAILED);
}
@@ -1823,7 +1821,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
rc = ssh_scp_init(sshc->scp_session);
if(rc != SSH_OK) {
err_msg = ssh_get_error(sshc->ssh_session);
- failf(conn->data, "%s", err_msg);
+ failf(data, "%s", err_msg);
MOVE_TO_ERROR_STATE(CURLE_UPLOAD_FAILED);
}
@@ -1832,7 +1830,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
(int)data->set.new_file_perms);
if(rc != SSH_OK) {
err_msg = ssh_get_error(sshc->ssh_session);
- failf(conn->data, "%s", err_msg);
+ failf(data, "%s", err_msg);
MOVE_TO_ERROR_STATE(CURLE_UPLOAD_FAILED);
}
@@ -1851,7 +1849,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
with both accordingly */
conn->cselect_bits = CURL_CSELECT_OUT;
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
break;
@@ -1860,10 +1858,10 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
rc = ssh_scp_init(sshc->scp_session);
if(rc != SSH_OK) {
err_msg = ssh_get_error(sshc->ssh_session);
- failf(conn->data, "%s", err_msg);
+ failf(data, "%s", err_msg);
MOVE_TO_ERROR_STATE(CURLE_COULDNT_CONNECT);
}
- state(conn, SSH_SCP_DOWNLOAD);
+ state(data, SSH_SCP_DOWNLOAD);
/* FALLTHROUGH */
case SSH_SCP_DOWNLOAD:{
@@ -1872,7 +1870,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
rc = ssh_scp_pull_request(sshc->scp_session);
if(rc != SSH_SCP_REQUEST_NEWFILE) {
err_msg = ssh_get_error(sshc->ssh_session);
- failf(conn->data, "%s", err_msg);
+ failf(data, "%s", err_msg);
MOVE_TO_ERROR_STATE(CURLE_REMOTE_FILE_NOT_FOUND);
break;
}
@@ -1890,14 +1888,14 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
with both accordingly */
conn->cselect_bits = CURL_CSELECT_IN;
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
break;
}
case SSH_SCP_DONE:
if(data->set.upload)
- state(conn, SSH_SCP_SEND_EOF);
+ state(data, SSH_SCP_SEND_EOF);
else
- state(conn, SSH_SCP_CHANNEL_FREE);
+ state(data, SSH_SCP_CHANNEL_FREE);
break;
case SSH_SCP_SEND_EOF:
@@ -1915,7 +1913,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
}
}
- state(conn, SSH_SCP_CHANNEL_FREE);
+ state(data, SSH_SCP_CHANNEL_FREE);
break;
case SSH_SCP_CHANNEL_FREE:
@@ -1927,7 +1925,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
ssh_set_blocking(sshc->ssh_session, 0);
- state(conn, SSH_SESSION_DISCONNECT);
+ state(data, SSH_SESSION_DISCONNECT);
/* FALLTHROUGH */
case SSH_SESSION_DISCONNECT:
@@ -1942,9 +1940,9 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
ssh_disconnect(sshc->ssh_session);
SSH_STRING_FREE_CHAR(sshc->homedir);
- conn->data->state.most_recent_ftp_entrypath = NULL;
+ data->state.most_recent_ftp_entrypath = NULL;
- state(conn, SSH_SESSION_FREE);
+ state(data, SSH_SESSION_FREE);
/* FALLTHROUGH */
case SSH_SESSION_FREE:
if(sshc->ssh_session) {
@@ -1992,7 +1990,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
connclose(conn, "SSH session free");
sshc->state = SSH_SESSION_FREE; /* current */
sshc->nextstate = SSH_NO_STATE;
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
break;
case SSH_QUIT:
@@ -2000,7 +1998,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
default:
/* internal error */
sshc->nextstate = SSH_NO_STATE;
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
break;
}
@@ -2019,10 +2017,12 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
/* called by the multi interface to figure out what socket(s) to wait for and
for what actions in the DO_DONE, PERFORM and WAITPERFORM states */
-static int myssh_perform_getsock(const struct connectdata *conn,
- curl_socket_t *sock)
+static int myssh_getsock(struct Curl_easy *data,
+ struct connectdata *conn,
+ curl_socket_t *sock)
{
int bitmap = GETSOCK_BLANK;
+ (void)data;
sock[0] = conn->sock[FIRSTSOCKET];
if(conn->waitfor & KEEP_RECV)
@@ -2034,16 +2034,6 @@ static int myssh_perform_getsock(const struct connectdata *conn,
return bitmap;
}
-/* Generic function called by the multi interface to figure out what socket(s)
- to wait for and for what actions during the DOING and PROTOCONNECT states*/
-static int myssh_getsock(struct connectdata *conn,
- curl_socket_t *sock)
-{
- /* if we know the direction we can use the generic *_getsock() function even
- for the protocol_connect and doing states */
- return myssh_perform_getsock(conn, sock);
-}
-
static void myssh_block2waitfor(struct connectdata *conn, bool block)
{
struct ssh_conn *sshc = &conn->proto.sshc;
@@ -2065,13 +2055,14 @@ static void myssh_block2waitfor(struct connectdata *conn, bool block)
}
/* called repeatedly until done from multi.c */
-static CURLcode myssh_multi_statemach(struct connectdata *conn,
+static CURLcode myssh_multi_statemach(struct Curl_easy *data,
bool *done)
{
+ struct connectdata *conn = data->conn;
struct ssh_conn *sshc = &conn->proto.sshc;
bool block; /* we store the status and use that to provide a ssh_getsock()
implementation */
- CURLcode result = myssh_statemach_act(conn, &block);
+ CURLcode result = myssh_statemach_act(data, &block);
*done = (sshc->state == SSH_STOP) ? TRUE : FALSE;
myssh_block2waitfor(conn, block);
@@ -2079,24 +2070,24 @@ static CURLcode myssh_multi_statemach(struct connectdata *conn,
return result;
}
-static CURLcode myssh_block_statemach(struct connectdata *conn,
+static CURLcode myssh_block_statemach(struct Curl_easy *data,
bool disconnect)
{
+ struct connectdata *conn = data->conn;
struct ssh_conn *sshc = &conn->proto.sshc;
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
while((sshc->state != SSH_STOP) && !result) {
bool block;
timediff_t left = 1000;
struct curltime now = Curl_now();
- result = myssh_statemach_act(conn, &block);
+ result = myssh_statemach_act(data, &block);
if(result)
break;
if(!disconnect) {
- if(Curl_pgrsUpdate(conn))
+ if(Curl_pgrsUpdate(data))
return CURLE_ABORTED_BY_CALLBACK;
result = Curl_speedcheck(data, now);
@@ -2125,11 +2116,13 @@ static CURLcode myssh_block_statemach(struct connectdata *conn,
/*
* SSH setup connection
*/
-static CURLcode myssh_setup_connection(struct connectdata *conn)
+static CURLcode myssh_setup_connection(struct Curl_easy *data,
+ struct connectdata *conn)
{
struct SSHPROTO *ssh;
+ (void)conn;
- conn->data->req.protop = ssh = calloc(1, sizeof(struct SSHPROTO));
+ data->req.p.ssh = ssh = calloc(1, sizeof(struct SSHPROTO));
if(!ssh)
return CURLE_OUT_OF_MEMORY;
@@ -2143,17 +2136,17 @@ static Curl_send scp_send, sftp_send;
* Curl_ssh_connect() gets called from Curl_protocol_connect() to allow us to
* do protocol-specific actions at connect-time.
*/
-static CURLcode myssh_connect(struct connectdata *conn, bool *done)
+static CURLcode myssh_connect(struct Curl_easy *data, bool *done)
{
struct ssh_conn *ssh;
CURLcode result;
+ struct connectdata *conn = data->conn;
curl_socket_t sock = conn->sock[FIRSTSOCKET];
- struct Curl_easy *data = conn->data;
int rc;
/* initialize per-handle data if not already */
- if(!data->req.protop)
- myssh_setup_connection(conn);
+ if(!data->req.p.ssh)
+ myssh_setup_connection(data, conn);
/* We default to persistent connections. We set this already in this connect
function to make the re-use checks properly be able to check this bit. */
@@ -2246,22 +2239,22 @@ static CURLcode myssh_connect(struct connectdata *conn, bool *done)
/* we do not verify here, we do it at the state machine,
* after connection */
- state(conn, SSH_INIT);
+ state(data, SSH_INIT);
- result = myssh_multi_statemach(conn, done);
+ result = myssh_multi_statemach(data, done);
return result;
}
/* called from multi.c while DOing */
-static CURLcode scp_doing(struct connectdata *conn, bool *dophase_done)
+static CURLcode scp_doing(struct Curl_easy *data, bool *dophase_done)
{
CURLcode result;
- result = myssh_multi_statemach(conn, dophase_done);
+ result = myssh_multi_statemach(data, dophase_done);
if(*dophase_done) {
- DEBUGF(infof(conn->data, "DO phase is complete\n"));
+ DEBUGF(infof(data, "DO phase is complete\n"));
}
return result;
}
@@ -2276,34 +2269,35 @@ static CURLcode scp_doing(struct connectdata *conn, bool *dophase_done)
*/
static
-CURLcode scp_perform(struct connectdata *conn,
+CURLcode scp_perform(struct Curl_easy *data,
bool *connected, bool *dophase_done)
{
CURLcode result = CURLE_OK;
+ struct connectdata *conn = data->conn;
- DEBUGF(infof(conn->data, "DO phase starts\n"));
+ DEBUGF(infof(data, "DO phase starts\n"));
*dophase_done = FALSE; /* not done yet */
/* start the first command in the DO phase */
- state(conn, SSH_SCP_TRANS_INIT);
+ state(data, SSH_SCP_TRANS_INIT);
- result = myssh_multi_statemach(conn, dophase_done);
+ result = myssh_multi_statemach(data, dophase_done);
*connected = conn->bits.tcpconnect[FIRSTSOCKET];
if(*dophase_done) {
- DEBUGF(infof(conn->data, "DO phase is complete\n"));
+ DEBUGF(infof(data, "DO phase is complete\n"));
}
return result;
}
-static CURLcode myssh_do_it(struct connectdata *conn, bool *done)
+static CURLcode myssh_do_it(struct Curl_easy *data, bool *done)
{
CURLcode result;
bool connected = 0;
- struct Curl_easy *data = conn->data;
+ struct connectdata *conn = data->conn;
struct ssh_conn *sshc = &conn->proto.sshc;
*done = FALSE; /* default to false */
@@ -2320,9 +2314,9 @@ static CURLcode myssh_do_it(struct connectdata *conn, bool *done)
Curl_pgrsSetDownloadSize(data, -1);
if(conn->handler->protocol & CURLPROTO_SCP)
- result = scp_perform(conn, &connected, done);
+ result = scp_perform(data, &connected, done);
else
- result = sftp_perform(conn, &connected, done);
+ result = sftp_perform(data, &connected, done);
return result;
}
@@ -2330,7 +2324,8 @@ static CURLcode myssh_do_it(struct connectdata *conn, bool *done)
/* BLOCKING, but the function is using the state machine so the only reason
this is still blocking is that the multi interface code has no support for
disconnecting operations that takes a while */
-static CURLcode scp_disconnect(struct connectdata *conn,
+static CURLcode scp_disconnect(struct Curl_easy *data,
+ struct connectdata *conn,
bool dead_connection)
{
CURLcode result = CURLE_OK;
@@ -2340,9 +2335,9 @@ static CURLcode scp_disconnect(struct connectdata *conn,
if(ssh->ssh_session) {
/* only if there's a session still around to use! */
- state(conn, SSH_SESSION_DISCONNECT);
+ state(data, SSH_SESSION_DISCONNECT);
- result = myssh_block_statemach(conn, TRUE);
+ result = myssh_block_statemach(data, TRUE);
}
return result;
@@ -2350,44 +2345,45 @@ static CURLcode scp_disconnect(struct connectdata *conn,
/* generic done function for both SCP and SFTP called from their specific
done functions */
-static CURLcode myssh_done(struct connectdata *conn, CURLcode status)
+static CURLcode myssh_done(struct Curl_easy *data, CURLcode status)
{
CURLcode result = CURLE_OK;
- struct SSHPROTO *protop = conn->data->req.protop;
+ struct SSHPROTO *protop = data->req.p.ssh;
if(!status) {
/* run the state-machine */
- result = myssh_block_statemach(conn, FALSE);
+ result = myssh_block_statemach(data, FALSE);
}
else
result = status;
if(protop)
Curl_safefree(protop->path);
- if(Curl_pgrsDone(conn))
+ if(Curl_pgrsDone(data))
return CURLE_ABORTED_BY_CALLBACK;
- conn->data->req.keepon = 0; /* clear all bits */
+ data->req.keepon = 0; /* clear all bits */
return result;
}
-static CURLcode scp_done(struct connectdata *conn, CURLcode status,
+static CURLcode scp_done(struct Curl_easy *data, CURLcode status,
bool premature)
{
(void) premature; /* not used */
if(!status)
- state(conn, SSH_SCP_DONE);
+ state(data, SSH_SCP_DONE);
- return myssh_done(conn, status);
+ return myssh_done(data, status);
}
-static ssize_t scp_send(struct connectdata *conn, int sockindex,
+static ssize_t scp_send(struct Curl_easy *data, int sockindex,
const void *mem, size_t len, CURLcode *err)
{
int rc;
+ struct connectdata *conn = data->conn;
(void) sockindex; /* we only support SCP on the fixed known primary socket */
(void) err;
@@ -2413,10 +2409,11 @@ static ssize_t scp_send(struct connectdata *conn, int sockindex,
return len;
}
-static ssize_t scp_recv(struct connectdata *conn, int sockindex,
+static ssize_t scp_recv(struct Curl_easy *data, int sockindex,
char *mem, size_t len, CURLcode *err)
{
ssize_t nread;
+ struct connectdata *conn = data->conn;
(void) err;
(void) sockindex; /* we only support SCP on the fixed known primary socket */
@@ -2452,38 +2449,39 @@ static ssize_t scp_recv(struct connectdata *conn, int sockindex,
*/
static
-CURLcode sftp_perform(struct connectdata *conn,
+CURLcode sftp_perform(struct Curl_easy *data,
bool *connected,
bool *dophase_done)
{
CURLcode result = CURLE_OK;
+ struct connectdata *conn = data->conn;
- DEBUGF(infof(conn->data, "DO phase starts\n"));
+ DEBUGF(infof(data, "DO phase starts\n"));
*dophase_done = FALSE; /* not done yet */
/* start the first command in the DO phase */
- state(conn, SSH_SFTP_QUOTE_INIT);
+ state(data, SSH_SFTP_QUOTE_INIT);
/* run the state-machine */
- result = myssh_multi_statemach(conn, dophase_done);
+ result = myssh_multi_statemach(data, dophase_done);
*connected = conn->bits.tcpconnect[FIRSTSOCKET];
if(*dophase_done) {
- DEBUGF(infof(conn->data, "DO phase is complete\n"));
+ DEBUGF(infof(data, "DO phase is complete\n"));
}
return result;
}
/* called from multi.c while DOing */
-static CURLcode sftp_doing(struct connectdata *conn,
+static CURLcode sftp_doing(struct Curl_easy *data,
bool *dophase_done)
{
- CURLcode result = myssh_multi_statemach(conn, dophase_done);
+ CURLcode result = myssh_multi_statemach(data, dophase_done);
if(*dophase_done) {
- DEBUGF(infof(conn->data, "DO phase is complete\n"));
+ DEBUGF(infof(data, "DO phase is complete\n"));
}
return result;
}
@@ -2491,46 +2489,50 @@ static CURLcode sftp_doing(struct connectdata *conn,
/* BLOCKING, but the function is using the state machine so the only reason
this is still blocking is that the multi interface code has no support for
disconnecting operations that takes a while */
-static CURLcode sftp_disconnect(struct connectdata *conn, bool dead_connection)
+static CURLcode sftp_disconnect(struct Curl_easy *data,
+ struct connectdata *conn,
+ bool dead_connection)
{
CURLcode result = CURLE_OK;
(void) dead_connection;
- DEBUGF(infof(conn->data, "SSH DISCONNECT starts now\n"));
+ DEBUGF(infof(data, "SSH DISCONNECT starts now\n"));
if(conn->proto.sshc.ssh_session) {
/* only if there's a session still around to use! */
- state(conn, SSH_SFTP_SHUTDOWN);
- result = myssh_block_statemach(conn, TRUE);
+ state(data, SSH_SFTP_SHUTDOWN);
+ result = myssh_block_statemach(data, TRUE);
}
- DEBUGF(infof(conn->data, "SSH DISCONNECT is done\n"));
+ DEBUGF(infof(data, "SSH DISCONNECT is done\n"));
return result;
}
-static CURLcode sftp_done(struct connectdata *conn, CURLcode status,
- bool premature)
+static CURLcode sftp_done(struct Curl_easy *data, CURLcode status,
+ bool premature)
{
+ struct connectdata *conn = data->conn;
struct ssh_conn *sshc = &conn->proto.sshc;
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 && conn->data->set.postquote && !conn->bits.retry)
+ if(!premature && data->set.postquote && !conn->bits.retry)
sshc->nextstate = SSH_SFTP_POSTQUOTE_INIT;
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
}
- return myssh_done(conn, status);
+ return myssh_done(data, status);
}
/* return number of sent bytes */
-static ssize_t sftp_send(struct connectdata *conn, int sockindex,
+static ssize_t sftp_send(struct Curl_easy *data, int sockindex,
const void *mem, size_t len, CURLcode *err)
{
ssize_t nwrite;
+ struct connectdata *conn = data->conn;
(void)sockindex;
nwrite = sftp_write(conn->proto.sshc.sftp_file, mem, len);
@@ -2556,10 +2558,11 @@ static ssize_t sftp_send(struct connectdata *conn, int sockindex,
* Return number of received (decrypted) bytes
* or <0 on error
*/
-static ssize_t sftp_recv(struct connectdata *conn, int sockindex,
+static ssize_t sftp_recv(struct Curl_easy *data, int sockindex,
char *mem, size_t len, CURLcode *err)
{
ssize_t nread;
+ struct connectdata *conn = data->conn;
(void)sockindex;
DEBUGASSERT(len < CURL_MAX_READ_SIZE);
@@ -2567,8 +2570,8 @@ static ssize_t sftp_recv(struct connectdata *conn, int sockindex,
switch(conn->proto.sshc.sftp_recv_state) {
case 0:
conn->proto.sshc.sftp_file_index =
- sftp_async_read_begin(conn->proto.sshc.sftp_file,
- (uint32_t)len);
+ sftp_async_read_begin(conn->proto.sshc.sftp_file,
+ (uint32_t)len);
if(conn->proto.sshc.sftp_file_index < 0) {
*err = CURLE_RECV_ERROR;
return -1;
@@ -2602,11 +2605,11 @@ static ssize_t sftp_recv(struct connectdata *conn, int sockindex,
}
}
-static void sftp_quote(struct connectdata *conn)
+static void sftp_quote(struct Curl_easy *data)
{
const char *cp;
- struct Curl_easy *data = conn->data;
- struct SSHPROTO *protop = data->req.protop;
+ struct connectdata *conn = data->conn;
+ struct SSHPROTO *protop = data->req.p.ssh;
struct ssh_conn *sshc = &conn->proto.sshc;
CURLcode result;
@@ -2632,26 +2635,25 @@ static void sftp_quote(struct connectdata *conn)
protop->path);
if(!tmp) {
sshc->actualcode = CURLE_OUT_OF_MEMORY;
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
return;
}
- if(data->set.verbose) {
- Curl_debug(data, CURLINFO_HEADER_OUT, (char *) "PWD\n", 4);
- Curl_debug(data, CURLINFO_HEADER_IN, tmp, strlen(tmp));
- }
+ Curl_debug(data, CURLINFO_HEADER_OUT, (char *) "PWD\n", 4);
+ Curl_debug(data, CURLINFO_HEADER_IN, tmp, strlen(tmp));
+
/* this sends an FTP-like "header" to the header callback so that the
current directory can be read very similar to how it is read when
using ordinary FTP. */
- result = Curl_client_write(conn, CLIENTWRITE_HEADER, tmp, strlen(tmp));
+ result = Curl_client_write(data, CLIENTWRITE_HEADER, tmp, strlen(tmp));
free(tmp);
if(result) {
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = result;
}
else
- state(conn, SSH_SFTP_NEXT_QUOTE);
+ state(data, SSH_SFTP_NEXT_QUOTE);
return;
}
@@ -2662,7 +2664,7 @@ static void sftp_quote(struct connectdata *conn)
cp = strchr(cmd, ' ');
if(cp == NULL) {
failf(data, "Syntax error in SFTP command. Supply parameter(s)!");
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = CURLE_QUOTE_ERROR;
return;
@@ -2678,7 +2680,7 @@ static void sftp_quote(struct connectdata *conn)
failf(data, "Out of memory");
else
failf(data, "Syntax error: Bad first parameter");
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = result;
return;
@@ -2692,7 +2694,9 @@ static void sftp_quote(struct connectdata *conn)
*/
if(strncasecompare(cmd, "chgrp ", 6) ||
strncasecompare(cmd, "chmod ", 6) ||
- strncasecompare(cmd, "chown ", 6)) {
+ strncasecompare(cmd, "chown ", 6) ||
+ strncasecompare(cmd, "atime ", 6) ||
+ strncasecompare(cmd, "mtime ", 6)) {
/* attribute change */
/* sshc->quote_path1 contains the mode to set */
@@ -2702,16 +2706,16 @@ static void sftp_quote(struct connectdata *conn)
if(result == CURLE_OUT_OF_MEMORY)
failf(data, "Out of memory");
else
- failf(data, "Syntax error in chgrp/chmod/chown: "
+ failf(data, "Syntax error in chgrp/chmod/chown/atime/mtime: "
"Bad second parameter");
Curl_safefree(sshc->quote_path1);
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = result;
return;
}
sshc->quote_attrs = NULL;
- state(conn, SSH_SFTP_QUOTE_STAT);
+ state(data, SSH_SFTP_QUOTE_STAT);
return;
}
if(strncasecompare(cmd, "ln ", 3) ||
@@ -2726,17 +2730,17 @@ static void sftp_quote(struct connectdata *conn)
else
failf(data, "Syntax error in ln/symlink: Bad second parameter");
Curl_safefree(sshc->quote_path1);
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = result;
return;
}
- state(conn, SSH_SFTP_QUOTE_SYMLINK);
+ state(data, SSH_SFTP_QUOTE_SYMLINK);
return;
}
else if(strncasecompare(cmd, "mkdir ", 6)) {
/* create dir */
- state(conn, SSH_SFTP_QUOTE_MKDIR);
+ state(data, SSH_SFTP_QUOTE_MKDIR);
return;
}
else if(strncasecompare(cmd, "rename ", 7)) {
@@ -2750,26 +2754,26 @@ static void sftp_quote(struct connectdata *conn)
else
failf(data, "Syntax error in rename: Bad second parameter");
Curl_safefree(sshc->quote_path1);
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = result;
return;
}
- state(conn, SSH_SFTP_QUOTE_RENAME);
+ state(data, SSH_SFTP_QUOTE_RENAME);
return;
}
else if(strncasecompare(cmd, "rmdir ", 6)) {
/* delete dir */
- state(conn, SSH_SFTP_QUOTE_RMDIR);
+ state(data, SSH_SFTP_QUOTE_RMDIR);
return;
}
else if(strncasecompare(cmd, "rm ", 3)) {
- state(conn, SSH_SFTP_QUOTE_UNLINK);
+ state(data, SSH_SFTP_QUOTE_UNLINK);
return;
}
#ifdef HAS_STATVFS_SUPPORT
else if(strncasecompare(cmd, "statvfs ", 8)) {
- state(conn, SSH_SFTP_QUOTE_STATVFS);
+ state(data, SSH_SFTP_QUOTE_STATVFS);
return;
}
#endif
@@ -2777,14 +2781,14 @@ static void sftp_quote(struct connectdata *conn)
failf(data, "Unknown SFTP command");
Curl_safefree(sshc->quote_path1);
Curl_safefree(sshc->quote_path2);
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = CURLE_QUOTE_ERROR;
}
-static void sftp_quote_stat(struct connectdata *conn)
+static void sftp_quote_stat(struct Curl_easy *data)
{
- struct Curl_easy *data = conn->data;
+ struct connectdata *conn = data->conn;
struct ssh_conn *sshc = &conn->proto.sshc;
char *cmd = sshc->quote_item->data;
sshc->acceptfail = FALSE;
@@ -2812,7 +2816,7 @@ static void sftp_quote_stat(struct connectdata *conn)
Curl_safefree(sshc->quote_path2);
failf(data, "Attempt to get SFTP stats failed: %d",
sftp_get_error(sshc->sftp_session));
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = CURLE_QUOTE_ERROR;
return;
@@ -2826,7 +2830,7 @@ static void sftp_quote_stat(struct connectdata *conn)
Curl_safefree(sshc->quote_path1);
Curl_safefree(sshc->quote_path2);
failf(data, "Syntax error: chgrp gid not a number");
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = CURLE_QUOTE_ERROR;
return;
@@ -2841,7 +2845,7 @@ static void sftp_quote_stat(struct connectdata *conn)
Curl_safefree(sshc->quote_path1);
Curl_safefree(sshc->quote_path2);
failf(data, "Syntax error: chmod permissions not a number");
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = CURLE_QUOTE_ERROR;
return;
@@ -2856,16 +2860,44 @@ static void sftp_quote_stat(struct connectdata *conn)
Curl_safefree(sshc->quote_path1);
Curl_safefree(sshc->quote_path2);
failf(data, "Syntax error: chown uid not a number");
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = CURLE_QUOTE_ERROR;
return;
}
sshc->quote_attrs->flags |= SSH_FILEXFER_ATTR_UIDGID;
}
+ else if(strncasecompare(cmd, "atime", 5)) {
+ time_t date = Curl_getdate_capped(sshc->quote_path1);
+ if(date == -1) {
+ Curl_safefree(sshc->quote_path1);
+ Curl_safefree(sshc->quote_path2);
+ failf(data, "Syntax error: incorrect access date format");
+ state(data, SSH_SFTP_CLOSE);
+ sshc->nextstate = SSH_NO_STATE;
+ sshc->actualcode = CURLE_QUOTE_ERROR;
+ return;
+ }
+ sshc->quote_attrs->atime = (uint32_t)date;
+ sshc->quote_attrs->flags |= SSH_FILEXFER_ATTR_ACMODTIME;
+ }
+ else if(strncasecompare(cmd, "mtime", 5)) {
+ time_t date = Curl_getdate_capped(sshc->quote_path1);
+ if(date == -1) {
+ Curl_safefree(sshc->quote_path1);
+ Curl_safefree(sshc->quote_path2);
+ failf(data, "Syntax error: incorrect modification date format");
+ state(data, SSH_SFTP_CLOSE);
+ sshc->nextstate = SSH_NO_STATE;
+ sshc->actualcode = CURLE_QUOTE_ERROR;
+ return;
+ }
+ sshc->quote_attrs->mtime = (uint32_t)date;
+ sshc->quote_attrs->flags |= SSH_FILEXFER_ATTR_ACMODTIME;
+ }
/* Now send the completed structure... */
- state(conn, SSH_SFTP_QUOTE_SETSTAT);
+ state(data, SSH_SFTP_QUOTE_SETSTAT);
return;
}
diff --git a/Utilities/cmcurl/lib/vssh/libssh2.c b/Utilities/cmcurl/lib/vssh/libssh2.c
index 4f56bb44c..3130dcc74 100644
--- a/Utilities/cmcurl/lib/vssh/libssh2.c
+++ b/Utilities/cmcurl/lib/vssh/libssh2.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -103,30 +103,24 @@ 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 connectdata *conn);
-static CURLcode ssh_connect(struct connectdata *conn, bool *done);
-static CURLcode ssh_multi_statemach(struct connectdata *conn, bool *done);
-static CURLcode ssh_do(struct connectdata *conn, bool *done);
-
-static CURLcode scp_done(struct connectdata *conn,
- CURLcode, bool premature);
-static CURLcode scp_doing(struct connectdata *conn,
- bool *dophase_done);
-static CURLcode scp_disconnect(struct connectdata *conn, bool dead_connection);
-
-static CURLcode sftp_done(struct connectdata *conn,
- CURLcode, bool premature);
-static CURLcode sftp_doing(struct connectdata *conn,
- bool *dophase_done);
-static CURLcode sftp_disconnect(struct connectdata *conn, bool dead);
-static
-CURLcode sftp_perform(struct connectdata *conn,
- bool *connected,
- bool *dophase_done);
-static int ssh_getsock(struct connectdata *conn, curl_socket_t *sock);
-static int ssh_perform_getsock(const struct connectdata *conn,
- curl_socket_t *sock);
-static CURLcode ssh_setup_connection(struct connectdata *conn);
+static CURLcode ssh_force_knownhost_key_type(struct Curl_easy *data);
+static CURLcode ssh_connect(struct Curl_easy *data, bool *done);
+static CURLcode ssh_multi_statemach(struct Curl_easy *data, bool *done);
+static CURLcode ssh_do(struct Curl_easy *data, bool *done);
+static CURLcode scp_done(struct Curl_easy *data, CURLcode c, bool premature);
+static CURLcode scp_doing(struct Curl_easy *data, bool *dophase_done);
+static CURLcode scp_disconnect(struct Curl_easy *data,
+ struct connectdata *conn, bool dead_connection);
+static CURLcode sftp_done(struct Curl_easy *data, CURLcode, bool premature);
+static CURLcode sftp_doing(struct Curl_easy *data, bool *dophase_done);
+static CURLcode sftp_disconnect(struct Curl_easy *data,
+ struct connectdata *conn, bool dead);
+static CURLcode sftp_perform(struct Curl_easy *data, bool *connected,
+ bool *dophase_done);
+static int ssh_getsock(struct Curl_easy *data, struct connectdata *conn,
+ curl_socket_t *sock);
+static CURLcode ssh_setup_connection(struct Curl_easy *data,
+ struct connectdata *conn);
/*
* SCP protocol handler.
@@ -144,12 +138,13 @@ const struct Curl_handler Curl_handler_scp = {
ssh_getsock, /* proto_getsock */
ssh_getsock, /* doing_getsock */
ZERO_NULL, /* domore_getsock */
- ssh_perform_getsock, /* perform_getsock */
+ ssh_getsock, /* perform_getsock */
scp_disconnect, /* disconnect */
ZERO_NULL, /* readwrite */
ZERO_NULL, /* connection_check */
PORT_SSH, /* defport */
CURLPROTO_SCP, /* protocol */
+ CURLPROTO_SCP, /* family */
PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION
| PROTOPT_NOURLQUERY /* flags */
};
@@ -171,12 +166,13 @@ const struct Curl_handler Curl_handler_sftp = {
ssh_getsock, /* proto_getsock */
ssh_getsock, /* doing_getsock */
ZERO_NULL, /* domore_getsock */
- ssh_perform_getsock, /* perform_getsock */
+ ssh_getsock, /* perform_getsock */
sftp_disconnect, /* disconnect */
ZERO_NULL, /* readwrite */
ZERO_NULL, /* connection_check */
PORT_SSH, /* defport */
CURLPROTO_SFTP, /* protocol */
+ CURLPROTO_SFTP, /* family */
PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION
| PROTOPT_NOURLQUERY /* flags */
};
@@ -306,8 +302,9 @@ 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 connectdata *conn, sshstate nowstate)
+static void state(struct Curl_easy *data, 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 */
@@ -378,7 +375,7 @@ static void state(struct connectdata *conn, sshstate nowstate)
DEBUGASSERT(sizeof(names)/sizeof(names[0]) == SSH_LAST);
if(sshc->state != nowstate) {
- infof(conn->data, "SFTP %p state change from %s to %s\n",
+ infof(data, "SFTP %p state change from %s to %s\n",
(void *)sshc, names[sshc->state], names[nowstate]);
}
#endif
@@ -432,16 +429,16 @@ static int sshkeycallback(struct Curl_easy *easy,
#define libssh2_session_startup(x,y) libssh2_session_handshake(x,y)
#endif
-static CURLcode ssh_knownhost(struct connectdata *conn)
+static CURLcode ssh_knownhost(struct Curl_easy *data)
{
CURLcode result = CURLE_OK;
#ifdef HAVE_LIBSSH2_KNOWNHOST_API
- struct Curl_easy *data = conn->data;
-
if(data->set.str[STRING_SSH_KNOWNHOSTS]) {
/* we're 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;
int rc;
int keytype;
size_t keylen;
@@ -456,7 +453,6 @@ static CURLcode ssh_knownhost(struct connectdata *conn)
* What host name does OpenSSH store in its file if an IDN name is
* used?
*/
- struct libssh2_knownhost *host;
enum curl_khmatch keymatch;
curl_sshkeycallback func =
data->set.ssh_keyfunc?data->set.ssh_keyfunc:sshkeycallback;
@@ -562,13 +558,19 @@ static CURLcode ssh_knownhost(struct connectdata *conn)
default: /* unknown return codes will equal reject */
/* FALLTHROUGH */
case CURLKHSTAT_REJECT:
- state(conn, SSH_SESSION_FREE);
+ state(data, SSH_SESSION_FREE);
/* FALLTHROUGH */
case CURLKHSTAT_DEFER:
/* DEFER means bail out but keep the SSH_HOSTKEY state */
result = sshc->actualcode = CURLE_PEER_FAILED_VERIFICATION;
break;
+ case CURLKHSTAT_FINE_REPLACE:
+ /* remove old host+key that doesn't match */
+ if(host)
+ libssh2_knownhost_del(sshc->kh, host);
+ /*FALLTHROUGH*/
case CURLKHSTAT_FINE:
+ /*FALLTHROUGH*/
case CURLKHSTAT_FINE_ADD_TO_FILE:
/* proceed */
if(keycheck != LIBSSH2_KNOWNHOST_CHECK_MATCH) {
@@ -583,7 +585,8 @@ static CURLcode ssh_knownhost(struct connectdata *conn)
if(addrc)
infof(data, "Warning adding the known host %s failed!\n",
conn->host.name);
- else if(rc == CURLKHSTAT_FINE_ADD_TO_FILE) {
+ else if(rc == CURLKHSTAT_FINE_ADD_TO_FILE ||
+ rc == CURLKHSTAT_FINE_REPLACE) {
/* now we write the entire in-memory list of known hosts to the
known_hosts file */
int wrc =
@@ -600,15 +603,15 @@ static CURLcode ssh_knownhost(struct connectdata *conn)
}
}
#else /* HAVE_LIBSSH2_KNOWNHOST_API */
- (void)conn;
+ (void)data;
#endif
return result;
}
-static CURLcode ssh_check_fingerprint(struct connectdata *conn)
+static CURLcode ssh_check_fingerprint(struct Curl_easy *data)
{
+ struct connectdata *conn = data->conn;
struct ssh_conn *sshc = &conn->proto.sshc;
- struct Curl_easy *data = conn->data;
const char *pubkey_md5 = data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5];
char md5buffer[33];
@@ -635,7 +638,7 @@ static CURLcode ssh_check_fingerprint(struct connectdata *conn)
else
failf(data,
"Denied establishing ssh session: md5 fingerprint not available");
- state(conn, SSH_SESSION_FREE);
+ state(data, SSH_SESSION_FREE);
sshc->actualcode = CURLE_PEER_FAILED_VERIFICATION;
return sshc->actualcode;
}
@@ -643,14 +646,14 @@ static CURLcode ssh_check_fingerprint(struct connectdata *conn)
/* as we already matched, we skip the check for known hosts */
return CURLE_OK;
}
- return ssh_knownhost(conn);
+ return ssh_knownhost(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 connectdata *conn)
+static CURLcode ssh_force_knownhost_key_type(struct Curl_easy *data)
{
CURLcode result = CURLE_OK;
@@ -678,8 +681,8 @@ static CURLcode ssh_force_knownhost_key_type(struct connectdata *conn)
= "ssh-dss";
const char *hostkey_method = NULL;
+ struct connectdata *conn = data->conn;
struct ssh_conn *sshc = &conn->proto.sshc;
- struct Curl_easy *data = conn->data;
struct libssh2_knownhost* store = NULL;
const char *kh_name_end = NULL;
size_t kh_name_size = 0;
@@ -754,18 +757,18 @@ static CURLcode ssh_force_knownhost_key_type(struct connectdata *conn)
hostkey_method = hostkey_method_ssh_dss;
break;
case LIBSSH2_KNOWNHOST_KEY_RSA1:
- failf(data, "Found host key type RSA1 which is not supported\n");
+ failf(data, "Found host key type RSA1 which is not supported");
return CURLE_SSH;
default:
- failf(data, "Unknown host key type: %i\n",
+ failf(data, "Unknown host key type: %i",
(store->typemask & LIBSSH2_KNOWNHOST_KEY_MASK));
return CURLE_SSH;
}
infof(data, "Set \"%s\" as SSH hostkey type\n", hostkey_method);
result = libssh2_session_error_to_CURLE(
- libssh2_session_method_pref(
- sshc->ssh_session, LIBSSH2_METHOD_HOSTKEY, hostkey_method));
+ libssh2_session_method_pref(
+ sshc->ssh_session, LIBSSH2_METHOD_HOSTKEY, hostkey_method));
}
else {
infof(data, "Did not find host %s in %s\n",
@@ -785,11 +788,11 @@ static CURLcode ssh_force_knownhost_key_type(struct connectdata *conn)
* meaning it wants to be called again when the socket is ready
*/
-static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
+static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
- struct SSHPROTO *sftp_scp = data->req.protop;
+ struct connectdata *conn = data->conn;
+ struct SSHPROTO *sshp = data->req.p.ssh;
struct ssh_conn *sshc = &conn->proto.sshc;
curl_socket_t sock = conn->sock[FIRSTSOCKET];
int rc = LIBSSH2_ERROR_NONE;
@@ -800,7 +803,6 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
*block = 0; /* we're not blocking by default */
do {
-
switch(sshc->state) {
case SSH_INIT:
sshc->secondCreateDirs = 0;
@@ -811,13 +813,14 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
non-blocking */
libssh2_session_set_blocking(sshc->ssh_session, 0);
- result = ssh_force_knownhost_key_type(conn);
+ result = ssh_force_knownhost_key_type(data);
if(result) {
- state(conn, SSH_SESSION_FREE);
+ state(data, SSH_SESSION_FREE);
+ sshc->actualcode = result;
break;
}
- state(conn, SSH_S_STARTUP);
+ state(data, SSH_S_STARTUP);
/* FALLTHROUGH */
case SSH_S_STARTUP:
@@ -830,12 +833,12 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
(void)libssh2_session_last_error(sshc->ssh_session, &err_msg, NULL, 0);
failf(data, "Failure establishing ssh session: %d, %s", rc, err_msg);
- state(conn, SSH_SESSION_FREE);
+ state(data, SSH_SESSION_FREE);
sshc->actualcode = CURLE_FAILED_INIT;
break;
}
- state(conn, SSH_HOSTKEY);
+ state(data, SSH_HOSTKEY);
/* FALLTHROUGH */
case SSH_HOSTKEY:
@@ -844,9 +847,9 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
* against our known hosts. How that is handled (reading from file,
* whatever) is up to us.
*/
- result = ssh_check_fingerprint(conn);
+ result = ssh_check_fingerprint(data);
if(!result)
- state(conn, SSH_AUTHLIST);
+ state(data, SSH_AUTHLIST);
/* ssh_check_fingerprint sets state appropriately on error */
break;
@@ -869,14 +872,14 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
if(libssh2_userauth_authenticated(sshc->ssh_session)) {
sshc->authed = TRUE;
infof(data, "SSH user accepted with no authentication\n");
- state(conn, SSH_AUTH_DONE);
+ state(data, SSH_AUTH_DONE);
break;
}
ssherr = libssh2_session_last_errno(sshc->ssh_session);
if(ssherr == LIBSSH2_ERROR_EAGAIN)
rc = LIBSSH2_ERROR_EAGAIN;
else {
- state(conn, SSH_SESSION_FREE);
+ state(data, SSH_SESSION_FREE);
sshc->actualcode = libssh2_session_error_to_CURLE(ssherr);
}
break;
@@ -884,7 +887,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
infof(data, "SSH authentication methods available: %s\n",
sshc->authlist);
- state(conn, SSH_AUTH_PKEY_INIT);
+ state(data, SSH_AUTH_PKEY_INIT);
break;
case SSH_AUTH_PKEY_INIT:
@@ -956,7 +959,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
if(out_of_memory || sshc->rsa == NULL) {
Curl_safefree(sshc->rsa);
Curl_safefree(sshc->rsa_pub);
- state(conn, SSH_SESSION_FREE);
+ state(data, SSH_SESSION_FREE);
sshc->actualcode = CURLE_OUT_OF_MEMORY;
break;
}
@@ -969,10 +972,10 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
infof(data, "Using SSH public key file '%s'\n", sshc->rsa_pub);
infof(data, "Using SSH private key file '%s'\n", sshc->rsa);
- state(conn, SSH_AUTH_PKEY);
+ state(data, SSH_AUTH_PKEY);
}
else {
- state(conn, SSH_AUTH_PASS_INIT);
+ state(data, SSH_AUTH_PASS_INIT);
}
break;
@@ -995,14 +998,14 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
if(rc == 0) {
sshc->authed = TRUE;
infof(data, "Initialized SSH public key authentication\n");
- state(conn, SSH_AUTH_DONE);
+ state(data, SSH_AUTH_DONE);
}
else {
char *err_msg = NULL;
(void)libssh2_session_last_error(sshc->ssh_session,
&err_msg, NULL, 0);
infof(data, "SSH public key authentication failed: %s\n", err_msg);
- state(conn, SSH_AUTH_PASS_INIT);
+ state(data, SSH_AUTH_PASS_INIT);
rc = 0; /* clear rc and continue */
}
break;
@@ -1010,10 +1013,10 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
case SSH_AUTH_PASS_INIT:
if((data->set.ssh_auth_types & CURLSSH_AUTH_PASSWORD) &&
(strstr(sshc->authlist, "password") != NULL)) {
- state(conn, SSH_AUTH_PASS);
+ state(data, SSH_AUTH_PASS);
}
else {
- state(conn, SSH_AUTH_HOST_INIT);
+ state(data, SSH_AUTH_HOST_INIT);
rc = 0; /* clear rc and continue */
}
break;
@@ -1030,10 +1033,10 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
if(rc == 0) {
sshc->authed = TRUE;
infof(data, "Initialized password authentication\n");
- state(conn, SSH_AUTH_DONE);
+ state(data, SSH_AUTH_DONE);
}
else {
- state(conn, SSH_AUTH_HOST_INIT);
+ state(data, SSH_AUTH_HOST_INIT);
rc = 0; /* clear rc and continue */
}
break;
@@ -1041,15 +1044,15 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
case SSH_AUTH_HOST_INIT:
if((data->set.ssh_auth_types & CURLSSH_AUTH_HOST) &&
(strstr(sshc->authlist, "hostbased") != NULL)) {
- state(conn, SSH_AUTH_HOST);
+ state(data, SSH_AUTH_HOST);
}
else {
- state(conn, SSH_AUTH_AGENT_INIT);
+ state(data, SSH_AUTH_AGENT_INIT);
}
break;
case SSH_AUTH_HOST:
- state(conn, SSH_AUTH_AGENT_INIT);
+ state(data, SSH_AUTH_AGENT_INIT);
break;
case SSH_AUTH_AGENT_INIT:
@@ -1065,7 +1068,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
if(!sshc->ssh_agent) {
infof(data, "Could not create agent object\n");
- state(conn, SSH_AUTH_KEY_INIT);
+ state(data, SSH_AUTH_KEY_INIT);
break;
}
}
@@ -1075,16 +1078,16 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
break;
if(rc < 0) {
infof(data, "Failure connecting to agent\n");
- state(conn, SSH_AUTH_KEY_INIT);
+ state(data, SSH_AUTH_KEY_INIT);
rc = 0; /* clear rc and continue */
}
else {
- state(conn, SSH_AUTH_AGENT_LIST);
+ state(data, SSH_AUTH_AGENT_LIST);
}
}
else
#endif /* HAVE_LIBSSH2_AGENT_API */
- state(conn, SSH_AUTH_KEY_INIT);
+ state(data, SSH_AUTH_KEY_INIT);
break;
case SSH_AUTH_AGENT_LIST:
@@ -1095,11 +1098,11 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
break;
if(rc < 0) {
infof(data, "Failure requesting identities to agent\n");
- state(conn, SSH_AUTH_KEY_INIT);
+ state(data, SSH_AUTH_KEY_INIT);
rc = 0; /* clear rc and continue */
}
else {
- state(conn, SSH_AUTH_AGENT);
+ state(data, SSH_AUTH_AGENT);
sshc->sshagent_prev_identity = NULL;
}
#endif
@@ -1137,10 +1140,10 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
if(rc == LIBSSH2_ERROR_NONE) {
sshc->authed = TRUE;
infof(data, "Agent based authentication successful\n");
- state(conn, SSH_AUTH_DONE);
+ state(data, SSH_AUTH_DONE);
}
else {
- state(conn, SSH_AUTH_KEY_INIT);
+ state(data, SSH_AUTH_KEY_INIT);
rc = 0; /* clear rc and continue */
}
#endif
@@ -1149,10 +1152,10 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
case SSH_AUTH_KEY_INIT:
if((data->set.ssh_auth_types & CURLSSH_AUTH_KEYBOARD)
&& (strstr(sshc->authlist, "keyboard-interactive") != NULL)) {
- state(conn, SSH_AUTH_KEY);
+ state(data, SSH_AUTH_KEY);
}
else {
- state(conn, SSH_AUTH_DONE);
+ state(data, SSH_AUTH_DONE);
}
break;
@@ -1170,13 +1173,13 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
sshc->authed = TRUE;
infof(data, "Initialized keyboard interactive authentication\n");
}
- state(conn, SSH_AUTH_DONE);
+ state(data, SSH_AUTH_DONE);
break;
case SSH_AUTH_DONE:
if(!sshc->authed) {
failf(data, "Authentication failure");
- state(conn, SSH_SESSION_FREE);
+ state(data, SSH_SESSION_FREE);
sshc->actualcode = CURLE_LOGIN_DENIED;
break;
}
@@ -1186,17 +1189,17 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
*/
infof(data, "Authentication complete\n");
- Curl_pgrsTime(conn->data, TIMER_APPCONNECT); /* SSH is connected */
+ Curl_pgrsTime(data, TIMER_APPCONNECT); /* SSH is connected */
conn->sockfd = sock;
conn->writesockfd = CURL_SOCKET_BAD;
if(conn->handler->protocol == CURLPROTO_SFTP) {
- state(conn, SSH_SFTP_INIT);
+ state(data, SSH_SFTP_INIT);
break;
}
infof(data, "SSH CONNECT phase done\n");
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
break;
case SSH_SFTP_INIT:
@@ -1215,11 +1218,11 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
(void)libssh2_session_last_error(sshc->ssh_session,
&err_msg, NULL, 0);
failf(data, "Failure initializing sftp session: %s", err_msg);
- state(conn, SSH_SESSION_FREE);
+ state(data, SSH_SESSION_FREE);
sshc->actualcode = CURLE_FAILED_INIT;
break;
}
- state(conn, SSH_SFTP_REALPATH);
+ state(data, SSH_SFTP_REALPATH);
break;
case SSH_SFTP_REALPATH:
@@ -1239,11 +1242,11 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
tempHome[rc] = '\0';
sshc->homedir = strdup(tempHome);
if(!sshc->homedir) {
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->actualcode = CURLE_OUT_OF_MEMORY;
break;
}
- conn->data->state.most_recent_ftp_entrypath = sshc->homedir;
+ data->state.most_recent_ftp_entrypath = sshc->homedir;
}
else {
/* Return the error type */
@@ -1255,9 +1258,9 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
a time-out or similar */
result = CURLE_SSH;
sshc->actualcode = result;
- DEBUGF(infof(data, "error = %d makes libcurl = %d\n",
+ DEBUGF(infof(data, "error = %lu makes libcurl = %d\n",
sftperr, (int)result));
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
break;
}
}
@@ -1266,25 +1269,25 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
since the homedir will remain the same between request but the
working path will not. */
DEBUGF(infof(data, "SSH CONNECT phase done\n"));
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
break;
case SSH_SFTP_QUOTE_INIT:
- result = Curl_getworkingpath(conn, sshc->homedir, &sftp_scp->path);
+ result = Curl_getworkingpath(data, sshc->homedir, &sshp->path);
if(result) {
sshc->actualcode = result;
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
break;
}
if(data->set.quote) {
infof(data, "Sending quote commands\n");
sshc->quote_item = data->set.quote;
- state(conn, SSH_SFTP_QUOTE);
+ state(data, SSH_SFTP_QUOTE);
}
else {
- state(conn, SSH_SFTP_GETINFO);
+ state(data, SSH_SFTP_GETINFO);
}
break;
@@ -1292,10 +1295,10 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
if(data->set.postquote) {
infof(data, "Sending quote commands\n");
sshc->quote_item = data->set.postquote;
- state(conn, SSH_SFTP_QUOTE);
+ state(data, SSH_SFTP_QUOTE);
}
else {
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
}
break;
@@ -1326,29 +1329,28 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
if(strcasecompare("pwd", cmd)) {
/* output debug output if that is requested */
char *tmp = aprintf("257 \"%s\" is current directory.\n",
- sftp_scp->path);
+ sshp->path);
if(!tmp) {
result = CURLE_OUT_OF_MEMORY;
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
break;
}
- if(data->set.verbose) {
- Curl_debug(data, CURLINFO_HEADER_OUT, (char *)"PWD\n", 4);
- Curl_debug(data, CURLINFO_HEADER_IN, tmp, strlen(tmp));
- }
+ Curl_debug(data, CURLINFO_HEADER_OUT, (char *)"PWD\n", 4);
+ Curl_debug(data, CURLINFO_HEADER_IN, tmp, strlen(tmp));
+
/* this sends an FTP-like "header" to the header callback so that the
current directory can be read very similar to how it is read when
using ordinary FTP. */
- result = Curl_client_write(conn, CLIENTWRITE_HEADER, tmp, strlen(tmp));
+ result = Curl_client_write(data, CLIENTWRITE_HEADER, tmp, strlen(tmp));
free(tmp);
if(result) {
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = result;
}
else
- state(conn, SSH_SFTP_NEXT_QUOTE);
+ state(data, SSH_SFTP_NEXT_QUOTE);
break;
}
{
@@ -1360,7 +1362,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
if(cp == NULL) {
failf(data, "Syntax error command '%s'. Missing parameter!",
cmd);
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = CURLE_QUOTE_ERROR;
break;
@@ -1376,7 +1378,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
failf(data, "Out of memory");
else
failf(data, "Syntax error: Bad first parameter to '%s'", cmd);
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = result;
break;
@@ -1390,7 +1392,9 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
*/
if(strncasecompare(cmd, "chgrp ", 6) ||
strncasecompare(cmd, "chmod ", 6) ||
- strncasecompare(cmd, "chown ", 6) ) {
+ strncasecompare(cmd, "chown ", 6) ||
+ strncasecompare(cmd, "atime ", 6) ||
+ strncasecompare(cmd, "mtime ", 6)) {
/* attribute change */
/* sshc->quote_path1 contains the mode to set */
@@ -1402,13 +1406,13 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
else
failf(data, "Syntax error in %s: Bad second parameter", cmd);
Curl_safefree(sshc->quote_path1);
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = result;
break;
}
- memset(&sshc->quote_attrs, 0, sizeof(LIBSSH2_SFTP_ATTRIBUTES));
- state(conn, SSH_SFTP_QUOTE_STAT);
+ memset(&sshp->quote_attrs, 0, sizeof(LIBSSH2_SFTP_ATTRIBUTES));
+ state(data, SSH_SFTP_QUOTE_STAT);
break;
}
if(strncasecompare(cmd, "ln ", 3) ||
@@ -1424,17 +1428,17 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
failf(data,
"Syntax error in ln/symlink: Bad second parameter");
Curl_safefree(sshc->quote_path1);
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = result;
break;
}
- state(conn, SSH_SFTP_QUOTE_SYMLINK);
+ state(data, SSH_SFTP_QUOTE_SYMLINK);
break;
}
else if(strncasecompare(cmd, "mkdir ", 6)) {
/* create dir */
- state(conn, SSH_SFTP_QUOTE_MKDIR);
+ state(data, SSH_SFTP_QUOTE_MKDIR);
break;
}
else if(strncasecompare(cmd, "rename ", 7)) {
@@ -1448,26 +1452,26 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
else
failf(data, "Syntax error in rename: Bad second parameter");
Curl_safefree(sshc->quote_path1);
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = result;
break;
}
- state(conn, SSH_SFTP_QUOTE_RENAME);
+ state(data, SSH_SFTP_QUOTE_RENAME);
break;
}
else if(strncasecompare(cmd, "rmdir ", 6)) {
/* delete dir */
- state(conn, SSH_SFTP_QUOTE_RMDIR);
+ state(data, SSH_SFTP_QUOTE_RMDIR);
break;
}
else if(strncasecompare(cmd, "rm ", 3)) {
- state(conn, SSH_SFTP_QUOTE_UNLINK);
+ state(data, SSH_SFTP_QUOTE_UNLINK);
break;
}
#ifdef HAS_STATVFS_SUPPORT
else if(strncasecompare(cmd, "statvfs ", 8)) {
- state(conn, SSH_SFTP_QUOTE_STATVFS);
+ state(data, SSH_SFTP_QUOTE_STATVFS);
break;
}
#endif
@@ -1475,7 +1479,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
failf(data, "Unknown SFTP command");
Curl_safefree(sshc->quote_path1);
Curl_safefree(sshc->quote_path2);
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = CURLE_QUOTE_ERROR;
break;
@@ -1490,15 +1494,15 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
sshc->quote_item = sshc->quote_item->next;
if(sshc->quote_item) {
- state(conn, SSH_SFTP_QUOTE);
+ state(data, SSH_SFTP_QUOTE);
}
else {
if(sshc->nextstate != SSH_NO_STATE) {
- state(conn, sshc->nextstate);
+ state(data, sshc->nextstate);
sshc->nextstate = SSH_NO_STATE;
}
else {
- state(conn, SSH_SFTP_GETINFO);
+ state(data, SSH_SFTP_GETINFO);
}
}
break;
@@ -1526,7 +1530,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
rc = libssh2_sftp_stat_ex(sshc->sftp_session, sshc->quote_path2,
curlx_uztoui(strlen(sshc->quote_path2)),
LIBSSH2_SFTP_STAT,
- &sshc->quote_attrs);
+ &sshp->quote_attrs);
if(rc == LIBSSH2_ERROR_EAGAIN) {
break;
}
@@ -1536,7 +1540,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
Curl_safefree(sshc->quote_path2);
failf(data, "Attempt to get SFTP stats failed: %s",
sftp_libssh2_strerror(sftperr));
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = CURLE_QUOTE_ERROR;
break;
@@ -1545,51 +1549,79 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
/* Now set the new attributes... */
if(strncasecompare(cmd, "chgrp", 5)) {
- sshc->quote_attrs.gid = strtoul(sshc->quote_path1, NULL, 10);
- sshc->quote_attrs.flags = LIBSSH2_SFTP_ATTR_UIDGID;
- if(sshc->quote_attrs.gid == 0 && !ISDIGIT(sshc->quote_path1[0]) &&
+ sshp->quote_attrs.gid = strtoul(sshc->quote_path1, NULL, 10);
+ sshp->quote_attrs.flags = LIBSSH2_SFTP_ATTR_UIDGID;
+ if(sshp->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(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = CURLE_QUOTE_ERROR;
break;
}
}
else if(strncasecompare(cmd, "chmod", 5)) {
- sshc->quote_attrs.permissions = strtoul(sshc->quote_path1, NULL, 8);
- sshc->quote_attrs.flags = LIBSSH2_SFTP_ATTR_PERMISSIONS;
+ sshp->quote_attrs.permissions = strtoul(sshc->quote_path1, NULL, 8);
+ sshp->quote_attrs.flags = LIBSSH2_SFTP_ATTR_PERMISSIONS;
/* permissions are octal */
- if(sshc->quote_attrs.permissions == 0 &&
+ if(sshp->quote_attrs.permissions == 0 &&
!ISDIGIT(sshc->quote_path1[0])) {
Curl_safefree(sshc->quote_path1);
Curl_safefree(sshc->quote_path2);
failf(data, "Syntax error: chmod permissions not a number");
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = CURLE_QUOTE_ERROR;
break;
}
}
else if(strncasecompare(cmd, "chown", 5)) {
- sshc->quote_attrs.uid = strtoul(sshc->quote_path1, NULL, 10);
- sshc->quote_attrs.flags = LIBSSH2_SFTP_ATTR_UIDGID;
- if(sshc->quote_attrs.uid == 0 && !ISDIGIT(sshc->quote_path1[0]) &&
+ sshp->quote_attrs.uid = strtoul(sshc->quote_path1, NULL, 10);
+ sshp->quote_attrs.flags = LIBSSH2_SFTP_ATTR_UIDGID;
+ if(sshp->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(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = CURLE_QUOTE_ERROR;
break;
}
}
+ else if(strncasecompare(cmd, "atime", 5)) {
+ time_t date = Curl_getdate_capped(sshc->quote_path1);
+ if(date == -1) {
+ Curl_safefree(sshc->quote_path1);
+ Curl_safefree(sshc->quote_path2);
+ failf(data, "Syntax error: incorrect access date format");
+ state(data, SSH_SFTP_CLOSE);
+ sshc->nextstate = SSH_NO_STATE;
+ sshc->actualcode = CURLE_QUOTE_ERROR;
+ break;
+ }
+ sshp->quote_attrs.atime = (unsigned long)date;
+ sshp->quote_attrs.flags = LIBSSH2_SFTP_ATTR_ACMODTIME;
+ }
+ else if(strncasecompare(cmd, "mtime", 5)) {
+ time_t date = Curl_getdate_capped(sshc->quote_path1);
+ if(date == -1) {
+ Curl_safefree(sshc->quote_path1);
+ Curl_safefree(sshc->quote_path2);
+ failf(data, "Syntax error: incorrect modification date format");
+ state(data, SSH_SFTP_CLOSE);
+ sshc->nextstate = SSH_NO_STATE;
+ sshc->actualcode = CURLE_QUOTE_ERROR;
+ break;
+ }
+ sshp->quote_attrs.mtime = (unsigned long)date;
+ sshp->quote_attrs.flags = LIBSSH2_SFTP_ATTR_ACMODTIME;
+ }
/* Now send the completed structure... */
- state(conn, SSH_SFTP_QUOTE_SETSTAT);
+ state(data, SSH_SFTP_QUOTE_SETSTAT);
break;
}
@@ -1597,7 +1629,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
rc = libssh2_sftp_stat_ex(sshc->sftp_session, sshc->quote_path2,
curlx_uztoui(strlen(sshc->quote_path2)),
LIBSSH2_SFTP_SETSTAT,
- &sshc->quote_attrs);
+ &sshp->quote_attrs);
if(rc == LIBSSH2_ERROR_EAGAIN) {
break;
}
@@ -1607,12 +1639,12 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
Curl_safefree(sshc->quote_path2);
failf(data, "Attempt to set SFTP stats failed: %s",
sftp_libssh2_strerror(sftperr));
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = CURLE_QUOTE_ERROR;
break;
}
- state(conn, SSH_SFTP_NEXT_QUOTE);
+ state(data, SSH_SFTP_NEXT_QUOTE);
break;
case SSH_SFTP_QUOTE_SYMLINK:
@@ -1630,12 +1662,12 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
Curl_safefree(sshc->quote_path2);
failf(data, "symlink command failed: %s",
sftp_libssh2_strerror(sftperr));
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = CURLE_QUOTE_ERROR;
break;
}
- state(conn, SSH_SFTP_NEXT_QUOTE);
+ state(data, SSH_SFTP_NEXT_QUOTE);
break;
case SSH_SFTP_QUOTE_MKDIR:
@@ -1650,12 +1682,12 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
Curl_safefree(sshc->quote_path1);
failf(data, "mkdir command failed: %s",
sftp_libssh2_strerror(sftperr));
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = CURLE_QUOTE_ERROR;
break;
}
- state(conn, SSH_SFTP_NEXT_QUOTE);
+ state(data, SSH_SFTP_NEXT_QUOTE);
break;
case SSH_SFTP_QUOTE_RENAME:
@@ -1676,12 +1708,12 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
Curl_safefree(sshc->quote_path2);
failf(data, "rename command failed: %s",
sftp_libssh2_strerror(sftperr));
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = CURLE_QUOTE_ERROR;
break;
}
- state(conn, SSH_SFTP_NEXT_QUOTE);
+ state(data, SSH_SFTP_NEXT_QUOTE);
break;
case SSH_SFTP_QUOTE_RMDIR:
@@ -1695,12 +1727,12 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
Curl_safefree(sshc->quote_path1);
failf(data, "rmdir command failed: %s",
sftp_libssh2_strerror(sftperr));
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = CURLE_QUOTE_ERROR;
break;
}
- state(conn, SSH_SFTP_NEXT_QUOTE);
+ state(data, SSH_SFTP_NEXT_QUOTE);
break;
case SSH_SFTP_QUOTE_UNLINK:
@@ -1713,12 +1745,12 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
sftperr = libssh2_sftp_last_error(sshc->sftp_session);
Curl_safefree(sshc->quote_path1);
failf(data, "rm command failed: %s", sftp_libssh2_strerror(sftperr));
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = CURLE_QUOTE_ERROR;
break;
}
- state(conn, SSH_SFTP_NEXT_QUOTE);
+ state(data, SSH_SFTP_NEXT_QUOTE);
break;
#ifdef HAS_STATVFS_SUPPORT
@@ -1737,7 +1769,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
Curl_safefree(sshc->quote_path1);
failf(data, "statvfs command failed: %s",
sftp_libssh2_strerror(sftperr));
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = CURLE_QUOTE_ERROR;
break;
@@ -1758,30 +1790,30 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
statvfs.f_namemax);
if(!tmp) {
result = CURLE_OUT_OF_MEMORY;
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
break;
}
- result = Curl_client_write(conn, CLIENTWRITE_HEADER, tmp, strlen(tmp));
+ result = Curl_client_write(data, CLIENTWRITE_HEADER, tmp, strlen(tmp));
free(tmp);
if(result) {
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = result;
}
}
- state(conn, SSH_SFTP_NEXT_QUOTE);
+ state(data, SSH_SFTP_NEXT_QUOTE);
break;
}
#endif
case SSH_SFTP_GETINFO:
{
if(data->set.get_filetime) {
- state(conn, SSH_SFTP_FILETIME);
+ state(data, SSH_SFTP_FILETIME);
}
else {
- state(conn, SSH_SFTP_TRANS_INIT);
+ state(data, SSH_SFTP_TRANS_INIT);
}
break;
}
@@ -1790,8 +1822,8 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
{
LIBSSH2_SFTP_ATTRIBUTES attrs;
- rc = libssh2_sftp_stat_ex(sshc->sftp_session, sftp_scp->path,
- curlx_uztoui(strlen(sftp_scp->path)),
+ rc = libssh2_sftp_stat_ex(sshc->sftp_session, sshp->path,
+ curlx_uztoui(strlen(sshp->path)),
LIBSSH2_SFTP_STAT, &attrs);
if(rc == LIBSSH2_ERROR_EAGAIN) {
break;
@@ -1800,18 +1832,18 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
data->info.filetime = attrs.mtime;
}
- state(conn, SSH_SFTP_TRANS_INIT);
+ state(data, SSH_SFTP_TRANS_INIT);
break;
}
case SSH_SFTP_TRANS_INIT:
if(data->set.upload)
- state(conn, SSH_SFTP_UPLOAD_INIT);
+ state(data, SSH_SFTP_UPLOAD_INIT);
else {
- if(sftp_scp->path[strlen(sftp_scp->path)-1] == '/')
- state(conn, SSH_SFTP_READDIR_INIT);
+ if(sshp->path[strlen(sshp->path)-1] == '/')
+ state(data, SSH_SFTP_READDIR_INIT);
else
- state(conn, SSH_SFTP_DOWNLOAD_INIT);
+ state(data, SSH_SFTP_DOWNLOAD_INIT);
}
break;
@@ -1828,8 +1860,8 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
if(data->state.resume_from != 0) {
LIBSSH2_SFTP_ATTRIBUTES attrs;
if(data->state.resume_from < 0) {
- rc = libssh2_sftp_stat_ex(sshc->sftp_session, sftp_scp->path,
- curlx_uztoui(strlen(sftp_scp->path)),
+ rc = libssh2_sftp_stat_ex(sshc->sftp_session, sshp->path,
+ curlx_uztoui(strlen(sshp->path)),
LIBSSH2_SFTP_STAT, &attrs);
if(rc == LIBSSH2_ERROR_EAGAIN) {
break;
@@ -1855,12 +1887,12 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
/* If we have restart position then open for append */
flags = LIBSSH2_FXF_WRITE|LIBSSH2_FXF_APPEND;
else
- /* Clear file before writing (normal behaviour) */
+ /* Clear file before writing (normal behavior) */
flags = LIBSSH2_FXF_WRITE|LIBSSH2_FXF_CREAT|LIBSSH2_FXF_TRUNC;
sshc->sftp_handle =
- libssh2_sftp_open_ex(sshc->sftp_session, sftp_scp->path,
- curlx_uztoui(strlen(sftp_scp->path)),
+ libssh2_sftp_open_ex(sshc->sftp_session, sshp->path,
+ curlx_uztoui(strlen(sshp->path)),
flags, data->set.new_file_perms,
LIBSSH2_SFTP_OPENFILE);
@@ -1878,7 +1910,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
sftperr = LIBSSH2_FX_OK; /* not an sftp error at all */
if(sshc->secondCreateDirs) {
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->actualcode = sftperr != LIBSSH2_FX_OK ?
sftp_libssh2_error_to_CURLE(sftperr):CURLE_SSH;
failf(data, "Creating the dir/file failed: %s",
@@ -1889,14 +1921,14 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
(sftperr == LIBSSH2_FX_FAILURE) ||
(sftperr == LIBSSH2_FX_NO_SUCH_PATH)) &&
(data->set.ftp_create_missing_dirs &&
- (strlen(sftp_scp->path) > 1))) {
+ (strlen(sshp->path) > 1))) {
/* try to create the path remotely */
rc = 0; /* clear rc and continue */
sshc->secondCreateDirs = 1;
- state(conn, SSH_SFTP_CREATE_DIRS_INIT);
+ state(data, SSH_SFTP_CREATE_DIRS_INIT);
break;
}
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->actualcode = sftperr != LIBSSH2_FX_OK ?
sftp_libssh2_error_to_CURLE(sftperr):CURLE_SSH;
if(!sshc->actualcode) {
@@ -1906,7 +1938,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
sshc->actualcode = CURLE_SSH;
sftperr = LIBSSH2_FX_OK;
}
- failf(data, "Upload failed: %s (%d/%d)",
+ failf(data, "Upload failed: %s (%lu/%d)",
sftperr != LIBSSH2_FX_OK ?
sftp_libssh2_strerror(sftperr):"ssh error",
sftperr, rc);
@@ -1975,7 +2007,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
conn->sockfd = conn->writesockfd;
if(result) {
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->actualcode = result;
}
else {
@@ -1993,18 +2025,18 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
timeout here */
Curl_expire(data, 0, EXPIRE_RUN_NOW);
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
}
break;
}
case SSH_SFTP_CREATE_DIRS_INIT:
- if(strlen(sftp_scp->path) > 1) {
- sshc->slash_pos = sftp_scp->path + 1; /* ignore the leading '/' */
- state(conn, SSH_SFTP_CREATE_DIRS);
+ if(strlen(sshp->path) > 1) {
+ sshc->slash_pos = sshp->path + 1; /* ignore the leading '/' */
+ state(data, SSH_SFTP_CREATE_DIRS);
}
else {
- state(conn, SSH_SFTP_UPLOAD_INIT);
+ state(data, SSH_SFTP_UPLOAD_INIT);
}
break;
@@ -2013,17 +2045,17 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
if(sshc->slash_pos) {
*sshc->slash_pos = 0;
- infof(data, "Creating directory '%s'\n", sftp_scp->path);
- state(conn, SSH_SFTP_CREATE_DIRS_MKDIR);
+ infof(data, "Creating directory '%s'\n", sshp->path);
+ state(data, SSH_SFTP_CREATE_DIRS_MKDIR);
break;
}
- state(conn, SSH_SFTP_UPLOAD_INIT);
+ state(data, 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, sftp_scp->path,
- curlx_uztoui(strlen(sftp_scp->path)),
+ rc = libssh2_sftp_mkdir_ex(sshc->sftp_session, sshp->path,
+ curlx_uztoui(strlen(sshp->path)),
data->set.new_directory_perms);
if(rc == LIBSSH2_ERROR_EAGAIN) {
break;
@@ -2041,19 +2073,19 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
(sftperr != LIBSSH2_FX_FAILURE) &&
(sftperr != LIBSSH2_FX_PERMISSION_DENIED)) {
result = sftp_libssh2_error_to_CURLE(sftperr);
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->actualcode = result?result:CURLE_SSH;
break;
}
rc = 0; /* clear rc and continue */
}
- state(conn, SSH_SFTP_CREATE_DIRS);
+ state(data, SSH_SFTP_CREATE_DIRS);
break;
case SSH_SFTP_READDIR_INIT:
Curl_pgrsSetDownloadSize(data, -1);
if(data->set.opt_no_body) {
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
break;
}
@@ -2062,9 +2094,9 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
* listing
*/
sshc->sftp_handle = libssh2_sftp_open_ex(sshc->sftp_session,
- sftp_scp->path,
+ sshp->path,
curlx_uztoui(
- strlen(sftp_scp->path)),
+ strlen(sshp->path)),
0, 0, LIBSSH2_SFTP_OPENDIR);
if(!sshc->sftp_handle) {
if(libssh2_session_last_errno(sshc->ssh_session) ==
@@ -2075,51 +2107,51 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
sftperr = libssh2_sftp_last_error(sshc->sftp_session);
failf(data, "Could not open directory for reading: %s",
sftp_libssh2_strerror(sftperr));
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
result = sftp_libssh2_error_to_CURLE(sftperr);
sshc->actualcode = result?result:CURLE_SSH;
break;
}
- sshc->readdir_filename = malloc(PATH_MAX + 1);
- if(!sshc->readdir_filename) {
- state(conn, SSH_SFTP_CLOSE);
+ sshp->readdir_filename = malloc(PATH_MAX + 1);
+ if(!sshp->readdir_filename) {
+ state(data, SSH_SFTP_CLOSE);
sshc->actualcode = CURLE_OUT_OF_MEMORY;
break;
}
- sshc->readdir_longentry = malloc(PATH_MAX + 1);
- if(!sshc->readdir_longentry) {
- Curl_safefree(sshc->readdir_filename);
- state(conn, SSH_SFTP_CLOSE);
+ sshp->readdir_longentry = malloc(PATH_MAX + 1);
+ if(!sshp->readdir_longentry) {
+ Curl_safefree(sshp->readdir_filename);
+ state(data, SSH_SFTP_CLOSE);
sshc->actualcode = CURLE_OUT_OF_MEMORY;
break;
}
- Curl_dyn_init(&sshc->readdir, PATH_MAX * 2);
- state(conn, SSH_SFTP_READDIR);
+ Curl_dyn_init(&sshp->readdir, PATH_MAX * 2);
+ state(data, SSH_SFTP_READDIR);
break;
case SSH_SFTP_READDIR:
rc = libssh2_sftp_readdir_ex(sshc->sftp_handle,
- sshc->readdir_filename,
+ sshp->readdir_filename,
PATH_MAX,
- sshc->readdir_longentry,
+ sshp->readdir_longentry,
PATH_MAX,
- &sshc->readdir_attrs);
+ &sshp->readdir_attrs);
if(rc == LIBSSH2_ERROR_EAGAIN) {
break;
}
if(rc > 0) {
readdir_len = (size_t) rc;
- sshc->readdir_filename[readdir_len] = '\0';
+ sshp->readdir_filename[readdir_len] = '\0';
if(data->set.ftp_list_only) {
- result = Curl_client_write(conn, CLIENTWRITE_BODY,
- sshc->readdir_filename,
+ result = Curl_client_write(data, CLIENTWRITE_BODY,
+ sshp->readdir_filename,
readdir_len);
if(!result)
- result = Curl_client_write(conn, CLIENTWRITE_BODY,
+ result = Curl_client_write(data, CLIENTWRITE_BODY,
(char *)"\n", 1);
if(result) {
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
break;
}
/* since this counts what we send to the client, we include the
@@ -2127,39 +2159,37 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
data->req.bytecount += readdir_len + 1;
/* output debug output if that is requested */
- if(data->set.verbose) {
- Curl_debug(data, CURLINFO_DATA_IN, sshc->readdir_filename,
- readdir_len);
- Curl_debug(data, CURLINFO_DATA_IN, (char *)"\n", 1);
- }
+ Curl_debug(data, CURLINFO_DATA_IN, sshp->readdir_filename,
+ readdir_len);
+ Curl_debug(data, CURLINFO_DATA_IN, (char *)"\n", 1);
}
else {
- result = Curl_dyn_add(&sshc->readdir, sshc->readdir_longentry);
+ result = Curl_dyn_add(&sshp->readdir, sshp->readdir_longentry);
if(!result) {
- if((sshc->readdir_attrs.flags & LIBSSH2_SFTP_ATTR_PERMISSIONS) &&
- ((sshc->readdir_attrs.permissions & LIBSSH2_SFTP_S_IFMT) ==
+ if((sshp->readdir_attrs.flags & LIBSSH2_SFTP_ATTR_PERMISSIONS) &&
+ ((sshp->readdir_attrs.permissions & LIBSSH2_SFTP_S_IFMT) ==
LIBSSH2_SFTP_S_IFLNK)) {
- Curl_dyn_init(&sshc->readdir_link, PATH_MAX);
- result = Curl_dyn_add(&sshc->readdir_link, sftp_scp->path);
- state(conn, SSH_SFTP_READDIR_LINK);
+ Curl_dyn_init(&sshp->readdir_link, PATH_MAX);
+ result = Curl_dyn_add(&sshp->readdir_link, sshp->path);
+ state(data, SSH_SFTP_READDIR_LINK);
if(!result)
break;
}
else {
- state(conn, SSH_SFTP_READDIR_BOTTOM);
+ state(data, SSH_SFTP_READDIR_BOTTOM);
break;
}
}
sshc->actualcode = result;
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
break;
}
}
else if(rc == 0) {
- Curl_safefree(sshc->readdir_filename);
- Curl_safefree(sshc->readdir_longentry);
- state(conn, SSH_SFTP_READDIR_DONE);
+ Curl_safefree(sshp->readdir_filename);
+ Curl_safefree(sshp->readdir_longentry);
+ state(data, SSH_SFTP_READDIR_DONE);
break;
}
else if(rc < 0) {
@@ -2169,9 +2199,9 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
failf(data, "Could not open remote file for reading: %s :: %d",
sftp_libssh2_strerror(sftperr),
libssh2_session_last_errno(sshc->ssh_session));
- Curl_safefree(sshc->readdir_filename);
- Curl_safefree(sshc->readdir_longentry);
- state(conn, SSH_SFTP_CLOSE);
+ Curl_safefree(sshp->readdir_filename);
+ Curl_safefree(sshp->readdir_longentry);
+ state(data, SSH_SFTP_CLOSE);
break;
}
break;
@@ -2179,55 +2209,51 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
case SSH_SFTP_READDIR_LINK:
rc =
libssh2_sftp_symlink_ex(sshc->sftp_session,
- Curl_dyn_ptr(&sshc->readdir_link),
- (int)Curl_dyn_len(&sshc->readdir_link),
- sshc->readdir_filename,
+ Curl_dyn_ptr(&sshp->readdir_link),
+ (int)Curl_dyn_len(&sshp->readdir_link),
+ sshp->readdir_filename,
PATH_MAX, LIBSSH2_SFTP_READLINK);
if(rc == LIBSSH2_ERROR_EAGAIN) {
break;
}
- readdir_len = (size_t) rc;
- Curl_dyn_free(&sshc->readdir_link);
+ Curl_dyn_free(&sshp->readdir_link);
/* append filename and extra output */
- result = Curl_dyn_addf(&sshc->readdir, " -> %s", sshc->readdir_filename);
+ result = Curl_dyn_addf(&sshp->readdir, " -> %s", sshp->readdir_filename);
if(result) {
sshc->readdir_line = NULL;
- Curl_safefree(sshc->readdir_filename);
- Curl_safefree(sshc->readdir_longentry);
- state(conn, SSH_SFTP_CLOSE);
+ Curl_safefree(sshp->readdir_filename);
+ Curl_safefree(sshp->readdir_longentry);
+ state(data, SSH_SFTP_CLOSE);
sshc->actualcode = result;
break;
}
- state(conn, SSH_SFTP_READDIR_BOTTOM);
+ state(data, SSH_SFTP_READDIR_BOTTOM);
break;
case SSH_SFTP_READDIR_BOTTOM:
- result = Curl_dyn_addn(&sshc->readdir, "\n", 1);
+ result = Curl_dyn_addn(&sshp->readdir, "\n", 1);
if(!result)
- result = Curl_client_write(conn, CLIENTWRITE_BODY,
- Curl_dyn_ptr(&sshc->readdir),
- Curl_dyn_len(&sshc->readdir));
+ result = Curl_client_write(data, CLIENTWRITE_BODY,
+ Curl_dyn_ptr(&sshp->readdir),
+ Curl_dyn_len(&sshp->readdir));
if(!result) {
-
/* output debug output if that is requested */
- if(data->set.verbose) {
- Curl_debug(data, CURLINFO_DATA_IN,
- Curl_dyn_ptr(&sshc->readdir),
- Curl_dyn_len(&sshc->readdir));
- }
- data->req.bytecount += Curl_dyn_len(&sshc->readdir);
+ Curl_debug(data, CURLINFO_DATA_IN,
+ Curl_dyn_ptr(&sshp->readdir),
+ Curl_dyn_len(&sshp->readdir));
+ data->req.bytecount += Curl_dyn_len(&sshp->readdir);
}
if(result) {
- Curl_dyn_free(&sshc->readdir);
- state(conn, SSH_STOP);
+ Curl_dyn_free(&sshp->readdir);
+ state(data, SSH_STOP);
}
else {
- Curl_dyn_reset(&sshc->readdir);
- state(conn, SSH_SFTP_READDIR);
+ Curl_dyn_reset(&sshp->readdir);
+ state(data, SSH_SFTP_READDIR);
}
break;
@@ -2238,12 +2264,12 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
break;
}
sshc->sftp_handle = NULL;
- Curl_safefree(sshc->readdir_filename);
- Curl_safefree(sshc->readdir_longentry);
+ Curl_safefree(sshp->readdir_filename);
+ Curl_safefree(sshp->readdir_longentry);
/* no data to transfer */
Curl_setup_transfer(data, -1, -1, FALSE, -1);
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
break;
case SSH_SFTP_DOWNLOAD_INIT:
@@ -2251,8 +2277,8 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
* Work on getting the specified file
*/
sshc->sftp_handle =
- libssh2_sftp_open_ex(sshc->sftp_session, sftp_scp->path,
- curlx_uztoui(strlen(sftp_scp->path)),
+ libssh2_sftp_open_ex(sshc->sftp_session, sshp->path,
+ curlx_uztoui(strlen(sshp->path)),
LIBSSH2_FXF_READ, data->set.new_file_perms,
LIBSSH2_SFTP_OPENFILE);
if(!sshc->sftp_handle) {
@@ -2264,20 +2290,20 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
sftperr = libssh2_sftp_last_error(sshc->sftp_session);
failf(data, "Could not open remote file for reading: %s",
sftp_libssh2_strerror(sftperr));
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
result = sftp_libssh2_error_to_CURLE(sftperr);
sshc->actualcode = result?result:CURLE_SSH;
break;
}
- state(conn, SSH_SFTP_DOWNLOAD_STAT);
+ state(data, SSH_SFTP_DOWNLOAD_STAT);
break;
case SSH_SFTP_DOWNLOAD_STAT:
{
LIBSSH2_SFTP_ATTRIBUTES attrs;
- rc = libssh2_sftp_stat_ex(sshc->sftp_session, sftp_scp->path,
- curlx_uztoui(strlen(sftp_scp->path)),
+ rc = libssh2_sftp_stat_ex(sshc->sftp_session, sshp->path,
+ curlx_uztoui(strlen(sshp->path)),
LIBSSH2_SFTP_STAT, &attrs);
if(rc == LIBSSH2_ERROR_EAGAIN) {
break;
@@ -2302,14 +2328,14 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
failf(data, "Bad file size (%" CURL_FORMAT_CURL_OFF_T ")", size);
return CURLE_BAD_DOWNLOAD_RESUME;
}
- if(conn->data->state.use_range) {
+ if(data->state.use_range) {
curl_off_t from, to;
char *ptr;
char *ptr2;
CURLofft to_t;
CURLofft from_t;
- from_t = curlx_strtoofft(conn->data->state.range, &ptr, 0, &from);
+ from_t = curlx_strtoofft(data->state.range, &ptr, 0, &from);
if(from_t == CURL_OFFT_FLOW)
return CURLE_RANGE_ERROR;
while(*ptr && (ISSPACE(*ptr) || (*ptr == '-')))
@@ -2340,7 +2366,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
size = to - from + 1;
}
- SFTP_SEEK(conn->proto.sshc.sftp_handle, from);
+ SFTP_SEEK(sshc->sftp_handle, from);
}
data->req.size = size;
data->req.maxdownload = size;
@@ -2383,7 +2409,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
/* no data to transfer */
Curl_setup_transfer(data, -1, -1, FALSE, -1);
infof(data, "File already completely downloaded\n");
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
break;
}
Curl_setup_transfer(data, FIRSTSOCKET, data->req.size, FALSE, -1);
@@ -2399,11 +2425,11 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
if(result) {
/* this should never occur; the close state should be entered
at the time the error occurs */
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->actualcode = result;
}
else {
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
}
break;
@@ -2422,7 +2448,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
sshc->sftp_handle = NULL;
}
- Curl_safefree(sftp_scp->path);
+ Curl_safefree(sshp->path);
DEBUGF(infof(data, "SFTP DONE done\n"));
@@ -2431,11 +2457,11 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
SSH_SFTP_CLOSE to pass the correct result back */
if(sshc->nextstate != SSH_NO_STATE &&
sshc->nextstate != SSH_SFTP_CLOSE) {
- state(conn, sshc->nextstate);
+ state(data, sshc->nextstate);
sshc->nextstate = SSH_SFTP_CLOSE;
}
else {
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
result = sshc->actualcode;
}
break;
@@ -2470,16 +2496,16 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
}
Curl_safefree(sshc->homedir);
- conn->data->state.most_recent_ftp_entrypath = NULL;
+ data->state.most_recent_ftp_entrypath = NULL;
- state(conn, SSH_SESSION_DISCONNECT);
+ state(data, SSH_SESSION_DISCONNECT);
break;
case SSH_SCP_TRANS_INIT:
- result = Curl_getworkingpath(conn, sshc->homedir, &sftp_scp->path);
+ result = Curl_getworkingpath(data, sshc->homedir, &sshp->path);
if(result) {
sshc->actualcode = result;
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
break;
}
@@ -2487,13 +2513,13 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
if(data->state.infilesize < 0) {
failf(data, "SCP requires a known file size for upload");
sshc->actualcode = CURLE_UPLOAD_FAILED;
- state(conn, SSH_SCP_CHANNEL_FREE);
+ state(data, SSH_SCP_CHANNEL_FREE);
break;
}
- state(conn, SSH_SCP_UPLOAD_INIT);
+ state(data, SSH_SCP_UPLOAD_INIT);
}
else {
- state(conn, SSH_SCP_DOWNLOAD_INIT);
+ state(data, SSH_SCP_DOWNLOAD_INIT);
}
break;
@@ -2505,7 +2531,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
* directory in the path.
*/
sshc->ssh_channel =
- SCP_SEND(sshc->ssh_session, sftp_scp->path, data->set.new_file_perms,
+ SCP_SEND(sshc->ssh_session, sshp->path, data->set.new_file_perms,
data->state.infilesize);
if(!sshc->ssh_channel) {
int ssh_err;
@@ -2519,8 +2545,8 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
ssh_err = (int)(libssh2_session_last_error(sshc->ssh_session,
&err_msg, NULL, 0));
- failf(conn->data, "%s", err_msg);
- state(conn, SSH_SCP_CHANNEL_FREE);
+ 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 ||
@@ -2538,7 +2564,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
conn->sockfd = conn->writesockfd;
if(result) {
- state(conn, SSH_SCP_CHANNEL_FREE);
+ state(data, SSH_SCP_CHANNEL_FREE);
sshc->actualcode = result;
}
else {
@@ -2551,7 +2577,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
with both accordingly */
conn->cselect_bits = CURL_CSELECT_OUT;
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
}
break;
@@ -2573,12 +2599,12 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
struct stat sb;
memset(&sb, 0, sizeof(struct stat));
sshc->ssh_channel = libssh2_scp_recv(sshc->ssh_session,
- sftp_scp->path, &sb);
+ sshp->path, &sb);
#else
libssh2_struct_stat sb;
memset(&sb, 0, sizeof(libssh2_struct_stat));
sshc->ssh_channel = libssh2_scp_recv2(sshc->ssh_session,
- sftp_scp->path, &sb);
+ sshp->path, &sb);
#endif
if(!sshc->ssh_channel) {
@@ -2594,8 +2620,8 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
ssh_err = (int)(libssh2_session_last_error(sshc->ssh_session,
&err_msg, NULL, 0));
- failf(conn->data, "%s", err_msg);
- state(conn, SSH_SCP_CHANNEL_FREE);
+ failf(data, "%s", err_msg);
+ state(data, SSH_SCP_CHANNEL_FREE);
sshc->actualcode = libssh2_session_error_to_CURLE(ssh_err);
break;
}
@@ -2614,19 +2640,19 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
conn->cselect_bits = CURL_CSELECT_IN;
if(result) {
- state(conn, SSH_SCP_CHANNEL_FREE);
+ state(data, SSH_SCP_CHANNEL_FREE);
sshc->actualcode = result;
}
else
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
}
break;
case SSH_SCP_DONE:
if(data->set.upload)
- state(conn, SSH_SCP_SEND_EOF);
+ state(data, SSH_SCP_SEND_EOF);
else
- state(conn, SSH_SCP_CHANNEL_FREE);
+ state(data, SSH_SCP_CHANNEL_FREE);
break;
case SSH_SCP_SEND_EOF:
@@ -2643,7 +2669,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
rc, err_msg);
}
}
- state(conn, SSH_SCP_WAIT_EOF);
+ state(data, SSH_SCP_WAIT_EOF);
break;
case SSH_SCP_WAIT_EOF:
@@ -2659,7 +2685,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
infof(data, "Failed to get channel EOF: %d %s\n", rc, err_msg);
}
}
- state(conn, SSH_SCP_WAIT_CLOSE);
+ state(data, SSH_SCP_WAIT_CLOSE);
break;
case SSH_SCP_WAIT_CLOSE:
@@ -2675,7 +2701,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
infof(data, "Channel failed to close: %d %s\n", rc, err_msg);
}
}
- state(conn, SSH_SCP_CHANNEL_FREE);
+ state(data, SSH_SCP_CHANNEL_FREE);
break;
case SSH_SCP_CHANNEL_FREE:
@@ -2695,9 +2721,9 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
}
DEBUGF(infof(data, "SCP DONE phase complete\n"));
#if 0 /* PREV */
- state(conn, SSH_SESSION_DISCONNECT);
+ state(data, SSH_SESSION_DISCONNECT);
#endif
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
result = sshc->actualcode;
break;
@@ -2735,9 +2761,9 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
}
Curl_safefree(sshc->homedir);
- conn->data->state.most_recent_ftp_entrypath = NULL;
+ data->state.most_recent_ftp_entrypath = NULL;
- state(conn, SSH_SESSION_FREE);
+ state(data, SSH_SESSION_FREE);
break;
case SSH_SESSION_FREE:
@@ -2805,11 +2831,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
Curl_safefree(sshc->quote_path2);
Curl_safefree(sshc->homedir);
-
- Curl_safefree(sshc->readdir_filename);
- Curl_safefree(sshc->readdir_longentry);
Curl_safefree(sshc->readdir_line);
- Curl_dyn_free(&sshc->readdir);
/* the code we are about to return */
result = sshc->actualcode;
@@ -2819,7 +2841,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
connclose(conn, "SSH session free");
sshc->state = SSH_SESSION_FREE; /* current */
sshc->nextstate = SSH_NO_STATE;
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
break;
case SSH_QUIT:
@@ -2827,7 +2849,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
default:
/* internal error */
sshc->nextstate = SSH_NO_STATE;
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
break;
}
@@ -2844,11 +2866,12 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
/* called by the multi interface to figure out what socket(s) to wait for and
for what actions in the DO_DONE, PERFORM and WAITPERFORM states */
-static int ssh_perform_getsock(const struct connectdata *conn,
- curl_socket_t *sock)
+static int ssh_getsock(struct Curl_easy *data,
+ struct connectdata *conn,
+ curl_socket_t *sock)
{
-#ifdef HAVE_LIBSSH2_SESSION_BLOCK_DIRECTION
int bitmap = GETSOCK_BLANK;
+ (void)data;
sock[0] = conn->sock[FIRSTSOCKET];
@@ -2859,32 +2882,8 @@ static int ssh_perform_getsock(const struct connectdata *conn,
bitmap |= GETSOCK_WRITESOCK(FIRSTSOCKET);
return bitmap;
-#else
- /* if we don't know the direction we can use the generic *_getsock()
- function even for the protocol_connect and doing states */
- return Curl_single_getsock(conn, sock);
-#endif
-}
-
-/* Generic function called by the multi interface to figure out what socket(s)
- to wait for and for what actions during the DOING and PROTOCONNECT states*/
-static int ssh_getsock(struct connectdata *conn,
- curl_socket_t *sock)
-{
-#ifndef HAVE_LIBSSH2_SESSION_BLOCK_DIRECTION
- (void)conn;
- (void)sock;
- /* if we don't know any direction we can just play along as we used to and
- not provide any sensible info */
- return GETSOCK_BLANK;
-#else
- /* if we know the direction we can use the generic *_getsock() function even
- for the protocol_connect and doing states */
- return ssh_perform_getsock(conn, sock);
-#endif
}
-#ifdef HAVE_LIBSSH2_SESSION_BLOCK_DIRECTION
/*
* When one of the libssh2 functions has returned LIBSSH2_ERROR_EAGAIN this
* function is used to figure out in what direction and stores this info so
@@ -2892,8 +2891,9 @@ static int ssh_getsock(struct connectdata *conn,
* function in all cases so that when it _doesn't_ return EAGAIN we can
* restore the default wait bits.
*/
-static void ssh_block2waitfor(struct connectdata *conn, bool block)
+static void ssh_block2waitfor(struct Curl_easy *data, bool block)
{
+ struct connectdata *conn = data->conn;
struct ssh_conn *sshc = &conn->proto.sshc;
int dir = 0;
if(block) {
@@ -2909,46 +2909,43 @@ static void ssh_block2waitfor(struct connectdata *conn, bool block)
the original set */
conn->waitfor = sshc->orig_waitfor;
}
-#else
- /* no libssh2 directional support so we simply don't know */
-#define ssh_block2waitfor(x,y) Curl_nop_stmt
-#endif
/* called repeatedly until done from multi.c */
-static CURLcode ssh_multi_statemach(struct connectdata *conn, bool *done)
+static CURLcode ssh_multi_statemach(struct Curl_easy *data, bool *done)
{
+ struct connectdata *conn = data->conn;
struct ssh_conn *sshc = &conn->proto.sshc;
CURLcode result = CURLE_OK;
bool block; /* we store the status and use that to provide a ssh_getsock()
implementation */
do {
- result = ssh_statemach_act(conn, &block);
+ result = ssh_statemach_act(data, &block);
*done = (sshc->state == SSH_STOP) ? TRUE : FALSE;
/* if there's no error, it isn't done and it didn't EWOULDBLOCK, then
try again */
} while(!result && !*done && !block);
- ssh_block2waitfor(conn, block);
+ ssh_block2waitfor(data, block);
return result;
}
-static CURLcode ssh_block_statemach(struct connectdata *conn,
- bool duringconnect)
+static CURLcode ssh_block_statemach(struct Curl_easy *data,
+ struct connectdata *conn,
+ bool duringconnect)
{
struct ssh_conn *sshc = &conn->proto.sshc;
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
while((sshc->state != SSH_STOP) && !result) {
bool block;
timediff_t left = 1000;
struct curltime now = Curl_now();
- result = ssh_statemach_act(conn, &block);
+ result = ssh_statemach_act(data, &block);
if(result)
break;
- if(Curl_pgrsUpdate(conn))
+ if(Curl_pgrsUpdate(data))
return CURLE_ABORTED_BY_CALLBACK;
result = Curl_speedcheck(data, now);
@@ -2961,7 +2958,6 @@ static CURLcode ssh_block_statemach(struct connectdata *conn,
return CURLE_OPERATION_TIMEDOUT;
}
-#ifdef HAVE_LIBSSH2_SESSION_BLOCK_DIRECTION
if(block) {
int dir = libssh2_session_block_directions(sshc->ssh_session);
curl_socket_t sock = conn->sock[FIRSTSOCKET];
@@ -2975,8 +2971,6 @@ static CURLcode ssh_block_statemach(struct connectdata *conn,
(void)Curl_socket_check(fd_read, CURL_SOCKET_BAD, fd_write,
left>1000?1000:left);
}
-#endif
-
}
return result;
@@ -2985,11 +2979,13 @@ static CURLcode ssh_block_statemach(struct connectdata *conn,
/*
* SSH setup and connection
*/
-static CURLcode ssh_setup_connection(struct connectdata *conn)
+static CURLcode ssh_setup_connection(struct Curl_easy *data,
+ struct connectdata *conn)
{
struct SSHPROTO *ssh;
+ (void)conn;
- conn->data->req.protop = ssh = calloc(1, sizeof(struct SSHPROTO));
+ data->req.p.ssh = ssh = calloc(1, sizeof(struct SSHPROTO));
if(!ssh)
return CURLE_OUT_OF_MEMORY;
@@ -2999,36 +2995,83 @@ static CURLcode ssh_setup_connection(struct connectdata *conn)
static Curl_recv scp_recv, sftp_recv;
static Curl_send scp_send, sftp_send;
+#ifndef CURL_DISABLE_PROXY
+static ssize_t ssh_tls_recv(libssh2_socket_t sock, void *buffer,
+ size_t length, int flags, void **abstract)
+{
+ struct Curl_easy *data = (struct Curl_easy *)*abstract;
+ ssize_t nread;
+ CURLcode result;
+ struct connectdata *conn = data->conn;
+ Curl_recv *backup = conn->recv[0];
+ struct ssh_conn *ssh = &conn->proto.sshc;
+ (void)flags;
+
+ /* swap in the TLS reader function for this call only, and then swap back
+ the SSH one again */
+ conn->recv[0] = ssh->tls_recv;
+ result = Curl_read(data, sock, buffer, length, &nread);
+ conn->recv[0] = backup;
+ if(result == CURLE_AGAIN)
+ return -EAGAIN; /* magic return code for libssh2 */
+ else if(result)
+ return -1; /* generic error */
+ Curl_debug(data, CURLINFO_DATA_IN, (char *)buffer, (size_t)nread);
+ return nread;
+}
+
+static ssize_t ssh_tls_send(libssh2_socket_t sock, const void *buffer,
+ size_t length, int flags, void **abstract)
+{
+ struct Curl_easy *data = (struct Curl_easy *)*abstract;
+ ssize_t nwrite;
+ CURLcode result;
+ struct connectdata *conn = data->conn;
+ Curl_send *backup = conn->send[0];
+ struct ssh_conn *ssh = &conn->proto.sshc;
+ (void)flags;
+
+ /* swap in the TLS writer function for this call only, and then swap back
+ the SSH one again */
+ conn->send[0] = ssh->tls_send;
+ result = Curl_write(data, sock, buffer, length, &nwrite);
+ conn->send[0] = backup;
+ if(result == CURLE_AGAIN)
+ return -EAGAIN; /* magic return code for libssh2 */
+ else if(result)
+ return -1; /* error */
+ Curl_debug(data, CURLINFO_DATA_OUT, (char *)buffer, (size_t)nwrite);
+ return nwrite;
+}
+#endif
+
/*
* Curl_ssh_connect() gets called from Curl_protocol_connect() to allow us to
* do protocol-specific actions at connect-time.
*/
-static CURLcode ssh_connect(struct connectdata *conn, bool *done)
+static CURLcode ssh_connect(struct Curl_easy *data, bool *done)
{
#ifdef CURL_LIBSSH2_DEBUG
curl_socket_t sock;
#endif
- struct ssh_conn *ssh;
+ struct SSHPROTO *sshp = data->req.p.ssh;
+ struct ssh_conn *sshc;
CURLcode result;
- struct Curl_easy *data = conn->data;
+ struct connectdata *conn = data->conn;
/* initialize per-handle data if not already */
- if(!data->req.protop)
- ssh_setup_connection(conn);
+ if(!sshp) {
+ result = ssh_setup_connection(data, conn);
+ if(result)
+ return result;
+ sshp = data->req.p.ssh;
+ }
/* We default to persistent connections. We set this already in this connect
function to make the re-use checks properly be able to check this bit. */
connkeep(conn, "SSH default");
- if(conn->handler->protocol & CURLPROTO_SCP) {
- conn->recv[FIRSTSOCKET] = scp_recv;
- conn->send[FIRSTSOCKET] = scp_send;
- }
- else {
- conn->recv[FIRSTSOCKET] = sftp_recv;
- conn->send[FIRSTSOCKET] = sftp_send;
- }
- ssh = &conn->proto.sshc;
+ sshc = &conn->proto.sshc;
#ifdef CURL_LIBSSH2_DEBUG
if(conn->user) {
@@ -3040,17 +3083,72 @@ static CURLcode ssh_connect(struct connectdata *conn, bool *done)
sock = conn->sock[FIRSTSOCKET];
#endif /* CURL_LIBSSH2_DEBUG */
- ssh->ssh_session = libssh2_session_init_ex(my_libssh2_malloc,
- my_libssh2_free,
- my_libssh2_realloc, conn);
- if(ssh->ssh_session == NULL) {
+ sshc->ssh_session = libssh2_session_init_ex(my_libssh2_malloc,
+ my_libssh2_free,
+ my_libssh2_realloc, data);
+ if(sshc->ssh_session == NULL) {
failf(data, "Failure initialising ssh session");
return CURLE_FAILED_INIT;
}
+#ifndef CURL_DISABLE_PROXY
+ if(conn->http_proxy.proxytype == CURLPROXY_HTTPS) {
+ /*
+ * This crazy union dance is here to avoid assigning a void pointer a
+ * function pointer as it is invalid C. The problem is of course that
+ * libssh2 has such an API...
+ */
+ union receive {
+ void *recvp;
+ ssize_t (*recvptr)(libssh2_socket_t, void *, size_t, int, void **);
+ };
+ union transfer {
+ void *sendp;
+ ssize_t (*sendptr)(libssh2_socket_t, const void *, size_t, int, void **);
+ };
+ union receive sshrecv;
+ union transfer sshsend;
+
+ sshrecv.recvptr = ssh_tls_recv;
+ sshsend.sendptr = ssh_tls_send;
+
+ infof(data, "Uses HTTPS proxy!\n");
+ /*
+ Setup libssh2 callbacks to make it read/write TLS from the socket.
+
+ ssize_t
+ recvcb(libssh2_socket_t sock, void *buffer, size_t length,
+ int flags, void **abstract);
+
+ ssize_t
+ sendcb(libssh2_socket_t sock, const void *buffer, size_t length,
+ int flags, void **abstract);
+
+ */
+ libssh2_session_callback_set(sshc->ssh_session,
+ LIBSSH2_CALLBACK_RECV, sshrecv.recvp);
+ libssh2_session_callback_set(sshc->ssh_session,
+ LIBSSH2_CALLBACK_SEND, sshsend.sendp);
+
+ /* Store the underlying TLS recv/send function pointers to be used when
+ reading from the proxy */
+ sshc->tls_recv = conn->recv[FIRSTSOCKET];
+ sshc->tls_send = conn->send[FIRSTSOCKET];
+ }
+
+#endif /* CURL_DISABLE_PROXY */
+ if(conn->handler->protocol & CURLPROTO_SCP) {
+ conn->recv[FIRSTSOCKET] = scp_recv;
+ conn->send[FIRSTSOCKET] = scp_send;
+ }
+ else {
+ conn->recv[FIRSTSOCKET] = sftp_recv;
+ conn->send[FIRSTSOCKET] = sftp_send;
+ }
+
if(data->set.ssh_compression) {
#if LIBSSH2_VERSION_NUM >= 0x010208
- if(libssh2_session_flag(ssh->ssh_session, LIBSSH2_FLAG_COMPRESS, 1) < 0)
+ if(libssh2_session_flag(sshc->ssh_session, LIBSSH2_FLAG_COMPRESS, 1) < 0)
#endif
infof(data, "Failed to enable compression for ssh session\n");
}
@@ -3058,14 +3156,14 @@ static CURLcode ssh_connect(struct connectdata *conn, bool *done)
#ifdef HAVE_LIBSSH2_KNOWNHOST_API
if(data->set.str[STRING_SSH_KNOWNHOSTS]) {
int rc;
- ssh->kh = libssh2_knownhost_init(ssh->ssh_session);
- if(!ssh->kh) {
- libssh2_session_free(ssh->ssh_session);
+ sshc->kh = libssh2_knownhost_init(sshc->ssh_session);
+ if(!sshc->kh) {
+ libssh2_session_free(sshc->ssh_session);
return CURLE_FAILED_INIT;
}
/* read all known hosts from there */
- rc = libssh2_knownhost_readfile(ssh->kh,
+ rc = libssh2_knownhost_readfile(sshc->kh,
data->set.str[STRING_SSH_KNOWNHOSTS],
LIBSSH2_KNOWNHOST_FILE_OPENSSH);
if(rc < 0)
@@ -3075,13 +3173,13 @@ static CURLcode ssh_connect(struct connectdata *conn, bool *done)
#endif /* HAVE_LIBSSH2_KNOWNHOST_API */
#ifdef CURL_LIBSSH2_DEBUG
- libssh2_trace(ssh->ssh_session, ~0);
+ libssh2_trace(sshc->ssh_session, ~0);
infof(data, "SSH socket: %d\n", (int)sock);
#endif /* CURL_LIBSSH2_DEBUG */
- state(conn, SSH_INIT);
+ state(data, SSH_INIT);
- result = ssh_multi_statemach(conn, done);
+ result = ssh_multi_statemach(data, done);
return result;
}
@@ -3096,40 +3194,41 @@ static CURLcode ssh_connect(struct connectdata *conn, bool *done)
*/
static
-CURLcode scp_perform(struct connectdata *conn,
- bool *connected,
- bool *dophase_done)
+CURLcode scp_perform(struct Curl_easy *data,
+ bool *connected,
+ bool *dophase_done)
{
CURLcode result = CURLE_OK;
+ struct connectdata *conn = data->conn;
- DEBUGF(infof(conn->data, "DO phase starts\n"));
+ DEBUGF(infof(data, "DO phase starts\n"));
*dophase_done = FALSE; /* not done yet */
/* start the first command in the DO phase */
- state(conn, SSH_SCP_TRANS_INIT);
+ state(data, SSH_SCP_TRANS_INIT);
/* run the state-machine */
- result = ssh_multi_statemach(conn, dophase_done);
+ result = ssh_multi_statemach(data, dophase_done);
*connected = conn->bits.tcpconnect[FIRSTSOCKET];
if(*dophase_done) {
- DEBUGF(infof(conn->data, "DO phase is complete\n"));
+ DEBUGF(infof(data, "DO phase is complete\n"));
}
return result;
}
/* called from multi.c while DOing */
-static CURLcode scp_doing(struct connectdata *conn,
- bool *dophase_done)
+static CURLcode scp_doing(struct Curl_easy *data,
+ bool *dophase_done)
{
CURLcode result;
- result = ssh_multi_statemach(conn, dophase_done);
+ result = ssh_multi_statemach(data, dophase_done);
if(*dophase_done) {
- DEBUGF(infof(conn->data, "DO phase is complete\n"));
+ DEBUGF(infof(data, "DO phase is complete\n"));
}
return result;
}
@@ -3139,11 +3238,11 @@ static CURLcode scp_doing(struct connectdata *conn,
* separate ones but this way means less duplicated code.
*/
-static CURLcode ssh_do(struct connectdata *conn, bool *done)
+static CURLcode ssh_do(struct Curl_easy *data, bool *done)
{
CURLcode result;
bool connected = 0;
- struct Curl_easy *data = conn->data;
+ struct connectdata *conn = data->conn;
struct ssh_conn *sshc = &conn->proto.sshc;
*done = FALSE; /* default to false */
@@ -3160,9 +3259,9 @@ static CURLcode ssh_do(struct connectdata *conn, bool *done)
Curl_pgrsSetDownloadSize(data, -1);
if(conn->handler->protocol & CURLPROTO_SCP)
- result = scp_perform(conn, &connected, done);
+ result = scp_perform(data, &connected, done);
else
- result = sftp_perform(conn, &connected, done);
+ result = sftp_perform(data, &connected, done);
return result;
}
@@ -3170,18 +3269,20 @@ static CURLcode ssh_do(struct connectdata *conn, bool *done)
/* BLOCKING, but the function is using the state machine so the only reason
this is still blocking is that the multi interface code has no support for
disconnecting operations that takes a while */
-static CURLcode scp_disconnect(struct connectdata *conn, bool dead_connection)
+static CURLcode scp_disconnect(struct Curl_easy *data,
+ struct connectdata *conn,
+ bool dead_connection)
{
CURLcode result = CURLE_OK;
- struct ssh_conn *ssh = &conn->proto.sshc;
+ struct ssh_conn *sshc = &conn->proto.sshc;
(void) dead_connection;
- if(ssh->ssh_session) {
+ if(sshc->ssh_session) {
/* only if there's a session still around to use! */
- state(conn, SSH_SESSION_DISCONNECT);
+ state(data, SSH_SESSION_DISCONNECT);
- result = ssh_block_statemach(conn, FALSE);
+ result = ssh_block_statemach(data, conn, FALSE);
}
return result;
@@ -3189,51 +3290,56 @@ static CURLcode scp_disconnect(struct connectdata *conn, bool dead_connection)
/* generic done function for both SCP and SFTP called from their specific
done functions */
-static CURLcode ssh_done(struct connectdata *conn, CURLcode status)
+static CURLcode ssh_done(struct Curl_easy *data, CURLcode status)
{
CURLcode result = CURLE_OK;
- struct SSHPROTO *sftp_scp = conn->data->req.protop;
+ struct SSHPROTO *sshp = data->req.p.ssh;
+ struct connectdata *conn = data->conn;
if(!status) {
/* run the state-machine */
- result = ssh_block_statemach(conn, FALSE);
+ result = ssh_block_statemach(data, conn, FALSE);
}
else
result = status;
- if(sftp_scp)
- Curl_safefree(sftp_scp->path);
- if(Curl_pgrsDone(conn))
+ Curl_safefree(sshp->path);
+ Curl_safefree(sshp->readdir_filename);
+ Curl_safefree(sshp->readdir_longentry);
+ Curl_dyn_free(&sshp->readdir);
+
+ if(Curl_pgrsDone(data))
return CURLE_ABORTED_BY_CALLBACK;
- conn->data->req.keepon = 0; /* clear all bits */
+ data->req.keepon = 0; /* clear all bits */
return result;
}
-static CURLcode scp_done(struct connectdata *conn, CURLcode status,
+static CURLcode scp_done(struct Curl_easy *data, CURLcode status,
bool premature)
{
(void)premature; /* not used */
if(!status)
- state(conn, SSH_SCP_DONE);
+ state(data, SSH_SCP_DONE);
- return ssh_done(conn, status);
+ return ssh_done(data, status);
}
-static ssize_t scp_send(struct connectdata *conn, int sockindex,
+static ssize_t scp_send(struct Curl_easy *data, int sockindex,
const void *mem, size_t len, CURLcode *err)
{
ssize_t nwrite;
+ struct connectdata *conn = data->conn;
+ struct ssh_conn *sshc = &conn->proto.sshc;
(void)sockindex; /* we only support SCP on the fixed known primary socket */
/* libssh2_channel_write() returns int! */
- nwrite = (ssize_t)
- libssh2_channel_write(conn->proto.sshc.ssh_channel, mem, len);
+ nwrite = (ssize_t) libssh2_channel_write(sshc->ssh_channel, mem, len);
- ssh_block2waitfor(conn, (nwrite == LIBSSH2_ERROR_EAGAIN)?TRUE:FALSE);
+ ssh_block2waitfor(data, (nwrite == LIBSSH2_ERROR_EAGAIN)?TRUE:FALSE);
if(nwrite == LIBSSH2_ERROR_EAGAIN) {
*err = CURLE_AGAIN;
@@ -3247,17 +3353,18 @@ static ssize_t scp_send(struct connectdata *conn, int sockindex,
return nwrite;
}
-static ssize_t scp_recv(struct connectdata *conn, int sockindex,
+static ssize_t scp_recv(struct Curl_easy *data, int sockindex,
char *mem, size_t len, CURLcode *err)
{
ssize_t nread;
+ struct connectdata *conn = data->conn;
+ struct ssh_conn *sshc = &conn->proto.sshc;
(void)sockindex; /* we only support SCP on the fixed known primary socket */
/* libssh2_channel_read() returns int */
- nread = (ssize_t)
- libssh2_channel_read(conn->proto.sshc.ssh_channel, mem, len);
+ nread = (ssize_t) libssh2_channel_read(sshc->ssh_channel, mem, len);
- ssh_block2waitfor(conn, (nread == LIBSSH2_ERROR_EAGAIN)?TRUE:FALSE);
+ ssh_block2waitfor(data, (nread == LIBSSH2_ERROR_EAGAIN)?TRUE:FALSE);
if(nread == LIBSSH2_ERROR_EAGAIN) {
*err = CURLE_AGAIN;
nread = -1;
@@ -3280,39 +3387,39 @@ static ssize_t scp_recv(struct connectdata *conn, int sockindex,
*/
static
-CURLcode sftp_perform(struct connectdata *conn,
+CURLcode sftp_perform(struct Curl_easy *data,
bool *connected,
bool *dophase_done)
{
CURLcode result = CURLE_OK;
- DEBUGF(infof(conn->data, "DO phase starts\n"));
+ DEBUGF(infof(data, "DO phase starts\n"));
*dophase_done = FALSE; /* not done yet */
/* start the first command in the DO phase */
- state(conn, SSH_SFTP_QUOTE_INIT);
+ state(data, SSH_SFTP_QUOTE_INIT);
/* run the state-machine */
- result = ssh_multi_statemach(conn, dophase_done);
+ result = ssh_multi_statemach(data, dophase_done);
- *connected = conn->bits.tcpconnect[FIRSTSOCKET];
+ *connected = data->conn->bits.tcpconnect[FIRSTSOCKET];
if(*dophase_done) {
- DEBUGF(infof(conn->data, "DO phase is complete\n"));
+ DEBUGF(infof(data, "DO phase is complete\n"));
}
return result;
}
/* called from multi.c while DOing */
-static CURLcode sftp_doing(struct connectdata *conn,
+static CURLcode sftp_doing(struct Curl_easy *data,
bool *dophase_done)
{
- CURLcode result = ssh_multi_statemach(conn, dophase_done);
+ CURLcode result = ssh_multi_statemach(data, dophase_done);
if(*dophase_done) {
- DEBUGF(infof(conn->data, "DO phase is complete\n"));
+ DEBUGF(infof(data, "DO phase is complete\n"));
}
return result;
}
@@ -3320,53 +3427,56 @@ static CURLcode sftp_doing(struct connectdata *conn,
/* BLOCKING, but the function is using the state machine so the only reason
this is still blocking is that the multi interface code has no support for
disconnecting operations that takes a while */
-static CURLcode sftp_disconnect(struct connectdata *conn, bool dead_connection)
+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;
(void) dead_connection;
- DEBUGF(infof(conn->data, "SSH DISCONNECT starts now\n"));
+ DEBUGF(infof(data, "SSH DISCONNECT starts now\n"));
- if(conn->proto.sshc.ssh_session) {
+ if(sshc->ssh_session) {
/* only if there's a session still around to use! */
- state(conn, SSH_SFTP_SHUTDOWN);
- result = ssh_block_statemach(conn, FALSE);
+ state(data, SSH_SFTP_SHUTDOWN);
+ result = ssh_block_statemach(data, conn, FALSE);
}
- DEBUGF(infof(conn->data, "SSH DISCONNECT is done\n"));
+ DEBUGF(infof(data, "SSH DISCONNECT is done\n"));
return result;
}
-static CURLcode sftp_done(struct connectdata *conn, CURLcode status,
+static CURLcode sftp_done(struct Curl_easy *data, CURLcode status,
bool premature)
{
+ struct connectdata *conn = data->conn;
struct ssh_conn *sshc = &conn->proto.sshc;
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 && conn->data->set.postquote && !conn->bits.retry)
+ if(!premature && data->set.postquote && !conn->bits.retry)
sshc->nextstate = SSH_SFTP_POSTQUOTE_INIT;
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
}
- return ssh_done(conn, status);
+ return ssh_done(data, status);
}
/* return number of sent bytes */
-static ssize_t sftp_send(struct connectdata *conn, int sockindex,
+static ssize_t sftp_send(struct Curl_easy *data, int sockindex,
const void *mem, size_t len, CURLcode *err)
{
- ssize_t nwrite; /* libssh2_sftp_write() used to return size_t in 0.14
- but is changed to ssize_t in 0.15. These days we don't
- support libssh2 0.15*/
+ ssize_t nwrite;
+ struct connectdata *conn = data->conn;
+ struct ssh_conn *sshc = &conn->proto.sshc;
(void)sockindex;
- nwrite = libssh2_sftp_write(conn->proto.sshc.sftp_handle, mem, len);
+ nwrite = libssh2_sftp_write(sshc->sftp_handle, mem, len);
- ssh_block2waitfor(conn, (nwrite == LIBSSH2_ERROR_EAGAIN)?TRUE:FALSE);
+ ssh_block2waitfor(data, (nwrite == LIBSSH2_ERROR_EAGAIN)?TRUE:FALSE);
if(nwrite == LIBSSH2_ERROR_EAGAIN) {
*err = CURLE_AGAIN;
@@ -3384,15 +3494,17 @@ static ssize_t sftp_send(struct connectdata *conn, int sockindex,
* Return number of received (decrypted) bytes
* or <0 on error
*/
-static ssize_t sftp_recv(struct connectdata *conn, int sockindex,
+static ssize_t sftp_recv(struct Curl_easy *data, int sockindex,
char *mem, size_t len, CURLcode *err)
{
ssize_t nread;
+ struct connectdata *conn = data->conn;
+ struct ssh_conn *sshc = &conn->proto.sshc;
(void)sockindex;
- nread = libssh2_sftp_read(conn->proto.sshc.sftp_handle, mem, len);
+ nread = libssh2_sftp_read(sshc->sftp_handle, mem, len);
- ssh_block2waitfor(conn, (nread == LIBSSH2_ERROR_EAGAIN)?TRUE:FALSE);
+ ssh_block2waitfor(data, (nread == LIBSSH2_ERROR_EAGAIN)?TRUE:FALSE);
if(nread == LIBSSH2_ERROR_EAGAIN) {
*err = CURLE_AGAIN;
diff --git a/Utilities/cmcurl/lib/vssh/ssh.h b/Utilities/cmcurl/lib/vssh/ssh.h
index 9e49993e9..52e1ee6c2 100644
--- a/Utilities/cmcurl/lib/vssh/ssh.h
+++ b/Utilities/cmcurl/lib/vssh/ssh.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -111,6 +111,17 @@ typedef enum {
struct. */
struct SSHPROTO {
char *path; /* the path we operate on */
+#ifdef USE_LIBSSH2
+ struct dynbuf readdir_link;
+ struct dynbuf readdir;
+ char *readdir_filename;
+ char *readdir_longentry;
+
+ LIBSSH2_SFTP_ATTRIBUTES quote_attrs; /* used by the SFTP_QUOTE state */
+
+ /* Here's a set of struct members used by the SFTP_READDIR state */
+ LIBSSH2_SFTP_ATTRIBUTES readdir_attrs;
+#endif
};
/* ssh_conn is used for struct connection-oriented data in the connectdata
@@ -123,6 +134,8 @@ struct ssh_conn {
char *rsa_pub; /* path name */
char *rsa; /* path name */
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 */
@@ -130,8 +143,6 @@ struct ssh_conn {
char *quote_path1; /* two generic pointers for the QUOTE stuff */
char *quote_path2;
- bool acceptfail; /* used by the SFTP_QUOTE (continue if
- quote command fails) */
char *homedir; /* when doing SFTP we figure out home dir in the
connect phase */
char *readdir_line;
@@ -140,9 +151,8 @@ struct ssh_conn {
int secondCreateDirs; /* counter use by the code to see if the
second attempt has been made to change
to/create a directory */
- char *slash_pos; /* used by the SFTP_CREATE_DIRS state */
-
int orig_waitfor; /* default READ/WRITE bits wait for */
+ char *slash_pos; /* used by the SFTP_CREATE_DIRS state */
#if defined(USE_LIBSSH)
char *readdir_linkPath;
@@ -168,20 +178,17 @@ struct ssh_conn {
const char *readdir_longentry;
char *readdir_tmp;
#elif defined(USE_LIBSSH2)
- struct dynbuf readdir_link;
- struct dynbuf readdir;
- char *readdir_filename;
- char *readdir_longentry;
-
- LIBSSH2_SFTP_ATTRIBUTES quote_attrs; /* used by the SFTP_QUOTE state */
-
- /* Here's a set of struct members used by the SFTP_READDIR state */
- LIBSSH2_SFTP_ATTRIBUTES readdir_attrs;
LIBSSH2_SESSION *ssh_session; /* Secure Shell session */
LIBSSH2_CHANNEL *ssh_channel; /* Secure Shell channel handle */
LIBSSH2_SFTP *sftp_session; /* SFTP handle */
LIBSSH2_SFTP_HANDLE *sftp_handle;
+#ifndef CURL_DISABLE_PROXY
+ /* for HTTPS proxy storage */
+ Curl_recv *tls_recv;
+ Curl_send *tls_send;
+#endif
+
#ifdef HAVE_LIBSSH2_AGENT_API
LIBSSH2_AGENT *ssh_agent; /* proxy to ssh-agent/pageant */
struct libssh2_agent_publickey *sshagent_identity,
diff --git a/Utilities/cmcurl/lib/vssh/wolfssh.c b/Utilities/cmcurl/lib/vssh/wolfssh.c
index dcbbab6c3..6020180a5 100644
--- a/Utilities/cmcurl/lib/vssh/wolfssh.c
+++ b/Utilities/cmcurl/lib/vssh/wolfssh.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2019 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2019 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -45,27 +45,30 @@
#include "curl_memory.h"
#include "memdebug.h"
-static CURLcode wssh_connect(struct connectdata *conn, bool *done);
-static CURLcode wssh_multi_statemach(struct connectdata *conn, bool *done);
-static CURLcode wssh_do(struct connectdata *conn, bool *done);
+static CURLcode wssh_connect(struct Curl_easy *data, bool *done);
+static CURLcode wssh_multi_statemach(struct Curl_easy *data, bool *done);
+static CURLcode wssh_do(struct Curl_easy *data, bool *done);
#if 0
-static CURLcode wscp_done(struct connectdata *conn,
+static CURLcode wscp_done(struct Curl_easy *data,
CURLcode, bool premature);
-static CURLcode wscp_doing(struct connectdata *conn,
+static CURLcode wscp_doing(struct Curl_easy *data,
bool *dophase_done);
-static CURLcode wscp_disconnect(struct connectdata *conn,
+static CURLcode wscp_disconnect(struct Curl_easy *data,
+ struct connectdata *conn,
bool dead_connection);
#endif
-static CURLcode wsftp_done(struct connectdata *conn,
+static CURLcode wsftp_done(struct Curl_easy *data,
CURLcode, bool premature);
-static CURLcode wsftp_doing(struct connectdata *conn,
+static CURLcode wsftp_doing(struct Curl_easy *data,
bool *dophase_done);
-static CURLcode wsftp_disconnect(struct connectdata *conn, bool dead);
-static int wssh_getsock(struct connectdata *conn,
+static CURLcode wsftp_disconnect(struct Curl_easy *data,
+ struct connectdata *conn,
+ bool dead);
+static int wssh_getsock(struct Curl_easy *data,
+ struct connectdata *conn,
curl_socket_t *sock);
-static int wssh_perform_getsock(const struct connectdata *conn,
- curl_socket_t *sock);
-static CURLcode wssh_setup_connection(struct connectdata *conn);
+static CURLcode wssh_setup_connection(struct Curl_easy *data,
+ struct connectdata *conn);
#if 0
/*
@@ -84,7 +87,7 @@ const struct Curl_handler Curl_handler_scp = {
wssh_getsock, /* proto_getsock */
wssh_getsock, /* doing_getsock */
ZERO_NULL, /* domore_getsock */
- wssh_perform_getsock, /* perform_getsock */
+ wssh_getsock, /* perform_getsock */
wscp_disconnect, /* disconnect */
ZERO_NULL, /* readwrite */
ZERO_NULL, /* connection_check */
@@ -112,12 +115,13 @@ const struct Curl_handler Curl_handler_sftp = {
wssh_getsock, /* proto_getsock */
wssh_getsock, /* doing_getsock */
ZERO_NULL, /* domore_getsock */
- wssh_perform_getsock, /* perform_getsock */
+ wssh_getsock, /* perform_getsock */
wsftp_disconnect, /* disconnect */
ZERO_NULL, /* readwrite */
ZERO_NULL, /* connection_check */
PORT_SSH, /* defport */
CURLPROTO_SFTP, /* protocol */
+ CURLPROTO_SFTP, /* family */
PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION
| PROTOPT_NOURLQUERY /* flags */
};
@@ -126,8 +130,9 @@ 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 connectdata *conn, sshstate nowstate)
+static void state(struct Curl_easy *data, 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 */
@@ -198,7 +203,7 @@ static void state(struct connectdata *conn, sshstate nowstate)
DEBUGASSERT(sizeof(names)/sizeof(names[0]) == SSH_LAST);
if(sshc->state != nowstate) {
- infof(conn->data, "wolfssh %p state change from %s to %s\n",
+ infof(data, "wolfssh %p state change from %s to %s\n",
(void *)sshc, names[sshc->state], names[nowstate]);
}
#endif
@@ -206,11 +211,11 @@ static void state(struct connectdata *conn, sshstate nowstate)
sshc->state = nowstate;
}
-static ssize_t wscp_send(struct connectdata *conn, int sockindex,
+static ssize_t wscp_send(struct Curl_easy *data, int sockindex,
const void *mem, size_t len, CURLcode *err)
{
ssize_t nwrite = 0;
- (void)conn;
+ (void)data;
(void)sockindex; /* we only support SCP on the fixed known primary socket */
(void)mem;
(void)len;
@@ -219,11 +224,11 @@ static ssize_t wscp_send(struct connectdata *conn, int sockindex,
return nwrite;
}
-static ssize_t wscp_recv(struct connectdata *conn, int sockindex,
+static ssize_t wscp_recv(struct Curl_easy *data, int sockindex,
char *mem, size_t len, CURLcode *err)
{
ssize_t nread = 0;
- (void)conn;
+ (void)data;
(void)sockindex; /* we only support SCP on the fixed known primary socket */
(void)mem;
(void)len;
@@ -233,9 +238,10 @@ static ssize_t wscp_recv(struct connectdata *conn, int sockindex,
}
/* return number of sent bytes */
-static ssize_t wsftp_send(struct connectdata *conn, int sockindex,
+static ssize_t wsftp_send(struct Curl_easy *data, int sockindex,
const void *mem, size_t len, CURLcode *err)
{
+ struct connectdata *conn = data->conn;
struct ssh_conn *sshc = &conn->proto.sshc;
word32 offset[2];
int rc;
@@ -262,11 +268,11 @@ static ssize_t wsftp_send(struct connectdata *conn, int sockindex,
return -1;
}
if(rc < 0) {
- failf(conn->data, "wolfSSH_SFTP_SendWritePacket returned %d\n", rc);
+ failf(data, "wolfSSH_SFTP_SendWritePacket returned %d", rc);
return -1;
}
DEBUGASSERT(rc == (int)len);
- infof(conn->data, "sent %zd bytes SFTP from offset %zd\n",
+ infof(data, "sent %zd bytes SFTP from offset %zd\n",
len, sshc->offset);
sshc->offset += len;
return (ssize_t)rc;
@@ -276,10 +282,11 @@ static ssize_t wsftp_send(struct connectdata *conn, int sockindex,
* Return number of received (decrypted) bytes
* or <0 on error
*/
-static ssize_t wsftp_recv(struct connectdata *conn, int sockindex,
+static ssize_t wsftp_recv(struct Curl_easy *data, int sockindex,
char *mem, size_t len, CURLcode *err)
{
int rc;
+ struct connectdata *conn = data->conn;
struct ssh_conn *sshc = &conn->proto.sshc;
word32 offset[2];
(void)sockindex;
@@ -307,7 +314,7 @@ static ssize_t wsftp_recv(struct connectdata *conn, int sockindex,
DEBUGASSERT(rc <= (int)len);
if(rc < 0) {
- failf(conn->data, "wolfSSH_SFTP_SendReadPacket returned %d\n", rc);
+ failf(data, "wolfSSH_SFTP_SendReadPacket returned %d", rc);
return -1;
}
sshc->offset += len;
@@ -318,11 +325,13 @@ static ssize_t wsftp_recv(struct connectdata *conn, int sockindex,
/*
* SSH setup and connection
*/
-static CURLcode wssh_setup_connection(struct connectdata *conn)
+static CURLcode wssh_setup_connection(struct Curl_easy *data,
+ struct connectdata *conn)
{
struct SSHPROTO *ssh;
+ (void)conn;
- conn->data->req.protop = ssh = calloc(1, sizeof(struct SSHPROTO));
+ data->req.p.ssh = ssh = calloc(1, sizeof(struct SSHPROTO));
if(!ssh)
return CURLE_OUT_OF_MEMORY;
@@ -336,28 +345,28 @@ static int userauth(byte authtype,
WS_UserAuthData* authdata,
void *ctx)
{
- struct connectdata *conn = ctx;
- DEBUGF(infof(conn->data, "wolfssh callback: type %s\n",
+ struct Curl_easy *data = ctx;
+ DEBUGF(infof(data, "wolfssh callback: type %s\n",
authtype == WOLFSSH_USERAUTH_PASSWORD ? "PASSWORD" :
"PUBLICCKEY"));
if(authtype == WOLFSSH_USERAUTH_PASSWORD) {
- authdata->sf.password.password = (byte *)conn->passwd;
- authdata->sf.password.passwordSz = (word32) strlen(conn->passwd);
+ authdata->sf.password.password = (byte *)data->conn->passwd;
+ authdata->sf.password.passwordSz = (word32) strlen(data->conn->passwd);
}
return 0;
}
-static CURLcode wssh_connect(struct connectdata *conn, bool *done)
+static CURLcode wssh_connect(struct Curl_easy *data, bool *done)
{
- struct Curl_easy *data = conn->data;
+ struct connectdata *conn = data->conn;
struct ssh_conn *sshc;
curl_socket_t sock = conn->sock[FIRSTSOCKET];
int rc;
/* initialize per-handle data if not already */
- if(!data->req.protop)
- wssh_setup_connection(conn);
+ if(!data->req.p.ssh)
+ wssh_setup_connection(data, conn);
/* We default to persistent connections. We set this already in this connect
function to make the re-use checks properly be able to check this bit. */
@@ -392,7 +401,7 @@ static CURLcode wssh_connect(struct connectdata *conn, bool *done)
/* set callback for authentication */
wolfSSH_SetUserAuth(sshc->ctx, userauth);
- wolfSSH_SetUserAuthCtx(sshc->ssh_session, conn);
+ wolfSSH_SetUserAuthCtx(sshc->ssh_session, data);
rc = wolfSSH_set_fd(sshc->ssh_session, (int)sock);
if(rc) {
@@ -406,11 +415,11 @@ static CURLcode wssh_connect(struct connectdata *conn, bool *done)
*done = TRUE;
if(conn->handler->protocol & CURLPROTO_SCP)
- state(conn, SSH_INIT);
+ state(data, SSH_INIT);
else
- state(conn, SSH_SFTP_INIT);
+ state(data, SSH_SFTP_INIT);
- return wssh_multi_statemach(conn, done);
+ return wssh_multi_statemach(data, done);
error:
wolfSSH_free(sshc->ssh_session);
wolfSSH_CTX_free(sshc->ctx);
@@ -424,12 +433,12 @@ static CURLcode wssh_connect(struct connectdata *conn, bool *done)
* wants to be called again when the socket is ready
*/
-static CURLcode wssh_statemach_act(struct connectdata *conn, bool *block)
+static CURLcode wssh_statemach_act(struct Curl_easy *data, bool *block)
{
CURLcode result = CURLE_OK;
+ struct connectdata *conn = data->conn;
struct ssh_conn *sshc = &conn->proto.sshc;
- struct Curl_easy *data = conn->data;
- struct SSHPROTO *sftp_scp = data->req.protop;
+ struct SSHPROTO *sftp_scp = data->req.p.ssh;
WS_SFTPNAME *name;
int rc = 0;
*block = FALSE; /* we're not blocking by default */
@@ -437,7 +446,7 @@ static CURLcode wssh_statemach_act(struct connectdata *conn, bool *block)
do {
switch(sshc->state) {
case SSH_INIT:
- state(conn, SSH_S_STARTUP);
+ state(data, SSH_S_STARTUP);
/* FALLTHROUGH */
case SSH_S_STARTUP:
rc = wolfSSH_connect(sshc->ssh_session);
@@ -454,11 +463,11 @@ static CURLcode wssh_statemach_act(struct connectdata *conn, bool *block)
return CURLE_OK;
}
else if(rc != WS_SUCCESS) {
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
return CURLE_SSH;
}
infof(data, "wolfssh connected!\n");
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
break;
case SSH_STOP:
break;
@@ -479,7 +488,7 @@ static CURLcode wssh_statemach_act(struct connectdata *conn, bool *block)
}
else if(rc == WS_SUCCESS) {
infof(data, "wolfssh SFTP connected!\n");
- state(conn, SSH_SFTP_REALPATH);
+ state(data, SSH_SFTP_REALPATH);
}
else {
failf(data, "wolfssh SFTP connect error %d", rc);
@@ -510,45 +519,45 @@ static CURLcode wssh_statemach_act(struct connectdata *conn, bool *block)
infof(data, "wolfssh SFTP realpath succeeded!\n");
}
wolfSSH_SFTPNAME_list_free(name);
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
return CURLE_OK;
}
failf(data, "wolfssh SFTP realpath %d", rc);
return CURLE_SSH;
case SSH_SFTP_QUOTE_INIT:
- result = Curl_getworkingpath(conn, sshc->homedir, &sftp_scp->path);
+ result = Curl_getworkingpath(data, sshc->homedir, &sftp_scp->path);
if(result) {
sshc->actualcode = result;
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
break;
}
if(data->set.quote) {
infof(data, "Sending quote commands\n");
sshc->quote_item = data->set.quote;
- state(conn, SSH_SFTP_QUOTE);
+ state(data, SSH_SFTP_QUOTE);
}
else {
- state(conn, SSH_SFTP_GETINFO);
+ state(data, SSH_SFTP_GETINFO);
}
break;
case SSH_SFTP_GETINFO:
if(data->set.get_filetime) {
- state(conn, SSH_SFTP_FILETIME);
+ state(data, SSH_SFTP_FILETIME);
}
else {
- state(conn, SSH_SFTP_TRANS_INIT);
+ state(data, SSH_SFTP_TRANS_INIT);
}
break;
case SSH_SFTP_TRANS_INIT:
if(data->set.upload)
- state(conn, SSH_SFTP_UPLOAD_INIT);
+ state(data, SSH_SFTP_UPLOAD_INIT);
else {
if(sftp_scp->path[strlen(sftp_scp->path)-1] == '/')
- state(conn, SSH_SFTP_READDIR_INIT);
+ state(data, SSH_SFTP_READDIR_INIT);
else
- state(conn, SSH_SFTP_DOWNLOAD_INIT);
+ state(data, SSH_SFTP_DOWNLOAD_INIT);
}
break;
case SSH_SFTP_UPLOAD_INIT: {
@@ -583,7 +592,7 @@ static CURLcode wssh_statemach_act(struct connectdata *conn, bool *block)
/* If we have restart position then open for append */
flags = WOLFSSH_FXF_WRITE|WOLFSSH_FXF_APPEND;
else
- /* Clear file before writing (normal behaviour) */
+ /* Clear file before writing (normal behavior) */
flags = WOLFSSH_FXF_WRITE|WOLFSSH_FXF_CREAT|WOLFSSH_FXF_TRUNC;
memset(&createattrs, 0, sizeof(createattrs));
@@ -611,7 +620,7 @@ static CURLcode wssh_statemach_act(struct connectdata *conn, bool *block)
failf(data, "wolfssh SFTP upload open failed: %d", rc);
return CURLE_SSH;
}
- state(conn, SSH_SFTP_DOWNLOAD_STAT);
+ state(data, SSH_SFTP_DOWNLOAD_STAT);
/* If we have a restart point then we need to seek to the correct
position. */
@@ -676,7 +685,7 @@ static CURLcode wssh_statemach_act(struct connectdata *conn, bool *block)
conn->sockfd = conn->writesockfd;
if(result) {
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->actualcode = result;
}
else {
@@ -694,7 +703,7 @@ static CURLcode wssh_statemach_act(struct connectdata *conn, bool *block)
timeout here */
Curl_expire(data, 0, EXPIRE_RUN_NOW);
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
}
break;
}
@@ -717,7 +726,7 @@ static CURLcode wssh_statemach_act(struct connectdata *conn, bool *block)
}
else if(rc == WS_SUCCESS) {
infof(data, "wolfssh SFTP open succeeded!\n");
- state(conn, SSH_SFTP_DOWNLOAD_STAT);
+ state(data, SSH_SFTP_DOWNLOAD_STAT);
return CURLE_OK;
}
@@ -762,7 +771,7 @@ static CURLcode wssh_statemach_act(struct connectdata *conn, bool *block)
/* We cannot seek with wolfSSH so resuming and range requests are not
possible */
- if(conn->data->state.use_range || data->state.resume_from) {
+ if(data->state.use_range || data->state.resume_from) {
infof(data, "wolfSSH cannot do range/seek on SFTP\n");
return CURLE_BAD_DOWNLOAD_RESUME;
}
@@ -772,7 +781,7 @@ static CURLcode wssh_statemach_act(struct connectdata *conn, bool *block)
/* no data to transfer */
Curl_setup_transfer(data, -1, -1, FALSE, -1);
infof(data, "File already completely downloaded\n");
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
break;
}
Curl_setup_transfer(data, FIRSTSOCKET, data->req.size, FALSE, -1);
@@ -788,11 +797,11 @@ static CURLcode wssh_statemach_act(struct connectdata *conn, bool *block)
if(result) {
/* this should never occur; the close state should be entered
at the time the error occurs */
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->actualcode = result;
}
else {
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
}
break;
}
@@ -813,7 +822,7 @@ static CURLcode wssh_statemach_act(struct connectdata *conn, bool *block)
return CURLE_OK;
}
else if(rc == WS_SUCCESS) {
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
return CURLE_OK;
}
@@ -823,10 +832,10 @@ static CURLcode wssh_statemach_act(struct connectdata *conn, bool *block)
case SSH_SFTP_READDIR_INIT:
Curl_pgrsSetDownloadSize(data, -1);
if(data->set.opt_no_body) {
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
break;
}
- state(conn, SSH_SFTP_READDIR);
+ state(data, SSH_SFTP_READDIR);
/* FALLTHROUGH */
case SSH_SFTP_READDIR:
name = wolfSSH_SFTP_LS(sshc->ssh_session, sftp_scp->path);
@@ -853,11 +862,11 @@ static CURLcode wssh_statemach_act(struct connectdata *conn, bool *block)
data->set.ftp_list_only ?
name->fName : name->lName);
if(line == NULL) {
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
sshc->actualcode = CURLE_OUT_OF_MEMORY;
break;
}
- result = Curl_client_write(conn, CLIENTWRITE_BODY,
+ result = Curl_client_write(data, CLIENTWRITE_BODY,
line, strlen(line));
free(line);
if(result) {
@@ -867,7 +876,7 @@ static CURLcode wssh_statemach_act(struct connectdata *conn, bool *block)
name = name->next;
}
wolfSSH_SFTPNAME_list_free(origname);
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
return result;
}
failf(data, "wolfssh SFTP ls failed: %d", rc);
@@ -877,7 +886,7 @@ static CURLcode wssh_statemach_act(struct connectdata *conn, bool *block)
Curl_safefree(sshc->homedir);
wolfSSH_free(sshc->ssh_session);
wolfSSH_CTX_free(sshc->ctx);
- state(conn, SSH_STOP);
+ state(data, SSH_STOP);
return CURLE_OK;
default:
break;
@@ -887,19 +896,20 @@ static CURLcode wssh_statemach_act(struct connectdata *conn, bool *block)
}
/* called repeatedly until done from multi.c */
-static CURLcode wssh_multi_statemach(struct connectdata *conn, bool *done)
+static CURLcode wssh_multi_statemach(struct Curl_easy *data, bool *done)
{
+ struct connectdata *conn = data->conn;
struct ssh_conn *sshc = &conn->proto.sshc;
CURLcode result = CURLE_OK;
bool block; /* we store the status and use that to provide a ssh_getsock()
implementation */
do {
- result = wssh_statemach_act(conn, &block);
+ result = wssh_statemach_act(data, &block);
*done = (sshc->state == SSH_STOP) ? TRUE : FALSE;
/* if there's no error, it isn't done and it didn't EWOULDBLOCK, then
try again */
if(*done) {
- DEBUGF(infof(conn->data, "wssh_statemach_act says DONE\n"));
+ DEBUGF(infof(data, "wssh_statemach_act says DONE\n"));
}
} while(!result && !*done && !block);
@@ -907,37 +917,38 @@ static CURLcode wssh_multi_statemach(struct connectdata *conn, bool *done)
}
static
-CURLcode wscp_perform(struct connectdata *conn,
+CURLcode wscp_perform(struct Curl_easy *data,
bool *connected,
bool *dophase_done)
{
- (void)conn;
+ (void)data;
(void)connected;
(void)dophase_done;
return CURLE_OK;
}
static
-CURLcode wsftp_perform(struct connectdata *conn,
+CURLcode wsftp_perform(struct Curl_easy *data,
bool *connected,
bool *dophase_done)
{
CURLcode result = CURLE_OK;
+ struct connectdata *conn = data->conn;
- DEBUGF(infof(conn->data, "DO phase starts\n"));
+ DEBUGF(infof(data, "DO phase starts\n"));
*dophase_done = FALSE; /* not done yet */
/* start the first command in the DO phase */
- state(conn, SSH_SFTP_QUOTE_INIT);
+ state(data, SSH_SFTP_QUOTE_INIT);
/* run the state-machine */
- result = wssh_multi_statemach(conn, dophase_done);
+ result = wssh_multi_statemach(data, dophase_done);
*connected = conn->bits.tcpconnect[FIRSTSOCKET];
if(*dophase_done) {
- DEBUGF(infof(conn->data, "DO phase is complete\n"));
+ DEBUGF(infof(data, "DO phase is complete\n"));
}
return result;
@@ -946,11 +957,11 @@ CURLcode wsftp_perform(struct connectdata *conn,
/*
* The DO function is generic for both protocols.
*/
-static CURLcode wssh_do(struct connectdata *conn, bool *done)
+static CURLcode wssh_do(struct Curl_easy *data, bool *done)
{
CURLcode result;
bool connected = 0;
- struct Curl_easy *data = conn->data;
+ struct connectdata *conn = data->conn;
struct ssh_conn *sshc = &conn->proto.sshc;
*done = FALSE; /* default to false */
@@ -965,31 +976,31 @@ static CURLcode wssh_do(struct connectdata *conn, bool *done)
Curl_pgrsSetDownloadSize(data, -1);
if(conn->handler->protocol & CURLPROTO_SCP)
- result = wscp_perform(conn, &connected, done);
+ result = wscp_perform(data, &connected, done);
else
- result = wsftp_perform(conn, &connected, done);
+ result = wsftp_perform(data, &connected, done);
return result;
}
-static CURLcode wssh_block_statemach(struct connectdata *conn,
+static CURLcode wssh_block_statemach(struct Curl_easy *data,
bool disconnect)
{
+ struct connectdata *conn = data->conn;
struct ssh_conn *sshc = &conn->proto.sshc;
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
while((sshc->state != SSH_STOP) && !result) {
bool block;
timediff_t left = 1000;
struct curltime now = Curl_now();
- result = wssh_statemach_act(conn, &block);
+ result = wssh_statemach_act(data, &block);
if(result)
break;
if(!disconnect) {
- if(Curl_pgrsUpdate(conn))
+ if(Curl_pgrsUpdate(data))
return CURLE_ABORTED_BY_CALLBACK;
result = Curl_speedcheck(data, now);
@@ -1024,29 +1035,29 @@ static CURLcode wssh_block_statemach(struct connectdata *conn,
/* generic done function for both SCP and SFTP called from their specific
done functions */
-static CURLcode wssh_done(struct connectdata *conn, CURLcode status)
+static CURLcode wssh_done(struct Curl_easy *data, CURLcode status)
{
CURLcode result = CURLE_OK;
- struct SSHPROTO *sftp_scp = conn->data->req.protop;
+ struct SSHPROTO *sftp_scp = data->req.p.ssh;
if(!status) {
/* run the state-machine */
- result = wssh_block_statemach(conn, FALSE);
+ result = wssh_block_statemach(data, FALSE);
}
else
result = status;
if(sftp_scp)
Curl_safefree(sftp_scp->path);
- if(Curl_pgrsDone(conn))
+ if(Curl_pgrsDone(data))
return CURLE_ABORTED_BY_CALLBACK;
- conn->data->req.keepon = 0; /* clear all bits */
+ data->req.keepon = 0; /* clear all bits */
return result;
}
#if 0
-static CURLcode wscp_done(struct connectdata *conn,
+static CURLcode wscp_done(struct Curl_easy *data,
CURLcode code, bool premature)
{
CURLcode result = CURLE_OK;
@@ -1057,7 +1068,7 @@ static CURLcode wscp_done(struct connectdata *conn,
return result;
}
-static CURLcode wscp_doing(struct connectdata *conn,
+static CURLcode wscp_doing(struct Curl_easy *data,
bool *dophase_done)
{
CURLcode result = CURLE_OK;
@@ -1067,9 +1078,11 @@ static CURLcode wscp_doing(struct connectdata *conn,
return result;
}
-static CURLcode wscp_disconnect(struct connectdata *conn, bool dead_connection)
+static CURLcode wscp_disconnect(struct Curl_easy *data,
+ struct connectdata *conn, bool dead_connection)
{
CURLcode result = CURLE_OK;
+ (void)data;
(void)conn;
(void)dead_connection;
@@ -1077,54 +1090,52 @@ static CURLcode wscp_disconnect(struct connectdata *conn, bool dead_connection)
}
#endif
-static CURLcode wsftp_done(struct connectdata *conn,
+static CURLcode wsftp_done(struct Curl_easy *data,
CURLcode code, bool premature)
{
(void)premature;
- state(conn, SSH_SFTP_CLOSE);
+ state(data, SSH_SFTP_CLOSE);
- return wssh_done(conn, code);
+ return wssh_done(data, code);
}
-static CURLcode wsftp_doing(struct connectdata *conn,
+static CURLcode wsftp_doing(struct Curl_easy *data,
bool *dophase_done)
{
- CURLcode result = wssh_multi_statemach(conn, dophase_done);
+ CURLcode result = wssh_multi_statemach(data, dophase_done);
if(*dophase_done) {
- DEBUGF(infof(conn->data, "DO phase is complete\n"));
+ DEBUGF(infof(data, "DO phase is complete\n"));
}
return result;
}
-static CURLcode wsftp_disconnect(struct connectdata *conn, bool dead)
+static CURLcode wsftp_disconnect(struct Curl_easy *data,
+ struct connectdata *conn,
+ bool dead)
{
CURLcode result = CURLE_OK;
(void)dead;
- DEBUGF(infof(conn->data, "SSH DISCONNECT starts now\n"));
+ DEBUGF(infof(data, "SSH DISCONNECT starts now\n"));
if(conn->proto.sshc.ssh_session) {
/* only if there's a session still around to use! */
- state(conn, SSH_SFTP_SHUTDOWN);
- result = wssh_block_statemach(conn, TRUE);
+ state(data, SSH_SFTP_SHUTDOWN);
+ result = wssh_block_statemach(data, TRUE);
}
- DEBUGF(infof(conn->data, "SSH DISCONNECT is done\n"));
+ DEBUGF(infof(data, "SSH DISCONNECT is done\n"));
return result;
}
-static int wssh_getsock(struct connectdata *conn,
+static int wssh_getsock(struct Curl_easy *data,
+ struct connectdata *conn,
curl_socket_t *sock)
{
- return wssh_perform_getsock(conn, sock);
-}
-
-static int wssh_perform_getsock(const struct connectdata *conn,
- curl_socket_t *sock)
-{
int bitmap = GETSOCK_BLANK;
int dir = conn->waitfor;
+ (void)data;
sock[0] = conn->sock[FIRSTSOCKET];
if(dir == KEEP_RECV)
diff --git a/Utilities/cmcurl/lib/vssh/wolfssh.h b/Utilities/cmcurl/lib/vssh/wolfssh.h
index a9b9a3b09..7b6ac489a 100644
--- a/Utilities/cmcurl/lib/vssh/wolfssh.h
+++ b/Utilities/cmcurl/lib/vssh/wolfssh.h
@@ -11,7 +11,7 @@
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/vtls/bearssl.c b/Utilities/cmcurl/lib/vtls/bearssl.c
index 44e7406e8..29b08c0e6 100644
--- a/Utilities/cmcurl/lib/vtls/bearssl.c
+++ b/Utilities/cmcurl/lib/vtls/bearssl.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2019 - 2020, Michael Forney, <mforney@mforney.org>
+ * Copyright (C) 2019 - 2021, Michael Forney, <mforney@mforney.org>
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -294,9 +294,9 @@ static const br_x509_class x509_vtable = {
x509_get_pkey
};
-static CURLcode bearssl_connect_step1(struct connectdata *conn, int sockindex)
+static CURLcode bearssl_connect_step1(struct Curl_easy *data,
+ struct connectdata *conn, int sockindex)
{
- struct Curl_easy *data = conn->data;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
struct ssl_backend_data *backend = connssl->backend;
const char * const ssl_cafile = SSL_CONN_CONFIG(CAfile);
@@ -349,8 +349,8 @@ static CURLcode bearssl_connect_step1(struct connectdata *conn, int sockindex)
ret = load_cafile(ssl_cafile, &backend->anchors, &backend->anchors_len);
if(ret != CURLE_OK) {
if(verifypeer) {
- failf(data, "error setting certificate verify locations:\n"
- " CAfile: %s\n", ssl_cafile);
+ failf(data, "error setting certificate verify locations."
+ " CAfile: %s", ssl_cafile);
return ret;
}
infof(data, "error setting certificate verify locations,"
@@ -374,12 +374,12 @@ static CURLcode bearssl_connect_step1(struct connectdata *conn, int sockindex)
if(SSL_SET_OPTION(primary.sessionid)) {
void *session;
- Curl_ssl_sessionid_lock(conn);
- if(!Curl_ssl_getsessionid(conn, &session, NULL, sockindex)) {
+ Curl_ssl_sessionid_lock(data);
+ if(!Curl_ssl_getsessionid(data, conn, &session, NULL, sockindex)) {
br_ssl_engine_set_session_parameters(&backend->ctx.eng, session);
infof(data, "BearSSL: re-using session ID\n");
}
- Curl_ssl_sessionid_unlock(conn);
+ Curl_ssl_sessionid_unlock(data);
}
if(conn->bits.tls_enable_alpn) {
@@ -429,10 +429,10 @@ static CURLcode bearssl_connect_step1(struct connectdata *conn, int sockindex)
return CURLE_OK;
}
-static CURLcode bearssl_run_until(struct connectdata *conn, int sockindex,
+static CURLcode bearssl_run_until(struct Curl_easy *data,
+ struct connectdata *conn, int sockindex,
unsigned target)
{
- struct Curl_easy *data = conn->data;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
struct ssl_backend_data *backend = connssl->backend;
curl_socket_t sockfd = conn->sock[sockindex];
@@ -507,14 +507,15 @@ static CURLcode bearssl_run_until(struct connectdata *conn, int sockindex,
}
}
-static CURLcode bearssl_connect_step2(struct connectdata *conn, int sockindex)
+static CURLcode bearssl_connect_step2(struct Curl_easy *data,
+ struct connectdata *conn, int sockindex)
{
- struct Curl_easy *data = conn->data;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
struct ssl_backend_data *backend = connssl->backend;
CURLcode ret;
- ret = bearssl_run_until(conn, sockindex, BR_SSL_SENDAPP | BR_SSL_RECVAPP);
+ ret = bearssl_run_until(data, conn, sockindex,
+ BR_SSL_SENDAPP | BR_SSL_RECVAPP);
if(ret == CURLE_AGAIN)
return CURLE_OK;
if(ret == CURLE_OK) {
@@ -527,9 +528,9 @@ static CURLcode bearssl_connect_step2(struct connectdata *conn, int sockindex)
return ret;
}
-static CURLcode bearssl_connect_step3(struct connectdata *conn, int sockindex)
+static CURLcode bearssl_connect_step3(struct Curl_easy *data,
+ struct connectdata *conn, int sockindex)
{
- struct Curl_easy *data = conn->data;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
struct ssl_backend_data *backend = connssl->backend;
CURLcode ret;
@@ -552,7 +553,7 @@ static CURLcode bearssl_connect_step3(struct connectdata *conn, int sockindex)
conn->negnpn = CURL_HTTP_VERSION_1_1;
else
infof(data, "ALPN, unrecognized protocol %s\n", protocol);
- Curl_multiuse_state(conn, conn->negnpn == CURL_HTTP_VERSION_2 ?
+ Curl_multiuse_state(data, conn->negnpn == CURL_HTTP_VERSION_2 ?
BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);
}
else
@@ -568,12 +569,13 @@ static CURLcode bearssl_connect_step3(struct connectdata *conn, int sockindex)
if(!session)
return CURLE_OUT_OF_MEMORY;
br_ssl_engine_get_session_parameters(&backend->ctx.eng, session);
- Curl_ssl_sessionid_lock(conn);
- incache = !(Curl_ssl_getsessionid(conn, &oldsession, NULL, sockindex));
+ Curl_ssl_sessionid_lock(data);
+ incache = !(Curl_ssl_getsessionid(data, conn,
+ &oldsession, NULL, sockindex));
if(incache)
- Curl_ssl_delsessionid(conn, oldsession);
- ret = Curl_ssl_addsessionid(conn, session, 0, sockindex);
- Curl_ssl_sessionid_unlock(conn);
+ Curl_ssl_delsessionid(data, oldsession);
+ ret = Curl_ssl_addsessionid(data, conn, session, 0, sockindex);
+ Curl_ssl_sessionid_unlock(data);
if(ret) {
free(session);
return CURLE_OUT_OF_MEMORY;
@@ -585,17 +587,17 @@ static CURLcode bearssl_connect_step3(struct connectdata *conn, int sockindex)
return CURLE_OK;
}
-static ssize_t bearssl_send(struct connectdata *conn, int sockindex,
+static ssize_t bearssl_send(struct Curl_easy *data, int sockindex,
const void *buf, size_t len, CURLcode *err)
{
- struct Curl_easy *data = conn->data;
+ struct connectdata *conn = data->conn;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
struct ssl_backend_data *backend = connssl->backend;
unsigned char *app;
size_t applen;
for(;;) {
- *err = bearssl_run_until(conn, sockindex, BR_SSL_SENDAPP);
+ *err = bearssl_run_until(data, conn, sockindex, BR_SSL_SENDAPP);
if (*err != CURLE_OK)
return -1;
app = br_ssl_engine_sendapp_buf(&backend->ctx.eng, &applen);
@@ -618,15 +620,16 @@ static ssize_t bearssl_send(struct connectdata *conn, int sockindex,
}
}
-static ssize_t bearssl_recv(struct connectdata *conn, int sockindex,
+static ssize_t bearssl_recv(struct Curl_easy *data, int sockindex,
char *buf, size_t len, CURLcode *err)
{
+ struct connectdata *conn = data->conn;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
struct ssl_backend_data *backend = connssl->backend;
unsigned char *app;
size_t applen;
- *err = bearssl_run_until(conn, sockindex, BR_SSL_RECVAPP);
+ *err = bearssl_run_until(data, conn, sockindex, BR_SSL_RECVAPP);
if(*err != CURLE_OK)
return -1;
app = br_ssl_engine_recvapp_buf(&backend->ctx.eng, &applen);
@@ -640,13 +643,13 @@ static ssize_t bearssl_recv(struct connectdata *conn, int sockindex,
return applen;
}
-static CURLcode bearssl_connect_common(struct connectdata *conn,
+static CURLcode bearssl_connect_common(struct Curl_easy *data,
+ struct connectdata *conn,
int sockindex,
bool nonblocking,
bool *done)
{
CURLcode ret;
- struct Curl_easy *data = conn->data;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
curl_socket_t sockfd = conn->sock[sockindex];
timediff_t timeout_ms;
@@ -659,7 +662,7 @@ static CURLcode bearssl_connect_common(struct connectdata *conn,
}
if(ssl_connect_1 == connssl->connecting_state) {
- ret = bearssl_connect_step1(conn, sockindex);
+ ret = bearssl_connect_step1(data, conn, sockindex);
if(ret)
return ret;
}
@@ -712,7 +715,7 @@ static CURLcode bearssl_connect_common(struct connectdata *conn,
* before step2 has completed while ensuring that a client using select()
* or epoll() will always have a valid fdset to wait on.
*/
- ret = bearssl_connect_step2(conn, sockindex);
+ ret = bearssl_connect_step2(data, conn, sockindex);
if(ret || (nonblocking &&
(ssl_connect_2 == connssl->connecting_state ||
ssl_connect_2_reading == connssl->connecting_state ||
@@ -721,7 +724,7 @@ static CURLcode bearssl_connect_common(struct connectdata *conn,
}
if(ssl_connect_3 == connssl->connecting_state) {
- ret = bearssl_connect_step3(conn, sockindex);
+ ret = bearssl_connect_step3(data, conn, sockindex);
if(ret)
return ret;
}
@@ -741,21 +744,21 @@ static CURLcode bearssl_connect_common(struct connectdata *conn,
return CURLE_OK;
}
-static size_t Curl_bearssl_version(char *buffer, size_t size)
+static size_t bearssl_version(char *buffer, size_t size)
{
return msnprintf(buffer, size, "BearSSL");
}
-static bool Curl_bearssl_data_pending(const struct connectdata *conn,
- int connindex)
+static bool bearssl_data_pending(const struct connectdata *conn,
+ int connindex)
{
const struct ssl_connect_data *connssl = &conn->ssl[connindex];
struct ssl_backend_data *backend = connssl->backend;
return br_ssl_engine_current_state(&backend->ctx.eng) & BR_SSL_RECVAPP;
}
-static CURLcode Curl_bearssl_random(struct Curl_easy *data UNUSED_PARAM,
- unsigned char *entropy, size_t length)
+static CURLcode bearssl_random(struct Curl_easy *data UNUSED_PARAM,
+ unsigned char *entropy, size_t length)
{
static br_hmac_drbg_context ctx;
static bool seeded = FALSE;
@@ -774,12 +777,13 @@ static CURLcode Curl_bearssl_random(struct Curl_easy *data UNUSED_PARAM,
return CURLE_OK;
}
-static CURLcode Curl_bearssl_connect(struct connectdata *conn, int sockindex)
+static CURLcode bearssl_connect(struct Curl_easy *data,
+ struct connectdata *conn, int sockindex)
{
CURLcode ret;
bool done = FALSE;
- ret = bearssl_connect_common(conn, sockindex, FALSE, &done);
+ ret = bearssl_connect_common(data, conn, sockindex, FALSE, &done);
if(ret)
return ret;
@@ -788,20 +792,22 @@ static CURLcode Curl_bearssl_connect(struct connectdata *conn, int sockindex)
return CURLE_OK;
}
-static CURLcode Curl_bearssl_connect_nonblocking(struct connectdata *conn,
- int sockindex, bool *done)
+static CURLcode bearssl_connect_nonblocking(struct Curl_easy *data,
+ struct connectdata *conn,
+ int sockindex, bool *done)
{
- return bearssl_connect_common(conn, sockindex, TRUE, done);
+ return bearssl_connect_common(data, conn, sockindex, TRUE, done);
}
-static void *Curl_bearssl_get_internals(struct ssl_connect_data *connssl,
- CURLINFO info UNUSED_PARAM)
+static void *bearssl_get_internals(struct ssl_connect_data *connssl,
+ CURLINFO info UNUSED_PARAM)
{
struct ssl_backend_data *backend = connssl->backend;
return &backend->ctx;
}
-static void Curl_bearssl_close(struct connectdata *conn, int sockindex)
+static void bearssl_close(struct Curl_easy *data,
+ struct connectdata *conn, int sockindex)
{
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
struct ssl_backend_data *backend = connssl->backend;
@@ -809,35 +815,22 @@ static void Curl_bearssl_close(struct connectdata *conn, int sockindex)
if(backend->active) {
br_ssl_engine_close(&backend->ctx.eng);
- (void)bearssl_run_until(conn, sockindex, BR_SSL_CLOSED);
+ (void)bearssl_run_until(data, conn, sockindex, BR_SSL_CLOSED);
}
for(i = 0; i < backend->anchors_len; ++i)
free(backend->anchors[i].dn.data);
free(backend->anchors);
}
-static void Curl_bearssl_session_free(void *ptr)
+static void bearssl_session_free(void *ptr)
{
free(ptr);
}
-static CURLcode Curl_bearssl_md5sum(unsigned char *input,
- size_t inputlen,
- unsigned char *md5sum,
- size_t md5len UNUSED_PARAM)
-{
- br_md5_context ctx;
-
- br_md5_init(&ctx);
- br_md5_update(&ctx, input, inputlen);
- br_md5_out(&ctx, md5sum);
- return CURLE_OK;
-}
-
-static CURLcode Curl_bearssl_sha256sum(const unsigned char *input,
- size_t inputlen,
- unsigned char *sha256sum,
- size_t sha256len UNUSED_PARAM)
+static CURLcode bearssl_sha256sum(const unsigned char *input,
+ size_t inputlen,
+ unsigned char *sha256sum,
+ size_t sha256len UNUSED_PARAM)
{
br_sha256_context ctx;
@@ -854,24 +847,23 @@ const struct Curl_ssl Curl_ssl_bearssl = {
Curl_none_init,
Curl_none_cleanup,
- Curl_bearssl_version,
+ bearssl_version,
Curl_none_check_cxn,
Curl_none_shutdown,
- Curl_bearssl_data_pending,
- Curl_bearssl_random,
+ bearssl_data_pending,
+ bearssl_random,
Curl_none_cert_status_request,
- Curl_bearssl_connect,
- Curl_bearssl_connect_nonblocking,
- Curl_bearssl_get_internals,
- Curl_bearssl_close,
+ bearssl_connect,
+ bearssl_connect_nonblocking,
+ bearssl_get_internals,
+ bearssl_close,
Curl_none_close_all,
- Curl_bearssl_session_free,
+ bearssl_session_free,
Curl_none_set_engine,
Curl_none_set_engine_default,
Curl_none_engines_list,
Curl_none_false_start,
- Curl_bearssl_md5sum,
- Curl_bearssl_sha256sum
+ bearssl_sha256sum
};
#endif /* USE_BEARSSL */
diff --git a/Utilities/cmcurl/lib/vtls/bearssl.h b/Utilities/cmcurl/lib/vtls/bearssl.h
index 5f94922b9..d72b7d0e2 100644
--- a/Utilities/cmcurl/lib/vtls/bearssl.h
+++ b/Utilities/cmcurl/lib/vtls/bearssl.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2019, Michael Forney, <mforney@mforney.org>
+ * Copyright (C) 2019 - 2020, Michael Forney, <mforney@mforney.org>
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/vtls/gskit.c b/Utilities/cmcurl/lib/vtls/gskit.c
index 0538e4a46..9b5f649f7 100644
--- a/Utilities/cmcurl/lib/vtls/gskit.c
+++ b/Utilities/cmcurl/lib/vtls/gskit.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -301,10 +301,9 @@ static CURLcode set_callback(struct Curl_easy *data,
}
-static CURLcode set_ciphers(struct connectdata *conn,
+static CURLcode set_ciphers(struct Curl_easy *data,
gsk_handle h, unsigned int *protoflags)
{
- struct Curl_easy *data = conn->data;
const char *cipherlist = SSL_CONN_CONFIG(cipher_list);
const char *clp;
const struct gskit_cipher *ctp;
@@ -435,7 +434,7 @@ static CURLcode set_ciphers(struct connectdata *conn,
}
-static int Curl_gskit_init(void)
+static int gskit_init(void)
{
/* No initialisation needed. */
@@ -443,7 +442,7 @@ static int Curl_gskit_init(void)
}
-static void Curl_gskit_cleanup(void)
+static void gskit_cleanup(void)
{
/* Nothing to do. */
}
@@ -587,11 +586,11 @@ static int pipe_ssloverssl(struct connectdata *conn, int sockindex,
}
-static void close_one(struct ssl_connect_data *connssl,
+static void close_one(struct ssl_connect_data *connssl, struct Curl_easy *data,
struct connectdata *conn, int sockindex)
{
if(BACKEND->handle) {
- gskit_status(conn->data, gsk_secure_soc_close(&BACKEND->handle),
+ gskit_status(data, gsk_secure_soc_close(&BACKEND->handle),
"gsk_secure_soc_close()", 0);
/* Last chance to drain output. */
while(pipe_ssloverssl(conn, sockindex, SOS_WRITE) > 0)
@@ -612,10 +611,10 @@ static void close_one(struct ssl_connect_data *connssl,
static ssize_t gskit_send(struct connectdata *conn, int sockindex,
- const void *mem, size_t len, CURLcode *curlcode)
+ const void *mem, size_t len, CURLcode *curlcode)
{
+ struct connectdata *conn = data->conn;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
- struct Curl_easy *data = conn->data;
CURLcode cc = CURLE_SEND_ERROR;
int written;
@@ -636,11 +635,11 @@ static ssize_t gskit_send(struct connectdata *conn, int sockindex,
}
-static ssize_t gskit_recv(struct connectdata *conn, int num, char *buf,
- size_t buffersize, CURLcode *curlcode)
+static ssize_t gskit_recv(struct Curl_easy *data, int num, char *buf,
+ size_t buffersize, CURLcode *curlcode)
{
+ struct connectdata *conn = data->conn;
struct ssl_connect_data *connssl = &conn->ssl[num];
- struct Curl_easy *data = conn->data;
int nread;
CURLcode cc = CURLE_RECV_ERROR;
@@ -664,9 +663,8 @@ static ssize_t gskit_recv(struct connectdata *conn, int num, char *buf,
}
static CURLcode
-set_ssl_version_min_max(unsigned int *protoflags, struct connectdata *conn)
+set_ssl_version_min_max(unsigned int *protoflags, struct Curl_easy *data)
{
- struct Curl_easy *data = conn->data;
long ssl_version = SSL_CONN_CONFIG(version);
long ssl_version_max = SSL_CONN_CONFIG(version_max);
long i = ssl_version;
@@ -696,16 +694,16 @@ set_ssl_version_min_max(unsigned int *protoflags, struct connectdata *conn)
return CURLE_OK;
}
-static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex)
+static CURLcode gskit_connect_step1(struct Curl_easy *data,
+ struct connectdata *conn, int sockindex)
{
- struct Curl_easy *data = conn->data;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
gsk_handle envir;
CURLcode result;
int rc;
const char * const keyringfile = SSL_CONN_CONFIG(CAfile);
const char * const keyringpwd = SSL_SET_OPTION(key_passwd);
- const char * const keyringlabel = SSL_SET_OPTION(cert);
+ const char * const keyringlabel = SSL_SET_OPTION(primary.clientcert);
const long int ssl_version = SSL_CONN_CONFIG(version);
const bool verifypeer = SSL_CONN_CONFIG(verifypeer);
const char * const hostname = SSL_IS_PROXY()? conn->http_proxy.host.name:
@@ -798,7 +796,7 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex)
case CURL_SSLVERSION_TLSv1_1:
case CURL_SSLVERSION_TLSv1_2:
case CURL_SSLVERSION_TLSv1_3:
- result = set_ssl_version_min_max(&protoflags, conn);
+ result = set_ssl_version_min_max(&protoflags, data);
if(result != CURLE_OK)
return result;
break;
@@ -832,7 +830,7 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex)
result = set_numeric(data, BACKEND->handle, GSK_FD, BACKEND->localfd >= 0?
BACKEND->localfd: conn->sock[sockindex]);
if(!result)
- result = set_ciphers(conn, BACKEND->handle, &protoflags);
+ result = set_ciphers(data, BACKEND->handle, &protoflags);
if(!protoflags) {
failf(data, "No SSL protocol/cipher combination enabled");
result = CURLE_SSL_CIPHER;
@@ -915,15 +913,15 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex)
}
/* Error: rollback. */
- close_one(connssl, conn, sockindex);
+ close_one(connssl, data, conn, sockindex);
return result;
}
-static CURLcode gskit_connect_step2(struct connectdata *conn, int sockindex,
+static CURLcode gskit_connect_step2(struct Curl_easy *data,
+ struct connectdata *conn, int sockindex,
bool nonblocking)
{
- struct Curl_easy *data = conn->data;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
Qso_OverlappedIO_t cstat;
struct timeval stmv;
@@ -971,9 +969,9 @@ static CURLcode gskit_connect_step2(struct connectdata *conn, int sockindex,
}
-static CURLcode gskit_connect_step3(struct connectdata *conn, int sockindex)
+static CURLcode gskit_connect_step3(struct Curl_easy *data,
+ struct connectdata *conn, int sockindex)
{
- struct Curl_easy *data = conn->data;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
const gsk_cert_data_elem *cdev;
int cdec;
@@ -1016,7 +1014,7 @@ static CURLcode gskit_connect_step3(struct connectdata *conn, int sockindex)
}
/* Verify host. */
- result = Curl_verifyhost(conn, cert, certend);
+ result = Curl_verifyhost(data, conn, cert, certend);
if(result)
return result;
@@ -1031,7 +1029,7 @@ static CURLcode gskit_connect_step3(struct connectdata *conn, int sockindex)
return result;
if(cert) {
- result = Curl_extract_certinfo(conn, 0, cert, certend);
+ result = Curl_extract_certinfo(data, 0, cert, certend);
if(result)
return result;
}
@@ -1059,10 +1057,10 @@ static CURLcode gskit_connect_step3(struct connectdata *conn, int sockindex)
}
-static CURLcode gskit_connect_common(struct connectdata *conn, int sockindex,
+static CURLcode gskit_connect_common(struct Curl_easy *data,
+ struct connectdata *conn, int sockindex,
bool nonblocking, bool *done)
{
- struct Curl_easy *data = conn->data;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
timediff_t timeout_ms;
CURLcode result = CURLE_OK;
@@ -1082,7 +1080,7 @@ static CURLcode gskit_connect_common(struct connectdata *conn, int sockindex,
result = CURLE_OPERATION_TIMEDOUT;
}
else
- result = gskit_connect_step1(conn, sockindex);
+ result = gskit_connect_step1(data, conn, sockindex);
}
/* Handle handshake pipelining. */
@@ -1101,7 +1099,7 @@ static CURLcode gskit_connect_common(struct connectdata *conn, int sockindex,
result = CURLE_OPERATION_TIMEDOUT;
}
else
- result = gskit_connect_step2(conn, sockindex, nonblocking);
+ result = gskit_connect_step2(data, conn, sockindex, nonblocking);
}
/* Handle handshake pipelining. */
@@ -1111,10 +1109,10 @@ static CURLcode gskit_connect_common(struct connectdata *conn, int sockindex,
/* Step 3: gather certificate info, verify host. */
if(!result && connssl->connecting_state == ssl_connect_3)
- result = gskit_connect_step3(conn, sockindex);
+ result = gskit_connect_step3(data, conn, sockindex);
if(result)
- close_one(connssl, conn, sockindex);
+ close_one(connssl, data, conn, sockindex);
else if(connssl->connecting_state == ssl_connect_done) {
connssl->state = ssl_connection_complete;
connssl->connecting_state = ssl_connect_1;
@@ -1127,25 +1125,27 @@ static CURLcode gskit_connect_common(struct connectdata *conn, int sockindex,
}
-static CURLcode Curl_gskit_connect_nonblocking(struct connectdata *conn,
- int sockindex, bool *done)
+static CURLcode gskit_connect_nonblocking(struct Curl_easy *data,
+ struct connectdata *conn,
+ int sockindex, bool *done)
{
CURLcode result;
- result = gskit_connect_common(conn, sockindex, TRUE, done);
+ result = gskit_connect_common(data, conn, sockindex, TRUE, done);
if(*done || result)
conn->ssl[sockindex].connecting_state = ssl_connect_1;
return result;
}
-static CURLcode Curl_gskit_connect(struct connectdata *conn, int sockindex)
+static CURLcode gskit_connect(struct Curl_easy *data,
+ struct connectdata *conn, int sockindex)
{
CURLcode result;
bool done;
conn->ssl[sockindex].connecting_state = ssl_connect_1;
- result = gskit_connect_common(conn, sockindex, FALSE, &done);
+ result = gskit_connect_common(data, conn, sockindex, FALSE, &done);
if(result)
return result;
@@ -1155,17 +1155,18 @@ static CURLcode Curl_gskit_connect(struct connectdata *conn, int sockindex)
}
-static void Curl_gskit_close(struct connectdata *conn, int sockindex)
+static void gskit_close(struct Curl_easy *data, struct connectdata *conn,
+ int sockindex)
{
- close_one(&conn->ssl[sockindex], conn, sockindex);
- close_one(&conn->proxy_ssl[sockindex], conn, sockindex);
+ close_one(&conn->ssl[sockindex], data, conn, sockindex);
+ close_one(&conn->proxy_ssl[sockindex], data, conn, sockindex);
}
-static int Curl_gskit_shutdown(struct connectdata *conn, int sockindex)
+static int gskit_shutdown(struct Curl_easy *data,
+ struct connectdata *conn, int sockindex)
{
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
- struct Curl_easy *data = conn->data;
int what;
int rc;
char buf[120];
@@ -1178,7 +1179,7 @@ static int Curl_gskit_shutdown(struct connectdata *conn, int sockindex)
return 0;
#endif
- close_one(connssl, conn, sockindex);
+ close_one(connssl, data, conn, sockindex);
rc = 0;
what = SOCKET_READABLE(conn->sock[sockindex],
SSL_SHUTDOWN_TIMEOUT);
@@ -1219,13 +1220,13 @@ static int Curl_gskit_shutdown(struct connectdata *conn, int sockindex)
}
-static size_t Curl_gskit_version(char *buffer, size_t size)
+static size_t gskit_version(char *buffer, size_t size)
{
return msnprintf(buffer, size, "GSKit");
}
-static int Curl_gskit_check_cxn(struct connectdata *cxn)
+static int gskit_check_cxn(struct connectdata *cxn)
{
struct ssl_connect_data *connssl = &cxn->ssl[FIRSTSOCKET];
int err;
@@ -1247,8 +1248,8 @@ static int Curl_gskit_check_cxn(struct connectdata *cxn)
return -1; /* connection status unknown */
}
-static void *Curl_gskit_get_internals(struct ssl_connect_data *connssl,
- CURLINFO info UNUSED_PARAM)
+static void *gskit_get_internals(struct ssl_connect_data *connssl,
+ CURLINFO info UNUSED_PARAM)
{
(void)info;
return BACKEND->handle;
@@ -1262,18 +1263,18 @@ const struct Curl_ssl Curl_ssl_gskit = {
sizeof(struct ssl_backend_data),
- Curl_gskit_init, /* init */
- Curl_gskit_cleanup, /* cleanup */
- Curl_gskit_version, /* version */
- Curl_gskit_check_cxn, /* check_cxn */
- Curl_gskit_shutdown, /* shutdown */
+ gskit_init, /* init */
+ gskit_cleanup, /* cleanup */
+ gskit_version, /* version */
+ gskit_check_cxn, /* check_cxn */
+ gskit_shutdown, /* shutdown */
Curl_none_data_pending, /* data_pending */
Curl_none_random, /* random */
Curl_none_cert_status_request, /* cert_status_request */
- Curl_gskit_connect, /* connect */
- Curl_gskit_connect_nonblocking, /* connect_nonblocking */
- Curl_gskit_get_internals, /* get_internals */
- Curl_gskit_close, /* close_one */
+ gskit_connect, /* connect */
+ gskit_connect_nonblocking, /* connect_nonblocking */
+ gskit_get_internals, /* get_internals */
+ gskit_close, /* close_one */
Curl_none_close_all, /* close_all */
/* No session handling for GSKit */
Curl_none_session_free, /* session_free */
@@ -1281,7 +1282,6 @@ const struct Curl_ssl Curl_ssl_gskit = {
Curl_none_set_engine_default, /* set_engine_default */
Curl_none_engines_list, /* engines_list */
Curl_none_false_start, /* false_start */
- Curl_none_md5sum, /* md5sum */
NULL /* sha256sum */
};
diff --git a/Utilities/cmcurl/lib/vtls/gskit.h b/Utilities/cmcurl/lib/vtls/gskit.h
index b06b5e17d..202df7e07 100644
--- a/Utilities/cmcurl/lib/vtls/gskit.h
+++ b/Utilities/cmcurl/lib/vtls/gskit.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
diff --git a/Utilities/cmcurl/lib/vtls/gtls.c b/Utilities/cmcurl/lib/vtls/gtls.c
index 16b0bd6cb..3ddee1974 100644
--- a/Utilities/cmcurl/lib/vtls/gtls.c
+++ b/Utilities/cmcurl/lib/vtls/gtls.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -81,43 +81,43 @@ static bool gtls_inited = FALSE;
struct ssl_backend_data {
gnutls_session_t session;
gnutls_certificate_credentials_t cred;
-#ifdef USE_TLS_SRP
+#ifdef HAVE_GNUTLS_SRP
gnutls_srp_client_credentials_t srp_client_cred;
#endif
};
-static ssize_t Curl_gtls_push(void *s, const void *buf, size_t len)
+static ssize_t gtls_push(void *s, const void *buf, size_t len)
{
curl_socket_t sock = *(curl_socket_t *)s;
ssize_t ret = swrite(sock, buf, len);
return ret;
}
-static ssize_t Curl_gtls_pull(void *s, void *buf, size_t len)
+static ssize_t gtls_pull(void *s, void *buf, size_t len)
{
curl_socket_t sock = *(curl_socket_t *)s;
ssize_t ret = sread(sock, buf, len);
return ret;
}
-static ssize_t Curl_gtls_push_ssl(void *s, const void *buf, size_t len)
+static ssize_t gtls_push_ssl(void *s, const void *buf, size_t len)
{
return gnutls_record_send((gnutls_session_t) s, buf, len);
}
-static ssize_t Curl_gtls_pull_ssl(void *s, void *buf, size_t len)
+static ssize_t gtls_pull_ssl(void *s, void *buf, size_t len)
{
return gnutls_record_recv((gnutls_session_t) s, buf, len);
}
-/* Curl_gtls_init()
+/* gtls_init()
*
* Global GnuTLS init, called from Curl_ssl_init(). This calls functions that
* are not thread-safe and thus this function itself is not thread-safe and
* must only be called from within curl_global_init() to keep the thread
* situation under control!
*/
-static int Curl_gtls_init(void)
+static int gtls_init(void)
{
int ret = 1;
if(!gtls_inited) {
@@ -131,7 +131,7 @@ static int Curl_gtls_init(void)
return ret;
}
-static void Curl_gtls_cleanup(void)
+static void gtls_cleanup(void)
{
if(gtls_inited) {
gnutls_global_deinit();
@@ -200,12 +200,12 @@ static void unload_file(gnutls_datum_t data)
/* this function does a SSL/TLS (re-)handshake */
-static CURLcode handshake(struct connectdata *conn,
+static CURLcode handshake(struct Curl_easy *data,
+ struct connectdata *conn,
int sockindex,
bool duringconnect,
bool nonblocking)
{
- struct Curl_easy *data = conn->data;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
struct ssl_backend_data *backend = connssl->backend;
gnutls_session_t session = backend->session;
@@ -304,7 +304,7 @@ static gnutls_x509_crt_fmt_t do_file_type(const char *type)
return GNUTLS_X509_FMT_PEM;
if(strcasecompare(type, "DER"))
return GNUTLS_X509_FMT_DER;
- return -1;
+ return GNUTLS_X509_FMT_PEM; /* default to PEM */
}
#define GNUTLS_CIPHERS "NORMAL:-ARCFOUR-128:-CTYPE-ALL:+CTYPE-X509"
@@ -314,9 +314,9 @@ static gnutls_x509_crt_fmt_t do_file_type(const char *type)
#define GNUTLS_SRP "+SRP"
static CURLcode
-set_ssl_version_min_max(const char **prioritylist, struct connectdata *conn)
+set_ssl_version_min_max(const char **prioritylist, struct Curl_easy *data)
{
- struct Curl_easy *data = conn->data;
+ struct connectdata *conn = data->conn;
long ssl_version = SSL_CONN_CONFIG(version);
long ssl_version_max = SSL_CONN_CONFIG(version_max);
@@ -379,10 +379,10 @@ set_ssl_version_min_max(const char **prioritylist, struct connectdata *conn)
}
static CURLcode
-gtls_connect_step1(struct connectdata *conn,
+gtls_connect_step1(struct Curl_easy *data,
+ struct connectdata *conn,
int sockindex)
{
- struct Curl_easy *data = conn->data;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
struct ssl_backend_data *backend = connssl->backend;
unsigned int init_flags;
@@ -399,15 +399,8 @@ gtls_connect_step1(struct connectdata *conn,
#endif
const char *prioritylist;
const char *err = NULL;
-#ifndef CURL_DISABLE_PROXY
- const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
- conn->host.name;
- long * const certverifyresult = SSL_IS_PROXY() ?
- &data->set.proxy_ssl.certverifyresult : &data->set.ssl.certverifyresult;
-#else
- const char * const hostname = conn->host.name;
- long * const certverifyresult = &data->set.ssl.certverifyresult;
-#endif
+ const char * const hostname = SSL_HOST_NAME();
+ long * const certverifyresult = &SSL_SET_OPTION_LVALUE(certverifyresult);
if(connssl->state == ssl_connection_complete)
/* to make us tolerant against being called more than once for the
@@ -415,7 +408,7 @@ gtls_connect_step1(struct connectdata *conn,
return CURLE_OK;
if(!gtls_inited)
- Curl_gtls_init();
+ gtls_init();
/* Initialize certverifyresult to OK */
*certverifyresult = 0;
@@ -434,7 +427,7 @@ gtls_connect_step1(struct connectdata *conn,
return CURLE_SSL_CONNECT_ERROR;
}
-#ifdef USE_TLS_SRP
+#ifdef HAVE_GNUTLS_SRP
if(SSL_SET_OPTION(authtype) == CURL_TLSAUTH_SRP) {
infof(data, "Using TLS-SRP username: %s\n", SSL_SET_OPTION(username));
@@ -575,7 +568,7 @@ gtls_connect_step1(struct connectdata *conn,
case CURL_SSLVERSION_TLSv1_2:
case CURL_SSLVERSION_TLSv1_3:
{
- CURLcode result = set_ssl_version_min_max(&prioritylist, conn);
+ CURLcode result = set_ssl_version_min_max(&prioritylist, data);
if(result != CURLE_OK)
return result;
break;
@@ -588,7 +581,7 @@ gtls_connect_step1(struct connectdata *conn,
return CURLE_SSL_CONNECT_ERROR;
}
-#ifdef USE_TLS_SRP
+#ifdef HAVE_GNUTLS_SRP
/* Only add SRP to the cipher list if SRP is requested. Otherwise
* GnuTLS will disable TLS 1.3 support. */
if(SSL_SET_OPTION(authtype) == CURL_TLSAUTH_SRP) {
@@ -610,7 +603,7 @@ gtls_connect_step1(struct connectdata *conn,
else {
#endif
rc = gnutls_priority_set_direct(session, prioritylist, &err);
-#ifdef USE_TLS_SRP
+#ifdef HAVE_GNUTLS_SRP
}
#endif
@@ -645,7 +638,7 @@ gtls_connect_step1(struct connectdata *conn,
gnutls_alpn_set_protocols(session, protocols, cur, 0);
}
- if(SSL_SET_OPTION(cert)) {
+ if(SSL_SET_OPTION(primary.clientcert)) {
if(SSL_SET_OPTION(key_passwd)) {
const unsigned int supported_key_encryption_algorithms =
GNUTLS_PKCS_USE_PKCS12_3DES | GNUTLS_PKCS_USE_PKCS12_ARCFOUR |
@@ -654,9 +647,9 @@ gtls_connect_step1(struct connectdata *conn,
GNUTLS_PKCS_USE_PBES2_AES_256;
rc = gnutls_certificate_set_x509_key_file2(
backend->cred,
- SSL_SET_OPTION(cert),
+ SSL_SET_OPTION(primary.clientcert),
SSL_SET_OPTION(key) ?
- SSL_SET_OPTION(key) : SSL_SET_OPTION(cert),
+ SSL_SET_OPTION(key) : SSL_SET_OPTION(primary.clientcert),
do_file_type(SSL_SET_OPTION(cert_type)),
SSL_SET_OPTION(key_passwd),
supported_key_encryption_algorithms);
@@ -670,9 +663,9 @@ gtls_connect_step1(struct connectdata *conn,
else {
if(gnutls_certificate_set_x509_key_file(
backend->cred,
- SSL_SET_OPTION(cert),
+ SSL_SET_OPTION(primary.clientcert),
SSL_SET_OPTION(key) ?
- SSL_SET_OPTION(key) : SSL_SET_OPTION(cert),
+ SSL_SET_OPTION(key) : SSL_SET_OPTION(primary.clientcert),
do_file_type(SSL_SET_OPTION(cert_type)) ) !=
GNUTLS_E_SUCCESS) {
failf(data, "error reading X.509 key or certificate file");
@@ -681,7 +674,7 @@ gtls_connect_step1(struct connectdata *conn,
}
}
-#ifdef USE_TLS_SRP
+#ifdef HAVE_GNUTLS_SRP
/* put the credentials to the current session */
if(SSL_SET_OPTION(authtype) == CURL_TLSAUTH_SRP) {
rc = gnutls_credentials_set(session, GNUTLS_CRD_SRP,
@@ -705,16 +698,16 @@ gtls_connect_step1(struct connectdata *conn,
#ifndef CURL_DISABLE_PROXY
if(conn->proxy_ssl[sockindex].use) {
transport_ptr = conn->proxy_ssl[sockindex].backend->session;
- gnutls_transport_push = Curl_gtls_push_ssl;
- gnutls_transport_pull = Curl_gtls_pull_ssl;
+ gnutls_transport_push = gtls_push_ssl;
+ gnutls_transport_pull = gtls_pull_ssl;
}
else
#endif
{
/* file descriptor for the socket */
transport_ptr = &conn->sock[sockindex];
- gnutls_transport_push = Curl_gtls_push;
- gnutls_transport_pull = Curl_gtls_pull;
+ gnutls_transport_push = gtls_push;
+ gnutls_transport_pull = gtls_pull;
}
/* set the connection handle */
@@ -738,15 +731,16 @@ gtls_connect_step1(struct connectdata *conn,
void *ssl_sessionid;
size_t ssl_idsize;
- Curl_ssl_sessionid_lock(conn);
- if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, &ssl_idsize, sockindex)) {
+ Curl_ssl_sessionid_lock(data);
+ if(!Curl_ssl_getsessionid(data, conn,
+ &ssl_sessionid, &ssl_idsize, sockindex)) {
/* we got a session id, use it! */
gnutls_session_set_data(session, ssl_sessionid, ssl_idsize);
/* Informational message */
infof(data, "SSL re-using session ID\n");
}
- Curl_ssl_sessionid_unlock(conn);
+ Curl_ssl_sessionid_unlock(data);
}
return CURLE_OK;
@@ -814,7 +808,8 @@ static Curl_recv gtls_recv;
static Curl_send gtls_send;
static CURLcode
-gtls_connect_step3(struct connectdata *conn,
+gtls_connect_step3(struct Curl_easy *data,
+ struct connectdata *conn,
int sockindex)
{
unsigned int cert_list_size;
@@ -827,7 +822,6 @@ gtls_connect_step3(struct connectdata *conn,
size_t size;
time_t certclock;
const char *ptr;
- struct Curl_easy *data = conn->data;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
struct ssl_backend_data *backend = connssl->backend;
gnutls_session_t session = backend->session;
@@ -839,15 +833,8 @@ gtls_connect_step3(struct connectdata *conn,
unsigned int bits;
gnutls_protocol_t version = gnutls_protocol_get_version(session);
#endif
-#ifndef CURL_DISABLE_PROXY
- const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
- conn->host.name;
- long * const certverifyresult = SSL_IS_PROXY() ?
- &data->set.proxy_ssl.certverifyresult : &data->set.ssl.certverifyresult;
-#else
- const char * const hostname = conn->host.name;
- long * const certverifyresult = &data->set.ssl.certverifyresult;
-#endif
+ const char * const hostname = SSL_HOST_NAME();
+ long * const certverifyresult = &SSL_SET_OPTION_LVALUE(certverifyresult);
/* the name of the cipher suite used, e.g. ECDHE_RSA_AES_256_GCM_SHA384. */
ptr = gnutls_cipher_suite_get_name(gnutls_kx_get(session),
@@ -868,7 +855,7 @@ gtls_connect_step3(struct connectdata *conn,
if(SSL_CONN_CONFIG(verifypeer) ||
SSL_CONN_CONFIG(verifyhost) ||
SSL_SET_OPTION(issuercert)) {
-#ifdef USE_TLS_SRP
+#ifdef HAVE_GNUTLS_SRP
if(SSL_SET_OPTION(authtype) == CURL_TLSAUTH_SRP
&& SSL_SET_OPTION(username) != NULL
&& !SSL_CONN_CONFIG(verifypeer)
@@ -881,7 +868,7 @@ gtls_connect_step3(struct connectdata *conn,
failf(data, "failed to get server cert");
*certverifyresult = GNUTLS_E_NO_CERTIFICATE_FOUND;
return CURLE_PEER_FAILED_VERIFICATION;
-#ifdef USE_TLS_SRP
+#ifdef HAVE_GNUTLS_SRP
}
#endif
}
@@ -899,7 +886,7 @@ gtls_connect_step3(struct connectdata *conn,
const char *beg = (const char *) chainp[i].data;
const char *end = beg + chainp[i].size;
- result = Curl_extract_certinfo(conn, i, beg, end);
+ result = Curl_extract_certinfo(data, i, beg, end);
if(result)
return result;
}
@@ -1128,22 +1115,15 @@ gtls_connect_step3(struct connectdata *conn,
}
#endif
if(!rc) {
-#ifndef CURL_DISABLE_PROXY
- const char * const dispname = SSL_IS_PROXY() ?
- conn->http_proxy.host.dispname : conn->host.dispname;
-#else
- const char * const dispname = conn->host.dispname;
-#endif
-
if(SSL_CONN_CONFIG(verifyhost)) {
failf(data, "SSL: certificate subject name (%s) does not match "
- "target host name '%s'", certname, dispname);
+ "target host name '%s'", certname, SSL_HOST_DISPNAME());
gnutls_x509_crt_deinit(x509_cert);
return CURLE_PEER_FAILED_VERIFICATION;
}
else
infof(data, "\t common name: %s (does not match '%s')\n",
- certname, dispname);
+ certname, SSL_HOST_DISPNAME());
}
else
infof(data, "\t common name: %s (matched)\n", certname);
@@ -1246,13 +1226,18 @@ gtls_connect_step3(struct connectdata *conn,
certclock = gnutls_x509_crt_get_expiration_time(x509_cert);
showtime(data, "expire date", certclock);
+
+ gnutls_free(certfields.data);
}
rc = gnutls_x509_crt_get_issuer_dn2(x509_cert, &certfields);
if(rc)
infof(data, "Failed to get certificate issuer\n");
- else
+ else {
infof(data, "\t issuer: %s\n", certfields.data);
+
+ gnutls_free(certfields.data);
+ }
#endif
gnutls_x509_crt_deinit(x509_cert);
@@ -1279,7 +1264,7 @@ gtls_connect_step3(struct connectdata *conn,
else
infof(data, "ALPN, server did not agree to a protocol\n");
- Curl_multiuse_state(conn, conn->negnpn == CURL_HTTP_VERSION_2 ?
+ Curl_multiuse_state(data, conn->negnpn == CURL_HTTP_VERSION_2 ?
BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);
}
@@ -1306,19 +1291,19 @@ gtls_connect_step3(struct connectdata *conn,
/* extract session ID to the allocated buffer */
gnutls_session_get_data(session, connect_sessionid, &connect_idsize);
- Curl_ssl_sessionid_lock(conn);
- incache = !(Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL,
+ Curl_ssl_sessionid_lock(data);
+ incache = !(Curl_ssl_getsessionid(data, conn, &ssl_sessionid, NULL,
sockindex));
if(incache) {
/* there was one before in the cache, so instead of risking that the
previous one was rejected, we just kill that and store the new */
- Curl_ssl_delsessionid(conn, ssl_sessionid);
+ Curl_ssl_delsessionid(data, ssl_sessionid);
}
/* store this session id */
- result = Curl_ssl_addsessionid(conn, connect_sessionid, connect_idsize,
- sockindex);
- Curl_ssl_sessionid_unlock(conn);
+ result = Curl_ssl_addsessionid(data, conn, connect_sessionid,
+ connect_idsize, sockindex);
+ Curl_ssl_sessionid_unlock(data);
if(result) {
free(connect_sessionid);
result = CURLE_OUT_OF_MEMORY;
@@ -1342,7 +1327,8 @@ gtls_connect_step3(struct connectdata *conn,
'ssl_connect_2_writing' (waiting to be able to write).
*/
static CURLcode
-gtls_connect_common(struct connectdata *conn,
+gtls_connect_common(struct Curl_easy *data,
+ struct connectdata *conn,
int sockindex,
bool nonblocking,
bool *done)
@@ -1352,19 +1338,19 @@ gtls_connect_common(struct connectdata *conn,
/* Initiate the connection, if not already done */
if(ssl_connect_1 == connssl->connecting_state) {
- rc = gtls_connect_step1(conn, sockindex);
+ rc = gtls_connect_step1(data, conn, sockindex);
if(rc)
return rc;
}
- rc = handshake(conn, sockindex, TRUE, nonblocking);
+ rc = handshake(data, conn, sockindex, TRUE, nonblocking);
if(rc)
/* handshake() sets its own error message with failf() */
return rc;
/* Finish connecting once the handshake is done */
if(ssl_connect_1 == connssl->connecting_state) {
- rc = gtls_connect_step3(conn, sockindex);
+ rc = gtls_connect_step3(data, conn, sockindex);
if(rc)
return rc;
}
@@ -1374,18 +1360,20 @@ gtls_connect_common(struct connectdata *conn,
return CURLE_OK;
}
-static CURLcode Curl_gtls_connect_nonblocking(struct connectdata *conn,
- int sockindex, bool *done)
+static CURLcode gtls_connect_nonblocking(struct Curl_easy *data,
+ struct connectdata *conn,
+ int sockindex, bool *done)
{
- return gtls_connect_common(conn, sockindex, TRUE, done);
+ return gtls_connect_common(data, conn, sockindex, TRUE, done);
}
-static CURLcode Curl_gtls_connect(struct connectdata *conn, int sockindex)
+static CURLcode gtls_connect(struct Curl_easy *data, struct connectdata *conn,
+ int sockindex)
{
CURLcode result;
bool done = FALSE;
- result = gtls_connect_common(conn, sockindex, FALSE, &done);
+ result = gtls_connect_common(data, conn, sockindex, FALSE, &done);
if(result)
return result;
@@ -1394,8 +1382,8 @@ static CURLcode Curl_gtls_connect(struct connectdata *conn, int sockindex)
return CURLE_OK;
}
-static bool Curl_gtls_data_pending(const struct connectdata *conn,
- int connindex)
+static bool gtls_data_pending(const struct connectdata *conn,
+ int connindex)
{
const struct ssl_connect_data *connssl = &conn->ssl[connindex];
bool res = FALSE;
@@ -1415,12 +1403,13 @@ static bool Curl_gtls_data_pending(const struct connectdata *conn,
return res;
}
-static ssize_t gtls_send(struct connectdata *conn,
+static ssize_t gtls_send(struct Curl_easy *data,
int sockindex,
const void *mem,
size_t len,
CURLcode *curlcode)
{
+ struct connectdata *conn = data->conn;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
struct ssl_backend_data *backend = connssl->backend;
ssize_t rc = gnutls_record_send(backend->session, mem, len);
@@ -1448,7 +1437,7 @@ static void close_one(struct ssl_connect_data *connssl)
gnutls_certificate_free_credentials(backend->cred);
backend->cred = NULL;
}
-#ifdef USE_TLS_SRP
+#ifdef HAVE_GNUTLS_SRP
if(backend->srp_client_cred) {
gnutls_srp_free_client_credentials(backend->srp_client_cred);
backend->srp_client_cred = NULL;
@@ -1456,8 +1445,10 @@ static void close_one(struct ssl_connect_data *connssl)
#endif
}
-static void Curl_gtls_close(struct connectdata *conn, int sockindex)
+static void gtls_close(struct Curl_easy *data, struct connectdata *conn,
+ int sockindex)
{
+ (void) data;
close_one(&conn->ssl[sockindex]);
#ifndef CURL_DISABLE_PROXY
close_one(&conn->proxy_ssl[sockindex]);
@@ -1468,12 +1459,12 @@ static void Curl_gtls_close(struct connectdata *conn, int sockindex)
* This function is called to shut down the SSL layer but keep the
* socket open (CCC - Clear Command Channel)
*/
-static int Curl_gtls_shutdown(struct connectdata *conn, int sockindex)
+static int gtls_shutdown(struct Curl_easy *data, struct connectdata *conn,
+ int sockindex)
{
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
struct ssl_backend_data *backend = connssl->backend;
int retval = 0;
- struct Curl_easy *data = conn->data;
#ifndef CURL_DISABLE_FTP
/* This has only been tested on the proftpd server, and the mod_tls code
@@ -1530,7 +1521,7 @@ static int Curl_gtls_shutdown(struct connectdata *conn, int sockindex)
}
gnutls_certificate_free_credentials(backend->cred);
-#ifdef USE_TLS_SRP
+#ifdef HAVE_GNUTLS_SRP
if(SSL_SET_OPTION(authtype) == CURL_TLSAUTH_SRP
&& SSL_SET_OPTION(username) != NULL)
gnutls_srp_free_client_credentials(backend->srp_client_cred);
@@ -1542,12 +1533,13 @@ static int Curl_gtls_shutdown(struct connectdata *conn, int sockindex)
return retval;
}
-static ssize_t gtls_recv(struct connectdata *conn, /* connection data */
+static ssize_t gtls_recv(struct Curl_easy *data, /* connection data */
int num, /* socketindex */
char *buf, /* store read data here */
size_t buffersize, /* max amount to read */
CURLcode *curlcode)
{
+ struct connectdata *conn = data->conn;
struct ssl_connect_data *connssl = &conn->ssl[num];
struct ssl_backend_data *backend = connssl->backend;
ssize_t ret;
@@ -1561,7 +1553,7 @@ static ssize_t gtls_recv(struct connectdata *conn, /* connection data */
if(ret == GNUTLS_E_REHANDSHAKE) {
/* BLOCKING call, this is bad but a work-around for now. Fixing this "the
proper way" takes a whole lot of work. */
- CURLcode result = handshake(conn, num, FALSE, FALSE);
+ CURLcode result = handshake(data, conn, num, FALSE, FALSE);
if(result)
/* handshake() writes error message on its own */
*curlcode = result;
@@ -1571,7 +1563,7 @@ static ssize_t gtls_recv(struct connectdata *conn, /* connection data */
}
if(ret < 0) {
- failf(conn->data, "GnuTLS recv error (%d): %s",
+ failf(data, "GnuTLS recv error (%d): %s",
(int)ret, gnutls_strerror((int)ret));
*curlcode = CURLE_RECV_ERROR;
@@ -1581,18 +1573,18 @@ static ssize_t gtls_recv(struct connectdata *conn, /* connection data */
return ret;
}
-static void Curl_gtls_session_free(void *ptr)
+static void gtls_session_free(void *ptr)
{
free(ptr);
}
-static size_t Curl_gtls_version(char *buffer, size_t size)
+static size_t gtls_version(char *buffer, size_t size)
{
return msnprintf(buffer, size, "GnuTLS/%s", gnutls_check_version(NULL));
}
#ifndef USE_GNUTLS_NETTLE
-static int Curl_gtls_seed(struct Curl_easy *data)
+static int gtls_seed(struct Curl_easy *data)
{
/* we have the "SSL is seeded" boolean static to prevent multiple
time-consuming seedings in vain */
@@ -1610,8 +1602,8 @@ static int Curl_gtls_seed(struct Curl_easy *data)
#endif
/* data might be NULL! */
-static CURLcode Curl_gtls_random(struct Curl_easy *data,
- unsigned char *entropy, size_t length)
+static CURLcode gtls_random(struct Curl_easy *data,
+ unsigned char *entropy, size_t length)
{
#if defined(USE_GNUTLS_NETTLE)
int rc;
@@ -1620,36 +1612,16 @@ static CURLcode Curl_gtls_random(struct Curl_easy *data,
return rc?CURLE_FAILED_INIT:CURLE_OK;
#elif defined(USE_GNUTLS)
if(data)
- Curl_gtls_seed(data); /* Initiate the seed if not already done */
+ gtls_seed(data); /* Initiate the seed if not already done */
gcry_randomize(entropy, length, GCRY_STRONG_RANDOM);
#endif
return CURLE_OK;
}
-static CURLcode Curl_gtls_md5sum(unsigned char *tmp, /* input */
- size_t tmplen,
- unsigned char *md5sum, /* output */
- size_t md5len)
-{
-#if defined(USE_GNUTLS_NETTLE)
- struct md5_ctx MD5pw;
- md5_init(&MD5pw);
- md5_update(&MD5pw, (unsigned int)tmplen, tmp);
- md5_digest(&MD5pw, (unsigned int)md5len, md5sum);
-#elif defined(USE_GNUTLS)
- gcry_md_hd_t MD5pw;
- gcry_md_open(&MD5pw, GCRY_MD_MD5, 0);
- gcry_md_write(MD5pw, tmp, tmplen);
- memcpy(md5sum, gcry_md_read(MD5pw, 0), md5len);
- gcry_md_close(MD5pw);
-#endif
- return CURLE_OK;
-}
-
-static CURLcode Curl_gtls_sha256sum(const unsigned char *tmp, /* input */
- size_t tmplen,
- unsigned char *sha256sum, /* output */
- size_t sha256len)
+static CURLcode gtls_sha256sum(const unsigned char *tmp, /* input */
+ size_t tmplen,
+ unsigned char *sha256sum, /* output */
+ size_t sha256len)
{
#if defined(USE_GNUTLS_NETTLE)
struct sha256_ctx SHA256pw;
@@ -1666,12 +1638,12 @@ static CURLcode Curl_gtls_sha256sum(const unsigned char *tmp, /* input */
return CURLE_OK;
}
-static bool Curl_gtls_cert_status_request(void)
+static bool gtls_cert_status_request(void)
{
return TRUE;
}
-static void *Curl_gtls_get_internals(struct ssl_connect_data *connssl,
+static void *gtls_get_internals(struct ssl_connect_data *connssl,
CURLINFO info UNUSED_PARAM)
{
struct ssl_backend_data *backend = connssl->backend;
@@ -1689,26 +1661,25 @@ const struct Curl_ssl Curl_ssl_gnutls = {
sizeof(struct ssl_backend_data),
- Curl_gtls_init, /* init */
- Curl_gtls_cleanup, /* cleanup */
- Curl_gtls_version, /* version */
+ gtls_init, /* init */
+ gtls_cleanup, /* cleanup */
+ gtls_version, /* version */
Curl_none_check_cxn, /* check_cxn */
- Curl_gtls_shutdown, /* shutdown */
- Curl_gtls_data_pending, /* data_pending */
- Curl_gtls_random, /* random */
- Curl_gtls_cert_status_request, /* cert_status_request */
- Curl_gtls_connect, /* connect */
- Curl_gtls_connect_nonblocking, /* connect_nonblocking */
- Curl_gtls_get_internals, /* get_internals */
- Curl_gtls_close, /* close_one */
+ gtls_shutdown, /* shutdown */
+ gtls_data_pending, /* data_pending */
+ gtls_random, /* random */
+ gtls_cert_status_request, /* cert_status_request */
+ gtls_connect, /* connect */
+ gtls_connect_nonblocking, /* connect_nonblocking */
+ gtls_get_internals, /* get_internals */
+ gtls_close, /* close_one */
Curl_none_close_all, /* close_all */
- Curl_gtls_session_free, /* session_free */
+ gtls_session_free, /* session_free */
Curl_none_set_engine, /* set_engine */
Curl_none_set_engine_default, /* set_engine_default */
Curl_none_engines_list, /* engines_list */
Curl_none_false_start, /* false_start */
- Curl_gtls_md5sum, /* md5sum */
- Curl_gtls_sha256sum /* sha256sum */
+ gtls_sha256sum /* sha256sum */
};
#endif /* USE_GNUTLS */
diff --git a/Utilities/cmcurl/lib/vtls/gtls.h b/Utilities/cmcurl/lib/vtls/gtls.h
index 780fc109d..1a146a3a9 100644
--- a/Utilities/cmcurl/lib/vtls/gtls.h
+++ b/Utilities/cmcurl/lib/vtls/gtls.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
diff --git a/Utilities/cmcurl/lib/vtls/keylog.c b/Utilities/cmcurl/lib/vtls/keylog.c
index 70d22ecf0..a45945f8f 100644
--- a/Utilities/cmcurl/lib/vtls/keylog.c
+++ b/Utilities/cmcurl/lib/vtls/keylog.c
@@ -9,7 +9,7 @@
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/vtls/keylog.h b/Utilities/cmcurl/lib/vtls/keylog.h
index c6b99db93..63626da90 100644
--- a/Utilities/cmcurl/lib/vtls/keylog.h
+++ b/Utilities/cmcurl/lib/vtls/keylog.h
@@ -11,7 +11,7 @@
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/vtls/mbedtls.c b/Utilities/cmcurl/lib/vtls/mbedtls.c
index 545f824c6..fc3a948d1 100644
--- a/Utilities/cmcurl/lib/vtls/mbedtls.c
+++ b/Utilities/cmcurl/lib/vtls/mbedtls.c
@@ -5,12 +5,12 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
+ * Copyright (C) 2012 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 2010 - 2011, Hoi-Ho Chan, <hoiho.chan@gmail.com>
- * Copyright (C) 2012 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -31,6 +31,9 @@
#ifdef USE_MBEDTLS
+/* Define this to enable lots of debugging for mbedTLS */
+/* #define MBEDTLS_DEBUG */
+
#include <mbedtls/version.h>
#if MBEDTLS_VERSION_NUMBER >= 0x02040000
#include <mbedtls/net_sockets.h>
@@ -46,6 +49,12 @@
#include <mbedtls/ctr_drbg.h>
#include <mbedtls/sha256.h>
+#if MBEDTLS_VERSION_MAJOR >= 2
+# ifdef MBEDTLS_DEBUG
+# include <mbedtls/debug.h>
+# endif
+#endif
+
#include "urldata.h"
#include "sendf.h"
#include "inet_pton.h"
@@ -113,9 +122,6 @@ static int entropy_func_mutex(void *data, unsigned char *output, size_t len)
#endif /* THREADING_SUPPORT */
-/* Define this to enable lots of debugging for mbedTLS */
-#undef MBEDTLS_DEBUG
-
#ifdef MBEDTLS_DEBUG
static void mbed_debug(void *context, int level, const char *f_name,
int line_nb, const char *line)
@@ -190,9 +196,9 @@ static CURLcode mbedtls_version_from_curl(int *mbedver, long version)
}
static CURLcode
-set_ssl_version_min_max(struct connectdata *conn, int sockindex)
+set_ssl_version_min_max(struct Curl_easy *data, struct connectdata *conn,
+ int sockindex)
{
- struct Curl_easy *data = conn->data;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
struct ssl_backend_data *backend = connssl->backend;
int mbedtls_ver_min = MBEDTLS_SSL_MINOR_VERSION_1;
@@ -235,16 +241,15 @@ set_ssl_version_min_max(struct connectdata *conn, int sockindex)
}
static CURLcode
-mbed_connect_step1(struct connectdata *conn,
+mbed_connect_step1(struct Curl_easy *data, struct connectdata *conn,
int sockindex)
{
- struct Curl_easy *data = conn->data;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
struct ssl_backend_data *backend = connssl->backend;
const char * const ssl_cafile = SSL_CONN_CONFIG(CAfile);
const bool verifypeer = SSL_CONN_CONFIG(verifypeer);
const char * const ssl_capath = SSL_CONN_CONFIG(CApath);
- char * const ssl_cert = SSL_SET_OPTION(cert);
+ char * const ssl_cert = SSL_SET_OPTION(primary.clientcert);
const char * const ssl_crlfile = SSL_SET_OPTION(CRLfile);
#ifndef CURL_DISABLE_PROXY
const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
@@ -274,7 +279,7 @@ mbed_connect_step1(struct connectdata *conn,
#ifdef MBEDTLS_ERROR_C
mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
#endif /* MBEDTLS_ERROR_C */
- failf(data, "Failed - mbedTLS: ctr_drbg_init returned (-0x%04X) %s\n",
+ failf(data, "Failed - mbedTLS: ctr_drbg_init returned (-0x%04X) %s",
-ret, errorbuf);
}
#else
@@ -287,7 +292,7 @@ mbed_connect_step1(struct connectdata *conn,
#ifdef MBEDTLS_ERROR_C
mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
#endif /* MBEDTLS_ERROR_C */
- failf(data, "Failed - mbedTLS: ctr_drbg_init returned (-0x%04X) %s\n",
+ failf(data, "Failed - mbedTLS: ctr_drbg_init returned (-0x%04X) %s",
-ret, errorbuf);
}
#endif /* THREADING_SUPPORT */
@@ -421,7 +426,7 @@ mbed_connect_step1(struct connectdata *conn,
case CURL_SSLVERSION_TLSv1_2:
case CURL_SSLVERSION_TLSv1_3:
{
- CURLcode result = set_ssl_version_min_max(conn, sockindex);
+ CURLcode result = set_ssl_version_min_max(data, conn, sockindex);
if(result != CURLE_OK)
return result;
break;
@@ -457,17 +462,17 @@ mbed_connect_step1(struct connectdata *conn,
if(SSL_SET_OPTION(primary.sessionid)) {
void *old_session = NULL;
- Curl_ssl_sessionid_lock(conn);
- if(!Curl_ssl_getsessionid(conn, &old_session, NULL, sockindex)) {
+ Curl_ssl_sessionid_lock(data);
+ if(!Curl_ssl_getsessionid(data, conn, &old_session, NULL, sockindex)) {
ret = mbedtls_ssl_set_session(&backend->ssl, old_session);
if(ret) {
- Curl_ssl_sessionid_unlock(conn);
+ Curl_ssl_sessionid_unlock(data);
failf(data, "mbedtls_ssl_set_session returned -0x%x", -ret);
return CURLE_SSL_CONNECT_ERROR;
}
infof(data, "mbedTLS re-using session\n");
}
- Curl_ssl_sessionid_unlock(conn);
+ Curl_ssl_sessionid_unlock(data);
}
mbedtls_ssl_conf_ca_chain(&backend->config,
@@ -535,11 +540,10 @@ mbed_connect_step1(struct connectdata *conn,
}
static CURLcode
-mbed_connect_step2(struct connectdata *conn,
+mbed_connect_step2(struct Curl_easy *data, struct connectdata *conn,
int sockindex)
{
int ret;
- struct Curl_easy *data = conn->data;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
struct ssl_backend_data *backend = connssl->backend;
const mbedtls_x509_crt *peercert;
@@ -695,7 +699,7 @@ mbed_connect_step2(struct connectdata *conn,
else {
infof(data, "ALPN, server did not agree to a protocol\n");
}
- Curl_multiuse_state(conn, conn->negnpn == CURL_HTTP_VERSION_2 ?
+ Curl_multiuse_state(data, conn->negnpn == CURL_HTTP_VERSION_2 ?
BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);
}
#endif
@@ -707,13 +711,12 @@ mbed_connect_step2(struct connectdata *conn,
}
static CURLcode
-mbed_connect_step3(struct connectdata *conn,
+mbed_connect_step3(struct Curl_easy *data, struct connectdata *conn,
int sockindex)
{
CURLcode retcode = CURLE_OK;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
struct ssl_backend_data *backend = connssl->backend;
- struct Curl_easy *data = conn->data;
DEBUGASSERT(ssl_connect_3 == connssl->connecting_state);
@@ -738,12 +741,13 @@ mbed_connect_step3(struct connectdata *conn,
}
/* If there's already a matching session in the cache, delete it */
- Curl_ssl_sessionid_lock(conn);
- if(!Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL, sockindex))
- Curl_ssl_delsessionid(conn, old_ssl_sessionid);
+ Curl_ssl_sessionid_lock(data);
+ if(!Curl_ssl_getsessionid(data, conn, &old_ssl_sessionid, NULL, sockindex))
+ Curl_ssl_delsessionid(data, old_ssl_sessionid);
- retcode = Curl_ssl_addsessionid(conn, our_ssl_sessionid, 0, sockindex);
- Curl_ssl_sessionid_unlock(conn);
+ retcode = Curl_ssl_addsessionid(data, conn,
+ our_ssl_sessionid, 0, sockindex);
+ Curl_ssl_sessionid_unlock(data);
if(retcode) {
mbedtls_ssl_session_free(our_ssl_sessionid);
free(our_ssl_sessionid);
@@ -757,16 +761,16 @@ mbed_connect_step3(struct connectdata *conn,
return CURLE_OK;
}
-static ssize_t mbed_send(struct connectdata *conn, int sockindex,
+static ssize_t mbed_send(struct Curl_easy *data, int sockindex,
const void *mem, size_t len,
CURLcode *curlcode)
{
+ struct connectdata *conn = data->conn;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
struct ssl_backend_data *backend = connssl->backend;
int ret = -1;
- ret = mbedtls_ssl_write(&backend->ssl,
- (unsigned char *)mem, len);
+ ret = mbedtls_ssl_write(&backend->ssl, (unsigned char *)mem, len);
if(ret < 0) {
*curlcode = (ret == MBEDTLS_ERR_SSL_WANT_WRITE) ?
@@ -777,15 +781,18 @@ static ssize_t mbed_send(struct connectdata *conn, int sockindex,
return ret;
}
-static void Curl_mbedtls_close_all(struct Curl_easy *data)
+static void mbedtls_close_all(struct Curl_easy *data)
{
(void)data;
}
-static void Curl_mbedtls_close(struct connectdata *conn, int sockindex)
+static void mbedtls_close(struct Curl_easy *data,
+ struct connectdata *conn, int sockindex)
{
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
struct ssl_backend_data *backend = connssl->backend;
+
+ (void) data;
mbedtls_pk_free(&backend->pk);
mbedtls_x509_crt_free(&backend->clicert);
mbedtls_x509_crt_free(&backend->cacert);
@@ -798,16 +805,16 @@ static void Curl_mbedtls_close(struct connectdata *conn, int sockindex)
#endif /* THREADING_SUPPORT */
}
-static ssize_t mbed_recv(struct connectdata *conn, int num,
+static ssize_t mbed_recv(struct Curl_easy *data, int num,
char *buf, size_t buffersize,
CURLcode *curlcode)
{
+ struct connectdata *conn = data->conn;
struct ssl_connect_data *connssl = &conn->ssl[num];
struct ssl_backend_data *backend = connssl->backend;
int ret = -1;
ssize_t len = -1;
- memset(buf, 0, buffersize);
ret = mbedtls_ssl_read(&backend->ssl, (unsigned char *)buf,
buffersize);
@@ -825,13 +832,13 @@ static ssize_t mbed_recv(struct connectdata *conn, int num,
return len;
}
-static void Curl_mbedtls_session_free(void *ptr)
+static void mbedtls_session_free(void *ptr)
{
mbedtls_ssl_session_free(ptr);
free(ptr);
}
-static size_t Curl_mbedtls_version(char *buffer, size_t size)
+static size_t mbedtls_version(char *buffer, size_t size)
{
#ifdef MBEDTLS_VERSION_C
/* if mbedtls_version_get_number() is available it is better */
@@ -843,8 +850,8 @@ static size_t Curl_mbedtls_version(char *buffer, size_t size)
#endif
}
-static CURLcode Curl_mbedtls_random(struct Curl_easy *data,
- unsigned char *entropy, size_t length)
+static CURLcode mbedtls_random(struct Curl_easy *data,
+ unsigned char *entropy, size_t length)
{
#if defined(MBEDTLS_CTR_DRBG_C)
int ret = -1;
@@ -862,7 +869,7 @@ static CURLcode Curl_mbedtls_random(struct Curl_easy *data,
#ifdef MBEDTLS_ERROR_C
mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
#endif /* MBEDTLS_ERROR_C */
- failf(data, "Failed - mbedTLS: ctr_drbg_seed returned (-0x%04X) %s\n",
+ failf(data, "Failed - mbedTLS: ctr_drbg_seed returned (-0x%04X) %s",
-ret, errorbuf);
}
else {
@@ -872,7 +879,7 @@ static CURLcode Curl_mbedtls_random(struct Curl_easy *data,
#ifdef MBEDTLS_ERROR_C
mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
#endif /* MBEDTLS_ERROR_C */
- failf(data, "mbedTLS: ctr_drbg_init returned (-0x%04X) %s\n",
+ failf(data, "mbedTLS: ctr_drbg_init returned (-0x%04X) %s",
-ret, errorbuf);
}
}
@@ -893,13 +900,13 @@ static CURLcode Curl_mbedtls_random(struct Curl_easy *data,
}
static CURLcode
-mbed_connect_common(struct connectdata *conn,
+mbed_connect_common(struct Curl_easy *data,
+ struct connectdata *conn,
int sockindex,
bool nonblocking,
bool *done)
{
CURLcode retcode;
- struct Curl_easy *data = conn->data;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
curl_socket_t sockfd = conn->sock[sockindex];
timediff_t timeout_ms;
@@ -920,7 +927,7 @@ mbed_connect_common(struct connectdata *conn,
failf(data, "SSL connection timeout");
return CURLE_OPERATION_TIMEDOUT;
}
- retcode = mbed_connect_step1(conn, sockindex);
+ retcode = mbed_connect_step1(data, conn, sockindex);
if(retcode)
return retcode;
}
@@ -975,7 +982,7 @@ mbed_connect_common(struct connectdata *conn,
* ensuring that a client using select() or epoll() will always
* have a valid fdset to wait on.
*/
- retcode = mbed_connect_step2(conn, sockindex);
+ retcode = mbed_connect_step2(data, conn, sockindex);
if(retcode || (nonblocking &&
(ssl_connect_2 == connssl->connecting_state ||
ssl_connect_2_reading == connssl->connecting_state ||
@@ -985,7 +992,7 @@ mbed_connect_common(struct connectdata *conn,
} /* repeat step2 until all transactions are done. */
if(ssl_connect_3 == connssl->connecting_state) {
- retcode = mbed_connect_step3(conn, sockindex);
+ retcode = mbed_connect_step3(data, conn, sockindex);
if(retcode)
return retcode;
}
@@ -1005,19 +1012,21 @@ mbed_connect_common(struct connectdata *conn,
return CURLE_OK;
}
-static CURLcode Curl_mbedtls_connect_nonblocking(struct connectdata *conn,
- int sockindex, bool *done)
+static CURLcode mbedtls_connect_nonblocking(struct Curl_easy *data,
+ struct connectdata *conn,
+ int sockindex, bool *done)
{
- return mbed_connect_common(conn, sockindex, TRUE, done);
+ return mbed_connect_common(data, conn, sockindex, TRUE, done);
}
-static CURLcode Curl_mbedtls_connect(struct connectdata *conn, int sockindex)
+static CURLcode mbedtls_connect(struct Curl_easy *data,
+ struct connectdata *conn, int sockindex)
{
CURLcode retcode;
bool done = FALSE;
- retcode = mbed_connect_common(conn, sockindex, FALSE, &done);
+ retcode = mbed_connect_common(data, conn, sockindex, FALSE, &done);
if(retcode)
return retcode;
@@ -1030,28 +1039,28 @@ static CURLcode Curl_mbedtls_connect(struct connectdata *conn, int sockindex)
* return 0 error initializing SSL
* return 1 SSL initialized successfully
*/
-static int Curl_mbedtls_init(void)
+static int mbedtls_init(void)
{
return Curl_mbedtlsthreadlock_thread_setup();
}
-static void Curl_mbedtls_cleanup(void)
+static void mbedtls_cleanup(void)
{
(void)Curl_mbedtlsthreadlock_thread_cleanup();
}
-static bool Curl_mbedtls_data_pending(const struct connectdata *conn,
- int sockindex)
+static bool mbedtls_data_pending(const struct connectdata *conn,
+ int sockindex)
{
const struct ssl_connect_data *connssl = &conn->ssl[sockindex];
struct ssl_backend_data *backend = connssl->backend;
return mbedtls_ssl_get_bytes_avail(&backend->ssl) != 0;
}
-static CURLcode Curl_mbedtls_sha256sum(const unsigned char *input,
- size_t inputlen,
- unsigned char *sha256sum,
- size_t sha256len UNUSED_PARAM)
+static CURLcode mbedtls_sha256sum(const unsigned char *input,
+ size_t inputlen,
+ unsigned char *sha256sum,
+ size_t sha256len UNUSED_PARAM)
{
(void)sha256len;
#if MBEDTLS_VERSION_NUMBER < 0x02070000
@@ -1064,8 +1073,8 @@ static CURLcode Curl_mbedtls_sha256sum(const unsigned char *input,
return CURLE_OK;
}
-static void *Curl_mbedtls_get_internals(struct ssl_connect_data *connssl,
- CURLINFO info UNUSED_PARAM)
+static void *mbedtls_get_internals(struct ssl_connect_data *connssl,
+ CURLINFO info UNUSED_PARAM)
{
struct ssl_backend_data *backend = connssl->backend;
(void)info;
@@ -1081,26 +1090,25 @@ const struct Curl_ssl Curl_ssl_mbedtls = {
sizeof(struct ssl_backend_data),
- Curl_mbedtls_init, /* init */
- Curl_mbedtls_cleanup, /* cleanup */
- Curl_mbedtls_version, /* version */
+ mbedtls_init, /* init */
+ mbedtls_cleanup, /* cleanup */
+ mbedtls_version, /* version */
Curl_none_check_cxn, /* check_cxn */
Curl_none_shutdown, /* shutdown */
- Curl_mbedtls_data_pending, /* data_pending */
- Curl_mbedtls_random, /* random */
+ mbedtls_data_pending, /* data_pending */
+ mbedtls_random, /* random */
Curl_none_cert_status_request, /* cert_status_request */
- Curl_mbedtls_connect, /* connect */
- Curl_mbedtls_connect_nonblocking, /* connect_nonblocking */
- Curl_mbedtls_get_internals, /* get_internals */
- Curl_mbedtls_close, /* close_one */
- Curl_mbedtls_close_all, /* close_all */
- Curl_mbedtls_session_free, /* session_free */
+ mbedtls_connect, /* connect */
+ mbedtls_connect_nonblocking, /* connect_nonblocking */
+ mbedtls_get_internals, /* get_internals */
+ mbedtls_close, /* close_one */
+ mbedtls_close_all, /* close_all */
+ mbedtls_session_free, /* session_free */
Curl_none_set_engine, /* set_engine */
Curl_none_set_engine_default, /* set_engine_default */
Curl_none_engines_list, /* engines_list */
Curl_none_false_start, /* false_start */
- Curl_none_md5sum, /* md5sum */
- Curl_mbedtls_sha256sum /* sha256sum */
+ mbedtls_sha256sum /* sha256sum */
};
#endif /* USE_MBEDTLS */
diff --git a/Utilities/cmcurl/lib/vtls/mbedtls.h b/Utilities/cmcurl/lib/vtls/mbedtls.h
index 0cc64b399..1abd331ea 100644
--- a/Utilities/cmcurl/lib/vtls/mbedtls.h
+++ b/Utilities/cmcurl/lib/vtls/mbedtls.h
@@ -7,12 +7,12 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2012 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2012 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 2010, Hoi-Ho Chan, <hoiho.chan@gmail.com>
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/vtls/mbedtls_threadlock.c b/Utilities/cmcurl/lib/vtls/mbedtls_threadlock.c
index 4d672f106..473f5171e 100644
--- a/Utilities/cmcurl/lib/vtls/mbedtls_threadlock.c
+++ b/Utilities/cmcurl/lib/vtls/mbedtls_threadlock.c
@@ -10,7 +10,7 @@
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/vtls/mbedtls_threadlock.h b/Utilities/cmcurl/lib/vtls/mbedtls_threadlock.h
index 96a787d1a..e40dfc8d6 100644
--- a/Utilities/cmcurl/lib/vtls/mbedtls_threadlock.h
+++ b/Utilities/cmcurl/lib/vtls/mbedtls_threadlock.h
@@ -12,7 +12,7 @@
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/vtls/mesalink.c b/Utilities/cmcurl/lib/vtls/mesalink.c
index 7132bdfd2..b6d1005ec 100644
--- a/Utilities/cmcurl/lib/vtls/mesalink.c
+++ b/Utilities/cmcurl/lib/vtls/mesalink.c
@@ -6,11 +6,11 @@
* \___|\___/|_| \_\_____|
*
* Copyright (C) 2017 - 2018, Yiming Jing, <jingyiming@baidu.com>
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -89,10 +89,10 @@ static int do_file_type(const char *type)
* layer and do all necessary magic.
*/
static CURLcode
-mesalink_connect_step1(struct connectdata *conn, int sockindex)
+mesalink_connect_step1(struct Curl_easy *data,
+ struct connectdata *conn, int sockindex)
{
char *ciphers;
- struct Curl_easy *data = conn->data;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
struct in_addr addr4;
#ifdef ENABLE_IPV6
@@ -158,8 +158,8 @@ mesalink_connect_step1(struct connectdata *conn, int sockindex)
SSL_CONN_CONFIG(CApath))) {
if(SSL_CONN_CONFIG(verifypeer)) {
failf(data,
- "error setting certificate verify locations:\n"
- " CAfile: %s\n CApath: %s",
+ "error setting certificate verify locations: "
+ " CAfile: %s CApath: %s",
SSL_CONN_CONFIG(CAfile) ?
SSL_CONN_CONFIG(CAfile) : "none",
SSL_CONN_CONFIG(CApath) ?
@@ -173,20 +173,18 @@ mesalink_connect_step1(struct connectdata *conn, int sockindex)
else {
infof(data, "successfully set certificate verify locations:\n");
}
- infof(data,
- " CAfile: %s\n"
- " CApath: %s\n",
- SSL_CONN_CONFIG(CAfile)?
- SSL_CONN_CONFIG(CAfile): "none",
- SSL_CONN_CONFIG(CApath)?
- SSL_CONN_CONFIG(CApath): "none");
+ infof(data, " CAfile: %s\n",
+ SSL_CONN_CONFIG(CAfile) ? SSL_CONN_CONFIG(CAfile): "none");
+ infof(data, " CApath: %s\n",
+ SSL_CONN_CONFIG(CApath) ? SSL_CONN_CONFIG(CApath): "none");
}
- if(SSL_SET_OPTION(cert) && SSL_SET_OPTION(key)) {
+ if(SSL_SET_OPTION(primary.clientcert) && SSL_SET_OPTION(key)) {
int file_type = do_file_type(SSL_SET_OPTION(cert_type));
- if(SSL_CTX_use_certificate_chain_file(BACKEND->ctx, SSL_SET_OPTION(cert),
- file_type) != 1) {
+ if(SSL_CTX_use_certificate_chain_file(BACKEND->ctx,
+ SSL_SET_OPTION(primary.clientcert),
+ file_type) != 1) {
failf(data, "unable to use client certificate (no key or wrong pass"
" phrase?)");
return CURLE_SSL_CONNECT_ERROR;
@@ -262,11 +260,11 @@ mesalink_connect_step1(struct connectdata *conn, int sockindex)
if(SSL_SET_OPTION(primary.sessionid)) {
void *ssl_sessionid = NULL;
- Curl_ssl_sessionid_lock(conn);
- if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL, sockindex)) {
+ Curl_ssl_sessionid_lock(data);
+ if(!Curl_ssl_getsessionid(data, conn, &ssl_sessionid, NULL, sockindex)) {
/* we got a session id, use it! */
if(!SSL_set_session(BACKEND->handle, ssl_sessionid)) {
- Curl_ssl_sessionid_unlock(conn);
+ Curl_ssl_sessionid_unlock(data);
failf(
data,
"SSL: SSL_set_session failed: %s",
@@ -276,7 +274,7 @@ mesalink_connect_step1(struct connectdata *conn, int sockindex)
/* Informational message */
infof(data, "SSL re-using session ID\n");
}
- Curl_ssl_sessionid_unlock(conn);
+ Curl_ssl_sessionid_unlock(data);
}
#endif /* MESALINK_HAVE_SESSION */
@@ -290,10 +288,10 @@ mesalink_connect_step1(struct connectdata *conn, int sockindex)
}
static CURLcode
-mesalink_connect_step2(struct connectdata *conn, int sockindex)
+mesalink_connect_step2(struct Curl_easy *data,
+ struct connectdata *conn, int sockindex)
{
int ret = -1;
- struct Curl_easy *data = conn->data;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
conn->recv[sockindex] = mesalink_recv;
@@ -350,27 +348,28 @@ mesalink_connect_step3(struct connectdata *conn, int sockindex)
our_ssl_sessionid = SSL_get_session(BACKEND->handle);
- Curl_ssl_sessionid_lock(conn);
+ Curl_ssl_sessionid_lock(data);
incache =
- !(Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL, sockindex));
+ !(Curl_ssl_getsessionid(data, conn,
+ &old_ssl_sessionid, NULL, sockindex));
if(incache) {
if(old_ssl_sessionid != our_ssl_sessionid) {
infof(data, "old SSL session ID is stale, removing\n");
- Curl_ssl_delsessionid(conn, old_ssl_sessionid);
+ Curl_ssl_delsessionid(data, old_ssl_sessionid);
incache = FALSE;
}
}
if(!incache) {
result = Curl_ssl_addsessionid(
- conn, our_ssl_sessionid, 0 /* unknown size */, sockindex);
+ data, conn, our_ssl_sessionid, 0 /* unknown size */, sockindex);
if(result) {
- Curl_ssl_sessionid_unlock(conn);
+ Curl_ssl_sessionid_unlock(data);
failf(data, "failed to store ssl session");
return result;
}
}
- Curl_ssl_sessionid_unlock(conn);
+ Curl_ssl_sessionid_unlock(data);
}
#endif /* MESALINK_HAVE_SESSION */
@@ -380,9 +379,10 @@ mesalink_connect_step3(struct connectdata *conn, int sockindex)
}
static ssize_t
-mesalink_send(struct connectdata *conn, int sockindex, const void *mem,
+mesalink_send(struct Curl_easy *data, int sockindex, const void *mem,
size_t len, CURLcode *curlcode)
{
+ struct connectdata *conn = data->conn;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
char error_buffer[MESALINK_MAX_ERROR_SZ];
int memlen = (len > (size_t)INT_MAX) ? INT_MAX : (int)len;
@@ -397,7 +397,7 @@ mesalink_send(struct connectdata *conn, int sockindex, const void *mem,
*curlcode = CURLE_AGAIN;
return -1;
default:
- failf(conn->data,
+ failf(data,
"SSL write: %s, errno %d",
ERR_error_string_n(err, error_buffer, sizeof(error_buffer)),
SOCKERRNO);
@@ -409,10 +409,12 @@ mesalink_send(struct connectdata *conn, int sockindex, const void *mem,
}
static void
-Curl_mesalink_close(struct connectdata *conn, int sockindex)
+mesalink_close(struct Curl_easy *data, struct connectdata *conn, int sockindex)
{
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ (void) data;
+
if(BACKEND->handle) {
(void)SSL_shutdown(BACKEND->handle);
SSL_free(BACKEND->handle);
@@ -425,9 +427,10 @@ Curl_mesalink_close(struct connectdata *conn, int sockindex)
}
static ssize_t
-mesalink_recv(struct connectdata *conn, int num, char *buf, size_t buffersize,
+mesalink_recv(struct Curl_easy *data, int num, char *buf, size_t buffersize,
CURLcode *curlcode)
{
+ struct connectdata *conn = data->conn;
struct ssl_connect_data *connssl = &conn->ssl[num];
char error_buffer[MESALINK_MAX_ERROR_SZ];
int buffsize = (buffersize > (size_t)INT_MAX) ? INT_MAX : (int)buffersize;
@@ -446,7 +449,7 @@ mesalink_recv(struct connectdata *conn, int num, char *buf, size_t buffersize,
*curlcode = CURLE_AGAIN;
return -1;
default:
- failf(conn->data,
+ failf(data,
"SSL read: %s, errno %d",
ERR_error_string_n(err, error_buffer, sizeof(error_buffer)),
SOCKERRNO);
@@ -458,13 +461,13 @@ mesalink_recv(struct connectdata *conn, int num, char *buf, size_t buffersize,
}
static size_t
-Curl_mesalink_version(char *buffer, size_t size)
+mesalink_version(char *buffer, size_t size)
{
return msnprintf(buffer, size, "MesaLink/%s", MESALINK_VERSION_STRING);
}
static int
-Curl_mesalink_init(void)
+mesalink_init(void)
{
return (SSL_library_init() == SSL_SUCCESS);
}
@@ -474,11 +477,14 @@ Curl_mesalink_init(void)
* socket open (CCC - Clear Command Channel)
*/
static int
-Curl_mesalink_shutdown(struct connectdata *conn, int sockindex)
+mesalink_shutdown(struct Curl_easy *data,
+ struct connectdata *conn, int sockindex)
{
int retval = 0;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ (void) data;
+
if(BACKEND->handle) {
SSL_free(BACKEND->handle);
BACKEND->handle = NULL;
@@ -487,11 +493,10 @@ Curl_mesalink_shutdown(struct connectdata *conn, int sockindex)
}
static CURLcode
-mesalink_connect_common(struct connectdata *conn, int sockindex,
- bool nonblocking, bool *done)
+mesalink_connect_common(struct Curl_easy *data, struct connectdata *conn,
+ int sockindex, bool nonblocking, bool *done)
{
CURLcode result;
- struct Curl_easy *data = conn->data;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
curl_socket_t sockfd = conn->sock[sockindex];
timediff_t timeout_ms;
@@ -513,7 +518,7 @@ mesalink_connect_common(struct connectdata *conn, int sockindex,
return CURLE_OPERATION_TIMEDOUT;
}
- result = mesalink_connect_step1(conn, sockindex);
+ result = mesalink_connect_step1(data, conn, sockindex);
if(result)
return result;
}
@@ -570,7 +575,7 @@ mesalink_connect_common(struct connectdata *conn, int sockindex,
* ensuring that a client using select() or epoll() will always
* have a valid fdset to wait on.
*/
- result = mesalink_connect_step2(conn, sockindex);
+ result = mesalink_connect_step2(data, conn, sockindex);
if(result ||
(nonblocking && (ssl_connect_2 == connssl->connecting_state ||
@@ -602,19 +607,20 @@ mesalink_connect_common(struct connectdata *conn, int sockindex,
}
static CURLcode
-Curl_mesalink_connect_nonblocking(struct connectdata *conn, int sockindex,
- bool *done)
+mesalink_connect_nonblocking(struct Curl_easy *data, struct connectdata *conn,
+ int sockindex, bool *done)
{
- return mesalink_connect_common(conn, sockindex, TRUE, done);
+ return mesalink_connect_common(data, conn, sockindex, TRUE, done);
}
static CURLcode
-Curl_mesalink_connect(struct connectdata *conn, int sockindex)
+mesalink_connect(struct Curl_easy *data, struct connectdata *conn,
+ int sockindex)
{
CURLcode result;
bool done = FALSE;
- result = mesalink_connect_common(conn, sockindex, FALSE, &done);
+ result = mesalink_connect_common(data, conn, sockindex, FALSE, &done);
if(result)
return result;
@@ -624,8 +630,8 @@ Curl_mesalink_connect(struct connectdata *conn, int sockindex)
}
static void *
-Curl_mesalink_get_internals(struct ssl_connect_data *connssl,
- CURLINFO info UNUSED_PARAM)
+mesalink_get_internals(struct ssl_connect_data *connssl,
+ CURLINFO info UNUSED_PARAM)
{
(void)info;
return BACKEND->handle;
@@ -638,26 +644,25 @@ const struct Curl_ssl Curl_ssl_mesalink = {
sizeof(struct ssl_backend_data),
- Curl_mesalink_init, /* init */
- Curl_none_cleanup, /* cleanup */
- Curl_mesalink_version, /* version */
- Curl_none_check_cxn, /* check_cxn */
- Curl_mesalink_shutdown, /* shutdown */
- Curl_none_data_pending, /* data_pending */
- Curl_none_random, /* random */
+ mesalink_init, /* init */
+ Curl_none_cleanup, /* cleanup */
+ mesalink_version, /* version */
+ Curl_none_check_cxn, /* check_cxn */
+ mesalink_shutdown, /* shutdown */
+ Curl_none_data_pending, /* data_pending */
+ Curl_none_random, /* random */
Curl_none_cert_status_request, /* cert_status_request */
- Curl_mesalink_connect, /* connect */
- Curl_mesalink_connect_nonblocking, /* connect_nonblocking */
- Curl_mesalink_get_internals, /* get_internals */
- Curl_mesalink_close, /* close_one */
- Curl_none_close_all, /* close_all */
- Curl_none_session_free, /* session_free */
- Curl_none_set_engine, /* set_engine */
- Curl_none_set_engine_default, /* set_engine_default */
- Curl_none_engines_list, /* engines_list */
- Curl_none_false_start, /* false_start */
- Curl_none_md5sum, /* md5sum */
- NULL /* sha256sum */
+ mesalink_connect, /* connect */
+ mesalink_connect_nonblocking, /* connect_nonblocking */
+ mesalink_get_internals, /* get_internals */
+ mesalink_close, /* close_one */
+ Curl_none_close_all, /* close_all */
+ Curl_none_session_free, /* session_free */
+ Curl_none_set_engine, /* set_engine */
+ Curl_none_set_engine_default, /* set_engine_default */
+ Curl_none_engines_list, /* engines_list */
+ Curl_none_false_start, /* false_start */
+ NULL /* sha256sum */
};
#endif
diff --git a/Utilities/cmcurl/lib/vtls/mesalink.h b/Utilities/cmcurl/lib/vtls/mesalink.h
index 54cb94ad3..03f520c1d 100644
--- a/Utilities/cmcurl/lib/vtls/mesalink.h
+++ b/Utilities/cmcurl/lib/vtls/mesalink.h
@@ -7,12 +7,12 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2017-2018, Yiming Jing, <jingyiming@baidu.com>
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2017 - 2018, Yiming Jing, <jingyiming@baidu.com>
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/vtls/nss.c b/Utilities/cmcurl/lib/vtls/nss.c
index 0f0d1ee6c..e5ab71cdf 100644
--- a/Utilities/cmcurl/lib/vtls/nss.c
+++ b/Utilities/cmcurl/lib/vtls/nss.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -83,7 +83,7 @@ struct ssl_backend_data {
PRFileDesc *handle;
char *client_nickname;
struct Curl_easy *data;
- struct curl_llist obj_list;
+ struct Curl_llist obj_list;
PK11GenericObject *obj_clicert;
};
@@ -91,14 +91,14 @@ static PRLock *nss_initlock = NULL;
static PRLock *nss_crllock = NULL;
static PRLock *nss_findslot_lock = NULL;
static PRLock *nss_trustload_lock = NULL;
-static struct curl_llist nss_crl_list;
+static struct Curl_llist nss_crl_list;
static NSSInitContext *nss_context = NULL;
static volatile int initialized = 0;
/* type used to wrap pointers as list nodes */
struct ptr_list_wrap {
void *ptr;
- struct curl_llist_element node;
+ struct Curl_llist_element node;
};
struct cipher_s {
@@ -430,7 +430,7 @@ static PK11SlotInfo* nss_find_slot_by_name(const char *slot_name)
}
/* wrap 'ptr' as list node and tail-insert into 'list' */
-static CURLcode insert_wrapped_ptr(struct curl_llist *list, void *ptr)
+static CURLcode insert_wrapped_ptr(struct Curl_llist *list, void *ptr)
{
struct ptr_list_wrap *wrap = malloc(sizeof(*wrap));
if(!wrap)
@@ -443,7 +443,7 @@ static CURLcode insert_wrapped_ptr(struct curl_llist *list, void *ptr)
/* Call PK11_CreateGenericObject() with the given obj_class and filename. If
* the call succeeds, append the object handle to the list of objects so that
- * the object can be destroyed in Curl_nss_close(). */
+ * the object can be destroyed in nss_close(). */
static CURLcode nss_create_object(struct ssl_connect_data *connssl,
CK_OBJECT_CLASS obj_class,
const char *filename, bool cacert)
@@ -508,7 +508,7 @@ static CURLcode nss_create_object(struct ssl_connect_data *connssl,
/* Destroy the NSS object whose handle is given by ptr. This function is
* a callback of Curl_llist_alloc() used by Curl_llist_destroy() to destroy
- * NSS objects in Curl_nss_close() */
+ * NSS objects in nss_close() */
static void nss_destroy_object(void *user, void *ptr)
{
struct ptr_list_wrap *wrap = (struct ptr_list_wrap *) ptr;
@@ -587,7 +587,7 @@ static CURLcode nss_cache_crl(SECItem *crl_der)
return CURLE_SSL_CRL_BADFILE;
}
- /* store the CRL item so that we can free it in Curl_nss_cleanup() */
+ /* store the CRL item so that we can free it in nss_cleanup() */
if(insert_wrapped_ptr(&nss_crl_list, crl_der) != CURLE_OK) {
if(SECSuccess == CERT_UncacheCRL(db, crl_der))
SECITEM_FreeItem(crl_der, PR_TRUE);
@@ -665,14 +665,13 @@ fail:
return CURLE_SSL_CRL_BADFILE;
}
-static CURLcode nss_load_key(struct connectdata *conn, int sockindex,
- char *key_file)
+static CURLcode nss_load_key(struct Curl_easy *data, struct connectdata *conn,
+ int sockindex, char *key_file)
{
PK11SlotInfo *slot, *tmp;
SECStatus status;
CURLcode result;
struct ssl_connect_data *ssl = conn->ssl;
- struct Curl_easy *data = conn->data;
(void)sockindex; /* unused */
@@ -701,15 +700,15 @@ static CURLcode nss_load_key(struct connectdata *conn, int sockindex,
return (SECSuccess == status) ? CURLE_OK : CURLE_SSL_CERTPROBLEM;
}
-static int display_error(struct connectdata *conn, PRInt32 err,
+static int display_error(struct Curl_easy *data, PRInt32 err,
const char *filename)
{
switch(err) {
case SEC_ERROR_BAD_PASSWORD:
- failf(conn->data, "Unable to load client key: Incorrect password");
+ failf(data, "Unable to load client key: Incorrect password");
return 1;
case SEC_ERROR_UNKNOWN_CERT:
- failf(conn->data, "Unable to load certificate %s", filename);
+ failf(data, "Unable to load certificate %s", filename);
return 1;
default:
break;
@@ -717,17 +716,16 @@ static int display_error(struct connectdata *conn, PRInt32 err,
return 0; /* The caller will print a generic error */
}
-static CURLcode cert_stuff(struct connectdata *conn, int sockindex,
- char *cert_file, char *key_file)
+static CURLcode cert_stuff(struct Curl_easy *data, struct connectdata *conn,
+ int sockindex, char *cert_file, char *key_file)
{
- struct Curl_easy *data = conn->data;
CURLcode result;
if(cert_file) {
result = nss_load_cert(&conn->ssl[sockindex], cert_file, PR_FALSE);
if(result) {
const PRErrorCode err = PR_GetError();
- if(!display_error(conn, err, cert_file)) {
+ if(!display_error(data, err, cert_file)) {
const char *err_name = nss_error_to_name(err);
failf(data, "unable to load client cert: %d (%s)", err, err_name);
}
@@ -738,13 +736,13 @@ static CURLcode cert_stuff(struct connectdata *conn, int sockindex,
if(key_file || (is_file(cert_file))) {
if(key_file)
- result = nss_load_key(conn, sockindex, key_file);
+ result = nss_load_key(data, conn, sockindex, key_file);
else
/* In case the cert file also has the key */
- result = nss_load_key(conn, sockindex, cert_file);
+ result = nss_load_key(data, conn, sockindex, cert_file);
if(result) {
const PRErrorCode err = PR_GetError();
- if(!display_error(conn, err, key_file)) {
+ if(!display_error(data, err, key_file)) {
const char *err_name = nss_error_to_name(err);
failf(data, "unable to load client key: %d (%s)", err, err_name);
}
@@ -771,7 +769,8 @@ static char *nss_get_password(PK11SlotInfo *slot, PRBool retry, void *arg)
static SECStatus nss_auth_cert_hook(void *arg, PRFileDesc *fd, PRBool checksig,
PRBool isServer)
{
- struct connectdata *conn = (struct connectdata *)arg;
+ struct Curl_easy *data = (struct Curl_easy *)arg;
+ struct connectdata *conn = data->conn;
#ifdef SSL_ENABLE_OCSP_STAPLING
if(SSL_CONN_CONFIG(verifystatus)) {
@@ -779,12 +778,12 @@ static SECStatus nss_auth_cert_hook(void *arg, PRFileDesc *fd, PRBool checksig,
const SECItemArray *csa = SSL_PeerStapledOCSPResponses(fd);
if(!csa) {
- failf(conn->data, "Invalid OCSP response");
+ failf(data, "Invalid OCSP response");
return SECFailure;
}
if(csa->len == 0) {
- failf(conn->data, "No OCSP response received");
+ failf(data, "No OCSP response received");
return SECFailure;
}
@@ -794,14 +793,14 @@ static SECStatus nss_auth_cert_hook(void *arg, PRFileDesc *fd, PRBool checksig,
);
if(cacheResult != SECSuccess) {
- failf(conn->data, "Invalid OCSP response");
+ failf(data, "Invalid OCSP response");
return cacheResult;
}
}
#endif
if(!SSL_CONN_CONFIG(verifypeer)) {
- infof(conn->data, "skipping SSL peer certificate verification\n");
+ infof(data, "skipping SSL peer certificate verification\n");
return SECSuccess;
}
@@ -813,7 +812,8 @@ static SECStatus nss_auth_cert_hook(void *arg, PRFileDesc *fd, PRBool checksig,
*/
static void HandshakeCallback(PRFileDesc *sock, void *arg)
{
- struct connectdata *conn = (struct connectdata*) arg;
+ struct Curl_easy *data = (struct Curl_easy *)arg;
+ struct connectdata *conn = data->conn;
unsigned int buflenmax = 50;
unsigned char buf[50];
unsigned int buflen;
@@ -833,15 +833,15 @@ static void HandshakeCallback(PRFileDesc *sock, void *arg)
#endif
case SSL_NEXT_PROTO_NO_SUPPORT:
case SSL_NEXT_PROTO_NO_OVERLAP:
- infof(conn->data, "ALPN/NPN, server did not agree to a protocol\n");
+ infof(data, "ALPN/NPN, server did not agree to a protocol\n");
return;
#ifdef SSL_ENABLE_ALPN
case SSL_NEXT_PROTO_SELECTED:
- infof(conn->data, "ALPN, server accepted to use %.*s\n", buflen, buf);
+ infof(data, "ALPN, server accepted to use %.*s\n", buflen, buf);
break;
#endif
case SSL_NEXT_PROTO_NEGOTIATED:
- infof(conn->data, "NPN, server accepted to use %.*s\n", buflen, buf);
+ infof(data, "NPN, server accepted to use %.*s\n", buflen, buf);
break;
}
@@ -856,7 +856,7 @@ static void HandshakeCallback(PRFileDesc *sock, void *arg)
!memcmp(ALPN_HTTP_1_1, buf, ALPN_HTTP_1_1_LENGTH)) {
conn->negnpn = CURL_HTTP_VERSION_1_1;
}
- Curl_multiuse_state(conn, conn->negnpn == CURL_HTTP_VERSION_2 ?
+ Curl_multiuse_state(data, conn->negnpn == CURL_HTTP_VERSION_2 ?
BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);
}
}
@@ -865,8 +865,7 @@ static void HandshakeCallback(PRFileDesc *sock, void *arg)
static SECStatus CanFalseStartCallback(PRFileDesc *sock, void *client_data,
PRBool *canFalseStart)
{
- struct connectdata *conn = client_data;
- struct Curl_easy *data = conn->data;
+ struct Curl_easy *data = (struct Curl_easy *)client_data;
SSLChannelInfo channelInfo;
SSLCipherSuiteInfo cipherInfo;
@@ -949,7 +948,7 @@ static void display_cert_info(struct Curl_easy *data,
PR_Free(common_name);
}
-static CURLcode display_conn_info(struct connectdata *conn, PRFileDesc *sock)
+static CURLcode display_conn_info(struct Curl_easy *data, PRFileDesc *sock)
{
CURLcode result = CURLE_OK;
SSLChannelInfo channel;
@@ -965,16 +964,16 @@ static CURLcode display_conn_info(struct connectdata *conn, PRFileDesc *sock)
channel.cipherSuite) {
if(SSL_GetCipherSuiteInfo(channel.cipherSuite,
&suite, sizeof(suite)) == SECSuccess) {
- infof(conn->data, "SSL connection using %s\n", suite.cipherSuiteName);
+ infof(data, "SSL connection using %s\n", suite.cipherSuiteName);
}
}
cert = SSL_PeerCertificate(sock);
if(cert) {
- infof(conn->data, "Server certificate:\n");
+ infof(data, "Server certificate:\n");
- if(!conn->data->set.ssl.certinfo) {
- display_cert_info(conn->data, cert);
+ if(!data->set.ssl.certinfo) {
+ display_cert_info(data, cert);
CERT_DestroyCertificate(cert);
}
else {
@@ -995,10 +994,10 @@ static CURLcode display_conn_info(struct connectdata *conn, PRFileDesc *sock)
}
}
- result = Curl_ssl_init_certinfo(conn->data, i);
+ result = Curl_ssl_init_certinfo(data, i);
if(!result) {
for(i = 0; cert; cert = cert2) {
- result = Curl_extract_certinfo(conn, i++, (char *)cert->derCert.data,
+ result = Curl_extract_certinfo(data, i++, (char *)cert->derCert.data,
(char *)cert->derCert.data +
cert->derCert.len);
if(result)
@@ -1021,18 +1020,13 @@ static CURLcode display_conn_info(struct connectdata *conn, PRFileDesc *sock)
static SECStatus BadCertHandler(void *arg, PRFileDesc *sock)
{
- struct connectdata *conn = (struct connectdata *)arg;
- struct Curl_easy *data = conn->data;
+ struct Curl_easy *data = (struct Curl_easy *)arg;
+ struct connectdata *conn = data->conn;
PRErrorCode err = PR_GetError();
CERTCertificate *cert;
/* remember the cert verification result */
-#ifndef CURL_DISABLE_PROXY
- if(SSL_IS_PROXY())
- data->set.proxy_ssl.certverifyresult = err;
- else
-#endif
- data->set.ssl.certverifyresult = err;
+ SSL_SET_OPTION_LVALUE(certverifyresult) = err;
if(err == SSL_ERROR_BAD_CERT_DOMAIN && !SSL_CONN_CONFIG(verifyhost))
/* we are asked not to verify the host name */
@@ -1340,7 +1334,7 @@ static CURLcode nss_init_core(struct Curl_easy *data, const char *cert_dir)
infof(data, "Initializing NSS with certpath: %s\n", certpath);
nss_context = NSS_InitContext(certpath, "", "", "", &initparams,
- NSS_INIT_READONLY | NSS_INIT_PK11RELOAD);
+ NSS_INIT_READONLY | NSS_INIT_PK11RELOAD);
free(certpath);
if(nss_context != NULL)
@@ -1365,7 +1359,7 @@ static CURLcode nss_init_core(struct Curl_easy *data, const char *cert_dir)
}
/* data might be NULL */
-static CURLcode nss_init(struct Curl_easy *data)
+static CURLcode nss_setup(struct Curl_easy *data)
{
char *cert_dir;
struct_stat st;
@@ -1374,7 +1368,7 @@ static CURLcode nss_init(struct Curl_easy *data)
if(initialized)
return CURLE_OK;
- /* list of all CRL items we need to destroy in Curl_nss_cleanup() */
+ /* list of all CRL items we need to destroy in nss_cleanup() */
Curl_llist_init(&nss_crl_list, nss_destroy_crl_item);
/* First we check if $SSL_DIR points to a valid dir */
@@ -1428,7 +1422,7 @@ static CURLcode nss_init(struct Curl_easy *data)
* @retval 0 error initializing SSL
* @retval 1 SSL initialized successfully
*/
-static int Curl_nss_init(void)
+static int nss_init(void)
{
/* curl_global_init() is not thread-safe so this test is ok */
if(nss_initlock == NULL) {
@@ -1456,14 +1450,14 @@ CURLcode Curl_nss_force_init(struct Curl_easy *data)
}
PR_Lock(nss_initlock);
- result = nss_init(data);
+ result = nss_setup(data);
PR_Unlock(nss_initlock);
return result;
}
/* Global cleanup */
-static void Curl_nss_cleanup(void)
+static void nss_cleanup(void)
{
/* This function isn't required to be threadsafe and this is only done
* as a safety feature.
@@ -1503,7 +1497,7 @@ static void Curl_nss_cleanup(void)
* 0 means the connection has been closed
* -1 means the connection status is unknown
*/
-static int Curl_nss_check_cxn(struct connectdata *conn)
+static int nss_check_cxn(struct connectdata *conn)
{
struct ssl_connect_data *connssl = &conn->ssl[FIRSTSOCKET];
struct ssl_backend_data *backend = connssl->backend;
@@ -1522,7 +1516,7 @@ static int Curl_nss_check_cxn(struct connectdata *conn)
return -1; /* connection status unknown */
}
-static void nss_close(struct ssl_connect_data *connssl)
+static void close_one(struct ssl_connect_data *connssl)
{
/* before the cleanup, check whether we are using a client certificate */
struct ssl_backend_data *backend = connssl->backend;
@@ -1552,7 +1546,8 @@ static void nss_close(struct ssl_connect_data *connssl)
/*
* This function is called when an SSL connection is closed.
*/
-static void Curl_nss_close(struct connectdata *conn, int sockindex)
+static void nss_close(struct Curl_easy *data, struct connectdata *conn,
+ int sockindex)
{
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
#ifndef CURL_DISABLE_PROXY
@@ -1560,6 +1555,7 @@ static void Curl_nss_close(struct connectdata *conn, int sockindex)
#endif
struct ssl_backend_data *backend = connssl->backend;
+ (void)data;
if(backend->handle
#ifndef CURL_DISABLE_PROXY
|| connssl_proxy->backend->handle
@@ -1578,9 +1574,9 @@ static void Curl_nss_close(struct connectdata *conn, int sockindex)
a double close leading to crash. */
connssl_proxy->backend->handle = NULL;
- nss_close(connssl_proxy);
+ close_one(connssl_proxy);
#endif
- nss_close(connssl);
+ close_one(connssl);
}
/* return true if NSS can provide error code (and possibly msg) for the
@@ -1616,10 +1612,10 @@ static bool is_cc_error(PRInt32 err)
static Curl_recv nss_recv;
static Curl_send nss_send;
-static CURLcode nss_load_ca_certificates(struct connectdata *conn,
+static CURLcode nss_load_ca_certificates(struct Curl_easy *data,
+ struct connectdata *conn,
int sockindex)
{
- struct Curl_easy *data = conn->data;
const char *cafile = SSL_CONN_CONFIG(CAfile);
const char *capath = SSL_CONN_CONFIG(CApath);
bool use_trust_module;
@@ -1631,9 +1627,8 @@ static CURLcode nss_load_ca_certificates(struct connectdata *conn,
if(capath && !capath[0])
capath = NULL;
- infof(data, " CAfile: %s\n CApath: %s\n",
- cafile ? cafile : "none",
- capath ? capath : "none");
+ infof(data, " CAfile: %s\n", cafile ? cafile : "none");
+ infof(data, " CApath: %s\n", capath ? capath : "none");
/* load libnssckbi.so if no other trust roots were specified */
use_trust_module = !cafile && !capath;
@@ -1673,7 +1668,8 @@ static CURLcode nss_load_ca_certificates(struct connectdata *conn,
if(!dir)
return CURLE_SSL_CACERT_BADFILE;
- while((entry = PR_ReadDir(dir, PR_SKIP_BOTH | PR_SKIP_HIDDEN))) {
+ while((entry =
+ PR_ReadDir(dir, (PRDirFlags)(PR_SKIP_BOTH | PR_SKIP_HIDDEN)))) {
char *fullpath = aprintf("%s/%s", capath, entry->name);
if(!fullpath) {
PR_CloseDir(dir);
@@ -1824,26 +1820,20 @@ static CURLcode nss_set_blocking(struct ssl_connect_data *connssl,
return CURLE_OK;
}
-static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex)
+static CURLcode nss_setup_connect(struct Curl_easy *data,
+ struct connectdata *conn, int sockindex)
{
PRFileDesc *model = NULL;
PRFileDesc *nspr_io = NULL;
PRFileDesc *nspr_io_stub = NULL;
PRBool ssl_no_cache;
PRBool ssl_cbc_random_iv;
- struct Curl_easy *data = conn->data;
curl_socket_t sockfd = conn->sock[sockindex];
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
struct ssl_backend_data *backend = connssl->backend;
CURLcode result;
bool second_layer = FALSE;
SSLVersionRange sslver_supported;
-#ifndef CURL_DISABLE_PROXY
- const char *hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
- conn->host.name;
-#else
- const char *hostname = conn->host.name;
-#endif
SSLVersionRange sslver = {
SSL_LIBRARY_VERSION_TLS_1_0, /* min */
@@ -1860,11 +1850,11 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex)
backend->data = data;
- /* list of all NSS objects we need to destroy in Curl_nss_close() */
+ /* list of all NSS objects we need to destroy in nss_do_close() */
Curl_llist_init(&backend->obj_list, nss_destroy_object);
PR_Lock(nss_initlock);
- result = nss_init(conn->data);
+ result = nss_setup(data);
if(result) {
PR_Unlock(nss_initlock);
goto error;
@@ -1944,25 +1934,20 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex)
/* bypass the default SSL_AuthCertificate() hook in case we do not want to
* verify peer */
- if(SSL_AuthCertificateHook(model, nss_auth_cert_hook, conn) != SECSuccess)
+ if(SSL_AuthCertificateHook(model, nss_auth_cert_hook, data) != SECSuccess)
goto error;
/* not checked yet */
-#ifndef CURL_DISABLE_PROXY
- if(SSL_IS_PROXY())
- data->set.proxy_ssl.certverifyresult = 0;
- else
-#endif
- data->set.ssl.certverifyresult = 0;
+ SSL_SET_OPTION_LVALUE(certverifyresult) = 0;
- if(SSL_BadCertHook(model, BadCertHandler, conn) != SECSuccess)
+ if(SSL_BadCertHook(model, BadCertHandler, data) != SECSuccess)
goto error;
- if(SSL_HandshakeCallback(model, HandshakeCallback, conn) != SECSuccess)
+ if(SSL_HandshakeCallback(model, HandshakeCallback, data) != SECSuccess)
goto error;
{
- const CURLcode rv = nss_load_ca_certificates(conn, sockindex);
+ const CURLcode rv = nss_load_ca_certificates(data, conn, sockindex);
if((rv == CURLE_SSL_CACERT_BADFILE) && !SSL_CONN_CONFIG(verifypeer))
/* not a fatal error because we are not going to verify the peer */
infof(data, "warning: CA certificates failed to load\n");
@@ -1981,14 +1966,15 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex)
infof(data, " CRLfile: %s\n", SSL_SET_OPTION(CRLfile));
}
- if(SSL_SET_OPTION(cert)) {
- char *nickname = dup_nickname(data, SSL_SET_OPTION(cert));
+ if(SSL_SET_OPTION(primary.clientcert)) {
+ char *nickname = dup_nickname(data, SSL_SET_OPTION(primary.clientcert));
if(nickname) {
/* we are not going to use libnsspem.so to read the client cert */
backend->obj_clicert = NULL;
}
else {
- CURLcode rv = cert_stuff(conn, sockindex, SSL_SET_OPTION(cert),
+ CURLcode rv = cert_stuff(data, conn, sockindex,
+ SSL_SET_OPTION(primary.clientcert),
SSL_SET_OPTION(key));
if(rv) {
/* failf() is already done in cert_stuff() */
@@ -2086,7 +2072,7 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex)
goto error;
if(SSL_SetCanFalseStartCallback(backend->handle, CanFalseStartCallback,
- conn) != SECSuccess)
+ data) != SECSuccess)
goto error;
}
#endif
@@ -2124,11 +2110,11 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex)
goto error;
/* propagate hostname to the TLS layer */
- if(SSL_SetURL(backend->handle, hostname) != SECSuccess)
+ if(SSL_SetURL(backend->handle, SSL_HOST_NAME()) != SECSuccess)
goto error;
/* prevent NSS from re-using the session for a different hostname */
- if(SSL_SetSockPeerID(backend->handle, hostname) != SECSuccess)
+ if(SSL_SetSockPeerID(backend->handle, SSL_HOST_NAME()) != SECSuccess)
goto error;
return CURLE_OK;
@@ -2140,25 +2126,13 @@ error:
return nss_fail_connect(connssl, data, result);
}
-static CURLcode nss_do_connect(struct connectdata *conn, int sockindex)
+static CURLcode nss_do_connect(struct Curl_easy *data,
+ struct connectdata *conn, int sockindex)
{
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
struct ssl_backend_data *backend = connssl->backend;
- struct Curl_easy *data = conn->data;
CURLcode result = CURLE_SSL_CONNECT_ERROR;
PRUint32 timeout;
-#ifndef CURL_DISABLE_PROXY
- long * const certverifyresult = SSL_IS_PROXY() ?
- &data->set.proxy_ssl.certverifyresult : &data->set.ssl.certverifyresult;
- const char * const pinnedpubkey = SSL_IS_PROXY() ?
- data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] :
- data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG];
-#else
- long * const certverifyresult = &data->set.ssl.certverifyresult;
- const char * const pinnedpubkey =
- data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG];
-#endif
-
/* check timeout situation */
const timediff_t time_left = Curl_timeleft(data, NULL, TRUE);
@@ -2174,14 +2148,14 @@ static CURLcode nss_do_connect(struct connectdata *conn, int sockindex)
if(PR_GetError() == PR_WOULD_BLOCK_ERROR)
/* blocking direction is updated by nss_update_connecting_state() */
return CURLE_AGAIN;
- else if(*certverifyresult == SSL_ERROR_BAD_CERT_DOMAIN)
+ else if(SSL_SET_OPTION(certverifyresult) == SSL_ERROR_BAD_CERT_DOMAIN)
result = CURLE_PEER_FAILED_VERIFICATION;
- else if(*certverifyresult != 0)
+ else if(SSL_SET_OPTION(certverifyresult) != 0)
result = CURLE_PEER_FAILED_VERIFICATION;
goto error;
}
- result = display_conn_info(conn, backend->handle);
+ result = display_conn_info(data, backend->handle);
if(result)
goto error;
@@ -2204,7 +2178,7 @@ static CURLcode nss_do_connect(struct connectdata *conn, int sockindex)
}
}
- result = cmp_peer_pubkey(connssl, pinnedpubkey);
+ result = cmp_peer_pubkey(connssl, SSL_PINNED_PUB_KEY());
if(result)
/* status already printed */
goto error;
@@ -2215,11 +2189,11 @@ error:
return nss_fail_connect(connssl, data, result);
}
-static CURLcode nss_connect_common(struct connectdata *conn, int sockindex,
+static CURLcode nss_connect_common(struct Curl_easy *data,
+ struct connectdata *conn, int sockindex,
bool *done)
{
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
- struct Curl_easy *data = conn->data;
const bool blocking = (done == NULL);
CURLcode result;
@@ -2230,7 +2204,7 @@ static CURLcode nss_connect_common(struct connectdata *conn, int sockindex,
}
if(connssl->connecting_state == ssl_connect_1) {
- result = nss_setup_connect(conn, sockindex);
+ result = nss_setup_connect(data, conn, sockindex);
if(result)
/* we do not expect CURLE_AGAIN from nss_setup_connect() */
return result;
@@ -2243,7 +2217,7 @@ static CURLcode nss_connect_common(struct connectdata *conn, int sockindex,
if(result)
return result;
- result = nss_do_connect(conn, sockindex);
+ result = nss_do_connect(data, conn, sockindex);
switch(result) {
case CURLE_OK:
break;
@@ -2276,30 +2250,33 @@ static CURLcode nss_connect_common(struct connectdata *conn, int sockindex,
return CURLE_OK;
}
-static CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex)
+static CURLcode nss_connect(struct Curl_easy *data, struct connectdata *conn,
+ int sockindex)
{
- return nss_connect_common(conn, sockindex, /* blocking */ NULL);
+ return nss_connect_common(data, conn, sockindex, /* blocking */ NULL);
}
-static CURLcode Curl_nss_connect_nonblocking(struct connectdata *conn,
- int sockindex, bool *done)
+static CURLcode nss_connect_nonblocking(struct Curl_easy *data,
+ struct connectdata *conn,
+ int sockindex, bool *done)
{
- return nss_connect_common(conn, sockindex, done);
+ return nss_connect_common(data, conn, sockindex, done);
}
-static ssize_t nss_send(struct connectdata *conn, /* connection data */
+static ssize_t nss_send(struct Curl_easy *data, /* transfer */
int sockindex, /* socketindex */
const void *mem, /* send this data */
size_t len, /* amount to write */
CURLcode *curlcode)
{
+ struct connectdata *conn = data->conn;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
struct ssl_backend_data *backend = connssl->backend;
ssize_t rc;
/* The SelectClientCert() hook uses this for infof() and failf() but the
handle stored in nss_setup_connect() could have already been freed. */
- backend->data = conn->data;
+ backend->data = data;
rc = PR_Send(backend->handle, mem, (int)len, 0, PR_INTERVAL_NO_WAIT);
if(rc < 0) {
@@ -2309,10 +2286,10 @@ static ssize_t nss_send(struct connectdata *conn, /* connection data */
else {
/* print the error number and error string */
const char *err_name = nss_error_to_name(err);
- infof(conn->data, "SSL write: error %d (%s)\n", err, err_name);
+ infof(data, "SSL write: error %d (%s)\n", err, err_name);
/* print a human-readable message describing the error if available */
- nss_print_error_message(conn->data, err);
+ nss_print_error_message(data, err);
*curlcode = (is_cc_error(err))
? CURLE_SSL_CERTPROBLEM
@@ -2325,19 +2302,20 @@ static ssize_t nss_send(struct connectdata *conn, /* connection data */
return rc; /* number of bytes */
}
-static ssize_t nss_recv(struct connectdata *conn, /* connection data */
+static ssize_t nss_recv(struct Curl_easy *data, /* transfer */
int sockindex, /* socketindex */
- char *buf, /* store read data here */
- size_t buffersize, /* max amount to read */
+ char *buf, /* store read data here */
+ size_t buffersize, /* max amount to read */
CURLcode *curlcode)
{
+ struct connectdata *conn = data->conn;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
struct ssl_backend_data *backend = connssl->backend;
ssize_t nread;
/* The SelectClientCert() hook uses this for infof() and failf() but the
handle stored in nss_setup_connect() could have already been freed. */
- backend->data = conn->data;
+ backend->data = data;
nread = PR_Recv(backend->handle, buf, (int)buffersize, 0,
PR_INTERVAL_NO_WAIT);
@@ -2350,10 +2328,10 @@ static ssize_t nss_recv(struct connectdata *conn, /* connection data */
else {
/* print the error number and error string */
const char *err_name = nss_error_to_name(err);
- infof(conn->data, "SSL read: errno %d (%s)\n", err, err_name);
+ infof(data, "SSL read: errno %d (%s)\n", err, err_name);
/* print a human-readable message describing the error if available */
- nss_print_error_message(conn->data, err);
+ nss_print_error_message(data, err);
*curlcode = (is_cc_error(err))
? CURLE_SSL_CERTPROBLEM
@@ -2366,9 +2344,9 @@ static ssize_t nss_recv(struct connectdata *conn, /* connection data */
return nread;
}
-static size_t Curl_nss_version(char *buffer, size_t size)
+static size_t nss_version(char *buffer, size_t size)
{
- return msnprintf(buffer, size, "NSS/%s", NSS_VERSION);
+ return msnprintf(buffer, size, "NSS/%s", NSS_GetVersion());
}
/* data might be NULL */
@@ -2379,9 +2357,9 @@ static int Curl_nss_seed(struct Curl_easy *data)
}
/* data might be NULL */
-static CURLcode Curl_nss_random(struct Curl_easy *data,
- unsigned char *entropy,
- size_t length)
+static CURLcode nss_random(struct Curl_easy *data,
+ unsigned char *entropy,
+ size_t length)
{
Curl_nss_seed(data); /* Initiate the seed if not already done */
@@ -2392,28 +2370,10 @@ static CURLcode Curl_nss_random(struct Curl_easy *data,
return CURLE_OK;
}
-static CURLcode Curl_nss_md5sum(unsigned char *tmp, /* input */
- size_t tmplen,
- unsigned char *md5sum, /* output */
- size_t md5len)
-{
- PK11Context *MD5pw = PK11_CreateDigestContext(SEC_OID_MD5);
- unsigned int MD5out;
-
- if(!MD5pw)
- return CURLE_NOT_BUILT_IN;
-
- PK11_DigestOp(MD5pw, tmp, curlx_uztoui(tmplen));
- PK11_DigestFinal(MD5pw, md5sum, &MD5out, curlx_uztoui(md5len));
- PK11_DestroyContext(MD5pw, PR_TRUE);
-
- return CURLE_OK;
-}
-
-static CURLcode Curl_nss_sha256sum(const unsigned char *tmp, /* input */
- size_t tmplen,
- unsigned char *sha256sum, /* output */
- size_t sha256len)
+static CURLcode nss_sha256sum(const unsigned char *tmp, /* input */
+ size_t tmplen,
+ unsigned char *sha256sum, /* output */
+ size_t sha256len)
{
PK11Context *SHA256pw = PK11_CreateDigestContext(SEC_OID_SHA256);
unsigned int SHA256out;
@@ -2428,7 +2388,7 @@ static CURLcode Curl_nss_sha256sum(const unsigned char *tmp, /* input */
return CURLE_OK;
}
-static bool Curl_nss_cert_status_request(void)
+static bool nss_cert_status_request(void)
{
#ifdef SSL_ENABLE_OCSP_STAPLING
return TRUE;
@@ -2437,7 +2397,7 @@ static bool Curl_nss_cert_status_request(void)
#endif
}
-static bool Curl_nss_false_start(void)
+static bool nss_false_start(void)
{
#if NSSVERNUM >= 0x030f04 /* 3.15.4 */
return TRUE;
@@ -2446,7 +2406,7 @@ static bool Curl_nss_false_start(void)
#endif
}
-static void *Curl_nss_get_internals(struct ssl_connect_data *connssl,
+static void *nss_get_internals(struct ssl_connect_data *connssl,
CURLINFO info UNUSED_PARAM)
{
struct ssl_backend_data *backend = connssl->backend;
@@ -2464,28 +2424,27 @@ const struct Curl_ssl Curl_ssl_nss = {
sizeof(struct ssl_backend_data),
- Curl_nss_init, /* init */
- Curl_nss_cleanup, /* cleanup */
- Curl_nss_version, /* version */
- Curl_nss_check_cxn, /* check_cxn */
+ nss_init, /* init */
+ nss_cleanup, /* cleanup */
+ nss_version, /* version */
+ nss_check_cxn, /* check_cxn */
/* NSS has no shutdown function provided and thus always fail */
Curl_none_shutdown, /* shutdown */
Curl_none_data_pending, /* data_pending */
- Curl_nss_random, /* random */
- Curl_nss_cert_status_request, /* cert_status_request */
- Curl_nss_connect, /* connect */
- Curl_nss_connect_nonblocking, /* connect_nonblocking */
- Curl_nss_get_internals, /* get_internals */
- Curl_nss_close, /* close_one */
+ nss_random, /* random */
+ nss_cert_status_request, /* cert_status_request */
+ nss_connect, /* connect */
+ nss_connect_nonblocking, /* connect_nonblocking */
+ nss_get_internals, /* get_internals */
+ nss_close, /* close_one */
Curl_none_close_all, /* close_all */
/* NSS has its own session ID cache */
Curl_none_session_free, /* session_free */
Curl_none_set_engine, /* set_engine */
Curl_none_set_engine_default, /* set_engine_default */
Curl_none_engines_list, /* engines_list */
- Curl_nss_false_start, /* false_start */
- Curl_nss_md5sum, /* md5sum */
- Curl_nss_sha256sum /* sha256sum */
+ nss_false_start, /* false_start */
+ nss_sha256sum /* sha256sum */
};
#endif /* USE_NSS */
diff --git a/Utilities/cmcurl/lib/vtls/nssg.h b/Utilities/cmcurl/lib/vtls/nssg.h
index 41e51b021..37b364647 100644
--- a/Utilities/cmcurl/lib/vtls/nssg.h
+++ b/Utilities/cmcurl/lib/vtls/nssg.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
diff --git a/Utilities/cmcurl/lib/vtls/openssl.c b/Utilities/cmcurl/lib/vtls/openssl.c
index 1685a4aa4..784d9f70e 100644
--- a/Utilities/cmcurl/lib/vtls/openssl.c
+++ b/Utilities/cmcurl/lib/vtls/openssl.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -34,6 +34,13 @@
/* Wincrypt must be included before anything that could include OpenSSL. */
#if defined(USE_WIN32_CRYPTO)
#include <wincrypt.h>
+/* Undefine wincrypt conflicting symbols for BoringSSL. */
+#undef X509_NAME
+#undef X509_EXTENSIONS
+#undef PKCS7_ISSUER_AND_SERIAL
+#undef PKCS7_SIGNER_INFO
+#undef OCSP_REQUEST
+#undef OCSP_RESPONSE
#endif
#include "urldata.h"
@@ -193,6 +200,10 @@
!defined(OPENSSL_IS_BORINGSSL))
#define HAVE_SSL_CTX_SET_CIPHERSUITES
#define HAVE_SSL_CTX_SET_POST_HANDSHAKE_AUTH
+/* SET_EC_CURVES available under the same preconditions: see
+ * https://www.openssl.org/docs/manmaster/man3/SSL_CTX_set1_groups.html
+ */
+#define HAVE_SSL_CTX_SET_EC_CURVES
#endif
#if defined(LIBRESSL_VERSION_NUMBER)
@@ -214,6 +225,14 @@
"ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH"
#endif
+#ifdef HAVE_OPENSSL_SRP
+/* the function exists */
+#ifdef USE_TLS_SRP
+/* the functionality is not disabled */
+#define USE_OPENSSL_SRP
+#endif
+#endif
+
struct ssl_backend_data {
/* these ones requires specific SSL-types */
SSL_CTX* ctx;
@@ -343,6 +362,18 @@ static char *ossl_strerror(unsigned long error, char *buf, size_t size)
return buf;
}
+/* Return an extra data index for the transfer data.
+ * This index can be used with SSL_get_ex_data() and SSL_set_ex_data().
+ */
+static int ossl_get_ssl_data_index(void)
+{
+ static int ssl_ex_data_data_index = -1;
+ if(ssl_ex_data_data_index < 0) {
+ ssl_ex_data_data_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL);
+ }
+ return ssl_ex_data_data_index;
+}
+
/* Return an extra data index for the connection data.
* This index can be used with SSL_get_ex_data() and SSL_set_ex_data().
*/
@@ -391,7 +422,7 @@ static bool rand_enough(void)
return (0 != RAND_status()) ? TRUE : FALSE;
}
-static CURLcode Curl_ossl_seed(struct Curl_easy *data)
+static CURLcode ossl_seed(struct Curl_easy *data)
{
/* we have the "SSL is seeded" boolean static to prevent multiple
time-consuming seedings in vain */
@@ -553,8 +584,7 @@ static bool is_pkcs11_uri(const char *string)
#endif
-static CURLcode Curl_ossl_set_engine(struct Curl_easy *data,
- const char *engine);
+static CURLcode ossl_set_engine(struct Curl_easy *data, const char *engine);
static int
SSL_CTX_use_certificate_bio(SSL_CTX *ctx, BIO *in, int type,
@@ -681,7 +711,7 @@ SSL_CTX_use_certificate_chain_bio(SSL_CTX *ctx, BIO* in,
}
static
-int cert_stuff(struct connectdata *conn,
+int cert_stuff(struct Curl_easy *data,
SSL_CTX* ctx,
char *cert_file,
BIO *cert_bio,
@@ -691,7 +721,6 @@ int cert_stuff(struct connectdata *conn,
const char *key_type,
char *key_passwd)
{
- struct Curl_easy *data = conn->data;
char error_buffer[256];
bool check_privkey = TRUE;
@@ -754,7 +783,7 @@ int cert_stuff(struct connectdata *conn,
* cert_file is a PKCS#11 URI */
if(!data->state.engine) {
if(is_pkcs11_uri(cert_file)) {
- if(Curl_ossl_set_engine(data, "pkcs11") != CURLE_OK) {
+ if(ossl_set_engine(data, "pkcs11") != CURLE_OK) {
return 0;
}
}
@@ -953,7 +982,7 @@ int cert_stuff(struct connectdata *conn,
* key_file is a PKCS#11 URI */
if(!data->state.engine) {
if(is_pkcs11_uri(key_file)) {
- if(Curl_ossl_set_engine(data, "pkcs11") != CURLE_OK) {
+ if(ossl_set_engine(data, "pkcs11") != CURLE_OK) {
return 0;
}
}
@@ -1065,9 +1094,6 @@ int cert_stuff(struct connectdata *conn,
/* returns non-zero on failure */
static int x509_name_oneline(X509_NAME *a, char *buf, size_t size)
{
-#if 0
- return X509_NAME_oneline(a, buf, size);
-#else
BIO *bio_out = BIO_new(BIO_s_mem());
BUF_MEM *biomem;
int rc;
@@ -1089,7 +1115,6 @@ static int x509_name_oneline(X509_NAME *a, char *buf, size_t size)
BIO_free(bio_out);
return !rc;
-#endif
}
/**
@@ -1098,8 +1123,23 @@ static int x509_name_oneline(X509_NAME *a, char *buf, size_t size)
* @retval 0 error initializing SSL
* @retval 1 SSL initialized successfully
*/
-static int Curl_ossl_init(void)
+static int ossl_init(void)
{
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && \
+ !defined(LIBRESSL_VERSION_NUMBER)
+ const uint64_t flags =
+#ifdef OPENSSL_INIT_ENGINE_ALL_BUILTIN
+ /* not present in BoringSSL */
+ OPENSSL_INIT_ENGINE_ALL_BUILTIN |
+#endif
+#ifdef CURL_DISABLE_OPENSSL_AUTO_LOAD_CONFIG
+ OPENSSL_INIT_NO_LOAD_CONFIG |
+#else
+ OPENSSL_INIT_LOAD_CONFIG |
+#endif
+ 0;
+ OPENSSL_init_ssl(flags, NULL);
+#else
OPENSSL_load_builtin_modules();
#ifdef USE_OPENSSL_ENGINE
@@ -1118,10 +1158,6 @@ static int Curl_ossl_init(void)
CONF_MFLAGS_IGNORE_MISSING_FILE);
#endif
-#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && \
- !defined(LIBRESSL_VERSION_NUMBER)
- /* OpenSSL 1.1.0+ takes care of initialization itself */
-#else
/* Lets get nice error messages */
SSL_load_error_strings();
@@ -1135,14 +1171,15 @@ static int Curl_ossl_init(void)
Curl_tls_keylog_open();
/* Initialize the extra data indexes */
- if(ossl_get_ssl_conn_index() < 0 || ossl_get_ssl_sockindex_index() < 0)
+ if(ossl_get_ssl_data_index() < 0 || ossl_get_ssl_conn_index() < 0 ||
+ ossl_get_ssl_sockindex_index() < 0)
return 0;
return 1;
}
/* Global cleanup */
-static void Curl_ossl_cleanup(void)
+static void ossl_cleanup(void)
{
#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && \
!defined(LIBRESSL_VERSION_NUMBER)
@@ -1186,7 +1223,7 @@ static void Curl_ossl_cleanup(void)
* 0 means the connection has been closed
* -1 means the connection status is unknown
*/
-static int Curl_ossl_check_cxn(struct connectdata *conn)
+static int ossl_check_cxn(struct connectdata *conn)
{
/* SSL_peek takes data out of the raw recv buffer without peeking so we use
recv MSG_PEEK instead. Bug #795 */
@@ -1232,8 +1269,7 @@ static int Curl_ossl_check_cxn(struct connectdata *conn)
/* Selects an OpenSSL crypto engine
*/
-static CURLcode Curl_ossl_set_engine(struct Curl_easy *data,
- const char *engine)
+static CURLcode ossl_set_engine(struct Curl_easy *data, const char *engine)
{
#ifdef USE_OPENSSL_ENGINE
ENGINE *e;
@@ -1263,7 +1299,7 @@ static CURLcode Curl_ossl_set_engine(struct Curl_easy *data,
char buf[256];
ENGINE_free(e);
- failf(data, "Failed to initialise SSL Engine '%s':\n%s",
+ failf(data, "Failed to initialise SSL Engine '%s': %s",
engine, ossl_strerror(ERR_get_error(), buf, sizeof(buf)));
return CURLE_SSL_ENGINE_INITFAILED;
}
@@ -1278,7 +1314,7 @@ static CURLcode Curl_ossl_set_engine(struct Curl_easy *data,
/* Sets engine as default for all SSL operations
*/
-static CURLcode Curl_ossl_set_engine_default(struct Curl_easy *data)
+static CURLcode ossl_set_engine_default(struct Curl_easy *data)
{
#ifdef USE_OPENSSL_ENGINE
if(data->state.engine) {
@@ -1300,7 +1336,7 @@ static CURLcode Curl_ossl_set_engine_default(struct Curl_easy *data)
/* Return list of OpenSSL crypto engine names.
*/
-static struct curl_slist *Curl_ossl_engines_list(struct Curl_easy *data)
+static struct curl_slist *ossl_engines_list(struct Curl_easy *data)
{
struct curl_slist *list = NULL;
#ifdef USE_OPENSSL_ENGINE
@@ -1320,7 +1356,7 @@ static struct curl_slist *Curl_ossl_engines_list(struct Curl_easy *data)
return list;
}
-static void ossl_close(struct ssl_connect_data *connssl)
+static void ossl_closeone(struct ssl_connect_data *connssl)
{
struct ssl_backend_data *backend = connssl->backend;
if(backend->handle) {
@@ -1339,11 +1375,13 @@ static void ossl_close(struct ssl_connect_data *connssl)
/*
* This function is called when an SSL connection is closed.
*/
-static void Curl_ossl_close(struct connectdata *conn, int sockindex)
+static void ossl_close(struct Curl_easy *data, struct connectdata *conn,
+ int sockindex)
{
- ossl_close(&conn->ssl[sockindex]);
+ (void) data;
+ ossl_closeone(&conn->ssl[sockindex]);
#ifndef CURL_DISABLE_PROXY
- ossl_close(&conn->proxy_ssl[sockindex]);
+ ossl_closeone(&conn->proxy_ssl[sockindex]);
#endif
}
@@ -1351,11 +1389,11 @@ static void Curl_ossl_close(struct connectdata *conn, int sockindex)
* This function is called to shut down the SSL layer but keep the
* socket open (CCC - Clear Command Channel)
*/
-static int Curl_ossl_shutdown(struct connectdata *conn, int sockindex)
+static int ossl_shutdown(struct Curl_easy *data,
+ struct connectdata *conn, int sockindex)
{
int retval = 0;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
- struct Curl_easy *data = conn->data;
char buf[256]; /* We will use this for the OpenSSL error buffer, so it has
to be at least 256 bytes long. */
unsigned long sslerror;
@@ -1407,7 +1445,7 @@ static int Curl_ossl_shutdown(struct connectdata *conn, int sockindex)
default:
/* openssl/ssl.h says "look at error stack/return value/errno" */
sslerror = ERR_get_error();
- failf(conn->data, OSSL_PACKAGE " SSL_read on shutdown: %s, errno %d",
+ failf(data, OSSL_PACKAGE " SSL_read on shutdown: %s, errno %d",
(sslerror ?
ossl_strerror(sslerror, buf, sizeof(buf)) :
SSL_ERROR_to_str(err)),
@@ -1452,7 +1490,7 @@ static int Curl_ossl_shutdown(struct connectdata *conn, int sockindex)
return retval;
}
-static void Curl_ossl_session_free(void *ptr)
+static void ossl_session_free(void *ptr)
{
/* free the ID */
SSL_SESSION_free(ptr);
@@ -1462,7 +1500,7 @@ static void Curl_ossl_session_free(void *ptr)
* This function is called when the 'data' struct is going away. Close
* down everything and free all resources!
*/
-static void Curl_ossl_close_all(struct Curl_easy *data)
+static void ossl_close_all(struct Curl_easy *data)
{
#ifdef USE_OPENSSL_ENGINE
if(data->state.engine) {
@@ -1556,12 +1594,12 @@ static bool subj_alt_hostcheck(struct Curl_easy *data,
in the certificate and must exactly match the IP in the URI.
*/
-static CURLcode verifyhost(struct connectdata *conn, X509 *server_cert)
+static CURLcode verifyhost(struct Curl_easy *data, struct connectdata *conn,
+ X509 *server_cert)
{
bool matched = FALSE;
int target = GEN_DNS; /* target type, GEN_DNS or GEN_IPADD */
size_t addrlen = 0;
- struct Curl_easy *data = conn->data;
STACK_OF(GENERAL_NAME) *altnames;
#ifdef ENABLE_IPV6
struct in6_addr addr;
@@ -1571,16 +1609,8 @@ static CURLcode verifyhost(struct connectdata *conn, X509 *server_cert)
CURLcode result = CURLE_OK;
bool dNSName = FALSE; /* if a dNSName field exists in the cert */
bool iPAddress = FALSE; /* if a iPAddress field exists in the cert */
-#ifndef CURL_DISABLE_PROXY
- const char * const hostname = SSL_IS_PROXY() ?
- conn->http_proxy.host.name : conn->host.name;
- const char * const dispname = SSL_IS_PROXY() ?
- conn->http_proxy.host.dispname : conn->host.dispname;
-#else
- /* disabled proxy support */
- const char * const hostname = conn->host.name;
- const char * const dispname = conn->host.dispname;
-#endif
+ const char * const hostname = SSL_HOST_NAME();
+ const char * const dispname = SSL_HOST_DISPNAME();
#ifdef ENABLE_IPV6
if(conn->bits.ipv6_ip &&
@@ -1764,19 +1794,23 @@ static CURLcode verifyhost(struct connectdata *conn, X509 *server_cert)
#if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_TLSEXT) && \
!defined(OPENSSL_NO_OCSP)
-static CURLcode verifystatus(struct connectdata *conn,
+static CURLcode verifystatus(struct Curl_easy *data,
struct ssl_connect_data *connssl)
{
int i, ocsp_status;
unsigned char *status;
const unsigned char *p;
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
OCSP_RESPONSE *rsp = NULL;
OCSP_BASICRESP *br = NULL;
X509_STORE *st = NULL;
STACK_OF(X509) *ch = NULL;
struct ssl_backend_data *backend = connssl->backend;
+ X509 *cert;
+ OCSP_CERTID *id = NULL;
+ int cert_status, crl_reason;
+ ASN1_GENERALIZEDTIME *rev, *thisupd, *nextupd;
+ int ret;
long len = SSL_get_tlsext_status_ocsp_resp(backend->handle, &status);
@@ -1845,43 +1879,63 @@ static CURLcode verifystatus(struct connectdata *conn,
goto end;
}
- for(i = 0; i < OCSP_resp_count(br); i++) {
- int cert_status, crl_reason;
- OCSP_SINGLERESP *single = NULL;
-
- ASN1_GENERALIZEDTIME *rev, *thisupd, *nextupd;
+ /* Compute the certificate's ID */
+ cert = SSL_get_peer_certificate(backend->handle);
+ if(!cert) {
+ failf(data, "Error getting peer certificate");
+ result = CURLE_SSL_INVALIDCERTSTATUS;
+ goto end;
+ }
- single = OCSP_resp_get0(br, i);
- if(!single)
- continue;
+ for(i = 0; i < sk_X509_num(ch); i++) {
+ X509 *issuer = sk_X509_value(ch, i);
+ if(X509_check_issued(issuer, cert) == X509_V_OK) {
+ id = OCSP_cert_to_id(EVP_sha1(), cert, issuer);
+ break;
+ }
+ }
+ X509_free(cert);
- cert_status = OCSP_single_get0_status(single, &crl_reason, &rev,
- &thisupd, &nextupd);
+ if(!id) {
+ failf(data, "Error computing OCSP ID");
+ result = CURLE_SSL_INVALIDCERTSTATUS;
+ goto end;
+ }
- if(!OCSP_check_validity(thisupd, nextupd, 300L, -1L)) {
- failf(data, "OCSP response has expired");
- result = CURLE_SSL_INVALIDCERTSTATUS;
- goto end;
- }
+ /* Find the single OCSP response corresponding to the certificate ID */
+ ret = OCSP_resp_find_status(br, id, &cert_status, &crl_reason, &rev,
+ &thisupd, &nextupd);
+ OCSP_CERTID_free(id);
+ if(ret != 1) {
+ failf(data, "Could not find certificate ID in OCSP response");
+ result = CURLE_SSL_INVALIDCERTSTATUS;
+ goto end;
+ }
- infof(data, "SSL certificate status: %s (%d)\n",
- OCSP_cert_status_str(cert_status), cert_status);
+ /* Validate the corresponding single OCSP response */
+ if(!OCSP_check_validity(thisupd, nextupd, 300L, -1L)) {
+ failf(data, "OCSP response has expired");
+ result = CURLE_SSL_INVALIDCERTSTATUS;
+ goto end;
+ }
- switch(cert_status) {
- case V_OCSP_CERTSTATUS_GOOD:
- break;
+ infof(data, "SSL certificate status: %s (%d)\n",
+ OCSP_cert_status_str(cert_status), cert_status);
- case V_OCSP_CERTSTATUS_REVOKED:
- result = CURLE_SSL_INVALIDCERTSTATUS;
+ switch(cert_status) {
+ case V_OCSP_CERTSTATUS_GOOD:
+ break;
- failf(data, "SSL certificate revocation reason: %s (%d)",
- OCSP_crl_reason_str(crl_reason), crl_reason);
- goto end;
+ case V_OCSP_CERTSTATUS_REVOKED:
+ result = CURLE_SSL_INVALIDCERTSTATUS;
+ failf(data, "SSL certificate revocation reason: %s (%d)",
+ OCSP_crl_reason_str(crl_reason), crl_reason);
+ goto end;
- case V_OCSP_CERTSTATUS_UNKNOWN:
- result = CURLE_SSL_INVALIDCERTSTATUS;
- goto end;
- }
+ case V_OCSP_CERTSTATUS_UNKNOWN:
+ default:
+ result = CURLE_SSL_INVALIDCERTSTATUS;
+ goto end;
}
end:
@@ -2163,15 +2217,15 @@ select_next_proto_cb(SSL *ssl,
const unsigned char *in, unsigned int inlen,
void *arg)
{
- struct connectdata *conn = (struct connectdata*) arg;
-
+ struct Curl_easy *data = (struct Curl_easy *)arg;
+ struct connectdata *conn = data->conn;
(void)ssl;
#ifdef USE_NGHTTP2
- if(conn->data->set.httpversion >= CURL_HTTP_VERSION_2 &&
+ if(data->set.httpversion >= CURL_HTTP_VERSION_2 &&
!select_next_protocol(out, outlen, in, inlen, NGHTTP2_PROTO_VERSION_ID,
NGHTTP2_PROTO_VERSION_ID_LEN)) {
- infof(conn->data, "NPN, negotiated HTTP2 (%s)\n",
+ infof(data, "NPN, negotiated HTTP2 (%s)\n",
NGHTTP2_PROTO_VERSION_ID);
conn->negnpn = CURL_HTTP_VERSION_2;
return SSL_TLSEXT_ERR_OK;
@@ -2180,12 +2234,12 @@ select_next_proto_cb(SSL *ssl,
if(!select_next_protocol(out, outlen, in, inlen, ALPN_HTTP_1_1,
ALPN_HTTP_1_1_LENGTH)) {
- infof(conn->data, "NPN, negotiated HTTP1.1\n");
+ infof(data, "NPN, negotiated HTTP1.1\n");
conn->negnpn = CURL_HTTP_VERSION_1_1;
return SSL_TLSEXT_ERR_OK;
}
- infof(conn->data, "NPN, no overlap, use HTTP1.1\n");
+ infof(data, "NPN, no overlap, use HTTP1.1\n");
*out = (unsigned char *)ALPN_HTTP_1_1;
*outlen = ALPN_HTTP_1_1_LENGTH;
conn->negnpn = CURL_HTTP_VERSION_1_1;
@@ -2316,16 +2370,14 @@ typedef long ctx_option_t;
#if (OPENSSL_VERSION_NUMBER < 0x10100000L) /* 1.1.0 */
static CURLcode
set_ssl_version_min_max_legacy(ctx_option_t *ctx_options,
- struct connectdata *conn, int sockindex)
+ struct Curl_easy *data,
+ struct connectdata *conn, int sockindex)
{
-#if (OPENSSL_VERSION_NUMBER < 0x1000100FL) || !defined(TLS1_3_VERSION)
- /* convoluted #if condition just to avoid compiler warnings on unused
- variable */
- struct Curl_easy *data = conn->data;
-#endif
long ssl_version = SSL_CONN_CONFIG(version);
long ssl_version_max = SSL_CONN_CONFIG(version_max);
+ (void) data; /* In case it's unused. */
+
switch(ssl_version) {
case CURL_SSLVERSION_TLSv1_3:
#ifdef TLS1_3_VERSION
@@ -2400,17 +2452,18 @@ static int ossl_new_session_cb(SSL *ssl, SSL_SESSION *ssl_sessionid)
struct Curl_easy *data;
int sockindex;
curl_socket_t *sockindex_ptr;
+ int data_idx = ossl_get_ssl_data_index();
int connectdata_idx = ossl_get_ssl_conn_index();
int sockindex_idx = ossl_get_ssl_sockindex_index();
- if(connectdata_idx < 0 || sockindex_idx < 0)
+ if(data_idx < 0 || connectdata_idx < 0 || sockindex_idx < 0)
return 0;
conn = (struct connectdata*) SSL_get_ex_data(ssl, connectdata_idx);
if(!conn)
return 0;
- data = conn->data;
+ data = (struct Curl_easy *) SSL_get_ex_data(ssl, data_idx);
/* The sockindex has been stored as a pointer to an array element */
sockindex_ptr = (curl_socket_t*) SSL_get_ex_data(ssl, sockindex_idx);
@@ -2420,19 +2473,19 @@ static int ossl_new_session_cb(SSL *ssl, SSL_SESSION *ssl_sessionid)
bool incache;
void *old_ssl_sessionid = NULL;
- Curl_ssl_sessionid_lock(conn);
- incache = !(Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL,
+ Curl_ssl_sessionid_lock(data);
+ incache = !(Curl_ssl_getsessionid(data, conn, &old_ssl_sessionid, NULL,
sockindex));
if(incache) {
if(old_ssl_sessionid != ssl_sessionid) {
infof(data, "old SSL session ID is stale, removing\n");
- Curl_ssl_delsessionid(conn, old_ssl_sessionid);
+ Curl_ssl_delsessionid(data, old_ssl_sessionid);
incache = FALSE;
}
}
if(!incache) {
- if(!Curl_ssl_addsessionid(conn, ssl_sessionid,
+ if(!Curl_ssl_addsessionid(data, conn, ssl_sessionid,
0 /* unknown size */, sockindex)) {
/* the session has been put into the session cache */
res = 1;
@@ -2440,17 +2493,17 @@ static int ossl_new_session_cb(SSL *ssl, SSL_SESSION *ssl_sessionid)
else
failf(data, "failed to store ssl session");
}
- Curl_ssl_sessionid_unlock(conn);
+ Curl_ssl_sessionid_unlock(data);
}
return res;
}
-static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
+static CURLcode ossl_connect_step1(struct Curl_easy *data,
+ struct connectdata *conn, int sockindex)
{
CURLcode result = CURLE_OK;
char *ciphers;
- struct Curl_easy *data = conn->data;
SSL_METHOD_QUAL SSL_METHOD *req_method = NULL;
X509_LOOKUP *lookup = NULL;
curl_socket_t sockfd = conn->sock[sockindex];
@@ -2459,12 +2512,7 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
bool sni;
-#ifndef CURL_DISABLE_PROXY
- const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
- conn->host.name;
-#else
- const char * const hostname = conn->host.name;
-#endif
+ const char * const hostname = SSL_HOST_NAME();
#ifdef ENABLE_IPV6
struct in6_addr addr;
@@ -2472,18 +2520,12 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
struct in_addr addr;
#endif
#endif
-#ifndef CURL_DISABLE_PROXY
- long * const certverifyresult = SSL_IS_PROXY() ?
- &data->set.proxy_ssl.certverifyresult : &data->set.ssl.certverifyresult;
-#else
- long * const certverifyresult = &data->set.ssl.certverifyresult;
-#endif
const long int ssl_version = SSL_CONN_CONFIG(version);
-#ifdef USE_TLS_SRP
+#ifdef USE_OPENSSL_SRP
const enum CURL_TLSAUTH ssl_authtype = SSL_SET_OPTION(authtype);
#endif
- char * const ssl_cert = SSL_SET_OPTION(cert);
- const struct curl_blob *ssl_cert_blob = SSL_SET_OPTION(cert_blob);
+ char * const ssl_cert = SSL_SET_OPTION(primary.clientcert);
+ const struct curl_blob *ssl_cert_blob = SSL_SET_OPTION(primary.cert_blob);
const char * const ssl_cert_type = SSL_SET_OPTION(cert_type);
const char * const ssl_cafile = SSL_CONN_CONFIG(CAfile);
const char * const ssl_capath = SSL_CONN_CONFIG(CApath);
@@ -2496,11 +2538,11 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
DEBUGASSERT(ssl_connect_1 == connssl->connecting_state);
/* Make funny stuff to get random input */
- result = Curl_ossl_seed(data);
+ result = ossl_seed(data);
if(result)
return result;
- *certverifyresult = !X509_V_OK;
+ SSL_SET_OPTION_LVALUE(certverifyresult) = !X509_V_OK;
/* check to see if we've been told to use an explicit SSL/TLS version */
@@ -2524,7 +2566,7 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
failf(data, OSSL_PACKAGE " was built without SSLv2 support");
return CURLE_NOT_BUILT_IN;
#else
-#ifdef USE_TLS_SRP
+#ifdef USE_OPENSSL_SRP
if(ssl_authtype == CURL_TLSAUTH_SRP)
return CURLE_SSL_CONNECT_ERROR;
#endif
@@ -2537,7 +2579,7 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
failf(data, OSSL_PACKAGE " was built without SSLv3 support");
return CURLE_NOT_BUILT_IN;
#else
-#ifdef USE_TLS_SRP
+#ifdef USE_OPENSSL_SRP
if(ssl_authtype == CURL_TLSAUTH_SRP)
return CURLE_SSL_CONNECT_ERROR;
#endif
@@ -2682,7 +2724,8 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) /* 1.1.0 */
result = set_ssl_version_min_max(backend->ctx, conn);
#else
- result = set_ssl_version_min_max_legacy(&ctx_options, conn, sockindex);
+ result = set_ssl_version_min_max_legacy(&ctx_options, data, conn,
+ sockindex);
#endif
if(result != CURLE_OK)
return result;
@@ -2697,7 +2740,7 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
#ifdef HAS_NPN
if(conn->bits.tls_enable_npn)
- SSL_CTX_set_next_proto_select_cb(backend->ctx, select_next_proto_cb, conn);
+ SSL_CTX_set_next_proto_select_cb(backend->ctx, select_next_proto_cb, data);
#endif
#ifdef HAS_ALPN
@@ -2735,33 +2778,33 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
if(ssl_cert || ssl_cert_blob || ssl_cert_type) {
BIO *ssl_cert_bio = NULL;
BIO *ssl_key_bio = NULL;
- int result_cert_stuff;
if(ssl_cert_blob) {
/* the typecast of blob->len is fine since it is guaranteed to never be
larger than CURL_MAX_INPUT_LENGTH */
ssl_cert_bio = BIO_new_mem_buf(ssl_cert_blob->data,
(int)ssl_cert_blob->len);
if(!ssl_cert_bio)
- return CURLE_SSL_CERTPROBLEM;
+ result = CURLE_OUT_OF_MEMORY;
}
- if(SSL_SET_OPTION(key_blob)) {
+ if(!result && SSL_SET_OPTION(key_blob)) {
ssl_key_bio = BIO_new_mem_buf(SSL_SET_OPTION(key_blob)->data,
(int)SSL_SET_OPTION(key_blob)->len);
if(!ssl_key_bio)
- return CURLE_SSL_CERTPROBLEM;
+ result = CURLE_OUT_OF_MEMORY;
}
- result_cert_stuff = cert_stuff(conn, backend->ctx,
+ if(!result &&
+ !cert_stuff(data, backend->ctx,
ssl_cert, ssl_cert_bio, ssl_cert_type,
SSL_SET_OPTION(key), ssl_key_bio,
- SSL_SET_OPTION(key_type), SSL_SET_OPTION(key_passwd));
+ SSL_SET_OPTION(key_type), SSL_SET_OPTION(key_passwd)))
+ result = CURLE_SSL_CERTPROBLEM;
if(ssl_cert_bio)
BIO_free(ssl_cert_bio);
if(ssl_key_bio)
BIO_free(ssl_key_bio);
- if(!result_cert_stuff) {
+ if(result)
/* failf() is already done in cert_stuff() */
- return CURLE_SSL_CERTPROBLEM;
- }
+ return result;
}
ciphers = SSL_CONN_CONFIG(cipher_list);
@@ -2793,7 +2836,19 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
SSL_CTX_set_post_handshake_auth(backend->ctx, 1);
#endif
-#ifdef USE_TLS_SRP
+#ifdef HAVE_SSL_CTX_SET_EC_CURVES
+ {
+ char *curves = SSL_CONN_CONFIG(curves);
+ if(curves) {
+ if(!SSL_CTX_set1_curves_list(backend->ctx, curves)) {
+ failf(data, "failed setting curves list: '%s'", curves);
+ return CURLE_SSL_CIPHER;
+ }
+ }
+ }
+#endif
+
+#ifdef USE_OPENSSL_SRP
if(ssl_authtype == CURL_TLSAUTH_SRP) {
char * const ssl_username = SSL_SET_OPTION(username);
@@ -2910,7 +2965,7 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
/* "If GetLastError returns CRYPT_E_NOT_FOUND, the certificate is
good for all uses. If it returns zero, the certificate has no
valid uses." */
- if(GetLastError() != CRYPT_E_NOT_FOUND)
+ if((HRESULT)GetLastError() != CRYPT_E_NOT_FOUND)
continue;
}
else {
@@ -2970,7 +3025,7 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
{
if(ssl_cafile) {
if(!SSL_CTX_load_verify_file(backend->ctx, ssl_cafile)) {
- if(verifypeer) {
+ if(verifypeer && !imported_native_ca) {
/* Fail if we insist on successfully verifying the server. */
failf(data, "error setting certificate file: %s", ssl_cafile);
return CURLE_SSL_CACERT_BADFILE;
@@ -2978,11 +3033,11 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
/* Continue with a warning if no certificate verif is required. */
infof(data, "error setting certificate file, continuing anyway\n");
}
- infof(data, " CAfile: %s\n", ssl_cafile);
+ infof(data, " CAfile: %s\n", ssl_cafile);
}
if(ssl_capath) {
if(!SSL_CTX_load_verify_dir(backend->ctx, ssl_capath)) {
- if(verifypeer) {
+ if(verifypeer && !imported_native_ca) {
/* Fail if we insist on successfully verifying the server. */
failf(data, "error setting certificate path: %s", ssl_capath);
return CURLE_SSL_CACERT_BADFILE;
@@ -2990,7 +3045,7 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
/* Continue with a warning if no certificate verif is required. */
infof(data, "error setting certificate path, continuing anyway\n");
}
- infof(data, " CApath: %s\n", ssl_capath);
+ infof(data, " CApath: %s\n", ssl_capath);
}
}
#else
@@ -3000,8 +3055,8 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
if(!SSL_CTX_load_verify_locations(backend->ctx, ssl_cafile, ssl_capath)) {
if(verifypeer && !imported_native_ca) {
/* Fail if we insist on successfully verifying the server. */
- failf(data, "error setting certificate verify locations:\n"
- " CAfile: %s\n CApath: %s",
+ failf(data, "error setting certificate verify locations:"
+ " CAfile: %s CApath: %s",
ssl_cafile ? ssl_cafile : "none",
ssl_capath ? ssl_capath : "none");
return CURLE_SSL_CACERT_BADFILE;
@@ -3015,11 +3070,8 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
/* Everything is fine. */
infof(data, "successfully set certificate verify locations:\n");
}
- infof(data,
- " CAfile: %s\n"
- " CApath: %s\n",
- ssl_cafile ? ssl_cafile : "none",
- ssl_capath ? ssl_capath : "none");
+ infof(data, " CAfile: %s\n", ssl_cafile ? ssl_cafile : "none");
+ infof(data, " CApath: %s\n", ssl_capath ? ssl_capath : "none");
}
#endif
@@ -3137,30 +3189,43 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
#ifdef ENABLE_IPV6
(0 == Curl_inet_pton(AF_INET6, hostname, &addr)) &&
#endif
- sni &&
- !SSL_set_tlsext_host_name(backend->handle, hostname))
- infof(data, "WARNING: failed to configure server name indication (SNI) "
- "TLS extension\n");
+ sni) {
+ size_t nlen = strlen(hostname);
+ if((long)nlen >= data->set.buffer_size)
+ /* this is seriously messed up */
+ return CURLE_SSL_CONNECT_ERROR;
+
+ /* RFC 6066 section 3 says the SNI field is case insensitive, but browsers
+ send the data lowercase and subsequently there are now numerous servers
+ out there that don't work unless the name is lowercased */
+ Curl_strntolower(data->state.buffer, hostname, nlen);
+ data->state.buffer[nlen] = 0;
+ if(!SSL_set_tlsext_host_name(backend->handle, data->state.buffer))
+ infof(data, "WARNING: failed to configure server name indication (SNI) "
+ "TLS extension\n");
+ }
#endif
/* Check if there's a cached ID we can/should use here! */
if(SSL_SET_OPTION(primary.sessionid)) {
void *ssl_sessionid = NULL;
+ int data_idx = ossl_get_ssl_data_index();
int connectdata_idx = ossl_get_ssl_conn_index();
int sockindex_idx = ossl_get_ssl_sockindex_index();
- if(connectdata_idx >= 0 && sockindex_idx >= 0) {
+ if(data_idx >= 0 && connectdata_idx >= 0 && sockindex_idx >= 0) {
/* Store the data needed for the "new session" callback.
* The sockindex is stored as a pointer to an array element. */
+ SSL_set_ex_data(backend->handle, data_idx, data);
SSL_set_ex_data(backend->handle, connectdata_idx, conn);
SSL_set_ex_data(backend->handle, sockindex_idx, conn->sock + sockindex);
}
- Curl_ssl_sessionid_lock(conn);
- if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL, sockindex)) {
+ Curl_ssl_sessionid_lock(data);
+ if(!Curl_ssl_getsessionid(data, conn, &ssl_sessionid, NULL, sockindex)) {
/* we got a session id, use it! */
if(!SSL_set_session(backend->handle, ssl_sessionid)) {
- Curl_ssl_sessionid_unlock(conn);
+ Curl_ssl_sessionid_unlock(data);
failf(data, "SSL: SSL_set_session failed: %s",
ossl_strerror(ERR_get_error(), error_buffer,
sizeof(error_buffer)));
@@ -3169,7 +3234,7 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
/* Informational message */
infof(data, "SSL re-using session ID\n");
}
- Curl_ssl_sessionid_unlock(conn);
+ Curl_ssl_sessionid_unlock(data);
}
#ifndef CURL_DISABLE_PROXY
@@ -3196,17 +3261,11 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
return CURLE_OK;
}
-static CURLcode ossl_connect_step2(struct connectdata *conn, int sockindex)
+static CURLcode ossl_connect_step2(struct Curl_easy *data,
+ struct connectdata *conn, int sockindex)
{
- struct Curl_easy *data = conn->data;
int err;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
-#ifndef CURL_DISABLE_PROXY
- long * const certverifyresult = SSL_IS_PROXY() ?
- &data->set.proxy_ssl.certverifyresult : &data->set.ssl.certverifyresult;
-#else
- long * const certverifyresult = &data->set.ssl.certverifyresult;
-#endif
struct ssl_backend_data *backend = connssl->backend;
DEBUGASSERT(ssl_connect_2 == connssl->connecting_state
|| ssl_connect_2_reading == connssl->connecting_state
@@ -3265,12 +3324,13 @@ static CURLcode ossl_connect_step2(struct connectdata *conn, int sockindex)
reason = ERR_GET_REASON(errdetail);
if((lib == ERR_LIB_SSL) &&
- (reason == SSL_R_CERTIFICATE_VERIFY_FAILED)) {
+ ((reason == SSL_R_CERTIFICATE_VERIFY_FAILED) ||
+ (reason == SSL_R_SSLV3_ALERT_CERTIFICATE_EXPIRED))) {
result = CURLE_PEER_FAILED_VERIFICATION;
lerr = SSL_get_verify_result(backend->handle);
if(lerr != X509_V_OK) {
- *certverifyresult = lerr;
+ SSL_SET_OPTION_LVALUE(certverifyresult) = lerr;
msnprintf(error_buffer, sizeof(error_buffer),
"SSL certificate problem: %s",
X509_verify_cert_error_string(lerr));
@@ -3292,12 +3352,10 @@ static CURLcode ossl_connect_step2(struct connectdata *conn, int sockindex)
* the SO_ERROR is also lost.
*/
if(CURLE_SSL_CONNECT_ERROR == result && errdetail == 0) {
+ const char * const hostname = SSL_HOST_NAME();
#ifndef CURL_DISABLE_PROXY
- const char * const hostname = SSL_IS_PROXY() ?
- conn->http_proxy.host.name : conn->host.name;
const long int port = SSL_IS_PROXY() ? conn->port : conn->remote_port;
#else
- const char * const hostname = conn->host.name;
const long int port = conn->remote_port;
#endif
char extramsg[80]="";
@@ -3351,7 +3409,7 @@ static CURLcode ossl_connect_step2(struct connectdata *conn, int sockindex)
else
infof(data, "ALPN, server did not agree to a protocol\n");
- Curl_multiuse_state(conn, conn->negnpn == CURL_HTTP_VERSION_2 ?
+ Curl_multiuse_state(data, conn->negnpn == CURL_HTTP_VERSION_2 ?
BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);
}
#endif
@@ -3457,14 +3515,12 @@ typedef size_t numcert_t;
typedef int numcert_t;
#endif
-static CURLcode get_cert_chain(struct connectdata *conn,
+static CURLcode get_cert_chain(struct Curl_easy *data,
struct ssl_connect_data *connssl)
-
{
CURLcode result;
STACK_OF(X509) *sk;
int i;
- struct Curl_easy *data = conn->data;
numcert_t numcerts;
BIO *mem;
struct ssl_backend_data *backend = connssl->backend;
@@ -3739,31 +3795,25 @@ static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data, X509* cert,
* We check certificates to authenticate the server; otherwise we risk
* man-in-the-middle attack.
*/
-static CURLcode servercert(struct connectdata *conn,
+static CURLcode servercert(struct Curl_easy *data,
+ struct connectdata *conn,
struct ssl_connect_data *connssl,
bool strict)
{
CURLcode result = CURLE_OK;
int rc;
long lerr;
- struct Curl_easy *data = conn->data;
X509 *issuer;
BIO *fp = NULL;
char error_buffer[256]="";
char buffer[2048];
const char *ptr;
-#ifndef CURL_DISABLE_PROXY
- long * const certverifyresult = SSL_IS_PROXY() ?
- &data->set.proxy_ssl.certverifyresult : &data->set.ssl.certverifyresult;
-#else
- long * const certverifyresult = &data->set.ssl.certverifyresult;
-#endif
BIO *mem = BIO_new(BIO_s_mem());
struct ssl_backend_data *backend = connssl->backend;
if(data->set.ssl.certinfo)
/* we've been asked to gather certificate info! */
- (void)get_cert_chain(conn, connssl);
+ (void)get_cert_chain(data, connssl);
backend->server_cert = SSL_get_peer_certificate(backend->handle);
if(!backend->server_cert) {
@@ -3799,7 +3849,7 @@ static CURLcode servercert(struct connectdata *conn,
BIO_free(mem);
if(SSL_CONN_CONFIG(verifyhost)) {
- result = verifyhost(conn, backend->server_cert);
+ result = verifyhost(data, conn, backend->server_cert);
if(result) {
X509_free(backend->server_cert);
backend->server_cert = NULL;
@@ -3878,9 +3928,9 @@ static CURLcode servercert(struct connectdata *conn,
X509_free(issuer);
}
- lerr = *certverifyresult = SSL_get_verify_result(backend->handle);
-
- if(*certverifyresult != X509_V_OK) {
+ lerr = SSL_get_verify_result(backend->handle);
+ SSL_SET_OPTION_LVALUE(certverifyresult) = lerr;
+ if(lerr != X509_V_OK) {
if(SSL_CONN_CONFIG(verifypeer)) {
/* We probably never reach this, because SSL_connect() will fail
and we return earlier if verifypeer is set? */
@@ -3901,7 +3951,7 @@ static CURLcode servercert(struct connectdata *conn,
#if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_TLSEXT) && \
!defined(OPENSSL_NO_OCSP)
if(SSL_CONN_CONFIG(verifystatus)) {
- result = verifystatus(conn, connssl);
+ result = verifystatus(data, connssl);
if(result) {
X509_free(backend->server_cert);
backend->server_cert = NULL;
@@ -3929,7 +3979,8 @@ static CURLcode servercert(struct connectdata *conn,
return result;
}
-static CURLcode ossl_connect_step3(struct connectdata *conn, int sockindex)
+static CURLcode ossl_connect_step3(struct Curl_easy *data,
+ struct connectdata *conn, int sockindex)
{
CURLcode result = CURLE_OK;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
@@ -3943,8 +3994,8 @@ static CURLcode ossl_connect_step3(struct connectdata *conn, int sockindex)
* operations.
*/
- result = servercert(conn, connssl, (SSL_CONN_CONFIG(verifypeer) ||
- SSL_CONN_CONFIG(verifyhost)));
+ result = servercert(data, conn, connssl, (SSL_CONN_CONFIG(verifypeer) ||
+ SSL_CONN_CONFIG(verifyhost)));
if(!result)
connssl->connecting_state = ssl_connect_done;
@@ -3955,13 +4006,13 @@ static CURLcode ossl_connect_step3(struct connectdata *conn, int sockindex)
static Curl_recv ossl_recv;
static Curl_send ossl_send;
-static CURLcode ossl_connect_common(struct connectdata *conn,
+static CURLcode ossl_connect_common(struct Curl_easy *data,
+ struct connectdata *conn,
int sockindex,
bool nonblocking,
bool *done)
{
CURLcode result;
- struct Curl_easy *data = conn->data;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
curl_socket_t sockfd = conn->sock[sockindex];
int what;
@@ -3982,7 +4033,7 @@ static CURLcode ossl_connect_common(struct connectdata *conn,
return CURLE_OPERATION_TIMEDOUT;
}
- result = ossl_connect_step1(conn, sockindex);
+ result = ossl_connect_step1(data, conn, sockindex);
if(result)
return result;
}
@@ -4034,7 +4085,7 @@ static CURLcode ossl_connect_common(struct connectdata *conn,
* before step2 has completed while ensuring that a client using select()
* or epoll() will always have a valid fdset to wait on.
*/
- result = ossl_connect_step2(conn, sockindex);
+ result = ossl_connect_step2(data, conn, sockindex);
if(result || (nonblocking &&
(ssl_connect_2 == connssl->connecting_state ||
ssl_connect_2_reading == connssl->connecting_state ||
@@ -4044,7 +4095,7 @@ static CURLcode ossl_connect_common(struct connectdata *conn,
} /* repeat step2 until all transactions are done. */
if(ssl_connect_3 == connssl->connecting_state) {
- result = ossl_connect_step3(conn, sockindex);
+ result = ossl_connect_step3(data, conn, sockindex);
if(result)
return result;
}
@@ -4064,19 +4115,21 @@ static CURLcode ossl_connect_common(struct connectdata *conn,
return CURLE_OK;
}
-static CURLcode Curl_ossl_connect_nonblocking(struct connectdata *conn,
- int sockindex,
- bool *done)
+static CURLcode ossl_connect_nonblocking(struct Curl_easy *data,
+ struct connectdata *conn,
+ int sockindex,
+ bool *done)
{
- return ossl_connect_common(conn, sockindex, TRUE, done);
+ return ossl_connect_common(data, conn, sockindex, TRUE, done);
}
-static CURLcode Curl_ossl_connect(struct connectdata *conn, int sockindex)
+static CURLcode ossl_connect(struct Curl_easy *data, struct connectdata *conn,
+ int sockindex)
{
CURLcode result;
bool done = FALSE;
- result = ossl_connect_common(conn, sockindex, FALSE, &done);
+ result = ossl_connect_common(data, conn, sockindex, FALSE, &done);
if(result)
return result;
@@ -4085,8 +4138,8 @@ static CURLcode Curl_ossl_connect(struct connectdata *conn, int sockindex)
return CURLE_OK;
}
-static bool Curl_ossl_data_pending(const struct connectdata *conn,
- int connindex)
+static bool ossl_data_pending(const struct connectdata *conn,
+ int connindex)
{
const struct ssl_connect_data *connssl = &conn->ssl[connindex];
if(connssl->backend->handle && SSL_pending(connssl->backend->handle))
@@ -4101,9 +4154,9 @@ static bool Curl_ossl_data_pending(const struct connectdata *conn,
return FALSE;
}
-static size_t Curl_ossl_version(char *buffer, size_t size);
+static size_t ossl_version(char *buffer, size_t size);
-static ssize_t ossl_send(struct connectdata *conn,
+static ssize_t ossl_send(struct Curl_easy *data,
int sockindex,
const void *mem,
size_t len,
@@ -4116,6 +4169,7 @@ static ssize_t ossl_send(struct connectdata *conn,
unsigned long sslerror;
int memlen;
int rc;
+ struct connectdata *conn = data->conn;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
struct ssl_backend_data *backend = connssl->backend;
@@ -4147,7 +4201,7 @@ static ssize_t ossl_send(struct connectdata *conn,
strncpy(error_buffer, SSL_ERROR_to_str(err), sizeof(error_buffer));
error_buffer[sizeof(error_buffer) - 1] = '\0';
}
- failf(conn->data, OSSL_PACKAGE " SSL_write: %s, errno %d",
+ failf(data, OSSL_PACKAGE " SSL_write: %s, errno %d",
error_buffer, sockerr);
*curlcode = CURLE_SEND_ERROR;
return -1;
@@ -4164,18 +4218,17 @@ static ssize_t ossl_send(struct connectdata *conn,
#endif
) {
char ver[120];
- Curl_ossl_version(ver, 120);
- failf(conn->data, "Error: %s does not support double SSL tunneling.",
- ver);
+ ossl_version(ver, 120);
+ failf(data, "Error: %s does not support double SSL tunneling.", ver);
}
else
- failf(conn->data, "SSL_write() error: %s",
+ failf(data, "SSL_write() error: %s",
ossl_strerror(sslerror, error_buffer, sizeof(error_buffer)));
*curlcode = CURLE_SEND_ERROR;
return -1;
}
/* a true error */
- failf(conn->data, OSSL_PACKAGE " SSL_write: %s, errno %d",
+ failf(data, OSSL_PACKAGE " SSL_write: %s, errno %d",
SSL_ERROR_to_str(err), SOCKERRNO);
*curlcode = CURLE_SEND_ERROR;
return -1;
@@ -4184,7 +4237,7 @@ static ssize_t ossl_send(struct connectdata *conn,
return (ssize_t)rc; /* number of bytes */
}
-static ssize_t ossl_recv(struct connectdata *conn, /* connection data */
+static ssize_t ossl_recv(struct Curl_easy *data, /* transfer */
int num, /* socketindex */
char *buf, /* store read data here */
size_t buffersize, /* max amount to read */
@@ -4194,6 +4247,7 @@ static ssize_t ossl_recv(struct connectdata *conn, /* connection data */
unsigned long sslerror;
ssize_t nread;
int buffsize;
+ struct connectdata *conn = data->conn;
struct ssl_connect_data *connssl = &conn->ssl[num];
struct ssl_backend_data *backend = connssl->backend;
@@ -4237,7 +4291,7 @@ static ssize_t ossl_recv(struct connectdata *conn, /* connection data */
strncpy(error_buffer, SSL_ERROR_to_str(err), sizeof(error_buffer));
error_buffer[sizeof(error_buffer) - 1] = '\0';
}
- failf(conn->data, OSSL_PACKAGE " SSL_read: %s, errno %d",
+ failf(data, OSSL_PACKAGE " SSL_read: %s, errno %d",
error_buffer, sockerr);
*curlcode = CURLE_RECV_ERROR;
return -1;
@@ -4259,7 +4313,7 @@ static ssize_t ossl_recv(struct connectdata *conn, /* connection data */
msnprintf(error_buffer, sizeof(error_buffer),
"Connection closed abruptly");
}
- failf(conn->data, OSSL_PACKAGE " SSL_read: %s, errno %d"
+ failf(data, OSSL_PACKAGE " SSL_read: %s, errno %d"
" (Fatal because this is a curl debug build)",
error_buffer, sockerr);
*curlcode = CURLE_RECV_ERROR;
@@ -4271,7 +4325,7 @@ static ssize_t ossl_recv(struct connectdata *conn, /* connection data */
return nread;
}
-static size_t Curl_ossl_version(char *buffer, size_t size)
+static size_t ossl_version(char *buffer, size_t size)
{
#ifdef LIBRESSL_VERSION_NUMBER
#if LIBRESSL_VERSION_NUMBER < 0x2070100fL
@@ -4342,12 +4396,12 @@ static size_t Curl_ossl_version(char *buffer, size_t size)
}
/* can be called with data == NULL */
-static CURLcode Curl_ossl_random(struct Curl_easy *data,
- unsigned char *entropy, size_t length)
+static CURLcode ossl_random(struct Curl_easy *data,
+ unsigned char *entropy, size_t length)
{
int rc;
if(data) {
- if(Curl_ossl_seed(data)) /* Initiate the seed if not already done */
+ if(ossl_seed(data)) /* Initiate the seed if not already done */
return CURLE_FAILED_INIT; /* couldn't seed for some reason */
}
else {
@@ -4359,35 +4413,20 @@ static CURLcode Curl_ossl_random(struct Curl_easy *data,
return (rc == 1 ? CURLE_OK : CURLE_FAILED_INIT);
}
-static CURLcode Curl_ossl_md5sum(unsigned char *tmp, /* input */
- size_t tmplen,
- unsigned char *md5sum /* output */,
- size_t unused)
-{
- EVP_MD_CTX *mdctx;
- unsigned int len = 0;
- (void) unused;
-
- mdctx = EVP_MD_CTX_create();
- EVP_DigestInit_ex(mdctx, EVP_md5(), NULL);
- EVP_DigestUpdate(mdctx, tmp, tmplen);
- EVP_DigestFinal_ex(mdctx, md5sum, &len);
- EVP_MD_CTX_destroy(mdctx);
- return CURLE_OK;
-}
-
#if (OPENSSL_VERSION_NUMBER >= 0x0090800fL) && !defined(OPENSSL_NO_SHA256)
-static CURLcode Curl_ossl_sha256sum(const unsigned char *tmp, /* input */
- size_t tmplen,
- unsigned char *sha256sum /* output */,
- size_t unused)
+static CURLcode ossl_sha256sum(const unsigned char *tmp, /* input */
+ size_t tmplen,
+ unsigned char *sha256sum /* output */,
+ size_t unused)
{
EVP_MD_CTX *mdctx;
unsigned int len = 0;
(void) unused;
mdctx = EVP_MD_CTX_create();
- EVP_DigestInit_ex(mdctx, EVP_sha256(), NULL);
+ if(!mdctx)
+ return CURLE_OUT_OF_MEMORY;
+ EVP_DigestInit(mdctx, EVP_sha256());
EVP_DigestUpdate(mdctx, tmp, tmplen);
EVP_DigestFinal_ex(mdctx, sha256sum, &len);
EVP_MD_CTX_destroy(mdctx);
@@ -4395,7 +4434,7 @@ static CURLcode Curl_ossl_sha256sum(const unsigned char *tmp, /* input */
}
#endif
-static bool Curl_ossl_cert_status_request(void)
+static bool ossl_cert_status_request(void)
{
#if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_TLSEXT) && \
!defined(OPENSSL_NO_OCSP)
@@ -4405,8 +4444,8 @@ static bool Curl_ossl_cert_status_request(void)
#endif
}
-static void *Curl_ossl_get_internals(struct ssl_connect_data *connssl,
- CURLINFO info)
+static void *ossl_get_internals(struct ssl_connect_data *connssl,
+ CURLINFO info)
{
/* Legacy: CURLINFO_TLS_SESSION must return an SSL_CTX pointer. */
struct ssl_backend_data *backend = connssl->backend;
@@ -4428,29 +4467,28 @@ const struct Curl_ssl Curl_ssl_openssl = {
sizeof(struct ssl_backend_data),
- Curl_ossl_init, /* init */
- Curl_ossl_cleanup, /* cleanup */
- Curl_ossl_version, /* version */
- Curl_ossl_check_cxn, /* check_cxn */
- Curl_ossl_shutdown, /* shutdown */
- Curl_ossl_data_pending, /* data_pending */
- Curl_ossl_random, /* random */
- Curl_ossl_cert_status_request, /* cert_status_request */
- Curl_ossl_connect, /* connect */
- Curl_ossl_connect_nonblocking, /* connect_nonblocking */
- Curl_ossl_get_internals, /* get_internals */
- Curl_ossl_close, /* close_one */
- Curl_ossl_close_all, /* close_all */
- Curl_ossl_session_free, /* session_free */
- Curl_ossl_set_engine, /* set_engine */
- Curl_ossl_set_engine_default, /* set_engine_default */
- Curl_ossl_engines_list, /* engines_list */
- Curl_none_false_start, /* false_start */
- Curl_ossl_md5sum, /* md5sum */
+ ossl_init, /* init */
+ ossl_cleanup, /* cleanup */
+ ossl_version, /* version */
+ ossl_check_cxn, /* check_cxn */
+ ossl_shutdown, /* shutdown */
+ ossl_data_pending, /* data_pending */
+ ossl_random, /* random */
+ ossl_cert_status_request, /* cert_status_request */
+ ossl_connect, /* connect */
+ ossl_connect_nonblocking, /* connect_nonblocking */
+ ossl_get_internals, /* get_internals */
+ ossl_close, /* close_one */
+ ossl_close_all, /* close_all */
+ ossl_session_free, /* session_free */
+ ossl_set_engine, /* set_engine */
+ ossl_set_engine_default, /* set_engine_default */
+ ossl_engines_list, /* engines_list */
+ Curl_none_false_start, /* false_start */
#if (OPENSSL_VERSION_NUMBER >= 0x0090800fL) && !defined(OPENSSL_NO_SHA256)
- Curl_ossl_sha256sum /* sha256sum */
+ ossl_sha256sum /* sha256sum */
#else
- NULL /* sha256sum */
+ NULL /* sha256sum */
#endif
};
diff --git a/Utilities/cmcurl/lib/vtls/openssl.h b/Utilities/cmcurl/lib/vtls/openssl.h
index 114dc4bae..2f6e1b2db 100644
--- a/Utilities/cmcurl/lib/vtls/openssl.h
+++ b/Utilities/cmcurl/lib/vtls/openssl.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
diff --git a/Utilities/cmcurl/lib/vtls/schannel.c b/Utilities/cmcurl/lib/vtls/schannel.c
index 1c1432d75..0668f98f2 100644
--- a/Utilities/cmcurl/lib/vtls/schannel.c
+++ b/Utilities/cmcurl/lib/vtls/schannel.c
@@ -5,13 +5,13 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
+ * Copyright (C) 2012 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 2012 - 2016, Marc Hoersken, <info@marc-hoersken.de>
* Copyright (C) 2012, Mark Salisbury, <mark.salisbury@hp.com>
- * Copyright (C) 2012 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -142,7 +142,8 @@
static Curl_recv schannel_recv;
static Curl_send schannel_send;
-static CURLcode pkp_pin_peer_pubkey(struct connectdata *conn, int sockindex,
+static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data,
+ struct connectdata *conn, int sockindex,
const char *pinnedpubkey);
static void InitSecBuffer(SecBuffer *buffer, unsigned long BufType,
@@ -162,9 +163,9 @@ static void InitSecBufferDesc(SecBufferDesc *desc, SecBuffer *BufArr,
}
static CURLcode
-set_ssl_version_min_max(SCHANNEL_CRED *schannel_cred, struct connectdata *conn)
+set_ssl_version_min_max(SCHANNEL_CRED *schannel_cred, struct Curl_easy *data,
+ struct connectdata *conn)
{
- struct Curl_easy *data = conn->data;
long ssl_version = SSL_CONN_CONFIG(version);
long ssl_version_max = SSL_CONN_CONFIG(version_max);
long i = ssl_version;
@@ -346,6 +347,8 @@ set_ssl_ciphers(SCHANNEL_CRED *schannel_cred, char *ciphers)
}
#ifdef HAS_CLIENT_CERT_PATH
+
+/* Function allocates memory for store_path only if CURLE_OK is returned */
static CURLcode
get_cert_location(TCHAR *path, DWORD *store_name, TCHAR **store_path,
TCHAR **thumbprint)
@@ -388,25 +391,25 @@ get_cert_location(TCHAR *path, DWORD *store_name, TCHAR **store_path,
if(sep == NULL)
return CURLE_SSL_CERTPROBLEM;
+ *thumbprint = sep + 1;
+ if(_tcslen(*thumbprint) != CERT_THUMBPRINT_STR_LEN)
+ return CURLE_SSL_CERTPROBLEM;
+
*sep = TEXT('\0');
*store_path = _tcsdup(store_path_start);
*sep = TEXT('\\');
if(*store_path == NULL)
return CURLE_OUT_OF_MEMORY;
- *thumbprint = sep + 1;
- if(_tcslen(*thumbprint) != CERT_THUMBPRINT_STR_LEN)
- return CURLE_SSL_CERTPROBLEM;
-
return CURLE_OK;
}
#endif
static CURLcode
-schannel_connect_step1(struct connectdata *conn, int sockindex)
+schannel_connect_step1(struct Curl_easy *data, struct connectdata *conn,
+ int sockindex)
{
ssize_t written = -1;
- struct Curl_easy *data = conn->data;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
SecBuffer outbuf;
SecBufferDesc outbuf_desc;
@@ -418,7 +421,7 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
SCHANNEL_CRED schannel_cred;
PCCERT_CONTEXT client_certs[1] = { NULL };
SECURITY_STATUS sspi_status = SEC_E_OK;
- struct curl_schannel_cred *old_cred = NULL;
+ struct Curl_schannel_cred *old_cred = NULL;
struct in_addr addr;
#ifdef ENABLE_IPV6
struct in6_addr addr6;
@@ -491,8 +494,9 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
/* check for an existing re-usable credential handle */
if(SSL_SET_OPTION(primary.sessionid)) {
- Curl_ssl_sessionid_lock(conn);
- if(!Curl_ssl_getsessionid(conn, (void **)&old_cred, NULL, sockindex)) {
+ Curl_ssl_sessionid_lock(data);
+ if(!Curl_ssl_getsessionid(data, conn,
+ (void **)&old_cred, NULL, sockindex)) {
BACKEND->cred = old_cred;
DEBUGF(infof(data, "schannel: re-using existing credential handle\n"));
@@ -502,7 +506,7 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
"schannel: incremented credential handle refcount = %d\n",
BACKEND->cred->refcount));
}
- Curl_ssl_sessionid_unlock(conn);
+ Curl_ssl_sessionid_unlock(data);
}
if(!BACKEND->cred) {
@@ -561,7 +565,7 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
case CURL_SSLVERSION_TLSv1_2:
case CURL_SSLVERSION_TLSv1_3:
{
- result = set_ssl_version_min_max(&schannel_cred, conn);
+ result = set_ssl_version_min_max(&schannel_cred, data, conn);
if(result != CURLE_OK)
return result;
break;
@@ -588,7 +592,7 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
#ifdef HAS_CLIENT_CERT_PATH
/* client certificate */
- if(data->set.ssl.cert || data->set.ssl.cert_blob) {
+ if(data->set.ssl.primary.clientcert || data->set.ssl.primary.cert_blob) {
DWORD cert_store_name = 0;
TCHAR *cert_store_path = NULL;
TCHAR *cert_thumbprint_str = NULL;
@@ -598,27 +602,28 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
FILE *fInCert = NULL;
void *certdata = NULL;
size_t certsize = 0;
- bool blob = data->set.ssl.cert_blob != NULL;
+ bool blob = data->set.ssl.primary.cert_blob != NULL;
TCHAR *cert_path = NULL;
if(blob) {
- certdata = data->set.ssl.cert_blob->data;
- certsize = data->set.ssl.cert_blob->len;
+ certdata = data->set.ssl.primary.cert_blob->data;
+ certsize = data->set.ssl.primary.cert_blob->len;
}
else {
- cert_path = curlx_convert_UTF8_to_tchar(data->set.ssl.cert);
+ cert_path = curlx_convert_UTF8_to_tchar(
+ data->set.ssl.primary.clientcert);
if(!cert_path)
return CURLE_OUT_OF_MEMORY;
result = get_cert_location(cert_path, &cert_store_name,
&cert_store_path, &cert_thumbprint_str);
- if(result && (data->set.ssl.cert[0]!='\0'))
- fInCert = fopen(data->set.ssl.cert, "rb");
+ if(result && (data->set.ssl.primary.clientcert[0]!='\0'))
+ fInCert = fopen(data->set.ssl.primary.clientcert, "rb");
if(result && !fInCert) {
failf(data, "schannel: Failed to get certificate location"
" or file for %s",
- data->set.ssl.cert);
+ data->set.ssl.primary.clientcert);
curlx_unicodefree(cert_path);
return result;
}
@@ -628,7 +633,7 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
(!strcasecompare(data->set.ssl.cert_type, "P12"))) {
failf(data, "schannel: certificate format compatibility error "
" for %s",
- blob ? "(memory blob)" : data->set.ssl.cert);
+ blob ? "(memory blob)" : data->set.ssl.primary.clientcert);
curlx_unicodefree(cert_path);
return CURLE_SSL_CERTPROBLEM;
}
@@ -643,7 +648,7 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
size_t pwd_len = 0;
int str_w_len = 0;
const char *cert_showfilename_error = blob ?
- "(memory blob)" : data->set.ssl.cert;
+ "(memory blob)" : data->set.ssl.primary.clientcert;
curlx_unicodefree(cert_path);
if(fInCert) {
long cert_tell = 0;
@@ -664,7 +669,7 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
fclose(fInCert);
if(!continue_reading) {
failf(data, "schannel: Failed to read cert file %s",
- data->set.ssl.cert);
+ data->set.ssl.primary.clientcert);
free(certdata);
return CURLE_SSL_CERTPROBLEM;
}
@@ -771,15 +776,15 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
CertCloseStore(cert_store, 0);
}
#else
- if(data->set.ssl.cert) {
+ if(data->set.ssl.primary.clientcert || data->set.ssl.primary.cert_blob) {
failf(data, "schannel: client cert support not built in");
return CURLE_NOT_BUILT_IN;
}
#endif
/* allocate memory for the re-usable credential handle */
- BACKEND->cred = (struct curl_schannel_cred *)
- calloc(1, sizeof(struct curl_schannel_cred));
+ BACKEND->cred = (struct Curl_schannel_cred *)
+ calloc(1, sizeof(struct Curl_schannel_cred));
if(!BACKEND->cred) {
failf(data, "schannel: unable to allocate memory");
@@ -893,8 +898,8 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
ISC_REQ_STREAM;
/* allocate memory for the security context handle */
- BACKEND->ctxt = (struct curl_schannel_ctxt *)
- calloc(1, sizeof(struct curl_schannel_ctxt));
+ BACKEND->ctxt = (struct Curl_schannel_ctxt *)
+ calloc(1, sizeof(struct Curl_schannel_ctxt));
if(!BACKEND->ctxt) {
failf(data, "schannel: unable to allocate memory");
return CURLE_OUT_OF_MEMORY;
@@ -953,7 +958,7 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
"sending %lu bytes...\n", outbuf.cbBuffer));
/* send initial handshake data which is now stored in output buffer */
- result = Curl_write_plain(conn, conn->sock[sockindex], outbuf.pvBuffer,
+ result = Curl_write_plain(data, conn->sock[sockindex], outbuf.pvBuffer,
outbuf.cbBuffer, &written);
s_pSecFn->FreeContextBuffer(outbuf.pvBuffer);
if((result != CURLE_OK) || (outbuf.cbBuffer != (size_t) written)) {
@@ -977,11 +982,11 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
}
static CURLcode
-schannel_connect_step2(struct connectdata *conn, int sockindex)
+schannel_connect_step2(struct Curl_easy *data, struct connectdata *conn,
+ int sockindex)
{
int i;
ssize_t nread = -1, written = -1;
- struct Curl_easy *data = conn->data;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
unsigned char *reallocated_buffer;
SecBuffer outbuf[3];
@@ -1150,7 +1155,7 @@ schannel_connect_step2(struct connectdata *conn, int sockindex)
"sending %lu bytes...\n", outbuf[i].cbBuffer));
/* send handshake token to server */
- result = Curl_write_plain(conn, conn->sock[sockindex],
+ result = Curl_write_plain(data, conn->sock[sockindex],
outbuf[i].pvBuffer, outbuf[i].cbBuffer,
&written);
if((result != CURLE_OK) ||
@@ -1178,6 +1183,10 @@ schannel_connect_step2(struct connectdata *conn, int sockindex)
failf(data, "schannel: SNI or certificate check failed: %s",
Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer)));
return CURLE_PEER_FAILED_VERIFICATION;
+ case SEC_E_UNTRUSTED_ROOT:
+ failf(data, "schannel: %s",
+ Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer)));
+ return CURLE_PEER_FAILED_VERIFICATION;
/*
case SEC_E_INVALID_HANDLE:
case SEC_E_INVALID_TOKEN:
@@ -1245,7 +1254,7 @@ schannel_connect_step2(struct connectdata *conn, int sockindex)
data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] :
data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG];
if(pubkey_ptr) {
- result = pkp_pin_peer_pubkey(conn, sockindex, pubkey_ptr);
+ result = pkp_pin_peer_pubkey(data, conn, sockindex, pubkey_ptr);
if(result) {
failf(data, "SSL: public key does not match pinned public key!");
return result;
@@ -1254,7 +1263,7 @@ schannel_connect_step2(struct connectdata *conn, int sockindex)
#ifdef HAS_MANUAL_VERIFY_API
if(conn->ssl_config.verifypeer && BACKEND->use_manual_cred_validation) {
- return Curl_verify_certificate(conn, sockindex);
+ return Curl_verify_certificate(data, conn, sockindex);
}
#endif
@@ -1298,7 +1307,7 @@ cert_counter_callback(const CERT_CONTEXT *ccert_context, void *certs_count)
struct Adder_args
{
- struct connectdata *conn;
+ struct Curl_easy *data;
CURLcode result;
int idx;
int certs_count;
@@ -1313,17 +1322,18 @@ add_cert_to_certinfo(const CERT_CONTEXT *ccert_context, void *raw_arg)
const char *beg = (const char *) ccert_context->pbCertEncoded;
const char *end = beg + ccert_context->cbCertEncoded;
int insert_index = (args->certs_count - 1) - args->idx;
- args->result = Curl_extract_certinfo(args->conn, insert_index, beg, end);
+ args->result = Curl_extract_certinfo(args->data, insert_index,
+ beg, end);
args->idx++;
}
return args->result == CURLE_OK;
}
static CURLcode
-schannel_connect_step3(struct connectdata *conn, int sockindex)
+schannel_connect_step3(struct Curl_easy *data, struct connectdata *conn,
+ int sockindex)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
SECURITY_STATUS sspi_status = SEC_E_OK;
CERT_CONTEXT *ccert_context = NULL;
@@ -1393,7 +1403,7 @@ schannel_connect_step3(struct connectdata *conn, int sockindex)
}
else
infof(data, "ALPN, server did not agree to a protocol\n");
- Curl_multiuse_state(conn, conn->negnpn == CURL_HTTP_VERSION_2 ?
+ Curl_multiuse_state(data, conn->negnpn == CURL_HTTP_VERSION_2 ?
BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);
}
#endif
@@ -1401,26 +1411,26 @@ schannel_connect_step3(struct connectdata *conn, int sockindex)
/* save the current session data for possible re-use */
if(SSL_SET_OPTION(primary.sessionid)) {
bool incache;
- struct curl_schannel_cred *old_cred = NULL;
+ struct Curl_schannel_cred *old_cred = NULL;
- Curl_ssl_sessionid_lock(conn);
- incache = !(Curl_ssl_getsessionid(conn, (void **)&old_cred, NULL,
+ Curl_ssl_sessionid_lock(data);
+ incache = !(Curl_ssl_getsessionid(data, conn, (void **)&old_cred, NULL,
sockindex));
if(incache) {
if(old_cred != BACKEND->cred) {
DEBUGF(infof(data,
"schannel: old credential handle is stale, removing\n"));
/* we're not taking old_cred ownership here, no refcount++ is needed */
- Curl_ssl_delsessionid(conn, (void *)old_cred);
+ Curl_ssl_delsessionid(data, (void *)old_cred);
incache = FALSE;
}
}
if(!incache) {
- result = Curl_ssl_addsessionid(conn, (void *)BACKEND->cred,
- sizeof(struct curl_schannel_cred),
+ result = Curl_ssl_addsessionid(data, conn, (void *)BACKEND->cred,
+ sizeof(struct Curl_schannel_cred),
sockindex);
if(result) {
- Curl_ssl_sessionid_unlock(conn);
+ Curl_ssl_sessionid_unlock(data);
failf(data, "schannel: failed to store credential handle");
return result;
}
@@ -1431,7 +1441,7 @@ schannel_connect_step3(struct connectdata *conn, int sockindex)
"schannel: stored credential handle in session cache\n"));
}
}
- Curl_ssl_sessionid_unlock(conn);
+ Curl_ssl_sessionid_unlock(data);
}
if(data->set.ssl.certinfo) {
@@ -1451,7 +1461,7 @@ schannel_connect_step3(struct connectdata *conn, int sockindex)
result = Curl_ssl_init_certinfo(data, certs_count);
if(!result) {
struct Adder_args args;
- args.conn = conn;
+ args.data = data;
args.idx = 0;
args.certs_count = certs_count;
traverse_cert_store(ccert_context, add_cert_to_certinfo, &args);
@@ -1468,11 +1478,10 @@ schannel_connect_step3(struct connectdata *conn, int sockindex)
}
static CURLcode
-schannel_connect_common(struct connectdata *conn, int sockindex,
- bool nonblocking, bool *done)
+schannel_connect_common(struct Curl_easy *data, struct connectdata *conn,
+ int sockindex, bool nonblocking, bool *done)
{
CURLcode result;
- struct Curl_easy *data = conn->data;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
curl_socket_t sockfd = conn->sock[sockindex];
timediff_t timeout_ms;
@@ -1494,7 +1503,7 @@ schannel_connect_common(struct connectdata *conn, int sockindex,
return CURLE_OPERATION_TIMEDOUT;
}
- result = schannel_connect_step1(conn, sockindex);
+ result = schannel_connect_step1(data, conn, sockindex);
if(result)
return result;
}
@@ -1549,7 +1558,7 @@ schannel_connect_common(struct connectdata *conn, int sockindex,
* ensuring that a client using select() or epoll() will always
* have a valid fdset to wait on.
*/
- result = schannel_connect_step2(conn, sockindex);
+ result = schannel_connect_step2(data, conn, sockindex);
if(result || (nonblocking &&
(ssl_connect_2 == connssl->connecting_state ||
ssl_connect_2_reading == connssl->connecting_state ||
@@ -1559,7 +1568,7 @@ schannel_connect_common(struct connectdata *conn, int sockindex,
} /* repeat step2 until all transactions are done. */
if(ssl_connect_3 == connssl->connecting_state) {
- result = schannel_connect_step3(conn, sockindex);
+ result = schannel_connect_step3(data, conn, sockindex);
if(result)
return result;
}
@@ -1590,12 +1599,13 @@ schannel_connect_common(struct connectdata *conn, int sockindex,
}
static ssize_t
-schannel_send(struct connectdata *conn, int sockindex,
+schannel_send(struct Curl_easy *data, int sockindex,
const void *buf, size_t len, CURLcode *err)
{
ssize_t written = -1;
size_t data_len = 0;
- unsigned char *data = NULL;
+ unsigned char *ptr = NULL;
+ struct connectdata *conn = data->conn;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
SecBuffer outbuf[4];
SecBufferDesc outbuf_desc;
@@ -1622,19 +1632,19 @@ schannel_send(struct connectdata *conn, int sockindex,
/* calculate the complete message length and allocate a buffer for it */
data_len = BACKEND->stream_sizes.cbHeader + len +
BACKEND->stream_sizes.cbTrailer;
- data = (unsigned char *) malloc(data_len);
- if(data == NULL) {
+ ptr = (unsigned char *) malloc(data_len);
+ if(!ptr) {
*err = CURLE_OUT_OF_MEMORY;
return -1;
}
/* setup output buffers (header, data, trailer, empty) */
InitSecBuffer(&outbuf[0], SECBUFFER_STREAM_HEADER,
- data, BACKEND->stream_sizes.cbHeader);
+ ptr, BACKEND->stream_sizes.cbHeader);
InitSecBuffer(&outbuf[1], SECBUFFER_DATA,
- data + BACKEND->stream_sizes.cbHeader, curlx_uztoul(len));
+ ptr + BACKEND->stream_sizes.cbHeader, curlx_uztoul(len));
InitSecBuffer(&outbuf[2], SECBUFFER_STREAM_TRAILER,
- data + BACKEND->stream_sizes.cbHeader + len,
+ ptr + BACKEND->stream_sizes.cbHeader + len,
BACKEND->stream_sizes.cbTrailer);
InitSecBuffer(&outbuf[3], SECBUFFER_EMPTY, NULL, 0);
InitSecBufferDesc(&outbuf_desc, outbuf, 4);
@@ -1673,10 +1683,10 @@ schannel_send(struct connectdata *conn, int sockindex,
while(len > (size_t)written) {
ssize_t this_write = 0;
int what;
- timediff_t timeout_ms = Curl_timeleft(conn->data, NULL, FALSE);
+ timediff_t timeout_ms = Curl_timeleft(data, NULL, FALSE);
if(timeout_ms < 0) {
/* we already got the timeout */
- failf(conn->data, "schannel: timed out sending data "
+ failf(data, "schannel: timed out sending data "
"(bytes sent: %zd)", written);
*err = CURLE_OPERATION_TIMEDOUT;
written = -1;
@@ -1687,13 +1697,13 @@ schannel_send(struct connectdata *conn, int sockindex,
what = SOCKET_WRITABLE(conn->sock[sockindex], timeout_ms);
if(what < 0) {
/* fatal error */
- failf(conn->data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
+ failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
*err = CURLE_SEND_ERROR;
written = -1;
break;
}
else if(0 == what) {
- failf(conn->data, "schannel: timed out sending data "
+ failf(data, "schannel: timed out sending data "
"(bytes sent: %zd)", written);
*err = CURLE_OPERATION_TIMEDOUT;
written = -1;
@@ -1701,7 +1711,7 @@ schannel_send(struct connectdata *conn, int sockindex,
}
/* socket is writable */
- result = Curl_write_plain(conn, conn->sock[sockindex], data + written,
+ result = Curl_write_plain(data, conn->sock[sockindex], ptr + written,
len - written, &this_write);
if(result == CURLE_AGAIN)
continue;
@@ -1721,7 +1731,7 @@ schannel_send(struct connectdata *conn, int sockindex,
*err = CURLE_SEND_ERROR;
}
- Curl_safefree(data);
+ Curl_safefree(ptr);
if(len == (size_t)written)
/* Encrypted message including header, data and trailer entirely sent.
@@ -1732,12 +1742,12 @@ schannel_send(struct connectdata *conn, int sockindex,
}
static ssize_t
-schannel_recv(struct connectdata *conn, int sockindex,
+schannel_recv(struct Curl_easy *data, int sockindex,
char *buf, size_t len, CURLcode *err)
{
size_t size = 0;
ssize_t nread = -1;
- struct Curl_easy *data = conn->data;
+ struct connectdata *conn = data->conn;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
unsigned char *reallocated_buffer;
size_t reallocated_length;
@@ -1776,14 +1786,12 @@ schannel_recv(struct connectdata *conn, int sockindex,
infof(data, "schannel: server indicated shutdown in a prior call\n");
goto cleanup;
}
- else if(!len) {
- /* It's debatable what to return when !len. Regardless we can't return
- immediately because there may be data to decrypt (in the case we want to
- decrypt all encrypted cached data) so handle !len later in cleanup.
- */
- ; /* do nothing */
- }
- else if(!BACKEND->recv_connection_closed) {
+
+ /* It's debatable what to return when !len. Regardless we can't return
+ immediately because there may be data to decrypt (in the case we want to
+ decrypt all encrypted cached data) so handle !len later in cleanup.
+ */
+ else if(len && !BACKEND->recv_connection_closed) {
/* increase enc buffer in order to fit the requested amount of data */
size = BACKEND->encdata_length - BACKEND->encdata_offset;
if(size < CURL_SCHANNEL_BUFFER_FREE_SIZE ||
@@ -1950,7 +1958,7 @@ schannel_recv(struct connectdata *conn, int sockindex,
infof(data, "schannel: renegotiating SSL/TLS connection\n");
connssl->state = ssl_connection_negotiating;
connssl->connecting_state = ssl_connect_2_writing;
- *err = schannel_connect_common(conn, sockindex, FALSE, &done);
+ *err = schannel_connect_common(data, conn, sockindex, FALSE, &done);
if(*err) {
infof(data, "schannel: renegotiation failed\n");
goto cleanup;
@@ -2057,18 +2065,20 @@ schannel_recv(struct connectdata *conn, int sockindex,
return *err ? -1 : 0;
}
-static CURLcode Curl_schannel_connect_nonblocking(struct connectdata *conn,
- int sockindex, bool *done)
+static CURLcode schannel_connect_nonblocking(struct Curl_easy *data,
+ struct connectdata *conn,
+ int sockindex, bool *done)
{
- return schannel_connect_common(conn, sockindex, TRUE, done);
+ return schannel_connect_common(data, conn, sockindex, TRUE, done);
}
-static CURLcode Curl_schannel_connect(struct connectdata *conn, int sockindex)
+static CURLcode schannel_connect(struct Curl_easy *data,
+ struct connectdata *conn, int sockindex)
{
CURLcode result;
bool done = FALSE;
- result = schannel_connect_common(conn, sockindex, FALSE, &done);
+ result = schannel_connect_common(data, conn, sockindex, FALSE, &done);
if(result)
return result;
@@ -2077,8 +2087,8 @@ static CURLcode Curl_schannel_connect(struct connectdata *conn, int sockindex)
return CURLE_OK;
}
-static bool Curl_schannel_data_pending(const struct connectdata *conn,
- int sockindex)
+static bool schannel_data_pending(const struct connectdata *conn,
+ int sockindex)
{
const struct ssl_connect_data *connssl = &conn->ssl[sockindex];
@@ -2089,17 +2099,18 @@ static bool Curl_schannel_data_pending(const struct connectdata *conn,
return FALSE;
}
-static void Curl_schannel_close(struct connectdata *conn, int sockindex)
+static void schannel_close(struct Curl_easy *data, struct connectdata *conn,
+ int sockindex)
{
if(conn->ssl[sockindex].use)
/* if the SSL/TLS channel hasn't been shut down yet, do that now. */
- Curl_ssl_shutdown(conn, sockindex);
+ Curl_ssl_shutdown(data, conn, sockindex);
}
-static void Curl_schannel_session_free(void *ptr)
+static void schannel_session_free(void *ptr)
{
/* this is expected to be called under sessionid lock */
- struct curl_schannel_cred *cred = ptr;
+ struct Curl_schannel_cred *cred = ptr;
cred->refcount--;
if(cred->refcount == 0) {
@@ -2108,12 +2119,12 @@ static void Curl_schannel_session_free(void *ptr)
}
}
-static int Curl_schannel_shutdown(struct connectdata *conn, int sockindex)
+static int schannel_shutdown(struct Curl_easy *data, struct connectdata *conn,
+ int sockindex)
{
/* See https://msdn.microsoft.com/en-us/library/windows/desktop/aa380138.aspx
* Shutting Down an Schannel Connection
*/
- struct Curl_easy *data = conn->data;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
#ifndef CURL_DISABLE_PROXY
char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
@@ -2176,7 +2187,7 @@ static int Curl_schannel_shutdown(struct connectdata *conn, int sockindex)
if((sspi_status == SEC_E_OK) || (sspi_status == SEC_I_CONTEXT_EXPIRED)) {
/* send close message which is in output buffer */
ssize_t written;
- result = Curl_write_plain(conn, conn->sock[sockindex], outbuf.pvBuffer,
+ result = Curl_write_plain(data, conn->sock[sockindex], outbuf.pvBuffer,
outbuf.cbBuffer, &written);
s_pSecFn->FreeContextBuffer(outbuf.pvBuffer);
@@ -2196,14 +2207,9 @@ static int Curl_schannel_shutdown(struct connectdata *conn, int sockindex)
/* free SSPI Schannel API credential handle */
if(BACKEND->cred) {
- /*
- * When this function is called from Curl_schannel_close() the connection
- * might not have an associated transfer so the check for conn->data is
- * necessary.
- */
- Curl_ssl_sessionid_lock(conn);
- Curl_schannel_session_free(BACKEND->cred);
- Curl_ssl_sessionid_unlock(conn);
+ Curl_ssl_sessionid_lock(data);
+ schannel_session_free(BACKEND->cred);
+ Curl_ssl_sessionid_unlock(data);
BACKEND->cred = NULL;
}
@@ -2225,25 +2231,25 @@ static int Curl_schannel_shutdown(struct connectdata *conn, int sockindex)
return CURLE_OK;
}
-static int Curl_schannel_init(void)
+static int schannel_init(void)
{
return (Curl_sspi_global_init() == CURLE_OK ? 1 : 0);
}
-static void Curl_schannel_cleanup(void)
+static void schannel_cleanup(void)
{
Curl_sspi_global_cleanup();
}
-static size_t Curl_schannel_version(char *buffer, size_t size)
+static size_t schannel_version(char *buffer, size_t size)
{
size = msnprintf(buffer, size, "Schannel");
return size;
}
-static CURLcode Curl_schannel_random(struct Curl_easy *data UNUSED_PARAM,
- unsigned char *entropy, size_t length)
+static CURLcode schannel_random(struct Curl_easy *data UNUSED_PARAM,
+ unsigned char *entropy, size_t length)
{
HCRYPTPROV hCryptProv = 0;
@@ -2262,10 +2268,10 @@ static CURLcode Curl_schannel_random(struct Curl_easy *data UNUSED_PARAM,
return CURLE_OK;
}
-static CURLcode pkp_pin_peer_pubkey(struct connectdata *conn, int sockindex,
+static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data,
+ struct connectdata *conn, int sockindex,
const char *pinnedpubkey)
{
- struct Curl_easy *data = conn->data;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
CERT_CONTEXT *pCertContextServer = NULL;
@@ -2327,12 +2333,12 @@ static CURLcode pkp_pin_peer_pubkey(struct connectdata *conn, int sockindex,
return result;
}
-static void Curl_schannel_checksum(const unsigned char *input,
- size_t inputlen,
- unsigned char *checksum,
- size_t checksumlen,
- DWORD provType,
- const unsigned int algId)
+static void schannel_checksum(const unsigned char *input,
+ size_t inputlen,
+ unsigned char *checksum,
+ size_t checksumlen,
+ DWORD provType,
+ const unsigned int algId)
{
HCRYPTPROV hProv = 0;
HCRYPTHASH hHash = 0;
@@ -2377,28 +2383,18 @@ static void Curl_schannel_checksum(const unsigned char *input,
CryptReleaseContext(hProv, 0);
}
-static CURLcode Curl_schannel_md5sum(unsigned char *input,
- size_t inputlen,
- unsigned char *md5sum,
- size_t md5len)
-{
- Curl_schannel_checksum(input, inputlen, md5sum, md5len,
- PROV_RSA_FULL, CALG_MD5);
- return CURLE_OK;
-}
-
-static CURLcode Curl_schannel_sha256sum(const unsigned char *input,
- size_t inputlen,
- unsigned char *sha256sum,
- size_t sha256len)
+static CURLcode schannel_sha256sum(const unsigned char *input,
+ size_t inputlen,
+ unsigned char *sha256sum,
+ size_t sha256len)
{
- Curl_schannel_checksum(input, inputlen, sha256sum, sha256len,
- PROV_RSA_AES, CALG_SHA_256);
+ schannel_checksum(input, inputlen, sha256sum, sha256len,
+ PROV_RSA_AES, CALG_SHA_256);
return CURLE_OK;
}
-static void *Curl_schannel_get_internals(struct ssl_connect_data *connssl,
- CURLINFO info UNUSED_PARAM)
+static void *schannel_get_internals(struct ssl_connect_data *connssl,
+ CURLINFO info UNUSED_PARAM)
{
(void)info;
return &BACKEND->ctxt->ctxt_handle;
@@ -2412,26 +2408,25 @@ const struct Curl_ssl Curl_ssl_schannel = {
sizeof(struct ssl_backend_data),
- Curl_schannel_init, /* init */
- Curl_schannel_cleanup, /* cleanup */
- Curl_schannel_version, /* version */
+ schannel_init, /* init */
+ schannel_cleanup, /* cleanup */
+ schannel_version, /* version */
Curl_none_check_cxn, /* check_cxn */
- Curl_schannel_shutdown, /* shutdown */
- Curl_schannel_data_pending, /* data_pending */
- Curl_schannel_random, /* random */
+ schannel_shutdown, /* shutdown */
+ schannel_data_pending, /* data_pending */
+ schannel_random, /* random */
Curl_none_cert_status_request, /* cert_status_request */
- Curl_schannel_connect, /* connect */
- Curl_schannel_connect_nonblocking, /* connect_nonblocking */
- Curl_schannel_get_internals, /* get_internals */
- Curl_schannel_close, /* close_one */
+ schannel_connect, /* connect */
+ schannel_connect_nonblocking, /* connect_nonblocking */
+ schannel_get_internals, /* get_internals */
+ schannel_close, /* close_one */
Curl_none_close_all, /* close_all */
- Curl_schannel_session_free, /* session_free */
+ schannel_session_free, /* session_free */
Curl_none_set_engine, /* set_engine */
Curl_none_set_engine_default, /* set_engine_default */
Curl_none_engines_list, /* engines_list */
Curl_none_false_start, /* false_start */
- Curl_schannel_md5sum, /* md5sum */
- Curl_schannel_sha256sum /* sha256sum */
+ schannel_sha256sum /* sha256sum */
};
#endif /* USE_SCHANNEL */
diff --git a/Utilities/cmcurl/lib/vtls/schannel.h b/Utilities/cmcurl/lib/vtls/schannel.h
index ee8d7d47a..2952caa1a 100644
--- a/Utilities/cmcurl/lib/vtls/schannel.h
+++ b/Utilities/cmcurl/lib/vtls/schannel.h
@@ -8,11 +8,11 @@
* \___|\___/|_| \_\_____|
*
* Copyright (C) 2012, Marc Hoersken, <info@marc-hoersken.de>, et al.
- * Copyright (C) 2012 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2012 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -53,7 +53,8 @@
extern const struct Curl_ssl Curl_ssl_schannel;
-CURLcode Curl_verify_certificate(struct connectdata *conn, int sockindex);
+CURLcode Curl_verify_certificate(struct Curl_easy *data,
+ struct connectdata *conn, int sockindex);
/* structs to expose only in schannel.c and schannel_verify.c */
#ifdef EXPOSE_SCHANNEL_INTERNAL_STRUCTS
@@ -70,20 +71,20 @@ CURLcode Curl_verify_certificate(struct connectdata *conn, int sockindex);
#endif
#endif
-struct curl_schannel_cred {
+struct Curl_schannel_cred {
CredHandle cred_handle;
TimeStamp time_stamp;
int refcount;
};
-struct curl_schannel_ctxt {
+struct Curl_schannel_ctxt {
CtxtHandle ctxt_handle;
TimeStamp time_stamp;
};
struct ssl_backend_data {
- struct curl_schannel_cred *cred;
- struct curl_schannel_ctxt *ctxt;
+ struct Curl_schannel_cred *cred;
+ struct Curl_schannel_ctxt *ctxt;
SecPkgContext_StreamSizes stream_sizes;
size_t encdata_length, decdata_length;
size_t encdata_offset, decdata_offset;
diff --git a/Utilities/cmcurl/lib/vtls/schannel_verify.c b/Utilities/cmcurl/lib/vtls/schannel_verify.c
index ab7be3950..2ef39cc0f 100644
--- a/Utilities/cmcurl/lib/vtls/schannel_verify.c
+++ b/Utilities/cmcurl/lib/vtls/schannel_verify.c
@@ -7,11 +7,11 @@
*
* Copyright (C) 2012 - 2016, Marc Hoersken, <info@marc-hoersken.de>
* Copyright (C) 2012, Mark Salisbury, <mark.salisbury@hp.com>
- * Copyright (C) 2012 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2012 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -79,10 +79,9 @@ static int is_cr_or_lf(char c)
static CURLcode add_certs_to_store(HCERTSTORE trust_store,
const char *ca_file,
- struct connectdata *conn)
+ struct Curl_easy *data)
{
CURLcode result;
- struct Curl_easy *data = conn->data;
HANDLE ca_file_handle = INVALID_HANDLE_VALUE;
LARGE_INTEGER file_size;
char *ca_file_buffer = NULL;
@@ -477,7 +476,7 @@ static CURLcode verify_host(struct Curl_easy *data,
* (or some equivalent) encoding
*/
cert_hostname = curlx_convert_tchar_to_UTF8(
- &cert_hostname_buff[cert_hostname_buff_index]);
+ &cert_hostname_buff[cert_hostname_buff_index]);
if(!cert_hostname) {
result = CURLE_OUT_OF_MEMORY;
}
@@ -500,8 +499,8 @@ static CURLcode verify_host(struct Curl_easy *data,
"against certificate name (%s)\n",
conn_hostname, cert_hostname);
- cert_hostname_len = _tcslen(
- &cert_hostname_buff[cert_hostname_buff_index]);
+ cert_hostname_len =
+ _tcslen(&cert_hostname_buff[cert_hostname_buff_index]);
/* Move on to next cert name */
cert_hostname_buff_index += cert_hostname_len + 1;
@@ -522,15 +521,15 @@ static CURLcode verify_host(struct Curl_easy *data,
failf(data, "schannel: server certificate name verification failed");
cleanup:
- curlx_unicodefree(cert_hostname_buff);
+ Curl_safefree(cert_hostname_buff);
return result;
}
-CURLcode Curl_verify_certificate(struct connectdata *conn, int sockindex)
+CURLcode Curl_verify_certificate(struct Curl_easy *data,
+ struct connectdata *conn, int sockindex)
{
SECURITY_STATUS sspi_status;
- struct Curl_easy *data = conn->data;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
CURLcode result = CURLE_OK;
CERT_CONTEXT *pCertContextServer = NULL;
@@ -584,7 +583,7 @@ CURLcode Curl_verify_certificate(struct connectdata *conn, int sockindex)
}
else {
result = add_certs_to_store(trust_store, SSL_CONN_CONFIG(CAfile),
- conn);
+ data);
}
}
@@ -675,7 +674,7 @@ CURLcode Curl_verify_certificate(struct connectdata *conn, int sockindex)
if(result == CURLE_OK) {
if(SSL_CONN_CONFIG(verifyhost)) {
- result = verify_host(conn->data, pCertContextServer, conn_hostname);
+ result = verify_host(data, pCertContextServer, conn_hostname);
}
}
diff --git a/Utilities/cmcurl/lib/vtls/sectransp.c b/Utilities/cmcurl/lib/vtls/sectransp.c
index 2627aff16..9a8f7de8d 100644
--- a/Utilities/cmcurl/lib/vtls/sectransp.c
+++ b/Utilities/cmcurl/lib/vtls/sectransp.c
@@ -5,12 +5,12 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
+ * Copyright (C) 2012 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 2012 - 2017, Nick Zitzmann, <nickzman@gmail.com>.
- * Copyright (C) 2012 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -1291,9 +1291,9 @@ static CURLcode sectransp_version_from_curl(SSLProtocol *darwinver,
#endif
static CURLcode
-set_ssl_version_min_max(struct connectdata *conn, int sockindex)
+set_ssl_version_min_max(struct Curl_easy *data, struct connectdata *conn,
+ int sockindex)
{
- struct Curl_easy *data = conn->data;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
struct ssl_backend_data *backend = connssl->backend;
long ssl_version = SSL_CONN_CONFIG(version);
@@ -1387,21 +1387,26 @@ set_ssl_version_min_max(struct connectdata *conn, int sockindex)
}
-static CURLcode sectransp_connect_step1(struct connectdata *conn,
+static CURLcode sectransp_connect_step1(struct Curl_easy *data,
+ struct connectdata *conn,
int sockindex)
{
- struct Curl_easy *data = conn->data;
curl_socket_t sockfd = conn->sock[sockindex];
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
struct ssl_backend_data *backend = connssl->backend;
const char * const ssl_cafile = SSL_CONN_CONFIG(CAfile);
const struct curl_blob *ssl_cablob = NULL;
const bool verifypeer = SSL_CONN_CONFIG(verifypeer);
- char * const ssl_cert = SSL_SET_OPTION(cert);
- const struct curl_blob *ssl_cert_blob = SSL_SET_OPTION(cert_blob);
+ char * const ssl_cert = SSL_SET_OPTION(primary.clientcert);
+ const struct curl_blob *ssl_cert_blob = SSL_SET_OPTION(primary.cert_blob);
+#ifndef CURL_DISABLE_PROXY
const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
conn->host.name;
const long int port = SSL_IS_PROXY() ? conn->port : conn->remote_port;
+#else
+ const char * const hostname = conn->host.name;
+ const long int port = conn->remote_port;
+#endif
#ifdef ENABLE_IPV6
struct in6_addr addr;
#else
@@ -1473,7 +1478,7 @@ static CURLcode sectransp_connect_step1(struct connectdata *conn,
case CURL_SSLVERSION_TLSv1_2:
case CURL_SSLVERSION_TLSv1_3:
{
- CURLcode result = set_ssl_version_min_max(conn, sockindex);
+ CURLcode result = set_ssl_version_min_max(data, conn, sockindex);
if(result != CURLE_OK)
return result;
break;
@@ -1522,7 +1527,7 @@ static CURLcode sectransp_connect_step1(struct connectdata *conn,
case CURL_SSLVERSION_TLSv1_2:
case CURL_SSLVERSION_TLSv1_3:
{
- CURLcode result = set_ssl_version_min_max(conn, sockindex);
+ CURLcode result = set_ssl_version_min_max(data, conn, sockindex);
if(result != CURLE_OK)
return result;
break;
@@ -1606,8 +1611,11 @@ static CURLcode sectransp_connect_step1(struct connectdata *conn,
&kCFTypeArrayCallBacks);
#ifdef USE_NGHTTP2
- if(data->set.httpversion >= CURL_HTTP_VERSION_2 &&
- (!SSL_IS_PROXY() || !conn->bits.tunnel_proxy)) {
+ if(data->set.httpversion >= CURL_HTTP_VERSION_2
+#ifndef CURL_DISABLE_PROXY
+ && (!SSL_IS_PROXY() || !conn->bits.tunnel_proxy)
+#endif
+ ) {
CFArrayAppendValue(alpnArr, CFSTR(NGHTTP2_PROTO_VERSION_ID));
infof(data, "ALPN, offering %s\n", NGHTTP2_PROTO_VERSION_ID);
}
@@ -1944,12 +1952,12 @@ static CURLcode sectransp_connect_step1(struct connectdata *conn,
char *ssl_sessionid;
size_t ssl_sessionid_len;
- Curl_ssl_sessionid_lock(conn);
- if(!Curl_ssl_getsessionid(conn, (void **)&ssl_sessionid,
+ Curl_ssl_sessionid_lock(data);
+ if(!Curl_ssl_getsessionid(data, conn, (void **)&ssl_sessionid,
&ssl_sessionid_len, sockindex)) {
/* we got a session id, use it! */
err = SSLSetPeerID(backend->ssl_ctx, ssl_sessionid, ssl_sessionid_len);
- Curl_ssl_sessionid_unlock(conn);
+ Curl_ssl_sessionid_unlock(data);
if(err != noErr) {
failf(data, "SSL: SSLSetPeerID() failed: OSStatus %d", err);
return CURLE_SSL_CONNECT_ERROR;
@@ -1962,20 +1970,20 @@ static CURLcode sectransp_connect_step1(struct connectdata *conn,
else {
CURLcode result;
ssl_sessionid =
- aprintf("%s:%d:%d:%s:%hu", ssl_cafile,
+ aprintf("%s:%d:%d:%s:%ld", ssl_cafile,
verifypeer, SSL_CONN_CONFIG(verifyhost), hostname, port);
ssl_sessionid_len = strlen(ssl_sessionid);
err = SSLSetPeerID(backend->ssl_ctx, ssl_sessionid, ssl_sessionid_len);
if(err != noErr) {
- Curl_ssl_sessionid_unlock(conn);
+ Curl_ssl_sessionid_unlock(data);
failf(data, "SSL: SSLSetPeerID() failed: OSStatus %d", err);
return CURLE_SSL_CONNECT_ERROR;
}
- result = Curl_ssl_addsessionid(conn, ssl_sessionid, ssl_sessionid_len,
- sockindex);
- Curl_ssl_sessionid_unlock(conn);
+ result = Curl_ssl_addsessionid(data, conn, ssl_sessionid,
+ ssl_sessionid_len, sockindex);
+ Curl_ssl_sessionid_unlock(data);
if(result) {
failf(data, "failed to store ssl session");
return result;
@@ -2181,7 +2189,7 @@ static CURLcode verify_cert(const char *cafile, struct Curl_easy *data,
if(res < 0) {
free(certbuf);
CFRelease(array);
- failf(data, "SSL: invalid CA certificate #%d (offset %d) in bundle",
+ failf(data, "SSL: invalid CA certificate #%d (offset %zu) in bundle",
n, offset);
return CURLE_SSL_CACERT_BADFILE;
}
@@ -2371,16 +2379,20 @@ static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data,
#endif /* SECTRANSP_PINNEDPUBKEY */
static CURLcode
-sectransp_connect_step2(struct connectdata *conn, int sockindex)
+sectransp_connect_step2(struct Curl_easy *data, struct connectdata *conn,
+ int sockindex)
{
- struct Curl_easy *data = conn->data;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
struct ssl_backend_data *backend = connssl->backend;
OSStatus err;
SSLCipherSuite cipher;
SSLProtocol protocol = 0;
+#ifndef CURL_DISABLE_PROXY
const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
conn->host.name;
+#else
+ const char * const hostname = conn->host.name;
+#endif
DEBUGASSERT(ssl_connect_2 == connssl->connecting_state
|| ssl_connect_2_reading == connssl->connecting_state
@@ -2406,7 +2418,7 @@ sectransp_connect_step2(struct connectdata *conn, int sockindex)
return result;
}
/* the documentation says we need to call SSLHandshake() again */
- return sectransp_connect_step2(conn, sockindex);
+ return sectransp_connect_step2(data, conn, sockindex);
/* Problem with encrypt / decrypt */
case errSSLPeerDecodeError:
@@ -2681,7 +2693,7 @@ sectransp_connect_step2(struct connectdata *conn, int sockindex)
else
infof(data, "ALPN, server did not agree to a protocol\n");
- Curl_multiuse_state(conn, conn->negnpn == CURL_HTTP_VERSION_2 ?
+ Curl_multiuse_state(data, conn->negnpn == CURL_HTTP_VERSION_2 ?
BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);
/* chosenProtocol is a reference to the string within alpnArr
@@ -2699,10 +2711,10 @@ sectransp_connect_step2(struct connectdata *conn, int sockindex)
#ifndef CURL_DISABLE_VERBOSE_STRINGS
/* This should be called during step3 of the connection at the earliest */
static void
-show_verbose_server_cert(struct connectdata *conn,
+show_verbose_server_cert(struct Curl_easy *data,
+ struct connectdata *conn,
int sockindex)
{
- struct Curl_easy *data = conn->data;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
struct ssl_backend_data *backend = connssl->backend;
CFArrayRef server_certs = NULL;
@@ -2805,10 +2817,9 @@ show_verbose_server_cert(struct connectdata *conn,
#endif /* !CURL_DISABLE_VERBOSE_STRINGS */
static CURLcode
-sectransp_connect_step3(struct connectdata *conn,
+sectransp_connect_step3(struct Curl_easy *data, struct connectdata *conn,
int sockindex)
{
- struct Curl_easy *data = conn->data;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
/* There is no step 3!
@@ -2816,7 +2827,7 @@ sectransp_connect_step3(struct connectdata *conn,
* server certificates. */
#ifndef CURL_DISABLE_VERBOSE_STRINGS
if(data->set.verbose)
- show_verbose_server_cert(conn, sockindex);
+ show_verbose_server_cert(data, conn, sockindex);
#endif
connssl->connecting_state = ssl_connect_done;
@@ -2827,13 +2838,13 @@ static Curl_recv sectransp_recv;
static Curl_send sectransp_send;
static CURLcode
-sectransp_connect_common(struct connectdata *conn,
+sectransp_connect_common(struct Curl_easy *data,
+ struct connectdata *conn,
int sockindex,
bool nonblocking,
bool *done)
{
CURLcode result;
- struct Curl_easy *data = conn->data;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
curl_socket_t sockfd = conn->sock[sockindex];
int what;
@@ -2854,7 +2865,7 @@ sectransp_connect_common(struct connectdata *conn,
return CURLE_OPERATION_TIMEDOUT;
}
- result = sectransp_connect_step1(conn, sockindex);
+ result = sectransp_connect_step1(data, conn, sockindex);
if(result)
return result;
}
@@ -2908,7 +2919,7 @@ sectransp_connect_common(struct connectdata *conn,
* before step2 has completed while ensuring that a client using select()
* or epoll() will always have a valid fdset to wait on.
*/
- result = sectransp_connect_step2(conn, sockindex);
+ result = sectransp_connect_step2(data, conn, sockindex);
if(result || (nonblocking &&
(ssl_connect_2 == connssl->connecting_state ||
ssl_connect_2_reading == connssl->connecting_state ||
@@ -2919,7 +2930,7 @@ sectransp_connect_common(struct connectdata *conn,
if(ssl_connect_3 == connssl->connecting_state) {
- result = sectransp_connect_step3(conn, sockindex);
+ result = sectransp_connect_step3(data, conn, sockindex);
if(result)
return result;
}
@@ -2939,18 +2950,20 @@ sectransp_connect_common(struct connectdata *conn,
return CURLE_OK;
}
-static CURLcode Curl_sectransp_connect_nonblocking(struct connectdata *conn,
- int sockindex, bool *done)
+static CURLcode sectransp_connect_nonblocking(struct Curl_easy *data,
+ struct connectdata *conn,
+ int sockindex, bool *done)
{
- return sectransp_connect_common(conn, sockindex, TRUE, done);
+ return sectransp_connect_common(data, conn, sockindex, TRUE, done);
}
-static CURLcode Curl_sectransp_connect(struct connectdata *conn, int sockindex)
+static CURLcode sectransp_connect(struct Curl_easy *data,
+ struct connectdata *conn, int sockindex)
{
CURLcode result;
bool done = FALSE;
- result = sectransp_connect_common(conn, sockindex, FALSE, &done);
+ result = sectransp_connect_common(data, conn, sockindex, FALSE, &done);
if(result)
return result;
@@ -2960,11 +2973,14 @@ static CURLcode Curl_sectransp_connect(struct connectdata *conn, int sockindex)
return CURLE_OK;
}
-static void Curl_sectransp_close(struct connectdata *conn, int sockindex)
+static void sectransp_close(struct Curl_easy *data, struct connectdata *conn,
+ int sockindex)
{
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
struct ssl_backend_data *backend = connssl->backend;
+ (void) data;
+
if(backend->ssl_ctx) {
(void)SSLClose(backend->ssl_ctx);
#if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS
@@ -2982,11 +2998,11 @@ static void Curl_sectransp_close(struct connectdata *conn, int sockindex)
backend->ssl_sockfd = 0;
}
-static int Curl_sectransp_shutdown(struct connectdata *conn, int sockindex)
+static int sectransp_shutdown(struct Curl_easy *data,
+ struct connectdata *conn, int sockindex)
{
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
struct ssl_backend_data *backend = connssl->backend;
- struct Curl_easy *data = conn->data;
ssize_t nread;
int what;
int rc;
@@ -3000,7 +3016,7 @@ static int Curl_sectransp_shutdown(struct connectdata *conn, int sockindex)
return 0;
#endif
- Curl_sectransp_close(conn, sockindex);
+ sectransp_close(data, conn, sockindex);
rc = 0;
@@ -3038,7 +3054,7 @@ static int Curl_sectransp_shutdown(struct connectdata *conn, int sockindex)
return rc;
}
-static void Curl_sectransp_session_free(void *ptr)
+static void sectransp_session_free(void *ptr)
{
/* ST, as of iOS 5 and Mountain Lion, has no public method of deleting a
cached session ID inside the Security framework. There is a private
@@ -3049,7 +3065,7 @@ static void Curl_sectransp_session_free(void *ptr)
Curl_safefree(ptr);
}
-static size_t Curl_sectransp_version(char *buffer, size_t size)
+static size_t sectransp_version(char *buffer, size_t size)
{
return msnprintf(buffer, size, "SecureTransport");
}
@@ -3062,7 +3078,7 @@ static size_t Curl_sectransp_version(char *buffer, size_t size)
* 0 means the connection has been closed
* -1 means the connection status is unknown
*/
-static int Curl_sectransp_check_cxn(struct connectdata *conn)
+static int sectransp_check_cxn(struct connectdata *conn)
{
struct ssl_connect_data *connssl = &conn->ssl[FIRSTSOCKET];
struct ssl_backend_data *backend = connssl->backend;
@@ -3078,8 +3094,8 @@ static int Curl_sectransp_check_cxn(struct connectdata *conn)
return 0;
}
-static bool Curl_sectransp_data_pending(const struct connectdata *conn,
- int connindex)
+static bool sectransp_data_pending(const struct connectdata *conn,
+ int connindex)
{
const struct ssl_connect_data *connssl = &conn->ssl[connindex];
struct ssl_backend_data *backend = connssl->backend;
@@ -3096,8 +3112,8 @@ static bool Curl_sectransp_data_pending(const struct connectdata *conn,
return false;
}
-static CURLcode Curl_sectransp_random(struct Curl_easy *data UNUSED_PARAM,
- unsigned char *entropy, size_t length)
+static CURLcode sectransp_random(struct Curl_easy *data UNUSED_PARAM,
+ unsigned char *entropy, size_t length)
{
/* arc4random_buf() isn't available on cats older than Lion, so let's
do this manually for the benefit of the older cats. */
@@ -3116,27 +3132,17 @@ static CURLcode Curl_sectransp_random(struct Curl_easy *data UNUSED_PARAM,
return CURLE_OK;
}
-static CURLcode Curl_sectransp_md5sum(unsigned char *tmp, /* input */
- size_t tmplen,
- unsigned char *md5sum, /* output */
- size_t md5len)
-{
- (void)md5len;
- (void)CC_MD5(tmp, (CC_LONG)tmplen, md5sum);
- return CURLE_OK;
-}
-
-static CURLcode Curl_sectransp_sha256sum(const unsigned char *tmp, /* input */
- size_t tmplen,
- unsigned char *sha256sum, /* output */
- size_t sha256len)
+static CURLcode sectransp_sha256sum(const unsigned char *tmp, /* input */
+ size_t tmplen,
+ unsigned char *sha256sum, /* output */
+ size_t sha256len)
{
assert(sha256len >= CURL_SHA256_DIGEST_LENGTH);
(void)CC_SHA256(tmp, (CC_LONG)tmplen, sha256sum);
return CURLE_OK;
}
-static bool Curl_sectransp_false_start(void)
+static bool sectransp_false_start(void)
{
#if CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7
if(SSLSetSessionOption != NULL)
@@ -3145,13 +3151,13 @@ static bool Curl_sectransp_false_start(void)
return FALSE;
}
-static ssize_t sectransp_send(struct connectdata *conn,
+static ssize_t sectransp_send(struct Curl_easy *data,
int sockindex,
const void *mem,
size_t len,
CURLcode *curlcode)
{
- /*struct Curl_easy *data = conn->data;*/
+ struct connectdata *conn = data->conn;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
struct ssl_backend_data *backend = connssl->backend;
size_t processed = 0UL;
@@ -3186,7 +3192,7 @@ static ssize_t sectransp_send(struct connectdata *conn,
*curlcode = CURLE_AGAIN;
return -1L;
default:
- failf(conn->data, "SSLWrite() returned error %d", err);
+ failf(data, "SSLWrite() returned error %d", err);
*curlcode = CURLE_SEND_ERROR;
return -1L;
}
@@ -3203,7 +3209,7 @@ static ssize_t sectransp_send(struct connectdata *conn,
*curlcode = CURLE_AGAIN;
return -1L;
default:
- failf(conn->data, "SSLWrite() returned error %d", err);
+ failf(data, "SSLWrite() returned error %d", err);
*curlcode = CURLE_SEND_ERROR;
return -1L;
}
@@ -3212,13 +3218,13 @@ static ssize_t sectransp_send(struct connectdata *conn,
return (ssize_t)processed;
}
-static ssize_t sectransp_recv(struct connectdata *conn,
+static ssize_t sectransp_recv(struct Curl_easy *data,
int num,
char *buf,
size_t buffersize,
CURLcode *curlcode)
{
- /*struct Curl_easy *data = conn->data;*/
+ struct connectdata *conn = data->conn;
struct ssl_connect_data *connssl = &conn->ssl[num];
struct ssl_backend_data *backend = connssl->backend;
size_t processed = 0UL;
@@ -3250,14 +3256,14 @@ static ssize_t sectransp_recv(struct connectdata *conn,
Leopard's headers */
case -9841:
if(SSL_CONN_CONFIG(CAfile) && SSL_CONN_CONFIG(verifypeer)) {
- CURLcode result = verify_cert(SSL_CONN_CONFIG(CAfile), conn->data,
+ CURLcode result = verify_cert(SSL_CONN_CONFIG(CAfile), data,
backend->ssl_ctx);
if(result)
return result;
}
goto again;
default:
- failf(conn->data, "SSLRead() return error %d", err);
+ failf(data, "SSLRead() return error %d", err);
*curlcode = CURLE_RECV_ERROR;
return -1L;
break;
@@ -3266,8 +3272,8 @@ static ssize_t sectransp_recv(struct connectdata *conn,
return (ssize_t)processed;
}
-static void *Curl_sectransp_get_internals(struct ssl_connect_data *connssl,
- CURLINFO info UNUSED_PARAM)
+static void *sectransp_get_internals(struct ssl_connect_data *connssl,
+ CURLINFO info UNUSED_PARAM)
{
struct ssl_backend_data *backend = connssl->backend;
(void)info;
@@ -3287,24 +3293,23 @@ const struct Curl_ssl Curl_ssl_sectransp = {
Curl_none_init, /* init */
Curl_none_cleanup, /* cleanup */
- Curl_sectransp_version, /* version */
- Curl_sectransp_check_cxn, /* check_cxn */
- Curl_sectransp_shutdown, /* shutdown */
- Curl_sectransp_data_pending, /* data_pending */
- Curl_sectransp_random, /* random */
+ sectransp_version, /* version */
+ sectransp_check_cxn, /* check_cxn */
+ sectransp_shutdown, /* shutdown */
+ sectransp_data_pending, /* data_pending */
+ sectransp_random, /* random */
Curl_none_cert_status_request, /* cert_status_request */
- Curl_sectransp_connect, /* connect */
- Curl_sectransp_connect_nonblocking, /* connect_nonblocking */
- Curl_sectransp_get_internals, /* get_internals */
- Curl_sectransp_close, /* close_one */
+ sectransp_connect, /* connect */
+ sectransp_connect_nonblocking, /* connect_nonblocking */
+ sectransp_get_internals, /* get_internals */
+ sectransp_close, /* close_one */
Curl_none_close_all, /* close_all */
- Curl_sectransp_session_free, /* session_free */
+ sectransp_session_free, /* session_free */
Curl_none_set_engine, /* set_engine */
Curl_none_set_engine_default, /* set_engine_default */
Curl_none_engines_list, /* engines_list */
- Curl_sectransp_false_start, /* false_start */
- Curl_sectransp_md5sum, /* md5sum */
- Curl_sectransp_sha256sum /* sha256sum */
+ sectransp_false_start, /* false_start */
+ sectransp_sha256sum /* sha256sum */
};
#ifdef __clang__
diff --git a/Utilities/cmcurl/lib/vtls/sectransp.h b/Utilities/cmcurl/lib/vtls/sectransp.h
index 5cec797b3..0febd6613 100644
--- a/Utilities/cmcurl/lib/vtls/sectransp.h
+++ b/Utilities/cmcurl/lib/vtls/sectransp.h
@@ -8,11 +8,11 @@
* \___|\___/|_| \_\_____|
*
* Copyright (C) 2012 - 2014, Nick Zitzmann, <nickzman@gmail.com>.
- * Copyright (C) 2012 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2012 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
diff --git a/Utilities/cmcurl/lib/vtls/vtls.c b/Utilities/cmcurl/lib/vtls/vtls.c
index 281043aa6..b8ab7494f 100644
--- a/Utilities/cmcurl/lib/vtls/vtls.c
+++ b/Utilities/cmcurl/lib/vtls/vtls.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -75,17 +75,21 @@
(1<<CURL_LOCK_DATA_SSL_SESSION)))
#define CLONE_STRING(var) \
- if(source->var) { \
- dest->var = strdup(source->var); \
- if(!dest->var) \
- return FALSE; \
- } \
- else \
- dest->var = NULL;
-
-#define CLONE_BLOB(var) \
- if(blobdup(&dest->var, source->var)) \
- return FALSE;
+ do { \
+ if(source->var) { \
+ dest->var = strdup(source->var); \
+ if(!dest->var) \
+ return FALSE; \
+ } \
+ else \
+ dest->var = NULL; \
+ } while(0)
+
+#define CLONE_BLOB(var) \
+ do { \
+ if(blobdup(&dest->var, source->var)) \
+ return FALSE; \
+ } while(0)
static CURLcode blobdup(struct curl_blob **dest,
struct curl_blob *src)
@@ -138,6 +142,7 @@ Curl_ssl_config_matches(struct ssl_primary_config *data,
Curl_safe_strcasecompare(data->egdsocket, needle->egdsocket) &&
Curl_safe_strcasecompare(data->cipher_list, needle->cipher_list) &&
Curl_safe_strcasecompare(data->cipher_list13, needle->cipher_list13) &&
+ Curl_safe_strcasecompare(data->curves, needle->curves) &&
Curl_safe_strcasecompare(data->pinned_key, needle->pinned_key))
return TRUE;
@@ -164,6 +169,7 @@ Curl_clone_primary_ssl_config(struct ssl_primary_config *source,
CLONE_STRING(cipher_list);
CLONE_STRING(cipher_list13);
CLONE_STRING(pinned_key);
+ CLONE_STRING(curves);
return TRUE;
}
@@ -179,16 +185,17 @@ void Curl_free_primary_ssl_config(struct ssl_primary_config *sslc)
Curl_safefree(sslc->cipher_list13);
Curl_safefree(sslc->pinned_key);
Curl_safefree(sslc->cert_blob);
+ Curl_safefree(sslc->curves);
}
#ifdef USE_SSL
-static int multissl_init(const struct Curl_ssl *backend);
+static int multissl_setup(const struct Curl_ssl *backend);
#endif
int Curl_ssl_backend(void)
{
#ifdef USE_SSL
- multissl_init(NULL);
+ multissl_setup(NULL);
return Curl_ssl->info.id;
#else
return (int)CURLSSLBACKEND_NONE;
@@ -284,7 +291,8 @@ ssl_connect_init_proxy(struct connectdata *conn, int sockindex)
#endif
CURLcode
-Curl_ssl_connect(struct connectdata *conn, int sockindex)
+Curl_ssl_connect(struct Curl_easy *data, struct connectdata *conn,
+ int sockindex)
{
CURLcode result;
@@ -296,26 +304,27 @@ Curl_ssl_connect(struct connectdata *conn, int sockindex)
}
#endif
- if(!ssl_prefs_check(conn->data))
+ if(!ssl_prefs_check(data))
return CURLE_SSL_CONNECT_ERROR;
/* mark this is being ssl-enabled from here on. */
conn->ssl[sockindex].use = TRUE;
conn->ssl[sockindex].state = ssl_connection_negotiating;
- result = Curl_ssl->connect_blocking(conn, sockindex);
+ result = Curl_ssl->connect_blocking(data, conn, sockindex);
if(!result)
- Curl_pgrsTime(conn->data, TIMER_APPCONNECT); /* SSL is connected */
+ Curl_pgrsTime(data, TIMER_APPCONNECT); /* SSL is connected */
return result;
}
CURLcode
-Curl_ssl_connect_nonblocking(struct connectdata *conn, int sockindex,
- bool *done)
+Curl_ssl_connect_nonblocking(struct Curl_easy *data, struct connectdata *conn,
+ int sockindex, bool *done)
{
CURLcode result;
+
#ifndef CURL_DISABLE_PROXY
if(conn->bits.proxy_ssl_connected[sockindex]) {
result = ssl_connect_init_proxy(conn, sockindex);
@@ -323,47 +332,46 @@ Curl_ssl_connect_nonblocking(struct connectdata *conn, int sockindex,
return result;
}
#endif
- if(!ssl_prefs_check(conn->data))
+ if(!ssl_prefs_check(data))
return CURLE_SSL_CONNECT_ERROR;
/* mark this is being ssl requested from here on. */
conn->ssl[sockindex].use = TRUE;
- result = Curl_ssl->connect_nonblocking(conn, sockindex, done);
+ result = Curl_ssl->connect_nonblocking(data, conn, sockindex, done);
if(!result && *done)
- Curl_pgrsTime(conn->data, TIMER_APPCONNECT); /* SSL is connected */
+ Curl_pgrsTime(data, TIMER_APPCONNECT); /* SSL is connected */
return result;
}
/*
* Lock shared SSL session data
*/
-void Curl_ssl_sessionid_lock(struct connectdata *conn)
+void Curl_ssl_sessionid_lock(struct Curl_easy *data)
{
- if(SSLSESSION_SHARED(conn->data))
- Curl_share_lock(conn->data,
- CURL_LOCK_DATA_SSL_SESSION, CURL_LOCK_ACCESS_SINGLE);
+ if(SSLSESSION_SHARED(data))
+ Curl_share_lock(data, CURL_LOCK_DATA_SSL_SESSION, CURL_LOCK_ACCESS_SINGLE);
}
/*
* Unlock shared SSL session data
*/
-void Curl_ssl_sessionid_unlock(struct connectdata *conn)
+void Curl_ssl_sessionid_unlock(struct Curl_easy *data)
{
- if(SSLSESSION_SHARED(conn->data))
- Curl_share_unlock(conn->data, CURL_LOCK_DATA_SSL_SESSION);
+ if(SSLSESSION_SHARED(data))
+ Curl_share_unlock(data, CURL_LOCK_DATA_SSL_SESSION);
}
/*
* Check if there's a session ID for the given connection in the cache, and if
* there's one suitable, it is provided. Returns TRUE when no entry matched.
*/
-bool Curl_ssl_getsessionid(struct connectdata *conn,
+bool Curl_ssl_getsessionid(struct Curl_easy *data,
+ struct connectdata *conn,
void **ssl_sessionid,
size_t *idsize, /* set 0 if unknown */
int sockindex)
{
- struct curl_ssl_session *check;
- struct Curl_easy *data = conn->data;
+ struct Curl_ssl_session *check;
size_t i;
long *general_age;
bool no_match = TRUE;
@@ -429,7 +437,7 @@ bool Curl_ssl_getsessionid(struct connectdata *conn,
/*
* Kill a single session ID entry in the cache.
*/
-void Curl_ssl_kill_session(struct curl_ssl_session *session)
+void Curl_ssl_kill_session(struct Curl_ssl_session *session)
{
if(session->sessionid) {
/* defensive check */
@@ -450,13 +458,12 @@ void Curl_ssl_kill_session(struct curl_ssl_session *session)
/*
* Delete the given session ID from the cache.
*/
-void Curl_ssl_delsessionid(struct connectdata *conn, void *ssl_sessionid)
+void Curl_ssl_delsessionid(struct Curl_easy *data, void *ssl_sessionid)
{
size_t i;
- struct Curl_easy *data = conn->data;
for(i = 0; i < data->set.general_ssl.max_ssl_sessions; i++) {
- struct curl_ssl_session *check = &data->state.session[i];
+ struct Curl_ssl_session *check = &data->state.session[i];
if(check->sessionid == ssl_sessionid) {
Curl_ssl_kill_session(check);
@@ -471,14 +478,14 @@ void Curl_ssl_delsessionid(struct connectdata *conn, void *ssl_sessionid)
* layer. Curl_XXXX_session_free() will be called to free/kill the session ID
* later on.
*/
-CURLcode Curl_ssl_addsessionid(struct connectdata *conn,
+CURLcode Curl_ssl_addsessionid(struct Curl_easy *data,
+ struct connectdata *conn,
void *ssl_sessionid,
size_t idsize,
int sockindex)
{
size_t i;
- struct Curl_easy *data = conn->data; /* the mother of all structs */
- struct curl_ssl_session *store = &data->state.session[0];
+ struct Curl_ssl_session *store = &data->state.session[0];
long oldest_age = data->state.session[0].age; /* zero if unused */
char *clone_host;
char *clone_conn_to_host;
@@ -617,16 +624,18 @@ int Curl_ssl_getsock(struct connectdata *conn,
/* USE_OPENSSL || USE_GNUTLS || USE_SCHANNEL || USE_SECTRANSP || USE_NSS */
#endif
-void Curl_ssl_close(struct connectdata *conn, int sockindex)
+void Curl_ssl_close(struct Curl_easy *data, struct connectdata *conn,
+ int sockindex)
{
DEBUGASSERT((sockindex <= 1) && (sockindex >= -1));
- Curl_ssl->close_one(conn, sockindex);
+ Curl_ssl->close_one(data, conn, sockindex);
conn->ssl[sockindex].state = ssl_connection_none;
}
-CURLcode Curl_ssl_shutdown(struct connectdata *conn, int sockindex)
+CURLcode Curl_ssl_shutdown(struct Curl_easy *data, struct connectdata *conn,
+ int sockindex)
{
- if(Curl_ssl->shut_down(conn, sockindex))
+ if(Curl_ssl->shut_down(data, conn, sockindex))
return CURLE_SSL_SHUTDOWN_FAILED;
conn->ssl[sockindex].use = FALSE; /* get back to ordinary socket usage */
@@ -664,13 +673,13 @@ struct curl_slist *Curl_ssl_engines_list(struct Curl_easy *data)
*/
CURLcode Curl_ssl_initsessions(struct Curl_easy *data, size_t amount)
{
- struct curl_ssl_session *session;
+ struct Curl_ssl_session *session;
if(data->state.session)
/* this is just a precaution to prevent multiple inits */
return CURLE_OK;
- session = calloc(amount, sizeof(struct curl_ssl_session));
+ session = calloc(amount, sizeof(struct Curl_ssl_session));
if(!session)
return CURLE_OUT_OF_MEMORY;
@@ -681,12 +690,12 @@ CURLcode Curl_ssl_initsessions(struct Curl_easy *data, size_t amount)
return CURLE_OK;
}
-static size_t Curl_multissl_version(char *buffer, size_t size);
+static size_t multissl_version(char *buffer, size_t size);
size_t Curl_ssl_version(char *buffer, size_t size)
{
#ifdef CURL_WITH_MULTI_SSL
- return Curl_multissl_version(buffer, size);
+ return multissl_version(buffer, size);
#else
return Curl_ssl->version(buffer, size);
#endif
@@ -1027,16 +1036,6 @@ CURLcode Curl_pin_peer_pubkey(struct Curl_easy *data,
return result;
}
-#ifndef CURL_DISABLE_CRYPTO_AUTH
-CURLcode Curl_ssl_md5sum(unsigned char *tmp, /* input */
- size_t tmplen,
- unsigned char *md5sum, /* output */
- size_t md5len)
-{
- return Curl_ssl->md5sum(tmp, tmplen, md5sum, md5len);
-}
-#endif
-
/*
* Check whether the SSL backend supports the status_request extension.
*/
@@ -1073,9 +1072,11 @@ int Curl_none_init(void)
void Curl_none_cleanup(void)
{ }
-int Curl_none_shutdown(struct connectdata *conn UNUSED_PARAM,
+int Curl_none_shutdown(struct Curl_easy *data UNUSED_PARAM,
+ struct connectdata *conn UNUSED_PARAM,
int sockindex UNUSED_PARAM)
{
+ (void)data;
(void)conn;
(void)sockindex;
return 0;
@@ -1145,70 +1146,44 @@ bool Curl_none_false_start(void)
return FALSE;
}
-#ifndef CURL_DISABLE_CRYPTO_AUTH
-CURLcode Curl_none_md5sum(unsigned char *input, size_t inputlen,
- unsigned char *md5sum, size_t md5len UNUSED_PARAM)
+static int multissl_init(void)
{
- struct MD5_context *MD5pw;
-
- (void)md5len;
-
- MD5pw = Curl_MD5_init(Curl_DIGEST_MD5);
- if(!MD5pw)
- return CURLE_OUT_OF_MEMORY;
- Curl_MD5_update(MD5pw, input, curlx_uztoui(inputlen));
- Curl_MD5_final(MD5pw, md5sum);
- return CURLE_OK;
-}
-#else
-CURLcode Curl_none_md5sum(unsigned char *input UNUSED_PARAM,
- size_t inputlen UNUSED_PARAM,
- unsigned char *md5sum UNUSED_PARAM,
- size_t md5len UNUSED_PARAM)
-{
- (void)input;
- (void)inputlen;
- (void)md5sum;
- (void)md5len;
- return CURLE_NOT_BUILT_IN;
-}
-#endif
-
-static int Curl_multissl_init(void)
-{
- if(multissl_init(NULL))
+ if(multissl_setup(NULL))
return 1;
return Curl_ssl->init();
}
-static CURLcode Curl_multissl_connect(struct connectdata *conn, int sockindex)
+static CURLcode multissl_connect(struct Curl_easy *data,
+ struct connectdata *conn, int sockindex)
{
- if(multissl_init(NULL))
+ if(multissl_setup(NULL))
return CURLE_FAILED_INIT;
- return Curl_ssl->connect_blocking(conn, sockindex);
+ return Curl_ssl->connect_blocking(data, conn, sockindex);
}
-static CURLcode Curl_multissl_connect_nonblocking(struct connectdata *conn,
- int sockindex, bool *done)
+static CURLcode multissl_connect_nonblocking(struct Curl_easy *data,
+ struct connectdata *conn,
+ int sockindex, bool *done)
{
- if(multissl_init(NULL))
+ if(multissl_setup(NULL))
return CURLE_FAILED_INIT;
- return Curl_ssl->connect_nonblocking(conn, sockindex, done);
+ return Curl_ssl->connect_nonblocking(data, conn, sockindex, done);
}
-static void *Curl_multissl_get_internals(struct ssl_connect_data *connssl,
- CURLINFO info)
+static void *multissl_get_internals(struct ssl_connect_data *connssl,
+ CURLINFO info)
{
- if(multissl_init(NULL))
+ if(multissl_setup(NULL))
return NULL;
return Curl_ssl->get_internals(connssl, info);
}
-static void Curl_multissl_close(struct connectdata *conn, int sockindex)
+static void multissl_close(struct Curl_easy *data, struct connectdata *conn,
+ int sockindex)
{
- if(multissl_init(NULL))
+ if(multissl_setup(NULL))
return;
- Curl_ssl->close_one(conn, sockindex);
+ Curl_ssl->close_one(data, conn, sockindex);
}
static const struct Curl_ssl Curl_ssl_multi = {
@@ -1216,25 +1191,24 @@ static const struct Curl_ssl Curl_ssl_multi = {
0, /* supports nothing */
(size_t)-1, /* something insanely large to be on the safe side */
- Curl_multissl_init, /* init */
+ multissl_init, /* init */
Curl_none_cleanup, /* cleanup */
- Curl_multissl_version, /* version */
+ multissl_version, /* version */
Curl_none_check_cxn, /* check_cxn */
Curl_none_shutdown, /* shutdown */
Curl_none_data_pending, /* data_pending */
Curl_none_random, /* random */
Curl_none_cert_status_request, /* cert_status_request */
- Curl_multissl_connect, /* connect */
- Curl_multissl_connect_nonblocking, /* connect_nonblocking */
- Curl_multissl_get_internals, /* get_internals */
- Curl_multissl_close, /* close_one */
+ multissl_connect, /* connect */
+ multissl_connect_nonblocking, /* connect_nonblocking */
+ multissl_get_internals, /* get_internals */
+ multissl_close, /* close_one */
Curl_none_close_all, /* close_all */
Curl_none_session_free, /* session_free */
Curl_none_set_engine, /* set_engine */
Curl_none_set_engine_default, /* set_engine_default */
Curl_none_engines_list, /* engines_list */
Curl_none_false_start, /* false_start */
- Curl_none_md5sum, /* md5sum */
NULL /* sha256sum */
};
@@ -1299,7 +1273,7 @@ static const struct Curl_ssl *available_backends[] = {
NULL
};
-static size_t Curl_multissl_version(char *buffer, size_t size)
+static size_t multissl_version(char *buffer, size_t size)
{
static const struct Curl_ssl *selected;
static char backends[200];
@@ -1343,7 +1317,7 @@ static size_t Curl_multissl_version(char *buffer, size_t size)
return backends_len;
}
-static int multissl_init(const struct Curl_ssl *backend)
+static int multissl_setup(const struct Curl_ssl *backend)
{
const char *env;
char *env_tmp;
@@ -1402,7 +1376,7 @@ CURLsslset curl_global_sslset(curl_sslbackend id, const char *name,
for(i = 0; available_backends[i]; i++) {
if(available_backends[i]->info.id == id ||
(name && strcasecompare(available_backends[i]->info.name, name))) {
- multissl_init(available_backends[i]);
+ multissl_setup(available_backends[i]);
return CURLSSLSET_OK;
}
}
diff --git a/Utilities/cmcurl/lib/vtls/vtls.h b/Utilities/cmcurl/lib/vtls/vtls.h
index bcc844416..9666682ec 100644
--- a/Utilities/cmcurl/lib/vtls/vtls.h
+++ b/Utilities/cmcurl/lib/vtls/vtls.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -47,7 +47,8 @@ struct Curl_ssl {
size_t (*version)(char *buffer, size_t size);
int (*check_cxn)(struct connectdata *cxn);
- int (*shut_down)(struct connectdata *conn, int sockindex);
+ int (*shut_down)(struct Curl_easy *data, struct connectdata *conn,
+ int sockindex);
bool (*data_pending)(const struct connectdata *conn,
int connindex);
@@ -56,11 +57,14 @@ struct Curl_ssl {
size_t length);
bool (*cert_status_request)(void);
- CURLcode (*connect_blocking)(struct connectdata *conn, int sockindex);
- CURLcode (*connect_nonblocking)(struct connectdata *conn, int sockindex,
+ CURLcode (*connect_blocking)(struct Curl_easy *data,
+ struct connectdata *conn, int sockindex);
+ CURLcode (*connect_nonblocking)(struct Curl_easy *data,
+ struct connectdata *conn, int sockindex,
bool *done);
void *(*get_internals)(struct ssl_connect_data *connssl, CURLINFO info);
- void (*close_one)(struct connectdata *conn, int sockindex);
+ void (*close_one)(struct Curl_easy *data, struct connectdata *conn,
+ int sockindex);
void (*close_all)(struct Curl_easy *data);
void (*session_free)(void *ptr);
@@ -69,9 +73,6 @@ struct Curl_ssl {
struct curl_slist *(*engines_list)(struct Curl_easy *data);
bool (*false_start)(void);
-
- CURLcode (*md5sum)(unsigned char *input, size_t inputlen,
- unsigned char *md5sum, size_t md5sumlen);
CURLcode (*sha256sum)(const unsigned char *input, size_t inputlen,
unsigned char *sha256sum, size_t sha256sumlen);
};
@@ -82,7 +83,8 @@ extern const struct Curl_ssl *Curl_ssl;
int Curl_none_init(void);
void Curl_none_cleanup(void);
-int Curl_none_shutdown(struct connectdata *conn, int sockindex);
+int Curl_none_shutdown(struct Curl_easy *data, struct connectdata *conn,
+ int sockindex);
int Curl_none_check_cxn(struct connectdata *conn);
CURLcode Curl_none_random(struct Curl_easy *data, unsigned char *entropy,
size_t length);
@@ -95,8 +97,6 @@ CURLcode Curl_none_set_engine_default(struct Curl_easy *data);
struct curl_slist *Curl_none_engines_list(struct Curl_easy *data);
bool Curl_none_false_start(void);
bool Curl_ssl_tls13_ciphersuites(void);
-CURLcode Curl_none_md5sum(unsigned char *input, size_t inputlen,
- unsigned char *md5sum, size_t md5len);
#include "openssl.h" /* OpenSSL versions */
#include "gtls.h" /* GnuTLS versions */
@@ -131,12 +131,26 @@ CURLcode Curl_none_md5sum(unsigned char *input, size_t inputlen,
CURL_SOCKET_BAD ? FIRSTSOCKET : SECONDARYSOCKET].state)
#define SSL_SET_OPTION(var) \
(SSL_IS_PROXY() ? data->set.proxy_ssl.var : data->set.ssl.var)
+#define SSL_SET_OPTION_LVALUE(var) \
+ (*(SSL_IS_PROXY() ? &data->set.proxy_ssl.var : &data->set.ssl.var))
#define SSL_CONN_CONFIG(var) \
(SSL_IS_PROXY() ? conn->proxy_ssl_config.var : conn->ssl_config.var)
+#define SSL_HOST_NAME() \
+ (SSL_IS_PROXY() ? conn->http_proxy.host.name : conn->host.name)
+#define SSL_HOST_DISPNAME() \
+ (SSL_IS_PROXY() ? conn->http_proxy.host.dispname : conn->host.dispname)
+#define SSL_PINNED_PUB_KEY() (SSL_IS_PROXY() \
+ ? data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] \
+ : data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG])
#else
#define SSL_IS_PROXY() FALSE
#define SSL_SET_OPTION(var) data->set.ssl.var
+#define SSL_SET_OPTION_LVALUE(var) data->set.ssl.var
#define SSL_CONN_CONFIG(var) conn->ssl_config.var
+#define SSL_HOST_NAME() conn->host.name
+#define SSL_HOST_DISPNAME() conn->host.dispname
+#define SSL_PINNED_PUB_KEY() \
+ data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG]
#endif
bool Curl_ssl_config_matches(struct ssl_primary_config *data,
@@ -151,15 +165,19 @@ int Curl_ssl_backend(void);
#ifdef USE_SSL
int Curl_ssl_init(void);
void Curl_ssl_cleanup(void);
-CURLcode Curl_ssl_connect(struct connectdata *conn, int sockindex);
-CURLcode Curl_ssl_connect_nonblocking(struct connectdata *conn,
+CURLcode Curl_ssl_connect(struct Curl_easy *data, struct connectdata *conn,
+ int sockindex);
+CURLcode Curl_ssl_connect_nonblocking(struct Curl_easy *data,
+ struct connectdata *conn,
int sockindex,
bool *done);
/* tell the SSL stuff to close down all open information regarding
connections (and thus session ID caching etc) */
void Curl_ssl_close_all(struct Curl_easy *data);
-void Curl_ssl_close(struct connectdata *conn, int sockindex);
-CURLcode Curl_ssl_shutdown(struct connectdata *conn, int sockindex);
+void Curl_ssl_close(struct Curl_easy *data, struct connectdata *conn,
+ int sockindex);
+CURLcode Curl_ssl_shutdown(struct Curl_easy *data, struct connectdata *conn,
+ int sockindex);
CURLcode Curl_ssl_set_engine(struct Curl_easy *data, const char *engine);
/* Sets engine as default for all SSL operations */
CURLcode Curl_ssl_set_engine_default(struct Curl_easy *data);
@@ -191,10 +209,10 @@ CURLcode Curl_ssl_push_certinfo(struct Curl_easy *data, int certnum,
* The purpose of explicitly locking SSL session cache data is to allow
* individual SSL engines to manage session lifetime in their specific way.
*/
-void Curl_ssl_sessionid_lock(struct connectdata *conn);
+void Curl_ssl_sessionid_lock(struct Curl_easy *data);
/* Unlock session cache mutex */
-void Curl_ssl_sessionid_unlock(struct connectdata *conn);
+void Curl_ssl_sessionid_unlock(struct Curl_easy *data);
/* extract a session ID
* Sessionid mutex must be locked (see Curl_ssl_sessionid_lock).
@@ -202,7 +220,8 @@ void Curl_ssl_sessionid_unlock(struct connectdata *conn);
* is properly taken (e.g. its refcount is incremented
* under sessionid mutex).
*/
-bool Curl_ssl_getsessionid(struct connectdata *conn,
+bool Curl_ssl_getsessionid(struct Curl_easy *data,
+ struct connectdata *conn,
void **ssl_sessionid,
size_t *idsize, /* set 0 if unknown */
int sockindex);
@@ -211,7 +230,8 @@ bool Curl_ssl_getsessionid(struct connectdata *conn,
* Caller must ensure that it has properly shared ownership of this sessionid
* object with cache (e.g. incrementing refcount on success)
*/
-CURLcode Curl_ssl_addsessionid(struct connectdata *conn,
+CURLcode Curl_ssl_addsessionid(struct Curl_easy *data,
+ struct connectdata *conn,
void *ssl_sessionid,
size_t idsize,
int sockindex);
@@ -221,22 +241,18 @@ CURLcode Curl_ssl_addsessionid(struct connectdata *conn,
* take sessionid object ownership from sessionid cache
* (e.g. decrement refcount).
*/
-void Curl_ssl_kill_session(struct curl_ssl_session *session);
+void Curl_ssl_kill_session(struct Curl_ssl_session *session);
/* delete a session from the cache
* Sessionid mutex must be locked (see Curl_ssl_sessionid_lock).
* This will call engine-specific curlssl_session_free function, which must
* take sessionid object ownership from sessionid cache
* (e.g. decrement refcount).
*/
-void Curl_ssl_delsessionid(struct connectdata *conn, void *ssl_sessionid);
+void Curl_ssl_delsessionid(struct Curl_easy *data, void *ssl_sessionid);
/* get N random bytes into the buffer */
CURLcode Curl_ssl_random(struct Curl_easy *data, unsigned char *buffer,
size_t length);
-CURLcode Curl_ssl_md5sum(unsigned char *tmp, /* input */
- size_t tmplen,
- unsigned char *md5sum, /* output */
- size_t md5len);
/* Check pinned public key. */
CURLcode Curl_pin_peer_pubkey(struct Curl_easy *data,
const char *pinnedpubkey,
@@ -253,10 +269,10 @@ bool Curl_ssl_false_start(void);
/* When SSL support is not present, just define away these function calls */
#define Curl_ssl_init() 1
#define Curl_ssl_cleanup() Curl_nop_stmt
-#define Curl_ssl_connect(x,y) CURLE_NOT_BUILT_IN
+#define Curl_ssl_connect(x,y,z) CURLE_NOT_BUILT_IN
#define Curl_ssl_close_all(x) Curl_nop_stmt
-#define Curl_ssl_close(x,y) Curl_nop_stmt
-#define Curl_ssl_shutdown(x,y) CURLE_NOT_BUILT_IN
+#define Curl_ssl_close(x,y,z) Curl_nop_stmt
+#define Curl_ssl_shutdown(x,y,z) CURLE_NOT_BUILT_IN
#define Curl_ssl_set_engine(x,y) CURLE_NOT_BUILT_IN
#define Curl_ssl_set_engine_default(x) CURLE_NOT_BUILT_IN
#define Curl_ssl_engines_list(x) NULL
@@ -266,7 +282,7 @@ bool Curl_ssl_false_start(void);
#define Curl_ssl_data_pending(x,y) 0
#define Curl_ssl_check_cxn(x) 0
#define Curl_ssl_free_certinfo(x) Curl_nop_stmt
-#define Curl_ssl_connect_nonblocking(x,y,z) CURLE_NOT_BUILT_IN
+#define Curl_ssl_connect_nonblocking(x,y,z,w) CURLE_NOT_BUILT_IN
#define Curl_ssl_kill_session(x) Curl_nop_stmt
#define Curl_ssl_random(x,y,z) ((void)x, CURLE_NOT_BUILT_IN)
#define Curl_ssl_cert_status_request() FALSE
diff --git a/Utilities/cmcurl/lib/vtls/wolfssl.c b/Utilities/cmcurl/lib/vtls/wolfssl.c
index 7b2a124e4..e1fa45926 100644
--- a/Utilities/cmcurl/lib/vtls/wolfssl.c
+++ b/Utilities/cmcurl/lib/vtls/wolfssl.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -217,11 +217,10 @@ static int do_file_type(const char *type)
* layer and do all necessary magic.
*/
static CURLcode
-wolfssl_connect_step1(struct connectdata *conn,
+wolfssl_connect_step1(struct Curl_easy *data, struct connectdata *conn,
int sockindex)
{
char *ciphers;
- struct Curl_easy *data = conn->data;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
struct ssl_backend_data *backend = connssl->backend;
SSL_METHOD* req_method = NULL;
@@ -256,7 +255,7 @@ wolfssl_connect_step1(struct connectdata *conn,
use_sni(TRUE);
break;
case CURL_SSLVERSION_TLSv1_0:
-#ifdef WOLFSSL_ALLOW_TLSV10
+#if defined(WOLFSSL_ALLOW_TLSV10) && !defined(NO_OLD_TLS)
req_method = TLSv1_client_method();
use_sni(TRUE);
#else
@@ -265,8 +264,13 @@ wolfssl_connect_step1(struct connectdata *conn,
#endif
break;
case CURL_SSLVERSION_TLSv1_1:
+#ifndef NO_OLD_TLS
req_method = TLSv1_1_client_method();
use_sni(TRUE);
+#else
+ failf(data, "wolfSSL does not support TLS 1.1");
+ return CURLE_NOT_BUILT_IN;
+#endif
break;
case CURL_SSLVERSION_TLSv1_2:
req_method = TLSv1_2_client_method();
@@ -353,8 +357,8 @@ wolfssl_connect_step1(struct connectdata *conn,
SSL_CONN_CONFIG(CApath))) {
if(SSL_CONN_CONFIG(verifypeer)) {
/* Fail if we insist on successfully verifying the server. */
- failf(data, "error setting certificate verify locations:\n"
- " CAfile: %s\n CApath: %s",
+ failf(data, "error setting certificate verify locations:"
+ " CAfile: %s CApath: %s",
SSL_CONN_CONFIG(CAfile)?
SSL_CONN_CONFIG(CAfile): "none",
SSL_CONN_CONFIG(CApath)?
@@ -372,21 +376,19 @@ wolfssl_connect_step1(struct connectdata *conn,
/* Everything is fine. */
infof(data, "successfully set certificate verify locations:\n");
}
- infof(data,
- " CAfile: %s\n"
- " CApath: %s\n",
- SSL_CONN_CONFIG(CAfile) ? SSL_CONN_CONFIG(CAfile):
- "none",
- SSL_CONN_CONFIG(CApath) ? SSL_CONN_CONFIG(CApath):
- "none");
+ infof(data, " CAfile: %s\n",
+ SSL_CONN_CONFIG(CAfile) ? SSL_CONN_CONFIG(CAfile) : "none");
+ infof(data, " CApath: %s\n",
+ SSL_CONN_CONFIG(CApath) ? SSL_CONN_CONFIG(CApath) : "none");
}
/* Load the client certificate, and private key */
- if(SSL_SET_OPTION(cert) && SSL_SET_OPTION(key)) {
+ if(SSL_SET_OPTION(primary.clientcert) && SSL_SET_OPTION(key)) {
int file_type = do_file_type(SSL_SET_OPTION(cert_type));
- if(SSL_CTX_use_certificate_file(backend->ctx, SSL_SET_OPTION(cert),
- file_type) != 1) {
+ if(SSL_CTX_use_certificate_file(backend->ctx,
+ SSL_SET_OPTION(primary.clientcert),
+ file_type) != 1) {
failf(data, "unable to use client certificate (no key or wrong pass"
" phrase?)");
return CURLE_SSL_CONNECT_ERROR;
@@ -502,16 +504,23 @@ wolfssl_connect_step1(struct connectdata *conn,
}
#endif /* OPENSSL_EXTRA */
+#ifdef HAVE_SECURE_RENEGOTIATION
+ if(wolfSSL_UseSecureRenegotiation(backend->handle) != SSL_SUCCESS) {
+ failf(data, "SSL: failed setting secure renegotiation");
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+#endif /* HAVE_SECURE_RENEGOTIATION */
+
/* Check if there's a cached ID we can/should use here! */
if(SSL_SET_OPTION(primary.sessionid)) {
void *ssl_sessionid = NULL;
- Curl_ssl_sessionid_lock(conn);
- if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL, sockindex)) {
+ Curl_ssl_sessionid_lock(data);
+ if(!Curl_ssl_getsessionid(data, conn, &ssl_sessionid, NULL, sockindex)) {
/* we got a session id, use it! */
if(!SSL_set_session(backend->handle, ssl_sessionid)) {
char error_buffer[WOLFSSL_MAX_ERROR_SZ];
- Curl_ssl_sessionid_unlock(conn);
+ Curl_ssl_sessionid_unlock(data);
failf(data, "SSL: SSL_set_session failed: %s",
ERR_error_string(SSL_get_error(backend->handle, 0),
error_buffer));
@@ -520,7 +529,7 @@ wolfssl_connect_step1(struct connectdata *conn,
/* Informational message */
infof(data, "SSL re-using session ID\n");
}
- Curl_ssl_sessionid_unlock(conn);
+ Curl_ssl_sessionid_unlock(data);
}
/* pass the raw socket into the SSL layer */
@@ -535,11 +544,10 @@ wolfssl_connect_step1(struct connectdata *conn,
static CURLcode
-wolfssl_connect_step2(struct connectdata *conn,
+wolfssl_connect_step2(struct Curl_easy *data, struct connectdata *conn,
int sockindex)
{
int ret = -1;
- struct Curl_easy *data = conn->data;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
struct ssl_backend_data *backend = connssl->backend;
#ifndef CURL_DISABLE_PROXY
@@ -610,7 +618,7 @@ wolfssl_connect_step2(struct connectdata *conn,
* as also mismatching CN fields */
else if(DOMAIN_NAME_MISMATCH == detail) {
#if 1
- failf(data, "\tsubject alt name(s) or common name do not match \"%s\"\n",
+ failf(data, "\tsubject alt name(s) or common name do not match \"%s\"",
dispname);
return CURLE_PEER_FAILED_VERIFICATION;
#else
@@ -637,7 +645,7 @@ wolfssl_connect_step2(struct connectdata *conn,
#if LIBWOLFSSL_VERSION_HEX >= 0x02007000 /* 2.7.0 */
else if(ASN_NO_SIGNER_E == detail) {
if(SSL_CONN_CONFIG(verifypeer)) {
- failf(data, "\tCA signer not available for verification\n");
+ failf(data, "\tCA signer not available for verification");
return CURLE_SSL_CACERT_BADFILE;
}
else {
@@ -725,7 +733,7 @@ wolfssl_connect_step2(struct connectdata *conn,
else
infof(data, "ALPN, unrecognized protocol %.*s\n", protocol_len,
protocol);
- Curl_multiuse_state(conn, conn->negnpn == CURL_HTTP_VERSION_2 ?
+ Curl_multiuse_state(data, conn->negnpn == CURL_HTTP_VERSION_2 ?
BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);
}
else if(rc == SSL_ALPN_NOT_FOUND)
@@ -751,11 +759,10 @@ wolfssl_connect_step2(struct connectdata *conn,
static CURLcode
-wolfssl_connect_step3(struct connectdata *conn,
+wolfssl_connect_step3(struct Curl_easy *data, struct connectdata *conn,
int sockindex)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
struct ssl_backend_data *backend = connssl->backend;
@@ -768,27 +775,27 @@ wolfssl_connect_step3(struct connectdata *conn,
our_ssl_sessionid = SSL_get_session(backend->handle);
- Curl_ssl_sessionid_lock(conn);
- incache = !(Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL,
+ Curl_ssl_sessionid_lock(data);
+ incache = !(Curl_ssl_getsessionid(data, conn, &old_ssl_sessionid, NULL,
sockindex));
if(incache) {
if(old_ssl_sessionid != our_ssl_sessionid) {
infof(data, "old SSL session ID is stale, removing\n");
- Curl_ssl_delsessionid(conn, old_ssl_sessionid);
+ Curl_ssl_delsessionid(data, old_ssl_sessionid);
incache = FALSE;
}
}
if(!incache) {
- result = Curl_ssl_addsessionid(conn, our_ssl_sessionid,
+ result = Curl_ssl_addsessionid(data, conn, our_ssl_sessionid,
0 /* unknown size */, sockindex);
if(result) {
- Curl_ssl_sessionid_unlock(conn);
+ Curl_ssl_sessionid_unlock(data);
failf(data, "failed to store ssl session");
return result;
}
}
- Curl_ssl_sessionid_unlock(conn);
+ Curl_ssl_sessionid_unlock(data);
}
connssl->connecting_state = ssl_connect_done;
@@ -797,12 +804,13 @@ wolfssl_connect_step3(struct connectdata *conn,
}
-static ssize_t wolfssl_send(struct connectdata *conn,
- int sockindex,
- const void *mem,
- size_t len,
- CURLcode *curlcode)
+static ssize_t wolfssl_send(struct Curl_easy *data,
+ int sockindex,
+ const void *mem,
+ size_t len,
+ CURLcode *curlcode)
{
+ struct connectdata *conn = data->conn;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
struct ssl_backend_data *backend = connssl->backend;
char error_buffer[WOLFSSL_MAX_ERROR_SZ];
@@ -819,7 +827,7 @@ static ssize_t wolfssl_send(struct connectdata *conn,
*curlcode = CURLE_AGAIN;
return -1;
default:
- failf(conn->data, "SSL write: %s, errno %d",
+ failf(data, "SSL write: %s, errno %d",
ERR_error_string(err, error_buffer),
SOCKERRNO);
*curlcode = CURLE_SEND_ERROR;
@@ -829,11 +837,14 @@ static ssize_t wolfssl_send(struct connectdata *conn,
return rc;
}
-static void Curl_wolfssl_close(struct connectdata *conn, int sockindex)
+static void wolfssl_close(struct Curl_easy *data, struct connectdata *conn,
+ int sockindex)
{
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
struct ssl_backend_data *backend = connssl->backend;
+ (void) data;
+
if(backend->handle) {
(void)SSL_shutdown(backend->handle);
SSL_free(backend->handle);
@@ -845,12 +856,13 @@ static void Curl_wolfssl_close(struct connectdata *conn, int sockindex)
}
}
-static ssize_t wolfssl_recv(struct connectdata *conn,
+static ssize_t wolfssl_recv(struct Curl_easy *data,
int num,
char *buf,
size_t buffersize,
CURLcode *curlcode)
{
+ struct connectdata *conn = data->conn;
struct ssl_connect_data *connssl = &conn->ssl[num];
struct ssl_backend_data *backend = connssl->backend;
char error_buffer[WOLFSSL_MAX_ERROR_SZ];
@@ -869,9 +881,8 @@ static ssize_t wolfssl_recv(struct connectdata *conn,
*curlcode = CURLE_AGAIN;
return -1;
default:
- failf(conn->data, "SSL read: %s, errno %d",
- ERR_error_string(err, error_buffer),
- SOCKERRNO);
+ failf(data, "SSL read: %s, errno %d",
+ ERR_error_string(err, error_buffer), SOCKERRNO);
*curlcode = CURLE_RECV_ERROR;
return -1;
}
@@ -880,14 +891,14 @@ static ssize_t wolfssl_recv(struct connectdata *conn,
}
-static void Curl_wolfssl_session_free(void *ptr)
+static void wolfssl_session_free(void *ptr)
{
(void)ptr;
/* wolfSSL reuses sessions on own, no free */
}
-static size_t Curl_wolfssl_version(char *buffer, size_t size)
+static size_t wolfssl_version(char *buffer, size_t size)
{
#if LIBWOLFSSL_VERSION_HEX >= 0x03006000
return msnprintf(buffer, size, "wolfSSL/%s", wolfSSL_lib_version());
@@ -897,7 +908,7 @@ static size_t Curl_wolfssl_version(char *buffer, size_t size)
}
-static int Curl_wolfssl_init(void)
+static int wolfssl_init(void)
{
#ifdef OPENSSL_EXTRA
Curl_tls_keylog_open();
@@ -906,7 +917,7 @@ static int Curl_wolfssl_init(void)
}
-static void Curl_wolfssl_cleanup(void)
+static void wolfssl_cleanup(void)
{
wolfSSL_Cleanup();
#ifdef OPENSSL_EXTRA
@@ -915,8 +926,8 @@ static void Curl_wolfssl_cleanup(void)
}
-static bool Curl_wolfssl_data_pending(const struct connectdata *conn,
- int connindex)
+static bool wolfssl_data_pending(const struct connectdata *conn,
+ int connindex)
{
const struct ssl_connect_data *connssl = &conn->ssl[connindex];
struct ssl_backend_data *backend = connssl->backend;
@@ -931,12 +942,15 @@ static bool Curl_wolfssl_data_pending(const struct connectdata *conn,
* This function is called to shut down the SSL layer but keep the
* socket open (CCC - Clear Command Channel)
*/
-static int Curl_wolfssl_shutdown(struct connectdata *conn, int sockindex)
+static int wolfssl_shutdown(struct Curl_easy *data, struct connectdata *conn,
+ int sockindex)
{
int retval = 0;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
struct ssl_backend_data *backend = connssl->backend;
+ (void) data;
+
if(backend->handle) {
SSL_free(backend->handle);
backend->handle = NULL;
@@ -946,13 +960,13 @@ static int Curl_wolfssl_shutdown(struct connectdata *conn, int sockindex)
static CURLcode
-wolfssl_connect_common(struct connectdata *conn,
+wolfssl_connect_common(struct Curl_easy *data,
+ struct connectdata *conn,
int sockindex,
bool nonblocking,
bool *done)
{
CURLcode result;
- struct Curl_easy *data = conn->data;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
curl_socket_t sockfd = conn->sock[sockindex];
int what;
@@ -973,7 +987,7 @@ wolfssl_connect_common(struct connectdata *conn,
return CURLE_OPERATION_TIMEDOUT;
}
- result = wolfssl_connect_step1(conn, sockindex);
+ result = wolfssl_connect_step1(data, conn, sockindex);
if(result)
return result;
}
@@ -1028,7 +1042,7 @@ wolfssl_connect_common(struct connectdata *conn,
* ensuring that a client using select() or epoll() will always
* have a valid fdset to wait on.
*/
- result = wolfssl_connect_step2(conn, sockindex);
+ result = wolfssl_connect_step2(data, conn, sockindex);
if(result || (nonblocking &&
(ssl_connect_2 == connssl->connecting_state ||
ssl_connect_2_reading == connssl->connecting_state ||
@@ -1037,7 +1051,7 @@ wolfssl_connect_common(struct connectdata *conn,
} /* repeat step2 until all transactions are done. */
if(ssl_connect_3 == connssl->connecting_state) {
- result = wolfssl_connect_step3(conn, sockindex);
+ result = wolfssl_connect_step3(data, conn, sockindex);
if(result)
return result;
}
@@ -1058,19 +1072,21 @@ wolfssl_connect_common(struct connectdata *conn,
}
-static CURLcode Curl_wolfssl_connect_nonblocking(struct connectdata *conn,
- int sockindex, bool *done)
+static CURLcode wolfssl_connect_nonblocking(struct Curl_easy *data,
+ struct connectdata *conn,
+ int sockindex, bool *done)
{
- return wolfssl_connect_common(conn, sockindex, TRUE, done);
+ return wolfssl_connect_common(data, conn, sockindex, TRUE, done);
}
-static CURLcode Curl_wolfssl_connect(struct connectdata *conn, int sockindex)
+static CURLcode wolfssl_connect(struct Curl_easy *data,
+ struct connectdata *conn, int sockindex)
{
CURLcode result;
bool done = FALSE;
- result = wolfssl_connect_common(conn, sockindex, FALSE, &done);
+ result = wolfssl_connect_common(data, conn, sockindex, FALSE, &done);
if(result)
return result;
@@ -1079,8 +1095,8 @@ static CURLcode Curl_wolfssl_connect(struct connectdata *conn, int sockindex)
return CURLE_OK;
}
-static CURLcode Curl_wolfssl_random(struct Curl_easy *data,
- unsigned char *entropy, size_t length)
+static CURLcode wolfssl_random(struct Curl_easy *data,
+ unsigned char *entropy, size_t length)
{
WC_RNG rng;
(void)data;
@@ -1095,10 +1111,10 @@ static CURLcode Curl_wolfssl_random(struct Curl_easy *data,
return CURLE_OK;
}
-static CURLcode Curl_wolfssl_sha256sum(const unsigned char *tmp, /* input */
- size_t tmplen,
- unsigned char *sha256sum /* output */,
- size_t unused)
+static CURLcode wolfssl_sha256sum(const unsigned char *tmp, /* input */
+ size_t tmplen,
+ unsigned char *sha256sum /* output */,
+ size_t unused)
{
wc_Sha256 SHA256pw;
(void)unused;
@@ -1108,7 +1124,7 @@ static CURLcode Curl_wolfssl_sha256sum(const unsigned char *tmp, /* input */
return CURLE_OK;
}
-static void *Curl_wolfssl_get_internals(struct ssl_connect_data *connssl,
+static void *wolfssl_get_internals(struct ssl_connect_data *connssl,
CURLINFO info UNUSED_PARAM)
{
struct ssl_backend_data *backend = connssl->backend;
@@ -1126,26 +1142,25 @@ const struct Curl_ssl Curl_ssl_wolfssl = {
sizeof(struct ssl_backend_data),
- Curl_wolfssl_init, /* init */
- Curl_wolfssl_cleanup, /* cleanup */
- Curl_wolfssl_version, /* version */
+ wolfssl_init, /* init */
+ wolfssl_cleanup, /* cleanup */
+ wolfssl_version, /* version */
Curl_none_check_cxn, /* check_cxn */
- Curl_wolfssl_shutdown, /* shutdown */
- Curl_wolfssl_data_pending, /* data_pending */
- Curl_wolfssl_random, /* random */
+ wolfssl_shutdown, /* shutdown */
+ wolfssl_data_pending, /* data_pending */
+ wolfssl_random, /* random */
Curl_none_cert_status_request, /* cert_status_request */
- Curl_wolfssl_connect, /* connect */
- Curl_wolfssl_connect_nonblocking, /* connect_nonblocking */
- Curl_wolfssl_get_internals, /* get_internals */
- Curl_wolfssl_close, /* close_one */
+ wolfssl_connect, /* connect */
+ wolfssl_connect_nonblocking, /* connect_nonblocking */
+ wolfssl_get_internals, /* get_internals */
+ wolfssl_close, /* close_one */
Curl_none_close_all, /* close_all */
- Curl_wolfssl_session_free, /* session_free */
+ wolfssl_session_free, /* session_free */
Curl_none_set_engine, /* set_engine */
Curl_none_set_engine_default, /* set_engine_default */
Curl_none_engines_list, /* engines_list */
Curl_none_false_start, /* false_start */
- Curl_none_md5sum, /* md5sum */
- Curl_wolfssl_sha256sum /* sha256sum */
+ wolfssl_sha256sum /* sha256sum */
};
#endif
diff --git a/Utilities/cmcurl/lib/vtls/wolfssl.h b/Utilities/cmcurl/lib/vtls/wolfssl.h
index 2b9673c0f..d411e6913 100644
--- a/Utilities/cmcurl/lib/vtls/wolfssl.h
+++ b/Utilities/cmcurl/lib/vtls/wolfssl.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
diff --git a/Utilities/cmcurl/lib/warnless.c b/Utilities/cmcurl/lib/warnless.c
index cfd5e8e14..c0764c42d 100644
--- a/Utilities/cmcurl/lib/warnless.c
+++ b/Utilities/cmcurl/lib/warnless.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -156,25 +156,6 @@ unsigned char curlx_ultouc(unsigned long ulnum)
}
/*
-** unsigned long to signed int
-*/
-
-int curlx_ultosi(unsigned long ulnum)
-{
-#ifdef __INTEL_COMPILER
-# pragma warning(push)
-# pragma warning(disable:810) /* conversion may lose significant bits */
-#endif
-
- DEBUGASSERT(ulnum <= (unsigned long) CURL_MASK_SINT);
- return (int)(ulnum & (unsigned long) CURL_MASK_SINT);
-
-#ifdef __INTEL_COMPILER
-# pragma warning(pop)
-#endif
-}
-
-/*
** unsigned size_t to signed curl_off_t
*/
diff --git a/Utilities/cmcurl/lib/warnless.h b/Utilities/cmcurl/lib/warnless.h
index ab78f9448..2c619bf81 100644
--- a/Utilities/cmcurl/lib/warnless.h
+++ b/Utilities/cmcurl/lib/warnless.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -33,8 +33,6 @@ unsigned short curlx_ultous(unsigned long ulnum);
unsigned char curlx_ultouc(unsigned long ulnum);
-int curlx_ultosi(unsigned long ulnum);
-
int curlx_uztosi(size_t uznum);
curl_off_t curlx_uztoso(size_t uznum);
diff --git a/Utilities/cmcurl/lib/wildcard.c b/Utilities/cmcurl/lib/wildcard.c
index e94d3c544..105bcce4e 100644
--- a/Utilities/cmcurl/lib/wildcard.c
+++ b/Utilities/cmcurl/lib/wildcard.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
diff --git a/Utilities/cmcurl/lib/wildcard.h b/Utilities/cmcurl/lib/wildcard.h
index 306c8c99f..081be9ed9 100644
--- a/Utilities/cmcurl/lib/wildcard.h
+++ b/Utilities/cmcurl/lib/wildcard.h
@@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2010 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2010 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -39,18 +39,18 @@ typedef enum {
CURLWC_ERROR, /* error cases */
CURLWC_DONE /* if is wildcard->state == CURLWC_DONE wildcard loop
will end */
-} curl_wildcard_states;
+} wildcard_states;
-typedef void (*curl_wildcard_dtor)(void *ptr);
+typedef void (*wildcard_dtor)(void *ptr);
/* struct keeping information about wildcard download process */
struct WildcardData {
- curl_wildcard_states state;
+ wildcard_states state;
char *path; /* path to the directory, where we trying wildcard-match */
char *pattern; /* wildcard pattern */
- struct curl_llist filelist; /* llist with struct Curl_fileinfo */
+ struct Curl_llist filelist; /* llist with struct Curl_fileinfo */
void *protdata; /* pointer to protocol specific temporary data */
- curl_wildcard_dtor dtor;
+ wildcard_dtor dtor;
void *customptr; /* for CURLOPT_CHUNK_DATA pointer */
};
diff --git a/Utilities/cmcurl/lib/x509asn1.c b/Utilities/cmcurl/lib/x509asn1.c
index 52747d57d..f29aa05b8 100644
--- a/Utilities/cmcurl/lib/x509asn1.c
+++ b/Utilities/cmcurl/lib/x509asn1.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -945,13 +945,12 @@ static void do_pubkey(struct Curl_easy *data, int certnum,
}
}
-CURLcode Curl_extract_certinfo(struct connectdata *conn,
+CURLcode Curl_extract_certinfo(struct Curl_easy *data,
int certnum,
const char *beg,
const char *end)
{
struct Curl_X509certificate cert;
- struct Curl_easy *data = conn->data;
struct Curl_asn1Element param;
const char *ccp;
char *cp1;
@@ -1132,10 +1131,9 @@ static const char *checkOID(const char *beg, const char *end,
return matched? ccp: NULL;
}
-CURLcode Curl_verifyhost(struct connectdata *conn,
+CURLcode Curl_verifyhost(struct Curl_easy *data, struct connectdata *conn,
const char *beg, const char *end)
{
- struct Curl_easy *data = conn->data;
struct Curl_X509certificate cert;
struct Curl_asn1Element dn;
struct Curl_asn1Element elem;
diff --git a/Utilities/cmcurl/lib/x509asn1.h b/Utilities/cmcurl/lib/x509asn1.h
index 0b7fb8817..326e32d58 100644
--- a/Utilities/cmcurl/lib/x509asn1.h
+++ b/Utilities/cmcurl/lib/x509asn1.h
@@ -8,11 +8,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * 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
@@ -125,9 +125,9 @@ const char *Curl_ASN1tostr(struct Curl_asn1Element *elem, int type);
const char *Curl_DNtostr(struct Curl_asn1Element *dn);
int Curl_parseX509(struct Curl_X509certificate *cert,
const char *beg, const char *end);
-CURLcode Curl_extract_certinfo(struct connectdata *conn, int certnum,
+CURLcode Curl_extract_certinfo(struct Curl_easy *data, int certnum,
const char *beg, const char *end);
-CURLcode Curl_verifyhost(struct connectdata *conn,
+CURLcode Curl_verifyhost(struct Curl_easy *data, struct connectdata *conn,
const char *beg, const char *end);
#endif /* USE_GSKIT or USE_NSS or USE_GNUTLS or USE_WOLFSSL or USE_SCHANNEL */
#endif /* HEADER_CURL_X509ASN1_H */
diff --git a/Utilities/cmexpat/CMakeLists.txt b/Utilities/cmexpat/CMakeLists.txt
index cf315563d..b8dc4e8cc 100644
--- a/Utilities/cmexpat/CMakeLists.txt
+++ b/Utilities/cmexpat/CMakeLists.txt
@@ -1,6 +1,6 @@
# Disable warnings to avoid changing 3rd party code.
IF(CMAKE_C_COMPILER_ID MATCHES
- "^(GNU|Clang|AppleClang|XLClang|XL|VisualAge|SunPro|HP|Intel)$")
+ "^(GNU|Clang|AppleClang|XLClang|XL|VisualAge|SunPro|HP|Intel|IntelLLVM)$")
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -w")
ELSEIF(CMAKE_C_COMPILER_ID STREQUAL "PathScale")
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -woffall")
diff --git a/Utilities/cmjsoncpp/CMakeLists.txt b/Utilities/cmjsoncpp/CMakeLists.txt
index 764be8d55..74e998823 100644
--- a/Utilities/cmjsoncpp/CMakeLists.txt
+++ b/Utilities/cmjsoncpp/CMakeLists.txt
@@ -2,7 +2,7 @@ project(JsonCpp CXX)
# Disable warnings to avoid changing 3rd party code.
if(CMAKE_CXX_COMPILER_ID MATCHES
- "^(GNU|Clang|AppleClang|XLClang|XL|VisualAge|SunPro|HP|Intel)$")
+ "^(GNU|Clang|AppleClang|XLClang|XL|VisualAge|SunPro|HP|Intel|IntelLLVM)$")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -w")
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "PathScale")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -woffall")
diff --git a/Utilities/cmjsoncpp/src/lib_json/json_reader.cpp b/Utilities/cmjsoncpp/src/lib_json/json_reader.cpp
index 6eeba0e65..8362fc4cb 100644
--- a/Utilities/cmjsoncpp/src/lib_json/json_reader.cpp
+++ b/Utilities/cmjsoncpp/src/lib_json/json_reader.cpp
@@ -2,74 +2,88 @@
// Copyright (C) 2016 InfoTeCS JSC. All rights reserved.
// Distributed under MIT license, or public domain if desired and
// recognized in your jurisdiction.
-// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
+// See file LICENSE for detail or copy at
+// http://jsoncpp.sourceforge.net/LICENSE
#if !defined(JSON_IS_AMALGAMATION)
-#include <json/assertions.h>
-#include <json/reader.h>
-#include <json/value.h>
-#include "json_tool.h"
+# include <json/assertions.h>
+# include <json/reader.h>
+# include <json/value.h>
+
+# include "json_tool.h"
#endif // if !defined(JSON_IS_AMALGAMATION)
-#include <utility>
-#include <stdio.h>
-#include <assert.h>
-#include <string.h>
#include <istream>
-#include <sstream>
+#include <limits>
#include <memory>
#include <set>
-#include <limits>
+#include <sstream>
+#include <utility>
+
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
#if defined(_MSC_VER)
-#if !defined(WINCE) && defined(__STDC_SECURE_LIB__) && _MSC_VER >= 1500 // VC++ 9.0 and above
-#define snprintf sprintf_s
-#elif _MSC_VER >= 1900 // VC++ 14.0 and above
-#define snprintf std::snprintf
-#else
-#define snprintf _snprintf
-#endif
+# if !defined(WINCE) && defined(__STDC_SECURE_LIB__) && \
+ _MSC_VER >= 1500 // VC++ 9.0 and above
+# define snprintf sprintf_s
+# elif _MSC_VER >= 1900 // VC++ 14.0 and above
+# define snprintf std::snprintf
+# else
+# define snprintf _snprintf
+# endif
#elif defined(__ANDROID__) || defined(__QNXNTO__)
-#define snprintf snprintf
+# define snprintf snprintf
#elif __cplusplus >= 201103L
-#if !defined(__MINGW32__) && !defined(__CYGWIN__)
-#define snprintf std::snprintf
-#endif
+# if !defined(__MINGW32__) && !defined(__CYGWIN__)
+# define snprintf std::snprintf
+# endif
#endif
#if defined(__QNXNTO__)
-#define sscanf std::sscanf
+# define sscanf std::sscanf
#endif
#if defined(_MSC_VER) && _MSC_VER >= 1400 // VC++ 8.0
// Disable warning about strdup being deprecated.
-#pragma warning(disable : 4996)
+# pragma warning(disable : 4996)
#endif
-// Define JSONCPP_DEPRECATED_STACK_LIMIT as an appropriate integer at compile time to change the stack limit
+// Define JSONCPP_DEPRECATED_STACK_LIMIT as an appropriate integer at compile
+// time to change the stack limit
#if !defined(JSONCPP_DEPRECATED_STACK_LIMIT)
-#define JSONCPP_DEPRECATED_STACK_LIMIT 1000
+# define JSONCPP_DEPRECATED_STACK_LIMIT 1000
#endif
-static size_t const stackLimit_g = JSONCPP_DEPRECATED_STACK_LIMIT; // see readValue()
+static size_t const stackLimit_g =
+ JSONCPP_DEPRECATED_STACK_LIMIT; // see readValue()
namespace Json {
#if __cplusplus >= 201103L || (defined(_CPPLIB_VER) && _CPPLIB_VER >= 520)
typedef std::unique_ptr<CharReader> CharReaderPtr;
#else
-typedef std::auto_ptr<CharReader> CharReaderPtr;
+typedef std::auto_ptr<CharReader> CharReaderPtr;
#endif
// Implementation of class Features
// ////////////////////////////////
Features::Features()
- : allowComments_(true), strictRoot_(false),
- allowDroppedNullPlaceholders_(false), allowNumericKeys_(false) {}
+ : allowComments_(true)
+ , strictRoot_(false)
+ , allowDroppedNullPlaceholders_(false)
+ , allowNumericKeys_(false)
+{
+}
-Features Features::all() { return Features(); }
+Features Features::all()
+{
+ return Features();
+}
-Features Features::strictMode() {
+Features Features::strictMode()
+{
Features features;
features.allowComments_ = false;
features.strictRoot_ = true;
@@ -81,7 +95,8 @@ Features Features::strictMode() {
// Implementation of class Reader
// ////////////////////////////////
-bool Reader::containsNewLine(Reader::Location begin, Reader::Location end) {
+bool Reader::containsNewLine(Reader::Location begin, Reader::Location end)
+{
for (; begin < end; ++begin)
if (*begin == '\n' || *begin == '\r')
return true;
@@ -92,24 +107,44 @@ bool Reader::containsNewLine(Reader::Location begin, Reader::Location end) {
// //////////////////////////////////////////////////////////////////
Reader::Reader()
- : errors_(), document_(), begin_(), end_(), current_(), lastValueEnd_(),
- lastValue_(), commentsBefore_(), features_(Features::all()),
- collectComments_() {}
+ : errors_()
+ , document_()
+ , begin_()
+ , end_()
+ , current_()
+ , lastValueEnd_()
+ , lastValue_()
+ , commentsBefore_()
+ , features_(Features::all())
+ , collectComments_()
+{
+}
Reader::Reader(const Features& features)
- : errors_(), document_(), begin_(), end_(), current_(), lastValueEnd_(),
- lastValue_(), commentsBefore_(), features_(features), collectComments_() {
+ : errors_()
+ , document_()
+ , begin_()
+ , end_()
+ , current_()
+ , lastValueEnd_()
+ , lastValue_()
+ , commentsBefore_()
+ , features_(features)
+ , collectComments_()
+{
}
-bool
-Reader::parse(const std::string& document, Value& root, bool collectComments) {
- document_.assign(document.begin(), document.end());
- const char* begin = document_.c_str();
- const char* end = begin + document_.length();
- return parse(begin, end, root, collectComments);
+bool Reader::parse(const std::string& document, Value& root,
+ bool collectComments)
+{
+ this->document_.assign(document.begin(), document.end());
+ const char* begin = this->document_.c_str();
+ const char* end = begin + this->document_.length();
+ return this->parse(begin, end, root, collectComments);
}
-bool Reader::parse(std::istream& sin, Value& root, bool collectComments) {
+bool Reader::parse(std::istream& sin, Value& root, bool collectComments)
+{
// std::istream_iterator<char> begin(sin);
// std::istream_iterator<char> end;
// Those would allow streamed input from a file, if parse() were a
@@ -119,257 +154,263 @@ bool Reader::parse(std::istream& sin, Value& root, bool collectComments) {
// create an extra copy.
JSONCPP_STRING doc;
std::getline(sin, doc, (char)EOF);
- return parse(doc.data(), doc.data() + doc.size(), root, collectComments);
+ return this->parse(doc.data(), doc.data() + doc.size(), root,
+ collectComments);
}
-bool Reader::parse(const char* beginDoc,
- const char* endDoc,
- Value& root,
- bool collectComments) {
- if (!features_.allowComments_) {
+bool Reader::parse(const char* beginDoc, const char* endDoc, Value& root,
+ bool collectComments)
+{
+ if (!this->features_.allowComments_) {
collectComments = false;
}
- begin_ = beginDoc;
- end_ = endDoc;
- collectComments_ = collectComments;
- current_ = begin_;
- lastValueEnd_ = 0;
- lastValue_ = 0;
- commentsBefore_.clear();
- errors_.clear();
- while (!nodes_.empty())
- nodes_.pop();
- nodes_.push(&root);
-
- bool successful = readValue();
+ this->begin_ = beginDoc;
+ this->end_ = endDoc;
+ this->collectComments_ = collectComments;
+ this->current_ = this->begin_;
+ this->lastValueEnd_ = 0;
+ this->lastValue_ = 0;
+ this->commentsBefore_.clear();
+ this->errors_.clear();
+ while (!this->nodes_.empty())
+ this->nodes_.pop();
+ this->nodes_.push(&root);
+
+ bool successful = this->readValue();
Token token;
- skipCommentTokens(token);
- if (collectComments_ && !commentsBefore_.empty())
- root.setComment(commentsBefore_, commentAfter);
- if (features_.strictRoot_) {
+ this->skipCommentTokens(token);
+ if (this->collectComments_ && !this->commentsBefore_.empty())
+ root.setComment(this->commentsBefore_, commentAfter);
+ if (this->features_.strictRoot_) {
if (!root.isArray() && !root.isObject()) {
- // Set error location to start of doc, ideally should be first token found
- // in doc
+ // Set error location to start of doc, ideally should be first token
+ // found in doc
token.type_ = tokenError;
token.start_ = beginDoc;
token.end_ = endDoc;
- addError(
- "A valid JSON document must be either an array or an object value.",
- token);
+ this->addError(
+ "A valid JSON document must be either an array or an object value.",
+ token);
return false;
}
}
return successful;
}
-bool Reader::readValue() {
+bool Reader::readValue()
+{
// readValue() may call itself only if it calls readObject() or ReadArray().
- // These methods execute nodes_.push() just before and nodes_.pop)() just after calling readValue().
- // parse() executes one nodes_.push(), so > instead of >=.
- if (nodes_.size() > stackLimit_g) throwRuntimeError("Exceeded stackLimit in readValue().");
+ // These methods execute nodes_.push() just before and nodes_.pop)() just
+ // after calling readValue(). parse() executes one nodes_.push(), so >
+ // instead of >=.
+ if (this->nodes_.size() > stackLimit_g)
+ throwRuntimeError("Exceeded stackLimit in readValue().");
Token token;
- skipCommentTokens(token);
+ this->skipCommentTokens(token);
bool successful = true;
- if (collectComments_ && !commentsBefore_.empty()) {
- currentValue().setComment(commentsBefore_, commentBefore);
- commentsBefore_.clear();
+ if (this->collectComments_ && !this->commentsBefore_.empty()) {
+ this->currentValue().setComment(this->commentsBefore_, commentBefore);
+ this->commentsBefore_.clear();
}
switch (token.type_) {
- case tokenObjectBegin:
- successful = readObject(token);
- currentValue().setOffsetLimit(current_ - begin_);
- break;
- case tokenArrayBegin:
- successful = readArray(token);
- currentValue().setOffsetLimit(current_ - begin_);
- break;
- case tokenNumber:
- successful = decodeNumber(token);
- break;
- case tokenString:
- successful = decodeString(token);
- break;
- case tokenTrue:
- {
- Value v(true);
- currentValue().swapPayload(v);
- currentValue().setOffsetStart(token.start_ - begin_);
- currentValue().setOffsetLimit(token.end_ - begin_);
- }
- break;
- case tokenFalse:
- {
- Value v(false);
- currentValue().swapPayload(v);
- currentValue().setOffsetStart(token.start_ - begin_);
- currentValue().setOffsetLimit(token.end_ - begin_);
- }
- break;
- case tokenNull:
- {
- Value v;
- currentValue().swapPayload(v);
- currentValue().setOffsetStart(token.start_ - begin_);
- currentValue().setOffsetLimit(token.end_ - begin_);
- }
- break;
- case tokenArraySeparator:
- case tokenObjectEnd:
- case tokenArrayEnd:
- if (features_.allowDroppedNullPlaceholders_) {
- // "Un-read" the current token and mark the current value as a null
- // token.
- current_--;
- Value v;
- currentValue().swapPayload(v);
- currentValue().setOffsetStart(current_ - begin_ - 1);
- currentValue().setOffsetLimit(current_ - begin_);
+ case tokenObjectBegin:
+ successful = this->readObject(token);
+ this->currentValue().setOffsetLimit(this->current_ - this->begin_);
+ break;
+ case tokenArrayBegin:
+ successful = this->readArray(token);
+ this->currentValue().setOffsetLimit(this->current_ - this->begin_);
+ break;
+ case tokenNumber:
+ successful = this->decodeNumber(token);
break;
- } // Else, fall through...
- default:
- currentValue().setOffsetStart(token.start_ - begin_);
- currentValue().setOffsetLimit(token.end_ - begin_);
- return addError("Syntax error: value, object or array expected.", token);
+ case tokenString:
+ successful = this->decodeString(token);
+ break;
+ case tokenTrue: {
+ Value v(true);
+ this->currentValue().swapPayload(v);
+ this->currentValue().setOffsetStart(token.start_ - this->begin_);
+ this->currentValue().setOffsetLimit(token.end_ - this->begin_);
+ } break;
+ case tokenFalse: {
+ Value v(false);
+ this->currentValue().swapPayload(v);
+ this->currentValue().setOffsetStart(token.start_ - this->begin_);
+ this->currentValue().setOffsetLimit(token.end_ - this->begin_);
+ } break;
+ case tokenNull: {
+ Value v;
+ this->currentValue().swapPayload(v);
+ this->currentValue().setOffsetStart(token.start_ - this->begin_);
+ this->currentValue().setOffsetLimit(token.end_ - this->begin_);
+ } break;
+ case tokenArraySeparator:
+ case tokenObjectEnd:
+ case tokenArrayEnd:
+ if (this->features_.allowDroppedNullPlaceholders_) {
+ // "Un-read" the current token and mark the current value as a null
+ // token.
+ this->current_--;
+ Value v;
+ this->currentValue().swapPayload(v);
+ this->currentValue().setOffsetStart(this->current_ - this->begin_ - 1);
+ this->currentValue().setOffsetLimit(this->current_ - this->begin_);
+ break;
+ } // Else, fall through...
+ default:
+ this->currentValue().setOffsetStart(token.start_ - this->begin_);
+ this->currentValue().setOffsetLimit(token.end_ - this->begin_);
+ return this->addError("Syntax error: value, object or array expected.",
+ token);
}
- if (collectComments_) {
- lastValueEnd_ = current_;
- lastValue_ = &currentValue();
+ if (this->collectComments_) {
+ this->lastValueEnd_ = this->current_;
+ this->lastValue_ = &this->currentValue();
}
return successful;
}
-void Reader::skipCommentTokens(Token& token) {
- if (features_.allowComments_) {
+void Reader::skipCommentTokens(Token& token)
+{
+ if (this->features_.allowComments_) {
do {
- readToken(token);
+ this->readToken(token);
} while (token.type_ == tokenComment);
} else {
- readToken(token);
+ this->readToken(token);
}
}
-bool Reader::readToken(Token& token) {
- skipSpaces();
- token.start_ = current_;
- Char c = getNextChar();
+bool Reader::readToken(Token& token)
+{
+ this->skipSpaces();
+ token.start_ = this->current_;
+ Char c = this->getNextChar();
bool ok = true;
switch (c) {
- case '{':
- token.type_ = tokenObjectBegin;
- break;
- case '}':
- token.type_ = tokenObjectEnd;
- break;
- case '[':
- token.type_ = tokenArrayBegin;
- break;
- case ']':
- token.type_ = tokenArrayEnd;
- break;
- case '"':
- token.type_ = tokenString;
- ok = readString();
- break;
- case '/':
- token.type_ = tokenComment;
- ok = readComment();
- break;
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- case '-':
- token.type_ = tokenNumber;
- readNumber();
- break;
- case 't':
- token.type_ = tokenTrue;
- ok = match("rue", 3);
- break;
- case 'f':
- token.type_ = tokenFalse;
- ok = match("alse", 4);
- break;
- case 'n':
- token.type_ = tokenNull;
- ok = match("ull", 3);
- break;
- case ',':
- token.type_ = tokenArraySeparator;
- break;
- case ':':
- token.type_ = tokenMemberSeparator;
- break;
- case 0:
- token.type_ = tokenEndOfStream;
- break;
- default:
- ok = false;
- break;
+ case '{':
+ token.type_ = tokenObjectBegin;
+ break;
+ case '}':
+ token.type_ = tokenObjectEnd;
+ break;
+ case '[':
+ token.type_ = tokenArrayBegin;
+ break;
+ case ']':
+ token.type_ = tokenArrayEnd;
+ break;
+ case '"':
+ token.type_ = tokenString;
+ ok = this->readString();
+ break;
+ case '/':
+ token.type_ = tokenComment;
+ ok = this->readComment();
+ break;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ case '-':
+ token.type_ = tokenNumber;
+ this->readNumber();
+ break;
+ case 't':
+ token.type_ = tokenTrue;
+ ok = this->match("rue", 3);
+ break;
+ case 'f':
+ token.type_ = tokenFalse;
+ ok = this->match("alse", 4);
+ break;
+ case 'n':
+ token.type_ = tokenNull;
+ ok = this->match("ull", 3);
+ break;
+ case ',':
+ token.type_ = tokenArraySeparator;
+ break;
+ case ':':
+ token.type_ = tokenMemberSeparator;
+ break;
+ case 0:
+ token.type_ = tokenEndOfStream;
+ break;
+ default:
+ ok = false;
+ break;
}
if (!ok)
token.type_ = tokenError;
- token.end_ = current_;
+ token.end_ = this->current_;
return true;
}
-void Reader::skipSpaces() {
- while (current_ != end_) {
- Char c = *current_;
+void Reader::skipSpaces()
+{
+ while (this->current_ != this->end_) {
+ Char c = *this->current_;
if (c == ' ' || c == '\t' || c == '\r' || c == '\n')
- ++current_;
+ ++this->current_;
else
break;
}
}
-bool Reader::match(Location pattern, int patternLength) {
- if (end_ - current_ < patternLength)
+bool Reader::match(Location pattern, int patternLength)
+{
+ if (this->end_ - this->current_ < patternLength)
return false;
int index = patternLength;
while (index--)
- if (current_[index] != pattern[index])
+ if (this->current_[index] != pattern[index])
return false;
- current_ += patternLength;
+ this->current_ += patternLength;
return true;
}
-bool Reader::readComment() {
- Location commentBegin = current_ - 1;
- Char c = getNextChar();
+bool Reader::readComment()
+{
+ Location commentBegin = this->current_ - 1;
+ Char c = this->getNextChar();
bool successful = false;
if (c == '*')
- successful = readCStyleComment();
+ successful = this->readCStyleComment();
else if (c == '/')
- successful = readCppStyleComment();
+ successful = this->readCppStyleComment();
if (!successful)
return false;
- if (collectComments_) {
+ if (this->collectComments_) {
CommentPlacement placement = commentBefore;
- if (lastValueEnd_ && !containsNewLine(lastValueEnd_, commentBegin)) {
- if (c != '*' || !containsNewLine(commentBegin, current_))
+ if (this->lastValueEnd_ &&
+ !containsNewLine(this->lastValueEnd_, commentBegin)) {
+ if (c != '*' || !containsNewLine(commentBegin, this->current_))
placement = commentAfterOnSameLine;
}
- addComment(commentBegin, current_, placement);
+ this->addComment(commentBegin, this->current_, placement);
}
return true;
}
-JSONCPP_STRING Reader::normalizeEOL(Reader::Location begin, Reader::Location end) {
+JSONCPP_STRING Reader::normalizeEOL(Reader::Location begin,
+ Reader::Location end)
+{
JSONCPP_STRING normalized;
normalized.reserve(static_cast<size_t>(end - begin));
Reader::Location current = begin;
@@ -377,8 +418,8 @@ JSONCPP_STRING Reader::normalizeEOL(Reader::Location begin, Reader::Location end
char c = *current++;
if (c == '\r') {
if (current != end && *current == '\n')
- // convert dos EOL
- ++current;
+ // convert dos EOL
+ ++current;
// convert Mac EOL
normalized += '\n';
} else {
@@ -388,36 +429,39 @@ JSONCPP_STRING Reader::normalizeEOL(Reader::Location begin, Reader::Location end
return normalized;
}
-void
-Reader::addComment(Location begin, Location end, CommentPlacement placement) {
- assert(collectComments_);
+void Reader::addComment(Location begin, Location end,
+ CommentPlacement placement)
+{
+ assert(this->collectComments_);
const JSONCPP_STRING& normalized = normalizeEOL(begin, end);
if (placement == commentAfterOnSameLine) {
- assert(lastValue_ != 0);
- lastValue_->setComment(normalized, placement);
+ assert(this->lastValue_ != 0);
+ this->lastValue_->setComment(normalized, placement);
} else {
- commentsBefore_ += normalized;
+ this->commentsBefore_ += normalized;
}
}
-bool Reader::readCStyleComment() {
- while ((current_ + 1) < end_) {
- Char c = getNextChar();
- if (c == '*' && *current_ == '/')
+bool Reader::readCStyleComment()
+{
+ while ((this->current_ + 1) < this->end_) {
+ Char c = this->getNextChar();
+ if (c == '*' && *this->current_ == '/')
break;
}
- return getNextChar() == '/';
+ return this->getNextChar() == '/';
}
-bool Reader::readCppStyleComment() {
- while (current_ != end_) {
- Char c = getNextChar();
+bool Reader::readCppStyleComment()
+{
+ while (this->current_ != this->end_) {
+ Char c = this->getNextChar();
if (c == '\n')
break;
if (c == '\r') {
// Consume DOS EOL. It will be normalized in addComment.
- if (current_ != end_ && *current_ == '\n')
- getNextChar();
+ if (this->current_ != this->end_ && *this->current_ == '\n')
+ this->getNextChar();
// Break on Moc OS 9 EOL.
break;
}
@@ -425,127 +469,132 @@ bool Reader::readCppStyleComment() {
return true;
}
-void Reader::readNumber() {
- const char *p = current_;
+void Reader::readNumber()
+{
+ const char* p = this->current_;
char c = '0'; // stopgap for already consumed character
// integral part
while (c >= '0' && c <= '9')
- c = (current_ = p) < end_ ? *p++ : '\0';
+ c = (this->current_ = p) < this->end_ ? *p++ : '\0';
// fractional part
if (c == '.') {
- c = (current_ = p) < end_ ? *p++ : '\0';
+ c = (this->current_ = p) < this->end_ ? *p++ : '\0';
while (c >= '0' && c <= '9')
- c = (current_ = p) < end_ ? *p++ : '\0';
+ c = (this->current_ = p) < this->end_ ? *p++ : '\0';
}
// exponential part
if (c == 'e' || c == 'E') {
- c = (current_ = p) < end_ ? *p++ : '\0';
+ c = (this->current_ = p) < this->end_ ? *p++ : '\0';
if (c == '+' || c == '-')
- c = (current_ = p) < end_ ? *p++ : '\0';
+ c = (this->current_ = p) < this->end_ ? *p++ : '\0';
while (c >= '0' && c <= '9')
- c = (current_ = p) < end_ ? *p++ : '\0';
+ c = (this->current_ = p) < this->end_ ? *p++ : '\0';
}
}
-bool Reader::readString() {
+bool Reader::readString()
+{
Char c = '\0';
- while (current_ != end_) {
- c = getNextChar();
+ while (this->current_ != this->end_) {
+ c = this->getNextChar();
if (c == '\\')
- getNextChar();
+ this->getNextChar();
else if (c == '"')
break;
}
return c == '"';
}
-bool Reader::readObject(Token& tokenStart) {
+bool Reader::readObject(Token& tokenStart)
+{
Token tokenName;
JSONCPP_STRING name;
Value init(objectValue);
- currentValue().swapPayload(init);
- currentValue().setOffsetStart(tokenStart.start_ - begin_);
- while (readToken(tokenName)) {
+ this->currentValue().swapPayload(init);
+ this->currentValue().setOffsetStart(tokenStart.start_ - this->begin_);
+ while (this->readToken(tokenName)) {
bool initialTokenOk = true;
while (tokenName.type_ == tokenComment && initialTokenOk)
- initialTokenOk = readToken(tokenName);
+ initialTokenOk = this->readToken(tokenName);
if (!initialTokenOk)
break;
if (tokenName.type_ == tokenObjectEnd && name.empty()) // empty object
return true;
name.clear();
if (tokenName.type_ == tokenString) {
- if (!decodeString(tokenName, name))
- return recoverFromError(tokenObjectEnd);
- } else if (tokenName.type_ == tokenNumber && features_.allowNumericKeys_) {
+ if (!this->decodeString(tokenName, name))
+ return this->recoverFromError(tokenObjectEnd);
+ } else if (tokenName.type_ == tokenNumber &&
+ this->features_.allowNumericKeys_) {
Value numberName;
- if (!decodeNumber(tokenName, numberName))
- return recoverFromError(tokenObjectEnd);
+ if (!this->decodeNumber(tokenName, numberName))
+ return this->recoverFromError(tokenObjectEnd);
name = JSONCPP_STRING(numberName.asCString());
} else {
break;
}
Token colon;
- if (!readToken(colon) || colon.type_ != tokenMemberSeparator) {
- return addErrorAndRecover(
- "Missing ':' after object member name", colon, tokenObjectEnd);
+ if (!this->readToken(colon) || colon.type_ != tokenMemberSeparator) {
+ return this->addErrorAndRecover("Missing ':' after object member name",
+ colon, tokenObjectEnd);
}
- Value& value = currentValue()[name];
- nodes_.push(&value);
- bool ok = readValue();
- nodes_.pop();
+ Value& value = this->currentValue()[name];
+ this->nodes_.push(&value);
+ bool ok = this->readValue();
+ this->nodes_.pop();
if (!ok) // error already set
- return recoverFromError(tokenObjectEnd);
+ return this->recoverFromError(tokenObjectEnd);
Token comma;
- if (!readToken(comma) ||
+ if (!this->readToken(comma) ||
(comma.type_ != tokenObjectEnd && comma.type_ != tokenArraySeparator &&
comma.type_ != tokenComment)) {
- return addErrorAndRecover(
- "Missing ',' or '}' in object declaration", comma, tokenObjectEnd);
+ return this->addErrorAndRecover(
+ "Missing ',' or '}' in object declaration", comma, tokenObjectEnd);
}
bool finalizeTokenOk = true;
while (comma.type_ == tokenComment && finalizeTokenOk)
- finalizeTokenOk = readToken(comma);
+ finalizeTokenOk = this->readToken(comma);
if (comma.type_ == tokenObjectEnd)
return true;
}
- return addErrorAndRecover(
- "Missing '}' or object member name", tokenName, tokenObjectEnd);
+ return this->addErrorAndRecover("Missing '}' or object member name",
+ tokenName, tokenObjectEnd);
}
-bool Reader::readArray(Token& tokenStart) {
+bool Reader::readArray(Token& tokenStart)
+{
Value init(arrayValue);
- currentValue().swapPayload(init);
- currentValue().setOffsetStart(tokenStart.start_ - begin_);
- skipSpaces();
- if (current_ != end_ && *current_ == ']') // empty array
+ this->currentValue().swapPayload(init);
+ this->currentValue().setOffsetStart(tokenStart.start_ - this->begin_);
+ this->skipSpaces();
+ if (this->current_ != this->end_ && *this->current_ == ']') // empty array
{
Token endArray;
- readToken(endArray);
+ this->readToken(endArray);
return true;
}
int index = 0;
for (;;) {
- Value& value = currentValue()[index++];
- nodes_.push(&value);
- bool ok = readValue();
- nodes_.pop();
+ Value& value = this->currentValue()[index++];
+ this->nodes_.push(&value);
+ bool ok = this->readValue();
+ this->nodes_.pop();
if (!ok) // error already set
- return recoverFromError(tokenArrayEnd);
+ return this->recoverFromError(tokenArrayEnd);
Token token;
// Accept Comment after last item in the array.
- ok = readToken(token);
+ ok = this->readToken(token);
while (token.type_ == tokenComment && ok) {
- ok = readToken(token);
+ ok = this->readToken(token);
}
bool badTokenType =
- (token.type_ != tokenArraySeparator && token.type_ != tokenArrayEnd);
+ (token.type_ != tokenArraySeparator && token.type_ != tokenArrayEnd);
if (!ok || badTokenType) {
- return addErrorAndRecover(
- "Missing ',' or ']' in array declaration", token, tokenArrayEnd);
+ return this->addErrorAndRecover(
+ "Missing ',' or ']' in array declaration", token, tokenArrayEnd);
}
if (token.type_ == tokenArrayEnd)
break;
@@ -553,17 +602,19 @@ bool Reader::readArray(Token& tokenStart) {
return true;
}
-bool Reader::decodeNumber(Token& token) {
+bool Reader::decodeNumber(Token& token)
+{
Value decoded;
- if (!decodeNumber(token, decoded))
+ if (!this->decodeNumber(token, decoded))
return false;
- currentValue().swapPayload(decoded);
- currentValue().setOffsetStart(token.start_ - begin_);
- currentValue().setOffsetLimit(token.end_ - begin_);
+ this->currentValue().swapPayload(decoded);
+ this->currentValue().setOffsetStart(token.start_ - this->begin_);
+ this->currentValue().setOffsetLimit(token.end_ - this->begin_);
return true;
}
-bool Reader::decodeNumber(Token& token, Value& decoded) {
+bool Reader::decodeNumber(Token& token, Value& decoded)
+{
// Attempts to parse the number as an integer. If the number is
// larger than the maximum supported value of an integer then
// we decode the number as a double.
@@ -571,16 +622,17 @@ bool Reader::decodeNumber(Token& token, Value& decoded) {
bool isNegative = *current == '-';
if (isNegative)
++current;
- // TODO: Help the compiler do the div and mod at compile time or get rid of them.
- Value::LargestUInt maxIntegerValue =
- isNegative ? Value::LargestUInt(Value::maxLargestInt) + 1
- : Value::maxLargestUInt;
+ // TODO: Help the compiler do the div and mod at compile time or get rid of
+ // them.
+ Value::LargestUInt maxIntegerValue = isNegative
+ ? Value::LargestUInt(Value::maxLargestInt) + 1
+ : Value::maxLargestUInt;
Value::LargestUInt threshold = maxIntegerValue / 10;
Value::LargestUInt value = 0;
while (current < token.end_) {
Char c = *current++;
if (c < '0' || c > '9')
- return decodeDouble(token, decoded);
+ return this->decodeDouble(token, decoded);
Value::UInt digit(static_cast<Value::UInt>(c - '0'));
if (value >= threshold) {
// We've hit or exceeded the max value divided by 10 (rounded down). If
@@ -589,7 +641,7 @@ bool Reader::decodeNumber(Token& token, Value& decoded) {
// Otherwise treat this number as a double to avoid overflow.
if (value > threshold || current != token.end_ ||
digit > maxIntegerValue % 10) {
- return decodeDouble(token, decoded);
+ return this->decodeDouble(token, decoded);
}
}
value = value * 10 + digit;
@@ -605,40 +657,44 @@ bool Reader::decodeNumber(Token& token, Value& decoded) {
return true;
}
-bool Reader::decodeDouble(Token& token) {
+bool Reader::decodeDouble(Token& token)
+{
Value decoded;
- if (!decodeDouble(token, decoded))
+ if (!this->decodeDouble(token, decoded))
return false;
- currentValue().swapPayload(decoded);
- currentValue().setOffsetStart(token.start_ - begin_);
- currentValue().setOffsetLimit(token.end_ - begin_);
+ this->currentValue().swapPayload(decoded);
+ this->currentValue().setOffsetStart(token.start_ - this->begin_);
+ this->currentValue().setOffsetLimit(token.end_ - this->begin_);
return true;
}
-bool Reader::decodeDouble(Token& token, Value& decoded) {
+bool Reader::decodeDouble(Token& token, Value& decoded)
+{
double value = 0;
JSONCPP_STRING buffer(token.start_, token.end_);
JSONCPP_ISTRINGSTREAM is(buffer);
if (!(is >> value))
- return addError("'" + JSONCPP_STRING(token.start_, token.end_) +
- "' is not a number.",
- token);
+ return this->addError("'" + JSONCPP_STRING(token.start_, token.end_) +
+ "' is not a number.",
+ token);
decoded = value;
return true;
}
-bool Reader::decodeString(Token& token) {
+bool Reader::decodeString(Token& token)
+{
JSONCPP_STRING decoded_string;
- if (!decodeString(token, decoded_string))
+ if (!this->decodeString(token, decoded_string))
return false;
Value decoded(decoded_string);
- currentValue().swapPayload(decoded);
- currentValue().setOffsetStart(token.start_ - begin_);
- currentValue().setOffsetLimit(token.end_ - begin_);
+ this->currentValue().swapPayload(decoded);
+ this->currentValue().setOffsetStart(token.start_ - this->begin_);
+ this->currentValue().setOffsetLimit(token.end_ - this->begin_);
return true;
}
-bool Reader::decodeString(Token& token, JSONCPP_STRING& decoded) {
+bool Reader::decodeString(Token& token, JSONCPP_STRING& decoded)
+{
decoded.reserve(static_cast<size_t>(token.end_ - token.start_ - 2));
Location current = token.start_ + 1; // skip '"'
Location end = token.end_ - 1; // do not include '"'
@@ -648,41 +704,43 @@ bool Reader::decodeString(Token& token, JSONCPP_STRING& decoded) {
break;
else if (c == '\\') {
if (current == end)
- return addError("Empty escape sequence in string", token, current);
+ return this->addError("Empty escape sequence in string", token,
+ current);
Char escape = *current++;
switch (escape) {
- case '"':
- decoded += '"';
- break;
- case '/':
- decoded += '/';
- break;
- case '\\':
- decoded += '\\';
- break;
- case 'b':
- decoded += '\b';
- break;
- case 'f':
- decoded += '\f';
- break;
- case 'n':
- decoded += '\n';
- break;
- case 'r':
- decoded += '\r';
- break;
- case 't':
- decoded += '\t';
- break;
- case 'u': {
- unsigned int unicode;
- if (!decodeUnicodeCodePoint(token, current, end, unicode))
- return false;
- decoded += codePointToUTF8(unicode);
- } break;
- default:
- return addError("Bad escape sequence in string", token, current);
+ case '"':
+ decoded += '"';
+ break;
+ case '/':
+ decoded += '/';
+ break;
+ case '\\':
+ decoded += '\\';
+ break;
+ case 'b':
+ decoded += '\b';
+ break;
+ case 'f':
+ decoded += '\f';
+ break;
+ case 'n':
+ decoded += '\n';
+ break;
+ case 'r':
+ decoded += '\r';
+ break;
+ case 't':
+ decoded += '\t';
+ break;
+ case 'u': {
+ unsigned int unicode;
+ if (!this->decodeUnicodeCodePoint(token, current, end, unicode))
+ return false;
+ decoded += codePointToUTF8(unicode);
+ } break;
+ default:
+ return this->addError("Bad escape sequence in string", token,
+ current);
}
} else {
decoded += c;
@@ -691,44 +749,43 @@ bool Reader::decodeString(Token& token, JSONCPP_STRING& decoded) {
return true;
}
-bool Reader::decodeUnicodeCodePoint(Token& token,
- Location& current,
- Location end,
- unsigned int& unicode) {
+bool Reader::decodeUnicodeCodePoint(Token& token, Location& current,
+ Location end, unsigned int& unicode)
+{
- if (!decodeUnicodeEscapeSequence(token, current, end, unicode))
+ if (!this->decodeUnicodeEscapeSequence(token, current, end, unicode))
return false;
if (unicode >= 0xD800 && unicode <= 0xDBFF) {
// surrogate pairs
if (end - current < 6)
- return addError(
- "additional six characters expected to parse unicode surrogate pair.",
- token,
- current);
+ return this->addError(
+ "additional six characters expected to parse unicode surrogate pair.",
+ token, current);
unsigned int surrogatePair;
if (*(current++) == '\\' && *(current++) == 'u') {
- if (decodeUnicodeEscapeSequence(token, current, end, surrogatePair)) {
- unicode = 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF);
+ if (this->decodeUnicodeEscapeSequence(token, current, end,
+ surrogatePair)) {
+ unicode =
+ 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF);
} else
return false;
} else
- return addError("expecting another \\u token to begin the second half of "
- "a unicode surrogate pair",
- token,
- current);
+ return this->addError(
+ "expecting another \\u token to begin the second half of "
+ "a unicode surrogate pair",
+ token, current);
}
return true;
}
-bool Reader::decodeUnicodeEscapeSequence(Token& token,
- Location& current,
+bool Reader::decodeUnicodeEscapeSequence(Token& token, Location& current,
Location end,
- unsigned int& ret_unicode) {
+ unsigned int& ret_unicode)
+{
if (end - current < 4)
- return addError(
- "Bad unicode escape sequence in string: four digits expected.",
- token,
- current);
+ return this->addError(
+ "Bad unicode escape sequence in string: four digits expected.", token,
+ current);
int unicode = 0;
for (int index = 0; index < 4; ++index) {
Char c = *current++;
@@ -740,60 +797,65 @@ bool Reader::decodeUnicodeEscapeSequence(Token& token,
else if (c >= 'A' && c <= 'F')
unicode += c - 'A' + 10;
else
- return addError(
- "Bad unicode escape sequence in string: hexadecimal digit expected.",
- token,
- current);
+ return this->addError(
+ "Bad unicode escape sequence in string: hexadecimal digit expected.",
+ token, current);
}
ret_unicode = static_cast<unsigned int>(unicode);
return true;
}
-bool
-Reader::addError(const JSONCPP_STRING& message, Token& token, Location extra) {
+bool Reader::addError(const JSONCPP_STRING& message, Token& token,
+ Location extra)
+{
ErrorInfo info;
info.token_ = token;
info.message_ = message;
info.extra_ = extra;
- errors_.push_back(info);
+ this->errors_.push_back(info);
return false;
}
-bool Reader::recoverFromError(TokenType skipUntilToken) {
- size_t const errorCount = errors_.size();
+bool Reader::recoverFromError(TokenType skipUntilToken)
+{
+ size_t const errorCount = this->errors_.size();
Token skip;
for (;;) {
- if (!readToken(skip))
- errors_.resize(errorCount); // discard errors caused by recovery
+ if (!this->readToken(skip))
+ this->errors_.resize(errorCount); // discard errors caused by recovery
if (skip.type_ == skipUntilToken || skip.type_ == tokenEndOfStream)
break;
}
- errors_.resize(errorCount);
+ this->errors_.resize(errorCount);
return false;
}
-bool Reader::addErrorAndRecover(const JSONCPP_STRING& message,
- Token& token,
- TokenType skipUntilToken) {
- addError(message, token);
- return recoverFromError(skipUntilToken);
+bool Reader::addErrorAndRecover(const JSONCPP_STRING& message, Token& token,
+ TokenType skipUntilToken)
+{
+ this->addError(message, token);
+ return this->recoverFromError(skipUntilToken);
}
-Value& Reader::currentValue() { return *(nodes_.top()); }
+Value& Reader::currentValue()
+{
+ return *(this->nodes_.top());
+}
-Reader::Char Reader::getNextChar() {
- if (current_ == end_)
+Reader::Char Reader::getNextChar()
+{
+ if (this->current_ == this->end_)
return 0;
- return *current_++;
+ return *this->current_++;
}
-void Reader::getLocationLineAndColumn(Location location,
- int& line,
- int& column) const {
- Location current = begin_;
+void Reader::getLocationLineAndColumn(Location location, int& line,
+ int& column) const
+{
+ Location current = this->begin_;
Location lastLineStart = current;
line = 0;
- while (current < location && current != end_) {
+ while (current < location && current != this->end_) {
Char c = *current++;
if (c == '\r') {
if (*current == '\n')
@@ -810,91 +872,96 @@ void Reader::getLocationLineAndColumn(Location location,
++line;
}
-JSONCPP_STRING Reader::getLocationLineAndColumn(Location location) const {
+JSONCPP_STRING Reader::getLocationLineAndColumn(Location location) const
+{
int line, column;
- getLocationLineAndColumn(location, line, column);
+ this->getLocationLineAndColumn(location, line, column);
char buffer[18 + 16 + 16 + 1];
snprintf(buffer, sizeof(buffer), "Line %d, Column %d", line, column);
return buffer;
}
// Deprecated. Preserved for backward compatibility
-JSONCPP_STRING Reader::getFormatedErrorMessages() const {
- return getFormattedErrorMessages();
+JSONCPP_STRING Reader::getFormatedErrorMessages() const
+{
+ return this->getFormattedErrorMessages();
}
-JSONCPP_STRING Reader::getFormattedErrorMessages() const {
+JSONCPP_STRING Reader::getFormattedErrorMessages() const
+{
JSONCPP_STRING formattedMessage;
- for (Errors::const_iterator itError = errors_.begin();
- itError != errors_.end();
- ++itError) {
+ for (Errors::const_iterator itError = this->errors_.begin();
+ itError != this->errors_.end(); ++itError) {
const ErrorInfo& error = *itError;
formattedMessage +=
- "* " + getLocationLineAndColumn(error.token_.start_) + "\n";
+ "* " + this->getLocationLineAndColumn(error.token_.start_) + "\n";
formattedMessage += " " + error.message_ + "\n";
if (error.extra_)
- formattedMessage +=
- "See " + getLocationLineAndColumn(error.extra_) + " for detail.\n";
+ formattedMessage += "See " +
+ this->getLocationLineAndColumn(error.extra_) + " for detail.\n";
}
return formattedMessage;
}
-std::vector<Reader::StructuredError> Reader::getStructuredErrors() const {
+std::vector<Reader::StructuredError> Reader::getStructuredErrors() const
+{
std::vector<Reader::StructuredError> allErrors;
- for (Errors::const_iterator itError = errors_.begin();
- itError != errors_.end();
- ++itError) {
+ for (Errors::const_iterator itError = this->errors_.begin();
+ itError != this->errors_.end(); ++itError) {
const ErrorInfo& error = *itError;
Reader::StructuredError structured;
- structured.offset_start = error.token_.start_ - begin_;
- structured.offset_limit = error.token_.end_ - begin_;
+ structured.offset_start = error.token_.start_ - this->begin_;
+ structured.offset_limit = error.token_.end_ - this->begin_;
structured.message = error.message_;
allErrors.push_back(structured);
}
return allErrors;
}
-bool Reader::pushError(const Value& value, const JSONCPP_STRING& message) {
- ptrdiff_t const length = end_ - begin_;
- if(value.getOffsetStart() > length
- || value.getOffsetLimit() > length)
+bool Reader::pushError(const Value& value, const JSONCPP_STRING& message)
+{
+ ptrdiff_t const length = this->end_ - this->begin_;
+ if (value.getOffsetStart() > length || value.getOffsetLimit() > length)
return false;
Token token;
token.type_ = tokenError;
- token.start_ = begin_ + value.getOffsetStart();
- token.end_ = end_ + value.getOffsetLimit();
+ token.start_ = this->begin_ + value.getOffsetStart();
+ token.end_ = this->end_ + value.getOffsetLimit();
ErrorInfo info;
info.token_ = token;
info.message_ = message;
info.extra_ = 0;
- errors_.push_back(info);
+ this->errors_.push_back(info);
return true;
}
-bool Reader::pushError(const Value& value, const JSONCPP_STRING& message, const Value& extra) {
- ptrdiff_t const length = end_ - begin_;
- if(value.getOffsetStart() > length
- || value.getOffsetLimit() > length
- || extra.getOffsetLimit() > length)
+bool Reader::pushError(const Value& value, const JSONCPP_STRING& message,
+ const Value& extra)
+{
+ ptrdiff_t const length = this->end_ - this->begin_;
+ if (value.getOffsetStart() > length || value.getOffsetLimit() > length ||
+ extra.getOffsetLimit() > length)
return false;
Token token;
token.type_ = tokenError;
- token.start_ = begin_ + value.getOffsetStart();
- token.end_ = begin_ + value.getOffsetLimit();
+ token.start_ = this->begin_ + value.getOffsetStart();
+ token.end_ = this->begin_ + value.getOffsetLimit();
ErrorInfo info;
info.token_ = token;
info.message_ = message;
- info.extra_ = begin_ + extra.getOffsetStart();
- errors_.push_back(info);
+ info.extra_ = this->begin_ + extra.getOffsetStart();
+ this->errors_.push_back(info);
return true;
}
-bool Reader::good() const {
- return !errors_.size();
+bool Reader::good() const
+{
+ return !this->errors_.size();
}
// exact copy of Features
-class OurFeatures {
+class OurFeatures
+{
public:
static OurFeatures all();
bool allowComments_;
@@ -906,43 +973,48 @@ public:
bool rejectDupKeys_;
bool allowSpecialFloats_;
int stackLimit_;
-}; // OurFeatures
+}; // OurFeatures
// exact copy of Implementation of class Features
// ////////////////////////////////
-OurFeatures OurFeatures::all() { return OurFeatures(); }
+OurFeatures OurFeatures::all()
+{
+ return OurFeatures();
+}
// Implementation of class Reader
// ////////////////////////////////
// exact copy of Reader, renamed to OurReader
-class OurReader {
+class OurReader
+{
public:
typedef char Char;
typedef const Char* Location;
- struct StructuredError {
+ struct StructuredError
+ {
ptrdiff_t offset_start;
ptrdiff_t offset_limit;
JSONCPP_STRING message;
};
OurReader(OurFeatures const& features);
- bool parse(const char* beginDoc,
- const char* endDoc,
- Value& root,
+ bool parse(const char* beginDoc, const char* endDoc, Value& root,
bool collectComments = true);
JSONCPP_STRING getFormattedErrorMessages() const;
std::vector<StructuredError> getStructuredErrors() const;
bool pushError(const Value& value, const JSONCPP_STRING& message);
- bool pushError(const Value& value, const JSONCPP_STRING& message, const Value& extra);
+ bool pushError(const Value& value, const JSONCPP_STRING& message,
+ const Value& extra);
bool good() const;
private:
- OurReader(OurReader const&); // no impl
- void operator=(OurReader const&); // no impl
+ OurReader(OurReader const&); // no impl
+ void operator=(OurReader const&); // no impl
- enum TokenType {
+ enum TokenType
+ {
tokenEndOfStream = 0,
tokenObjectBegin,
tokenObjectEnd,
@@ -962,14 +1034,16 @@ private:
tokenError
};
- class Token {
+ class Token
+ {
public:
TokenType type_;
Location start_;
Location end_;
};
- class ErrorInfo {
+ class ErrorInfo
+ {
public:
Token token_;
JSONCPP_STRING message_;
@@ -996,24 +1070,20 @@ private:
bool decodeString(Token& token, JSONCPP_STRING& decoded);
bool decodeDouble(Token& token);
bool decodeDouble(Token& token, Value& decoded);
- bool decodeUnicodeCodePoint(Token& token,
- Location& current,
- Location end,
+ bool decodeUnicodeCodePoint(Token& token, Location& current, Location end,
unsigned int& unicode);
- bool decodeUnicodeEscapeSequence(Token& token,
- Location& current,
- Location end,
- unsigned int& unicode);
- bool addError(const JSONCPP_STRING& message, Token& token, Location extra = 0);
+ bool decodeUnicodeEscapeSequence(Token& token, Location& current,
+ Location end, unsigned int& unicode);
+ bool addError(const JSONCPP_STRING& message, Token& token,
+ Location extra = 0);
bool recoverFromError(TokenType skipUntilToken);
- bool addErrorAndRecover(const JSONCPP_STRING& message,
- Token& token,
+ bool addErrorAndRecover(const JSONCPP_STRING& message, Token& token,
TokenType skipUntilToken);
void skipUntilSpace();
Value& currentValue();
Char getNextChar();
- void
- getLocationLineAndColumn(Location location, int& line, int& column) const;
+ void getLocationLineAndColumn(Location location, int& line,
+ int& column) const;
JSONCPP_STRING getLocationLineAndColumn(Location location) const;
void addComment(Location begin, Location end, CommentPlacement placement);
void skipCommentTokens(Token& token);
@@ -1034,11 +1104,13 @@ private:
OurFeatures const features_;
bool collectComments_;
-}; // OurReader
+}; // OurReader
// complete copy of Read impl, for OurReader
-bool OurReader::containsNewLine(OurReader::Location begin, OurReader::Location end) {
+bool OurReader::containsNewLine(OurReader::Location begin,
+ OurReader::Location end)
+{
for (; begin < end; ++begin)
if (*begin == '\n' || *begin == '\r')
return true;
@@ -1046,315 +1118,322 @@ bool OurReader::containsNewLine(OurReader::Location begin, OurReader::Location e
}
OurReader::OurReader(OurFeatures const& features)
- : errors_(), document_(), begin_(), end_(), current_(), lastValueEnd_(),
- lastValue_(), commentsBefore_(),
- features_(features), collectComments_() {
+ : errors_()
+ , document_()
+ , begin_()
+ , end_()
+ , current_()
+ , lastValueEnd_()
+ , lastValue_()
+ , commentsBefore_()
+ , features_(features)
+ , collectComments_()
+{
}
-bool OurReader::parse(const char* beginDoc,
- const char* endDoc,
- Value& root,
- bool collectComments) {
- if (!features_.allowComments_) {
+bool OurReader::parse(const char* beginDoc, const char* endDoc, Value& root,
+ bool collectComments)
+{
+ if (!this->features_.allowComments_) {
collectComments = false;
}
- begin_ = beginDoc;
- end_ = endDoc;
- collectComments_ = collectComments;
- current_ = begin_;
- lastValueEnd_ = 0;
- lastValue_ = 0;
- commentsBefore_.clear();
- errors_.clear();
- while (!nodes_.empty())
- nodes_.pop();
- nodes_.push(&root);
-
- bool successful = readValue();
+ this->begin_ = beginDoc;
+ this->end_ = endDoc;
+ this->collectComments_ = collectComments;
+ this->current_ = this->begin_;
+ this->lastValueEnd_ = 0;
+ this->lastValue_ = 0;
+ this->commentsBefore_.clear();
+ this->errors_.clear();
+ while (!this->nodes_.empty())
+ this->nodes_.pop();
+ this->nodes_.push(&root);
+
+ bool successful = this->readValue();
Token token;
- skipCommentTokens(token);
- if (features_.failIfExtra_) {
- if ((features_.strictRoot_ || token.type_ != tokenError) && token.type_ != tokenEndOfStream) {
- addError("Extra non-whitespace after JSON value.", token);
+ this->skipCommentTokens(token);
+ if (this->features_.failIfExtra_) {
+ if ((this->features_.strictRoot_ || token.type_ != tokenError) &&
+ token.type_ != tokenEndOfStream) {
+ this->addError("Extra non-whitespace after JSON value.", token);
return false;
}
}
- if (collectComments_ && !commentsBefore_.empty())
- root.setComment(commentsBefore_, commentAfter);
- if (features_.strictRoot_) {
+ if (this->collectComments_ && !this->commentsBefore_.empty())
+ root.setComment(this->commentsBefore_, commentAfter);
+ if (this->features_.strictRoot_) {
if (!root.isArray() && !root.isObject()) {
- // Set error location to start of doc, ideally should be first token found
- // in doc
+ // Set error location to start of doc, ideally should be first token
+ // found in doc
token.type_ = tokenError;
token.start_ = beginDoc;
token.end_ = endDoc;
- addError(
- "A valid JSON document must be either an array or an object value.",
- token);
+ this->addError(
+ "A valid JSON document must be either an array or an object value.",
+ token);
return false;
}
}
return successful;
}
-bool OurReader::readValue() {
+bool OurReader::readValue()
+{
// To preserve the old behaviour we cast size_t to int.
- if (static_cast<int>(nodes_.size()) > features_.stackLimit_) throwRuntimeError("Exceeded stackLimit in readValue().");
+ if (static_cast<int>(this->nodes_.size()) > this->features_.stackLimit_)
+ throwRuntimeError("Exceeded stackLimit in readValue().");
Token token;
- skipCommentTokens(token);
+ this->skipCommentTokens(token);
bool successful = true;
- if (collectComments_ && !commentsBefore_.empty()) {
- currentValue().setComment(commentsBefore_, commentBefore);
- commentsBefore_.clear();
+ if (this->collectComments_ && !this->commentsBefore_.empty()) {
+ this->currentValue().setComment(this->commentsBefore_, commentBefore);
+ this->commentsBefore_.clear();
}
switch (token.type_) {
- case tokenObjectBegin:
- successful = readObject(token);
- currentValue().setOffsetLimit(current_ - begin_);
- break;
- case tokenArrayBegin:
- successful = readArray(token);
- currentValue().setOffsetLimit(current_ - begin_);
- break;
- case tokenNumber:
- successful = decodeNumber(token);
- break;
- case tokenString:
- successful = decodeString(token);
- break;
- case tokenTrue:
- {
- Value v(true);
- currentValue().swapPayload(v);
- currentValue().setOffsetStart(token.start_ - begin_);
- currentValue().setOffsetLimit(token.end_ - begin_);
- }
- break;
- case tokenFalse:
- {
- Value v(false);
- currentValue().swapPayload(v);
- currentValue().setOffsetStart(token.start_ - begin_);
- currentValue().setOffsetLimit(token.end_ - begin_);
- }
- break;
- case tokenNull:
- {
- Value v;
- currentValue().swapPayload(v);
- currentValue().setOffsetStart(token.start_ - begin_);
- currentValue().setOffsetLimit(token.end_ - begin_);
- }
- break;
- case tokenNaN:
- {
- Value v(std::numeric_limits<double>::quiet_NaN());
- currentValue().swapPayload(v);
- currentValue().setOffsetStart(token.start_ - begin_);
- currentValue().setOffsetLimit(token.end_ - begin_);
- }
- break;
- case tokenPosInf:
- {
- Value v(std::numeric_limits<double>::infinity());
- currentValue().swapPayload(v);
- currentValue().setOffsetStart(token.start_ - begin_);
- currentValue().setOffsetLimit(token.end_ - begin_);
- }
- break;
- case tokenNegInf:
- {
- Value v(-std::numeric_limits<double>::infinity());
- currentValue().swapPayload(v);
- currentValue().setOffsetStart(token.start_ - begin_);
- currentValue().setOffsetLimit(token.end_ - begin_);
- }
- break;
- case tokenArraySeparator:
- case tokenObjectEnd:
- case tokenArrayEnd:
- if (features_.allowDroppedNullPlaceholders_) {
- // "Un-read" the current token and mark the current value as a null
- // token.
- current_--;
- Value v;
- currentValue().swapPayload(v);
- currentValue().setOffsetStart(current_ - begin_ - 1);
- currentValue().setOffsetLimit(current_ - begin_);
+ case tokenObjectBegin:
+ successful = this->readObject(token);
+ this->currentValue().setOffsetLimit(this->current_ - this->begin_);
+ break;
+ case tokenArrayBegin:
+ successful = this->readArray(token);
+ this->currentValue().setOffsetLimit(this->current_ - this->begin_);
+ break;
+ case tokenNumber:
+ successful = this->decodeNumber(token);
break;
- } // else, fall through ...
- default:
- currentValue().setOffsetStart(token.start_ - begin_);
- currentValue().setOffsetLimit(token.end_ - begin_);
- return addError("Syntax error: value, object or array expected.", token);
+ case tokenString:
+ successful = this->decodeString(token);
+ break;
+ case tokenTrue: {
+ Value v(true);
+ this->currentValue().swapPayload(v);
+ this->currentValue().setOffsetStart(token.start_ - this->begin_);
+ this->currentValue().setOffsetLimit(token.end_ - this->begin_);
+ } break;
+ case tokenFalse: {
+ Value v(false);
+ this->currentValue().swapPayload(v);
+ this->currentValue().setOffsetStart(token.start_ - this->begin_);
+ this->currentValue().setOffsetLimit(token.end_ - this->begin_);
+ } break;
+ case tokenNull: {
+ Value v;
+ this->currentValue().swapPayload(v);
+ this->currentValue().setOffsetStart(token.start_ - this->begin_);
+ this->currentValue().setOffsetLimit(token.end_ - this->begin_);
+ } break;
+ case tokenNaN: {
+ Value v(std::numeric_limits<double>::quiet_NaN());
+ this->currentValue().swapPayload(v);
+ this->currentValue().setOffsetStart(token.start_ - this->begin_);
+ this->currentValue().setOffsetLimit(token.end_ - this->begin_);
+ } break;
+ case tokenPosInf: {
+ Value v(std::numeric_limits<double>::infinity());
+ this->currentValue().swapPayload(v);
+ this->currentValue().setOffsetStart(token.start_ - this->begin_);
+ this->currentValue().setOffsetLimit(token.end_ - this->begin_);
+ } break;
+ case tokenNegInf: {
+ Value v(-std::numeric_limits<double>::infinity());
+ this->currentValue().swapPayload(v);
+ this->currentValue().setOffsetStart(token.start_ - this->begin_);
+ this->currentValue().setOffsetLimit(token.end_ - this->begin_);
+ } break;
+ case tokenArraySeparator:
+ case tokenObjectEnd:
+ case tokenArrayEnd:
+ if (this->features_.allowDroppedNullPlaceholders_) {
+ // "Un-read" the current token and mark the current value as a null
+ // token.
+ this->current_--;
+ Value v;
+ this->currentValue().swapPayload(v);
+ this->currentValue().setOffsetStart(this->current_ - this->begin_ - 1);
+ this->currentValue().setOffsetLimit(this->current_ - this->begin_);
+ break;
+ } // else, fall through ...
+ default:
+ this->currentValue().setOffsetStart(token.start_ - this->begin_);
+ this->currentValue().setOffsetLimit(token.end_ - this->begin_);
+ return this->addError("Syntax error: value, object or array expected.",
+ token);
}
- if (collectComments_) {
- lastValueEnd_ = current_;
- lastValue_ = &currentValue();
+ if (this->collectComments_) {
+ this->lastValueEnd_ = this->current_;
+ this->lastValue_ = &this->currentValue();
}
return successful;
}
-void OurReader::skipCommentTokens(Token& token) {
- if (features_.allowComments_) {
+void OurReader::skipCommentTokens(Token& token)
+{
+ if (this->features_.allowComments_) {
do {
- readToken(token);
+ this->readToken(token);
} while (token.type_ == tokenComment);
} else {
- readToken(token);
+ this->readToken(token);
}
}
-bool OurReader::readToken(Token& token) {
- skipSpaces();
- token.start_ = current_;
- Char c = getNextChar();
+bool OurReader::readToken(Token& token)
+{
+ this->skipSpaces();
+ token.start_ = this->current_;
+ Char c = this->getNextChar();
bool ok = true;
switch (c) {
- case '{':
- token.type_ = tokenObjectBegin;
- break;
- case '}':
- token.type_ = tokenObjectEnd;
- break;
- case '[':
- token.type_ = tokenArrayBegin;
- break;
- case ']':
- token.type_ = tokenArrayEnd;
- break;
- case '"':
- token.type_ = tokenString;
- ok = readString();
- break;
- case '\'':
- if (features_.allowSingleQuotes_) {
- token.type_ = tokenString;
- ok = readStringSingleQuote();
- break;
- } // else continue
- case '/':
- token.type_ = tokenComment;
- ok = readComment();
- break;
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- token.type_ = tokenNumber;
- readNumber(false);
- break;
- case '-':
- if (readNumber(true)) {
+ case '{':
+ token.type_ = tokenObjectBegin;
+ break;
+ case '}':
+ token.type_ = tokenObjectEnd;
+ break;
+ case '[':
+ token.type_ = tokenArrayBegin;
+ break;
+ case ']':
+ token.type_ = tokenArrayEnd;
+ break;
+ case '"':
+ token.type_ = tokenString;
+ ok = this->readString();
+ break;
+ case '\'':
+ if (this->features_.allowSingleQuotes_) {
+ token.type_ = tokenString;
+ ok = this->readStringSingleQuote();
+ break;
+ } // else continue
+ case '/':
+ token.type_ = tokenComment;
+ ok = this->readComment();
+ break;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
token.type_ = tokenNumber;
- } else {
- token.type_ = tokenNegInf;
- ok = features_.allowSpecialFloats_ && match("nfinity", 7);
- }
- break;
- case 't':
- token.type_ = tokenTrue;
- ok = match("rue", 3);
- break;
- case 'f':
- token.type_ = tokenFalse;
- ok = match("alse", 4);
- break;
- case 'n':
- token.type_ = tokenNull;
- ok = match("ull", 3);
- break;
- case 'N':
- if (features_.allowSpecialFloats_) {
- token.type_ = tokenNaN;
- ok = match("aN", 2);
- } else {
- ok = false;
- }
- break;
- case 'I':
- if (features_.allowSpecialFloats_) {
- token.type_ = tokenPosInf;
- ok = match("nfinity", 7);
- } else {
+ this->readNumber(false);
+ break;
+ case '-':
+ if (this->readNumber(true)) {
+ token.type_ = tokenNumber;
+ } else {
+ token.type_ = tokenNegInf;
+ ok = this->features_.allowSpecialFloats_ && this->match("nfinity", 7);
+ }
+ break;
+ case 't':
+ token.type_ = tokenTrue;
+ ok = this->match("rue", 3);
+ break;
+ case 'f':
+ token.type_ = tokenFalse;
+ ok = this->match("alse", 4);
+ break;
+ case 'n':
+ token.type_ = tokenNull;
+ ok = this->match("ull", 3);
+ break;
+ case 'N':
+ if (this->features_.allowSpecialFloats_) {
+ token.type_ = tokenNaN;
+ ok = this->match("aN", 2);
+ } else {
+ ok = false;
+ }
+ break;
+ case 'I':
+ if (this->features_.allowSpecialFloats_) {
+ token.type_ = tokenPosInf;
+ ok = this->match("nfinity", 7);
+ } else {
+ ok = false;
+ }
+ break;
+ case ',':
+ token.type_ = tokenArraySeparator;
+ break;
+ case ':':
+ token.type_ = tokenMemberSeparator;
+ break;
+ case 0:
+ token.type_ = tokenEndOfStream;
+ break;
+ default:
ok = false;
- }
- break;
- case ',':
- token.type_ = tokenArraySeparator;
- break;
- case ':':
- token.type_ = tokenMemberSeparator;
- break;
- case 0:
- token.type_ = tokenEndOfStream;
- break;
- default:
- ok = false;
- break;
+ break;
}
if (!ok)
token.type_ = tokenError;
- token.end_ = current_;
+ token.end_ = this->current_;
return true;
}
-void OurReader::skipSpaces() {
- while (current_ != end_) {
- Char c = *current_;
+void OurReader::skipSpaces()
+{
+ while (this->current_ != this->end_) {
+ Char c = *this->current_;
if (c == ' ' || c == '\t' || c == '\r' || c == '\n')
- ++current_;
+ ++this->current_;
else
break;
}
}
-bool OurReader::match(Location pattern, int patternLength) {
- if (end_ - current_ < patternLength)
+bool OurReader::match(Location pattern, int patternLength)
+{
+ if (this->end_ - this->current_ < patternLength)
return false;
int index = patternLength;
while (index--)
- if (current_[index] != pattern[index])
+ if (this->current_[index] != pattern[index])
return false;
- current_ += patternLength;
+ this->current_ += patternLength;
return true;
}
-bool OurReader::readComment() {
- Location commentBegin = current_ - 1;
- Char c = getNextChar();
+bool OurReader::readComment()
+{
+ Location commentBegin = this->current_ - 1;
+ Char c = this->getNextChar();
bool successful = false;
if (c == '*')
- successful = readCStyleComment();
+ successful = this->readCStyleComment();
else if (c == '/')
- successful = readCppStyleComment();
+ successful = this->readCppStyleComment();
if (!successful)
return false;
- if (collectComments_) {
+ if (this->collectComments_) {
CommentPlacement placement = commentBefore;
- if (lastValueEnd_ && !containsNewLine(lastValueEnd_, commentBegin)) {
- if (c != '*' || !containsNewLine(commentBegin, current_))
+ if (this->lastValueEnd_ &&
+ !containsNewLine(this->lastValueEnd_, commentBegin)) {
+ if (c != '*' || !containsNewLine(commentBegin, this->current_))
placement = commentAfterOnSameLine;
}
- addComment(commentBegin, current_, placement);
+ this->addComment(commentBegin, this->current_, placement);
}
return true;
}
-JSONCPP_STRING OurReader::normalizeEOL(OurReader::Location begin, OurReader::Location end) {
+JSONCPP_STRING OurReader::normalizeEOL(OurReader::Location begin,
+ OurReader::Location end)
+{
JSONCPP_STRING normalized;
normalized.reserve(static_cast<size_t>(end - begin));
OurReader::Location current = begin;
@@ -1362,8 +1441,8 @@ JSONCPP_STRING OurReader::normalizeEOL(OurReader::Location begin, OurReader::Loc
char c = *current++;
if (c == '\r') {
if (current != end && *current == '\n')
- // convert dos EOL
- ++current;
+ // convert dos EOL
+ ++current;
// convert Mac EOL
normalized += '\n';
} else {
@@ -1373,36 +1452,39 @@ JSONCPP_STRING OurReader::normalizeEOL(OurReader::Location begin, OurReader::Loc
return normalized;
}
-void
-OurReader::addComment(Location begin, Location end, CommentPlacement placement) {
- assert(collectComments_);
+void OurReader::addComment(Location begin, Location end,
+ CommentPlacement placement)
+{
+ assert(this->collectComments_);
const JSONCPP_STRING& normalized = normalizeEOL(begin, end);
if (placement == commentAfterOnSameLine) {
- assert(lastValue_ != 0);
- lastValue_->setComment(normalized, placement);
+ assert(this->lastValue_ != 0);
+ this->lastValue_->setComment(normalized, placement);
} else {
- commentsBefore_ += normalized;
+ this->commentsBefore_ += normalized;
}
}
-bool OurReader::readCStyleComment() {
- while ((current_ + 1) < end_) {
- Char c = getNextChar();
- if (c == '*' && *current_ == '/')
+bool OurReader::readCStyleComment()
+{
+ while ((this->current_ + 1) < this->end_) {
+ Char c = this->getNextChar();
+ if (c == '*' && *this->current_ == '/')
break;
}
- return getNextChar() == '/';
+ return this->getNextChar() == '/';
}
-bool OurReader::readCppStyleComment() {
- while (current_ != end_) {
- Char c = getNextChar();
+bool OurReader::readCppStyleComment()
+{
+ while (this->current_ != this->end_) {
+ Char c = this->getNextChar();
if (c == '\n')
break;
if (c == '\r') {
// Consume DOS EOL. It will be normalized in addComment.
- if (current_ != end_ && *current_ == '\n')
- getNextChar();
+ if (this->current_ != this->end_ && *this->current_ == '\n')
+ this->getNextChar();
// Break on Moc OS 9 EOL.
break;
}
@@ -1410,150 +1492,156 @@ bool OurReader::readCppStyleComment() {
return true;
}
-bool OurReader::readNumber(bool checkInf) {
- const char *p = current_;
- if (checkInf && p != end_ && *p == 'I') {
- current_ = ++p;
+bool OurReader::readNumber(bool checkInf)
+{
+ const char* p = this->current_;
+ if (checkInf && p != this->end_ && *p == 'I') {
+ this->current_ = ++p;
return false;
}
char c = '0'; // stopgap for already consumed character
// integral part
while (c >= '0' && c <= '9')
- c = (current_ = p) < end_ ? *p++ : '\0';
+ c = (this->current_ = p) < this->end_ ? *p++ : '\0';
// fractional part
if (c == '.') {
- c = (current_ = p) < end_ ? *p++ : '\0';
+ c = (this->current_ = p) < this->end_ ? *p++ : '\0';
while (c >= '0' && c <= '9')
- c = (current_ = p) < end_ ? *p++ : '\0';
+ c = (this->current_ = p) < this->end_ ? *p++ : '\0';
}
// exponential part
if (c == 'e' || c == 'E') {
- c = (current_ = p) < end_ ? *p++ : '\0';
+ c = (this->current_ = p) < this->end_ ? *p++ : '\0';
if (c == '+' || c == '-')
- c = (current_ = p) < end_ ? *p++ : '\0';
+ c = (this->current_ = p) < this->end_ ? *p++ : '\0';
while (c >= '0' && c <= '9')
- c = (current_ = p) < end_ ? *p++ : '\0';
+ c = (this->current_ = p) < this->end_ ? *p++ : '\0';
}
return true;
}
-bool OurReader::readString() {
+bool OurReader::readString()
+{
Char c = 0;
- while (current_ != end_) {
- c = getNextChar();
+ while (this->current_ != this->end_) {
+ c = this->getNextChar();
if (c == '\\')
- getNextChar();
+ this->getNextChar();
else if (c == '"')
break;
}
return c == '"';
}
-
-bool OurReader::readStringSingleQuote() {
+bool OurReader::readStringSingleQuote()
+{
Char c = 0;
- while (current_ != end_) {
- c = getNextChar();
+ while (this->current_ != this->end_) {
+ c = this->getNextChar();
if (c == '\\')
- getNextChar();
+ this->getNextChar();
else if (c == '\'')
break;
}
return c == '\'';
}
-bool OurReader::readObject(Token& tokenStart) {
+bool OurReader::readObject(Token& tokenStart)
+{
Token tokenName;
JSONCPP_STRING name;
Value init(objectValue);
- currentValue().swapPayload(init);
- currentValue().setOffsetStart(tokenStart.start_ - begin_);
- while (readToken(tokenName)) {
+ this->currentValue().swapPayload(init);
+ this->currentValue().setOffsetStart(tokenStart.start_ - this->begin_);
+ while (this->readToken(tokenName)) {
bool initialTokenOk = true;
while (tokenName.type_ == tokenComment && initialTokenOk)
- initialTokenOk = readToken(tokenName);
+ initialTokenOk = this->readToken(tokenName);
if (!initialTokenOk)
break;
if (tokenName.type_ == tokenObjectEnd && name.empty()) // empty object
return true;
name.clear();
if (tokenName.type_ == tokenString) {
- if (!decodeString(tokenName, name))
- return recoverFromError(tokenObjectEnd);
- } else if (tokenName.type_ == tokenNumber && features_.allowNumericKeys_) {
+ if (!this->decodeString(tokenName, name))
+ return this->recoverFromError(tokenObjectEnd);
+ } else if (tokenName.type_ == tokenNumber &&
+ this->features_.allowNumericKeys_) {
Value numberName;
- if (!decodeNumber(tokenName, numberName))
- return recoverFromError(tokenObjectEnd);
+ if (!this->decodeNumber(tokenName, numberName))
+ return this->recoverFromError(tokenObjectEnd);
name = numberName.asString();
} else {
break;
}
Token colon;
- if (!readToken(colon) || colon.type_ != tokenMemberSeparator) {
- return addErrorAndRecover(
- "Missing ':' after object member name", colon, tokenObjectEnd);
+ if (!this->readToken(colon) || colon.type_ != tokenMemberSeparator) {
+ return this->addErrorAndRecover("Missing ':' after object member name",
+ colon, tokenObjectEnd);
}
- if (name.length() >= (1U<<30)) throwRuntimeError("keylength >= 2^30");
- if (features_.rejectDupKeys_ && currentValue().isMember(name)) {
+ if (name.length() >= (1U << 30))
+ throwRuntimeError("keylength >= 2^30");
+ if (this->features_.rejectDupKeys_ &&
+ this->currentValue().isMember(name)) {
JSONCPP_STRING msg = "Duplicate key: '" + name + "'";
- return addErrorAndRecover(
- msg, tokenName, tokenObjectEnd);
+ return this->addErrorAndRecover(msg, tokenName, tokenObjectEnd);
}
- Value& value = currentValue()[name];
- nodes_.push(&value);
- bool ok = readValue();
- nodes_.pop();
+ Value& value = this->currentValue()[name];
+ this->nodes_.push(&value);
+ bool ok = this->readValue();
+ this->nodes_.pop();
if (!ok) // error already set
- return recoverFromError(tokenObjectEnd);
+ return this->recoverFromError(tokenObjectEnd);
Token comma;
- if (!readToken(comma) ||
+ if (!this->readToken(comma) ||
(comma.type_ != tokenObjectEnd && comma.type_ != tokenArraySeparator &&
comma.type_ != tokenComment)) {
- return addErrorAndRecover(
- "Missing ',' or '}' in object declaration", comma, tokenObjectEnd);
+ return this->addErrorAndRecover(
+ "Missing ',' or '}' in object declaration", comma, tokenObjectEnd);
}
bool finalizeTokenOk = true;
while (comma.type_ == tokenComment && finalizeTokenOk)
- finalizeTokenOk = readToken(comma);
+ finalizeTokenOk = this->readToken(comma);
if (comma.type_ == tokenObjectEnd)
return true;
}
- return addErrorAndRecover(
- "Missing '}' or object member name", tokenName, tokenObjectEnd);
+ return this->addErrorAndRecover("Missing '}' or object member name",
+ tokenName, tokenObjectEnd);
}
-bool OurReader::readArray(Token& tokenStart) {
+bool OurReader::readArray(Token& tokenStart)
+{
Value init(arrayValue);
- currentValue().swapPayload(init);
- currentValue().setOffsetStart(tokenStart.start_ - begin_);
- skipSpaces();
- if (current_ != end_ && *current_ == ']') // empty array
+ this->currentValue().swapPayload(init);
+ this->currentValue().setOffsetStart(tokenStart.start_ - this->begin_);
+ this->skipSpaces();
+ if (this->current_ != this->end_ && *this->current_ == ']') // empty array
{
Token endArray;
- readToken(endArray);
+ this->readToken(endArray);
return true;
}
int index = 0;
for (;;) {
- Value& value = currentValue()[index++];
- nodes_.push(&value);
- bool ok = readValue();
- nodes_.pop();
+ Value& value = this->currentValue()[index++];
+ this->nodes_.push(&value);
+ bool ok = this->readValue();
+ this->nodes_.pop();
if (!ok) // error already set
- return recoverFromError(tokenArrayEnd);
+ return this->recoverFromError(tokenArrayEnd);
Token token;
// Accept Comment after last item in the array.
- ok = readToken(token);
+ ok = this->readToken(token);
while (token.type_ == tokenComment && ok) {
- ok = readToken(token);
+ ok = this->readToken(token);
}
bool badTokenType =
- (token.type_ != tokenArraySeparator && token.type_ != tokenArrayEnd);
+ (token.type_ != tokenArraySeparator && token.type_ != tokenArrayEnd);
if (!ok || badTokenType) {
- return addErrorAndRecover(
- "Missing ',' or ']' in array declaration", token, tokenArrayEnd);
+ return this->addErrorAndRecover(
+ "Missing ',' or ']' in array declaration", token, tokenArrayEnd);
}
if (token.type_ == tokenArrayEnd)
break;
@@ -1561,17 +1649,19 @@ bool OurReader::readArray(Token& tokenStart) {
return true;
}
-bool OurReader::decodeNumber(Token& token) {
+bool OurReader::decodeNumber(Token& token)
+{
Value decoded;
- if (!decodeNumber(token, decoded))
+ if (!this->decodeNumber(token, decoded))
return false;
- currentValue().swapPayload(decoded);
- currentValue().setOffsetStart(token.start_ - begin_);
- currentValue().setOffsetLimit(token.end_ - begin_);
+ this->currentValue().swapPayload(decoded);
+ this->currentValue().setOffsetStart(token.start_ - this->begin_);
+ this->currentValue().setOffsetLimit(token.end_ - this->begin_);
return true;
}
-bool OurReader::decodeNumber(Token& token, Value& decoded) {
+bool OurReader::decodeNumber(Token& token, Value& decoded)
+{
// Attempts to parse the number as an integer. If the number is
// larger than the maximum supported value of an integer then
// we decode the number as a double.
@@ -1579,16 +1669,17 @@ bool OurReader::decodeNumber(Token& token, Value& decoded) {
bool isNegative = *current == '-';
if (isNegative)
++current;
- // TODO: Help the compiler do the div and mod at compile time or get rid of them.
- Value::LargestUInt maxIntegerValue =
- isNegative ? Value::LargestUInt(Value::minLargestInt)
- : Value::maxLargestUInt;
+ // TODO: Help the compiler do the div and mod at compile time or get rid of
+ // them.
+ Value::LargestUInt maxIntegerValue = isNegative
+ ? Value::LargestUInt(Value::minLargestInt)
+ : Value::maxLargestUInt;
Value::LargestUInt threshold = maxIntegerValue / 10;
Value::LargestUInt value = 0;
while (current < token.end_) {
Char c = *current++;
if (c < '0' || c > '9')
- return decodeDouble(token, decoded);
+ return this->decodeDouble(token, decoded);
Value::UInt digit(static_cast<Value::UInt>(c - '0'));
if (value >= threshold) {
// We've hit or exceeded the max value divided by 10 (rounded down). If
@@ -1597,7 +1688,7 @@ bool OurReader::decodeNumber(Token& token, Value& decoded) {
// Otherwise treat this number as a double to avoid overflow.
if (value > threshold || current != token.end_ ||
digit > maxIntegerValue % 10) {
- return decodeDouble(token, decoded);
+ return this->decodeDouble(token, decoded);
}
}
value = value * 10 + digit;
@@ -1611,17 +1702,19 @@ bool OurReader::decodeNumber(Token& token, Value& decoded) {
return true;
}
-bool OurReader::decodeDouble(Token& token) {
+bool OurReader::decodeDouble(Token& token)
+{
Value decoded;
- if (!decodeDouble(token, decoded))
+ if (!this->decodeDouble(token, decoded))
return false;
- currentValue().swapPayload(decoded);
- currentValue().setOffsetStart(token.start_ - begin_);
- currentValue().setOffsetLimit(token.end_ - begin_);
+ this->currentValue().swapPayload(decoded);
+ this->currentValue().setOffsetStart(token.start_ - this->begin_);
+ this->currentValue().setOffsetLimit(token.end_ - this->begin_);
return true;
}
-bool OurReader::decodeDouble(Token& token, Value& decoded) {
+bool OurReader::decodeDouble(Token& token, Value& decoded)
+{
double value = 0;
const int bufferSize = 32;
int count;
@@ -1629,7 +1722,7 @@ bool OurReader::decodeDouble(Token& token, Value& decoded) {
// Sanity check to avoid buffer overflow exploits.
if (length < 0) {
- return addError("Unable to parse token length", token);
+ return this->addError("Unable to parse token length", token);
}
size_t const ulength = static_cast<size_t>(length);
@@ -1652,25 +1745,27 @@ bool OurReader::decodeDouble(Token& token, Value& decoded) {
}
if (count != 1)
- return addError("'" + JSONCPP_STRING(token.start_, token.end_) +
- "' is not a number.",
- token);
+ return this->addError("'" + JSONCPP_STRING(token.start_, token.end_) +
+ "' is not a number.",
+ token);
decoded = value;
return true;
}
-bool OurReader::decodeString(Token& token) {
+bool OurReader::decodeString(Token& token)
+{
JSONCPP_STRING decoded_string;
- if (!decodeString(token, decoded_string))
+ if (!this->decodeString(token, decoded_string))
return false;
Value decoded(decoded_string);
- currentValue().swapPayload(decoded);
- currentValue().setOffsetStart(token.start_ - begin_);
- currentValue().setOffsetLimit(token.end_ - begin_);
+ this->currentValue().swapPayload(decoded);
+ this->currentValue().setOffsetStart(token.start_ - this->begin_);
+ this->currentValue().setOffsetLimit(token.end_ - this->begin_);
return true;
}
-bool OurReader::decodeString(Token& token, JSONCPP_STRING& decoded) {
+bool OurReader::decodeString(Token& token, JSONCPP_STRING& decoded)
+{
decoded.reserve(static_cast<size_t>(token.end_ - token.start_ - 2));
Location current = token.start_ + 1; // skip '"'
Location end = token.end_ - 1; // do not include '"'
@@ -1680,41 +1775,43 @@ bool OurReader::decodeString(Token& token, JSONCPP_STRING& decoded) {
break;
else if (c == '\\') {
if (current == end)
- return addError("Empty escape sequence in string", token, current);
+ return this->addError("Empty escape sequence in string", token,
+ current);
Char escape = *current++;
switch (escape) {
- case '"':
- decoded += '"';
- break;
- case '/':
- decoded += '/';
- break;
- case '\\':
- decoded += '\\';
- break;
- case 'b':
- decoded += '\b';
- break;
- case 'f':
- decoded += '\f';
- break;
- case 'n':
- decoded += '\n';
- break;
- case 'r':
- decoded += '\r';
- break;
- case 't':
- decoded += '\t';
- break;
- case 'u': {
- unsigned int unicode;
- if (!decodeUnicodeCodePoint(token, current, end, unicode))
- return false;
- decoded += codePointToUTF8(unicode);
- } break;
- default:
- return addError("Bad escape sequence in string", token, current);
+ case '"':
+ decoded += '"';
+ break;
+ case '/':
+ decoded += '/';
+ break;
+ case '\\':
+ decoded += '\\';
+ break;
+ case 'b':
+ decoded += '\b';
+ break;
+ case 'f':
+ decoded += '\f';
+ break;
+ case 'n':
+ decoded += '\n';
+ break;
+ case 'r':
+ decoded += '\r';
+ break;
+ case 't':
+ decoded += '\t';
+ break;
+ case 'u': {
+ unsigned int unicode;
+ if (!this->decodeUnicodeCodePoint(token, current, end, unicode))
+ return false;
+ decoded += codePointToUTF8(unicode);
+ } break;
+ default:
+ return this->addError("Bad escape sequence in string", token,
+ current);
}
} else {
decoded += c;
@@ -1723,45 +1820,44 @@ bool OurReader::decodeString(Token& token, JSONCPP_STRING& decoded) {
return true;
}
-bool OurReader::decodeUnicodeCodePoint(Token& token,
- Location& current,
- Location end,
- unsigned int& unicode) {
+bool OurReader::decodeUnicodeCodePoint(Token& token, Location& current,
+ Location end, unsigned int& unicode)
+{
unicode = 0; // Convince scanbuild this is always initialized before use.
- if (!decodeUnicodeEscapeSequence(token, current, end, unicode))
+ if (!this->decodeUnicodeEscapeSequence(token, current, end, unicode))
return false;
if (unicode >= 0xD800 && unicode <= 0xDBFF) {
// surrogate pairs
if (end - current < 6)
- return addError(
- "additional six characters expected to parse unicode surrogate pair.",
- token,
- current);
+ return this->addError(
+ "additional six characters expected to parse unicode surrogate pair.",
+ token, current);
unsigned int surrogatePair;
if (*(current++) == '\\' && *(current++) == 'u') {
- if (decodeUnicodeEscapeSequence(token, current, end, surrogatePair)) {
- unicode = 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF);
+ if (this->decodeUnicodeEscapeSequence(token, current, end,
+ surrogatePair)) {
+ unicode =
+ 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF);
} else
return false;
} else
- return addError("expecting another \\u token to begin the second half of "
- "a unicode surrogate pair",
- token,
- current);
+ return this->addError(
+ "expecting another \\u token to begin the second half of "
+ "a unicode surrogate pair",
+ token, current);
}
return true;
}
-bool OurReader::decodeUnicodeEscapeSequence(Token& token,
- Location& current,
- Location end,
- unsigned int& ret_unicode) {
+bool OurReader::decodeUnicodeEscapeSequence(Token& token, Location& current,
+ Location end,
+ unsigned int& ret_unicode)
+{
if (end - current < 4)
- return addError(
- "Bad unicode escape sequence in string: four digits expected.",
- token,
- current);
+ return this->addError(
+ "Bad unicode escape sequence in string: four digits expected.", token,
+ current);
int unicode = 0;
for (int index = 0; index < 4; ++index) {
Char c = *current++;
@@ -1773,60 +1869,65 @@ bool OurReader::decodeUnicodeEscapeSequence(Token& token,
else if (c >= 'A' && c <= 'F')
unicode += c - 'A' + 10;
else
- return addError(
- "Bad unicode escape sequence in string: hexadecimal digit expected.",
- token,
- current);
+ return this->addError(
+ "Bad unicode escape sequence in string: hexadecimal digit expected.",
+ token, current);
}
ret_unicode = static_cast<unsigned int>(unicode);
return true;
}
-bool
-OurReader::addError(const JSONCPP_STRING& message, Token& token, Location extra) {
+bool OurReader::addError(const JSONCPP_STRING& message, Token& token,
+ Location extra)
+{
ErrorInfo info;
info.token_ = token;
info.message_ = message;
info.extra_ = extra;
- errors_.push_back(info);
+ this->errors_.push_back(info);
return false;
}
-bool OurReader::recoverFromError(TokenType skipUntilToken) {
- size_t errorCount = errors_.size();
+bool OurReader::recoverFromError(TokenType skipUntilToken)
+{
+ size_t errorCount = this->errors_.size();
Token skip;
for (;;) {
- if (!readToken(skip))
- errors_.resize(errorCount); // discard errors caused by recovery
+ if (!this->readToken(skip))
+ this->errors_.resize(errorCount); // discard errors caused by recovery
if (skip.type_ == skipUntilToken || skip.type_ == tokenEndOfStream)
break;
}
- errors_.resize(errorCount);
+ this->errors_.resize(errorCount);
return false;
}
-bool OurReader::addErrorAndRecover(const JSONCPP_STRING& message,
- Token& token,
- TokenType skipUntilToken) {
- addError(message, token);
- return recoverFromError(skipUntilToken);
+bool OurReader::addErrorAndRecover(const JSONCPP_STRING& message, Token& token,
+ TokenType skipUntilToken)
+{
+ this->addError(message, token);
+ return this->recoverFromError(skipUntilToken);
}
-Value& OurReader::currentValue() { return *(nodes_.top()); }
+Value& OurReader::currentValue()
+{
+ return *(this->nodes_.top());
+}
-OurReader::Char OurReader::getNextChar() {
- if (current_ == end_)
+OurReader::Char OurReader::getNextChar()
+{
+ if (this->current_ == this->end_)
return 0;
- return *current_++;
+ return *this->current_++;
}
-void OurReader::getLocationLineAndColumn(Location location,
- int& line,
- int& column) const {
- Location current = begin_;
+void OurReader::getLocationLineAndColumn(Location location, int& line,
+ int& column) const
+{
+ Location current = this->begin_;
Location lastLineStart = current;
line = 0;
- while (current < location && current != end_) {
+ while (current < location && current != this->end_) {
Char c = *current++;
if (c == '\r') {
if (*current == '\n')
@@ -1843,101 +1944,105 @@ void OurReader::getLocationLineAndColumn(Location location,
++line;
}
-JSONCPP_STRING OurReader::getLocationLineAndColumn(Location location) const {
+JSONCPP_STRING OurReader::getLocationLineAndColumn(Location location) const
+{
int line, column;
- getLocationLineAndColumn(location, line, column);
+ this->getLocationLineAndColumn(location, line, column);
char buffer[18 + 16 + 16 + 1];
snprintf(buffer, sizeof(buffer), "Line %d, Column %d", line, column);
return buffer;
}
-JSONCPP_STRING OurReader::getFormattedErrorMessages() const {
+JSONCPP_STRING OurReader::getFormattedErrorMessages() const
+{
JSONCPP_STRING formattedMessage;
- for (Errors::const_iterator itError = errors_.begin();
- itError != errors_.end();
- ++itError) {
+ for (Errors::const_iterator itError = this->errors_.begin();
+ itError != this->errors_.end(); ++itError) {
const ErrorInfo& error = *itError;
formattedMessage +=
- "* " + getLocationLineAndColumn(error.token_.start_) + "\n";
+ "* " + this->getLocationLineAndColumn(error.token_.start_) + "\n";
formattedMessage += " " + error.message_ + "\n";
if (error.extra_)
- formattedMessage +=
- "See " + getLocationLineAndColumn(error.extra_) + " for detail.\n";
+ formattedMessage += "See " +
+ this->getLocationLineAndColumn(error.extra_) + " for detail.\n";
}
return formattedMessage;
}
-std::vector<OurReader::StructuredError> OurReader::getStructuredErrors() const {
+std::vector<OurReader::StructuredError> OurReader::getStructuredErrors() const
+{
std::vector<OurReader::StructuredError> allErrors;
- for (Errors::const_iterator itError = errors_.begin();
- itError != errors_.end();
- ++itError) {
+ for (Errors::const_iterator itError = this->errors_.begin();
+ itError != this->errors_.end(); ++itError) {
const ErrorInfo& error = *itError;
OurReader::StructuredError structured;
- structured.offset_start = error.token_.start_ - begin_;
- structured.offset_limit = error.token_.end_ - begin_;
+ structured.offset_start = error.token_.start_ - this->begin_;
+ structured.offset_limit = error.token_.end_ - this->begin_;
structured.message = error.message_;
allErrors.push_back(structured);
}
return allErrors;
}
-bool OurReader::pushError(const Value& value, const JSONCPP_STRING& message) {
- ptrdiff_t length = end_ - begin_;
- if(value.getOffsetStart() > length
- || value.getOffsetLimit() > length)
+bool OurReader::pushError(const Value& value, const JSONCPP_STRING& message)
+{
+ ptrdiff_t length = this->end_ - this->begin_;
+ if (value.getOffsetStart() > length || value.getOffsetLimit() > length)
return false;
Token token;
token.type_ = tokenError;
- token.start_ = begin_ + value.getOffsetStart();
- token.end_ = end_ + value.getOffsetLimit();
+ token.start_ = this->begin_ + value.getOffsetStart();
+ token.end_ = this->end_ + value.getOffsetLimit();
ErrorInfo info;
info.token_ = token;
info.message_ = message;
info.extra_ = 0;
- errors_.push_back(info);
+ this->errors_.push_back(info);
return true;
}
-bool OurReader::pushError(const Value& value, const JSONCPP_STRING& message, const Value& extra) {
- ptrdiff_t length = end_ - begin_;
- if(value.getOffsetStart() > length
- || value.getOffsetLimit() > length
- || extra.getOffsetLimit() > length)
+bool OurReader::pushError(const Value& value, const JSONCPP_STRING& message,
+ const Value& extra)
+{
+ ptrdiff_t length = this->end_ - this->begin_;
+ if (value.getOffsetStart() > length || value.getOffsetLimit() > length ||
+ extra.getOffsetLimit() > length)
return false;
Token token;
token.type_ = tokenError;
- token.start_ = begin_ + value.getOffsetStart();
- token.end_ = begin_ + value.getOffsetLimit();
+ token.start_ = this->begin_ + value.getOffsetStart();
+ token.end_ = this->begin_ + value.getOffsetLimit();
ErrorInfo info;
info.token_ = token;
info.message_ = message;
- info.extra_ = begin_ + extra.getOffsetStart();
- errors_.push_back(info);
+ info.extra_ = this->begin_ + extra.getOffsetStart();
+ this->errors_.push_back(info);
return true;
}
-bool OurReader::good() const {
- return !errors_.size();
+bool OurReader::good() const
+{
+ return !this->errors_.size();
}
-
-class OurCharReader : public CharReader {
+class OurCharReader : public CharReader
+{
bool const collectComments_;
OurReader reader_;
+
public:
- OurCharReader(
- bool collectComments,
- OurFeatures const& features)
- : collectComments_(collectComments)
- , reader_(features)
- {}
- bool parse(
- char const* beginDoc, char const* endDoc,
- Value* root, JSONCPP_STRING* errs) JSONCPP_OVERRIDE {
- bool ok = reader_.parse(beginDoc, endDoc, *root, collectComments_);
+ OurCharReader(bool collectComments, OurFeatures const& features)
+ : collectComments_(collectComments)
+ , reader_(features)
+ {
+ }
+ bool parse(char const* beginDoc, char const* endDoc, Value* root,
+ JSONCPP_STRING* errs) JSONCPP_OVERRIDE
+ {
+ bool ok =
+ this->reader_.parse(beginDoc, endDoc, *root, this->collectComments_);
if (errs) {
- *errs = reader_.getFormattedErrorMessages();
+ *errs = this->reader_.getFormattedErrorMessages();
}
return ok;
}
@@ -1945,23 +2050,26 @@ public:
CharReaderBuilder::CharReaderBuilder()
{
- setDefaults(&settings_);
+ setDefaults(&this->settings_);
}
CharReaderBuilder::~CharReaderBuilder()
-{}
+{
+}
CharReader* CharReaderBuilder::newCharReader() const
{
- bool collectComments = settings_["collectComments"].asBool();
+ bool collectComments = this->settings_["collectComments"].asBool();
OurFeatures features = OurFeatures::all();
- features.allowComments_ = settings_["allowComments"].asBool();
- features.strictRoot_ = settings_["strictRoot"].asBool();
- features.allowDroppedNullPlaceholders_ = settings_["allowDroppedNullPlaceholders"].asBool();
- features.allowNumericKeys_ = settings_["allowNumericKeys"].asBool();
- features.allowSingleQuotes_ = settings_["allowSingleQuotes"].asBool();
- features.stackLimit_ = settings_["stackLimit"].asInt();
- features.failIfExtra_ = settings_["failIfExtra"].asBool();
- features.rejectDupKeys_ = settings_["rejectDupKeys"].asBool();
- features.allowSpecialFloats_ = settings_["allowSpecialFloats"].asBool();
+ features.allowComments_ = this->settings_["allowComments"].asBool();
+ features.strictRoot_ = this->settings_["strictRoot"].asBool();
+ features.allowDroppedNullPlaceholders_ =
+ this->settings_["allowDroppedNullPlaceholders"].asBool();
+ features.allowNumericKeys_ = this->settings_["allowNumericKeys"].asBool();
+ features.allowSingleQuotes_ = this->settings_["allowSingleQuotes"].asBool();
+ features.stackLimit_ = this->settings_["stackLimit"].asInt();
+ features.failIfExtra_ = this->settings_["failIfExtra"].asBool();
+ features.rejectDupKeys_ = this->settings_["rejectDupKeys"].asBool();
+ features.allowSpecialFloats_ =
+ this->settings_["allowSpecialFloats"].asBool();
return new OurCharReader(collectComments, features);
}
static void getValidReaderKeys(std::set<JSONCPP_STRING>* valid_keys)
@@ -1981,28 +2089,29 @@ static void getValidReaderKeys(std::set<JSONCPP_STRING>* valid_keys)
bool CharReaderBuilder::validate(Json::Value* invalid) const
{
Json::Value my_invalid;
- if (!invalid) invalid = &my_invalid; // so we do not need to test for NULL
+ if (!invalid)
+ invalid = &my_invalid; // so we do not need to test for NULL
Json::Value& inv = *invalid;
std::set<JSONCPP_STRING> valid_keys;
getValidReaderKeys(&valid_keys);
- Value::Members keys = settings_.getMemberNames();
+ Value::Members keys = this->settings_.getMemberNames();
size_t n = keys.size();
for (size_t i = 0; i < n; ++i) {
JSONCPP_STRING const& key = keys[i];
if (valid_keys.find(key) == valid_keys.end()) {
- inv[key] = settings_[key];
+ inv[key] = this->settings_[key];
}
}
return 0u == inv.size();
}
Value& CharReaderBuilder::operator[](JSONCPP_STRING key)
{
- return settings_[key];
+ return this->settings_[key];
}
// static
void CharReaderBuilder::strictMode(Json::Value* settings)
{
-//! [CharReaderBuilderStrictMode]
+ //! [CharReaderBuilderStrictMode]
(*settings)["allowComments"] = false;
(*settings)["strictRoot"] = true;
(*settings)["allowDroppedNullPlaceholders"] = false;
@@ -2012,12 +2121,12 @@ void CharReaderBuilder::strictMode(Json::Value* settings)
(*settings)["failIfExtra"] = true;
(*settings)["rejectDupKeys"] = true;
(*settings)["allowSpecialFloats"] = false;
-//! [CharReaderBuilderStrictMode]
+ //! [CharReaderBuilderStrictMode]
}
// static
void CharReaderBuilder::setDefaults(Json::Value* settings)
{
-//! [CharReaderBuilderDefaults]
+ //! [CharReaderBuilderDefaults]
(*settings)["collectComments"] = true;
(*settings)["allowComments"] = true;
(*settings)["strictRoot"] = false;
@@ -2028,15 +2137,14 @@ void CharReaderBuilder::setDefaults(Json::Value* settings)
(*settings)["failIfExtra"] = false;
(*settings)["rejectDupKeys"] = false;
(*settings)["allowSpecialFloats"] = false;
-//! [CharReaderBuilderDefaults]
+ //! [CharReaderBuilderDefaults]
}
//////////////////////////////////
// global functions
-bool parseFromStream(
- CharReader::Factory const& fact, JSONCPP_ISTREAM& sin,
- Value* root, JSONCPP_STRING* errs)
+bool parseFromStream(CharReader::Factory const& fact, JSONCPP_ISTREAM& sin,
+ Value* root, JSONCPP_STRING* errs)
{
JSONCPP_OSTRINGSTREAM ssin;
ssin << sin.rdbuf();
@@ -2048,14 +2156,13 @@ bool parseFromStream(
return reader->parse(begin, end, root, errs);
}
-JSONCPP_ISTREAM& operator>>(JSONCPP_ISTREAM& sin, Value& root) {
+JSONCPP_ISTREAM& operator>>(JSONCPP_ISTREAM& sin, Value& root)
+{
CharReaderBuilder b;
JSONCPP_STRING errs;
bool ok = parseFromStream(b, sin, &root, &errs);
if (!ok) {
- fprintf(stderr,
- "Error from reader: %s",
- errs.c_str());
+ fprintf(stderr, "Error from reader: %s", errs.c_str());
throwRuntimeError(errs);
}
diff --git a/Utilities/cmjsoncpp/src/lib_json/json_value.cpp b/Utilities/cmjsoncpp/src/lib_json/json_value.cpp
index f271e5731..eadb1c375 100644
--- a/Utilities/cmjsoncpp/src/lib_json/json_value.cpp
+++ b/Utilities/cmjsoncpp/src/lib_json/json_value.cpp
@@ -1,23 +1,25 @@
// Copyright 2011 Baptiste Lepilleur and The JsonCpp Authors
// Distributed under MIT license, or public domain if desired and
// recognized in your jurisdiction.
-// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
+// See file LICENSE for detail or copy at
+// http://jsoncpp.sourceforge.net/LICENSE
#if !defined(JSON_IS_AMALGAMATION)
-#include <json/assertions.h>
-#include <json/value.h>
-#include <json/writer.h>
+# include <json/assertions.h>
+# include <json/value.h>
+# include <json/writer.h>
#endif // if !defined(JSON_IS_AMALGAMATION)
-#include <math.h>
#include <sstream>
#include <utility>
-#include <string.h>
+
#include <assert.h>
+#include <math.h>
+#include <string.h>
#ifdef JSON_USE_CPPTL
-#include <cpptl/conststring.h>
+# include <cpptl/conststring.h>
#endif
-#include <cstddef> // size_t
#include <algorithm> // min()
+#include <cstddef> // size_t
#define JSON_ASSERT_UNREACHABLE assert(false)
@@ -27,24 +29,24 @@ namespace Json {
// kNull must be word-aligned to avoid crashing on ARM. We use an alignment of
// 8 (instead of 4) as a bit of future-proofing.
#if defined(__ARMEL__)
-#define ALIGNAS(byte_alignment) __attribute__((aligned(byte_alignment)))
+# define ALIGNAS(byte_alignment) __attribute__((aligned(byte_alignment)))
#else
-#define ALIGNAS(byte_alignment)
+# define ALIGNAS(byte_alignment)
#endif
-//static const unsigned char ALIGNAS(8) kNull[sizeof(Value)] = { 0 };
-//const unsigned char& kNullRef = kNull[0];
-//const Value& Value::null = reinterpret_cast<const Value&>(kNullRef);
-//const Value& Value::nullRef = null;
+// static const unsigned char ALIGNAS(8) kNull[sizeof(Value)] = { 0 };
+// const unsigned char& kNullRef = kNull[0];
+// const Value& Value::null = reinterpret_cast<const Value&>(kNullRef);
+// const Value& Value::nullRef = null;
// static
Value const& Value::nullSingleton()
{
- static Value const nullStatic;
- return nullStatic;
+ static Value const nullStatic;
+ return nullStatic;
}
-// for backwards compatibility, we'll leave these global references around, but DO NOT
-// use them in JSONCPP library code any more!
+// for backwards compatibility, we'll leave these global references around, but
+// DO NOT use them in JSONCPP library code any more!
Value const& Value::null = Value::nullSingleton();
Value const& Value::nullRef = Value::nullSingleton();
@@ -66,23 +68,29 @@ const LargestUInt Value::maxLargestUInt = LargestUInt(-1);
#if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
template <typename T, typename U>
-static inline bool InRange(double d, T min, U max) {
+static inline bool InRange(double d, T min, U max)
+{
// The casts can lose precision, but we are looking only for
// an approximate range. Might fail on edge cases though. ~cdunn
- //return d >= static_cast<double>(min) && d <= static_cast<double>(max);
+ // return d >= static_cast<double>(min) && d <= static_cast<double>(max);
return d >= min && d <= max;
}
#else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
-static inline double integerToDouble(Json::UInt64 value) {
- return static_cast<double>(Int64(value / 2)) * 2.0 + static_cast<double>(Int64(value & 1));
+static inline double integerToDouble(Json::UInt64 value)
+{
+ return static_cast<double>(Int64(value / 2)) * 2.0 +
+ static_cast<double>(Int64(value & 1));
}
-template <typename T> static inline double integerToDouble(T value) {
+template <typename T>
+static inline double integerToDouble(T value)
+{
return static_cast<double>(value);
}
template <typename T, typename U>
-static inline bool InRange(double d, T min, U max) {
+static inline bool InRange(double d, T min, U max)
+{
return d >= integerToDouble(min) && d <= integerToDouble(max);
}
#endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
@@ -94,8 +102,7 @@ static inline bool InRange(double d, T min, U max) {
* computed using strlen(value).
* @return Pointer on the duplicate instance of string.
*/
-static inline char* duplicateStringValue(const char* value,
- size_t length)
+static inline char* duplicateStringValue(const char* value, size_t length)
{
// Avoid an integer overflow in the call to malloc below by limiting length
// to a sane value.
@@ -104,9 +111,8 @@ static inline char* duplicateStringValue(const char* value,
char* newString = static_cast<char*>(malloc(length + 1));
if (newString == NULL) {
- throwRuntimeError(
- "in Json::Value::duplicateStringValue(): "
- "Failed to allocate string value buffer");
+ throwRuntimeError("in Json::Value::duplicateStringValue(): "
+ "Failed to allocate string value buffer");
}
memcpy(newString, value, length);
newString[length] = 0;
@@ -115,30 +121,30 @@ static inline char* duplicateStringValue(const char* value,
/* Record the length as a prefix.
*/
-static inline char* duplicateAndPrefixStringValue(
- const char* value,
- unsigned int length)
+static inline char* duplicateAndPrefixStringValue(const char* value,
+ unsigned int length)
{
// Avoid an integer overflow in the call to malloc below by limiting length
// to a sane value.
- JSON_ASSERT_MESSAGE(length <= static_cast<unsigned>(Value::maxInt) - sizeof(unsigned) - 1U,
+ JSON_ASSERT_MESSAGE(length <= static_cast<unsigned>(Value::maxInt) -
+ sizeof(unsigned) - 1U,
"in Json::Value::duplicateAndPrefixStringValue(): "
"length too big for prefixing");
- unsigned actualLength = length + static_cast<unsigned>(sizeof(unsigned)) + 1U;
+ unsigned actualLength =
+ length + static_cast<unsigned>(sizeof(unsigned)) + 1U;
char* newString = static_cast<char*>(malloc(actualLength));
if (newString == 0) {
- throwRuntimeError(
- "in Json::Value::duplicateAndPrefixStringValue(): "
- "Failed to allocate string value buffer");
+ throwRuntimeError("in Json::Value::duplicateAndPrefixStringValue(): "
+ "Failed to allocate string value buffer");
}
*reinterpret_cast<unsigned*>(newString) = length;
memcpy(newString + sizeof(unsigned), value, length);
- newString[actualLength - 1U] = 0; // to avoid buffer over-run accidents by users later
+ newString[actualLength - 1U] =
+ 0; // to avoid buffer over-run accidents by users later
return newString;
}
-inline static void decodePrefixedString(
- bool isPrefixed, char const* prefixed,
- unsigned* length, char const** value)
+inline static void decodePrefixedString(bool isPrefixed, char const* prefixed,
+ unsigned* length, char const** value)
{
if (!isPrefixed) {
*length = static_cast<unsigned>(strlen(prefixed));
@@ -148,10 +154,12 @@ inline static void decodePrefixedString(
*value = prefixed + sizeof(unsigned);
}
}
-/** Free the string duplicated by duplicateStringValue()/duplicateAndPrefixStringValue().
+/** Free the string duplicated by
+ * duplicateStringValue()/duplicateAndPrefixStringValue().
*/
#if JSONCPP_USING_SECURE_MEMORY
-static inline void releasePrefixedStringValue(char* value) {
+static inline void releasePrefixedStringValue(char* value)
+{
unsigned length = 0;
char const* valueDecoded;
decodePrefixedString(true, value, &length, &valueDecoded);
@@ -159,17 +167,20 @@ static inline void releasePrefixedStringValue(char* value) {
memset(value, 0, size);
free(value);
}
-static inline void releaseStringValue(char* value, unsigned length) {
+static inline void releaseStringValue(char* value, unsigned length)
+{
// length==0 => we allocated the strings memory
- size_t size = (length==0) ? strlen(value) : length;
+ size_t size = (length == 0) ? strlen(value) : length;
memset(value, 0, size);
free(value);
}
-#else // !JSONCPP_USING_SECURE_MEMORY
-static inline void releasePrefixedStringValue(char* value) {
+#else // !JSONCPP_USING_SECURE_MEMORY
+static inline void releasePrefixedStringValue(char* value)
+{
free(value);
}
-static inline void releaseStringValue(char* value, unsigned) {
+static inline void releaseStringValue(char* value, unsigned)
+{
free(value);
}
#endif // JSONCPP_USING_SECURE_MEMORY
@@ -185,26 +196,30 @@ static inline void releaseStringValue(char* value, unsigned) {
// //////////////////////////////////////////////////////////////////
#if !defined(JSON_IS_AMALGAMATION)
-#include "json_valueiterator.inl"
+# include "json_valueiterator.inl"
#endif // if !defined(JSON_IS_AMALGAMATION)
namespace Json {
Exception::Exception(JSONCPP_STRING const& msg)
: msg_(msg)
-{}
+{
+}
Exception::~Exception() JSONCPP_NOEXCEPT
-{}
+{
+}
char const* Exception::what() const JSONCPP_NOEXCEPT
{
- return msg_.c_str();
+ return this->msg_.c_str();
}
RuntimeError::RuntimeError(JSONCPP_STRING const& msg)
: Exception(msg)
-{}
+{
+}
LogicError::LogicError(JSONCPP_STRING const& msg)
: Exception(msg)
-{}
+{
+}
JSONCPP_NORETURN void throwRuntimeError(JSONCPP_STRING const& msg)
{
throw RuntimeError(msg);
@@ -222,25 +237,29 @@ JSONCPP_NORETURN void throwLogicError(JSONCPP_STRING const& msg)
// //////////////////////////////////////////////////////////////////
// //////////////////////////////////////////////////////////////////
-Value::CommentInfo::CommentInfo() : comment_(0)
-{}
+Value::CommentInfo::CommentInfo()
+ : comment_(0)
+{
+}
-Value::CommentInfo::~CommentInfo() {
- if (comment_)
- releaseStringValue(comment_, 0u);
+Value::CommentInfo::~CommentInfo()
+{
+ if (this->comment_)
+ releaseStringValue(this->comment_, 0u);
}
-void Value::CommentInfo::setComment(const char* text, size_t len) {
- if (comment_) {
- releaseStringValue(comment_, 0u);
- comment_ = 0;
+void Value::CommentInfo::setComment(const char* text, size_t len)
+{
+ if (this->comment_) {
+ releaseStringValue(this->comment_, 0u);
+ this->comment_ = 0;
}
JSON_ASSERT(text != 0);
JSON_ASSERT_MESSAGE(
- text[0] == '\0' || text[0] == '/',
- "in Json::Value::setComment(): Comments must start with /");
+ text[0] == '\0' || text[0] == '/',
+ "in Json::Value::setComment(): Comments must start with /");
// It seems that /**/ style comments are acceptable as well.
- comment_ = duplicateStringValue(text, len);
+ this->comment_ = duplicateStringValue(text, len);
}
// //////////////////////////////////////////////////////////////////
@@ -254,91 +273,130 @@ void Value::CommentInfo::setComment(const char* text, size_t len) {
// Notes: policy_ indicates if the string was allocated when
// a string is stored.
-Value::CZString::CZString(ArrayIndex aindex) : cstr_(0), index_(aindex) {}
+Value::CZString::CZString(ArrayIndex aindex)
+ : cstr_(0)
+ , index_(aindex)
+{
+}
-Value::CZString::CZString(char const* str, unsigned ulength, DuplicationPolicy allocate)
- : cstr_(str) {
+Value::CZString::CZString(char const* str, unsigned ulength,
+ DuplicationPolicy allocate)
+ : cstr_(str)
+{
// allocate != duplicate
- storage_.policy_ = allocate & 0x3;
- storage_.length_ = ulength & 0x3FFFFFFF;
+ this->storage_.policy_ = allocate & 0x3;
+ this->storage_.length_ = ulength & 0x3FFFFFFF;
}
-Value::CZString::CZString(const CZString& other) {
- cstr_ = (other.storage_.policy_ != noDuplication && other.cstr_ != 0
- ? duplicateStringValue(other.cstr_, other.storage_.length_)
- : other.cstr_);
- storage_.policy_ = static_cast<unsigned>(other.cstr_
- ? (static_cast<DuplicationPolicy>(other.storage_.policy_) == noDuplication
- ? noDuplication : duplicate)
- : static_cast<DuplicationPolicy>(other.storage_.policy_)) & 3U;
- storage_.length_ = other.storage_.length_;
+Value::CZString::CZString(const CZString& other)
+{
+ this->cstr_ = (other.storage_.policy_ != noDuplication && other.cstr_ != 0
+ ? duplicateStringValue(other.cstr_, other.storage_.length_)
+ : other.cstr_);
+ this->storage_.policy_ =
+ static_cast<unsigned>(
+ other.cstr_ ? (static_cast<DuplicationPolicy>(other.storage_.policy_) ==
+ noDuplication
+ ? noDuplication
+ : duplicate)
+ : static_cast<DuplicationPolicy>(other.storage_.policy_)) &
+ 3U;
+ this->storage_.length_ = other.storage_.length_;
}
#if JSON_HAS_RVALUE_REFERENCES
Value::CZString::CZString(CZString&& other)
- : cstr_(other.cstr_), index_(other.index_) {
+ : cstr_(other.cstr_)
+ , index_(other.index_)
+{
other.cstr_ = nullptr;
}
#endif
-Value::CZString::~CZString() {
- if (cstr_ && storage_.policy_ == duplicate) {
- releaseStringValue(const_cast<char*>(cstr_), storage_.length_ + 1u); //+1 for null terminating character for sake of completeness but not actually necessary
+Value::CZString::~CZString()
+{
+ if (this->cstr_ && this->storage_.policy_ == duplicate) {
+ releaseStringValue(const_cast<char*>(this->cstr_),
+ this->storage_.length_ +
+ 1u); //+1 for null terminating character for sake of
+ //completeness but not actually necessary
}
}
-void Value::CZString::swap(CZString& other) {
- std::swap(cstr_, other.cstr_);
- std::swap(index_, other.index_);
+void Value::CZString::swap(CZString& other)
+{
+ std::swap(this->cstr_, other.cstr_);
+ std::swap(this->index_, other.index_);
}
-Value::CZString& Value::CZString::operator=(const CZString& other) {
- cstr_ = other.cstr_;
- index_ = other.index_;
+Value::CZString& Value::CZString::operator=(const CZString& other)
+{
+ this->cstr_ = other.cstr_;
+ this->index_ = other.index_;
return *this;
}
#if JSON_HAS_RVALUE_REFERENCES
-Value::CZString& Value::CZString::operator=(CZString&& other) {
- cstr_ = other.cstr_;
- index_ = other.index_;
+Value::CZString& Value::CZString::operator=(CZString&& other)
+{
+ this->cstr_ = other.cstr_;
+ this->index_ = other.index_;
other.cstr_ = nullptr;
return *this;
}
#endif
-bool Value::CZString::operator<(const CZString& other) const {
- if (!cstr_) return index_ < other.index_;
- //return strcmp(cstr_, other.cstr_) < 0;
+bool Value::CZString::operator<(const CZString& other) const
+{
+ if (!this->cstr_)
+ return this->index_ < other.index_;
+ // return strcmp(cstr_, other.cstr_) < 0;
// Assume both are strings.
unsigned this_len = this->storage_.length_;
unsigned other_len = other.storage_.length_;
unsigned min_len = std::min<unsigned>(this_len, other_len);
JSON_ASSERT(this->cstr_ && other.cstr_);
int comp = memcmp(this->cstr_, other.cstr_, min_len);
- if (comp < 0) return true;
- if (comp > 0) return false;
+ if (comp < 0)
+ return true;
+ if (comp > 0)
+ return false;
return (this_len < other_len);
}
-bool Value::CZString::operator==(const CZString& other) const {
- if (!cstr_) return index_ == other.index_;
- //return strcmp(cstr_, other.cstr_) == 0;
+bool Value::CZString::operator==(const CZString& other) const
+{
+ if (!this->cstr_)
+ return this->index_ == other.index_;
+ // return strcmp(cstr_, other.cstr_) == 0;
// Assume both are strings.
unsigned this_len = this->storage_.length_;
unsigned other_len = other.storage_.length_;
- if (this_len != other_len) return false;
+ if (this_len != other_len)
+ return false;
JSON_ASSERT(this->cstr_ && other.cstr_);
int comp = memcmp(this->cstr_, other.cstr_, this_len);
return comp == 0;
}
-ArrayIndex Value::CZString::index() const { return index_; }
+ArrayIndex Value::CZString::index() const
+{
+ return this->index_;
+}
-//const char* Value::CZString::c_str() const { return cstr_; }
-const char* Value::CZString::data() const { return cstr_; }
-unsigned Value::CZString::length() const { return storage_.length_; }
-bool Value::CZString::isStaticString() const { return storage_.policy_ == noDuplication; }
+// const char* Value::CZString::c_str() const { return cstr_; }
+const char* Value::CZString::data() const
+{
+ return this->cstr_;
+}
+unsigned Value::CZString::length() const
+{
+ return this->storage_.length_;
+}
+bool Value::CZString::isStaticString() const
+{
+ return this->storage_.policy_ == noDuplication;
+}
// //////////////////////////////////////////////////////////////////
// //////////////////////////////////////////////////////////////////
@@ -352,210 +410,238 @@ bool Value::CZString::isStaticString() const { return storage_.policy_ == noDupl
* memset( this, 0, sizeof(Value) )
* This optimization is used in ValueInternalMap fast allocator.
*/
-Value::Value(ValueType vtype) {
+Value::Value(ValueType vtype)
+{
static char const emptyString[] = "";
- initBasic(vtype);
+ this->initBasic(vtype);
switch (vtype) {
- case nullValue:
- break;
- case intValue:
- case uintValue:
- value_.int_ = 0;
- break;
- case realValue:
- value_.real_ = 0.0;
- break;
- case stringValue:
- // allocated_ == false, so this is safe.
- value_.string_ = const_cast<char*>(static_cast<char const*>(emptyString));
- break;
- case arrayValue:
- case objectValue:
- value_.map_ = new ObjectValues();
- break;
- case booleanValue:
- value_.bool_ = false;
- break;
- default:
- JSON_ASSERT_UNREACHABLE;
+ case nullValue:
+ break;
+ case intValue:
+ case uintValue:
+ this->value_.int_ = 0;
+ break;
+ case realValue:
+ this->value_.real_ = 0.0;
+ break;
+ case stringValue:
+ // allocated_ == false, so this is safe.
+ this->value_.string_ =
+ const_cast<char*>(static_cast<char const*>(emptyString));
+ break;
+ case arrayValue:
+ case objectValue:
+ this->value_.map_ = new ObjectValues();
+ break;
+ case booleanValue:
+ this->value_.bool_ = false;
+ break;
+ default:
+ JSON_ASSERT_UNREACHABLE;
}
}
-Value::Value(Int value) {
- initBasic(intValue);
- value_.int_ = value;
+Value::Value(Int value)
+{
+ this->initBasic(intValue);
+ this->value_.int_ = value;
}
-Value::Value(UInt value) {
- initBasic(uintValue);
- value_.uint_ = value;
+Value::Value(UInt value)
+{
+ this->initBasic(uintValue);
+ this->value_.uint_ = value;
}
#if defined(JSON_HAS_INT64)
-Value::Value(Int64 value) {
- initBasic(intValue);
- value_.int_ = value;
+Value::Value(Int64 value)
+{
+ this->initBasic(intValue);
+ this->value_.int_ = value;
}
-Value::Value(UInt64 value) {
- initBasic(uintValue);
- value_.uint_ = value;
+Value::Value(UInt64 value)
+{
+ this->initBasic(uintValue);
+ this->value_.uint_ = value;
}
#endif // defined(JSON_HAS_INT64)
-Value::Value(double value) {
- initBasic(realValue);
- value_.real_ = value;
+Value::Value(double value)
+{
+ this->initBasic(realValue);
+ this->value_.real_ = value;
}
-Value::Value(const char* value) {
- initBasic(stringValue, true);
+Value::Value(const char* value)
+{
+ this->initBasic(stringValue, true);
JSON_ASSERT_MESSAGE(value != NULL, "Null Value Passed to Value Constructor");
- value_.string_ = duplicateAndPrefixStringValue(value, static_cast<unsigned>(strlen(value)));
+ this->value_.string_ =
+ duplicateAndPrefixStringValue(value, static_cast<unsigned>(strlen(value)));
}
-Value::Value(const char* beginValue, const char* endValue) {
- initBasic(stringValue, true);
- value_.string_ =
- duplicateAndPrefixStringValue(beginValue, static_cast<unsigned>(endValue - beginValue));
+Value::Value(const char* beginValue, const char* endValue)
+{
+ this->initBasic(stringValue, true);
+ this->value_.string_ = duplicateAndPrefixStringValue(
+ beginValue, static_cast<unsigned>(endValue - beginValue));
}
-Value::Value(const JSONCPP_STRING& value) {
- initBasic(stringValue, true);
- value_.string_ =
- duplicateAndPrefixStringValue(value.data(), static_cast<unsigned>(value.length()));
+Value::Value(const JSONCPP_STRING& value)
+{
+ this->initBasic(stringValue, true);
+ this->value_.string_ = duplicateAndPrefixStringValue(
+ value.data(), static_cast<unsigned>(value.length()));
}
-Value::Value(const StaticString& value) {
- initBasic(stringValue);
- value_.string_ = const_cast<char*>(value.c_str());
+Value::Value(const StaticString& value)
+{
+ this->initBasic(stringValue);
+ this->value_.string_ = const_cast<char*>(value.c_str());
}
#ifdef JSON_USE_CPPTL
-Value::Value(const CppTL::ConstString& value) {
+Value::Value(const CppTL::ConstString& value)
+{
initBasic(stringValue, true);
- value_.string_ = duplicateAndPrefixStringValue(value, static_cast<unsigned>(value.length()));
+ value_.string_ = duplicateAndPrefixStringValue(
+ value, static_cast<unsigned>(value.length()));
}
#endif
-Value::Value(bool value) {
- initBasic(booleanValue);
- value_.bool_ = value;
+Value::Value(bool value)
+{
+ this->initBasic(booleanValue);
+ this->value_.bool_ = value;
}
Value::Value(Value const& other)
- : type_(other.type_), allocated_(false)
- ,
- comments_(0), start_(other.start_), limit_(other.limit_)
-{
- switch (type_) {
- case nullValue:
- case intValue:
- case uintValue:
- case realValue:
- case booleanValue:
- value_ = other.value_;
- break;
- case stringValue:
- if (other.value_.string_ && other.allocated_) {
- unsigned len;
- char const* str;
- decodePrefixedString(other.allocated_, other.value_.string_,
- &len, &str);
- value_.string_ = duplicateAndPrefixStringValue(str, len);
- allocated_ = true;
- } else {
- value_.string_ = other.value_.string_;
- allocated_ = false;
- }
- break;
- case arrayValue:
- case objectValue:
- value_.map_ = new ObjectValues(*other.value_.map_);
- break;
- default:
- JSON_ASSERT_UNREACHABLE;
+ : type_(other.type_)
+ , allocated_(false)
+ , comments_(0)
+ , start_(other.start_)
+ , limit_(other.limit_)
+{
+ switch (this->type_) {
+ case nullValue:
+ case intValue:
+ case uintValue:
+ case realValue:
+ case booleanValue:
+ this->value_ = other.value_;
+ break;
+ case stringValue:
+ if (other.value_.string_ && other.allocated_) {
+ unsigned len;
+ char const* str;
+ decodePrefixedString(other.allocated_, other.value_.string_, &len,
+ &str);
+ this->value_.string_ = duplicateAndPrefixStringValue(str, len);
+ this->allocated_ = true;
+ } else {
+ this->value_.string_ = other.value_.string_;
+ this->allocated_ = false;
+ }
+ break;
+ case arrayValue:
+ case objectValue:
+ this->value_.map_ = new ObjectValues(*other.value_.map_);
+ break;
+ default:
+ JSON_ASSERT_UNREACHABLE;
}
if (other.comments_) {
- comments_ = new CommentInfo[numberOfCommentPlacement];
+ this->comments_ = new CommentInfo[numberOfCommentPlacement];
for (int comment = 0; comment < numberOfCommentPlacement; ++comment) {
const CommentInfo& otherComment = other.comments_[comment];
if (otherComment.comment_)
- comments_[comment].setComment(
- otherComment.comment_, strlen(otherComment.comment_));
+ this->comments_[comment].setComment(otherComment.comment_,
+ strlen(otherComment.comment_));
}
}
}
#if JSON_HAS_RVALUE_REFERENCES
// Move constructor
-Value::Value(Value&& other) {
- initBasic(nullValue);
- swap(other);
+Value::Value(Value&& other)
+{
+ this->initBasic(nullValue);
+ this->swap(other);
}
#endif
-Value::~Value() {
- switch (type_) {
- case nullValue:
- case intValue:
- case uintValue:
- case realValue:
- case booleanValue:
- break;
- case stringValue:
- if (allocated_)
- releasePrefixedStringValue(value_.string_);
- break;
- case arrayValue:
- case objectValue:
- delete value_.map_;
- break;
- default:
- JSON_ASSERT_UNREACHABLE;
+Value::~Value()
+{
+ switch (this->type_) {
+ case nullValue:
+ case intValue:
+ case uintValue:
+ case realValue:
+ case booleanValue:
+ break;
+ case stringValue:
+ if (this->allocated_)
+ releasePrefixedStringValue(this->value_.string_);
+ break;
+ case arrayValue:
+ case objectValue:
+ delete this->value_.map_;
+ break;
+ default:
+ JSON_ASSERT_UNREACHABLE;
}
- delete[] comments_;
+ delete[] this->comments_;
- value_.uint_ = 0;
+ this->value_.uint_ = 0;
}
-Value& Value::operator=(Value other) {
- swap(other);
+Value& Value::operator=(Value other)
+{
+ this->swap(other);
return *this;
}
-void Value::swapPayload(Value& other) {
- ValueType temp = type_;
- type_ = other.type_;
+void Value::swapPayload(Value& other)
+{
+ ValueType temp = this->type_;
+ this->type_ = other.type_;
other.type_ = temp;
- std::swap(value_, other.value_);
- int temp2 = allocated_;
- allocated_ = other.allocated_;
+ std::swap(this->value_, other.value_);
+ int temp2 = this->allocated_;
+ this->allocated_ = other.allocated_;
other.allocated_ = temp2 & 0x1;
}
-void Value::copyPayload(const Value& other) {
- type_ = other.type_;
- value_ = other.value_;
- allocated_ = other.allocated_;
+void Value::copyPayload(const Value& other)
+{
+ this->type_ = other.type_;
+ this->value_ = other.value_;
+ this->allocated_ = other.allocated_;
}
-void Value::swap(Value& other) {
- swapPayload(other);
- std::swap(comments_, other.comments_);
- std::swap(start_, other.start_);
- std::swap(limit_, other.limit_);
+void Value::swap(Value& other)
+{
+ this->swapPayload(other);
+ std::swap(this->comments_, other.comments_);
+ std::swap(this->start_, other.start_);
+ std::swap(this->limit_, other.limit_);
}
-void Value::copy(const Value& other) {
- copyPayload(other);
- comments_ = other.comments_;
- start_ = other.start_;
- limit_ = other.limit_;
+void Value::copy(const Value& other)
+{
+ this->copyPayload(other);
+ this->comments_ = other.comments_;
+ this->start_ = other.start_;
+ this->limit_ = other.limit_;
}
-ValueType Value::type() const { return type_; }
+ValueType Value::type() const
+{
+ return this->type_;
+}
-int Value::compare(const Value& other) const {
+int Value::compare(const Value& other) const
+{
if (*this < other)
return -1;
if (*this > other)
@@ -563,509 +649,568 @@ int Value::compare(const Value& other) const {
return 0;
}
-bool Value::operator<(const Value& other) const {
- int typeDelta = type_ - other.type_;
+bool Value::operator<(const Value& other) const
+{
+ int typeDelta = this->type_ - other.type_;
if (typeDelta)
return typeDelta < 0 ? true : false;
- switch (type_) {
- case nullValue:
- return false;
- case intValue:
- return value_.int_ < other.value_.int_;
- case uintValue:
- return value_.uint_ < other.value_.uint_;
- case realValue:
- return value_.real_ < other.value_.real_;
- case booleanValue:
- return value_.bool_ < other.value_.bool_;
- case stringValue:
- {
- if ((value_.string_ == 0) || (other.value_.string_ == 0)) {
- if (other.value_.string_) return true;
- else return false;
+ switch (this->type_) {
+ case nullValue:
+ return false;
+ case intValue:
+ return this->value_.int_ < other.value_.int_;
+ case uintValue:
+ return this->value_.uint_ < other.value_.uint_;
+ case realValue:
+ return this->value_.real_ < other.value_.real_;
+ case booleanValue:
+ return this->value_.bool_ < other.value_.bool_;
+ case stringValue: {
+ if ((this->value_.string_ == 0) || (other.value_.string_ == 0)) {
+ if (other.value_.string_)
+ return true;
+ else
+ return false;
+ }
+ unsigned this_len;
+ unsigned other_len;
+ char const* this_str;
+ char const* other_str;
+ decodePrefixedString(this->allocated_, this->value_.string_, &this_len,
+ &this_str);
+ decodePrefixedString(other.allocated_, other.value_.string_, &other_len,
+ &other_str);
+ unsigned min_len = std::min<unsigned>(this_len, other_len);
+ JSON_ASSERT(this_str && other_str);
+ int comp = memcmp(this_str, other_str, min_len);
+ if (comp < 0)
+ return true;
+ if (comp > 0)
+ return false;
+ return (this_len < other_len);
}
- unsigned this_len;
- unsigned other_len;
- char const* this_str;
- char const* other_str;
- decodePrefixedString(this->allocated_, this->value_.string_, &this_len, &this_str);
- decodePrefixedString(other.allocated_, other.value_.string_, &other_len, &other_str);
- unsigned min_len = std::min<unsigned>(this_len, other_len);
- JSON_ASSERT(this_str && other_str);
- int comp = memcmp(this_str, other_str, min_len);
- if (comp < 0) return true;
- if (comp > 0) return false;
- return (this_len < other_len);
- }
- case arrayValue:
- case objectValue: {
- int delta = int(value_.map_->size() - other.value_.map_->size());
- if (delta)
- return delta < 0;
- return (*value_.map_) < (*other.value_.map_);
- }
- default:
- JSON_ASSERT_UNREACHABLE;
+ case arrayValue:
+ case objectValue: {
+ int delta = int(this->value_.map_->size() - other.value_.map_->size());
+ if (delta)
+ return delta < 0;
+ return (*this->value_.map_) < (*other.value_.map_);
+ }
+ default:
+ JSON_ASSERT_UNREACHABLE;
}
return false; // unreachable
}
-bool Value::operator<=(const Value& other) const { return !(other < *this); }
+bool Value::operator<=(const Value& other) const
+{
+ return !(other < *this);
+}
-bool Value::operator>=(const Value& other) const { return !(*this < other); }
+bool Value::operator>=(const Value& other) const
+{
+ return !(*this < other);
+}
-bool Value::operator>(const Value& other) const { return other < *this; }
+bool Value::operator>(const Value& other) const
+{
+ return other < *this;
+}
-bool Value::operator==(const Value& other) const {
+bool Value::operator==(const Value& other) const
+{
// if ( type_ != other.type_ )
// GCC 2.95.3 says:
// attempt to take address of bit-field structure member `Json::Value::type_'
// Beats me, but a temp solves the problem.
int temp = other.type_;
- if (type_ != temp)
+ if (this->type_ != temp)
return false;
- switch (type_) {
- case nullValue:
- return true;
- case intValue:
- return value_.int_ == other.value_.int_;
- case uintValue:
- return value_.uint_ == other.value_.uint_;
- case realValue:
- return value_.real_ == other.value_.real_;
- case booleanValue:
- return value_.bool_ == other.value_.bool_;
- case stringValue:
- {
- if ((value_.string_ == 0) || (other.value_.string_ == 0)) {
- return (value_.string_ == other.value_.string_);
+ switch (this->type_) {
+ case nullValue:
+ return true;
+ case intValue:
+ return this->value_.int_ == other.value_.int_;
+ case uintValue:
+ return this->value_.uint_ == other.value_.uint_;
+ case realValue:
+ return this->value_.real_ == other.value_.real_;
+ case booleanValue:
+ return this->value_.bool_ == other.value_.bool_;
+ case stringValue: {
+ if ((this->value_.string_ == 0) || (other.value_.string_ == 0)) {
+ return (this->value_.string_ == other.value_.string_);
+ }
+ unsigned this_len;
+ unsigned other_len;
+ char const* this_str;
+ char const* other_str;
+ decodePrefixedString(this->allocated_, this->value_.string_, &this_len,
+ &this_str);
+ decodePrefixedString(other.allocated_, other.value_.string_, &other_len,
+ &other_str);
+ if (this_len != other_len)
+ return false;
+ JSON_ASSERT(this_str && other_str);
+ int comp = memcmp(this_str, other_str, this_len);
+ return comp == 0;
}
- unsigned this_len;
- unsigned other_len;
- char const* this_str;
- char const* other_str;
- decodePrefixedString(this->allocated_, this->value_.string_, &this_len, &this_str);
- decodePrefixedString(other.allocated_, other.value_.string_, &other_len, &other_str);
- if (this_len != other_len) return false;
- JSON_ASSERT(this_str && other_str);
- int comp = memcmp(this_str, other_str, this_len);
- return comp == 0;
- }
- case arrayValue:
- case objectValue:
- return value_.map_->size() == other.value_.map_->size() &&
- (*value_.map_) == (*other.value_.map_);
- default:
- JSON_ASSERT_UNREACHABLE;
+ case arrayValue:
+ case objectValue:
+ return this->value_.map_->size() == other.value_.map_->size() &&
+ (*this->value_.map_) == (*other.value_.map_);
+ default:
+ JSON_ASSERT_UNREACHABLE;
}
return false; // unreachable
}
-bool Value::operator!=(const Value& other) const { return !(*this == other); }
+bool Value::operator!=(const Value& other) const
+{
+ return !(*this == other);
+}
-const char* Value::asCString() const {
+const char* Value::asCString() const
+{
JSON_ASSERT_MESSAGE(type_ == stringValue,
"in Json::Value::asCString(): requires stringValue");
- if (value_.string_ == 0) return 0;
+ if (this->value_.string_ == 0)
+ return 0;
unsigned this_len;
char const* this_str;
- decodePrefixedString(this->allocated_, this->value_.string_, &this_len, &this_str);
+ decodePrefixedString(this->allocated_, this->value_.string_, &this_len,
+ &this_str);
return this_str;
}
#if JSONCPP_USING_SECURE_MEMORY
-unsigned Value::getCStringLength() const {
+unsigned Value::getCStringLength() const
+{
JSON_ASSERT_MESSAGE(type_ == stringValue,
- "in Json::Value::asCString(): requires stringValue");
- if (value_.string_ == 0) return 0;
+ "in Json::Value::asCString(): requires stringValue");
+ if (value_.string_ == 0)
+ return 0;
unsigned this_len;
char const* this_str;
- decodePrefixedString(this->allocated_, this->value_.string_, &this_len, &this_str);
+ decodePrefixedString(this->allocated_, this->value_.string_, &this_len,
+ &this_str);
return this_len;
}
#endif
-bool Value::getString(char const** str, char const** cend) const {
- if (type_ != stringValue) return false;
- if (value_.string_ == 0) return false;
+bool Value::getString(char const** str, char const** cend) const
+{
+ if (this->type_ != stringValue)
+ return false;
+ if (this->value_.string_ == 0)
+ return false;
unsigned length;
decodePrefixedString(this->allocated_, this->value_.string_, &length, str);
*cend = *str + length;
return true;
}
-JSONCPP_STRING Value::asString() const {
- switch (type_) {
- case nullValue:
- return "";
- case stringValue:
- {
- if (value_.string_ == 0) return "";
- unsigned this_len;
- char const* this_str;
- decodePrefixedString(this->allocated_, this->value_.string_, &this_len, &this_str);
- return JSONCPP_STRING(this_str, this_len);
- }
- case booleanValue:
- return value_.bool_ ? "true" : "false";
- case intValue:
- return valueToString(value_.int_);
- case uintValue:
- return valueToString(value_.uint_);
- case realValue:
- return valueToString(value_.real_);
- default:
- JSON_FAIL_MESSAGE("Type is not convertible to string");
+JSONCPP_STRING Value::asString() const
+{
+ switch (this->type_) {
+ case nullValue:
+ return "";
+ case stringValue: {
+ if (this->value_.string_ == 0)
+ return "";
+ unsigned this_len;
+ char const* this_str;
+ decodePrefixedString(this->allocated_, this->value_.string_, &this_len,
+ &this_str);
+ return JSONCPP_STRING(this_str, this_len);
+ }
+ case booleanValue:
+ return this->value_.bool_ ? "true" : "false";
+ case intValue:
+ return valueToString(this->value_.int_);
+ case uintValue:
+ return valueToString(this->value_.uint_);
+ case realValue:
+ return valueToString(this->value_.real_);
+ default:
+ JSON_FAIL_MESSAGE("Type is not convertible to string");
}
}
#ifdef JSON_USE_CPPTL
-CppTL::ConstString Value::asConstString() const {
+CppTL::ConstString Value::asConstString() const
+{
unsigned len;
char const* str;
- decodePrefixedString(allocated_, value_.string_,
- &len, &str);
+ decodePrefixedString(allocated_, value_.string_, &len, &str);
return CppTL::ConstString(str, len);
}
#endif
-Value::Int Value::asInt() const {
- switch (type_) {
- case intValue:
- JSON_ASSERT_MESSAGE(isInt(), "LargestInt out of Int range");
- return Int(value_.int_);
- case uintValue:
- JSON_ASSERT_MESSAGE(isInt(), "LargestUInt out of Int range");
- return Int(value_.uint_);
- case realValue:
- JSON_ASSERT_MESSAGE(InRange(value_.real_, minInt, maxInt),
- "double out of Int range");
- return Int(value_.real_);
- case nullValue:
- return 0;
- case booleanValue:
- return value_.bool_ ? 1 : 0;
- default:
- break;
+Value::Int Value::asInt() const
+{
+ switch (this->type_) {
+ case intValue:
+ JSON_ASSERT_MESSAGE(isInt(), "LargestInt out of Int range");
+ return Int(this->value_.int_);
+ case uintValue:
+ JSON_ASSERT_MESSAGE(isInt(), "LargestUInt out of Int range");
+ return Int(this->value_.uint_);
+ case realValue:
+ JSON_ASSERT_MESSAGE(InRange(value_.real_, minInt, maxInt),
+ "double out of Int range");
+ return Int(this->value_.real_);
+ case nullValue:
+ return 0;
+ case booleanValue:
+ return this->value_.bool_ ? 1 : 0;
+ default:
+ break;
}
JSON_FAIL_MESSAGE("Value is not convertible to Int.");
}
-Value::UInt Value::asUInt() const {
- switch (type_) {
- case intValue:
- JSON_ASSERT_MESSAGE(isUInt(), "LargestInt out of UInt range");
- return UInt(value_.int_);
- case uintValue:
- JSON_ASSERT_MESSAGE(isUInt(), "LargestUInt out of UInt range");
- return UInt(value_.uint_);
- case realValue:
- JSON_ASSERT_MESSAGE(InRange(value_.real_, 0, maxUInt),
- "double out of UInt range");
- return UInt(value_.real_);
- case nullValue:
- return 0;
- case booleanValue:
- return value_.bool_ ? 1 : 0;
- default:
- break;
+Value::UInt Value::asUInt() const
+{
+ switch (this->type_) {
+ case intValue:
+ JSON_ASSERT_MESSAGE(isUInt(), "LargestInt out of UInt range");
+ return UInt(this->value_.int_);
+ case uintValue:
+ JSON_ASSERT_MESSAGE(isUInt(), "LargestUInt out of UInt range");
+ return UInt(this->value_.uint_);
+ case realValue:
+ JSON_ASSERT_MESSAGE(InRange(value_.real_, 0, maxUInt),
+ "double out of UInt range");
+ return UInt(this->value_.real_);
+ case nullValue:
+ return 0;
+ case booleanValue:
+ return this->value_.bool_ ? 1 : 0;
+ default:
+ break;
}
JSON_FAIL_MESSAGE("Value is not convertible to UInt.");
}
#if defined(JSON_HAS_INT64)
-Value::Int64 Value::asInt64() const {
- switch (type_) {
- case intValue:
- return Int64(value_.int_);
- case uintValue:
- JSON_ASSERT_MESSAGE(isInt64(), "LargestUInt out of Int64 range");
- return Int64(value_.uint_);
- case realValue:
- JSON_ASSERT_MESSAGE(InRange(value_.real_, minInt64, maxInt64),
- "double out of Int64 range");
- return Int64(value_.real_);
- case nullValue:
- return 0;
- case booleanValue:
- return value_.bool_ ? 1 : 0;
- default:
- break;
+Value::Int64 Value::asInt64() const
+{
+ switch (this->type_) {
+ case intValue:
+ return Int64(this->value_.int_);
+ case uintValue:
+ JSON_ASSERT_MESSAGE(isInt64(), "LargestUInt out of Int64 range");
+ return Int64(this->value_.uint_);
+ case realValue:
+ JSON_ASSERT_MESSAGE(InRange(value_.real_, minInt64, maxInt64),
+ "double out of Int64 range");
+ return Int64(this->value_.real_);
+ case nullValue:
+ return 0;
+ case booleanValue:
+ return this->value_.bool_ ? 1 : 0;
+ default:
+ break;
}
JSON_FAIL_MESSAGE("Value is not convertible to Int64.");
}
-Value::UInt64 Value::asUInt64() const {
- switch (type_) {
- case intValue:
- JSON_ASSERT_MESSAGE(isUInt64(), "LargestInt out of UInt64 range");
- return UInt64(value_.int_);
- case uintValue:
- return UInt64(value_.uint_);
- case realValue:
- JSON_ASSERT_MESSAGE(InRange(value_.real_, 0, maxUInt64),
- "double out of UInt64 range");
- return UInt64(value_.real_);
- case nullValue:
- return 0;
- case booleanValue:
- return value_.bool_ ? 1 : 0;
- default:
- break;
+Value::UInt64 Value::asUInt64() const
+{
+ switch (this->type_) {
+ case intValue:
+ JSON_ASSERT_MESSAGE(isUInt64(), "LargestInt out of UInt64 range");
+ return UInt64(this->value_.int_);
+ case uintValue:
+ return UInt64(this->value_.uint_);
+ case realValue:
+ JSON_ASSERT_MESSAGE(InRange(value_.real_, 0, maxUInt64),
+ "double out of UInt64 range");
+ return UInt64(this->value_.real_);
+ case nullValue:
+ return 0;
+ case booleanValue:
+ return this->value_.bool_ ? 1 : 0;
+ default:
+ break;
}
JSON_FAIL_MESSAGE("Value is not convertible to UInt64.");
}
#endif // if defined(JSON_HAS_INT64)
-LargestInt Value::asLargestInt() const {
+LargestInt Value::asLargestInt() const
+{
#if defined(JSON_NO_INT64)
return asInt();
#else
- return asInt64();
+ return this->asInt64();
#endif
}
-LargestUInt Value::asLargestUInt() const {
+LargestUInt Value::asLargestUInt() const
+{
#if defined(JSON_NO_INT64)
return asUInt();
#else
- return asUInt64();
+ return this->asUInt64();
#endif
}
-double Value::asDouble() const {
- switch (type_) {
- case intValue:
- return static_cast<double>(value_.int_);
- case uintValue:
+double Value::asDouble() const
+{
+ switch (this->type_) {
+ case intValue:
+ return static_cast<double>(this->value_.int_);
+ case uintValue:
#if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
- return static_cast<double>(value_.uint_);
+ return static_cast<double>(this->value_.uint_);
#else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
- return integerToDouble(value_.uint_);
+ return integerToDouble(value_.uint_);
#endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
- case realValue:
- return value_.real_;
- case nullValue:
- return 0.0;
- case booleanValue:
- return value_.bool_ ? 1.0 : 0.0;
- default:
- break;
+ case realValue:
+ return this->value_.real_;
+ case nullValue:
+ return 0.0;
+ case booleanValue:
+ return this->value_.bool_ ? 1.0 : 0.0;
+ default:
+ break;
}
JSON_FAIL_MESSAGE("Value is not convertible to double.");
}
-float Value::asFloat() const {
- switch (type_) {
- case intValue:
- return static_cast<float>(value_.int_);
- case uintValue:
+float Value::asFloat() const
+{
+ switch (this->type_) {
+ case intValue:
+ return static_cast<float>(this->value_.int_);
+ case uintValue:
#if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
- return static_cast<float>(value_.uint_);
+ return static_cast<float>(this->value_.uint_);
#else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
- // This can fail (silently?) if the value is bigger than MAX_FLOAT.
- return static_cast<float>(integerToDouble(value_.uint_));
+ // This can fail (silently?) if the value is bigger than MAX_FLOAT.
+ return static_cast<float>(integerToDouble(value_.uint_));
#endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
- case realValue:
- return static_cast<float>(value_.real_);
- case nullValue:
- return 0.0;
- case booleanValue:
- return value_.bool_ ? 1.0f : 0.0f;
- default:
- break;
+ case realValue:
+ return static_cast<float>(this->value_.real_);
+ case nullValue:
+ return 0.0;
+ case booleanValue:
+ return this->value_.bool_ ? 1.0f : 0.0f;
+ default:
+ break;
}
JSON_FAIL_MESSAGE("Value is not convertible to float.");
}
-bool Value::asBool() const {
- switch (type_) {
- case booleanValue:
- return value_.bool_;
- case nullValue:
- return false;
- case intValue:
- return value_.int_ ? true : false;
- case uintValue:
- return value_.uint_ ? true : false;
- case realValue:
- // This is kind of strange. Not recommended.
- return (value_.real_ != 0.0) ? true : false;
- default:
- break;
+bool Value::asBool() const
+{
+ switch (this->type_) {
+ case booleanValue:
+ return this->value_.bool_;
+ case nullValue:
+ return false;
+ case intValue:
+ return this->value_.int_ ? true : false;
+ case uintValue:
+ return this->value_.uint_ ? true : false;
+ case realValue:
+ // This is kind of strange. Not recommended.
+ return (this->value_.real_ != 0.0) ? true : false;
+ default:
+ break;
}
JSON_FAIL_MESSAGE("Value is not convertible to bool.");
}
-bool Value::isConvertibleTo(ValueType other) const {
+bool Value::isConvertibleTo(ValueType other) const
+{
switch (other) {
- case nullValue:
- return (isNumeric() && asDouble() == 0.0) ||
- (type_ == booleanValue && value_.bool_ == false) ||
- (type_ == stringValue && asString().empty()) ||
- (type_ == arrayValue && value_.map_->size() == 0) ||
- (type_ == objectValue && value_.map_->size() == 0) ||
- type_ == nullValue;
- case intValue:
- return isInt() ||
- (type_ == realValue && InRange(value_.real_, minInt, maxInt)) ||
- type_ == booleanValue || type_ == nullValue;
- case uintValue:
- return isUInt() ||
- (type_ == realValue && InRange(value_.real_, 0, maxUInt)) ||
- type_ == booleanValue || type_ == nullValue;
- case realValue:
- return isNumeric() || type_ == booleanValue || type_ == nullValue;
- case booleanValue:
- return isNumeric() || type_ == booleanValue || type_ == nullValue;
- case stringValue:
- return isNumeric() || type_ == booleanValue || type_ == stringValue ||
- type_ == nullValue;
- case arrayValue:
- return type_ == arrayValue || type_ == nullValue;
- case objectValue:
- return type_ == objectValue || type_ == nullValue;
+ case nullValue:
+ return (this->isNumeric() && this->asDouble() == 0.0) ||
+ (this->type_ == booleanValue && this->value_.bool_ == false) ||
+ (this->type_ == stringValue && this->asString().empty()) ||
+ (this->type_ == arrayValue && this->value_.map_->size() == 0) ||
+ (this->type_ == objectValue && this->value_.map_->size() == 0) ||
+ this->type_ == nullValue;
+ case intValue:
+ return this->isInt() ||
+ (this->type_ == realValue &&
+ InRange(this->value_.real_, minInt, maxInt)) ||
+ this->type_ == booleanValue || this->type_ == nullValue;
+ case uintValue:
+ return this->isUInt() ||
+ (this->type_ == realValue &&
+ InRange(this->value_.real_, 0, maxUInt)) ||
+ this->type_ == booleanValue || this->type_ == nullValue;
+ case realValue:
+ return this->isNumeric() || this->type_ == booleanValue ||
+ this->type_ == nullValue;
+ case booleanValue:
+ return this->isNumeric() || this->type_ == booleanValue ||
+ this->type_ == nullValue;
+ case stringValue:
+ return this->isNumeric() || this->type_ == booleanValue ||
+ this->type_ == stringValue || this->type_ == nullValue;
+ case arrayValue:
+ return this->type_ == arrayValue || this->type_ == nullValue;
+ case objectValue:
+ return this->type_ == objectValue || this->type_ == nullValue;
}
JSON_ASSERT_UNREACHABLE;
return false;
}
/// Number of values in array or object
-ArrayIndex Value::size() const {
- switch (type_) {
- case nullValue:
- case intValue:
- case uintValue:
- case realValue:
- case booleanValue:
- case stringValue:
- return 0;
- case arrayValue: // size of the array is highest index + 1
- if (!value_.map_->empty()) {
- ObjectValues::const_iterator itLast = value_.map_->end();
- --itLast;
- return (*itLast).first.index() + 1;
- }
- return 0;
- case objectValue:
- return ArrayIndex(value_.map_->size());
+ArrayIndex Value::size() const
+{
+ switch (this->type_) {
+ case nullValue:
+ case intValue:
+ case uintValue:
+ case realValue:
+ case booleanValue:
+ case stringValue:
+ return 0;
+ case arrayValue: // size of the array is highest index + 1
+ if (!this->value_.map_->empty()) {
+ ObjectValues::const_iterator itLast = this->value_.map_->end();
+ --itLast;
+ return (*itLast).first.index() + 1;
+ }
+ return 0;
+ case objectValue:
+ return ArrayIndex(this->value_.map_->size());
}
JSON_ASSERT_UNREACHABLE;
return 0; // unreachable;
}
-bool Value::empty() const {
- if (isNull() || isArray() || isObject())
- return size() == 0u;
+bool Value::empty() const
+{
+ if (this->isNull() || this->isArray() || this->isObject())
+ return this->size() == 0u;
else
return false;
}
-bool Value::operator!() const { return isNull(); }
+bool Value::operator!() const
+{
+ return this->isNull();
+}
-void Value::clear() {
+void Value::clear()
+{
JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == arrayValue ||
- type_ == objectValue,
+ type_ == objectValue,
"in Json::Value::clear(): requires complex value");
- start_ = 0;
- limit_ = 0;
- switch (type_) {
- case arrayValue:
- case objectValue:
- value_.map_->clear();
- break;
- default:
- break;
+ this->start_ = 0;
+ this->limit_ = 0;
+ switch (this->type_) {
+ case arrayValue:
+ case objectValue:
+ this->value_.map_->clear();
+ break;
+ default:
+ break;
}
}
-void Value::resize(ArrayIndex newSize) {
+void Value::resize(ArrayIndex newSize)
+{
JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == arrayValue,
"in Json::Value::resize(): requires arrayValue");
- if (type_ == nullValue)
+ if (this->type_ == nullValue)
*this = Value(arrayValue);
- ArrayIndex oldSize = size();
+ ArrayIndex oldSize = this->size();
if (newSize == 0)
- clear();
+ this->clear();
else if (newSize > oldSize)
(*this)[newSize - 1];
else {
for (ArrayIndex index = newSize; index < oldSize; ++index) {
- value_.map_->erase(index);
+ this->value_.map_->erase(index);
}
JSON_ASSERT(size() == newSize);
}
}
-Value& Value::operator[](ArrayIndex index) {
+Value& Value::operator[](ArrayIndex index)
+{
JSON_ASSERT_MESSAGE(
- type_ == nullValue || type_ == arrayValue,
- "in Json::Value::operator[](ArrayIndex): requires arrayValue");
- if (type_ == nullValue)
+ type_ == nullValue || type_ == arrayValue,
+ "in Json::Value::operator[](ArrayIndex): requires arrayValue");
+ if (this->type_ == nullValue)
*this = Value(arrayValue);
CZString key(index);
- ObjectValues::iterator it = value_.map_->lower_bound(key);
- if (it != value_.map_->end() && (*it).first == key)
+ ObjectValues::iterator it = this->value_.map_->lower_bound(key);
+ if (it != this->value_.map_->end() && (*it).first == key)
return (*it).second;
ObjectValues::value_type defaultValue(key, nullSingleton());
- it = value_.map_->insert(it, defaultValue);
+ it = this->value_.map_->insert(it, defaultValue);
return (*it).second;
}
-Value& Value::operator[](int index) {
+Value& Value::operator[](int index)
+{
JSON_ASSERT_MESSAGE(
- index >= 0,
- "in Json::Value::operator[](int index): index cannot be negative");
+ index >= 0,
+ "in Json::Value::operator[](int index): index cannot be negative");
return (*this)[ArrayIndex(index)];
}
-const Value& Value::operator[](ArrayIndex index) const {
+const Value& Value::operator[](ArrayIndex index) const
+{
JSON_ASSERT_MESSAGE(
- type_ == nullValue || type_ == arrayValue,
- "in Json::Value::operator[](ArrayIndex)const: requires arrayValue");
- if (type_ == nullValue)
+ type_ == nullValue || type_ == arrayValue,
+ "in Json::Value::operator[](ArrayIndex)const: requires arrayValue");
+ if (this->type_ == nullValue)
return nullSingleton();
CZString key(index);
- ObjectValues::const_iterator it = value_.map_->find(key);
- if (it == value_.map_->end())
+ ObjectValues::const_iterator it = this->value_.map_->find(key);
+ if (it == this->value_.map_->end())
return nullSingleton();
return (*it).second;
}
-const Value& Value::operator[](int index) const {
+const Value& Value::operator[](int index) const
+{
JSON_ASSERT_MESSAGE(
- index >= 0,
- "in Json::Value::operator[](int index) const: index cannot be negative");
+ index >= 0,
+ "in Json::Value::operator[](int index) const: index cannot be negative");
return (*this)[ArrayIndex(index)];
}
-void Value::initBasic(ValueType vtype, bool allocated) {
- type_ = vtype;
- allocated_ = allocated;
- comments_ = 0;
- start_ = 0;
- limit_ = 0;
+void Value::initBasic(ValueType vtype, bool allocated)
+{
+ this->type_ = vtype;
+ this->allocated_ = allocated;
+ this->comments_ = 0;
+ this->start_ = 0;
+ this->limit_ = 0;
}
// Access an object value by name, create a null member if it does not exist.
// @pre Type of '*this' is object or null.
// @param key is null-terminated.
-Value& Value::resolveReference(const char* key) {
+Value& Value::resolveReference(const char* key)
+{
JSON_ASSERT_MESSAGE(
- type_ == nullValue || type_ == objectValue,
- "in Json::Value::resolveReference(): requires objectValue");
- if (type_ == nullValue)
+ type_ == nullValue || type_ == objectValue,
+ "in Json::Value::resolveReference(): requires objectValue");
+ if (this->type_ == nullValue)
*this = Value(objectValue);
- CZString actualKey(
- key, static_cast<unsigned>(strlen(key)), CZString::noDuplication); // NOTE!
- ObjectValues::iterator it = value_.map_->lower_bound(actualKey);
- if (it != value_.map_->end() && (*it).first == actualKey)
+ CZString actualKey(key, static_cast<unsigned>(strlen(key)),
+ CZString::noDuplication); // NOTE!
+ ObjectValues::iterator it = this->value_.map_->lower_bound(actualKey);
+ if (it != this->value_.map_->end() && (*it).first == actualKey)
return (*it).second;
ObjectValues::value_type defaultValue(actualKey, nullSingleton());
- it = value_.map_->insert(it, defaultValue);
+ it = this->value_.map_->insert(it, defaultValue);
Value& value = (*it).second;
return value;
}
@@ -1074,198 +1219,223 @@ Value& Value::resolveReference(const char* key) {
Value& Value::resolveReference(char const* key, char const* cend)
{
JSON_ASSERT_MESSAGE(
- type_ == nullValue || type_ == objectValue,
- "in Json::Value::resolveReference(key, end): requires objectValue");
- if (type_ == nullValue)
+ type_ == nullValue || type_ == objectValue,
+ "in Json::Value::resolveReference(key, end): requires objectValue");
+ if (this->type_ == nullValue)
*this = Value(objectValue);
- CZString actualKey(
- key, static_cast<unsigned>(cend-key), CZString::duplicateOnCopy);
- ObjectValues::iterator it = value_.map_->lower_bound(actualKey);
- if (it != value_.map_->end() && (*it).first == actualKey)
+ CZString actualKey(key, static_cast<unsigned>(cend - key),
+ CZString::duplicateOnCopy);
+ ObjectValues::iterator it = this->value_.map_->lower_bound(actualKey);
+ if (it != this->value_.map_->end() && (*it).first == actualKey)
return (*it).second;
ObjectValues::value_type defaultValue(actualKey, nullSingleton());
- it = value_.map_->insert(it, defaultValue);
+ it = this->value_.map_->insert(it, defaultValue);
Value& value = (*it).second;
return value;
}
-Value Value::get(ArrayIndex index, const Value& defaultValue) const {
+Value Value::get(ArrayIndex index, const Value& defaultValue) const
+{
const Value* value = &((*this)[index]);
return value == &nullSingleton() ? defaultValue : *value;
}
-bool Value::isValidIndex(ArrayIndex index) const { return index < size(); }
+bool Value::isValidIndex(ArrayIndex index) const
+{
+ return index < this->size();
+}
Value const* Value::find(char const* key, char const* cend) const
{
- JSON_ASSERT_MESSAGE(
- type_ == nullValue || type_ == objectValue,
- "in Json::Value::find(key, end, found): requires objectValue or nullValue");
- if (type_ == nullValue) return NULL;
- CZString actualKey(key, static_cast<unsigned>(cend-key), CZString::noDuplication);
- ObjectValues::const_iterator it = value_.map_->find(actualKey);
- if (it == value_.map_->end()) return NULL;
+ JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == objectValue,
+ "in Json::Value::find(key, end, found): requires "
+ "objectValue or nullValue");
+ if (this->type_ == nullValue)
+ return NULL;
+ CZString actualKey(key, static_cast<unsigned>(cend - key),
+ CZString::noDuplication);
+ ObjectValues::const_iterator it = this->value_.map_->find(actualKey);
+ if (it == this->value_.map_->end())
+ return NULL;
return &(*it).second;
}
const Value& Value::operator[](const char* key) const
{
- Value const* found = find(key, key + strlen(key));
- if (!found) return nullSingleton();
+ Value const* found = this->find(key, key + strlen(key));
+ if (!found)
+ return nullSingleton();
return *found;
}
Value const& Value::operator[](JSONCPP_STRING const& key) const
{
- Value const* found = find(key.data(), key.data() + key.length());
- if (!found) return nullSingleton();
+ Value const* found = this->find(key.data(), key.data() + key.length());
+ if (!found)
+ return nullSingleton();
return *found;
}
-Value& Value::operator[](const char* key) {
- return resolveReference(key, key + strlen(key));
+Value& Value::operator[](const char* key)
+{
+ return this->resolveReference(key, key + strlen(key));
}
-Value& Value::operator[](const JSONCPP_STRING& key) {
- return resolveReference(key.data(), key.data() + key.length());
+Value& Value::operator[](const JSONCPP_STRING& key)
+{
+ return this->resolveReference(key.data(), key.data() + key.length());
}
-Value& Value::operator[](const StaticString& key) {
- return resolveReference(key.c_str());
+Value& Value::operator[](const StaticString& key)
+{
+ return this->resolveReference(key.c_str());
}
#ifdef JSON_USE_CPPTL
-Value& Value::operator[](const CppTL::ConstString& key) {
+Value& Value::operator[](const CppTL::ConstString& key)
+{
return resolveReference(key.c_str(), key.end_c_str());
}
Value const& Value::operator[](CppTL::ConstString const& key) const
{
Value const* found = find(key.c_str(), key.end_c_str());
- if (!found) return nullSingleton();
+ if (!found)
+ return nullSingleton();
return *found;
}
#endif
-Value& Value::append(const Value& value) { return (*this)[size()] = value; }
+Value& Value::append(const Value& value)
+{
+ return (*this)[this->size()] = value;
+}
#if JSON_HAS_RVALUE_REFERENCES
- Value& Value::append(Value&& value) { return (*this)[size()] = value; }
+Value& Value::append(Value&& value)
+{
+ return (*this)[this->size()] = value;
+}
#endif
-Value Value::get(char const* key, char const* cend, Value const& defaultValue) const
+Value Value::get(char const* key, char const* cend,
+ Value const& defaultValue) const
{
- Value const* found = find(key, cend);
+ Value const* found = this->find(key, cend);
return !found ? defaultValue : *found;
}
Value Value::get(char const* key, Value const& defaultValue) const
{
- return get(key, key + strlen(key), defaultValue);
+ return this->get(key, key + strlen(key), defaultValue);
}
Value Value::get(JSONCPP_STRING const& key, Value const& defaultValue) const
{
- return get(key.data(), key.data() + key.length(), defaultValue);
+ return this->get(key.data(), key.data() + key.length(), defaultValue);
}
-
bool Value::removeMember(const char* key, const char* cend, Value* removed)
{
- if (type_ != objectValue) {
+ if (this->type_ != objectValue) {
return false;
}
- CZString actualKey(key, static_cast<unsigned>(cend-key), CZString::noDuplication);
- ObjectValues::iterator it = value_.map_->find(actualKey);
- if (it == value_.map_->end())
+ CZString actualKey(key, static_cast<unsigned>(cend - key),
+ CZString::noDuplication);
+ ObjectValues::iterator it = this->value_.map_->find(actualKey);
+ if (it == this->value_.map_->end())
return false;
*removed = it->second;
- value_.map_->erase(it);
+ this->value_.map_->erase(it);
return true;
}
bool Value::removeMember(const char* key, Value* removed)
{
- return removeMember(key, key + strlen(key), removed);
+ return this->removeMember(key, key + strlen(key), removed);
}
bool Value::removeMember(JSONCPP_STRING const& key, Value* removed)
{
- return removeMember(key.data(), key.data() + key.length(), removed);
+ return this->removeMember(key.data(), key.data() + key.length(), removed);
}
Value Value::removeMember(const char* key)
{
JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == objectValue,
"in Json::Value::removeMember(): requires objectValue");
- if (type_ == nullValue)
+ if (this->type_ == nullValue)
return nullSingleton();
- Value removed; // null
- removeMember(key, key + strlen(key), &removed);
+ Value removed; // null
+ this->removeMember(key, key + strlen(key), &removed);
return removed; // still null if removeMember() did nothing
}
Value Value::removeMember(const JSONCPP_STRING& key)
{
- return removeMember(key.c_str());
+ return this->removeMember(key.c_str());
}
-bool Value::removeIndex(ArrayIndex index, Value* removed) {
- if (type_ != arrayValue) {
+bool Value::removeIndex(ArrayIndex index, Value* removed)
+{
+ if (this->type_ != arrayValue) {
return false;
}
CZString key(index);
- ObjectValues::iterator it = value_.map_->find(key);
- if (it == value_.map_->end()) {
+ ObjectValues::iterator it = this->value_.map_->find(key);
+ if (it == this->value_.map_->end()) {
return false;
}
*removed = it->second;
- ArrayIndex oldSize = size();
+ ArrayIndex oldSize = this->size();
// shift left all items left, into the place of the "removed"
- for (ArrayIndex i = index; i < (oldSize - 1); ++i){
+ for (ArrayIndex i = index; i < (oldSize - 1); ++i) {
CZString keey(i);
- (*value_.map_)[keey] = (*this)[i + 1];
+ (*this->value_.map_)[keey] = (*this)[i + 1];
}
// erase the last one ("leftover")
CZString keyLast(oldSize - 1);
- ObjectValues::iterator itLast = value_.map_->find(keyLast);
- value_.map_->erase(itLast);
+ ObjectValues::iterator itLast = this->value_.map_->find(keyLast);
+ this->value_.map_->erase(itLast);
return true;
}
#ifdef JSON_USE_CPPTL
Value Value::get(const CppTL::ConstString& key,
- const Value& defaultValue) const {
+ const Value& defaultValue) const
+{
return get(key.c_str(), key.end_c_str(), defaultValue);
}
#endif
bool Value::isMember(char const* key, char const* cend) const
{
- Value const* value = find(key, cend);
+ Value const* value = this->find(key, cend);
return NULL != value;
}
bool Value::isMember(char const* key) const
{
- return isMember(key, key + strlen(key));
+ return this->isMember(key, key + strlen(key));
}
bool Value::isMember(JSONCPP_STRING const& key) const
{
- return isMember(key.data(), key.data() + key.length());
+ return this->isMember(key.data(), key.data() + key.length());
}
#ifdef JSON_USE_CPPTL
-bool Value::isMember(const CppTL::ConstString& key) const {
+bool Value::isMember(const CppTL::ConstString& key) const
+{
return isMember(key.c_str(), key.end_c_str());
}
#endif
-Value::Members Value::getMemberNames() const {
+Value::Members Value::getMemberNames() const
+{
JSON_ASSERT_MESSAGE(
- type_ == nullValue || type_ == objectValue,
- "in Json::Value::getMemberNames(), value must be objectValue");
- if (type_ == nullValue)
+ type_ == nullValue || type_ == objectValue,
+ "in Json::Value::getMemberNames(), value must be objectValue");
+ if (this->type_ == nullValue)
return Value::Members();
Members members;
- members.reserve(value_.map_->size());
- ObjectValues::const_iterator it = value_.map_->begin();
- ObjectValues::const_iterator itEnd = value_.map_->end();
+ members.reserve(this->value_.map_->size());
+ ObjectValues::const_iterator it = this->value_.map_->begin();
+ ObjectValues::const_iterator itEnd = this->value_.map_->end();
for (; it != itEnd; ++it) {
- members.push_back(JSONCPP_STRING((*it).first.data(),
- (*it).first.length()));
+ members.push_back(
+ JSONCPP_STRING((*it).first.data(), (*it).first.length()));
}
return members;
}
@@ -1277,8 +1447,8 @@ Value::Members Value::getMemberNames() const {
// if ( type_ == objectValue )
// {
// return CppTL::Enum::any( CppTL::Enum::transform(
-// CppTL::Enum::keys( *(value_.map_), CppTL::Type<const CZString &>() ),
-// MemberNamesTransform() ) );
+// CppTL::Enum::keys( *(value_.map_), CppTL::Type<const CZString &>()
+// ), MemberNamesTransform() ) );
// }
// return EnumMemberNames();
//}
@@ -1295,99 +1465,114 @@ Value::Members Value::getMemberNames() const {
//
//# endif
-static bool IsIntegral(double d) {
+static bool IsIntegral(double d)
+{
double integral_part;
return modf(d, &integral_part) == 0.0;
}
-bool Value::isNull() const { return type_ == nullValue; }
+bool Value::isNull() const
+{
+ return this->type_ == nullValue;
+}
-bool Value::isBool() const { return type_ == booleanValue; }
+bool Value::isBool() const
+{
+ return this->type_ == booleanValue;
+}
-bool Value::isInt() const {
- switch (type_) {
- case intValue:
+bool Value::isInt() const
+{
+ switch (this->type_) {
+ case intValue:
#if defined(JSON_HAS_INT64)
- return value_.int_ >= minInt && value_.int_ <= maxInt;
+ return this->value_.int_ >= minInt && this->value_.int_ <= maxInt;
#else
- return true;
+ return true;
#endif
- case uintValue:
- return value_.uint_ <= UInt(maxInt);
- case realValue:
- return value_.real_ >= minInt && value_.real_ <= maxInt &&
- IsIntegral(value_.real_);
- default:
- break;
+ case uintValue:
+ return this->value_.uint_ <= UInt(maxInt);
+ case realValue:
+ return this->value_.real_ >= minInt && this->value_.real_ <= maxInt &&
+ IsIntegral(this->value_.real_);
+ default:
+ break;
}
return false;
}
-bool Value::isUInt() const {
- switch (type_) {
- case intValue:
+bool Value::isUInt() const
+{
+ switch (this->type_) {
+ case intValue:
#if defined(JSON_HAS_INT64)
- return value_.int_ >= 0 && LargestUInt(value_.int_) <= LargestUInt(maxUInt);
+ return this->value_.int_ >= 0 &&
+ LargestUInt(this->value_.int_) <= LargestUInt(maxUInt);
#else
- return value_.int_ >= 0;
+ return value_.int_ >= 0;
#endif
- case uintValue:
+ case uintValue:
#if defined(JSON_HAS_INT64)
- return value_.uint_ <= maxUInt;
+ return this->value_.uint_ <= maxUInt;
#else
- return true;
+ return true;
#endif
- case realValue:
- return value_.real_ >= 0 && value_.real_ <= maxUInt &&
- IsIntegral(value_.real_);
- default:
- break;
+ case realValue:
+ return this->value_.real_ >= 0 && this->value_.real_ <= maxUInt &&
+ IsIntegral(this->value_.real_);
+ default:
+ break;
}
return false;
}
-bool Value::isInt64() const {
+bool Value::isInt64() const
+{
#if defined(JSON_HAS_INT64)
- switch (type_) {
- case intValue:
- return true;
- case uintValue:
- return value_.uint_ <= UInt64(maxInt64);
- case realValue:
- // Note that maxInt64 (= 2^63 - 1) is not exactly representable as a
- // double, so double(maxInt64) will be rounded up to 2^63. Therefore we
- // require the value to be strictly less than the limit.
- return value_.real_ >= double(minInt64) &&
- value_.real_ < double(maxInt64) && IsIntegral(value_.real_);
- default:
- break;
+ switch (this->type_) {
+ case intValue:
+ return true;
+ case uintValue:
+ return this->value_.uint_ <= UInt64(maxInt64);
+ case realValue:
+ // Note that maxInt64 (= 2^63 - 1) is not exactly representable as a
+ // double, so double(maxInt64) will be rounded up to 2^63. Therefore we
+ // require the value to be strictly less than the limit.
+ return this->value_.real_ >= double(minInt64) &&
+ this->value_.real_ < double(maxInt64) &&
+ IsIntegral(this->value_.real_);
+ default:
+ break;
}
#endif // JSON_HAS_INT64
return false;
}
-bool Value::isUInt64() const {
+bool Value::isUInt64() const
+{
#if defined(JSON_HAS_INT64)
- switch (type_) {
- case intValue:
- return value_.int_ >= 0;
- case uintValue:
- return true;
- case realValue:
- // Note that maxUInt64 (= 2^64 - 1) is not exactly representable as a
- // double, so double(maxUInt64) will be rounded up to 2^64. Therefore we
- // require the value to be strictly less than the limit.
- return value_.real_ >= 0 && value_.real_ < maxUInt64AsDouble &&
- IsIntegral(value_.real_);
- default:
- break;
+ switch (this->type_) {
+ case intValue:
+ return this->value_.int_ >= 0;
+ case uintValue:
+ return true;
+ case realValue:
+ // Note that maxUInt64 (= 2^64 - 1) is not exactly representable as a
+ // double, so double(maxUInt64) will be rounded up to 2^64. Therefore we
+ // require the value to be strictly less than the limit.
+ return this->value_.real_ >= 0 &&
+ this->value_.real_ < maxUInt64AsDouble &&
+ IsIntegral(this->value_.real_);
+ default:
+ break;
}
#endif // JSON_HAS_INT64
return false;
}
-bool Value::isIntegral() const {
- switch (type_) {
+bool Value::isIntegral() const
+{
+ switch (this->type_) {
case intValue:
case uintValue:
return true;
@@ -1396,9 +1581,12 @@ bool Value::isIntegral() const {
// Note that maxUInt64 (= 2^64 - 1) is not exactly representable as a
// double, so double(maxUInt64) will be rounded up to 2^64. Therefore we
// require the value to be strictly less than the limit.
- return value_.real_ >= double(minInt64) && value_.real_ < maxUInt64AsDouble && IsIntegral(value_.real_);
+ return this->value_.real_ >= double(minInt64) &&
+ this->value_.real_ < maxUInt64AsDouble &&
+ IsIntegral(this->value_.real_);
#else
- return value_.real_ >= minInt && value_.real_ <= maxUInt && IsIntegral(value_.real_);
+ return value_.real_ >= minInt && value_.real_ <= maxUInt &&
+ IsIntegral(value_.real_);
#endif // JSON_HAS_INT64
default:
break;
@@ -1406,53 +1594,89 @@ bool Value::isIntegral() const {
return false;
}
-bool Value::isDouble() const { return type_ == intValue || type_ == uintValue || type_ == realValue; }
+bool Value::isDouble() const
+{
+ return this->type_ == intValue || this->type_ == uintValue ||
+ this->type_ == realValue;
+}
-bool Value::isNumeric() const { return isDouble(); }
+bool Value::isNumeric() const
+{
+ return this->isDouble();
+}
-bool Value::isString() const { return type_ == stringValue; }
+bool Value::isString() const
+{
+ return this->type_ == stringValue;
+}
-bool Value::isArray() const { return type_ == arrayValue; }
+bool Value::isArray() const
+{
+ return this->type_ == arrayValue;
+}
-bool Value::isObject() const { return type_ == objectValue; }
+bool Value::isObject() const
+{
+ return this->type_ == objectValue;
+}
-void Value::setComment(const char* comment, size_t len, CommentPlacement placement) {
- if (!comments_)
- comments_ = new CommentInfo[numberOfCommentPlacement];
- if ((len > 0) && (comment[len-1] == '\n')) {
+void Value::setComment(const char* comment, size_t len,
+ CommentPlacement placement)
+{
+ if (!this->comments_)
+ this->comments_ = new CommentInfo[numberOfCommentPlacement];
+ if ((len > 0) && (comment[len - 1] == '\n')) {
// Always discard trailing newline, to aid indentation.
len -= 1;
}
- comments_[placement].setComment(comment, len);
+ this->comments_[placement].setComment(comment, len);
}
-void Value::setComment(const char* comment, CommentPlacement placement) {
- setComment(comment, strlen(comment), placement);
+void Value::setComment(const char* comment, CommentPlacement placement)
+{
+ this->setComment(comment, strlen(comment), placement);
}
-void Value::setComment(const JSONCPP_STRING& comment, CommentPlacement placement) {
- setComment(comment.c_str(), comment.length(), placement);
+void Value::setComment(const JSONCPP_STRING& comment,
+ CommentPlacement placement)
+{
+ this->setComment(comment.c_str(), comment.length(), placement);
}
-bool Value::hasComment(CommentPlacement placement) const {
- return comments_ != 0 && comments_[placement].comment_ != 0;
+bool Value::hasComment(CommentPlacement placement) const
+{
+ return this->comments_ != 0 && this->comments_[placement].comment_ != 0;
}
-JSONCPP_STRING Value::getComment(CommentPlacement placement) const {
- if (hasComment(placement))
- return comments_[placement].comment_;
+JSONCPP_STRING Value::getComment(CommentPlacement placement) const
+{
+ if (this->hasComment(placement))
+ return this->comments_[placement].comment_;
return "";
}
-void Value::setOffsetStart(ptrdiff_t start) { start_ = start; }
+void Value::setOffsetStart(ptrdiff_t start)
+{
+ this->start_ = start;
+}
-void Value::setOffsetLimit(ptrdiff_t limit) { limit_ = limit; }
+void Value::setOffsetLimit(ptrdiff_t limit)
+{
+ this->limit_ = limit;
+}
-ptrdiff_t Value::getOffsetStart() const { return start_; }
+ptrdiff_t Value::getOffsetStart() const
+{
+ return this->start_;
+}
-ptrdiff_t Value::getOffsetLimit() const { return limit_; }
+ptrdiff_t Value::getOffsetLimit() const
+{
+ return this->limit_;
+}
-JSONCPP_STRING Value::toStyledString() const {
+JSONCPP_STRING Value::toStyledString() const
+{
StreamWriterBuilder builder;
JSONCPP_STRING out = this->hasComment(commentBefore) ? "\n" : "";
@@ -1462,54 +1686,58 @@ JSONCPP_STRING Value::toStyledString() const {
return out;
}
-Value::const_iterator Value::begin() const {
- switch (type_) {
- case arrayValue:
- case objectValue:
- if (value_.map_)
- return const_iterator(value_.map_->begin());
- break;
- default:
- break;
+Value::const_iterator Value::begin() const
+{
+ switch (this->type_) {
+ case arrayValue:
+ case objectValue:
+ if (this->value_.map_)
+ return const_iterator(this->value_.map_->begin());
+ break;
+ default:
+ break;
}
return const_iterator();
}
-Value::const_iterator Value::end() const {
- switch (type_) {
- case arrayValue:
- case objectValue:
- if (value_.map_)
- return const_iterator(value_.map_->end());
- break;
- default:
- break;
+Value::const_iterator Value::end() const
+{
+ switch (this->type_) {
+ case arrayValue:
+ case objectValue:
+ if (this->value_.map_)
+ return const_iterator(this->value_.map_->end());
+ break;
+ default:
+ break;
}
return const_iterator();
}
-Value::iterator Value::begin() {
- switch (type_) {
- case arrayValue:
- case objectValue:
- if (value_.map_)
- return iterator(value_.map_->begin());
- break;
- default:
- break;
+Value::iterator Value::begin()
+{
+ switch (this->type_) {
+ case arrayValue:
+ case objectValue:
+ if (this->value_.map_)
+ return iterator(this->value_.map_->begin());
+ break;
+ default:
+ break;
}
return iterator();
}
-Value::iterator Value::end() {
- switch (type_) {
- case arrayValue:
- case objectValue:
- if (value_.map_)
- return iterator(value_.map_->end());
- break;
- default:
- break;
+Value::iterator Value::end()
+{
+ switch (this->type_) {
+ case arrayValue:
+ case objectValue:
+ if (this->value_.map_)
+ return iterator(this->value_.map_->end());
+ break;
+ default:
+ break;
}
return iterator();
}
@@ -1517,26 +1745,41 @@ Value::iterator Value::end() {
// class PathArgument
// //////////////////////////////////////////////////////////////////
-PathArgument::PathArgument() : key_(), index_(), kind_(kindNone) {}
+PathArgument::PathArgument()
+ : key_()
+ , index_()
+ , kind_(kindNone)
+{
+}
PathArgument::PathArgument(ArrayIndex index)
- : key_(), index_(index), kind_(kindIndex) {}
+ : key_()
+ , index_(index)
+ , kind_(kindIndex)
+{
+}
PathArgument::PathArgument(const char* key)
- : key_(key), index_(), kind_(kindKey) {}
+ : key_(key)
+ , index_()
+ , kind_(kindKey)
+{
+}
PathArgument::PathArgument(const JSONCPP_STRING& key)
- : key_(key.c_str()), index_(), kind_(kindKey) {}
+ : key_(key.c_str())
+ , index_()
+ , kind_(kindKey)
+{
+}
// class Path
// //////////////////////////////////////////////////////////////////
-Path::Path(const JSONCPP_STRING& path,
- const PathArgument& a1,
- const PathArgument& a2,
- const PathArgument& a3,
- const PathArgument& a4,
- const PathArgument& a5) {
+Path::Path(const JSONCPP_STRING& path, const PathArgument& a1,
+ const PathArgument& a2, const PathArgument& a3,
+ const PathArgument& a4, const PathArgument& a5)
+{
InArgs in;
in.reserve(5);
in.push_back(&a1);
@@ -1544,10 +1787,11 @@ Path::Path(const JSONCPP_STRING& path,
in.push_back(&a3);
in.push_back(&a4);
in.push_back(&a5);
- makePath(path, in);
+ this->makePath(path, in);
}
-void Path::makePath(const JSONCPP_STRING& path, const InArgs& in) {
+void Path::makePath(const JSONCPP_STRING& path, const InArgs& in)
+{
const char* current = path.c_str();
const char* end = current + path.length();
InArgs::const_iterator itInArg = in.begin();
@@ -1555,17 +1799,17 @@ void Path::makePath(const JSONCPP_STRING& path, const InArgs& in) {
if (*current == '[') {
++current;
if (*current == '%')
- addPathInArg(path, in, itInArg, PathArgument::kindIndex);
+ this->addPathInArg(path, in, itInArg, PathArgument::kindIndex);
else {
ArrayIndex index = 0;
for (; current != end && *current >= '0' && *current <= '9'; ++current)
index = index * 10 + ArrayIndex(*current - '0');
- args_.push_back(index);
+ this->args_.push_back(index);
}
if (current == end || *++current != ']')
- invalidPath(path, int(current - path.c_str()));
+ this->invalidPath(path, int(current - path.c_str()));
} else if (*current == '%') {
- addPathInArg(path, in, itInArg, PathArgument::kindKey);
+ this->addPathInArg(path, in, itInArg, PathArgument::kindKey);
++current;
} else if (*current == '.' || *current == ']') {
++current;
@@ -1573,31 +1817,34 @@ void Path::makePath(const JSONCPP_STRING& path, const InArgs& in) {
const char* beginName = current;
while (current != end && !strchr("[.", *current))
++current;
- args_.push_back(JSONCPP_STRING(beginName, current));
+ this->args_.push_back(JSONCPP_STRING(beginName, current));
}
}
}
-void Path::addPathInArg(const JSONCPP_STRING& /*path*/,
- const InArgs& in,
+void Path::addPathInArg(const JSONCPP_STRING& /*path*/, const InArgs& in,
InArgs::const_iterator& itInArg,
- PathArgument::Kind kind) {
+ PathArgument::Kind kind)
+{
if (itInArg == in.end()) {
// Error: missing argument %d
} else if ((*itInArg)->kind_ != kind) {
// Error: bad argument type
} else {
- args_.push_back(**itInArg++);
+ this->args_.push_back(**itInArg++);
}
}
-void Path::invalidPath(const JSONCPP_STRING& /*path*/, int /*location*/) {
+void Path::invalidPath(const JSONCPP_STRING& /*path*/, int /*location*/)
+{
// Error: invalid path.
}
-const Value& Path::resolve(const Value& root) const {
+const Value& Path::resolve(const Value& root) const
+{
const Value* node = &root;
- for (Args::const_iterator it = args_.begin(); it != args_.end(); ++it) {
+ for (Args::const_iterator it = this->args_.begin(); it != this->args_.end();
+ ++it) {
const PathArgument& arg = *it;
if (arg.kind_ == PathArgument::kindIndex) {
if (!node->isArray() || !node->isValidIndex(arg.index_)) {
@@ -1621,9 +1868,11 @@ const Value& Path::resolve(const Value& root) const {
return *node;
}
-Value Path::resolve(const Value& root, const Value& defaultValue) const {
+Value Path::resolve(const Value& root, const Value& defaultValue) const
+{
const Value* node = &root;
- for (Args::const_iterator it = args_.begin(); it != args_.end(); ++it) {
+ for (Args::const_iterator it = this->args_.begin(); it != this->args_.end();
+ ++it) {
const PathArgument& arg = *it;
if (arg.kind_ == PathArgument::kindIndex) {
if (!node->isArray() || !node->isValidIndex(arg.index_))
@@ -1640,9 +1889,11 @@ Value Path::resolve(const Value& root, const Value& defaultValue) const {
return *node;
}
-Value& Path::make(Value& root) const {
+Value& Path::make(Value& root) const
+{
Value* node = &root;
- for (Args::const_iterator it = args_.begin(); it != args_.end(); ++it) {
+ for (Args::const_iterator it = this->args_.begin(); it != this->args_.end();
+ ++it) {
const PathArgument& arg = *it;
if (arg.kind_ == PathArgument::kindIndex) {
if (!node->isArray()) {
diff --git a/Utilities/cmjsoncpp/src/lib_json/json_writer.cpp b/Utilities/cmjsoncpp/src/lib_json/json_writer.cpp
index fc8650598..803cfab01 100644
--- a/Utilities/cmjsoncpp/src/lib_json/json_writer.cpp
+++ b/Utilities/cmjsoncpp/src/lib_json/json_writer.cpp
@@ -1,111 +1,115 @@
// Copyright 2011 Baptiste Lepilleur and The JsonCpp Authors
// Distributed under MIT license, or public domain if desired and
// recognized in your jurisdiction.
-// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
+// See file LICENSE for detail or copy at
+// http://jsoncpp.sourceforge.net/LICENSE
#if !defined(JSON_IS_AMALGAMATION)
-#include <json/writer.h>
-#include "json_tool.h"
+# include <json/writer.h>
+
+# include "json_tool.h"
#endif // if !defined(JSON_IS_AMALGAMATION)
+#include <cassert>
+#include <cstdio>
+#include <cstring>
#include <iomanip>
#include <memory>
+#include <set>
#include <sstream>
#include <utility>
-#include <set>
-#include <cassert>
-#include <cstring>
-#include <cstdio>
-#if defined(_MSC_VER) && _MSC_VER >= 1200 && _MSC_VER < 1800 // Between VC++ 6.0 and VC++ 11.0
-#include <float.h>
-#define isfinite _finite
-#elif defined(__sun) && defined(__SVR4) //Solaris
-#if !defined(isfinite)
-#include <ieeefp.h>
-#define isfinite finite
-#endif
+#if defined(_MSC_VER) && _MSC_VER >= 1200 && \
+ _MSC_VER < 1800 // Between VC++ 6.0 and VC++ 11.0
+# include <float.h>
+# define isfinite _finite
+#elif defined(__sun) && defined(__SVR4) // Solaris
+# if !defined(isfinite)
+# include <ieeefp.h>
+# define isfinite finite
+# endif
#elif defined(_AIX)
-#if !defined(isfinite)
-#include <math.h>
-#define isfinite finite
-#endif
+# if !defined(isfinite)
+# include <math.h>
+# define isfinite finite
+# endif
#elif defined(__hpux)
-#if !defined(isfinite) && !defined(__GNUC__)
-#if defined(__ia64) && !defined(finite)
-#define isfinite(x) ((sizeof(x) == sizeof(float) ? \
- _Isfinitef(x) : _IsFinite(x)))
-#else
-#include <math.h>
-#define isfinite finite
-#endif
-#endif
+# if !defined(isfinite) && !defined(__GNUC__)
+# if defined(__ia64) && !defined(finite)
+# define isfinite(x) \
+ ((sizeof(x) == sizeof(float) ? _Isfinitef(x) : _IsFinite(x)))
+# else
+# include <math.h>
+# define isfinite finite
+# endif
+# endif
#else
-#include <cmath>
-#if !(defined(__QNXNTO__)) // QNX already defines isfinite
-#define isfinite std::isfinite
-#endif
+# include <cmath>
+# if !(defined(__QNXNTO__)) // QNX already defines isfinite
+# define isfinite std::isfinite
+# endif
#endif
#if defined(_MSC_VER)
-#if !defined(WINCE) && defined(__STDC_SECURE_LIB__) && _MSC_VER >= 1500 // VC++ 9.0 and above
-#define snprintf sprintf_s
-#elif _MSC_VER >= 1900 // VC++ 14.0 and above
-#define snprintf std::snprintf
-#else
-#define snprintf _snprintf
-#endif
+# if !defined(WINCE) && defined(__STDC_SECURE_LIB__) && \
+ _MSC_VER >= 1500 // VC++ 9.0 and above
+# define snprintf sprintf_s
+# elif _MSC_VER >= 1900 // VC++ 14.0 and above
+# define snprintf std::snprintf
+# else
+# define snprintf _snprintf
+# endif
#elif defined(__ANDROID__) || defined(__QNXNTO__)
-#define snprintf snprintf
+# define snprintf snprintf
#elif __cplusplus >= 201103L
-#if !defined(__MINGW32__) && !defined(__CYGWIN__)
-#define snprintf std::snprintf
-#endif
+# if !defined(__MINGW32__) && !defined(__CYGWIN__)
+# define snprintf std::snprintf
+# endif
#endif
-#if defined(__BORLANDC__)
-#include <float.h>
-#define isfinite _finite
-#define snprintf _snprintf
+#if defined(__BORLANDC__)
+# include <float.h>
+# define isfinite _finite
+# define snprintf _snprintf
#endif
// Solaris
#if defined(__sun)
-# include <ieeefp.h>
-# if !defined(isfinite)
-# define isfinite finite
-# endif
+# include <ieeefp.h>
+# if !defined(isfinite)
+# define isfinite finite
+# endif
#endif
// AIX
#if defined(_AIX)
-# if !defined(isfinite)
-# define isfinite finite
-# endif
+# if !defined(isfinite)
+# define isfinite finite
+# endif
#endif
// HP-UX
#if defined(__hpux)
-# if !defined(isfinite)
-# if defined(__ia64) && !defined(finite) && !defined(__GNUC__)
-# define isfinite(x) ((sizeof(x) == sizeof(float) ? \
- _Isfinitef(x) : _Isfinite(x)))
-# else
-# include <math.h>
-# define isfinite finite
+# if !defined(isfinite)
+# if defined(__ia64) && !defined(finite) && !defined(__GNUC__)
+# define isfinite(x) \
+ ((sizeof(x) == sizeof(float) ? _Isfinitef(x) : _Isfinite(x)))
+# else
+# include <math.h>
+# define isfinite finite
+# endif
# endif
-# endif
#endif
// Ancient glibc
#if defined(__GLIBC__) && __GLIBC__ == 2 && __GLIBC_MINOR__ < 2
-# if !defined(isfinite)
-# define isfinite __finite
-# endif
+# if !defined(isfinite)
+# define isfinite __finite
+# endif
#endif
#if defined(_MSC_VER) && _MSC_VER >= 1400 // VC++ 8.0
// Disable warning about strdup being deprecated.
-#pragma warning(disable : 4996)
+# pragma warning(disable : 4996)
#endif
namespace Json {
@@ -113,10 +117,11 @@ namespace Json {
#if __cplusplus >= 201103L || (defined(_CPPLIB_VER) && _CPPLIB_VER >= 520)
typedef std::unique_ptr<StreamWriter> StreamWriterPtr;
#else
-typedef std::auto_ptr<StreamWriter> StreamWriterPtr;
+typedef std::auto_ptr<StreamWriter> StreamWriterPtr;
#endif
-static bool containsControlCharacter(const char* str) {
+static bool containsControlCharacter(const char* str)
+{
while (*str) {
if (isControlCharacter(*(str++)))
return true;
@@ -124,17 +129,19 @@ static bool containsControlCharacter(const char* str) {
return false;
}
-static bool containsControlCharacter0(const char* str, unsigned len) {
+static bool containsControlCharacter0(const char* str, unsigned len)
+{
char const* end = str + len;
while (end != str) {
- if (isControlCharacter(*str) || 0==*str)
+ if (isControlCharacter(*str) || 0 == *str)
return true;
++str;
}
return false;
}
-JSONCPP_STRING valueToString(LargestInt value) {
+JSONCPP_STRING valueToString(LargestInt value)
+{
UIntToStringBuffer buffer;
char* current = buffer + sizeof(buffer);
if (value == Value::minLargestInt) {
@@ -150,7 +157,8 @@ JSONCPP_STRING valueToString(LargestInt value) {
return current;
}
-JSONCPP_STRING valueToString(LargestUInt value) {
+JSONCPP_STRING valueToString(LargestUInt value)
+{
UIntToStringBuffer buffer;
char* current = buffer + sizeof(buffer);
uintToString(value, current);
@@ -160,18 +168,22 @@ JSONCPP_STRING valueToString(LargestUInt value) {
#if defined(JSON_HAS_INT64)
-JSONCPP_STRING valueToString(Int value) {
+JSONCPP_STRING valueToString(Int value)
+{
return valueToString(LargestInt(value));
}
-JSONCPP_STRING valueToString(UInt value) {
+JSONCPP_STRING valueToString(UInt value)
+{
return valueToString(LargestUInt(value));
}
#endif // # if defined(JSON_HAS_INT64)
namespace {
-JSONCPP_STRING valueToString(double value, bool useSpecialFloats, unsigned int precision) {
+JSONCPP_STRING valueToString(double value, bool useSpecialFloats,
+ unsigned int precision)
+{
// Allocate a buffer that is more than large enough to store the 16 digits of
// precision requested below.
char buffer[36];
@@ -187,7 +199,8 @@ JSONCPP_STRING valueToString(double value, bool useSpecialFloats, unsigned int p
len = snprintf(buffer, sizeof(buffer), formatString, value);
fixNumericLocale(buffer, buffer + len);
- // try to ensure we preserve the fact that this was given to us as a double on input
+ // try to ensure we preserve the fact that this was given to us as a double
+ // on input
if (!strchr(buffer, '.') && !strchr(buffer, 'e')) {
strcat(buffer, ".0");
}
@@ -195,11 +208,14 @@ JSONCPP_STRING valueToString(double value, bool useSpecialFloats, unsigned int p
} else {
// IEEE standard states that NaN values will not compare to themselves
if (value != value) {
- len = snprintf(buffer, sizeof(buffer), useSpecialFloats ? "NaN" : "null");
+ len =
+ snprintf(buffer, sizeof(buffer), useSpecialFloats ? "NaN" : "null");
} else if (value < 0) {
- len = snprintf(buffer, sizeof(buffer), useSpecialFloats ? "-Infinity" : "-1e+9999");
+ len = snprintf(buffer, sizeof(buffer),
+ useSpecialFloats ? "-Infinity" : "-1e+9999");
} else {
- len = snprintf(buffer, sizeof(buffer), useSpecialFloats ? "Infinity" : "1e+9999");
+ len = snprintf(buffer, sizeof(buffer),
+ useSpecialFloats ? "Infinity" : "1e+9999");
}
}
assert(len >= 0);
@@ -207,11 +223,18 @@ JSONCPP_STRING valueToString(double value, bool useSpecialFloats, unsigned int p
}
}
-JSONCPP_STRING valueToString(double value) { return valueToString(value, false, 17); }
+JSONCPP_STRING valueToString(double value)
+{
+ return valueToString(value, false, 17);
+}
-JSONCPP_STRING valueToString(bool value) { return value ? "true" : "false"; }
+JSONCPP_STRING valueToString(bool value)
+{
+ return value ? "true" : "false";
+}
-JSONCPP_STRING valueToQuotedString(const char* value) {
+JSONCPP_STRING valueToQuotedString(const char* value)
+{
if (value == NULL)
return "";
// Not sure how to handle unicode...
@@ -222,51 +245,50 @@ JSONCPP_STRING valueToQuotedString(const char* value) {
// Appending to JSONCPP_STRING is not efficient, but this should be rare.
// (Note: forward slashes are *not* rare, but I am not escaping them.)
JSONCPP_STRING::size_type maxsize =
- strlen(value) * 2 + 3; // allescaped+quotes+NULL
+ strlen(value) * 2 + 3; // allescaped+quotes+NULL
JSONCPP_STRING result;
result.reserve(maxsize); // to avoid lots of mallocs
result += "\"";
for (const char* c = value; *c != 0; ++c) {
switch (*c) {
- case '\"':
- result += "\\\"";
- break;
- case '\\':
- result += "\\\\";
- break;
- case '\b':
- result += "\\b";
- break;
- case '\f':
- result += "\\f";
- break;
- case '\n':
- result += "\\n";
- break;
- case '\r':
- result += "\\r";
- break;
- case '\t':
- result += "\\t";
- break;
- // case '/':
- // Even though \/ is considered a legal escape in JSON, a bare
- // slash is also legal, so I see no reason to escape it.
- // (I hope I am not misunderstanding something.
- // blep notes: actually escaping \/ may be useful in javascript to avoid </
- // sequence.
- // Should add a flag to allow this compatibility mode and prevent this
- // sequence from occurring.
- default:
- if (isControlCharacter(*c)) {
- JSONCPP_OSTRINGSTREAM oss;
- oss << "\\u" << std::hex << std::uppercase << std::setfill('0')
- << std::setw(4) << static_cast<int>(*c);
- result += oss.str();
- } else {
- result += *c;
- }
- break;
+ case '\"':
+ result += "\\\"";
+ break;
+ case '\\':
+ result += "\\\\";
+ break;
+ case '\b':
+ result += "\\b";
+ break;
+ case '\f':
+ result += "\\f";
+ break;
+ case '\n':
+ result += "\\n";
+ break;
+ case '\r':
+ result += "\\r";
+ break;
+ case '\t':
+ result += "\\t";
+ break;
+ // case '/':
+ // Even though \/ is considered a legal escape in JSON, a bare
+ // slash is also legal, so I see no reason to escape it.
+ // (I hope I am not misunderstanding something.
+ // blep notes: actually escaping \/ may be useful in javascript to avoid
+ // </ sequence. Should add a flag to allow this compatibility mode and
+ // prevent this sequence from occurring.
+ default:
+ if (isControlCharacter(*c)) {
+ JSONCPP_OSTRINGSTREAM oss;
+ oss << "\\u" << std::hex << std::uppercase << std::setfill('0')
+ << std::setw(4) << static_cast<int>(*c);
+ result += oss.str();
+ } else {
+ result += *c;
+ }
+ break;
}
}
result += "\"";
@@ -274,7 +296,8 @@ JSONCPP_STRING valueToQuotedString(const char* value) {
}
// https://github.com/upcaste/upcaste/blob/master/src/upcore/src/cstring/strnpbrk.cpp
-static char const* strnpbrk(char const* s, char const* accept, size_t n) {
+static char const* strnpbrk(char const* s, char const* accept, size_t n)
+{
assert((s || !n) && accept);
char const* const end = s + n;
@@ -288,7 +311,8 @@ static char const* strnpbrk(char const* s, char const* accept, size_t n) {
}
return NULL;
}
-static JSONCPP_STRING valueToQuotedStringN(const char* value, unsigned length) {
+static JSONCPP_STRING valueToQuotedStringN(const char* value, unsigned length)
+{
if (value == NULL)
return "";
// Not sure how to handle unicode...
@@ -298,53 +322,51 @@ static JSONCPP_STRING valueToQuotedStringN(const char* value, unsigned length) {
// We have to walk value and escape any special characters.
// Appending to JSONCPP_STRING is not efficient, but this should be rare.
// (Note: forward slashes are *not* rare, but I am not escaping them.)
- JSONCPP_STRING::size_type maxsize =
- length * 2 + 3; // allescaped+quotes+NULL
+ JSONCPP_STRING::size_type maxsize = length * 2 + 3; // allescaped+quotes+NULL
JSONCPP_STRING result;
result.reserve(maxsize); // to avoid lots of mallocs
result += "\"";
char const* end = value + length;
for (const char* c = value; c != end; ++c) {
switch (*c) {
- case '\"':
- result += "\\\"";
- break;
- case '\\':
- result += "\\\\";
- break;
- case '\b':
- result += "\\b";
- break;
- case '\f':
- result += "\\f";
- break;
- case '\n':
- result += "\\n";
- break;
- case '\r':
- result += "\\r";
- break;
- case '\t':
- result += "\\t";
- break;
- // case '/':
- // Even though \/ is considered a legal escape in JSON, a bare
- // slash is also legal, so I see no reason to escape it.
- // (I hope I am not misunderstanding something.)
- // blep notes: actually escaping \/ may be useful in javascript to avoid </
- // sequence.
- // Should add a flag to allow this compatibility mode and prevent this
- // sequence from occurring.
- default:
- if ((isControlCharacter(*c)) || (*c == 0)) {
- JSONCPP_OSTRINGSTREAM oss;
- oss << "\\u" << std::hex << std::uppercase << std::setfill('0')
- << std::setw(4) << static_cast<int>(*c);
- result += oss.str();
- } else {
- result += *c;
- }
- break;
+ case '\"':
+ result += "\\\"";
+ break;
+ case '\\':
+ result += "\\\\";
+ break;
+ case '\b':
+ result += "\\b";
+ break;
+ case '\f':
+ result += "\\f";
+ break;
+ case '\n':
+ result += "\\n";
+ break;
+ case '\r':
+ result += "\\r";
+ break;
+ case '\t':
+ result += "\\t";
+ break;
+ // case '/':
+ // Even though \/ is considered a legal escape in JSON, a bare
+ // slash is also legal, so I see no reason to escape it.
+ // (I hope I am not misunderstanding something.)
+ // blep notes: actually escaping \/ may be useful in javascript to avoid
+ // </ sequence. Should add a flag to allow this compatibility mode and
+ // prevent this sequence from occurring.
+ default:
+ if ((isControlCharacter(*c)) || (*c == 0)) {
+ JSONCPP_OSTRINGSTREAM oss;
+ oss << "\\u" << std::hex << std::uppercase << std::setfill('0')
+ << std::setw(4) << static_cast<int>(*c);
+ result += oss.str();
+ } else {
+ result += *c;
+ }
+ break;
}
}
result += "\"";
@@ -353,80 +375,98 @@ static JSONCPP_STRING valueToQuotedStringN(const char* value, unsigned length) {
// Class Writer
// //////////////////////////////////////////////////////////////////
-Writer::~Writer() {}
+Writer::~Writer()
+{
+}
// Class FastWriter
// //////////////////////////////////////////////////////////////////
FastWriter::FastWriter()
- : yamlCompatiblityEnabled_(false), dropNullPlaceholders_(false),
- omitEndingLineFeed_(false) {}
+ : yamlCompatiblityEnabled_(false)
+ , dropNullPlaceholders_(false)
+ , omitEndingLineFeed_(false)
+{
+}
-void FastWriter::enableYAMLCompatibility() { yamlCompatiblityEnabled_ = true; }
+void FastWriter::enableYAMLCompatibility()
+{
+ this->yamlCompatiblityEnabled_ = true;
+}
-void FastWriter::dropNullPlaceholders() { dropNullPlaceholders_ = true; }
+void FastWriter::dropNullPlaceholders()
+{
+ this->dropNullPlaceholders_ = true;
+}
-void FastWriter::omitEndingLineFeed() { omitEndingLineFeed_ = true; }
+void FastWriter::omitEndingLineFeed()
+{
+ this->omitEndingLineFeed_ = true;
+}
-JSONCPP_STRING FastWriter::write(const Value& root) {
- document_.clear();
- writeValue(root);
- if (!omitEndingLineFeed_)
- document_ += "\n";
- return document_;
+JSONCPP_STRING FastWriter::write(const Value& root)
+{
+ this->document_.clear();
+ this->writeValue(root);
+ if (!this->omitEndingLineFeed_)
+ this->document_ += "\n";
+ return this->document_;
}
-void FastWriter::writeValue(const Value& value) {
+void FastWriter::writeValue(const Value& value)
+{
switch (value.type()) {
- case nullValue:
- if (!dropNullPlaceholders_)
- document_ += "null";
- break;
- case intValue:
- document_ += valueToString(value.asLargestInt());
- break;
- case uintValue:
- document_ += valueToString(value.asLargestUInt());
- break;
- case realValue:
- document_ += valueToString(value.asDouble());
- break;
- case stringValue:
- {
- // Is NULL possible for value.string_? No.
- char const* str;
- char const* end;
- bool ok = value.getString(&str, &end);
- if (ok) document_ += valueToQuotedStringN(str, static_cast<unsigned>(end-str));
- break;
- }
- case booleanValue:
- document_ += valueToString(value.asBool());
- break;
- case arrayValue: {
- document_ += '[';
- ArrayIndex size = value.size();
- for (ArrayIndex index = 0; index < size; ++index) {
- if (index > 0)
- document_ += ',';
- writeValue(value[index]);
- }
- document_ += ']';
- } break;
- case objectValue: {
- Value::Members members(value.getMemberNames());
- document_ += '{';
- for (Value::Members::iterator it = members.begin(); it != members.end();
- ++it) {
- const JSONCPP_STRING& name = *it;
- if (it != members.begin())
- document_ += ',';
- document_ += valueToQuotedStringN(name.data(), static_cast<unsigned>(name.length()));
- document_ += yamlCompatiblityEnabled_ ? ": " : ":";
- writeValue(value[name]);
+ case nullValue:
+ if (!this->dropNullPlaceholders_)
+ this->document_ += "null";
+ break;
+ case intValue:
+ this->document_ += valueToString(value.asLargestInt());
+ break;
+ case uintValue:
+ this->document_ += valueToString(value.asLargestUInt());
+ break;
+ case realValue:
+ this->document_ += valueToString(value.asDouble());
+ break;
+ case stringValue: {
+ // Is NULL possible for value.string_? No.
+ char const* str;
+ char const* end;
+ bool ok = value.getString(&str, &end);
+ if (ok)
+ this->document_ +=
+ valueToQuotedStringN(str, static_cast<unsigned>(end - str));
+ break;
}
- document_ += '}';
- } break;
+ case booleanValue:
+ this->document_ += valueToString(value.asBool());
+ break;
+ case arrayValue: {
+ this->document_ += '[';
+ ArrayIndex size = value.size();
+ for (ArrayIndex index = 0; index < size; ++index) {
+ if (index > 0)
+ this->document_ += ',';
+ this->writeValue(value[index]);
+ }
+ this->document_ += ']';
+ } break;
+ case objectValue: {
+ Value::Members members(value.getMemberNames());
+ this->document_ += '{';
+ for (Value::Members::iterator it = members.begin(); it != members.end();
+ ++it) {
+ const JSONCPP_STRING& name = *it;
+ if (it != members.begin())
+ this->document_ += ',';
+ this->document_ += valueToQuotedStringN(
+ name.data(), static_cast<unsigned>(name.length()));
+ this->document_ += this->yamlCompatiblityEnabled_ ? ": " : ":";
+ this->writeValue(value[name]);
+ }
+ this->document_ += '}';
+ } break;
}
}
@@ -434,454 +474,498 @@ void FastWriter::writeValue(const Value& value) {
// //////////////////////////////////////////////////////////////////
StyledWriter::StyledWriter()
- : rightMargin_(74), indentSize_(3), addChildValues_() {}
+ : rightMargin_(74)
+ , indentSize_(3)
+ , addChildValues_()
+{
+}
-JSONCPP_STRING StyledWriter::write(const Value& root) {
- document_.clear();
- addChildValues_ = false;
- indentString_.clear();
- writeCommentBeforeValue(root);
- writeValue(root);
- writeCommentAfterValueOnSameLine(root);
- document_ += "\n";
- return document_;
+JSONCPP_STRING StyledWriter::write(const Value& root)
+{
+ this->document_.clear();
+ this->addChildValues_ = false;
+ this->indentString_.clear();
+ this->writeCommentBeforeValue(root);
+ this->writeValue(root);
+ this->writeCommentAfterValueOnSameLine(root);
+ this->document_ += "\n";
+ return this->document_;
}
-void StyledWriter::writeValue(const Value& value) {
+void StyledWriter::writeValue(const Value& value)
+{
switch (value.type()) {
- case nullValue:
- pushValue("null");
- break;
- case intValue:
- pushValue(valueToString(value.asLargestInt()));
- break;
- case uintValue:
- pushValue(valueToString(value.asLargestUInt()));
- break;
- case realValue:
- pushValue(valueToString(value.asDouble()));
- break;
- case stringValue:
- {
- // Is NULL possible for value.string_? No.
- char const* str;
- char const* end;
- bool ok = value.getString(&str, &end);
- if (ok) pushValue(valueToQuotedStringN(str, static_cast<unsigned>(end-str)));
- else pushValue("");
- break;
- }
- case booleanValue:
- pushValue(valueToString(value.asBool()));
- break;
- case arrayValue:
- writeArrayValue(value);
- break;
- case objectValue: {
- Value::Members members(value.getMemberNames());
- if (members.empty())
- pushValue("{}");
- else {
- writeWithIndent("{");
- indent();
- Value::Members::iterator it = members.begin();
- for (;;) {
- const JSONCPP_STRING& name = *it;
- const Value& childValue = value[name];
- writeCommentBeforeValue(childValue);
- writeWithIndent(valueToQuotedString(name.c_str()));
- document_ += " : ";
- writeValue(childValue);
- if (++it == members.end()) {
- writeCommentAfterValueOnSameLine(childValue);
- break;
+ case nullValue:
+ this->pushValue("null");
+ break;
+ case intValue:
+ this->pushValue(valueToString(value.asLargestInt()));
+ break;
+ case uintValue:
+ this->pushValue(valueToString(value.asLargestUInt()));
+ break;
+ case realValue:
+ this->pushValue(valueToString(value.asDouble()));
+ break;
+ case stringValue: {
+ // Is NULL possible for value.string_? No.
+ char const* str;
+ char const* end;
+ bool ok = value.getString(&str, &end);
+ if (ok)
+ this->pushValue(
+ valueToQuotedStringN(str, static_cast<unsigned>(end - str)));
+ else
+ this->pushValue("");
+ break;
+ }
+ case booleanValue:
+ this->pushValue(valueToString(value.asBool()));
+ break;
+ case arrayValue:
+ this->writeArrayValue(value);
+ break;
+ case objectValue: {
+ Value::Members members(value.getMemberNames());
+ if (members.empty())
+ this->pushValue("{}");
+ else {
+ this->writeWithIndent("{");
+ this->indent();
+ Value::Members::iterator it = members.begin();
+ for (;;) {
+ const JSONCPP_STRING& name = *it;
+ const Value& childValue = value[name];
+ this->writeCommentBeforeValue(childValue);
+ this->writeWithIndent(valueToQuotedString(name.c_str()));
+ this->document_ += " : ";
+ this->writeValue(childValue);
+ if (++it == members.end()) {
+ this->writeCommentAfterValueOnSameLine(childValue);
+ break;
+ }
+ this->document_ += ',';
+ this->writeCommentAfterValueOnSameLine(childValue);
}
- document_ += ',';
- writeCommentAfterValueOnSameLine(childValue);
+ this->unindent();
+ this->writeWithIndent("}");
}
- unindent();
- writeWithIndent("}");
- }
- } break;
+ } break;
}
}
-void StyledWriter::writeArrayValue(const Value& value) {
+void StyledWriter::writeArrayValue(const Value& value)
+{
unsigned size = value.size();
if (size == 0)
- pushValue("[]");
+ this->pushValue("[]");
else {
- bool isArrayMultiLine = isMultineArray(value);
+ bool isArrayMultiLine = this->isMultineArray(value);
if (isArrayMultiLine) {
- writeWithIndent("[");
- indent();
- bool hasChildValue = !childValues_.empty();
+ this->writeWithIndent("[");
+ this->indent();
+ bool hasChildValue = !this->childValues_.empty();
unsigned index = 0;
for (;;) {
const Value& childValue = value[index];
- writeCommentBeforeValue(childValue);
+ this->writeCommentBeforeValue(childValue);
if (hasChildValue)
- writeWithIndent(childValues_[index]);
+ this->writeWithIndent(this->childValues_[index]);
else {
- writeIndent();
- writeValue(childValue);
+ this->writeIndent();
+ this->writeValue(childValue);
}
if (++index == size) {
- writeCommentAfterValueOnSameLine(childValue);
+ this->writeCommentAfterValueOnSameLine(childValue);
break;
}
- document_ += ',';
- writeCommentAfterValueOnSameLine(childValue);
+ this->document_ += ',';
+ this->writeCommentAfterValueOnSameLine(childValue);
}
- unindent();
- writeWithIndent("]");
+ this->unindent();
+ this->writeWithIndent("]");
} else // output on a single line
{
- assert(childValues_.size() == size);
- document_ += "[ ";
+ assert(this->childValues_.size() == size);
+ this->document_ += "[ ";
for (unsigned index = 0; index < size; ++index) {
if (index > 0)
- document_ += ", ";
- document_ += childValues_[index];
+ this->document_ += ", ";
+ this->document_ += this->childValues_[index];
}
- document_ += " ]";
+ this->document_ += " ]";
}
}
}
-bool StyledWriter::isMultineArray(const Value& value) {
+bool StyledWriter::isMultineArray(const Value& value)
+{
ArrayIndex const size = value.size();
- bool isMultiLine = size * 3 >= rightMargin_;
- childValues_.clear();
+ bool isMultiLine = size * 3 >= this->rightMargin_;
+ this->childValues_.clear();
for (ArrayIndex index = 0; index < size && !isMultiLine; ++index) {
const Value& childValue = value[index];
isMultiLine = ((childValue.isArray() || childValue.isObject()) &&
- childValue.size() > 0);
+ childValue.size() > 0);
}
if (!isMultiLine) // check if line length > max line length
{
- childValues_.reserve(size);
- addChildValues_ = true;
+ this->childValues_.reserve(size);
+ this->addChildValues_ = true;
ArrayIndex lineLength = 4 + (size - 1) * 2; // '[ ' + ', '*n + ' ]'
for (ArrayIndex index = 0; index < size; ++index) {
- if (hasCommentForValue(value[index])) {
+ if (this->hasCommentForValue(value[index])) {
isMultiLine = true;
}
- writeValue(value[index]);
- lineLength += static_cast<ArrayIndex>(childValues_[index].length());
+ this->writeValue(value[index]);
+ lineLength +=
+ static_cast<ArrayIndex>(this->childValues_[index].length());
}
- addChildValues_ = false;
- isMultiLine = isMultiLine || lineLength >= rightMargin_;
+ this->addChildValues_ = false;
+ isMultiLine = isMultiLine || lineLength >= this->rightMargin_;
}
return isMultiLine;
}
-void StyledWriter::pushValue(const JSONCPP_STRING& value) {
- if (addChildValues_)
- childValues_.push_back(value);
+void StyledWriter::pushValue(const JSONCPP_STRING& value)
+{
+ if (this->addChildValues_)
+ this->childValues_.push_back(value);
else
- document_ += value;
+ this->document_ += value;
}
-void StyledWriter::writeIndent() {
- if (!document_.empty()) {
- char last = document_[document_.length() - 1];
+void StyledWriter::writeIndent()
+{
+ if (!this->document_.empty()) {
+ char last = this->document_[this->document_.length() - 1];
if (last == ' ') // already indented
return;
if (last != '\n') // Comments may add new-line
- document_ += '\n';
+ this->document_ += '\n';
}
- document_ += indentString_;
+ this->document_ += this->indentString_;
}
-void StyledWriter::writeWithIndent(const JSONCPP_STRING& value) {
- writeIndent();
- document_ += value;
+void StyledWriter::writeWithIndent(const JSONCPP_STRING& value)
+{
+ this->writeIndent();
+ this->document_ += value;
}
-void StyledWriter::indent() { indentString_ += JSONCPP_STRING(indentSize_, ' '); }
+void StyledWriter::indent()
+{
+ this->indentString_ += JSONCPP_STRING(this->indentSize_, ' ');
+}
-void StyledWriter::unindent() {
- assert(indentString_.size() >= indentSize_);
- indentString_.resize(indentString_.size() - indentSize_);
+void StyledWriter::unindent()
+{
+ assert(this->indentString_.size() >= this->indentSize_);
+ this->indentString_.resize(this->indentString_.size() - this->indentSize_);
}
-void StyledWriter::writeCommentBeforeValue(const Value& root) {
+void StyledWriter::writeCommentBeforeValue(const Value& root)
+{
if (!root.hasComment(commentBefore))
return;
- document_ += "\n";
- writeIndent();
+ this->document_ += "\n";
+ this->writeIndent();
const JSONCPP_STRING& comment = root.getComment(commentBefore);
JSONCPP_STRING::const_iterator iter = comment.begin();
while (iter != comment.end()) {
- document_ += *iter;
- if (*iter == '\n' &&
- (iter != comment.end() && *(iter + 1) == '/'))
- writeIndent();
+ this->document_ += *iter;
+ if (*iter == '\n' && (iter != comment.end() && *(iter + 1) == '/'))
+ this->writeIndent();
++iter;
}
// Comments are stripped of trailing newlines, so add one here
- document_ += "\n";
+ this->document_ += "\n";
}
-void StyledWriter::writeCommentAfterValueOnSameLine(const Value& root) {
+void StyledWriter::writeCommentAfterValueOnSameLine(const Value& root)
+{
if (root.hasComment(commentAfterOnSameLine))
- document_ += " " + root.getComment(commentAfterOnSameLine);
+ this->document_ += " " + root.getComment(commentAfterOnSameLine);
if (root.hasComment(commentAfter)) {
- document_ += "\n";
- document_ += root.getComment(commentAfter);
- document_ += "\n";
+ this->document_ += "\n";
+ this->document_ += root.getComment(commentAfter);
+ this->document_ += "\n";
}
}
-bool StyledWriter::hasCommentForValue(const Value& value) {
+bool StyledWriter::hasCommentForValue(const Value& value)
+{
return value.hasComment(commentBefore) ||
- value.hasComment(commentAfterOnSameLine) ||
- value.hasComment(commentAfter);
+ value.hasComment(commentAfterOnSameLine) || value.hasComment(commentAfter);
}
// Class StyledStreamWriter
// //////////////////////////////////////////////////////////////////
StyledStreamWriter::StyledStreamWriter(JSONCPP_STRING indentation)
- : document_(NULL), rightMargin_(74), indentation_(indentation),
- addChildValues_() {}
-
-void StyledStreamWriter::write(JSONCPP_OSTREAM& out, const Value& root) {
- document_ = &out;
- addChildValues_ = false;
- indentString_.clear();
- indented_ = true;
- writeCommentBeforeValue(root);
- if (!indented_) writeIndent();
- indented_ = true;
- writeValue(root);
- writeCommentAfterValueOnSameLine(root);
- *document_ << "\n";
- document_ = NULL; // Forget the stream, for safety.
-}
-
-void StyledStreamWriter::writeValue(const Value& value) {
+ : document_(NULL)
+ , rightMargin_(74)
+ , indentation_(indentation)
+ , addChildValues_()
+{
+}
+
+void StyledStreamWriter::write(JSONCPP_OSTREAM& out, const Value& root)
+{
+ this->document_ = &out;
+ this->addChildValues_ = false;
+ this->indentString_.clear();
+ this->indented_ = true;
+ this->writeCommentBeforeValue(root);
+ if (!this->indented_)
+ this->writeIndent();
+ this->indented_ = true;
+ this->writeValue(root);
+ this->writeCommentAfterValueOnSameLine(root);
+ *this->document_ << "\n";
+ this->document_ = NULL; // Forget the stream, for safety.
+}
+
+void StyledStreamWriter::writeValue(const Value& value)
+{
switch (value.type()) {
- case nullValue:
- pushValue("null");
- break;
- case intValue:
- pushValue(valueToString(value.asLargestInt()));
- break;
- case uintValue:
- pushValue(valueToString(value.asLargestUInt()));
- break;
- case realValue:
- pushValue(valueToString(value.asDouble()));
- break;
- case stringValue:
- {
- // Is NULL possible for value.string_? No.
- char const* str;
- char const* end;
- bool ok = value.getString(&str, &end);
- if (ok) pushValue(valueToQuotedStringN(str, static_cast<unsigned>(end-str)));
- else pushValue("");
- break;
- }
- case booleanValue:
- pushValue(valueToString(value.asBool()));
- break;
- case arrayValue:
- writeArrayValue(value);
- break;
- case objectValue: {
- Value::Members members(value.getMemberNames());
- if (members.empty())
- pushValue("{}");
- else {
- writeWithIndent("{");
- indent();
- Value::Members::iterator it = members.begin();
- for (;;) {
- const JSONCPP_STRING& name = *it;
- const Value& childValue = value[name];
- writeCommentBeforeValue(childValue);
- writeWithIndent(valueToQuotedString(name.c_str()));
- *document_ << " : ";
- writeValue(childValue);
- if (++it == members.end()) {
- writeCommentAfterValueOnSameLine(childValue);
- break;
+ case nullValue:
+ this->pushValue("null");
+ break;
+ case intValue:
+ this->pushValue(valueToString(value.asLargestInt()));
+ break;
+ case uintValue:
+ this->pushValue(valueToString(value.asLargestUInt()));
+ break;
+ case realValue:
+ this->pushValue(valueToString(value.asDouble()));
+ break;
+ case stringValue: {
+ // Is NULL possible for value.string_? No.
+ char const* str;
+ char const* end;
+ bool ok = value.getString(&str, &end);
+ if (ok)
+ this->pushValue(
+ valueToQuotedStringN(str, static_cast<unsigned>(end - str)));
+ else
+ this->pushValue("");
+ break;
+ }
+ case booleanValue:
+ this->pushValue(valueToString(value.asBool()));
+ break;
+ case arrayValue:
+ this->writeArrayValue(value);
+ break;
+ case objectValue: {
+ Value::Members members(value.getMemberNames());
+ if (members.empty())
+ this->pushValue("{}");
+ else {
+ this->writeWithIndent("{");
+ this->indent();
+ Value::Members::iterator it = members.begin();
+ for (;;) {
+ const JSONCPP_STRING& name = *it;
+ const Value& childValue = value[name];
+ this->writeCommentBeforeValue(childValue);
+ this->writeWithIndent(valueToQuotedString(name.c_str()));
+ *this->document_ << " : ";
+ this->writeValue(childValue);
+ if (++it == members.end()) {
+ this->writeCommentAfterValueOnSameLine(childValue);
+ break;
+ }
+ *this->document_ << ",";
+ this->writeCommentAfterValueOnSameLine(childValue);
}
- *document_ << ",";
- writeCommentAfterValueOnSameLine(childValue);
+ this->unindent();
+ this->writeWithIndent("}");
}
- unindent();
- writeWithIndent("}");
- }
- } break;
+ } break;
}
}
-void StyledStreamWriter::writeArrayValue(const Value& value) {
+void StyledStreamWriter::writeArrayValue(const Value& value)
+{
unsigned size = value.size();
if (size == 0)
- pushValue("[]");
+ this->pushValue("[]");
else {
- bool isArrayMultiLine = isMultineArray(value);
+ bool isArrayMultiLine = this->isMultineArray(value);
if (isArrayMultiLine) {
- writeWithIndent("[");
- indent();
- bool hasChildValue = !childValues_.empty();
+ this->writeWithIndent("[");
+ this->indent();
+ bool hasChildValue = !this->childValues_.empty();
unsigned index = 0;
for (;;) {
const Value& childValue = value[index];
- writeCommentBeforeValue(childValue);
+ this->writeCommentBeforeValue(childValue);
if (hasChildValue)
- writeWithIndent(childValues_[index]);
+ this->writeWithIndent(this->childValues_[index]);
else {
- if (!indented_) writeIndent();
- indented_ = true;
- writeValue(childValue);
- indented_ = false;
+ if (!this->indented_)
+ this->writeIndent();
+ this->indented_ = true;
+ this->writeValue(childValue);
+ this->indented_ = false;
}
if (++index == size) {
- writeCommentAfterValueOnSameLine(childValue);
+ this->writeCommentAfterValueOnSameLine(childValue);
break;
}
- *document_ << ",";
- writeCommentAfterValueOnSameLine(childValue);
+ *this->document_ << ",";
+ this->writeCommentAfterValueOnSameLine(childValue);
}
- unindent();
- writeWithIndent("]");
+ this->unindent();
+ this->writeWithIndent("]");
} else // output on a single line
{
- assert(childValues_.size() == size);
- *document_ << "[ ";
+ assert(this->childValues_.size() == size);
+ *this->document_ << "[ ";
for (unsigned index = 0; index < size; ++index) {
if (index > 0)
- *document_ << ", ";
- *document_ << childValues_[index];
+ *this->document_ << ", ";
+ *this->document_ << this->childValues_[index];
}
- *document_ << " ]";
+ *this->document_ << " ]";
}
}
}
-bool StyledStreamWriter::isMultineArray(const Value& value) {
+bool StyledStreamWriter::isMultineArray(const Value& value)
+{
ArrayIndex const size = value.size();
- bool isMultiLine = size * 3 >= rightMargin_;
- childValues_.clear();
+ bool isMultiLine = size * 3 >= this->rightMargin_;
+ this->childValues_.clear();
for (ArrayIndex index = 0; index < size && !isMultiLine; ++index) {
const Value& childValue = value[index];
isMultiLine = ((childValue.isArray() || childValue.isObject()) &&
- childValue.size() > 0);
+ childValue.size() > 0);
}
if (!isMultiLine) // check if line length > max line length
{
- childValues_.reserve(size);
- addChildValues_ = true;
+ this->childValues_.reserve(size);
+ this->addChildValues_ = true;
ArrayIndex lineLength = 4 + (size - 1) * 2; // '[ ' + ', '*n + ' ]'
for (ArrayIndex index = 0; index < size; ++index) {
- if (hasCommentForValue(value[index])) {
+ if (this->hasCommentForValue(value[index])) {
isMultiLine = true;
}
- writeValue(value[index]);
- lineLength += static_cast<ArrayIndex>(childValues_[index].length());
+ this->writeValue(value[index]);
+ lineLength +=
+ static_cast<ArrayIndex>(this->childValues_[index].length());
}
- addChildValues_ = false;
- isMultiLine = isMultiLine || lineLength >= rightMargin_;
+ this->addChildValues_ = false;
+ isMultiLine = isMultiLine || lineLength >= this->rightMargin_;
}
return isMultiLine;
}
-void StyledStreamWriter::pushValue(const JSONCPP_STRING& value) {
- if (addChildValues_)
- childValues_.push_back(value);
+void StyledStreamWriter::pushValue(const JSONCPP_STRING& value)
+{
+ if (this->addChildValues_)
+ this->childValues_.push_back(value);
else
- *document_ << value;
+ *this->document_ << value;
}
-void StyledStreamWriter::writeIndent() {
+void StyledStreamWriter::writeIndent()
+{
// blep intended this to look at the so-far-written string
// to determine whether we are already indented, but
// with a stream we cannot do that. So we rely on some saved state.
// The caller checks indented_.
- *document_ << '\n' << indentString_;
+ *this->document_ << '\n' << this->indentString_;
}
-void StyledStreamWriter::writeWithIndent(const JSONCPP_STRING& value) {
- if (!indented_) writeIndent();
- *document_ << value;
- indented_ = false;
+void StyledStreamWriter::writeWithIndent(const JSONCPP_STRING& value)
+{
+ if (!this->indented_)
+ this->writeIndent();
+ *this->document_ << value;
+ this->indented_ = false;
}
-void StyledStreamWriter::indent() { indentString_ += indentation_; }
+void StyledStreamWriter::indent()
+{
+ this->indentString_ += this->indentation_;
+}
-void StyledStreamWriter::unindent() {
- assert(indentString_.size() >= indentation_.size());
- indentString_.resize(indentString_.size() - indentation_.size());
+void StyledStreamWriter::unindent()
+{
+ assert(this->indentString_.size() >= this->indentation_.size());
+ this->indentString_.resize(this->indentString_.size() -
+ this->indentation_.size());
}
-void StyledStreamWriter::writeCommentBeforeValue(const Value& root) {
+void StyledStreamWriter::writeCommentBeforeValue(const Value& root)
+{
if (!root.hasComment(commentBefore))
return;
- if (!indented_) writeIndent();
+ if (!this->indented_)
+ this->writeIndent();
const JSONCPP_STRING& comment = root.getComment(commentBefore);
JSONCPP_STRING::const_iterator iter = comment.begin();
while (iter != comment.end()) {
- *document_ << *iter;
- if (*iter == '\n' &&
- (iter != comment.end() && *(iter + 1) == '/'))
+ *this->document_ << *iter;
+ if (*iter == '\n' && (iter != comment.end() && *(iter + 1) == '/'))
// writeIndent(); // would include newline
- *document_ << indentString_;
+ *this->document_ << this->indentString_;
++iter;
}
- indented_ = false;
+ this->indented_ = false;
}
-void StyledStreamWriter::writeCommentAfterValueOnSameLine(const Value& root) {
+void StyledStreamWriter::writeCommentAfterValueOnSameLine(const Value& root)
+{
if (root.hasComment(commentAfterOnSameLine))
- *document_ << ' ' << root.getComment(commentAfterOnSameLine);
+ *this->document_ << ' ' << root.getComment(commentAfterOnSameLine);
if (root.hasComment(commentAfter)) {
- writeIndent();
- *document_ << root.getComment(commentAfter);
+ this->writeIndent();
+ *this->document_ << root.getComment(commentAfter);
}
- indented_ = false;
+ this->indented_ = false;
}
-bool StyledStreamWriter::hasCommentForValue(const Value& value) {
+bool StyledStreamWriter::hasCommentForValue(const Value& value)
+{
return value.hasComment(commentBefore) ||
- value.hasComment(commentAfterOnSameLine) ||
- value.hasComment(commentAfter);
+ value.hasComment(commentAfterOnSameLine) || value.hasComment(commentAfter);
}
//////////////////////////
// BuiltStyledStreamWriter
/// Scoped enums are not available until C++11.
-struct CommentStyle {
+struct CommentStyle
+{
/// Decide whether to write comments.
- enum Enum {
- None, ///< Drop all comments.
- Most, ///< Recover odd behavior of previous versions (not implemented yet).
- All ///< Keep all comments.
+ enum Enum
+ {
+ None, ///< Drop all comments.
+ Most, ///< Recover odd behavior of previous versions (not implemented yet).
+ All ///< Keep all comments.
};
};
struct BuiltStyledStreamWriter : public StreamWriter
{
- BuiltStyledStreamWriter(
- JSONCPP_STRING const& indentation,
- CommentStyle::Enum cs,
- JSONCPP_STRING const& colonSymbol,
- JSONCPP_STRING const& nullSymbol,
- JSONCPP_STRING const& endingLineFeedSymbol,
- bool useSpecialFloats,
- unsigned int precision);
+ BuiltStyledStreamWriter(JSONCPP_STRING const& indentation,
+ CommentStyle::Enum cs,
+ JSONCPP_STRING const& colonSymbol,
+ JSONCPP_STRING const& nullSymbol,
+ JSONCPP_STRING const& endingLineFeedSymbol,
+ bool useSpecialFloats, unsigned int precision);
int write(Value const& root, JSONCPP_OSTREAM* sout) JSONCPP_OVERRIDE;
+
private:
void writeValue(Value const& value);
void writeArrayValue(Value const& value);
@@ -911,13 +995,10 @@ private:
unsigned int precision_;
};
BuiltStyledStreamWriter::BuiltStyledStreamWriter(
- JSONCPP_STRING const& indentation,
- CommentStyle::Enum cs,
- JSONCPP_STRING const& colonSymbol,
- JSONCPP_STRING const& nullSymbol,
- JSONCPP_STRING const& endingLineFeedSymbol,
- bool useSpecialFloats,
- unsigned int precision)
+ JSONCPP_STRING const& indentation, CommentStyle::Enum cs,
+ JSONCPP_STRING const& colonSymbol, JSONCPP_STRING const& nullSymbol,
+ JSONCPP_STRING const& endingLineFeedSymbol, bool useSpecialFloats,
+ unsigned int precision)
: rightMargin_(74)
, indentation_(indentation)
, cs_(cs)
@@ -932,247 +1013,276 @@ BuiltStyledStreamWriter::BuiltStyledStreamWriter(
}
int BuiltStyledStreamWriter::write(Value const& root, JSONCPP_OSTREAM* sout)
{
- sout_ = sout;
- addChildValues_ = false;
- indented_ = true;
- indentString_.clear();
- writeCommentBeforeValue(root);
- if (!indented_) writeIndent();
- indented_ = true;
- writeValue(root);
- writeCommentAfterValueOnSameLine(root);
- *sout_ << endingLineFeedSymbol_;
- sout_ = NULL;
+ this->sout_ = sout;
+ this->addChildValues_ = false;
+ this->indented_ = true;
+ this->indentString_.clear();
+ this->writeCommentBeforeValue(root);
+ if (!this->indented_)
+ this->writeIndent();
+ this->indented_ = true;
+ this->writeValue(root);
+ this->writeCommentAfterValueOnSameLine(root);
+ *this->sout_ << this->endingLineFeedSymbol_;
+ this->sout_ = NULL;
return 0;
}
-void BuiltStyledStreamWriter::writeValue(Value const& value) {
+void BuiltStyledStreamWriter::writeValue(Value const& value)
+{
switch (value.type()) {
- case nullValue:
- pushValue(nullSymbol_);
- break;
- case intValue:
- pushValue(valueToString(value.asLargestInt()));
- break;
- case uintValue:
- pushValue(valueToString(value.asLargestUInt()));
- break;
- case realValue:
- pushValue(valueToString(value.asDouble(), useSpecialFloats_, precision_));
- break;
- case stringValue:
- {
- // Is NULL is possible for value.string_? No.
- char const* str;
- char const* end;
- bool ok = value.getString(&str, &end);
- if (ok) pushValue(valueToQuotedStringN(str, static_cast<unsigned>(end-str)));
- else pushValue("");
- break;
- }
- case booleanValue:
- pushValue(valueToString(value.asBool()));
- break;
- case arrayValue:
- writeArrayValue(value);
- break;
- case objectValue: {
- Value::Members members(value.getMemberNames());
- if (members.empty())
- pushValue("{}");
- else {
- writeWithIndent("{");
- indent();
- Value::Members::iterator it = members.begin();
- for (;;) {
- JSONCPP_STRING const& name = *it;
- Value const& childValue = value[name];
- writeCommentBeforeValue(childValue);
- writeWithIndent(valueToQuotedStringN(name.data(), static_cast<unsigned>(name.length())));
- *sout_ << colonSymbol_;
- writeValue(childValue);
- if (++it == members.end()) {
- writeCommentAfterValueOnSameLine(childValue);
- break;
+ case nullValue:
+ this->pushValue(this->nullSymbol_);
+ break;
+ case intValue:
+ this->pushValue(valueToString(value.asLargestInt()));
+ break;
+ case uintValue:
+ this->pushValue(valueToString(value.asLargestUInt()));
+ break;
+ case realValue:
+ this->pushValue(valueToString(value.asDouble(), this->useSpecialFloats_,
+ this->precision_));
+ break;
+ case stringValue: {
+ // Is NULL is possible for value.string_? No.
+ char const* str;
+ char const* end;
+ bool ok = value.getString(&str, &end);
+ if (ok)
+ this->pushValue(
+ valueToQuotedStringN(str, static_cast<unsigned>(end - str)));
+ else
+ this->pushValue("");
+ break;
+ }
+ case booleanValue:
+ this->pushValue(valueToString(value.asBool()));
+ break;
+ case arrayValue:
+ this->writeArrayValue(value);
+ break;
+ case objectValue: {
+ Value::Members members(value.getMemberNames());
+ if (members.empty())
+ this->pushValue("{}");
+ else {
+ this->writeWithIndent("{");
+ this->indent();
+ Value::Members::iterator it = members.begin();
+ for (;;) {
+ JSONCPP_STRING const& name = *it;
+ Value const& childValue = value[name];
+ this->writeCommentBeforeValue(childValue);
+ this->writeWithIndent(valueToQuotedStringN(
+ name.data(), static_cast<unsigned>(name.length())));
+ *this->sout_ << this->colonSymbol_;
+ this->writeValue(childValue);
+ if (++it == members.end()) {
+ this->writeCommentAfterValueOnSameLine(childValue);
+ break;
+ }
+ *this->sout_ << ",";
+ this->writeCommentAfterValueOnSameLine(childValue);
}
- *sout_ << ",";
- writeCommentAfterValueOnSameLine(childValue);
+ this->unindent();
+ this->writeWithIndent("}");
}
- unindent();
- writeWithIndent("}");
- }
- } break;
+ } break;
}
}
-void BuiltStyledStreamWriter::writeArrayValue(Value const& value) {
+void BuiltStyledStreamWriter::writeArrayValue(Value const& value)
+{
unsigned size = value.size();
if (size == 0)
- pushValue("[]");
+ this->pushValue("[]");
else {
- bool isMultiLine = (cs_ == CommentStyle::All) || isMultineArray(value);
+ bool isMultiLine =
+ (this->cs_ == CommentStyle::All) || this->isMultineArray(value);
if (isMultiLine) {
- writeWithIndent("[");
- indent();
- bool hasChildValue = !childValues_.empty();
+ this->writeWithIndent("[");
+ this->indent();
+ bool hasChildValue = !this->childValues_.empty();
unsigned index = 0;
for (;;) {
Value const& childValue = value[index];
- writeCommentBeforeValue(childValue);
+ this->writeCommentBeforeValue(childValue);
if (hasChildValue)
- writeWithIndent(childValues_[index]);
+ this->writeWithIndent(this->childValues_[index]);
else {
- if (!indented_) writeIndent();
- indented_ = true;
- writeValue(childValue);
- indented_ = false;
+ if (!this->indented_)
+ this->writeIndent();
+ this->indented_ = true;
+ this->writeValue(childValue);
+ this->indented_ = false;
}
if (++index == size) {
- writeCommentAfterValueOnSameLine(childValue);
+ this->writeCommentAfterValueOnSameLine(childValue);
break;
}
- *sout_ << ",";
- writeCommentAfterValueOnSameLine(childValue);
+ *this->sout_ << ",";
+ this->writeCommentAfterValueOnSameLine(childValue);
}
- unindent();
- writeWithIndent("]");
+ this->unindent();
+ this->writeWithIndent("]");
} else // output on a single line
{
- assert(childValues_.size() == size);
- *sout_ << "[";
- if (!indentation_.empty()) *sout_ << " ";
+ assert(this->childValues_.size() == size);
+ *this->sout_ << "[";
+ if (!this->indentation_.empty())
+ *this->sout_ << " ";
for (unsigned index = 0; index < size; ++index) {
if (index > 0)
- *sout_ << ((!indentation_.empty()) ? ", " : ",");
- *sout_ << childValues_[index];
+ *this->sout_ << ((!this->indentation_.empty()) ? ", " : ",");
+ *this->sout_ << this->childValues_[index];
}
- if (!indentation_.empty()) *sout_ << " ";
- *sout_ << "]";
+ if (!this->indentation_.empty())
+ *this->sout_ << " ";
+ *this->sout_ << "]";
}
}
}
-bool BuiltStyledStreamWriter::isMultineArray(Value const& value) {
+bool BuiltStyledStreamWriter::isMultineArray(Value const& value)
+{
ArrayIndex const size = value.size();
- bool isMultiLine = size * 3 >= rightMargin_;
- childValues_.clear();
+ bool isMultiLine = size * 3 >= this->rightMargin_;
+ this->childValues_.clear();
for (ArrayIndex index = 0; index < size && !isMultiLine; ++index) {
Value const& childValue = value[index];
isMultiLine = ((childValue.isArray() || childValue.isObject()) &&
- childValue.size() > 0);
+ childValue.size() > 0);
}
if (!isMultiLine) // check if line length > max line length
{
- childValues_.reserve(size);
- addChildValues_ = true;
+ this->childValues_.reserve(size);
+ this->addChildValues_ = true;
ArrayIndex lineLength = 4 + (size - 1) * 2; // '[ ' + ', '*n + ' ]'
for (ArrayIndex index = 0; index < size; ++index) {
if (hasCommentForValue(value[index])) {
isMultiLine = true;
}
- writeValue(value[index]);
- lineLength += static_cast<ArrayIndex>(childValues_[index].length());
+ this->writeValue(value[index]);
+ lineLength +=
+ static_cast<ArrayIndex>(this->childValues_[index].length());
}
- addChildValues_ = false;
- isMultiLine = isMultiLine || lineLength >= rightMargin_;
+ this->addChildValues_ = false;
+ isMultiLine = isMultiLine || lineLength >= this->rightMargin_;
}
return isMultiLine;
}
-void BuiltStyledStreamWriter::pushValue(JSONCPP_STRING const& value) {
- if (addChildValues_)
- childValues_.push_back(value);
+void BuiltStyledStreamWriter::pushValue(JSONCPP_STRING const& value)
+{
+ if (this->addChildValues_)
+ this->childValues_.push_back(value);
else
- *sout_ << value;
+ *this->sout_ << value;
}
-void BuiltStyledStreamWriter::writeIndent() {
+void BuiltStyledStreamWriter::writeIndent()
+{
// blep intended this to look at the so-far-written string
// to determine whether we are already indented, but
// with a stream we cannot do that. So we rely on some saved state.
// The caller checks indented_.
- if (!indentation_.empty()) {
+ if (!this->indentation_.empty()) {
// In this case, drop newlines too.
- *sout_ << '\n' << indentString_;
+ *this->sout_ << '\n' << this->indentString_;
}
}
-void BuiltStyledStreamWriter::writeWithIndent(JSONCPP_STRING const& value) {
- if (!indented_) writeIndent();
- *sout_ << value;
- indented_ = false;
+void BuiltStyledStreamWriter::writeWithIndent(JSONCPP_STRING const& value)
+{
+ if (!this->indented_)
+ this->writeIndent();
+ *this->sout_ << value;
+ this->indented_ = false;
}
-void BuiltStyledStreamWriter::indent() { indentString_ += indentation_; }
+void BuiltStyledStreamWriter::indent()
+{
+ this->indentString_ += this->indentation_;
+}
-void BuiltStyledStreamWriter::unindent() {
- assert(indentString_.size() >= indentation_.size());
- indentString_.resize(indentString_.size() - indentation_.size());
+void BuiltStyledStreamWriter::unindent()
+{
+ assert(this->indentString_.size() >= this->indentation_.size());
+ this->indentString_.resize(this->indentString_.size() -
+ this->indentation_.size());
}
-void BuiltStyledStreamWriter::writeCommentBeforeValue(Value const& root) {
- if (cs_ == CommentStyle::None) return;
+void BuiltStyledStreamWriter::writeCommentBeforeValue(Value const& root)
+{
+ if (this->cs_ == CommentStyle::None)
+ return;
if (!root.hasComment(commentBefore))
return;
- if (!indented_) writeIndent();
+ if (!this->indented_)
+ this->writeIndent();
const JSONCPP_STRING& comment = root.getComment(commentBefore);
JSONCPP_STRING::const_iterator iter = comment.begin();
while (iter != comment.end()) {
- *sout_ << *iter;
- if (*iter == '\n' &&
- (iter != comment.end() && *(iter + 1) == '/'))
+ *this->sout_ << *iter;
+ if (*iter == '\n' && (iter != comment.end() && *(iter + 1) == '/'))
// writeIndent(); // would write extra newline
- *sout_ << indentString_;
+ *this->sout_ << this->indentString_;
++iter;
}
- indented_ = false;
+ this->indented_ = false;
}
-void BuiltStyledStreamWriter::writeCommentAfterValueOnSameLine(Value const& root) {
- if (cs_ == CommentStyle::None) return;
+void BuiltStyledStreamWriter::writeCommentAfterValueOnSameLine(
+ Value const& root)
+{
+ if (this->cs_ == CommentStyle::None)
+ return;
if (root.hasComment(commentAfterOnSameLine))
- *sout_ << " " + root.getComment(commentAfterOnSameLine);
+ *this->sout_ << " " + root.getComment(commentAfterOnSameLine);
if (root.hasComment(commentAfter)) {
- writeIndent();
- *sout_ << root.getComment(commentAfter);
+ this->writeIndent();
+ *this->sout_ << root.getComment(commentAfter);
}
}
// static
-bool BuiltStyledStreamWriter::hasCommentForValue(const Value& value) {
+bool BuiltStyledStreamWriter::hasCommentForValue(const Value& value)
+{
return value.hasComment(commentBefore) ||
- value.hasComment(commentAfterOnSameLine) ||
- value.hasComment(commentAfter);
+ value.hasComment(commentAfterOnSameLine) || value.hasComment(commentAfter);
}
///////////////
// StreamWriter
StreamWriter::StreamWriter()
- : sout_(NULL)
+ : sout_(NULL)
{
}
StreamWriter::~StreamWriter()
{
}
StreamWriter::Factory::~Factory()
-{}
+{
+}
StreamWriterBuilder::StreamWriterBuilder()
{
- setDefaults(&settings_);
+ setDefaults(&this->settings_);
}
StreamWriterBuilder::~StreamWriterBuilder()
-{}
+{
+}
StreamWriter* StreamWriterBuilder::newStreamWriter() const
{
- JSONCPP_STRING indentation = settings_["indentation"].asString();
- JSONCPP_STRING cs_str = settings_["commentStyle"].asString();
- bool eyc = settings_["enableYAMLCompatibility"].asBool();
- bool dnp = settings_["dropNullPlaceholders"].asBool();
- bool usf = settings_["useSpecialFloats"].asBool();
- unsigned int pre = settings_["precision"].asUInt();
+ JSONCPP_STRING indentation = this->settings_["indentation"].asString();
+ JSONCPP_STRING cs_str = this->settings_["commentStyle"].asString();
+ bool eyc = this->settings_["enableYAMLCompatibility"].asBool();
+ bool dnp = this->settings_["dropNullPlaceholders"].asBool();
+ bool usf = this->settings_["useSpecialFloats"].asBool();
+ unsigned int pre = this->settings_["precision"].asUInt();
CommentStyle::Enum cs = CommentStyle::All;
if (cs_str == "All") {
cs = CommentStyle::All;
@@ -1191,11 +1301,11 @@ StreamWriter* StreamWriterBuilder::newStreamWriter() const
if (dnp) {
nullSymbol.clear();
}
- if (pre > 17) pre = 17;
+ if (pre > 17)
+ pre = 17;
JSONCPP_STRING endingLineFeedSymbol;
- return new BuiltStyledStreamWriter(
- indentation, cs,
- colonSymbol, nullSymbol, endingLineFeedSymbol, usf, pre);
+ return new BuiltStyledStreamWriter(indentation, cs, colonSymbol, nullSymbol,
+ endingLineFeedSymbol, usf, pre);
}
static void getValidWriterKeys(std::set<JSONCPP_STRING>* valid_keys)
{
@@ -1210,23 +1320,24 @@ static void getValidWriterKeys(std::set<JSONCPP_STRING>* valid_keys)
bool StreamWriterBuilder::validate(Json::Value* invalid) const
{
Json::Value my_invalid;
- if (!invalid) invalid = &my_invalid; // so we do not need to test for NULL
+ if (!invalid)
+ invalid = &my_invalid; // so we do not need to test for NULL
Json::Value& inv = *invalid;
std::set<JSONCPP_STRING> valid_keys;
getValidWriterKeys(&valid_keys);
- Value::Members keys = settings_.getMemberNames();
+ Value::Members keys = this->settings_.getMemberNames();
size_t n = keys.size();
for (size_t i = 0; i < n; ++i) {
JSONCPP_STRING const& key = keys[i];
if (valid_keys.find(key) == valid_keys.end()) {
- inv[key] = settings_[key];
+ inv[key] = this->settings_[key];
}
}
return 0u == inv.size();
}
Value& StreamWriterBuilder::operator[](JSONCPP_STRING key)
{
- return settings_[key];
+ return this->settings_[key];
}
// static
void StreamWriterBuilder::setDefaults(Json::Value* settings)
@@ -1241,14 +1352,17 @@ void StreamWriterBuilder::setDefaults(Json::Value* settings)
//! [StreamWriterBuilderDefaults]
}
-JSONCPP_STRING writeString(StreamWriter::Factory const& builder, Value const& root) {
+JSONCPP_STRING writeString(StreamWriter::Factory const& builder,
+ Value const& root)
+{
JSONCPP_OSTRINGSTREAM sout;
StreamWriterPtr const writer(builder.newStreamWriter());
writer->write(root, &sout);
return sout.str();
}
-JSONCPP_OSTREAM& operator<<(JSONCPP_OSTREAM& sout, Value const& root) {
+JSONCPP_OSTREAM& operator<<(JSONCPP_OSTREAM& sout, Value const& root)
+{
StreamWriterBuilder builder;
StreamWriterPtr const writer(builder.newStreamWriter());
writer->write(root, &sout);
diff --git a/Utilities/cmlibarchive/CMakeLists.txt b/Utilities/cmlibarchive/CMakeLists.txt
index bfcaf30bb..689d98afb 100644
--- a/Utilities/cmlibarchive/CMakeLists.txt
+++ b/Utilities/cmlibarchive/CMakeLists.txt
@@ -94,7 +94,7 @@ SET(CMAKE_REQUIRED_FLAGS)
# Disable warnings to avoid changing 3rd party code.
IF(CMAKE_C_COMPILER_ID MATCHES
- "^(GNU|Clang|AppleClang|XLClang|XL|VisualAge|SunPro|HP|Intel)$")
+ "^(GNU|Clang|AppleClang|XLClang|XL|VisualAge|SunPro|HP|Intel|IntelLLVM)$")
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -w")
ELSEIF(CMAKE_C_COMPILER_ID STREQUAL "PathScale")
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -woffall")
@@ -1475,9 +1475,15 @@ CHECK_C_SOURCE_COMPILES(
"#include <sys/sysmacros.h>\nint main() { return major(256); }"
MAJOR_IN_SYSMACROS)
+CMAKE_PUSH_CHECK_STATE()
+SET(CMAKE_REQUIRED_LIBRARIES ${LIBLZMA_LIBRARIES})
+SET(CMAKE_REQUIRED_INCLUDES ${LIBLZMA_INCLUDE_DIR})
+
CHECK_C_SOURCE_COMPILES(
"#include <lzma.h>\n#if LZMA_VERSION < 50020000\n#error unsupported\n#endif\nint main(void){lzma_stream_encoder_mt(0, 0); return 0;}"
- HAVE_LZMA_STREAM_ENCODER_MT)
+HAVE_LZMA_STREAM_ENCODER_MT)
+
+CMAKE_POP_CHECK_STATE()
IF(HAVE_STRERROR_R)
SET(HAVE_DECL_STRERROR_R 1)
diff --git a/Utilities/cmlibarchive/libarchive/archive_random.c b/Utilities/cmlibarchive/libarchive/archive_random.c
index 9d1aa493f..65ea69157 100644
--- a/Utilities/cmlibarchive/libarchive/archive_random.c
+++ b/Utilities/cmlibarchive/libarchive/archive_random.c
@@ -173,7 +173,7 @@ arc4_init(void)
}
static inline void
-arc4_addrandom(uint8_t *dat, int datlen)
+arc4_addrandom(u_char *dat, int datlen)
{
int n;
uint8_t si;
@@ -196,7 +196,7 @@ arc4_stir(void)
struct {
struct timeval tv;
pid_t pid;
- uint8_t rnd[KEYSIZE];
+ u_char rnd[KEYSIZE];
} rdat;
if (!rs_initialized) {
@@ -216,7 +216,7 @@ arc4_stir(void)
/* We'll just take whatever was on the stack too... */
}
- arc4_addrandom((uint8_t *)&rdat, KEYSIZE);
+ arc4_addrandom((u_char *)&rdat, KEYSIZE);
/*
* Discard early keystream, as per recommendations in:
@@ -258,7 +258,7 @@ arc4_getbyte(void)
static void
arc4random_buf(void *_buf, size_t n)
{
- uint8_t *buf = (uint8_t *)_buf;
+ u_char *buf = (u_char *)_buf;
_ARC4_LOCK();
arc4_stir_if_needed();
while (n--) {
diff --git a/Utilities/cmliblzma/CMakeLists.txt b/Utilities/cmliblzma/CMakeLists.txt
index 6b6fae63c..32a14dc23 100644
--- a/Utilities/cmliblzma/CMakeLists.txt
+++ b/Utilities/cmliblzma/CMakeLists.txt
@@ -148,7 +148,7 @@ INCLUDE_DIRECTORIES(
# Disable warnings to avoid changing 3rd party code.
IF(CMAKE_C_COMPILER_ID MATCHES
- "^(GNU|Clang|AppleClang|XLClang|XL|VisualAge|SunPro|HP|Intel)$")
+ "^(GNU|Clang|AppleClang|XLClang|XL|VisualAge|SunPro|HP|Intel|IntelLLVM)$")
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -w")
ELSEIF(CMAKE_C_COMPILER_ID STREQUAL "PathScale")
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -woffall")
diff --git a/Utilities/cmlibrhash/CMakeLists.txt b/Utilities/cmlibrhash/CMakeLists.txt
index 1b025fc7b..37e2399c4 100644
--- a/Utilities/cmlibrhash/CMakeLists.txt
+++ b/Utilities/cmlibrhash/CMakeLists.txt
@@ -2,7 +2,7 @@ project(librhash C)
# Disable warnings to avoid changing 3rd party code.
if(CMAKE_C_COMPILER_ID MATCHES
- "^(GNU|Clang|AppleClang|XLClang|XL|VisualAge|SunPro|HP|Intel)$")
+ "^(GNU|Clang|AppleClang|XLClang|XL|VisualAge|SunPro|HP|Intel|IntelLLVM)$")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -w")
elseif(CMAKE_C_COMPILER_ID STREQUAL "PathScale")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -woffall")
diff --git a/Utilities/cmlibuv/CMakeLists.txt b/Utilities/cmlibuv/CMakeLists.txt
index 92d241127..f8b47af46 100644
--- a/Utilities/cmlibuv/CMakeLists.txt
+++ b/Utilities/cmlibuv/CMakeLists.txt
@@ -2,7 +2,7 @@ project(libuv C)
# Disable warnings to avoid changing 3rd party code.
if(CMAKE_C_COMPILER_ID MATCHES
- "^(GNU|Clang|AppleClang|XLClang|XL|VisualAge|SunPro|HP|Intel)$")
+ "^(GNU|Clang|AppleClang|XLClang|XL|VisualAge|SunPro|HP|Intel|IntelLLVM)$")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -w")
elseif(CMAKE_C_COMPILER_ID STREQUAL "PathScale")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -woffall")
diff --git a/Utilities/cmnghttp2/CMakeLists.txt b/Utilities/cmnghttp2/CMakeLists.txt
index 3a11acec6..17cc6ddb2 100644
--- a/Utilities/cmnghttp2/CMakeLists.txt
+++ b/Utilities/cmnghttp2/CMakeLists.txt
@@ -1,6 +1,6 @@
# Disable warnings to avoid changing 3rd party code.
if(CMAKE_C_COMPILER_ID MATCHES
- "^(GNU|Clang|AppleClang|XLClang|XL|VisualAge|SunPro|HP|Intel)$")
+ "^(GNU|Clang|AppleClang|XLClang|XL|VisualAge|SunPro|HP|Intel|IntelLLVM)$")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -w")
elseif(CMAKE_C_COMPILER_ID STREQUAL "PathScale")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -woffall")
diff --git a/Utilities/cmzlib/CMakeLists.txt b/Utilities/cmzlib/CMakeLists.txt
index 0584c5560..d266af936 100644
--- a/Utilities/cmzlib/CMakeLists.txt
+++ b/Utilities/cmzlib/CMakeLists.txt
@@ -2,7 +2,7 @@ PROJECT(CMZLIB)
# Disable warnings to avoid changing 3rd party code.
if(CMAKE_C_COMPILER_ID MATCHES
- "^(GNU|Clang|AppleClang|XLClang|XL|VisualAge|SunPro|HP|Intel)$")
+ "^(GNU|Clang|AppleClang|XLClang|XL|VisualAge|SunPro|HP|Intel|IntelLLVM)$")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -w")
elseif(CMAKE_C_COMPILER_ID STREQUAL "PathScale")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -woffall")
diff --git a/Utilities/cmzstd/CMakeLists.txt b/Utilities/cmzstd/CMakeLists.txt
index 4f4f91fe0..323151c08 100644
--- a/Utilities/cmzstd/CMakeLists.txt
+++ b/Utilities/cmzstd/CMakeLists.txt
@@ -2,7 +2,7 @@ project(zstd C)
# Disable warnings to avoid changing 3rd party code.
if(CMAKE_C_COMPILER_ID MATCHES
- "^(GNU|Clang|AppleClang|XLClang|XL|VisualAge|SunPro|HP|Intel)$")
+ "^(GNU|Clang|AppleClang|XLClang|XL|VisualAge|SunPro|HP|Intel|IntelLLVM)$")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -w")
elseif(CMAKE_C_COMPILER_ID STREQUAL "PathScale")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -woffall")
diff --git a/Utilities/std/cm/optional b/Utilities/std/cm/optional
index 9a5d84076..2ebc78c0b 100644
--- a/Utilities/std/cm/optional
+++ b/Utilities/std/cm/optional
@@ -68,16 +68,22 @@ public:
optional& operator=(nullopt_t) noexcept;
optional& operator=(const optional& other);
- optional& operator=(optional&& other) noexcept;
- template <
- typename U = T,
- typename = typename std::enable_if<
- !std::is_same<typename std::decay<U>::type, cm::optional<T>>::value &&
- std::is_constructible<T, U>::value && std::is_assignable<T&, U>::value &&
+ template <typename U = T>
+ typename std::enable_if<std::is_constructible<T, U&&>::value &&
+ std::is_assignable<T&, U&&>::value,
+ optional&>::type
+ operator=(optional<U>&& other) noexcept;
+
+ template <typename U = T>
+ typename std::enable_if<
+ !std::is_same<typename std::decay<U>::type, cm::optional<T>>::value &&
+ std::is_constructible<T, U&&>::value &&
+ std::is_assignable<T&, U&&>::value &&
(!std::is_scalar<T>::value ||
- !std::is_same<typename std::decay<U>::type, T>::value)>::type>
- optional& operator=(U&& v);
+ !std::is_same<typename std::decay<U>::type, T>::value),
+ optional&>::type
+ operator=(U&& v);
const T* operator->() const;
T* operator->();
@@ -134,19 +140,24 @@ optional<T> make_optional(Args&&... args)
template <typename T>
optional<T>::optional(nullopt_t) noexcept
+ : optional()
{
}
template <typename T>
optional<T>::optional(const optional& other)
{
- *this = other;
+ if (other.has_value()) {
+ this->emplace(*other);
+ }
}
template <typename T>
optional<T>::optional(optional&& other) noexcept
{
- *this = std::move(other);
+ if (other.has_value()) {
+ this->emplace(std::move(*other));
+ }
}
template <typename T>
@@ -192,7 +203,11 @@ optional<T>& optional<T>::operator=(const optional& other)
}
template <typename T>
-optional<T>& optional<T>::operator=(optional&& other) noexcept
+template <typename U>
+typename std::enable_if<std::is_constructible<T, U&&>::value &&
+ std::is_assignable<T&, U&&>::value,
+ optional<T>&>::type
+optional<T>::operator=(optional<U>&& other) noexcept
{
if (other.has_value()) {
if (this->has_value()) {
@@ -207,8 +222,15 @@ optional<T>& optional<T>::operator=(optional&& other) noexcept
}
template <typename T>
-template <typename U, typename>
-optional<T>& optional<T>::operator=(U&& v)
+template <typename U>
+typename std::enable_if<
+ !std::is_same<typename std::decay<U>::type, cm::optional<T>>::value &&
+ std::is_constructible<T, U&&>::value &&
+ std::is_assignable<T&, U&&>::value &&
+ (!std::is_scalar<T>::value ||
+ !std::is_same<typename std::decay<U>::type, T>::value),
+ optional<T>&>::type
+optional<T>::operator=(U&& v)
{
if (this->has_value()) {
this->value() = v;
@@ -291,7 +313,7 @@ bool operator!=(const optional<T>& opt, nullopt_t) noexcept
}
template <typename T>
-bool operator<(const optional<T>& opt, nullopt_t) noexcept
+bool operator<(const optional<T>& /*opt*/, nullopt_t) noexcept
{
return false;
}
@@ -309,7 +331,7 @@ bool operator>(const optional<T>& opt, nullopt_t) noexcept
}
template <typename T>
-bool operator>=(const optional<T>& opt, nullopt_t) noexcept
+bool operator>=(const optional<T>& /*opt*/, nullopt_t) noexcept
{
return true;
}
@@ -333,13 +355,13 @@ bool operator<(nullopt_t, const optional<T>& opt) noexcept
}
template <typename T>
-bool operator<=(nullopt_t, const optional<T>& opt) noexcept
+bool operator<=(nullopt_t, const optional<T>& /*opt*/) noexcept
{
return true;
}
template <typename T>
-bool operator>(nullopt_t, const optional<T>& opt) noexcept
+bool operator>(nullopt_t, const optional<T>& /*opt*/) noexcept
{
return false;
}