summaryrefslogtreecommitdiff
path: root/libs
diff options
context:
space:
mode:
authordartraiden <wowemuh@gmail.com>2023-12-10 18:22:53 +0300
committerdartraiden <wowemuh@gmail.com>2023-12-10 18:25:13 +0300
commit2ae0fc7299825cc561197d3f23c90e52ae8db58b (patch)
tree95fa8e7eb16cdff25b74d2d0ec033e667d4fd2c5 /libs
parent76646f7a6d85fd5cdef2a610e0711bf4a9d8fdf3 (diff)
libcurl: update to 8.5.0
Diffstat (limited to 'libs')
-rw-r--r--libs/libcurl/docs/CHANGES5679
-rw-r--r--libs/libcurl/docs/THANKS42
-rw-r--r--libs/libcurl/include/curl/curl.h26
-rw-r--r--libs/libcurl/include/curl/curlver.h8
-rw-r--r--libs/libcurl/include/curl/system.h37
-rw-r--r--libs/libcurl/src/CMakeLists.txt21
-rw-r--r--libs/libcurl/src/Makefile.am2
-rw-r--r--libs/libcurl/src/Makefile.in2
-rw-r--r--libs/libcurl/src/altsvc.c10
-rw-r--r--libs/libcurl/src/arpa_telnet.h9
-rw-r--r--libs/libcurl/src/asyn-ares.c149
-rw-r--r--libs/libcurl/src/asyn-thread.c50
-rw-r--r--libs/libcurl/src/base64.c1
-rw-r--r--libs/libcurl/src/c-hyper.c106
-rw-r--r--libs/libcurl/src/cf-h1-proxy.c55
-rw-r--r--libs/libcurl/src/cf-h2-proxy.c67
-rw-r--r--libs/libcurl/src/cf-haproxy.c20
-rw-r--r--libs/libcurl/src/cf-https-connect.c54
-rw-r--r--libs/libcurl/src/cf-socket.c93
-rw-r--r--libs/libcurl/src/cfilters.c204
-rw-r--r--libs/libcurl/src/cfilters.h113
-rw-r--r--libs/libcurl/src/config-amigaos.h1
-rw-r--r--libs/libcurl/src/config-dos.h1
-rw-r--r--libs/libcurl/src/config-os400.h6
-rw-r--r--libs/libcurl/src/config-plan9.h2
-rw-r--r--libs/libcurl/src/config-riscos.h6
-rw-r--r--libs/libcurl/src/config-win32.h116
-rw-r--r--libs/libcurl/src/config-win32ce.h5
-rw-r--r--libs/libcurl/src/conncache.c25
-rw-r--r--libs/libcurl/src/connect.c93
-rw-r--r--libs/libcurl/src/content_encoding.c281
-rw-r--r--libs/libcurl/src/content_encoding.h9
-rw-r--r--libs/libcurl/src/cookie.c32
-rw-r--r--libs/libcurl/src/curl_config.h.cmake27
-rw-r--r--libs/libcurl/src/curl_config.h.in12
-rw-r--r--libs/libcurl/src/curl_hmac.h3
-rw-r--r--libs/libcurl/src/curl_memory.h6
-rw-r--r--libs/libcurl/src/curl_multibyte.c4
-rw-r--r--libs/libcurl/src/curl_multibyte.h8
-rw-r--r--libs/libcurl/src/curl_ntlm_core.c9
-rw-r--r--libs/libcurl/src/curl_ntlm_wb.c14
-rw-r--r--libs/libcurl/src/curl_path.h2
-rw-r--r--libs/libcurl/src/curl_rtmp.c2
-rw-r--r--libs/libcurl/src/curl_sasl.c3
-rw-r--r--libs/libcurl/src/curl_setup.h151
-rw-r--r--libs/libcurl/src/curl_setup_once.h8
-rw-r--r--libs/libcurl/src/curl_sspi.h16
-rw-r--r--libs/libcurl/src/curl_trc.c26
-rw-r--r--libs/libcurl/src/curl_trc.h108
-rw-r--r--libs/libcurl/src/doh.c43
-rw-r--r--libs/libcurl/src/dynbuf.c6
-rw-r--r--libs/libcurl/src/dynhds.c29
-rw-r--r--libs/libcurl/src/dynhds.h9
-rw-r--r--libs/libcurl/src/easy.c84
-rw-r--r--libs/libcurl/src/easy_lock.h9
-rw-r--r--libs/libcurl/src/file.c8
-rw-r--r--libs/libcurl/src/fopen.c77
-rw-r--r--libs/libcurl/src/formdata.c8
-rw-r--r--libs/libcurl/src/ftp.c6
-rw-r--r--libs/libcurl/src/ftplistparser.c3
-rw-r--r--libs/libcurl/src/functypes.h2
-rw-r--r--libs/libcurl/src/getenv.c5
-rw-r--r--libs/libcurl/src/hostasyn.c11
-rw-r--r--libs/libcurl/src/hostip.c115
-rw-r--r--libs/libcurl/src/hostip.h4
-rw-r--r--libs/libcurl/src/hostip6.c7
-rw-r--r--libs/libcurl/src/hsts.c28
-rw-r--r--libs/libcurl/src/http.c236
-rw-r--r--libs/libcurl/src/http.h6
-rw-r--r--libs/libcurl/src/http2.c134
-rw-r--r--libs/libcurl/src/http_aws_sigv4.c11
-rw-r--r--libs/libcurl/src/http_chunks.c83
-rw-r--r--libs/libcurl/src/http_chunks.h4
-rw-r--r--libs/libcurl/src/http_proxy.c2
-rw-r--r--libs/libcurl/src/idn.c2
-rw-r--r--libs/libcurl/src/imap.c4
-rw-r--r--libs/libcurl/src/ldap.c20
-rw-r--r--libs/libcurl/src/libcurl.plist6
-rw-r--r--libs/libcurl/src/md4.c5
-rw-r--r--libs/libcurl/src/memdebug.c2
-rw-r--r--libs/libcurl/src/memdebug.h4
-rw-r--r--libs/libcurl/src/mime.c5
-rw-r--r--libs/libcurl/src/mprintf.c7
-rw-r--r--libs/libcurl/src/mqtt.c9
-rw-r--r--libs/libcurl/src/multi.c295
-rw-r--r--libs/libcurl/src/multihandle.h15
-rw-r--r--libs/libcurl/src/netrc.c2
-rw-r--r--libs/libcurl/src/openldap.c54
-rw-r--r--libs/libcurl/src/pop3.c2
-rw-r--r--libs/libcurl/src/progress.c8
-rw-r--r--libs/libcurl/src/rand.c28
-rw-r--r--libs/libcurl/src/rand.h2
-rw-r--r--libs/libcurl/src/rename.c2
-rw-r--r--libs/libcurl/src/rtsp.c359
-rw-r--r--libs/libcurl/src/rtsp.h9
-rw-r--r--libs/libcurl/src/select.c2
-rw-r--r--libs/libcurl/src/sendf.c326
-rw-r--r--libs/libcurl/src/sendf.h127
-rw-r--r--libs/libcurl/src/setopt.c220
-rw-r--r--libs/libcurl/src/setup-win32.h13
-rw-r--r--libs/libcurl/src/share.h10
-rw-r--r--libs/libcurl/src/smb.c9
-rw-r--r--libs/libcurl/src/smtp.c2
-rw-r--r--libs/libcurl/src/socketpair.c6
-rw-r--r--libs/libcurl/src/socketpair.h17
-rw-r--r--libs/libcurl/src/socks.c48
-rw-r--r--libs/libcurl/src/strdup.c28
-rw-r--r--libs/libcurl/src/strdup.h3
-rw-r--r--libs/libcurl/src/strerror.c20
-rw-r--r--libs/libcurl/src/strerror.h2
-rw-r--r--libs/libcurl/src/system_win32.c4
-rw-r--r--libs/libcurl/src/system_win32.h6
-rw-r--r--libs/libcurl/src/tftp.c14
-rw-r--r--libs/libcurl/src/tftp.h3
-rw-r--r--libs/libcurl/src/timediff.c2
-rw-r--r--libs/libcurl/src/timeval.c7
-rw-r--r--libs/libcurl/src/transfer.c277
-rw-r--r--libs/libcurl/src/url.c1187
-rw-r--r--libs/libcurl/src/url.h9
-rw-r--r--libs/libcurl/src/urlapi.c45
-rw-r--r--libs/libcurl/src/urldata.h86
-rw-r--r--libs/libcurl/src/vauth/digest.c1
-rw-r--r--libs/libcurl/src/version.c12
-rw-r--r--libs/libcurl/src/version_win32.c4
-rw-r--r--libs/libcurl/src/version_win32.h4
-rw-r--r--libs/libcurl/src/vquic/curl_msh3.c35
-rw-r--r--libs/libcurl/src/vquic/curl_ngtcp2.c360
-rw-r--r--libs/libcurl/src/vquic/curl_quiche.c249
-rw-r--r--libs/libcurl/src/vquic/vquic.c27
-rw-r--r--libs/libcurl/src/vquic/vquic_int.h6
-rw-r--r--libs/libcurl/src/vssh/libssh.c46
-rw-r--r--libs/libcurl/src/vssh/libssh2.c262
-rw-r--r--libs/libcurl/src/vssh/ssh.h1
-rw-r--r--libs/libcurl/src/vssh/wolfssh.c3
-rw-r--r--libs/libcurl/src/vtls/bearssl.c54
-rw-r--r--libs/libcurl/src/vtls/gtls.c121
-rw-r--r--libs/libcurl/src/vtls/gtls.h6
-rw-r--r--libs/libcurl/src/vtls/keylog.c9
-rw-r--r--libs/libcurl/src/vtls/mbedtls.c10
-rw-r--r--libs/libcurl/src/vtls/mbedtls_threadlock.c2
-rw-r--r--libs/libcurl/src/vtls/openssl.c526
-rw-r--r--libs/libcurl/src/vtls/openssl.h21
-rw-r--r--libs/libcurl/src/vtls/rustls.c117
-rw-r--r--libs/libcurl/src/vtls/schannel.c174
-rw-r--r--libs/libcurl/src/vtls/schannel_int.h17
-rw-r--r--libs/libcurl/src/vtls/schannel_verify.c64
-rw-r--r--libs/libcurl/src/vtls/sectransp.c40
-rw-r--r--libs/libcurl/src/vtls/vtls.c419
-rw-r--r--libs/libcurl/src/vtls/vtls.h80
-rw-r--r--libs/libcurl/src/vtls/vtls_int.h40
-rw-r--r--libs/libcurl/src/vtls/wolfssl.c37
-rw-r--r--libs/libcurl/src/vtls/x509asn1.c10
-rw-r--r--libs/libcurl/src/warnless.c12
-rw-r--r--libs/libcurl/src/warnless.h21
-rw-r--r--libs/libcurl/src/ws.c8
155 files changed, 8246 insertions, 6519 deletions
diff --git a/libs/libcurl/docs/CHANGES b/libs/libcurl/docs/CHANGES
index 8d56bf8e28..85fa4522fb 100644
--- a/libs/libcurl/docs/CHANGES
+++ b/libs/libcurl/docs/CHANGES
@@ -6,6 +6,3260 @@
Changelog
+Version 8.5.0 (6 Dec 2023)
+
+Daniel Stenberg (6 Dec 2023)
+
+- RELEASE-NOTES: synced
+
+ The curl 8.5.0 release.
+
+Dan Fandrich (5 Dec 2023)
+
+- github/labeler: switch from the beta to labeler v5
+
+ Some keys were renamed and the dot option was made default.
+
+ Closes #12458
+
+Daniel Stenberg (5 Dec 2023)
+
+- DEPRECATE: remove NTLM_WB in June 2024
+
+ Ref: https://curl.se/mail/lib-2023-12/0010.html
+
+ Closes #12451
+
+Jacob Hoffman-Andrews (4 Dec 2023)
+
+- rustls: implement connect_blocking
+
+ Closes #11647
+
+Daniel Stenberg (4 Dec 2023)
+
+- examples/rtsp-options.c: add
+
+ Just a bare bones RTSP example using CURLOPT_RTSP_SESSION_ID and
+ CURLOPT_RTSP_REQUEST set to CURL_RTSPREQ_OPTIONS.
+
+ Closes #12452
+
+Stefan Eissing (4 Dec 2023)
+
+- ngtcp2: ignore errors on unknown streams
+
+ - expecially in is_alive checks on connections, we might
+ see incoming packets on streams already forgotten and closed,
+ leading to errors reported by nghttp3. Ignore those.
+
+ Closes #12449
+
+Daniel Stenberg (4 Dec 2023)
+
+- docs: make all examples in all libcurl man pages compile
+
+ Closes #12448
+
+- checksrc.pl: support #line instructions
+
+ makes it identify the correct source file and line
+
+- GHA/man-examples: verify libcurl man page examples
+
+- verify-examples.pl: verify that all man page examples compile clean
+
+- RELEASE-NOTES: synced
+
+Graham Campbell (2 Dec 2023)
+
+- http3: bump ngtcp2 and nghttp3 versions
+
+ nghttp3 v1.1.0
+ ngtcp2 v1.1.0
+
+ In docs and CI
+
+ Closes #12446
+
+- CI/quiche: use `3.1.4+quic` consistently in CI workflows
+
+ Closes #12447
+
+Viktor Szakats (2 Dec 2023)
+
+- test1545: disable deprecation warnings
+
+ Fixes:
+ https://ci.appveyor.com/project/curlorg/curl/builds/48631551/job/bhx74e0i66yr
+ p6pk#L1205
+
+ Same with details:
+ https://ci.appveyor.com/project/curlorg/curl/builds/48662893/job/ol8a78q9gmil
+ b6wt#L1263
+ ```
+ tests/libtest/lib1545.c:38:3: error: 'curl_formadd' is deprecated: since 7.56
+ .0. Use curl_mime_init() [-Werror=deprecated-declarations]
+ 38 | curl_formadd(&m_formpost, &lastptr, CURLFORM_COPYNAME, "file",
+ | ^~~~~~~~~~~~
+ [...]
+ ```
+
+ Follow-up to 07a3cd83e0456ca17dfd8c3104af7cf45b7a1ff5 #12421
+
+ Fixes #12445
+ Closes #12444
+
+Daniel Stenberg (2 Dec 2023)
+
+- INSTALL: update list of ports and CPU archs
+
+- symbols-in-versions: the CLOSEPOLICY options are deprecated
+
+ The were used with the CURLOPT_CLOSEPOLICY option, which *never* worked.
+
+z2_ (1 Dec 2023)
+
+- build: fix builds that disable protocols but not digest auth
+
+ - Build base64 functions if digest auth is not disabled.
+
+ Prior to this change if some protocols were disabled but not digest auth
+ then a build error would occur due to missing base64 functions.
+
+ Fixes https://github.com/curl/curl/issues/12440
+ Closes https://github.com/curl/curl/pull/12442
+
+Michał Antoniak (1 Dec 2023)
+
+- connect: reduce number of transportation providers
+
+ Use only the ones necessary - the ones that are built-in. Saves a few
+ bytes in the resulting code.
+
+ Closes #12438
+
+David Benjamin (1 Dec 2023)
+
+- vtls: consistently use typedef names for OpenSSL structs
+
+ The foo_st names don't appear in OpenSSL public API documentation. The
+ FOO typedefs are more common. This header was already referencing
+ SSL_CTX via <openssl/ssl.h>. There is a comment about avoiding
+ <openssl/x509v3.h>, but OpenSSL actually declares all the typedefs in
+ <openssl/ossl_typ.h>, which is already included by <openssl/ssl.h> (and
+ every other OpenSSL header), so just use that. Though I've included it
+ just to be explicit.
+
+ (I'm also fairly sure including <openssl/ssl.h> already triggers the
+ Schannel conflicts anyway. The comment was probably just out of date.)
+
+ Closes #12439
+
+Lau (1 Dec 2023)
+
+- libcurl-security.3: fix typo
+
+ Fixed minimal typo.
+
+ Closes #12437
+
+Stefan Eissing (1 Dec 2023)
+
+- ngtcp2: fix races in stream handling
+
+ - fix cases where ngtcp2 invokes callbacks on streams that
+ nghttp3 has already forgotten. Ignore the NGHTTP3_ERR_STREAM_NOT_FOUND
+ in these cases as it is normal behaviour.
+
+ Closes #12435
+
+Emanuele Torre (1 Dec 2023)
+
+- tool_writeout_json: fix JSON encoding of non-ascii bytes
+
+ char variables if unspecified can be either signed or unsigned depending
+ on the platform according to the C standard; in most platforms, they are
+ signed.
+
+ This meant that the *i<32 waas always true for bytes with the top bit
+ set. So they were always getting encoded as \uXXXX, and then since they
+ were also signed negative, they were getting extended with 1s causing
+ '\xe2' to be expanded to \uffffffe2, for example:
+
+ $ curl --variable 'v=“' --expand-write-out '{{v:json}}\n' file:///dev/nul
+ l
+ \uffffffe2\uffffff80\uffffff9c
+
+ I fixed this bug by making the code use explicitly unsigned char*
+ variables instead of char* variables.
+
+ Test 268 verifies
+
+ Reported-by: iconoclasthero
+ Closes #12434
+
+Stefan Eissing (1 Dec 2023)
+
+- cf-socket: TCP trace output local address used in connect
+
+ Closes #12427
+
+Jay Satiro (1 Dec 2023)
+
+- CURLINFO_PRETRANSFER_TIME_T.3: fix time explanation
+
+ - Change CURLINFO_PRETRANSFER_TIME_T explanation to say that it
+ includes protocol-specific instructions that trigger a transfer.
+
+ Prior to this change it explicitly said that it did not include those
+ instructions in the time, but that is incorrect.
+
+ The change is a copy of the fixed explanation already in
+ CURLINFO_PRETRANSFER_TIME, fixed by ec8dcd7b.
+
+ Reported-by: eeverettrbx@users.noreply.github.com
+
+ Fixes https://github.com/curl/curl/issues/12431
+ Closes https://github.com/curl/curl/pull/12432
+
+Daniel Stenberg (30 Nov 2023)
+
+- multi: during ratelimit multi_getsock should return no sockets
+
+ ... as there is nothing to wait for then, it just waits. Otherwise, this
+ causes much more CPU work and updates than necessary during ratelimit
+ periods.
+
+ Ref: https://curl.se/mail/lib-2023-11/0056.html
+ Closes #12430
+
+Dmitry Karpov (30 Nov 2023)
+
+- transfer: abort pause send when connection is marked for closing
+
+ This handles cases of some bi-directional "upgrade" scenarios
+ (i.e. WebSockets) where sending is paused until some "upgrade" handshake
+ is completed, but server rejects the handshake and closes the
+ connection.
+
+ Closes #12428
+
+Daniel Stenberg (28 Nov 2023)
+
+- RELEASE-NOTES: synced
+
+- openssl: when a session-ID is reused, skip OCSP stapling
+
+ Fixes #12399
+ Reported-by: Alexey Larikov
+ Closes #12418
+
+- test1545: test doing curl_formadd twice with missing file
+
+ Reproduces #12410
+ Verifies the fix
+ Closes #12421
+
+- Curl_http_body: cleanup properly when Curl_getformdata errors
+
+ Reported-by: yushicheng7788 on github
+ Based-on-work-by: yushicheng7788 on github
+ Fixes #12410
+ Closes #12421
+
+- test1477: verify that libcurl-errors.3 and public headers are synced
+
+ The script errorcodes.pl extracts all error codes from all headers and
+ checks that they are all documented, then checks that all documented
+ error codes are also specified in a header file.
+
+ Closes #12424
+
+- libcurl-errors.3: sync with current public headers
+
+ Closes #12424
+
+Stefan Eissing (28 Nov 2023)
+
+- test459: fix for parallel runs
+
+ - change warniing message to work better with varying filename
+ length.
+ - adapt test output check to new formatting
+
+ Follow-up to 97ccc4479f77ba3191c6
+ Closes #12423
+
+Daniel Stenberg (27 Nov 2023)
+
+- tool_cb_prg: make the carriage return fit for wide progress bars
+
+ When the progress bar was made max width (256 columns), the fly()
+ function attempted to generate its output buffer too long so that the
+ trailing carriage return would not fit and then the output would show
+ wrongly. The fly function is called when the expected total transfer is
+ unknown, which could be one or more progress calls before the actual
+ progress meter get shown when the expected transfer size is provided.
+
+ This new take also replaces the msnprintf() call with a much simpler
+ memset() for speed.
+
+ Reported-by: Tim Hill
+ Fixes #12407
+ Closes #12415
+
+- tool_parsecfg: make warning output propose double-quoting
+
+ When the config file parser detects a word that *probably* should be
+ quoted, mention double-quotes as a possible remedy.
+
+ Test 459 verifies.
+
+ Proposed-by: Jiehong on github
+ Fixes #12409
+ Closes #12412
+
+Jay Satiro (26 Nov 2023)
+
+- curl.rc: switch out the copyright symbol for plain ASCII
+
+ .. like we already do for libcurl.rc.
+
+ libcurl.rc copyright symbol used to cause a "non-ascii 8-bit codepoint"
+ warning so it was switched to ascii.
+
+ Ref: https://github.com/curl/curl/commit/1ca62bb5#commitcomment-133474972
+
+ Suggested-by: Robert Southee
+
+ Closes https://github.com/curl/curl/pull/12403
+
+Daniel Stenberg (26 Nov 2023)
+
+- conncache: use the closure handle when disconnecting surplus connections
+
+ Use the closure handle for disconnecting connection cache entries so
+ that anything that happens during the disconnect is not stored and
+ associated with the 'data' handle which already just finished a transfer
+ and it is important that details from the unrelated disconnect does not
+ taint meta-data in the data handle.
+
+ Like storing the response code.
+
+ This also adjust test 1506. Unfortunately it also removes a key part of
+ the test that verifies that a connection is closed since when this
+ output vanishes (because the closure handle is used), we don't know
+ exactly that the connection actually gets closed in this test...
+
+ Reported-by: ohyeaah on github
+ Fixes #12367
+ Closes #12405
+
+- RELEASE-NOTES: synced
+
+Stefan Eissing (24 Nov 2023)
+
+- quic: make eyeballers connect retries stop at weird replies
+
+ - when a connect immediately goes into DRAINING state, do
+ not attempt retries in the QUIC connection filter. Instead,
+ return CURLE_WEIRD_SERVER_REPLY
+ - When eyeballing, interpret CURLE_WEIRD_SERVER_REPLY as an
+ inconclusive answer. When all addresses have been attempted,
+ rewind the address list once on an inconclusive answer.
+ - refs #11832 where connects were retried indefinitely until
+ the overall timeout fired
+
+ Closes #12400
+
+Daniel Stenberg (24 Nov 2023)
+
+- CI: verify libcurl function SYNPOSIS sections
+
+ With the .github/scripits/verify-synopsis.pl script
+
+ Closes #12402
+
+- docs/libcurl: SYNSOPSIS cleanup
+
+ - use the correct include file
+ - make sure they are declared as in the header file
+ - fix minor nroff syntax mistakes (missing .fi)
+
+ These are verified by verify-synopsis.pl, which extracts the SYNPOSIS
+ code and runs it through gcc.
+
+ Closes #12402
+
+- sendf: fix comment typo
+
+- fopen: allocate the dir after fopen
+
+ Move the allocation of the directory name down to after the fopen() call
+ to allow that shortcut code path to avoid a superfluous malloc+free
+ cycle.
+
+ Follow-up to 73b65e94f35311
+
+ Closes #12398
+
+Stefan Eissing (24 Nov 2023)
+
+- transfer: cleanup done+excess handling
+
+ - add `SingleRequest->download_done` as indicator that
+ all download bytes have been received
+ - remove `stop_reading` bool from readwrite functions
+ - move excess body handling into client download writer
+
+ Closes #12371
+
+Daniel Stenberg (23 Nov 2023)
+
+- fopen: create new file using old file's mode
+
+ Because the function renames the temp file to the target name as a last
+ step, if the file was previously owned by a different user, not ORing
+ the old mode could otherwise end up creating a file that was no longer
+ readable by the original owner after save.
+
+ Reported-by: Loïc Yhuel
+ Fixes #12299
+ Closes #12395
+
+- test1476: require proxy
+
+ Follow-up from 323df4261c3542
+
+ Closes #12394
+
+- fopen: create short(er) temporary file name
+
+ Only using random letters in the name plus a ".tmp" extension. Not by
+ appending characters to the final file name.
+
+ Reported-by: Maksymilian Arciemowicz
+
+ Closes #12388
+
+Stefan Eissing (23 Nov 2023)
+
+- tests: git ignore generated second-hsts.txt file
+
+ File is generated in test lib1900
+
+ Follow-up to 7cb03229d9e9c5
+
+ Closes #12393
+
+Viktor Szakats (23 Nov 2023)
+
+- openssl: enable `infof_certstack` for 1.1 and LibreSSL 3.6
+
+ Lower the barrier to enable `infof_certstack()` from OpenSSL 3 to
+ OpenSSL 1.1.x, and LibreSSL 3.6 or upper.
+
+ With the caveat, that "group name" and "type name" are missing from
+ the log output with these TLS backends.
+
+ Follow-up to b6e6d4ff8f253c8b8055bab9d4d6a10f9be109f3 #12030
+
+ Reviewed-by: Daniel Stenberg
+ Closes #12385
+
+Daniel Stenberg (23 Nov 2023)
+
+- urldata: fix typo in comment
+
+- CI: codespell
+
+ The list of words to ignore is in the file
+ .github/scripts/codespell-ignore.txt
+
+ Closes #12390
+
+- lib: fix comment typos
+
+ Five separate ones, found by codespell
+
+ Closes #12390
+
+- test1476: verify cookie PSL mixed case
+
+- cookie: lowercase the domain names before PSL checks
+
+ Reported-by: Harry Sintonen
+
+ Closes #12387
+
+Viktor Szakats (23 Nov 2023)
+
+- openssl: fix building with v3 `no-deprecated` + add CI test
+
+ - build quictls with `no-deprecated` in CI to have test coverage for
+ this OpenSSL 3 configuration.
+
+ - don't call `OpenSSL_add_all_algorithms()`, `OpenSSL_add_all_digests()`.
+ The caller code is meant for OpenSSL 3, while these two functions were
+ only necessary before OpenSSL 1.1.0. They are missing from OpenSSL 3
+ if built with option `no-deprecated`, causing build errors:
+ ```
+ vtls/openssl.c:4097:3: error: call to undeclared function 'OpenSSL_add_all_
+ algorithms'; ISO C99 and later do not support implicit function declaration
+ s [-Wimplicit-function-declaration]
+ vtls/openssl.c:4098:3: error: call to undeclared function 'OpenSSL_add_all_
+ digests'; ISO C99 and later do not support implicit function declarations [
+ -Wimplicit-function-declaration]
+ ```
+ Ref: https://ci.appveyor.com/project/curlorg/curl-for-win/builds/48587418?f
+ ullLog=true#L7667
+
+ Regression from b6e6d4ff8f253c8b8055bab9d4d6a10f9be109f3 #12030
+ Bug: https://github.com/curl/curl/issues/12380#issuecomment-1822944669
+ Reviewed-by: Alex Bozarth
+
+ - vquic/curl_ngtcp2: fix using `SSL_get_peer_certificate` with
+ `no-deprecated` quictls 3 builds.
+ Do it by moving an existing solution for this from `vtls/openssl.c`
+ to `vtls/openssl.h` and adjusting caller code.
+ ```
+ vquic/curl_ngtcp2.c:1950:19: error: implicit declaration of function 'SSL_g
+ et_peer_certificate'; did you mean 'SSL_get1_peer_certificate'? [-Wimplicit
+ -function-declaration]
+ ```
+ Ref: https://github.com/curl/curl/actions/runs/6960723097/job/18940818625#s
+ tep:24:1178
+
+ - curl_ntlm_core: fix `-Wunused-parameter`, `-Wunused-variable` and
+ `-Wunused-function` when trying to build curl with NTLM enabled but
+ without the necessary TLS backend (with DES) support.
+
+ Closes #12384
+
+- curl.h: delete Symbian OS references
+
+ curl deprecated Symbian OS in 3d64031fa7a80ac4ae3fd09a5939196268b92f81
+ via #5989. Delete references to it from public headers, because there
+ is no fresh release to use those headers with.
+
+ Reviewed-by: Dan Fandrich
+ Reviewed-by: Jay Satiro
+ Closes #12378
+
+- windows: use built-in `_WIN32` macro to detect Windows
+
+ Windows compilers define `_WIN32` automatically. Windows SDK headers
+ or build env defines `WIN32`, or we have to take care of it. The
+ agreement seems to be that `_WIN32` is the preferred practice here.
+ Make the source code rely on that to detect we're building for Windows.
+
+ Public `curl.h` was using `WIN32`, `__WIN32__` and `CURL_WIN32` for
+ Windows detection, next to the official `_WIN32`. After this patch it
+ only uses `_WIN32` for this. Also, make it stop defining `CURL_WIN32`.
+
+ There is a slight chance these break compatibility with Windows
+ compilers that fail to define `_WIN32`. I'm not aware of any obsolete
+ or modern compiler affected, but in case there is one, one possible
+ solution is to define this macro manually.
+
+ grepping for `WIN32` remains useful to discover Windows-specific code.
+
+ Also:
+
+ - extend `checksrc` to ensure we're not using `WIN32` anymore.
+
+ - apply minor formatting here and there.
+
+ - delete unnecessary checks for `!MSDOS` when `_WIN32` is present.
+
+ Co-authored-by: Jay Satiro
+ Reviewed-by: Daniel Stenberg
+
+ Closes #12376
+
+Stefan Eissing (22 Nov 2023)
+
+- url: ConnectionExists revisited
+
+ - have common pattern of `if not match, continue`
+ - revert pages long if()s to return early
+ - move dead connection check to later since it may
+ be relatively expensive
+ - check multiuse also when NOT building with NGHTTP2
+ - for MULTIUSE bundles, verify that the inspected
+ connection indeed supports multiplexing when in use
+ (bundles may contain a mix of connection, afaict)
+
+ Closes #12373
+
+Daniel Stenberg (22 Nov 2023)
+
+- CURLMOPT_MAX_CONCURRENT_STREAMS: make sure the set value is within range
+
+ ... or use the default value.
+
+ Also clarify the documentation language somewhat.
+
+ Closes #12382
+
+- urldata: make maxconnects a 32 bit value
+
+ "2^32 idle connections ought to be enough for anybody"
+
+ Closes #12375
+
+- FEATURES: update the URL phrasing
+
+ The URL is length limited since a while back so "no limit" simply is not
+ true anymore. Mention the URL RFC standard used instead.
+
+ Closes #12383
+
+- wolfssh: remove redundant static prototypes
+
+ vssh/wolfssh.c:346:18: error: redundant redeclaration of ‘wscp_recv’ [-We
+ rror=redundant-decls]
+
+ Closes #12381
+
+- setopt: remove superfluous use of ternary expressions
+
+ Closes #12374
+
+- mime: store "form escape" as a single bit
+
+ Closes #12374
+
+- setopt: check CURLOPT_TFTP_BLKSIZE range on set
+
+ ... instead of later when the transfer is about to happen.
+
+ Closes #12374
+
+Viktor Szakats (21 Nov 2023)
+
+- build: add more picky warnings and fix them
+
+ Enable more picky compiler warnings. I've found these options in the
+ nghttp3 project when implementing the CMake quick picky warning
+ functionality for it [1].
+
+ `-Wunused-macros` was too noisy to keep around, but fixed a few issues
+ it revealed while testing.
+
+ - autotools: reflect the more precisely-versioned clang warnings.
+ Follow-up to 033f8e2a08eb1d3102f08c4d8c8e85470f8b460e #12324
+ - autotools: sync between clang and gcc the way we set `no-multichar`.
+ - autotools: avoid setting `-Wstrict-aliasing=3` twice.
+ - autotools: disable `-Wmissing-noreturn` for MSYS gcc targets [2].
+ It triggers in libtool-generated stub code.
+
+ - lib/timeval: delete a redundant `!MSDOS` guard from a `WIN32` branch.
+
+ - lib/curl_setup.h: delete duplicate declaration for `fileno`.
+ Added in initial commit ae1912cb0d494b48d514d937826c9fe83ec96c4d
+ (1999-12-29). This suggests this may not be needed anymore, but if
+ it does, we may restore this for those specific (non-Windows) systems.
+ - lib: delete unused macro `FTP_BUFFER_ALLOCSIZE` since
+ c1d6fe2aaa5a26e49a69a4f2495b3cc7a24d9394.
+ - lib: delete unused macro `isxdigit_ascii` since
+ f65f750742068f579f4ee6d8539ed9d5f0afcb85.
+ - lib/mqtt: delete unused macro `MQTT_HEADER_LEN`.
+ - lib/multi: delete unused macro `SH_READ`/`SH_WRITE`.
+ - lib/hostip: add `noreturn` function attribute via new `CURL_NORETURN`
+ macro.
+ - lib/mprintf: delete duplicate declaration for `Curl_dyn_vprintf`.
+ - lib/rand: fix `-Wunreachable-code` and related fallouts [3].
+ - lib/setopt: fix `-Wunreachable-code-break`.
+ - lib/system_win32 and lib/timeval: fix double declarations for
+ `Curl_freq` and `Curl_isVistaOrGreater` in CMake UNITY mode [4].
+ - lib/warnless: fix double declarations in CMake UNITY mode [5].
+ This was due to force-disabling the header guard of `warnless.h` to
+ to reapply it to source code coming after `warnless.c` in UNITY
+ builds. This reapplied declarations too, causing the warnings.
+ Solved by adding a header guard for the lines that actually need
+ to be reapplied.
+ - lib/vauth/digest: fix `-Wunreachable-code-break` [6].
+ - lib/vssh/libssh2: fix `-Wunreachable-code-break` and delete redundant
+ block.
+ - lib/vtls/sectransp: fix `-Wunreachable-code-break` [7].
+ - lib/vtls/sectransp: suppress `-Wunreachable-code`.
+ Detected in `else` branches of dynamic feature checks, with results
+ known at compile-time, e.g.
+ ```c
+ if(SecCertificateCopySubjectSummary) /* -> true */
+ ```
+ Likely fixable as a separate micro-project, but given SecureTransport
+ is deprecated anyway, let's just silence these locally.
+ - src/tool_help: delete duplicate declaration for `helptext`.
+ - src/tool_xattr: fix `-Wunreachable-code`.
+ - tests: delete duplicate declaration for `unitfail` [8].
+ - tests: delete duplicate declaration for `strncasecompare`.
+ - tests/libtest: delete duplicate declaration for `gethostname`.
+ Originally added in 687df5c8c39c370a59999b9afc0917d808d978b7
+ (2010-08-02).
+ Got complicated later: c49e9683b85ba9d12cbb6eebc4ab2c8dba68fbdc
+ If there are still systems around with warnings, we may restore the
+ prototype, but limited for those systems.
+ - tests/lib2305: delete duplicate declaration for
+ `libtest_debug_config`.
+ - tests/h2-download: fix `-Wunreachable-code-break`.
+
+ [1] https://github.com/ngtcp2/nghttp3/blob/a70edb08e954d690e8fb2c1df999b5a056
+ f8bf9f/cmake/PickyWarningsC.cmake
+ [2] https://ci.appveyor.com/project/curlorg/curl/builds/48553586/job/3qkgjaui
+ qla5fj45?fullLog=true#L1675
+ [3] https://github.com/curl/curl/actions/runs/6880886309/job/18716044703?pr=1
+ 2331#step:7:72
+ https://github.com/curl/curl/actions/runs/6883016087/job/18722707368?pr=1
+ 2331#step:7:109
+ [4] https://ci.appveyor.com/project/curlorg/curl/builds/48555101/job/9g15qkrr
+ iklpf1ut#L204
+ [5] https://ci.appveyor.com/project/curlorg/curl/builds/48555101/job/9g15qkrr
+ iklpf1ut#L218
+ [6] https://github.com/curl/curl/actions/runs/6880886309/job/18716042927?pr=1
+ 2331#step:7:290
+ [7] https://github.com/curl/curl/actions/runs/6891484996/job/18746659406?pr=1
+ 2331#step:9:1193
+ [8] https://github.com/curl/curl/actions/runs/6882803986/job/18722082562?pr=1
+ 2331#step:33:1870
+
+ Closes #12331
+
+Daniel Stenberg (21 Nov 2023)
+
+- transfer: avoid unreachable expression
+
+ If curl_off_t and size_t have the same size (which is common on modern
+ 64 bit systems), a condition cannot occur which Coverity pointed
+ out. Avoid the warning by having the code conditionally only used if
+ curl_off_t actually is larger.
+
+ Follow-up to 1cd2f0072fa482e25baa2
+
+ Closes #12370
+
+Stefan Eissing (21 Nov 2023)
+
+- transfer: readwrite improvements
+
+ - changed header/chunk/handler->readwrite prototypes to accept `buf`,
+ `blen` and a `pconsumed` pointer. They now get the buffer to work on
+ and report back how many bytes they consumed
+ - eliminated `k->str` in SingleRequest
+ - improved excess data handling to properly calculate with any body data
+ left in the headerb buffer
+ - eliminated `k->badheader` enum to only be a bool
+
+ Closes #12283
+
+Daniel Stenberg (21 Nov 2023)
+
+- RELEASE-NOTES: synced
+
+Jiří Hruška (21 Nov 2023)
+
+- transfer: avoid calling the read callback again after EOF
+
+ Regression since 7f43f3dc5994d01b12 (7.84.0)
+
+ Bug: https://curl.se/mail/lib-2023-11/0017.html
+
+ Closes #12363
+
+Daniel Stenberg (21 Nov 2023)
+
+- doh: provide better return code for responses w/o addresses
+
+ Previously it was wrongly returning CURLE_OUT_OF_MEMORY when the
+ response did not contain any addresses. Now it more accurately returns
+ CURLE_COULDNT_RESOLVE_HOST.
+
+ Reported-by: lRoccoon on github
+
+ Fixes #12365
+ Closes #12366
+
+Stefan Eissing (21 Nov 2023)
+
+- HTTP/2, HTTP/3: handle detach of onoing transfers
+
+ - refs #12356 where a UAF is reported when closing a connection
+ with a stream whose easy handle was cleaned up already
+ - handle DETACH events same as DONE events in h2/h3 filters
+
+ Fixes #12356
+ Reported-by: Paweł Wegner
+ Closes #12364
+
+Viktor Szakats (20 Nov 2023)
+
+- autotools: stop setting `-std=gnu89` with `--enable-warnings`
+
+ Do not alter the C standard when building with `--enable-warnings` when
+ building with gcc.
+
+ On one hand this alters warning results compared to a default build.
+ On the other, it may produce different binaries, which is unexpected.
+
+ Also fix new warnings that appeared after removing `-std=gnu89`:
+
+ - include: fix public curl headers to use the correct printf mask for
+ `CURL_FORMAT_CURL_OFF_T` and `CURL_FORMAT_CURL_OFF_TU` with mingw-w64
+ and Visual Studio 2013 and newer. This fixes the printf mask warnings
+ in examples and tests. E.g. [1]
+
+ - conncache: fix printf format string [2].
+
+ - http2: fix potential null pointer dereference [3].
+ (seen on Slackware with gcc 11.)
+
+ - libssh: fix printf format string in SFTP code [4].
+ Also make MSVC builds compatible with old CRT versions.
+
+ - libssh2: fix printf format string in SFTP code for MSVC.
+ Applying the same fix as for libssh above.
+
+ - unit1395: fix `argument is null` and related issues [5]:
+ - stop calling `strcmp()` with NULL to avoid undefined behaviour.
+ - fix checking results if some of them were NULL.
+ - do not pass NULL to printf `%s`.
+
+ - ci: keep a build job with `-std=gnu89` to continue testing for
+ C89-compliance. We can apply this to other gcc jobs as needed.
+ Ref: b23ce2cee7329bbf425f18b49973b7a5f23dfcb4 (2022-09-23) #9542
+
+ [1] https://dev.azure.com/daniel0244/curl/_build/results?buildId=18581&view=l
+ ogs&jobId=ccf9cc6d-2ef1-5cf2-2c09-30f0c14f923b
+ [2] https://github.com/curl/curl/actions/runs/6896854263/job/18763831142?pr=1
+ 2346#step:6:67
+ [3] https://github.com/curl/curl/actions/runs/6896854253/job/18763839238?pr=1
+ 2346#step:30:214
+ [4] https://github.com/curl/curl/actions/runs/6896854253/job/18763838007?pr=1
+ 2346#step:29:895
+ [5] https://github.com/curl/curl/actions/runs/6896854253/job/18763836775?pr=1
+ 2346#step:33:1689
+
+ Closes #12346
+
+- autotools: fix/improve gcc and Apple clang version detection
+
+ - Before this patch we expected `n.n` `-dumpversion` output, but Ubuntu
+ may return `n-win32` (also with `-dumpfullversion`). Causing these
+ errors and failing to enable picky warnings:
+ ```
+ ../configure: line 23845: test: : integer expression expected
+ ```
+ Ref: https://github.com/libssh2/libssh2/actions/runs/6263453828/job/1700789
+ 3718#step:5:143
+
+ Fix that by stripping any dash-suffix and handling a dotless (major-only)
+ version number by assuming `.0` in that case.
+
+ `9.3-posix`, `9.3-win32`, `6`, `9.3.0`, `11`, `11.2`, `11.2.0`
+ Ref: https://github.com/mamedev/mame/pull/9767
+
+ - fix Apple clang version detection for releases between
+ 'Apple LLVM version 7.3.0' and 'Apple LLVM version 10.0.1' where the
+ version was under-detected as 3.7 llvm/clang equivalent.
+
+ - fix Apple clang version detection for 'Apple clang version 11.0.0'
+ and newer where the Apple clang version was detected, instead of its
+ llvm/clang equivalent.
+
+ - display detected clang/gcc/icc compiler version.
+
+ Via libssh2:
+ - https://github.com/libssh2/libssh2/commit/00a3b88c51cdb407fbbb347a2e38c5c7d
+ 89875ad
+ https://github.com/libssh2/libssh2/pull/1187
+ - https://github.com/libssh2/libssh2/commit/89ccc83c7da73e7ca3a112e3500081319
+ 42b592e
+ https://github.com/libssh2/libssh2/pull/1232
+
+ Closes #12362
+
+- autotools: delete LCC compiler support bits
+
+ Follow-up to fd7ef00f4305a2919e6950def1cf83d0110a4acd #12222
+
+ Closes #12357
+
+- cmake: add test for `DISABLE` options, add `CURL_DISABLE_HEADERS_API`
+
+ - tests: verify CMake `DISABLE` options.
+
+ Make an exception for 2 CMake-only ones, and one more that's
+ using a different naming scheme, also in autotools and source.
+
+ - cmake: add support for `CURL_DISABLE_HEADERS_API`.
+
+ Suggested-by: Daniel Stenberg
+ Ref: https://github.com/curl/curl/pull/12345#pullrequestreview-1736238641
+
+ Closes #12353
+
+Jacob Hoffman-Andrews (20 Nov 2023)
+
+- hyper: temporarily remove HTTP/2 support
+
+ The current design of the Hyper integration requires rebuilding the
+ Hyper clientconn for each request. However, building the clientconn
+ requires resending the HTTP/2 connection preface, which is incorrect
+ from a protocol perspective. That in turn causes servers to send GOAWAY
+ frames, effectively degrading performance to "no connection reuse" in
+ the best case. It may also be triggering some bugs where requests get
+ dropped entirely and reconnects take too long.
+
+ This doesn't rule out HTTP/2 support with Hyper, but it may take a
+ redesign of the Hyper integration in order to make things work.
+
+ Closes #12191
+
+Jay Satiro (20 Nov 2023)
+
+- schannel: fix unused variable warning
+
+ Bug: https://github.com/curl/curl/pull/12349#issuecomment-1818000846
+ Reported-by: Viktor Szakats
+
+ Closes https://github.com/curl/curl/pull/12361
+
+Daniel Stenberg (19 Nov 2023)
+
+- url: find scheme with a "perfect hash"
+
+ Instead of a loop to scan over the potentially 30+ scheme names, this
+ uses a "perfect hash" table. This works fine because the set of schemes
+ is known and cannot change in a build. The hash algorithm and table size
+ is made to only make a single scheme index per table entry.
+
+ The perfect hash is generated by a separate tool (scripts/schemetable.c)
+
+ Closes #12347
+
+- scripts: add schemetable.c
+
+ This tool generates a scheme-matching table.
+
+ It iterates over a number of different initial and shift values in order
+ to find the hash algorithm that needs the smallest possible table.
+
+ The generated hash function, table and table size then needs to be used
+ by the url.c:Curl_getn_scheme_handler() function.
+
+Stefan Eissing (19 Nov 2023)
+
+- vtls/vquic, keep peer name information together
+
+ - add `struct ssl_peer` to keep hostname, dispname and sni
+ for a filter
+ - allocate `sni` for use in VTLS backend
+ - eliminate `Curl_ssl_snihost()` and its use of the download buffer
+ - use ssl_peer in SSL and QUIC filters
+
+ Closes #12349
+
+Viktor Szakats (18 Nov 2023)
+
+- build: always revert `#pragma GCC diagnostic` after use
+
+ Before this patch some source files were overriding gcc warning options,
+ but without restoring them at the end of the file. In CMake UNITY builds
+ these options spilled over to the remainder of the source code,
+ effecitvely disabling them for a larger portion of the codebase than
+ intended.
+
+ `#pragma clang diagnostic` didn't have such issue in the codebase.
+
+ Reviewed-by: Marcel Raad
+ Closes #12352
+
+- tidy-up: casing typos, delete unused Windows version aliases
+
+ - cmake: fix casing of `UnixSockets` to match the rest of the codebase.
+
+ - curl-compilers.m4: fix casing in a comment.
+
+ - setup-win32: delete unused Windows version constant aliases.
+
+ Reviewed-by: Marcel Raad
+ Closes #12351
+
+- keylog: disable if unused
+
+ Fully disable keylog code if there is no TLS or QUIC subsystem using it.
+
+ Closes #12350
+
+- cmake: add `CURL_DISABLE_BINDLOCAL` option
+
+ To match similar autotools option.
+
+ Default is `ON`.
+
+ Reviewed-by: Daniel Stenberg
+ Closes #12345
+
+- url: fix `-Wzero-length-array` with no protocols
+
+ Fixes:
+ ```
+ ./lib/url.c:178:56: warning: use of an empty initializer is a C2x extension [
+ -Wc2x-extensions]
+ 178 | static const struct Curl_handler * const protocols[] = {
+ | ^
+ ./lib/url.c:178:56: warning: zero size arrays are an extension [-Wzero-length
+ -array]
+ ```
+
+ Closes #12344
+
+- url: fix builds with `CURL_DISABLE_HTTP`
+
+ Fixes:
+ ```
+ ./lib/url.c:456:35: error: no member named 'formp' in 'struct UrlState'
+ 456 | Curl_mime_cleanpart(data->state.formp);
+ | ~~~~~~~~~~~ ^
+ ```
+
+ Regression from 74b87a8af13a155c659227f5acfa78243a8b2aa6 #11682
+
+ Closes #12343
+
+- http: fix `-Wunused-parameter` with no auth and no proxy
+
+ ```
+ lib/http.c:734:26: warning: unused parameter 'proxy' [-Wunused-parameter]
+ bool proxy)
+ ^
+ ```
+
+ Reviewed-by: Marcel Raad
+ Closes #12338
+
+Daniel Stenberg (16 Nov 2023)
+
+- TODO: Some TLS options are not offered for HTTPS proxies
+
+ Closes #12286
+ Closes #12342
+
+- RELEASE-NOTES: synced
+
+- duphandle: make dupset() not return with pointers to old alloced data
+
+ As the blob pointers are to be duplicated, the function must not return
+ mid-function with lingering pointers to the old handle's allocated data,
+ as that would lead to double-free in OOM situations.
+
+ Make sure to clear all destination pointers first to avoid this risk.
+
+ Closes #12337
+
+Viktor Szakats (16 Nov 2023)
+
+- http: fix `-Wunused-variable` compiler warning
+
+ Fix compiler warnings in builds with disabled auths, NTLM and SPNEGO.
+
+ E.g. with `CURL_DISABLE_BASIC_AUTH` + `CURL_DISABLE_BEARER_AUTH` +
+ `CURL_DISABLE_DIGEST_AUTH` + `CURL_DISABLE_NEGOTIATE_AUTH` +
+ `CURL_DISABLE_NTLM` on non-Windows.
+
+ ```
+ ./curl/lib/http.c:737:12: warning: unused variable 'result' [-Wunused-variabl
+ e]
+ CURLcode result = CURLE_OK;
+ ^
+ ./curl/lib/http.c:995:18: warning: variable 'availp' set but not used [-Wunus
+ ed-but-set-variable]
+ unsigned long *availp;
+ ^
+ ./curl/lib/http.c:996:16: warning: variable 'authp' set but not used [-Wunuse
+ d-but-set-variable]
+ struct auth *authp;
+ ^
+ ```
+
+ Regression from e92edfbef64448ef461117769881f3ed776dec4e #11490
+
+ Fixes #12228
+ Closes #12335
+
+Jay Satiro (16 Nov 2023)
+
+- tool: support bold headers in Windows
+
+ - If virtual terminal processing is enabled in Windows then use ANSI
+ escape codes Esc[1m and Esc[22m to turn bold on and off.
+
+ Suggested-by: Gisle Vanem
+
+ Ref: https://github.com/curl/curl/discussions/11770
+
+ Closes https://github.com/curl/curl/pull/12321
+
+Viktor Szakats (15 Nov 2023)
+
+- build: fix libssh2 + `CURL_DISABLE_DIGEST_AUTH` + `CURL_DISABLE_AWS`
+
+ Builds with libssh2 + `-DCURL_DISABLE_DIGEST_AUTH=ON` +
+ `-DCURL_DISABLE_AWS=ON` in combination with either Schannel on Windows,
+ or `-DCURL_DISABLE_NTLM=ON` on other operating systems failed while
+ compiling due to a missing HMAC declaration.
+
+ The reason is that HMAC is required by `lib/sha256.c` which publishes
+ `Curl_sha256it()` which is required by `lib/vssh/libssh2.c` when
+ building for libssh2 v1.8.2 (2019-05-25) or older.
+
+ Make sure to compile the HMAC bits for a successful build.
+
+ Both HMAC and `Curl_sha256it()` rely on the same internals, so splitting
+ them into separate sources isn't practical.
+
+ Fixes:
+ ```
+ [...]
+ In file included from ./curl/_x64-win-ucrt-cmake-llvm-bld/lib/CMakeFiles/libc
+ url_object.dir/Unity/unity_0_c.c:310:
+ ./curl/lib/sha256.c:527:42: error: array has incomplete element type 'const s
+ truct HMAC_params'
+ 527 | const struct HMAC_params Curl_HMAC_SHA256[] = {
+ | ^
+ ./curl/lib/curl_sha256.h:34:21: note: forward declaration of 'struct HMAC_par
+ ams'
+ [...]
+ ```
+
+ Regression from e92edfbef64448ef461117769881f3ed776dec4e #11490
+
+ Fixes #12273
+ Closes #12332
+
+Daniel Stenberg (15 Nov 2023)
+
+- duphandle: also free 'outcurl->cookies' in error path
+
+ Fixes memory-leak when OOM mid-function
+
+ Use plain free instead of safefree, since the entire struct is
+ freed below.
+
+ Remove some free calls that is already freed in Curl_freeset()
+
+ Closes #12329
+
+Viktor Szakats (15 Nov 2023)
+
+- config-win32: set `HAVE_SNPRINTF` for mingw-w64
+
+ It's available in all mingw-w64 releases. We already pre-fill this
+ detection in CMake.
+
+ Closes #12325
+
+- sasl: fix `-Wunused-function` compiler warning
+
+ In builds with disabled auths.
+
+ ```
+ lib/curl_sasl.c:266:17: warning: unused function 'get_server_message' [-Wunus
+ ed-function]
+ static CURLcode get_server_message(struct SASL *sasl, struct Curl_easy *data,
+ ^
+ 1 warning generated.
+ ```
+ Ref: https://github.com/curl/trurl/actions/runs/6871732122/job/18689066151#st
+ ep:3:3822
+
+ Reviewed-by: Daniel Stenberg
+ Closes #12326
+
+- build: picky warning updates
+
+ - cmake: sync some picky gcc warnings with autotools.
+ - cmake, autotools: add `-Wold-style-definition` for clang too.
+ - cmake: more precise version info for old clang options.
+ - cmake: use `IN LISTS` syntax in `foreach()`.
+
+ Reviewed-by: Daniel Stenberg
+ Reviewed-by: Marcel Raad
+ Closes #12324
+
+Daniel Stenberg (15 Nov 2023)
+
+- urldata: move cookielist from UserDefined to UrlState
+
+ 1. Because the value is not strictly set with a setopt option.
+
+ 2. Because otherwise when duping a handle when all the set.* fields are
+ first copied and an error happens (think out of memory mid-function),
+ the function would easily free the list *before* it was deep-copied,
+ which could lead to a double-free.
+
+ Closes #12323
+
+Viktor Szakats (14 Nov 2023)
+
+- autotools: avoid passing `LDFLAGS` twice to libcurl
+
+ autotools passes `LDFLAGS` automatically linker commands. curl's
+ `lib/Makefile.am` customizes libcurl linker flags. In that
+ customization, it added `LDFLAGS` to the custom flags. This resulted in
+ passing `LDFLAGS` _twice_ to the `libtool` command.
+
+ Most of the time this is benign, but some `LDFLAGS` options can break
+ the build when passed twice. One such example is passing `.o` files,
+ e.g. `crt*.o` files necessary when customizing the C runtime, e.g. for
+ MUSL builds.
+
+ Passing them twice resulted in duplicate symbol errors:
+ ```
+ libtool: link: clang-15 --target=aarch64-unknown-linux-musl [...] /usr/lib/a
+ arch64-linux-musl/crt1.o [...] /usr/lib/aarch64-linux-musl/crt1.o [...]
+ ld.lld-15: error: duplicate symbol: _start
+ >>> defined at crt1.c
+ >>> /usr/lib/aarch64-linux-musl/crt1.o:(.text+0x0)
+ >>> defined at crt1.c
+ >>> /usr/lib/aarch64-linux-musl/crt1.o:(.text+0x0)
+ [...]
+ clang: error: linker command failed with exit code 1 (use -v to see invocatio
+ n)
+ ```
+
+ This behaviour came with commit 1a593191c2769a47b8c3e4d9715ec9f6dddf5e36
+ (2013-07-23) as a fix for bug https://curl.haxx.se/bug/view.cgi?id=1217.
+ The patch was a works-for-me hack that ended up merged in curl:
+ https://sourceforge.net/p/curl/bugs/1217/#06ef
+ With the root cause remaining unclear.
+
+ Perhaps the SUNPro 12 linker was sensitive to `-L` `-l` order, requiring
+ `-L` first? This would be unusual and suggests a bug in either the
+ linker or in `libtool`.
+
+ The curl build does pass the list of detected libs via its own
+ `LIBCURL_LIBS` variable, which ends up before `LDFLAGS` on the `libtool`
+ command line, but it's the job of `libtool` to ensure that even
+ a peculiar linker gets the options in the expected order. Also because
+ autotools passes `LDFLAGS` last, making it hardly possible to pass
+ anything after it.
+
+ Perhaps in the 10 years since this issue, this already got a fix
+ upstream.
+
+ This patch deletes `LDFLAGS` from our customized libcurl options,
+ leaving a single copy of them as passed by autotools automatically.
+
+ Reverts 1a593191c2769a47b8c3e4d9715ec9f6dddf5e36
+ Closes #12310
+
+- autotools: accept linker flags via `CURL_LDFLAGS_{LIB,BIN}`
+
+ To allow passing `LDFLAGS` specific to libcurl (`CURL_LDFLAGS_LIB`) and
+ curl tool (`CURL_LDFLAGS_BIN`).
+
+ This makes it possible to build libcurl and curl with a single
+ invocation with lib- and tool-specific custom linker flags.
+
+ Such flag can be enabling `.map` files, a `.def` file for libcurl DLL,
+ controlling static/shared, incl. requesting a static curl tool (with
+ `-static-libtool-libs`) while building both shared and static libcurl.
+
+ curl-for-win uses the above and some more.
+
+ These options are already supported in `Makefile.mk`. CMake has built-in
+ variables for this.
+
+ Closes #12312
+
+Jay Satiro (14 Nov 2023)
+
+- tool_cb_hdr: add an additional parsing check
+
+ - Don't dereference the past-the-end element when parsing the server's
+ Content-disposition header.
+
+ As 'p' is advanced it can point to the past-the-end element and prior
+ to this change 'p' could be dereferenced in that case.
+
+ Technically the past-the-end element is not out of bounds because dynbuf
+ (which manages the header line) automatically adds a null terminator to
+ every buffer and that is not included in the buffer length passed to
+ the header callback.
+
+ Closes https://github.com/curl/curl/pull/12320
+
+Philip Heiduck (14 Nov 2023)
+
+- .cirrus.yml: freebsd 14
+
+ ensure curl works on latest freebsd version
+
+ Closes #12053
+
+Daniel Stenberg (13 Nov 2023)
+
+- easy: in duphandle, init the cookies for the new handle
+
+ ... not the source handle.
+
+ Closes #12318
+
+- duphandle: use strdup to clone *COPYPOSTFIELDS if size is not set
+
+ Previously it would unconditionally use the size, which is set to -1
+ when strlen is requested.
+
+ Updated test 544 to verify.
+
+ Closes #12317
+
+- RELEASE-NOTES: synced
+
+- curl_easy_duphandle.3: clarify how HSTS and alt-svc are duped
+
+ Closes #12315
+
+- urldata: move hstslist from 'set' to 'state'
+
+ To make it work properly with curl_easy_duphandle(). This, because
+ duphandle duplicates the entire 'UserDefined' struct by plain copy while
+ 'hstslist' is a linked curl_list of file names. This would lead to a
+ double-free when the second of the two involved easy handles were
+ closed.
+
+ Closes #12315
+
+- test1900: verify duphandle with HSTS using multiple files
+
+ Closes #12315
+
+Goro FUJI (13 Nov 2023)
+
+- http: allow longer HTTP/2 request method names
+
+ - Increase the maximum request method name length from 11 to 23.
+
+ For HTTP/1.1 and earlier there's not a specific limit in libcurl for
+ method length except that it is limited by the initial HTTP request
+ limit (DYN_HTTP_REQUEST). Prior to fc2f1e54 HTTP/2 was treated the same
+ and there was no specific limit.
+
+ According to Internet Assigned Numbers Authority (IANA) the longest
+ registered method is UPDATEREDIRECTREF which is 17 characters.
+
+ Also there are unregistered methods used by some companies that are
+ longer than 11 characters.
+
+ The limit was originally added by 61f52a97 but not used until fc2f1e54.
+
+ Ref: https://www.iana.org/assignments/http-methods/http-methods.xhtml
+
+ Closes https://github.com/curl/curl/pull/12311
+
+Jay Satiro (12 Nov 2023)
+
+- CURLOPT_CAINFO_BLOB.3: explain what CURL_BLOB_COPY does
+
+ - Add an explanation of the CURL_BLOB_COPY flag to CURLOPT_CAINFO_BLOB
+ and CURLOPT_PROXY_CAINFO_BLOB docs.
+
+ All the other _BLOB option docs already have the same explanation.
+
+ Closes https://github.com/curl/curl/pull/12277
+
+Viktor Szakats (11 Nov 2023)
+
+- tidy-up: dedupe Windows system libs in cmake
+
+ Reviewed-by: Daniel Stenberg
+ Closes #12307
+
+Junho Choi (11 Nov 2023)
+
+- ci: test with latest quiche release (0.19.0)
+
+ Closes #12180
+
+- quiche: use quiche_conn_peer_transport_params()
+
+ In recent quiche, transport parameter API is separated
+ with quiche_conn_peer_transport_params().
+ (https://github.com/cloudflare/quiche/pull/1575)
+ It breaks with bulding with latest(post 0.18.0) quiche.
+
+ Closes #12180
+
+Daniel Stenberg (11 Nov 2023)
+
+- Makefile: generate the VC 14.20 project files at dist-time
+
+ Follow-up to 28287092cc5a6d6ef8 (#12282)
+
+ Closes #12290
+
+Sam James (11 Nov 2023)
+
+- misc: fix -Walloc-size warnings
+
+ GCC 14 introduces a new -Walloc-size included in -Wextra which gives:
+
+ ```
+ src/tool_operate.c: In function ‘add_per_transfer’:
+ src/tool_operate.c:213:5: warning: allocation of insufficient size ‘1’ fo
+ r type ‘struct per_transfer’ with size ‘480’ [-Walloc-size]
+ 213 | p = calloc(sizeof(struct per_transfer), 1);
+ | ^
+ src/var.c: In function ‘addvariable’:
+ src/var.c:361:5: warning: allocation of insufficient size ‘1’ for type â€
+ ˜struct var’ with size ‘32’ [-Walloc-size]
+ 361 | p = calloc(sizeof(struct var), 1);
+ | ^
+ ```
+
+ The calloc prototype is:
+ ```
+ void *calloc(size_t nmemb, size_t size);
+ ```
+
+ So, just swap the number of members and size arguments to match the
+ prototype, as we're initialising 1 struct of size `sizeof(struct
+ ...)`. GCC then sees we're not doing anything wrong.
+
+ Closes #12292
+
+Mark Gaiser (11 Nov 2023)
+
+- IPFS: bugfixes
+
+ - Fixed endianness bug in gateway file parsing
+ - Use IPFS_PATH in tests where IPFS_DATA was used
+ - Fixed typos from traling -> trailing
+ - Fixed broken link in IPFS.md
+
+ Follow-up to 859e88f6533f9e
+
+ Reported-by: Michael Kaufmann
+ Bug: https://github.com/curl/curl/pull/12152#issuecomment-1798214137
+ Closes #12305
+
+Daniel Stenberg (11 Nov 2023)
+
+- VULN-DISCLOSURE-POLIC: remove broken link to hackerone
+
+ It should ideally soon not be done from hackerone anyway
+
+ Closes #12308
+
+Andrew Kurushin (11 Nov 2023)
+
+- schannel: add CA cache support for files and memory blobs
+
+ - Support CA bundle and blob caching.
+
+ Cache timeout is 24 hours or can be set via CURLOPT_CA_CACHE_TIMEOUT.
+
+ Closes https://github.com/curl/curl/pull/12261
+
+Daniel Stenberg (10 Nov 2023)
+
+- RELEASE-NOTES: synced
+
+Charlie C (10 Nov 2023)
+
+- cmake: option to disable install & drop `curlu` target when unused
+
+ This patch makes the following changes:
+ - adds the option `CURL_DISABLE_INSTALL` - to disable 'install' targets.
+ - Removes the target `curlu` when the option `BUILD_TESTING` is set to
+ `OFF` - to prevent it from being loaded in Visual Studio.
+
+ Closes #12287
+
+Kai Pastor (10 Nov 2023)
+
+- cmake: fix multiple include of CURL package
+
+ Fixes errors on second `find_package(CURL)`. This is a frequent case
+ with transitive dependencies:
+ ```
+ CMake Error at ...:
+ add_library cannot create ALIAS target "CURL::libcurl" because another
+ target with the same name already exists.
+ ```
+
+ Test to reproduce:
+ ```cmake
+ cmake_minimum_required(VERSION 3.27) # must be 3.18 or higher
+
+ project(curl)
+
+ set(CURL_DIR "example/lib/cmake/CURL/")
+ find_package(CURL CONFIG REQUIRED)
+ find_package(CURL CONFIG REQUIRED) # fails
+
+ add_executable(main main.c)
+ target_link_libraries(main CURL::libcurl)
+ ```
+
+ Ref: https://cmake.org/cmake/help/latest/release/3.18.html#other-changes
+ Ref: https://cmake.org/cmake/help/v3.18/policy/CMP0107.html
+ Ref: #12300
+ Assisted-by: Harry Mallon
+ Closes #11913
+
+Viktor Szakats (8 Nov 2023)
+
+- tidy-up: use `OPENSSL_VERSION_NUMBER`
+
+ Uniformly use `OPENSSL_VERSION_NUMBER` to check for OpenSSL version.
+ Before this patch some places used `OPENSSL_VERSION_MAJOR`.
+
+ Also fix `lib/md4.c`, which included `opensslconf.h`, but that doesn't
+ define any version number in these implementations: BoringSSL, AWS-LC,
+ LibreSSL, wolfSSL. (Only in mainline OpenSSL/quictls). Switch that to
+ `opensslv.h`. This wasn't causing a deeper problem because the code is
+ looking for v3, which is only provided by OpenSSL/quictls as of now.
+
+ According to https://github.com/openssl/openssl/issues/17517, the macro
+ `OPENSSL_VERSION_NUMBER` is safe to use and not deprecated.
+
+ Reviewed-by: Marcel Raad
+ Closes #12298
+
+Daniel Stenberg (8 Nov 2023)
+
+- resolve.d: drop a multi use-sentence
+
+ Since the `multi:` keyword adds that message.
+
+ Reported-by: ç©ä¸¹å°¼ Dan Jacobson
+ Fixes https://github.com/curl/curl/discussions/12294
+ Closes #12295
+
+- content_encoding: make Curl_all_content_encodings allocless
+
+ - Fixes a memory leak pointed out by Coverity
+ - Also found by OSS-Fuzz: https://bugs.chromium.org/p/oss-fuzz/issues/detail?
+ id=63947
+ - Avoids unncessary allocations
+
+ Follow-up ad051e1cbec68b2456a22661b
+
+ Closes #12289
+
+Michael Kaufmann (7 Nov 2023)
+
+- vtls: use ALPN "http/1.1" for HTTP/1.x, including HTTP/1.0
+
+ Some servers don't support the ALPN protocol "http/1.0" (e.g. IIS 10),
+ avoid it and use "http/1.1" instead.
+
+ This reverts commit df856cb5c9 (#10183).
+
+ Fixes #12259
+ Closes #12285
+
+Daniel Stenberg (7 Nov 2023)
+
+- Makefile.am: drop vc10, vc11 and vc12 projects from dist
+
+ They are end of life products. Support for generating them remain in the
+ repo for a while but this change drops them from distribution.
+
+ Closes #12288
+
+David Suter (7 Nov 2023)
+
+- projects: add VC14.20 project files
+
+ Windows projects included VC14, VC14.10, VC14.30 but not VC14.20.
+ OpenSSL and Wolf SSL scripts mention VC14.20 so I don't see a reason why
+ this is missing. Updated the templates to produce a VC14.20 project.
+ Project opens in Visual Studio 2019 as expected.
+
+ Closes #12282
+
+Daniel Stenberg (7 Nov 2023)
+
+- curl: move IPFS code into src/tool_ipfs.[ch]
+
+ - convert ensure_trailing into ensure_trailing_slash
+ - strdup the URL string to own it proper
+ - use shorter variable names
+ - combine some expressions
+ - simplify error handling in ipfs_gateway()
+ - add MAX_GATEWAY_URL_LEN + proper bailout if maximum is reached
+ - ipfs-gateway.d polish and simplification
+ - shorten ipfs error message + make them "synthetic"
+
+ Closes #12281
+
+Viktor Szakats (6 Nov 2023)
+
+- build: delete support bits for obsolete Windows compilers
+
+ - Pelles C: Unclear status, failed to obtain a fresh copy a few months
+ ago. Possible website is HTTP-only. ~10 years ago I left this compiler
+ dealing with crashes and other issues with no response on the forum
+ for years. It has seen some activity in curl back in 2021.
+ - LCC: Last stable release in September 2002.
+ - Salford C: Misses winsock2 support, possibly abandoned? Last mentioned
+ in 2006.
+ - Borland C++: We dropped Borland C++ support in 2018.
+ - MS Visual C++ 6.0: Released in 1998. curl already requires VS 2010
+ (or possibly 2008) as a minimum.
+
+ Closes #12222
+
+- build: delete `HAVE_STDINT_H` and `HAVE_INTTYPES_H`
+
+ We use `stdint.h` unconditionally in all places except one. These uses
+ are imposed by external dependencies / features. nghttp2, quic, wolfSSL
+ and `HAVE_MACH_ABSOLUTE_TIME` do require this C99 header. It means that
+ any of these features make curl require a C99 compiler. (In case of
+ MSVC, this means Visual Studio 2010 or newer.)
+
+ This patch changes the single use of `stdint.h` guarded by
+ `HAVE_STDINT_H` to use `stdint.h` unconditionally. Also stop using
+ `inttypes.h` as an alternative there. `HAVE_INTTYPES_H` wasn't used
+ anywhere else, allowing to delete this feature check as well.
+
+ Closes #12275
+
+Daniel Stenberg (6 Nov 2023)
+
+- tool_operate: do not mix memory models
+
+ Make sure 'inputpath' only points to memory allocated by libcurl so that
+ curl_free works correctly.
+
+ Pointed out by Coverity
+
+ Follow-up to 859e88f6533f9e1f890
+
+ Closes #12280
+
+Stefan Eissing (6 Nov 2023)
+
+- lib: client writer, part 2, accounting + logging
+
+ This PR has these changes:
+
+ Renaming of unencode_* to cwriter, e.g. client writers
+ - documentation of sendf.h functions
+ - move max decode stack checks back to content_encoding.c
+ - define writer phase which was used as order before
+ - introduce phases for monitoring inbetween decode phases
+ - offering default implementations for init/write/close
+
+ Add type paramter to client writer's do_write()
+ - always pass all writes through the writer stack
+ - writers who only care about BODY data will pass other writes unchanged
+
+ add RAW and PROTOCOL client writers
+ - RAW used for Curl_debug() logging of CURLINFO_DATA_IN
+ - PROTOCOL used for updates to data->req.bytecount, max_filesize checks and
+ Curl_pgrsSetDownloadCounter()
+ - remove all updates of data->req.bytecount and calls to
+ Curl_pgrsSetDownloadCounter() and Curl_debug() from other code
+ - adjust test457 expected output to no longer see the excess write
+
+ Closes #12184
+
+Daniel Stenberg (6 Nov 2023)
+
+- VULN-DISCLOSURE-POLICY: escape sequences are not a security flaw
+
+ Closes #12278
+
+Viktor Szakats (6 Nov 2023)
+
+- rand: fix build error with autotools + LibreSSL
+
+ autotools unexpectedly detects `arc4random` because it is also looking
+ into dependency libs. One dependency, LibreSSL, happens to publish an
+ `arc4random` function (via its shared lib before v3.7, also via static
+ lib as of v3.8.2). When trying to use this function in `lib/rand.c`,
+ its protoype is missing. To fix that, curl included a prototype, but
+ that used a C99 type without including `stdint.h`, causing:
+
+ ```
+ ../../lib/rand.c:37:1: error: unknown type name 'uint32_t'
+ 37 | uint32_t arc4random(void);
+ | ^
+ 1 error generated.
+ ```
+
+ This patch improves this by dropping the local prototype and instead
+ limiting `arc4random` use for non-OpenSSL builds. OpenSSL builds provide
+ their own random source anyway.
+
+ The better fix would be to teach autotools to not link dependency libs
+ while detecting `arc4random`.
+
+ LibreSSL publishing a non-namespaced `arc4random` tracked here:
+ https://github.com/libressl/portable/issues/928
+
+ Regression from 755ddbe901cd0c921fbc3ac5b3775c0dc683bc73 #10672
+
+ Reviewed-by: Daniel Stenberg
+ Fixes #12257
+ Closes #12274
+
+Daniel Stenberg (5 Nov 2023)
+
+- RELEASE-NOTES: synced
+
+- strdup: do Curl_strndup without strncpy
+
+ To avoid (false positive) gcc-13 compiler warnings.
+
+ Follow-up to 4855debd8a2c1cb
+
+ Assisted-by: Jay Satiro
+ Reported-by: Viktor Szakats
+ Fixes #12258
+
+Enno Boland (5 Nov 2023)
+
+- HTTP: fix empty-body warning
+
+ This change fixes a compiler warning with gcc-12.2.0 when
+ `-DCURL_DISABLE_BEARER_AUTH=ON` is used.
+
+ /home/tox/src/curl/lib/http.c: In function 'Curl_http_input_auth':
+ /home/tox/src/curl/lib/http.c:1147:12: warning: suggest braces around emp
+ ty body in an 'else' statement [-Wempty-body]
+ 1147 | ;
+ | ^
+
+ Closes #12262
+
+Daniel Stenberg (5 Nov 2023)
+
+- openssl: identify the "quictls" backend correctly
+
+ Since vanilla OpenSSL does not support the QUIC API I think it helps
+ users to identify the correct OpenSSL fork in version output. The best
+ (crude) way to do that right now seems to be to check if ngtcp2 support
+ is enabled.
+
+ Closes #12270
+
+Mark Gaiser (5 Nov 2023)
+
+- curl: improved IPFS and IPNS URL support
+
+ Previously just ipfs://<cid> and ipns://<cid> was supported, which is
+ too strict for some usecases.
+
+ This patch allows paths and query arguments to be used too.
+ Making this work according to normal http semantics:
+
+ ipfs://<cid>/foo/bar?key=val
+ ipns://<cid>/foo/bar?key=val
+
+ The gateway url support is changed.
+ It now only supports gateways in the form of:
+
+ http://<gateway>/foo/bar
+ http://<gateway>
+
+ Query arguments here are explicitly not allowed and trigger an intended
+ malformed url error.
+
+ There also was a crash when IPFS_PATH was set with a non trailing
+ forward slash. This has been fixed.
+
+ Lastly, a load of test cases have been added to verify the above.
+
+ Reported-by: Steven Allen
+ Fixes #12148
+ Closes #12152
+
+Harry Mallon (5 Nov 2023)
+
+- docs: KNOWN_BUGS cleanup
+
+ * Remove other mention of hyper memory-leaks from `KNOWN_BUGS`.
+ Should have been removed in 629723ecf22a8eae78d64cceec2f3bdae703ec95
+
+ * Remove mention of aws-sigv4 sort query string from `KNOWN_BUGS`.
+ Fixed in #11806
+
+ * Remove mention of aws-sigv4 query empty value problems
+
+ * Remove mention of aws-sigv4 missing amz-content-sha256
+ Fixed in #9995
+
+- http_aws_sigv4: canonicalise valueless query params
+
+ Fixes #8107
+ Closes #12244
+
+Michael Kaufmann (4 Nov 2023)
+
+- docs: preserve the modification date when copying the prebuilt man page
+
+ The previously built man page "curl.1" must be copied with the original
+ modification date, otherwise the man page is never updated.
+
+ This fixes a bug that has been introduced with commit 2568441cab.
+
+ Reviewed-by: Dan Fandrich
+ Reviewed-by: Daniel Stenberg
+
+ Closes #12199
+
+Daniel Stenberg (4 Nov 2023)
+
+- docs: remove bold from some man page SYNOPSIS sections
+
+ In the name of consistency
+
+ Closes #12267
+
+- openssl: two multi pointer checks should probably rather be asserts
+
+ ... so add the asserts now and consider removing the dynamic checks in a
+ future.
+
+ Ref: #12261
+ Closes #12264
+
+boilingoden (4 Nov 2023)
+
+- docs: add supported version for the json write-out
+
+ xref: https://curl.se/changes.html#7_70_0
+
+ Closes #12266
+
+Viktor Szakats (3 Nov 2023)
+
+- appveyor: make VS2008-built curl tool runnable
+
+ By linking the CRT statically. This avoids the error about missing
+ runtime DLL `MSVCR90.dll` when running the freshly built `curl.exe`.
+
+ Closes #12263
+
+Stefan Eissing (3 Nov 2023)
+
+- url: proxy ssl connection reuse fix
+
+ - tunnel https proxy used for http: transfers does
+ no check if proxy-ssl configuration matches
+ - test cases added, test_10_12 fails on 8.4.0
+
+ Closes #12255
+
+Jay Satiro (3 Nov 2023)
+
+- curl_sspi: support more revocation error names in error messages
+
+ - Add these revocation errors to sspi error list:
+ CRYPT_E_NO_REVOCATION_DLL, CRYPT_E_NO_REVOCATION_CHECK,
+ CRYPT_E_REVOCATION_OFFLINE and CRYPT_E_NOT_IN_REVOCATION_DATABASE.
+
+ Prior to this change those error codes were not matched to their macro
+ name and instead shown as "unknown error".
+
+ Before:
+
+ schannel: next InitializeSecurityContext failed:
+ Unknown error (0x80092013) - The revocation function was
+ unable to check revocation because the revocation server was offline.
+
+ After:
+
+ schannel: next InitializeSecurityContext failed:
+ CRYPT_E_REVOCATION_OFFLINE (0x80092013) - The revocation function was
+ unable to check revocation because the revocation server was offline.
+
+ Bug: https://github.com/curl/curl/issues/12239
+ Reported-by: Niracler Li
+
+ Closes https://github.com/curl/curl/pull/12241
+
+- strdup: don't allow Curl_strndup to read past a null terminator
+
+ - Use malloc + strncpy instead of Curl_memdup to dupe the string before
+ null terminating it.
+
+ Prior to this change if Curl_strndup was passed a length longer than
+ the allocated string then it could copy out of bounds.
+
+ This change is for posterity. Curl_strndup was added in the parent
+ commit and currently none of the calls to it pass a length that would
+ cause it to read past the allocated length of the input.
+
+ Follow-up to d3b3ba35.
+
+ Closes https://github.com/curl/curl/pull/12254
+
+Daniel Stenberg (2 Nov 2023)
+
+- lib: add and use Curl_strndup()
+
+ The Curl_strndup() function is similar to memdup(), but copies 'n' bytes
+ then adds a terminating null byte ('\0').
+
+ Closes #12251
+
+- CURPOST_POSTFIELDS.3: add CURLOPT_COPYPOSTFIELDS in SEE ALSO
+
+Stefan Eissing (2 Nov 2023)
+
+- pytest: use lower count in repeat tests
+
+ - lower large iteration counts in some tests somewhat for
+ the same coverage with less duration
+
+ Closes #12248
+
+Daniel Stenberg (2 Nov 2023)
+
+- RELEASE-NOTES: synced
+
+- docs: clarify that curl passes on input unfiltered
+
+ ... for several options.
+
+ Reported-by: Ophir Lojkine
+
+ Closes #12249
+
+- urlapi: when URL encoding the fragment, pass in the right length
+
+ A benign bug because it would only add an extra null terminator.
+
+ Made lib1560 get a test that runs this code.
+
+ Closes #12250
+
+Stefan Eissing (2 Nov 2023)
+
+- vtls: late clone of connection ssl config
+
+ - perform connection cache matching against `data->set.ssl.primary`
+ and proxy counterpart
+ - fully clone connection ssl config only when connection is used
+
+ Closes #12237
+
+- msh3: error when built with CURL_DISABLE_SOCKETPAIR set
+
+ Reported-by: Gisle Vanem
+ Closes #12252
+ Fixes #12213
+
+Daniel Stenberg (2 Nov 2023)
+
+- hsts: skip single-dot hostname
+
+ Reported-by: Maksymilian Arciemowicz
+
+ Closes #12247
+
+- vtls: fix build without proxy
+
+ Follow-up to bf0e278a3c54bc7fee7360da17c
+
+ closes #12243
+
+- docs/example/keepalive.c: show TCP keep-alive options
+
+ Closes #12242
+
+- lib1560: verify appending blank URL encoded query string
+
+- urlapi: skip appending NULL pointer query
+
+ Reported-by: kirbyn17 on hackerone
+
+ Closes #12240
+
+- lib1560: verify setting host to "" with and without URL encode
+
+- urlapi: avoid null deref if setting blank host to url encode
+
+ Reported-by: kirbyn17 on hackerone
+
+ Closes #12240
+
+- dynbuf: assert for NULL pointer inputs
+
+ Help us catch more mistakes.
+
+ Closes #12238
+
+- HTTP3: ngtcp2 builds are no longer experimental
+
+ The other HTTP/3 backends are still experimental.
+
+ Closes #12235
+
+Stefan Eissing (31 Oct 2023)
+
+- vtls: cleanup SSL config management
+
+ - remove `Curl_ssl_get_config()`, no longer needed
+
+ Closes #12204
+
+Daniel Stenberg (31 Oct 2023)
+
+- libcurl-thread.3: simplify the TLS section
+
+ All TLS libraries curl can use are threadsafe since OpenSSL 1.1.x, August
+ 2016.
+
+ Closes #12233
+
+- configure: better --disable-http
+
+ - disable HTTPS-proxy as well, since it can't work without HTTP
+
+ - curl_setup: when HTTP is disabled, also disable all features that are
+ HTTP-only
+
+ - version: HTTPS-proxy only exists if HTTP support exists
+
+ Closes #12223
+
+- http: consider resume with CURLOPT_FAILONERRROR and 416 to be fine
+
+ Finding a 'Content-Range:' in the response changed the handling.
+
+ Add test case 1475 to verify -C - with 416 and Content-Range: header,
+ which is almost exactly like test 194 which instead uses a fixed -C
+ offset. Adjusted test 194 to also be considered fine.
+
+ Fixes #10521
+ Reported-by: Smackd0wn
+ Fixes #12174
+ Reported-by: Anubhav Rai
+ Closes #12176
+
+Stefan Eissing (30 Oct 2023)
+
+- GHA: fix checkout of quictls repository to use correct branch name
+
+ Follow-up to c868b0e30f10cd0ac7
+
+ Closes #12232
+
+Daniel Stenberg (30 Oct 2023)
+
+- docs/example/localport.c: show off CURLOPT_LOCALPORT
+
+ Closes #12230
+
+- docs/examples/interface.c: show CURLOPT_INTERFACE use
+
+ Although super simple.
+
+ Closes #12229
+
+Viktor Szakats (30 Oct 2023)
+
+- build: fix compiler warning with auths disabled
+
+ ```
+ ./curl/lib/http.c:979:12: warning: unused function 'is_valid_auth_separator'
+ [-Wunused-function]
+ static int is_valid_auth_separator(char ch)
+ ^
+ 5 warnings generated.
+ ```
+
+ Follow-up to e92edfbef64448ef461117769881f3ed776dec4e #11490
+
+ Closes #12227
+
+- build: require Windows XP or newer
+
+ After this patch we assume availability of `getaddrinfo` and
+ `freeaddrinfo`, first introduced in Windows XP. Meaning curl
+ now requires building for Windows XP as a minimum.
+
+ TODO: assume these also in autotools.
+
+ Ref: https://github.com/curl/curl/pull/12221#issuecomment-1783761806
+ Closes #12225
+
+- appveyor: bump one job to OpenSSL 3.1 (was 1.1.1)
+
+ Use 3.1 with the modern runner image.
+
+ We still use 1.1.1 in 8 jobs.
+
+ 1.1.1 is EOL since 2023-09-11:
+ https://www.openssl.org/blog/blog/2023/03/28/1.1.1-EOL/
+
+ Also:
+ - add missing SSL-backend to job descriptions.
+ - tidy up CPU in job descriptions.
+
+ Closes #12226
+
+Daniel Stenberg (30 Oct 2023)
+
+- RELEASE-NOTES: synced
+
+- GHA: bump ngtcp2, nghttp3, nghttp2 and quictls versions
+
+ ngtcp2 1.0.1
+ nghttp3 1.0.0
+ nghttp2 1.58.0
+ quictls 3.1.4+quic
+
+ also sync HTTP3.md with these changes
+
+ Closes #12132
+
+Kareem (29 Oct 2023)
+
+- wolfssl: add default case for wolfssl_connect_step1 switch
+
+ Closes #12218
+
+Jay Satiro (29 Oct 2023)
+
+- curl_setup: disallow Windows IPv6 builds missing getaddrinfo
+
+ - On Windows if IPv6 is enabled but getaddrinfo is missing then #error
+ the build.
+
+ curl can be built with IPv6 support (ENABLE_IPV6) but without the
+ ability to resolve hosts to IPv6 addresses (HAVE_GETADDRINFO). On
+ Windows this is highly unlikely and should be considered a bad build
+ configuration.
+
+ Such a bad configuration has already given us a bug that was hard to
+ diagnose. See #12134 and #12136 for discussion.
+
+ Ref: https://github.com/curl/curl/issues/12134
+ Ref: https://github.com/curl/curl/pull/12136
+
+ Closes https://github.com/curl/curl/pull/12221
+
+Nico Rieck (29 Oct 2023)
+
+- openssl: make CURLSSLOPT_NATIVE_CA import Windows intermediate CAs
+
+ - If CURLSSLOPT_NATIVE_CA on Windows then import from intermediate CA
+ "CA" store after importing from root CA "ROOT" store.
+
+ This change allows curl to work in situations where a server does not
+ send all intermediate certs and they are present in the "CA" store (the
+ store with intermediate CAs). This is already allowed by the Schannel
+ backend.
+
+ Also this change makes partial chain verification possible for those
+ certs since we allow partial chain verification by default for OpenSSL
+ (unless CURLSSLOPT_NO_PARTIALCHAIN). This is not allowed by the Schannel
+ backend.
+
+ Prior to this change CURLSSLOPT_NATIVE_CA only imported "ROOT" certs.
+
+ Fixes https://github.com/curl/curl/issues/12155
+ Closes https://github.com/curl/curl/pull/12185
+
+Viktor Szakats (28 Oct 2023)
+
+- Makefile.mk: fix `-rtmp` option for non-Windows [ci skip]
+
+Daniel Stenberg (28 Oct 2023)
+
+- asyn-ares: handle no connection in the addrinfo callback
+
+ To avoid crashing.
+
+ Follow-up from 56a4db2
+ Closes #12219
+
+Jay Satiro (28 Oct 2023)
+
+- hostip6: fix DEBUG_ADDRINFO builds
+
+ - Removed unused and incorrect parameter from dump_addrinfo().
+
+ Bug: https://github.com/curl/curl/commit/56a4db2e#commitcomment-131050442
+ Reported-by: Gisle Vanem
+
+ Closes https://github.com/curl/curl/pull/12212
+
+Viktor Szakats (28 Oct 2023)
+
+- Makefile.mk: restore `_mingw.h` for default `_WIN32_WINNT`
+
+ In 8.4.0 we deleted `_mingw.h` as part of purging old-mingw support.
+ Turns out `_mingw.h` had the side-effect of setting a default
+ `_WIN32_WINNT` value expected by `lib/config-win32.h` to enable
+ `getaddrinfo` support in `Makefile.mk` mingw-w64 builds. This caused
+ disabling support for this unless specifying the value manually.
+
+ Restore this header and update its comment to tell why we continue
+ to need it.
+
+ This triggered a regression in official Windows curl builds starting
+ with 8.4.0_1. Fixed in 8.4.0_6. (8.5.0 will be using CMake.)
+
+ Regression from 38029101e2d78ba125732b3bab6ec267b80a0e72 #11625
+
+ Reported-by: zhengqwe on github
+ Helped-by: Nico Rieck
+ Fixes #12134
+ Fixes #12136
+ Closes #12217
+
+- hostip: silence compiler warning `-Wparentheses-equality`
+
+ Seen with LLVM 17.
+
+ ```
+ hostip.c:1336:22: warning: equality comparison with extraneous parentheses [-
+ Wparentheses-equality]
+ 1336 | (a->ai_family == PF_INET)) {
+ | ~~~~~~~~~~~~~^~~~~~~~~~
+ hostip.c:1336:22: note: remove extraneous parentheses around the comparison t
+ o silence this warning
+ 1336 | (a->ai_family == PF_INET)) {
+ | ~ ^ ~
+ hostip.c:1336:22: note: use '=' to turn this equality comparison into an assi
+ gnment
+ 1336 | (a->ai_family == PF_INET)) {
+ | ^~
+ | =
+ 1 warning generated.
+ ```
+
+ Follow-up to b651aba0962bb31353f55de4dc35f745952a1b10 #12145
+
+ Reviewed-by: Daniel Stenberg
+ Closes #12215
+
+Stefan Eissing (27 Oct 2023)
+
+- doh: use PIPEWAIT when HTTP/2 is attempted
+
+ Closes #12214
+
+Daniel Stenberg (27 Oct 2023)
+
+- setopt: remove outdated cookie comment
+
+ Closes #12206
+
+Stefan Eissing (27 Oct 2023)
+
+- cfilter: provide call to tell connection to forget a socket
+
+ - fixed libssh.c workaround for a socket being closed by
+ the library
+ - eliminate the terrible hack in cf-socket.c to guess when
+ this happened and try not closing the socket again.
+ - fixes race in eyeballing when socket could have failed to
+ be closed for a discarded connect attempt
+
+ Closes #12207
+
+- url: protocol handler lookup tidy-up
+
+ - rename lookup to what it does
+ - use ARRAYSIZE instead of NULL check for end
+ - offer alternate lookup for 0-terminated strings
+
+ Closes #12216
+
+Viktor Szakats (27 Oct 2023)
+
+- build: variadic macro tidy-ups
+
+ - delete unused `HAVE_VARIADIC_MACROS_C99/GCC` feature checks.
+ (both autotools and CMake.)
+ - delete duplicate `NULL` check in `Curl_trc_cf_infof()`.
+ - fix compiler warning in `CURL_DISABLE_VERBOSE_STRINGS` builds.
+ ```
+ ./lib/cf-socket.c:122:41: warning: unused parameter 'data' [-Wunused-parame
+ ter]
+ static void nosigpipe(struct Curl_easy *data,
+ ^
+ ```
+ - fix `#ifdef` comments in `lib/curl_trc.{c,h}`.
+ - fix indentation in some `infof()` calls.
+
+ Follow-up to dac293cfb7026b1ca4175d88b80f1432d3d3c684 #12167
+
+ Cherry-picked from #12105
+ Closes #12210
+
+- cmake: speed up threads setup for Windows
+
+ Win32 threads are always available. We enabled them unconditionally
+ (with `ENABLE_THREADED_RESOLVER`). CMake built-in thread detection
+ logic has this condition hard-coded for Windows as well (since at least
+ 2007).
+
+ Instead of doing all the work of detecting pthread combinations on
+ Windows, then discarding those results, skip these efforts and assume
+ built-in thread support when building for Windows.
+
+ This saves 1-3 slow CMake configuration steps.
+
+ Reviewed-by: Daniel Stenberg
+ Closes #12202
+
+- cmake: speed up zstd detection
+
+ Before this patch we detected the presence of a specific zstd API to
+ see if we can use the library. zstd published that API in its first
+ stable release: v1.0.0 (2016-08-31).
+
+ Replace that method by detecting the zstd library version instead and
+ accepting if it's v1.0.0 or newer. Also display this detected version
+ and display a warning if the zstd found is unfit for curl.
+
+ We use the same version detection method as zstd itself, via its public
+ C header.
+
+ This deviates from autotools which keeps using the slow method of
+ looking for the API by building a test program. The outcome is the same
+ as long as zstd keeps offering this API.
+
+ Ref: https://github.com/facebook/zstd/commit/5a0c8e24395079f8e8cdc90aa1659cd5
+ ab1b7427 (2016-08-12, committed)
+ Ref: https://github.com/facebook/zstd/releases/tag/v0.8.1 (2016-08-18, first
+ released)
+ Ref: https://github.com/facebook/zstd/releases/tag/v1.0.0
+
+ Reviewed-by: Daniel Stenberg
+ Closes #12200
+
+Daniel Stenberg (26 Oct 2023)
+
+- openssl: fix infof() to avoid compiler warning for %s with null
+
+ vtls/openssl.c: In function ‘ossl_connect_step2’:
+ ../lib/curl_trc.h:120:10: error: ‘%s’ directive argument is null [-Werror
+ =format-overflow=]
+ 120 | Curl_infof(data, __VA_ARGS__); } while(0)
+ | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ vtls/openssl.c:4008:5: note: in expansion of macro ‘infof’
+ 4008 | infof(data, "SSL connection using %s / %s / %s / %s",
+ | ^~~~~
+ vtls/openssl.c:4008:49: note: format string is defined here
+ 4008 | infof(data, "SSL connection using %s / %s / %s / %s",
+ | ^~
+
+ Follow-up to b6e6d4ff8f253c8b8055bab
+ Closes #12196
+
+Stefan Eissing (26 Oct 2023)
+
+- lib: apache style infof and trace macros/functions
+
+ - test for a simplified C99 variadic check
+ - args to infof() in --disable-verbose are no longer disregarded but
+ must compile.
+
+ Closes #12167
+ Fixes #12083
+ Fixes #11880
+ Fixes #11891
+
+Daniel Stenberg (26 Oct 2023)
+
+- RELEASE-NOTES: synced
+
+Stefan Eissing (26 Oct 2023)
+
+- urldata: move async resolver state from easy handle to connectdata
+
+ - resolving is done for a connection, not for every transfer
+ - save create/dup/free of a cares channel for each transfer
+ - check values of setopt calls against a local channel if no
+ connection has been attached yet, when needed.
+
+ Closes #12198
+
+Daniel Stenberg (26 Oct 2023)
+
+- CURLOPT_WRITEFUNCTION.3: clarify what libcurl returns for CURL_WRITEFUNC_ERRO
+ R
+
+ It returns CURLE_WRITE_ERROR. It was not previously stated clearly.
+
+ Reported-by: enWILLYado on github
+ Fixes #12201
+ Closes #12203
+
+Viktor Szakats (25 Oct 2023)
+
+- autotools: update references to deleted `crypt-auth` option
+
+ Delete leftovers of the `crypt-auth` `./configure` option and
+ add the new ones that replaced them.
+
+ Follow-up to e92edfbef64448ef461117769881f3ed776dec4e #11490
+
+ Reviewed-by: Daniel Stenberg
+ Closes #12194
+
+Stefan Eissing (25 Oct 2023)
+
+- lib: introduce struct easy_poll_set for poll information
+
+ Connection filter had a `get_select_socks()` method, inspired by the
+ various `getsocks` functions involved during the lifetime of a
+ transfer. These, depending on transfer state (CONNECT/DO/DONE/ etc.),
+ return sockets to monitor and flag if this shall be done for POLLIN
+ and/or POLLOUT.
+
+ Due to this design, sockets and flags could only be added, not
+ removed. This led to problems in filters like HTTP/2 where flow control
+ prohibits the sending of data until the peer increases the flow
+ window. The general transfer loop wants to write, adds POLLOUT, the
+ socket is writeable but no data can be written.
+
+ This leads to cpu busy loops. To prevent that, HTTP/2 did set the
+ `SEND_HOLD` flag of such a blocked transfer, so the transfer loop cedes
+ further attempts. This works if only one such filter is involved. If a
+ HTTP/2 transfer goes through a HTTP/2 proxy, two filters are
+ setting/clearing this flag and may step on each other's toes.
+
+ Connection filters `get_select_socks()` is replaced by
+ `adjust_pollset()`. They get passed a `struct easy_pollset` that keeps
+ up to `MAX_SOCKSPEREASYHANDLE` sockets and their `POLLIN|POLLOUT`
+ flags. This struct is initialized in `multi_getsock()` by calling the
+ various `getsocks()` implementations based on transfer state, as before.
+
+ After protocol handlers/transfer loop have set the sockets and flags
+ they want, the `easy_pollset` is *always* passed to the filters. Filters
+ "higher" in the chain are called first, starting at the first
+ not-yet-connection one. Each filter may add sockets and/or change
+ flags. When all flags are removed, the socket itself is removed from the
+ pollset.
+
+ Example:
+
+ * transfer wants to send, adds POLLOUT
+ * http/2 filter has a flow control block, removes POLLOUT and adds
+ POLLIN (it is waiting on a WINDOW_UPDATE from the server)
+ * TLS filter is connected and changes nothing
+ * h2-proxy filter also has a flow control block on its tunnel stream,
+ removes POLLOUT and adds POLLIN also.
+ * socket filter is connected and changes nothing
+ * The resulting pollset is then mixed together with all other transfers
+ and their pollsets, just as before.
+
+ Use of `SEND_HOLD` is no longer necessary in the filters.
+
+ All filters are adapted for the changed method. The handling in
+ `multi.c` has been adjusted, but its state handling the the protocol
+ handlers' `getsocks` method are untouched.
+
+ The most affected filters are http/2, ngtcp2, quiche and h2-proxy. TLS
+ filters needed to be adjusted for the connecting handshake read/write
+ handling.
+
+ No noticeable difference in performance was detected in local scorecard
+ runs.
+
+ Closes #11833
+
+Daniel Stenberg (25 Oct 2023)
+
+- tests/README: SOCKS tests are not using OpenSSH, it has its own server
+
+ Follow-up to 04fd67555cc
+
+ Closes #12195
+
+Jacob Hoffman-Andrews (25 Oct 2023)
+
+- tets: make test documentation more user-friendly
+
+ Put the instructions to run tests right at the top of tests/README.md.
+
+ Give instructions to read the runtests.1 man page for information
+ about flags. Delete redundant copy of the flags documentation in the
+ README.
+
+ Add a mention in README.md of the important parallelism flag, to make
+ test runs go much faster.
+
+ Move documentation of output line format into the runtests.1 man page,
+ and update it with missing flags.
+
+ Fix the order of two flags in the man page.
+
+ Closes #12193
+
+Viktor Szakats (24 Oct 2023)
+
+- cmake: pre-fill rest of detection values for Windows
+
+ The goal of this patch is to avoid unnecessary feature detection work
+ when doing Windows builds with CMake. Do this by pre-filling well-known
+ detection results for Windows and specifically for mingw-w64 and MSVC
+ compilers. Also limit feature checks to platforms where the results are
+ actually used. Drop a few redundant ones. And some tidying up.
+
+ - pre-fill remaining detection values in Windows CMake builds.
+
+ Based on actual detection results observed in CI runs, preceding
+ similar work over libssh2 and matching up values with
+ `lib/config-win32.h`.
+
+ This brings down CMake configuration time from 58 to 14 seconds on the
+ same local machine.
+
+ On AppVeyor CI this translates to:
+ - 128 seconds -> 50 seconds VS2022 MSVC with OpenSSL (per CMake job):
+ https://ci.appveyor.com/project/curlorg/curl/builds/48208419/job/4gw66ecr
+ jpy7necb#L296
+ https://ci.appveyor.com/project/curlorg/curl/builds/48217440/job/8m4fwrr2
+ fe249uo8#L186
+ - 62 seconds -> 16 seconds VS2017 MINGW (per CMake job):
+ https://ci.appveyor.com/project/curlorg/curl/builds/48208419/job/s1y8q5iv
+ lcs7ub29?fullLog=true#L290
+ https://ci.appveyor.com/project/curlorg/curl/builds/48217440/job/pchpxyjs
+ yc9kl13a?fullLog=true#L194
+
+ The formula is about 1-3 seconds delay for each detection. Almost all
+ of these trigger a full compile-link cycle behind the scenes, slow
+ even today, both cross and native, mingw-w64 and apparently MSVC too.
+ Enabling .map files or other custom build features slows it down
+ further. (Similar is expected for autotools configure.)
+
+ - stop detecting `idn2.h` if idn2 was deselected.
+ autotools does this.
+
+ - stop detecting `idn2.h` if idn2 was not found.
+ This deviates from autotools. Source code requires both header and
+ lib, so this is still correct, but faster.
+
+ - limit `ADDRESS_FAMILY` detection to Windows.
+
+ - normalize `HAVE_WIN32_WINNT` value to lowercase `0x0a12` format.
+
+ - pre-fill `HAVE_WIN32_WINNT`-dependent detection results.
+ Saving 4 (slow) feature-detections in most builds: `getaddrinfo`,
+ `freeaddrinfo`, `inet_ntop`, `inet_pton`
+
+ - fix pre-filled `HAVE_SYS_TIME_H`, `HAVE_SYS_PARAM_H`,
+ `HAVE_GETTIMEOFDAY` for mingw-w64.
+ Luckily this do not change build results, as `WIN32` took
+ priority over `HAVE_GETTIMEOFDAY` with the current source
+ code.
+
+ - limit `HAVE_CLOCK_GETTIME_MONOTONIC_RAW` and
+ `HAVE_CLOCK_GETTIME_MONOTONIC` detections to non-Windows.
+ We're not using these in the source code for Windows.
+
+ - reduce compiler warning noise in CMake internal logs:
+ - fix to include `winsock2.h` before `windows.h`.
+ Apply it to autotools test snippets too.
+ - delete previous `-D_WINSOCKAPI_=` hack that aimed to fix the above.
+ - cleanup `CMake/CurlTests.c` to emit less warnings.
+
+ - delete redundant `HAVE_MACRO_SIGSETJMP` feature check.
+ It was the same check as `HAVE_SIGSETJMP`.
+
+ - delete 'experimental' marking from `CURL_USE_OPENSSL`.
+
+ - show CMake version via `CMakeLists.txt`.
+ Credit to the `zlib-ng` project for the idea:
+ https://github.com/zlib-ng/zlib-ng/blob/61e181c8ae93dbf56040336179c9954078b
+ d1399/CMakeLists.txt#L7
+
+ - make `CMake/CurlTests.c` pass `checksrc`.
+
+ - `CMake/WindowsCache.cmake` tidy-ups.
+
+ - replace `WIN32` guard with `_WIN32` in `CMake/CurlTests.c`.
+
+ Closes #12044
+
+Jay Satiro (24 Oct 2023)
+
+- page-footer: clarify exit code 25
+
+ - Clarify that curl tool exit code 25 means an upload failed to start.
+
+ Exit code 25 is equivalent to CURLE_UPLOAD_FAILED (25). Prior to this
+ change the documentation only mentioned the case of FTP STOR failing.
+
+ Reported-by: Emanuele Torre
+
+ Ref: https://github.com/curl/curl/blob/curl-8_4_0/docs/libcurl/libcurl-errors
+ .3#L113-L115
+
+ Fixes https://github.com/curl/curl/issues/12189
+ Closes https://github.com/curl/curl/pull/12190
+
+Daniel Stenberg (24 Oct 2023)
+
+- scripts/cijobs.pl: adjust for appveyor
+
+ Follow-up to a1d73a6bb
+
+Alex Bozarth (24 Oct 2023)
+
+- OpenSSL: Include SIG and KEM algorithms in verbose
+
+ Currently the verbose output does not include which algorithms are used
+ for the signature and key exchange when using OpenSSL. Including the
+ algorithms used will enable better debugging when working on using new
+ algorithm implementations. Know what algorithms are used has become more
+ important with the fast growing research into new quantum-safe
+ algorithms.
+
+ This implementation includes a build time check for the OpenSSL version
+ to use a new function that will be included in OpenSSL 3.2 that was
+ introduced in openssl/openssl@6866824
+
+ Based-on-patch-by: Martin Schmatz <mrt@zurich.ibm.com>
+ Closes #12030
+
+Daniel Stenberg (23 Oct 2023)
+
+- http2: provide an error callback and failf the message
+
+ Getting nghttp2's error message helps users understand what's going
+ on. For example when the connection is brought down due a forbidden
+ header is used - as that header is then not displayed by curl itself.
+
+ Example:
+
+ curl: (92) Invalid HTTP header field was received: frame type: 1,
+ stream: 1, name: [upgrade], value: [h2,h2c]
+
+ Ref: #12172
+ Closes #12179
+
+Turiiya (23 Oct 2023)
+
+- BINDINGS: add V binding
+
+ Closes #12182
+
+Daniel Stenberg (22 Oct 2023)
+
+- configure: check for the fseeko declaration too
+
+ ... and make the code require both symbol and declaration.
+
+ This is because for Android, the symbol is always present in the lib at
+ build-time even when not actually available in run-time.
+
+ Assisted-by: Viktor Szakats
+ Reported-by: 12932 on github
+ Fixes #12086
+ Closes #12158
+
+Viktor Szakats (22 Oct 2023)
+
+- cmake: fix OpenSSL quic detection in quiche builds
+
+ An orphan call to `CheckQuicSupportInOpenSSL()` remained after a recent
+ update when checking QUIC for quiche. Move back QUIC detection to
+ a function and fixup callers to use that. Also make sure that quiche
+ gets QUIC from BoringSSL, because it doesn't support other forks at this
+ time.
+
+ Regression from dee310d54261f9a8416e87d50bccfe2cbe404949 #11555
+
+ Reported-by: Casey Bodley <cbodley@redhat.com>
+ Fixes #12160
+ Closes #12162
+
+Daniel Stenberg (22 Oct 2023)
+
+- RELEASE-NOTES: synced
+
+ bump to 8.5.0 for pending release
+
+Dan Fandrich (21 Oct 2023)
+
+- test3103: add missing quotes around a test tag attribute
+
+Loïc Yhuel (21 Oct 2023)
+
+- tool: fix --capath when proxy support is disabled
+
+ After 95e8515ca0, --capath always sets CURLOPT_PROXY_CAPATH, which fails
+ with CURLE_UNKNOWN_OPTION when proxy support is disabled.
+
+ Closes #12089
+
+Daniel Stenberg (21 Oct 2023)
+
+- openldap: move the alloc of ldapconninfo to *connect()
+
+ Fixes a minor memory leak on LDAP connection reuse.
+
+ Doing the allocation already in *setup_connection() is wrong since that
+ connect struct might get discarded early when an existing connection is
+ reused instead.
+
+ Closes #12166
+
+- openldap: set the callback argument in oldap_do
+
+ ... to make sure it has the current 'data' pointer and not a stale old
+ one.
+
+ Reported-by: Dan Fandrich
+ Closes #12166
+
+- gnutls: support CURLSSLOPT_NATIVE_CA
+
+ Remove the CURL_CA_FALLBACK logic. That build option was added to allow
+ primarily OpenSSL to use the default paths for loading the CA certs. For
+ GnuTLS it was instead made to load the "system certs", which is
+ different and not desirable.
+
+ The native CA store loading is now asked for with this option.
+
+ Follow-up to 7b55279d1d856
+
+ Co-authored-by: Jay Satiro
+
+ Closes #12137
+
+Stefan Eissing (21 Oct 2023)
+
+- RTSP: improved RTP parser
+
+ - fix HTTP header parsing to report incomplete
+ lines it buffers as consumed!
+ - re-implement the RTP parser for interleave RTP
+ messages for robustness. It is now keeping its
+ state at the connection
+ - RTSP protocol handler "readwrite" implementation
+ now tracks if the response is before/in/after
+ header parsing or "in" a bod by calling
+ "Curl_http_readwrite_headers()" itself. This
+ allows it to know when non-RTP bytes are "junk"
+ or HEADER or BODY.
+ - tested with #12035 and various small receive
+ sizes where current master fails
+
+ Closes #12052
+
+- http2: header conversion tightening
+
+ - fold the code to convert dynhds to the nghttp2 structs
+ into a dynhds internal method
+ - saves code duplication
+ - pacifies compiler analyzers
+
+ Closes #12097
+
+Daniel Stenberg (21 Oct 2023)
+
+- curl_ntlm_wb: fix elif typo
+
+ Reported-by: Manfred Schwarb
+ Follow-up to d4314cdf65ae
+ Bug: https://github.com/curl/curl/commit/d4314cdf65aee295db627016934bd9eb621a
+ b077#r130551295
+
+Dan Fandrich (20 Oct 2023)
+
+- test1683: remove commented-out check alternatives
+
+ Python precheck/postcheck alternatives were included but commented out.
+ Since these are not used and perl is guaranteed to be available to run
+ the perl versions anyway, the Python ones are removed.
+
+Daniel Stenberg (20 Oct 2023)
+
+- hostip: show the list of IPs when resolving is done
+
+ Getting 'curl.se' today then gets this verbose output which might help
+ debugging connectivity related matters.
+
+ * Host curl.se:80 was resolved.
+ * IPv6: 2a04:4e42::347, 2a04:4e42:200::347, 2a04:4e42:400::347,
+ 2a04:4e42:600::347, 2a04:4e42:800::347, 2a04:4e42:a00::347,
+ 2a04:4e42:c00::347, 2a04:4e42:e00::347
+ * IPv4: 151.101.193.91, 151.101.1.91, 151.101.65.91, 151.101.129.91
+
+ Co-authored-by: Jay Satiro
+ Closes #12145
+
+rilysh (20 Oct 2023)
+
+- docs: fix function typo in curl_easy_option_next.3
+
+ Closes #12170
+
+Daniel Stenberg (20 Oct 2023)
+
+- vssh: remove the #ifdef for Curl_ssh_init, use empty macro
+
+ In the same style as other init calls
+
+- easy: remove duplicate wolfSSH init call
+
+ It is already done in Curl_ssh_init() where it belongs.
+
+ Closes #12168
+
+- socks: make SOCKS5 use the CURLOPT_IPRESOLVE choice
+
+ Fixes #11949
+ Reported-by: Ammar Faizi
+ Closes #12163
+
+- urldata: move the 'internal' boolean to the state struct
+
+ ... where all the other state bits for the easy handles live.
+
+ Closes #12165
+
+- url: don't touch the multi handle when closing internal handles
+
+ Reported-by: Maksymilian Arciemowicz
+ Closes #12165
+
+Faraz Fallahi (19 Oct 2023)
+
+- getenv: PlayStation doesn't have getenv()
+
+ Closes #12140
+
+Daniel Stenberg (19 Oct 2023)
+
+- transfer: only reset the FTP wildcard engine in CLEAR state
+
+ To avoid the state machine to start over and redownload all the files
+ *again*.
+
+ Reported-by: lkordos on github
+ Regression from 843b3baa3e3cb228 (shipped in 8.1.0)
+ Bisect-by: Dan Fandrich
+ Fixes #11775
+ Closes #12156
+
+Stefan Eissing (19 Oct 2023)
+
+- GHA: move mod_h2 version in CI to v2.0.25
+
+ Closes #12157
+
+Daniel Stenberg (19 Oct 2023)
+
+- ntlm_wb: use pipe instead of socketpair when possible
+
+ Closes #12149
+
+- RELEASE-NOTES: synced
+
+- asyn-thread: use pipe instead of socketpair for IPC when available
+
+ If pipe() is present. Less overhead.
+
+ Helped-by: Viktor Szakats
+ Closes #12146
+
+Dan Fandrich (17 Oct 2023)
+
+- tests: Fix Windows test helper tool search & use it for handle64
+
+ The checkcmd() and checktestcmd() functions would not have worked on
+ Windows due to hard-coding the UNIX PATH separator character and not
+ adding .exe file extension. This meant that tools like stunnel, valgrind
+ and nghttpx would not have been found and used on Windows, and
+ inspection of previous test runs show none of those being found in pure
+ Windows CI builds.
+
+ With this fixed, they can be used to detect the handle64.exe program
+ before attempting to use it. When handle64.exe was called
+ unconditionally without it existing, it caused perl to abort the test
+ run with the error
+
+ The running command stopped because the preference variable
+ "ErrorActionPreference" or common parameter is set to Stop:
+ sh: handle64.exe: command not found
+
+ Closes #12115
+
+Daniel Stenberg (17 Oct 2023)
+
+- multi: use pipe instead of socketpair to *wakeup()
+
+ If pipe() is present. Less overhead.
+
+ Closes #12142
+
+Jay Satiro (17 Oct 2023)
+
+- build: fix 'threadsafe' feature detection for older gcc
+
+ - Add 'threadsafe' to the feature list shown during build if POSIX
+ threads are being used.
+
+ This is a follow-up to 5adb6000 which added support for building a
+ thread-safe libcurl with older versions of gcc where atomic is not
+ available but pthread is.
+
+ Reported-by: Dan Fandrich
+ Co-authored-by: Dan Fandrich
+
+ Fixes https://github.com/curl/curl/issues/12125
+ Closes https://github.com/curl/curl/pull/12127
+
+Daniel Stenberg (16 Oct 2023)
+
+- test729: verify socks4a with excessive proxy user name length
+
+- socks: better buffer size checks for socks4a user and hostname
+
+ Also limit the proxy user name to 255 bytes, which is the same limit as
+ in SOCKS5.
+
+ Reported-by: sd0 on hackerone
+ Closes #12139
+
+- curl.h: on FreeBSD include sys/param.h instead of osreldate.h
+
+ Should things build on Playstation as well
+
+ Fixes #12107
+ Reported-by: Faraz Fallahi
+ Closes #12123
+
+Marcin Rataj (16 Oct 2023)
+
+- tool_operate: fix links in ipfs errors
+
+ URL fragment links generated from headers in
+ https://curl.se/docs/ipfs.html are lowercase.
+
+ Closes #12133
+
+Viktor Szakats (15 Oct 2023)
+
+- cmake: replace `check_library_exists_concat()`
+
+ The idea of `check_library_exists_concat()` is that it detects an
+ optional component and adds it to the list of libs that we also use in
+ subsequent component checks. This caused problems when detecting
+ components with unnecessary dependencies that were not yet built.
+
+ CMake offers the `CMAKE_REQUIRED_LIBRARIES` variable to set libs used
+ for component checks, which we already use in most cases. That left 4
+ uses of `check_library_exists_concat()`. Only one of these actually
+ needed the 'concat' feature (ldap/lber).
+
+ Delete this function and replace it with standard
+ `check_library_exists()` and manual management of our `CURL_LIBS`
+ list we use when linking build targets. And special logic to handle the
+ ldap/lber case.
+
+ (We have a similar function for headers: `check_include_file_concat()`.
+ It works, but problematic for performance reasons and because it hides
+ the actual headers required in `check_symbol_exists()` calls.)
+
+ Ref: #11537 #11558
+ Fixes #11285
+ Fixes #11648
+ Closes #12070
+
+LoRd_MuldeR (15 Oct 2023)
+
+- tool_cb_wrt: fix write output for very old Windows versions
+
+ - Pass missing parameter for 'lpNumberOfCharsWritten' to WriteConsoleW()
+ function.
+
+ Apparently this parameter was *not* optional on older Windows versions.
+
+ Issue observed on Windows XP SP2. Issue not observed on Windows 7 SP1.
+ So at some point between those two Microsoft changed the behavior.
+
+ Prior to this change, on those versions if parameter is NULL then the
+ function call fails with error ERROR_INVALID_ACCESS.
+
+ Regression since af3f4e41.
+
+ Ref: https://github.com/MicrosoftDocs/Console-Docs/issues/299
+
+ Fixes https://github.com/curl/curl/issues/12131
+ Closes https://github.com/curl/curl/pull/12130
+
+Jay Satiro (15 Oct 2023)
+
+- tool_urlglob: fix build for old gcc versions
+
+ - Don't use __builtin_mul_overflow for GCC 4 and earlier.
+
+ The function was added in GCC 5.
+
+ Ref: https://gcc.gnu.org/gcc-5/changes.html
+
+ Reported-by: Dan Fandrich
+
+ Fixes https://github.com/curl/curl/issues/12124
+ Closes https://github.com/curl/curl/pull/12128
+
+Carlos Henrique Lima Melara (14 Oct 2023)
+
+- docs/libcurl: fix three minor man page format mistakes
+
+ Reported-by: Samuel Henrique
+
+ Closes https://github.com/curl/curl/pull/12126
+
+Jay Satiro (14 Oct 2023)
+
+- tests/server: add more SOCKS5 handshake error checking
+
+ - Add additional checking for missing and too-short SOCKS5 handshake
+ messages.
+
+ Prior to this change the SOCKS5 test server did not check that all parts
+ of the handshake were received successfully. If those parts were missing
+ or too short then the server would access uninitialized memory.
+
+ This issue was discovered in CI job 'memory-sanitizer' test results.
+ Test 2055 was failing due to the SOCKS5 test server not running. It was
+ not running because either it crashed or memory sanitizer aborted it
+ during Test 728. Test 728 connects to the SOCKS5 test server on a
+ redirect but does not send any data on purpose. The test server was not
+ prepared for that.
+
+ Reported-by: Dan Fandrich
+
+ Fixes https://github.com/curl/curl/issues/12117
+ Closes https://github.com/curl/curl/pull/12118
+
+Daniel Stenberg (14 Oct 2023)
+
+- RELEASE-NOTES: synced
+
+Sohom Datta (14 Oct 2023)
+
+- tool_getparam: limit --rate to be smaller than number of ms
+
+ Currently, curl allows users to specify absurd request rates that might
+ be higher than the number of milliseconds in the unit (ex: curl --rate
+ 3600050/h http://localhost:8080 does not error out despite there being
+ only 3600000ms in a hour).
+
+ This change adds a conditional check before the millisecond calculation
+ making sure that the number is not higher than the numerator (the unit)
+ If the number is higher, curl errors out with PARAM_NUMBER_TOO_LARGE
+
+ Closes #12116
+
+Daniel Stenberg (14 Oct 2023)
+
+- opts: fix two minor man page format mistakes
+
+Jay Satiro (14 Oct 2023)
+
+- curl_trc: remove a bad assertion
+
+ - Remove DEBUGASSERT that an internal handle must not have user
+ private_data set before calling the user's debug callback.
+
+ This is a follow-up to 0dc40b2a. The user can distinguish their easy
+ handle from an internal easy handle by setting CURLOPT_PRIVATE on their
+ easy handle. I had wrongly assumed that meant the user couldn't then
+ set CURLOPT_PRIVATE on an internal handle as well.
+
+ Bug: https://github.com/curl/curl/pull/12060#issuecomment-1754594697
+ Reported-by: Daniel Stenberg
+
+ Closes https://github.com/curl/curl/pull/12104
+
+Dan Fandrich (13 Oct 2023)
+
+- test613: stop showing an error on missing output file
+
+ This test would show an error message if the output was missing during
+ the log post-processing step, but the message was not captured by the
+ test harness and wasn't useful since the normal golden log file
+ comparison would the problem more clearly.
+
+Stefan Eissing (13 Oct 2023)
+
+- quic: manage connection idle timeouts
+
+ - configure a 120s idle timeout on our side of the connection
+ - track the timestamp when actual socket IO happens
+ - check IO timestamp to our *and* the peer's idle timeouts
+ in "is this connection alive" checks
+
+ Reported-by: calvin2021y on github
+ Fixes #12064
+ Closes #12077
+
+Dan Fandrich (13 Oct 2023)
+
+- CI: ignore test 286 on Appveyor gcc 9 build
+
+ This test fails sometimes with a super fast retry loop due to what may
+ just be a compiler bug. The test results are ignored on the one CI job
+ where it occurs because there seems to be nothing we can do to fix it.
+
+ Fixes #12040
+ Closes #12106
+
+Viktor Szakats (13 Oct 2023)
+
+- lib: fix gcc warning in printf call
+
+ Do not pass NULL to printf %s.
+
+ Seen with gcc 13.2.0 on Debian:
+ ```
+ .../curl/lib/connect.c:696:27: warning: '%s' directive argument is null [-Wfo
+ rmat-overflow=]
+ ```
+ Ref: https://github.com/curl/curl-for-win/actions/runs/6476161689/job/1758442
+ 6483#step:3:11104
+
+ Ref: #10284
+ Co-authored-by: Jay Satiro
+ Closes #12082
+
+Alex Klyubin (13 Oct 2023)
+
+- http2: safer invocation of populate_binsettings
+
+ populate_binsettings now returns a negative value on error, instead of a
+ huge positive value. Both places which call this function have been
+ updated to handle this change in its contract.
+
+ The way populate_binsettings had been used prior to this change the huge
+ positive values -- due to signed->unsigned conversion of the potentially
+ negative result of nghttp2_pack_settings_payload which returns negative
+ values on error -- are not possible. But only because http2.c currently
+ always provides a large enough output buffer and provides H2 SETTINGS
+ IVs which pass the verification logic inside nghttp2. If the
+ verification logic were to change or if http2.c started passing in more
+ IVs without increasing the output buffer size, the overflow could become
+ reachable, and libcurl/curl might start leaking memory contents to
+ servers/proxies...
+
+ Closes #12101
+
+Daniel Stenberg (13 Oct 2023)
+
+- openssl: avoid BN_num_bits() NULL pointer derefs
+
+ Reported-by: icy17 on github
+ Fixes #12099
+ Closes #12100
+
+- wolfssl: require WOLFSSL_SYS_CA_CERTS for loading system CA
+
+ This define is set in wolfssl's options.h file when this function and
+ feature is present. Handles both builds with the feature explicitly
+ disabled and wolfSSL versions before 5.5.2 - which introduced this API
+ call.
+
+ Closes #12108
+
+- tool_urlglob: make multiply() bail out on negative values
+
+ - Does not work correctly with negative values
+ - use __builtin_mul_overflow() on gcc
+
+ Reported-by: Torben Dury
+ Closes #12102
+
+Loïc Yhuel (13 Oct 2023)
+
+- cmake: fix CURL_DISABLE_GETOPTIONS
+
+ - Add CURL_DISABLE_GETOPTIONS to curl_config.h.cmake.
+
+ Prior to this change the option had no effect because it was missing
+ from that file.
+
+ Closes https://github.com/curl/curl/pull/12091
+
+- easy_lock: add a pthread_mutex_t fallback
+
+ This allows to keep the init threadsafe with gcc < 4.9.0 (no C11
+ atomics).
+
+ Closes https://github.com/curl/curl/pull/12090
+
+Viktor Szakats (12 Oct 2023)
+
+- CI: add autotools, out-of-tree, debug build to distro check job
+
+ Add a job that builds curl from a generated source tarball sample, with
+ autotools, out-of-tree, in debug mode.
+
+ Ref: #12085
+ Closes #12088
+
+Daniel Stenberg (12 Oct 2023)
+
+- http: avoid Expect: 100-continue if Upgrade: is used
+
+ Reported-by: Daniel Jelinski
+ Fixes #12022
+ Closes #12062
+
+Jan Alexander Steffens (heftig) (12 Oct 2023)
+
+- docs: use SOURCE_DATE_EPOCH for generated manpages
+
+ This should make builds from Git reproducible.
+
+ Closes #12092
+
+Daniel Stenberg (12 Oct 2023)
+
+- RELEASE-NOTES: synced
+
+ Bumped to 8.4.1
+
+Viktor Szakats (12 Oct 2023)
+
+- cmake: fix `HAVE_H_ERRNO_ASSIGNABLE` detection
+
+ Fix `HAVE_H_ERRNO_ASSIGNABLE` to not run, only compile its test snippet,
+ aligning this with autotools. This fixes an error when doing
+ cross-builds and also actually detects this feature. It affected systems
+ not allowlisted into this, e.g. SerenityOS.
+
+ We used this detection result to enable `HAVE_GETADDRINFO_THREADSAFE`.
+
+ Follow-up to 04a3a377d83fd72c4cf7a96c9cb6d44785e33264 #11979
+ Ref: #12095 (closed in favour of this patch)
+ Ref: #11964 (effort to sync cmake detections with autotools)
+
+ Reported-by: Kartatz on Github
+ Assisted-by: Kartatz on Github
+ Fixes #12093
+ Closes #12094
+
+- build: add `src/.checksrc` to source tarball
+
+ Regression from e5bb88b8f824ed87620bd923552534c83c2a516e #11958
+
+ Bug: https://github.com/curl/curl/pull/11958#issuecomment-1757079071
+ Reported-by: Romain Geissler
+ Fixes #12084
+ Closes #12085
+
Version 8.4.0 (11 Oct 2023)
Daniel Stenberg (11 Oct 2023)
@@ -7118,2428 +10372,3 @@ Daniel Stenberg (30 May 2023)
8.1.2 release
- THANKS: contributors from 8.1.2
-
-- lib1560: verify more scheme guessing
-
- - on 2nd level domains
- - on names without dots
-
- As mentioned in #11161, "imap.com" will be guessed IMAP
-
- Closes #11219
-
-- page-header: minor wording polish in the URL segment
-
- Closes #11217
-
-- page-header: mention curl version and how to figure out current release
-
- Closes #11216
-
-- RELEASE-NOTES: synced
-
-- configure: without pkg-config and no custom path, use -lnghttp2
-
- Reported-by: correctmost on github
- Fixes #11186
- Closes #11210
-
-Stefan Eissing (28 May 2023)
-
-- curl: cache the --trace-time value for a second
-
- - caches HH:MM:SS computed and reuses it for logging during
- the same second.
- - common function for plain log line start formatting
-
- Closes #11211
-
-Kev Jackson (28 May 2023)
-
-- libcurl.m4: remove trailing 'dnl' that causes this to break autoconf
-
- Closes #11212
-
-Stefan Eissing (26 May 2023)
-
-- http3: send EOF indicator early as possible
-
- - ngtcp2 and quiche implementations relied on the DONE_SEND event
- to forward the EOF for uploads to the libraries. This often
- result in a last 0 length EOF data. Tracking the amount of
- data left to upload allows EOF indication earlier.
- - refs #11205 where CloudFlare DoH servers did not like to
- receive the initial upload DATA without EOF and returned
- a 400 Bad Request
-
- Reported-by: Sergey Fionov
- Fixes #11205
- Closes #11207
-
-Daniel Stenberg (26 May 2023)
-
-- scripts/contri*sh: no longer grep -v ' '
-
- Originally these scripts filtered out names that have no space so that
- they better avoid nick names not intended for credits. Such names are
- not too commonly used, plus we now give credit even to those.
-
- Additionally: non-latin names, like Asian, don't have spaces at all so
- they were also filtered out and had to be manually added which made it
- an error-prone operation where Asian names eventually easily fell off by
- mistake.
-
- Closes #11206
-
-- cf-socket: restore Curl_sock_assign_addr()
-
- Regression since it was not private. Also used by msh3.c
-
- Follow-up to 8e85764b7bd7f05f5
- Reported-by: Gisle Vanem
- Fixes #11202
- Closes #11204
-
-- RELEASE-NOTES: synced
-
- Taken down to 8.1.2 now for pending patch release
-
-- libssh: when keyboard-interactive auth fails, try password
-
- The state machine had a mistake in that it would not carry on to that
- next step.
-
- This also adds a verbose output what methods that are available from the
- server and renames the macros that change to the next auth methods to
- try.
-
- Reported-by: 左潇峰
- Fixes #11196
- Closes #11197
-
-Emanuele Torre (25 May 2023)
-
-- configure: fix build with arbitrary CC and LD_LIBRARY_PATH
-
- Since ./configure and processes that inherit its environment variables
- are the only callers of the run-compiler script, we can just save the
- current value of the LD_LIBRARY_PATH and CC variables to another pair of
- environment variables, and make run-compiler a static script that
- simply restores CC and LD_LIBRARY_PATH to the saved value, and before
- running the compiler.
-
- This avoids having to inject the values of the variables in the script,
- possibly causing problems if they contains spaces, quotes, and other
- special characters.
-
- Also add exports in the script just in case LD_LIBRARY_PATH and CC are
- not already in the environment.
-
- follow-up from 471dab2
-
- Closes #11182
-
-Daniel Stenberg (25 May 2023)
-
-- urlapi: remove superfluous host name check
-
- ... as it is checked later more proper.
-
- Closes #11195
-
-Stefan Eissing (25 May 2023)
-
-- http2: fix EOF handling on uploads with auth negotiation
-
- - doing a POST with `--digest` does an override on the initial request
- with `Content-Length: 0`, but the http2 filter was unaware of that
- and expected the originally request body. It did therefore not
- send a final DATA frame with EOF flag to the server.
- - The fix overrides any initial notion of post size when the `done_send`
- event is triggered by the transfer loop, leading to the EOF that
- is necessary.
- - refs #11194. The fault did not happen in testing, as Apache httpd
- never tries to read the request body of the initial request,
- sends the 401 reply and closes the stream. The server used in the
- reported issue however tried to read the EOF and timed out on the
- request.
-
- Reported-by: Aleksander Mazur
- Fixes #11194
- Cloes #11200
-
-Daniel Stenberg (23 May 2023)
-
-- RELEASE-NOTES: synced
-
- bump to 8.2.0
-
-- lib: remove unused functions, make single-use static
-
- Closes #11174
-
-- scripts/singleuse.pl: add more API calls
-
-Christian Hesse (23 May 2023)
-
-- configure: quote the assignments for run-compiler
-
- Building for multilib failed, as the compiler command contains an
- extra argument. That needs quoting.
-
- Regression from b78ca50cb3dda361f9c1
-
- Fixes #11179
- Closes #11180
-
-Daniel Stenberg (23 May 2023)
-
-- misc: fix spelling mistakes
-
- Reported-by: musvaage on github
- Fixes #11171
- Closes #11172
-
-Version 8.1.1 (23 May 2023)
-
-Daniel Stenberg (23 May 2023)
-
-- RELEASE-NOTES: synced
-
- curl 8.1.1
-
-- THANKS: contributors from the 8.1.1 release
-
-Dan Fandrich (22 May 2023)
-
-- docs: fix fuzzing documentation link
-
- Follow-up to 4c712a1b
-
-- CI: add an Alpine build with MUSL
-
- MUSL is another libc implementation which has its own unique issues
- worth testing.
-
- Ref: #11140
- Closes #11178
-
-- runtests: add a missing \n at the end of a log message
-
-correctmost on github (22 May 2023)
-
-- SECURITY-PROCESS.md: link security advisory doc and fix typo
-
- Closes #11177
-
-Daniel Stenberg (22 May 2023)
-
-- TODO: build curl with Windows Unicode support
-
- Closes #7229
-
-- KNOWN_BUGS: hyper memory-leaks
-
- Closes #10803
-
-Stefan Eissing (22 May 2023)
-
-- http/2: unstick uploads
-
- - refs #11157 and #11175 where uploads get stuck or lead to RST streams
- - fixes our h2 send behaviour to continue sending in the nghttp2 session
- as long as it wants to. This will empty our send buffer as long as
- the remote stream/connection window allows.
- - in case the window is exhausted, the data remaining in the send buffer
- will wait for a WINDOW_UPDATE from the server. Which is a socket event
- that engages our transfer loop again
- - the problem in the issue was that we did not exhaust the window, but
- left data in the sendbuffer and no further socket events did happen.
- The server was just waiting for us to send more.
- - relatedly, there was an issue fixed that closing a stream with KEEP_HOLD
- set kept the transfer from shutting down - as it should have - leading
- to a timeout.
-
- Closes #11176
-
-Daniel Stenberg (21 May 2023)
-
-- workflows/macos: add a job using gcc + debug + secure transport
-
-Jay Satiro (21 May 2023)
-
-- lib: fix conversion warnings with gcc on macOS
-
-Daniel Stenberg (21 May 2023)
-
-- sectransp.c: make the code c89 compatible
-
- Follow-up to dd2bb485521c2ec713001b3a
-
- Reported-by: FeignClaims on github
- Fixes #11155
- Closes #11159
-
-Emanuele Torre (21 May 2023)
-
-- Revert "urlapi: respect CURLU_ALLOW_SPACE and CURLU_NO_AUTHORITY for redirect
- s"
-
- This reverts commit df6c2f7b544f1f35f2a3e0be11f345affeb6fe9c.
- (It only keep the test case that checks redirection to an absolute URL
- without hostname and CURLU_NO_AUTHORITY).
-
- I originally wanted to make CURLU_ALLOW_SPACE accept spaces in the
- hostname only because I thought
- curl_url_set(CURLUPART_URL, CURLU_ALLOW_SPACE) was already accepting
- them, and they were only not being accepted in the hostname when
- curl_url_set(CURLUPART_URL) was used for a redirection.
-
- That is not actually the case, urlapi never accepted hostnames with
- spaces, and a hostname with a space in it never makes sense.
- I probably misread the output of my original test when I they were
- normally accepted when using CURLU_ALLOW_SPACE, and not redirecting.
-
- Some other URL parsers seems to allow space in the host part of the URL,
- e.g. both python3's urllib.parse module, and Chromium's javascript URL
- object allow spaces (chromium percent escapes the spaces with %20),
- (they also both ignore TABs, and other whitespace characters), but those
- URLs with spaces in the hostname are useless, neither python3's requests
- module nor Chromium's window.location can actually use them.
-
- There is no reason to add support for URLs with spaces in the host,
- since it was not a inconsistency bug; let's revert that patch before it
- makes it into release. Sorry about that.
-
- I also reverted the extra check for CURLU_NO_AUTHORITY since that does
- not seem to be necessary, CURLU_NO_AUTHORITY already worked for
- redirects.
-
- Closes #11169
-
-Dan Fandrich (20 May 2023)
-
-- runtests: use the correct fd after select
-
- The code was using the wrong fd when determining which runner was ready
- with a response.
-
- Ref: #10818
- Closes #11160
-
-- test425: fix the log directory for the upload
-
- This must be %LOGDIR to let it work with parallel tests.
-
- Ref: #10969
-
-- runtests: handle interrupted reads from IPC pipes
-
- These can be interrupted by signals, especially SIGINT to shut down, and
- must be restarted so the IPC call arrives correctly. If the read just
- returns an error instead, the IPC calling state will go out of sync and
- a proper shutdown won't happen.
-
- Ref: #10818
-
-Stefan Eissing (20 May 2023)
-
-- http2: upload improvements
-
- Make send buffer smaller to have progress and "upload done" reporting
- closer to reality. Fix handling of send "drain" condition to no longer
- trigger once the transfer loop reports it is done sending. Also do not
- trigger the send "drain" on RST streams.
-
- Background:
- - a upload stall was reported in #11157 that timed out
- - test_07_33a reproduces a problem with such a stall if the
- server 404s the request and RSTs the stream.
- - test_07_33b verifies a successful PUT, using the parameters
- from #11157 and checks success
-
- Ref: #11157
- Closes #11165
-
-- http2: increase stream window size to 10 MB
-
- Reported-by: pandada8 on github
-
- Fixes #11162
- Closes #11167
-
-Daniel Stenberg (20 May 2023)
-
-- lib: rename struct 'http_req' to 'httpreq'
-
- Because FreeBSD 14 kidnapped the name.
- Ref: https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=271526
-
- Fixes #11163
- Closes #11164
-
-Viktor Szakats (20 May 2023)
-
-- cmake: avoid `list(PREPEND)` for compatibility
-
- `list(PREPEND)` requires CMake v3.15, our minimum is v3.7.
-
- Ref: https://cmake.org/cmake/help/latest/command/list.html#prepend
-
- Regression from 1e3319a167d2f32d295603167486e9e88af9bb4e
-
- Reported-by: Keitagit-kun on Github
- Fixes #11141
- Closes #11144
-
-Daniel Stenberg (19 May 2023)
-
-- RELEASE-NOTES: synced
-
-Stefan Eissing (19 May 2023)
-
-- ngtcp2: proper handling of uint64_t when adjusting send buffer
-
- Fixes #11149
- Closes #11153
-
-- ngtcp2: fix compiler warning about possible null-deref
-
- - compiler analyzer did not include the call context for this
- static function where the condition had already been checked.
- - eleminating the problem by making stream a call parameter
-
- Fixes #11147
- Closes #11151
-
-Emanuele Torre (19 May 2023)
-
-- docs: document that curl_url_cleanup(NULL) is a safe no-op
-
- This has always been the case, but it was not documented.
-
- The paragraph was copied verbatim from curl_easy_cleanup.3
-
- Closes #11150
-
-Antoine Pitrou (19 May 2023)
-
-- select: avoid returning an error on EINTR from select() or poll()
-
- This was already done for the poll() and select() calls
- made directly from Curl_poll(), but was missed in
- Curl_wait_ms(), which is called when there are no fds
- to wait on.
-
- Fixes #11135
- Closes #11143
-
-Daniel Stenberg (19 May 2023)
-
-- vquic.c: make recvfrom_packets static, avoid compiler warning
-
- warning: no previous prototype for 'recvfrom_packets'
-
- Reported-by: Keitagit-kun on github
- Fixes #11146
- Closes #11148
-
-- urlapi: allow numerical parts in the host name
-
- It can only be an IPv4 address if all parts are all digits and no more than
- four parts, otherwise it is a host name. Even slightly wrong IPv4 will now be
- passed through as a host name.
-
- Regression from 17a15d88467 shipped in 8.1.0
-
- Extended test 1560 accordingly.
-
- Reported-by: Pavel Kalyugin
- Fixes #11129
- Closes #11131
-
-Emilio Cobos Ãlvarez (19 May 2023)
-
-- http2: double http request parser max line length
-
- This works around #11138, by doubling the limit, and should be a
- relatively safe fix.
-
- Ideally the buffer would grow as needed and there would be no need for a
- limit? But that might be follow-up material.
-
- Fixes #11138
- Closes #11139
-
-Emanuele Torre (18 May 2023)
-
-- configure: fix --help alignment
-
- AC_ARG_ENABLE seems to only trim off whitespace from the start and end
- of its help-string argument, while prepending two spaces of indentation
- to all lines.
-
- This means that the two spaces of indentation between the --enable-rtsp
- and the --disable-rtsp line were not removed causing ./configure --help
- to print:
-
- Optional Features:
- [...]
- --enable-rtsp Enable RTSP support
- --disable-rtsp Disable RTSP support
-
- I removed the indentation to fix the issue, now it prints:
-
- Optional Features:
- [...]
- --enable-rtsp Enable RTSP support
- --disable-rtsp Disable RTSP support
-
- The --enable-hsts and --disable-hsts lines had the same problems, and
- have been fixed too.
-
- Closes #11142
-
-Deal(一线çµ) (18 May 2023)
-
-- cmake: repair cross compiling
-
- It cannot *run* code for testing purposes when cross-compiling.
-
- Closes #11130
-
-Daniel Stenberg (18 May 2023)
-
-- configure: generate a script to run the compiler
-
- in the CURL_RUN_IFELSE macro, with LD_LIBRARY_PATH set to the value of
- the configure invoke, and not the value that might be used later,
- intended for the execution of the output the compiler ouputs.
-
- For example when the compiler uses the same library (like libz) that
- configure checks for.
-
- Reported-by: Jonas Bülow
- Fixes #11114
- Closes #11120
-
-Stefan Eissing (18 May 2023)
-
-- cf-socket: completely remove the disabled USE_RECV_BEFORE_SEND_WORKAROUND
-
- Closes #11118
-
-Emanuele Torre (18 May 2023)
-
-- urlapi: respect CURLU_ALLOW_SPACE and CURLU_NO_AUTHORITY for redirects
-
- curl_url_set(uh, CURLUPART_URL, redirurl, flags) was not respecing
- CURLU_ALLOW_SPACE and CURLU_NO_AUTHORITY in the host part of redirurl
- when redirecting to an absolute URL.
-
- Closes #11136
-
-Colin Cross (18 May 2023)
-
-- hostip: move easy_lock.h include above curl_memory.h
-
- Similar to #9561, move easy_lock.h above curl_memory.h to fix building
- against musl libc.
-
- Closes #11140
-
-Hind Montassif (18 May 2023)
-
-- curl_easy_getinfo: clarify on return data types
-
- Closes #11126
-
-Emanuele Torre (18 May 2023)
-
-- checksrc: disallow spaces before labels
-
- Out of 415 labels throughout the code base, 86 of those labels were
- not at the start of the line. Which means labels always at the start of
- the line is the favoured style overall with 329 instances.
-
- Out of the 86 labels not at the start of the line:
- * 75 were indented with the same indentation level of the following line
- * 8 were indented with exactly one space
- * 2 were indented with one fewer indentation level then the following
- line
- * 1 was indented with the indentation level of the following line minus
- three space (probably unintentional)
-
- Co-Authored-By: Viktor Szakats
-
- Closes #11134
-
-Daniel Stenberg (18 May 2023)
-
-- cookie: update the comment on cookie length and size limits
-
- To refer to the proper cookie RFC and the upcoming RFC refresh.
-
- Closes #11127
-
-- url: provide better error message when URLs fail to parse
-
- By providing the URL API error message into the error message.
-
- Ref: #11129
- Closes #11137
-
-- RELEASE-NOTES: synced
-
- bumped to 8.1.1
-
-Jon Rumsey (18 May 2023)
-
-- os400: update chkstrings.c
-
- Compensate changes for recent changes to urldata.h to reclassify
- STRING_AWS_SIGV4.
-
- Fixes #11132
- Closes #11133
-
-Version 8.1.0 (17 May 2023)
-
-Daniel Stenberg (17 May 2023)
-
-- RELEASE-NOTES: synced
-
-- THANKS: contributors from the 8.1.0 release
-
-- hostip: include easy_lock.h before using GLOBAL_INIT_IS_THREADSAFE
-
- Since that header file is the only place that define can be defined.
-
- Reported-by: Marc Deslauriers
-
- Follow-up to 13718030ad4b3209
-
- Closes #11121
-
-Thomas Taylor (16 May 2023)
-
-- aws-sigv4.d: fix region identifier in example
-
- Closes #11117
-
-Philip Heiduck (15 May 2023)
-
-- mlc_config.json: remove this linkcheck CI job config file
-
- Closes #11113
-
-Daniel Silverstone (15 May 2023)
-
-- ssh: Add support for libssh2 read timeout
-
- Hook the new (1.11.0 or newer) libssh2 support for setting a read timeout
- into the SERVER_RESPONSE_TIMEOUT option. With this done, clients can use
- the standard curl response timeout setting to also control the time that
- libssh2 will wait for packets from a slow server. This is necessary to
- enable use of very slow SFTP servers.
-
- Signed-off-by: Daniel Silverstone <daniel.silverstone@codethink.co.uk>
-
- Closes #10965
-
-Osama Albahrani (14 May 2023)
-
-- GIT-INFO: add --with-openssl
-
- Closes #11110
-
-Daniel Stenberg (13 May 2023)
-
-- RELEASE-NOTES: synced
-
-Marcel Raad (13 May 2023)
-
-- md(4|5): don't use deprecated iOS functions
-
- They are marked as deprecated in iOS 13.0, which might result in
- warnings-as-errors.
-
- Also, use `*_MIN_REQUIRED` instead of `*_MIN_ALLOWED`, which seems to
- be what's currently used.
-
- Bug: https://github.com/curl/curl/issues/11098
- Closes https://github.com/curl/curl/pull/11102
-
-- md4: only build when used
-
- Its only usage in curl_ntlm_core.c is guarded by `USE_CURL_NTLM_CORE`,
- so let's use this here too.
-
- Ref: https://github.com/curl/curl/issues/11098
- Closes https://github.com/curl/curl/pull/11102
-
-Vítor Galvão (12 May 2023)
-
-- write-out.d: Use response_code in example
-
- Closes #11107
-
-Shohei Maeda (12 May 2023)
-
-- url: fix null dispname for --connect-to option
-
- Closes #11106
-
-Daniel Stenberg (12 May 2023)
-
-- test2306: verify getting a second response with folded headers
-
- Reproduces the isue #11101 and verifies the fix.
-
- Verifies a17b2a503f
-
-- headers: clear (possibly) lingering pointer in init
-
- The "prevhead" pointer is used for the headers storage but was not
- cleared correctly in init, which made it possible to act up when a
- handle is reused.
-
- Reported-by: Steve Herrell
- Fixes #11101
- Closes #11103
-
-- RELEASE-NOTES: synced
-
-- ngtcp2: use 0.15.0
-
- - nghttp3 0.11.0
- - nghttp2 1.53.0
-
- Adapt to new API calls
-
- Closes #11031
-
-Jay Satiro (10 May 2023)
-
-- openssl: fix indent
-
-Daniel Stenberg (10 May 2023)
-
-- CURLOPT_DNS_CACHE_TIMEOUT.3: fix spelling
-
- Follow-up to 9ed7d56e044f5aa1b29
-
- Closes #11096
-
-- hostip: use time_t for storing oldest DNS entry
-
- Theoretically, the oldest time could overflow an int. In practice that
- won't happen, but let's do this to please analyzers.
-
- Follow-up to 9ed7d56e044f5aa1b2928ccde6245d0
-
- Pointed out by Coverity.
- Closes #11094
-
-- http: free the url before storing a new copy
-
- To avoid a memory-leak.
-
- Reported-by: Hiroki Kurosawa
-
- Closes #11093
-
-- compressed.d: clarify the words on "not notifying headers"
-
- Reported-by: Dylan Anthony
- Fixes #11091
- Closes #11092
-
-- libssh2: free fingerprint better
-
- Reported-by: Wei Chong Tan
- Closes #11088
-
-- CURLOPT_IPRESOLVE.3: clarify that this for host names, not IP addresses
-
- Reported-by: Harry Sintonen
- Closes #11087
-
-- hostip: enforce a maximum DNS cache size independent of timeout value
-
- To reduce the damage an application can cause if using -1 or other
- ridiculous timeout values and letting the cache live long times.
-
- The maximum number of entries in the DNS cache is now totally
- arbitrarily and hard-coded set to 29999.
-
- Closes #11084
-
-- hostip: store dns timeout as 'int'
-
- ... because it set and held as an 'int' elsewhere and can never be
- larger.
-
-- RELEASE-NOTES: synced
-
-- tool_operate: refuse (--data or --form) and --continue-at combo
-
- libcurl assumes that a --continue-at resumption is done to continue an
- upload using the read callback and neither --data nor --form use
- that and thus won't do what the user wants. Whatever the user wants
- with this strange combination.
-
- Add test 426 to verify.
-
- Reported-by: Smackd0wn on github
- Fixes #11081
- Closes #11083
-
-- transfer: refuse POSTFIELDS + RESUME_FROM combo
-
- The code assumes that such a resume is wanting to continue an upload
- using the read callback, and since POSTFIELDS is done without callback
- libcurl will just misbehave.
-
- This combo will make the transfer fail with CURLE_BAD_FUNCTION_ARGUMENT
- with an explanation in the error message.
-
- Reported-by: Smackd0wn on github
- Fixes #11081
- Closes #11083
-
-- ipv4.d/ipv6.d: they are "mutex", not "boolean"
-
- ... which for example means they do not have --no-* versions.
-
- Reported-by: Harry Sintonen
- Fixes #11085
- Closes #11086
-
-- docs/SECURITY-ADVISORY.md: how to write a curl security advisory
-
- Closes #11080
-
-nobedee on github (5 May 2023)
-
-- MANUAL.md: add dict example for looking up a single definition
-
- Closes #11077
-
-Dan Fandrich (5 May 2023)
-
-- runtests: fix -c option when run with valgrind
-
- The curl binary argument wasn't being quoted properly. This seems to
- have broken at some point after quoting was added in commit 606b29fe.
-
- Reported-by: Daniel Stenberg
- Ref: #11073
- Fixes #11074
- Closes #11076
-
-- runtests: support creating more than one runner process
-
- The controller currently only creates and uses one, but more are now
- possible.
-
- Ref: #10818
-
-- runtests: spawn a new process for the test runner
-
- When the -j option is given, a new process is spawned in which the test
- programs are run and from which test servers are started. Only one
- process can be started at once, but this is sufficient to test that the
- infrastructure can isolate those functions in a new task. There should
- be no visible difference between the two modes at the moment.
-
- Ref: #10818
- Closes #11064
-
-- runtests: turn singletest() into a state machine
-
- This allows it to run in a non-blocking manner.
-
- Ref: #10818
-
-- runtests: change runner interface to be asynchronous
-
- Program arguments are marshalled and then written to the end of a pipe
- which is later read from and the arguments unmarshalled before the
- desired function is called normally. The function return values are
- then marshalled and written into another pipe when is later read from
- and unmarshalled before being returned to the caller.
-
- The implementation is currently blocking but can be made non-blocking
- without any changes to the API. This allows calling multiple runners
- without blocking in the future.
-
- Ref: #10818
-
-- runtests: call citest_finishtest in singletest
-
- This is where citest_starttest is called.
-
- Ref: #10818
-
-- runtests: add a runner initialization function
-
- This sets up the runner environment to start running tests.
-
- Ref: #10818
-
-- runtests: remove directory from server filename variables
-
- There will soon be multiple log directories so the paths will no longer
- be static in runtests.pl. Also, get rid of $SERVER2IN which was not
- used.
-
- Ref: #10818
-
-- runtests: reduce package exports after refactoring
-
- Some recent refactoring made these export no longer necessary. Also,
- stop displaying the Unix socket paths at startup since there will soon
- be many of them and they're not that interesting.
-
- Ref: #10818
-
-- runtests: use a function to obtain $LOGDIR for a test
-
- This will no longer be static soon.
-
- Ref: #10818
-
-Jay Satiro (5 May 2023)
-
-- tool_cb_hdr: Fix 'Location:' formatting for early VTE terminals
-
- - Disable hyperlink formatting for the 'Location:' header value in VTE
- 0.48.1 and earlier, since it is buggy in some of those versions.
-
- Prior to this change those terminals may show the location header value
- as gibberish or show it twice.
-
- Ref: https://gist.github.com/egmontkob/eb114294efbcd5adb1944c9f3cb5feda#backw
- ard-compatibility
-
- Fixes https://github.com/curl/curl/issues/10428
- Closes https://github.com/curl/curl/pull/11071
-
-François Michel (3 May 2023)
-
-- quiche: disable pacing while pacing is not actually performed
-
- Closes #11068
-
-Daniel Stenberg (2 May 2023)
-
-- easy_cleanup: require a "good" handle to act
-
- By insisting that the passed in handle is "good" (the magic number is
- intact), this can limit the potential damage if a bad pointer is passed
- in. Like when this function is called twice on the same handle pointer.
-
- Ref: #10964
- Closes #11061
-
-Andreas Falkenhahn (1 May 2023)
-
-- amiga: Fix CA certificate paths for AmiSSL and MorphOS
-
- AmiSSL stores certificates in `AmiSSL:Certs` and MorphOS stores them in
- `MOSSYS:Data/SSL/curl-ca-bundle.crt`.
-
- Closes https://github.com/curl/curl/pull/11059
-
-Daniel Stenberg (30 Apr 2023)
-
-- http2: (void)-mark when we explicitly ignore the return code
-
- When h2_progress_egress() is called. Pointed out by Coverity.
-
- Closes #11057
-
-- checksrc: find bad indentation in conditions without open brace
-
- If the previous line starts with if/while/for AND ends with a closed
- parenthesis and there's an equal number of open and closed parentheses
- on that line, verify that this line is indented $indent more steps, if
- not a cpp line.
-
- Also adjust the fall-out from this fix.
-
- Closes #11054
-
-Diogo Teles Sant'Anna (28 Apr 2023)
-
-- CI: Set minimal permissions on workflow ngtcp2-quictls.yml
-
- Signed-off-by: Diogo Teles Sant'Anna <diogoteles@google.com>
-
- Closes #11055
-
-Dan Fandrich (28 Apr 2023)
-
-- CI: use another glob syntax for matching files on Appveyor
-
- The previous globbing syntax was not matching files recursively in
- directories, so try appending a /* to more closely match the examples at
- https://www.appveyor.com/docs/how-to/filtering-commits/
-
-Daniel Stenberg (28 Apr 2023)
-
-- multi: add multi-ignore logic to multi_socket_action
-
- The multi-ignore logic that was previously applied to
- curl_multi_perform() (#10750) is here applied to the loop within
- curl_multi_socket_action() to make it use the same optimization: most
- handles have the same signal-ignore option state so this drastically
- reduces the number of ignore/unignore calls per libcurl function invoke.
-
- Follow-up to bc90308328afb8
-
- Closes #11045
-
-Stefan Eissing (28 Apr 2023)
-
-- http2: do flow window accounting for cancelled streams
-
- - nghttp2 does not free connection level window flow for
- aborted streams
- - when closing transfers, make sure that any buffered
- response data is "given back" to the flow control window
- - add tests test_02_22 and test_02_23 to reproduce
-
- Closes #11052
-
-- pingpong: fix compiler warning "assigning an enum to unsigned char"
-
- Closes #11050
-
-Daniel Stenberg (28 Apr 2023)
-
-- configure: fix detection of apxs (for httpd)
-
- The condition check was turned the wrong way around!
-
- Closes #11051
-
-Viktor Szakats (28 Apr 2023)
-
-- ci: `-Wno-vla` no longer necessary
-
- We handle this issue in the source now.
-
- Follow-up to b725fe1944b45406676ea3aff333ae3085a848d9
-
- Reviewed-by: Marcel Raad
- Reviewed-by: Daniel Stenberg
- Closes #11048
-
-Marcel Raad (28 Apr 2023)
-
-- tests/http: make curl_setup.h the first include
-
- This is required for the macros there to take effect for system
- libraries. Specifically, including the system libraries first led to
- warnings about `_FILE_OFFSET_BITS` being redefined in curl_config.h on
- the Solaris autobuilds for ws-data.c and ws-pingpong.c.
- Also make the curl includes come first for the other source files here
- for consistency.
-
- Closes https://github.com/curl/curl/pull/11046
-
-Emanuele Torre (27 Apr 2023)
-
-- checksrc: check for spaces before the colon of switch labels
-
- Closes #11047
-
-Daniel Stenberg (27 Apr 2023)
-
-- RELEASE-NOTES: synced
-
-- libssh: tell it to use SFTP non-blocking
-
- Reported-by: Andreas Huebner
- Fixes #11020
- Closes #11039
-
-Stefan Eissing (27 Apr 2023)
-
-- http2: enlarge the connection window
-
- - fixes stalled connections
-
- - Make the connection window large enough, so that there is
- some room left should 99/100 streams be PAUSED by the application
-
- Reported-by: Paweł Wegner
- Fixes #10988
- Closes #11043
-
-Daniel Stenberg (27 Apr 2023)
-
-- checksrc: fix SPACEBEFOREPAREN for conditions starting with "*"
-
- The open paren check wants to warn for spaces before open parenthesis
- for if/while/for but also for any function call. In order to avoid
- catching function pointer declarations, the logic allows a space if the
- first character after the open parenthesis is an asterisk.
-
- I also spotted what we did not include "switch" in the check but we should.
-
- This check is a little lame, but we reduce this problem by not allowing
- that space for if/while/for/switch.
-
- Reported-by: Emanuele Torre
- Closes #11044
-
-- docs: minor polish
-
- - "an HTTP*" (not "a")
- - remove a few contractions
- - remove a spurious "a"
- - reduce use of "I" in texts
-
- Closes #11040
-
-- ws: fix CONT opcode check
-
- Detected by Coverity. Follow-up to 930c00c259
-
- Closes #11037
-
-Dan Fandrich (27 Apr 2023)
-
-- CI: switch the awslc builds to build out-of-tree
-
- This is a common configuration that should be tested to avoid
- regressions. The awsls cmake build was already out-of-tree so the
- automake build now joins it.
-
- Ref: #11006
-
-- tests/http: fix out-of-tree builds
-
- Add both lib/ directories (src & build) to the search path so
- curl_setup.h and its dependencies can be found.
-
- Followup-to acd82c8b
-
- Ref: #11006
- Closes #11036
-
-Daniel Stenberg (27 Apr 2023)
-
-- urlapi: make internal function start with Curl_
-
- Curl_url_set_authority() it is.
-
- Follow-up to acd82c8bfd
-
- Closes #11035
-
-YX Hao (26 Apr 2023)
-
-- cf-socket: turn off IPV6_V6ONLY on Windows if it is supported
-
- IPV6_V6ONLY refs:
- https://en.wikipedia.org/wiki/IPv6#IPv4-mapped_IPv6_addresses
- https://github.com/golang/go/blob/master/src/net/ipsock_posix.go
- https://en.wikipedia.org/wiki/Unix-like
- https://learn.microsoft.com/en-us/windows/win32/winsock/ipproto-ipv6-socket-o
- ptions
-
- default value refs:
- https://datatracker.ietf.org/doc/html/rfc3493#section-5.3
- https://www.kernel.org/doc/html/latest/networking/ip-sysctl.html#proc-sys-net
- -ipv6-variables
-
- Closes #10975
-
-Daniel Stenberg (26 Apr 2023)
-
-- urldata: shrink *select_bits int => unsigned char
-
- - dselect_bits
- - cselect_bits
-
- ... are using less than 8 bits. Changed types and moved them towards
- the end of the structs to fit better.
-
- Closes #11025
-
-Stefan Eissing (26 Apr 2023)
-
-- tests/http: more tests with specific clients
-
- - Makefile support for building test specific clients in tests/http/clients
- - auto-make of clients when invoking pytest
- - added test_09_02 for server PUSH_PROMISEs using clients/h2-serverpush
- - added test_02_21 for lib based downloads and pausing/unpausing transfers
-
- curl url parser:
- - added internal method `curl_url_set_authority()` for setting the
- authority part of a url (used for PUSH_PROMISE)
-
- http2:
- - made logging of PUSH_PROMISE handling nicer
-
- Placing python test requirements in requirements.txt files
- - separate files to base test suite and http tests since use
- and module lists differ
- - using the files in the gh workflows
-
- websocket test cases, fixes for we and bufq
- - bufq: account for spare chunks in space calculation
- - bufq: reset chunks that are skipped empty
- - ws: correctly encode frames with 126 bytes payload
- - ws: update frame meta information on first call of collect
- callback that fills user buffer
- - test client ws-data: some test/reporting improvements
-
- Closes #11006
-
-Jay Satiro (26 Apr 2023)
-
-- libssh2: fix crash in keyboard callback
-
- - Always set the libssh2 'abstract' user-pointer to the libcurl easy
- handle associated with the ssh session, so it is always passed to the
- ssh keyboard callback.
-
- Prior to this change and since 8b5f100 (precedes curl 8.0.0), if libcurl
- was built without CURL_DEBUG then it could crash during the ssh auth
- phase due to a null dereference in the ssh keyboard callback.
-
- Reported-by: Andreas Falkenhahn
-
- Fixes https://github.com/curl/curl/pull/11024
- Closes https://github.com/curl/curl/pull/11026
-
-Daniel Stenberg (26 Apr 2023)
-
-- docs: clarify that more backends have HTTPS proxy support
-
- Closes #11033
-
-- KNOWN_BUGS: remove two not-bugs
-
- - 11.7 signal-based resolver timeouts
-
- Not considered a bug anymore but just implementation details. People
- should avoid using timeouts with the synchronous name resolver.
-
- - 11.16 libcurl uses renames instead of locking for atomic operations
-
- Not a bug, just a description of how it works
-
- Closes #11032
-
-Harry Sintonen (26 Apr 2023)
-
-- hostip: add locks around use of global buffer for alarm()
-
- When building with the sync name resolver and timeout ability we now
- require thread-safety to be present to enable it.
-
- Closes #11030
-
-Daniel Stenberg (26 Apr 2023)
-
-- curl_path: bring back support for SFTP path ending in /~
-
- libcurl used to do a directory listing for this case (even though the
- documentation says a URL needs to end in a slash for this), but
- 4e2b52b5f7a3 modified the behavior.
-
- This change brings back a directory listing for SFTP paths that are
- specified exactly as /~ in the URL.
-
- Reported-by: Pavel Mayorov
- Fixes #11001
- Closes #11023
-
-Emanuele Torre (26 Apr 2023)
-
-- docs/libcurl/curl_*escape.3: rename "url" argument to "input"/"string"
-
- Also reword the DESCRIPTION section to mention "input"/"string" argument
- in bold.
-
- Closes #11027
-
-- docs/libcurl: minor cleanups
-
- I was reading curl_unescape(3) and I noticed that there was an extra
- space after the open parenthesis in the SYNOPSIS; I removed the extra
- space.
-
- I also ran a few grep -r commands to find and remove extra spaces
- after '(' in other files, and to find and replace uses of `T*' instead
- of `T *'. Some of the instances of `T*` where unnecessary casts that I
- removed.
-
- I also fixed a comment that was misaligned in CURLMOPT_SOCKETFUNCTION.3.
-
- And I fixed some formatting inconsistencies: in curl_unescape(3), all
- function parameter were mentioned with bold text except length, that was
- mentioned as 'length'; and, in curl_easy_unescape(3), all parameters
- were mentioned in bold text except url that was italicised. Now they are
- all mentioned in bold.
- Documentation is not very consistent in how function parameter are
- formatted: many pages italicise them, and others display them in bold
- text; but I think it makes sense to at least be consistent with
- formatting within the same page.
-
- Closes #11027
-
-Daniel Stenberg (26 Apr 2023)
-
-- man pages: simplify the .TH sections
-
- - remove the version numbers
- - simplify the texts
-
- The date and version number will be put there for releases when maketgz
- runs the updatemanpages.pl script.
-
- Closes #11029
-
-- hostcheck: fix host name wildcard checking
-
- The leftmost "label" of the host name can now only match against single
- '*'. Like the browsers have worked for a long time.
-
- - extended unit test 1397 for this
- - move some SOURCE variables from unit/Makefile.am to unit/Makefile.inc
-
- Reported-by: Hiroki Kurosawa
- Closes #11018
-
-Dan Fandrich (25 Apr 2023)
-
-- smbserver: remove temporary files before exit
-
- Each execution of test 1451 would leave a file in /tmp before. Since
- Windows can't delete a file while it's open, all the temporary file
- names are stored and deleted on exit.
-
- Closes #10990
-
-Stefan Eissing (25 Apr 2023)
-
-- Websocket en-/decoding
-
- - state is fully kept at connection, since curl_ws_send() and
- curl_ws_rec() have lifetime beyond usual transfers
- - no more limit on frame sizes
-
- Reported-by: simplerobot on github
- Fixes #10962
- Closes #10999
-
-Patrick Monnerat (25 Apr 2023)
-
-- urldata: copy CURLOPT_AWS_SIGV4 value on handle duplication
-
- Prior to this change STRING_AWS_SIGV4 (CURLOPT_AWS_SIGV4) was wrongly
- marked as binary data that could not be duplicated.
-
- Without this fix, this option's value is not copied upon calling
- curl_easy_duphandle().
-
- Closes https://github.com/curl/curl/pull/11021
-
-Stefan Eissing (25 Apr 2023)
-
-- http3: expire unpaused transfers in all HTTP/3 backends
-
- Closes #11005
-
-- http2: always EXPIRE_RUN_NOW unpaused http/2 transfers
-
- - just increasing the http/2 flow window does not necessarily
- make a server send new data. It may already have exhausted
- the window before
-
- Closes #11005
-
-- http2: pass `stream` to http2_handle_stream_close to avoid NULL checks
-
- Closes #11005
-
-- h2/h3: replace `state.drain` counter with `state.dselect_bits`
-
- - `drain` was used by http/2 and http/3 implementations to indicate
- that the transfer requires send/recv independant from its socket
- poll state. Intended as a counter, it was used as bool flag only.
- - a similar mechanism exists on `connectdata->cselect_bits` where
- specific protocols can indicate something similar, only for the
- whole connection.
- - `cselect_bits` are cleard in transfer.c on use and, importantly,
- also set when the transfer loop expended its `maxloops` tries.
- `drain` was not cleared by transfer and the http2/3 implementations
- had to take care of that.
- - `dselect_bits` is cleared *and* set by the transfer loop. http2/3
- does no longer clear it, only set when new events happen.
-
- This change unifies the handling of socket poll overrides, extending
- `cselect_bits` by a easy handle specific value and a common treatment in
- transfers.
-
- Closes #11005
-
-Daniel Stenberg (25 Apr 2023)
-
-- socketpair: verify with a random value
-
- ... instead of using the curl time struct, since it would use a few
- uninitialized bytes and the sanitizers would complain. This is a neater
- approach I think.
-
- Reported-by: Boris Kuschel
- Fixes #10993
- Closes #11015
-
-Stefan Eissing (25 Apr 2023)
-
-- HTTP3: document the ngtcp2/nghttp3 versions to use for building curl
-
- - refs #11011 to clarify this for people building curl themselves
-
- Closes #11019
-
-Daniel Stenberg (25 Apr 2023)
-
-- lib: unify the upload/method handling
-
- By making sure we set state.upload based on the set.method value and not
- independently as set.upload, we reduce confusion and mixup risks, both
- internally and externally.
-
- Closes #11017
-
-- RELEASE-NOTES: synced
-
-Dan Fandrich (24 Apr 2023)
-
-- CI: don't run CI jobs if only another CI was changed
-
- A few paths were missed in the last commit, as well as a job added since
- then.
-
- Followup-to 395b9175
-
-- CI: adjust labeler match patterns
-
-- runtests: support buffering log messages in runner & servers
-
- Log messages generated with logmsg can now be buffered and returned from
- the runner as a return value. This will be needed with parallel testing
- to allow all messages for one test to be displayed together instead of
- interspersed with messages of multiple tests. Buffering can be disabled
- by setting a logging callback function with setlogfunc, which is
- currently being done to preserve existing logging behaviour for now.
-
- Some additional output is generated in verbose and debugprotocol modes,
- which don't always use logmsg. These modes also impact some servers
- which generate extra messages. No attempt is made to buffer everything
- if these modes are enabled.
-
- Ref: #10818
- Closes #11016
-
-- runtests: more consistently use logmsg in server control code
-
- Also, display an error when sshversioninfo returns one.
-
- Ref: #10818
-
-- runtests: create runner functions for clearlocks and stopservers
-
- runtests.pl now uses runner for all server actions beyond the initial
- variable configuration.
-
- Ref: #10818
-
-- runtests: tightened servers package exports
-
- The defaults are intended for runtests.pl, whereas runner.pm needs to
- explicitly specify them.
-
-- runtests: display logs on server failure in singletest()
-
- This is closer to the place where logs are displayed on test failure.
- Also, only display these logs if -p is given, which is the same flag
- that controls display of test failure logs. Some server log files
- need to be deleted later so that they stay around long enough to be
- displayed on failure.
-
- Ref: #10818
-
-- runtests: turn a print into a logmsg
-
- Also enable another couple of useful messages in verbose mode.
-
- Ref: #10818
-
-Daniel Stenberg (24 Apr 2023)
-
-- http: store the password in the correct variable
-
- Typo from fc2f1e547a4a, detected by Coverity (because there's dead code
- due to this).
-
- Closes #11002
-
-Stefan Eissing (24 Apr 2023)
-
-- HTTP3/quiche: terminate h1 response header when no body is sent
-
- - fixes a failure in test2501 where a response without body was missing
- the final empty line
-
- Closes #11003
-
-Dan Fandrich (22 Apr 2023)
-
-- runtests: move showdiff into runtests.pl
-
- It's not used anywhere else.
-
-- devtest: add a new script for testing the test harness
-
- This is currently useful for starting a test server on its own without
- an associated test, which can be used for interactive curl testing or
- for validating parts of the test harness itself. More commands can be
- added to perform additional functions in the future.
-
- Ref: #10818
- Closes #11008
-
-- runtests: refactor the main test loop into two
-
- The test loop now has an initial loop that first runs through all
- possible tests to build a set of those to attempt on this run based on
- features and keywords and only then goes through that new list to run
- them. This actually makes it three loops through all tests cases, as
- there is an existing loop that gathers possible test numbers from the
- test files on disk.
-
- This has two minor effects on the output: all the tests that will be
- skipped are displayed at the start (instead of being interspersed with
- other tests) and the -l option no longer shows a count of tests at the
- end or a (misleading) statement that tests have run successfully. The
- skipped tests are also omitted from the test results sent to AppVeyor
- and Azure in CI builds.
-
- Another effect is a reduction in the amount of work considered part of
- the "Test definition reading and preparation time" reported with -r
- making those figures slightly lower than before.
-
- Ref: #10818
-
-- runtests: track only the current test timings in runner.pm
-
- This avoids passing these data through through global variables, which
- soon won't be possible.
-
- Ref: #10818
-
-- runtests: skip test preprocessing when doing -l
-
- This speeds up the output tremendously by avoiding unnecessary work.
-
-- runtests: simplify value returned regarding use of valgrind
-
- As a side effect this will now also show in verbose mode that valgrind
- is being skipped on tests that explicitly disable it, such as 600.
-
- Ref: #10818
-
-- runtests: fix quoting in Appveyor and Azure test integration
-
- Test 1442's name was not quoted correctly so wasn't registered in
- Appveyor and it had the wrong name in Azure. The JSON string quotes were
- also invalid, even though both servers happened to accept it regardless.
-
- Closes #11010
-
-Daniel Stenberg (19 Apr 2023)
-
-- RELEASE-NOTES: synced
-
-Dan Fandrich (18 Apr 2023)
-
-- runtests: spread out the port numbers used by servers
-
- The server ports are chosen randomly for each server, but the random
- ranges chosen were inconsistently-sized and overlapping. Now, they are
- spread out more so at least the first random port chosen for each server
- is guaranteed to not also be chosen by another server. The starting port
- numbers are also raised to put them in the Ephemeral Port range—not the
- range defined by RFC 6335 but the one used by Linux, which starts lower
- and gives us more room to work with.
-
- Reported-by: Daniel Stenberg
-
-- runtests: fix problems on <killserver> failure
-
- The verify time must be set in this case, like all cases. An error
- message needs to be displayed as well.
-
-- runtests: fix perl warning when <tool> is wrong
-
-- runtests: don't try to stop stunnel before trying again
-
- Calling stopserver() before retrying stunnel due to an error would stop
- the dependent server (such as HTTP) meaning stunnel would have nothing
- to talk to when it came up. Don't try to force a stop when it didn't
- actually start. Also, don't mark the server as bad for future use when
- it starts up on a retry.
-
- Reported-by: eaglegai at github
- Tested-by: eaglegai at github
- Fixes #10976
-
-- runtests: don't accidentally randomly choose the same port
-
- If a server couldn't be started on a port, a new one is randomly chosen
- and the server is tried again. Avoid accidentally using a
- randomly-chosen 0 port offset by adding 1 to the random number.
-
- Found-by: Daniel Stenberg
-
-- runtests: don't attempt to use a port we know is in use
-
- This reduces the startup time when there is a known conflict on the
- random port chosen for a server. This was already done for stunnel, but
- now it's done for all servers.
-
-- http-server: fix server name in a log message
-
- This changed when the file was renamed in commit cbf57176
-
-- runtests: refactor into more packages
-
- testutil.pm now contains a few miscellaneous functions that are used in
- several places but have no better place to live. subvariables moves to
- servers.pm since most variables that it substitutes relate to servers,
- so this is the most appropriate place. Rename a few functions for better
- naming consistency.
-
- Ref: #10818
- Closes #10995
-
-- runtests: call timestampskippedevents() in singletest
-
- ..rather than by the runner
-
-- runtests: assume a newer Valgrind by default
-
- The tests for an older Valgrind version should probably just be deleted,
- given that they're testing for an 18-year-old version.
-
-- runtests: refactor test runner code into runner.pm
-
- This is code that is directly responsible for running a single test.
- This will eventually run in a separate process as part of the parallel
- testing project.
-
- Ref: #10818
-
-- runtests: skip unneeded work if test won't be running
-
- This speeds up tests by avoiding unnecessary processing.
-
- Ref: #10818
-
-- runtests: factor out singletest_postcheck
-
- This will eventually need to be part of the test runner.
-
- Ref: #10818
-
-- test303: kill server after test
-
- Otherwise, an HTTP test closely following this one with a tight time
- constraint (e.g. 672) could fail because the test server stays sitting
- with the wait command for a while.
-
-Patrick Monnerat (18 Apr 2023)
-
-- OS400: provide ILE/RPG usage examples
-
- Closes https://github.com/curl/curl/pull/10994
-
-- OS400: improve vararg emulation
-
- - Use V7R4 RPG procedure overloading to improve vararg emulation.
-
- From OS400 V7R4 and above, ILE/RPG implements a limited procedure
- overloading feature that can be used to improve curl's typed
- implementation of varargs procedures. This commit applies it to
- curl_easy_setopt(), curl_multi_setopt(), curl_share_setopt() and
- curl_easy_getinfo().
-
- Closes https://github.com/curl/curl/pull/10994
-
-- OS400: fix and complete ILE/RPG binding
-
- - Fix wrong definitions of CURL_ZERO_TERNINATED, curl_mime_data() and
- curl_mime_data_ccsid().
-
- - Add recent definitions, in particular blob, header API and WebSockets
- API.
-
- - Support for CURLVERSION_ELEVENTH.
-
- - New functions for EBCDIC support.
-
- Reflect these changes in README.OS400.
-
- Closes https://github.com/curl/curl/pull/10994
-
-- OS400: implement EBCDIC support for recent features
-
- - Support CURLVERSION_ELEVENTH.
-
- - New function curl_url_strerror_ccsid().
-
- - curl_easy_setopt_ccsid() supports blobs and 3 recent string options.
-
- - New function curl_easy_header_ccsid().
-
- - New generic latin1<-->ccsid conversion functions curl_from_ccsid() and
- curl_to_ccsid() for user convenience.
-
- - README.OS400 updated accordingly.
-
- - Removed a leftover QsoSSL support identifier.
-
- Closes https://github.com/curl/curl/pull/10994
-
-- OS400: rework build scripts
-
- - Rename shell function "system" to "CLcommand" to avoid confusion with
- built-in command.
-
- - Reformat scripts. Fix some indentations. Avoid lines > 80 characters
- where possible.
-
- - Support ASCII runtime development files in a user-defined directory
- path.
-
- - FIX SONAME detection.
-
- - Drop form API test program compilation (does not exist anymore).
-
- Closes https://github.com/curl/curl/pull/10994
-
-Sevan Janiyan (18 Apr 2023)
-
-- tests/sshserver.pl: Define AddressFamily earlier
-
- As the comment states "Address family must be specified before ListenAddress"
- , otherwise the tests fail to run
- `"failed starting SSH server" 52 times (582, 583, 600, 601, 602, 603, 604, 60
- 5, 606 and 43 more)`
-
- Closes #10983
-
-Stefan Eissing (18 Apr 2023)
-
-- quiche: Enable IDLE egress handling
-
- Follow-up to 544abeea which added the handling but wrongly left it
- commented out.
-
- Closes https://github.com/curl/curl/pull/11000
-
-Daniel Stenberg (18 Apr 2023)
-
-- docs/examples/protofeats.c: Outputs all protocols and features
-
- Showing off one way to get to char pointer arrays of info returned by
- curl_version_info()
-
- Closes #10991
-
-- tests/keywords.pl: remove
-
- This script does not work since the introduction of the test
- preprocessing. If we need this functionality, it probably needs to be
- moved into the runtests tool or similar.
-
- Reported-by: Dan Fandrich
- Fixes #10895
- Closes #10987
-
-Stefan Eissing (17 Apr 2023)
-
-- http2: support HTTP/2 to forward proxies, non-tunneling
-
- - with `--proxy-http2` allow h2 ALPN negotiation to
- forward proxies
- - applies to http: requests against a https: proxy only,
- as https: requests will auto-tunnel
- - adding a HTTP/1 request parser in http1.c
- - removed h2h3.c
- - using new request parser in nghttp2 and all h3 backends
- - adding test 2603 for request parser
- - adding h2 proxy test cases to test_10_*
-
- scorecard.py: request scoring accidentally always run curl
- with '-v'. Removed that, expect double numbers.
-
- labeller: added http1.* and h2-proxy sources to detection
-
- Closes #10967
-
-Daniel Stenberg (17 Apr 2023)
-
-- curl_easy_unescape.3: rename the argument
-
- and highlight it appropriately in the text.
-
- Closes #10979
-
-Viktor Szakats (17 Apr 2023)
-
-- autotools: sync up clang picky warnings with cmake
-
- Bringing missing options over from CMake.
-
- Move around existing `-Wno-pointer-bool-conversion` option to come
- _after_ `-Wconversion`.
-
- Reviewed-by: Marcel Raad
- Closes #10974
-
-Daniel Stenberg (17 Apr 2023)
-
-- tests/libtest/lib1900.c: remove
-
- This file was left behind when the rest of the test was previously removed.
-
- Follow-up to e50a877df74f
-
-- src/tool_operhlp.c: fix value stored to 'uerr' is never read
-
- Ref: https://github.com/curl/curl/pull/10974#issuecomment-1510461343
- Reported-by: Viktor Szakats
- Closes #10982
-
-Viktor Szakats (16 Apr 2023)
-
-- cmake: speed up and extend picky clang/gcc options
-
- Extend existing picky compiler options with ones missing compared to
- autotools builds. Also sync options between clang and gcc.
-
- Redesign the way we enable these options to avoid the slow option
- detection almost completely.
-
- This reduces the number of detections from 35 to zero for clang and
- 3 for gcc, even after adding a bunch of new options.
-
- clang 3.0 (2011-11-29) and gcc 2.95 (1999-07-31) now required.
-
- Also show enabled picky options.
-
- Ref: https://github.com/libssh2/libssh2/pull/952
-
- Reviewed-by: Daniel Stenberg
- Closes #10973
-
-Andreas Falkenhahn (16 Apr 2023)
-
-- nbtlm: use semicolons instead of commas for (void) args
-
- Closes #10978
-
-Daniel Stenberg (15 Apr 2023)
-
-- multi: free up more data earleier in DONE
-
- Before checking for more users of the connection and possibly bailing
- out.
-
- Fixes #10971
- Reported-by: Paweł Wegner
- Closes #10972
-
-- RELEASE-NOTES: synced
-
-- curl: do NOT append file name to path for upload when there's a query
-
- Added test 425 to verify.
-
- Reported-by: Dirk Rosenkranz
- Bug: https://curl.se/mail/archive-2023-04/0008.html
- Closes #10969
-
-- libcurl-thread.3: improved name resolver wording
-
- And make better .SH sections
-
- Closes #10966
-
-Colman Mbuya (14 Apr 2023)
-
-- CURLOPT_PROXY_SSL_VERIFYPEER.3: fix minor grammar mistake
-
- Closes #10968
-
-Daniel Stenberg (14 Apr 2023)
-
-- curl: add --proxy-http2
-
- For trying HTTP/2 with an HTTPS proxy.
-
- Closes #10926
-
-- KNOWN_BUGS: remove fixed or outdated issues, move non-bugs
-
- - remove h3 issues believed to be fixed
-
- - make the flaky CI issue be generic and not Windows specific
-
- - "TLS session cache does not work with TFO" now documented
-
- This is now a documented restriction and not a bug. TFO in general is
- rarely used and has other problems, making it a low-priotity thing to
- work on.
-
- - remove "Renegotiate from server may cause hang for OpenSSL backend"
-
- This is an OpenSSL issue, not a curl one. Even if it taints curl.
-
- - rm "make distclean loops forever"
-
- - rm "configure finding libs in wrong directory"
-
- Added a section to docs/INSTALL.md about it.
-
- - "A shared connection cache is not thread-safe"
-
- Moved over to TODO and expanded for other sharing improvements we
- could do
-
- - rm "CURLOPT_OPENSOCKETPAIRFUNCTION is missing"
-
- - rm "Blocking socket operations in non-blocking API"
-
- Already listed as a TODO
-
- - rm "curl compiled on OSX 10.13 failed to run on OSX 10.10"
-
- Water under the bridge. No one cares about this anymore.
-
- - rm "build on Linux links libcurl to libdl"
-
- Verified to not be true (anymore).
-
- - rm "libpsl is not supported"
-
- The cmake build supports it since cafb356e19cda22
-
- Closes #10963
-
-- url: fix PVS nits
-
- - expression 'hostptr' is always true
- - a part of conditional expression is always true: proxypasswd
- - expression 'proxyuser' is always true
- - avoid multiple Curl_now() calls in allocate_conn
-
- Ref: #10929
- Closes #10959
-
-- bufq: simplify since expression is always true
-
- The check for 'len' is already done so it will remain true until
- updated. Pointed out by PVS.
-
- Ref: #10929
- Closes #10958
-
-- hash: fix assigning same value
-
- Pointed out by PVS
-
- Ref: #10929
- Closes #10956
-
-- cookie: address PVS nits
-
- - avoid assigning the same value again
- - remove superfluous check of co->domain
- - reduce variable scope for namep/valuep
-
- Ref: #10929
- Closes #10954
-
-Stefan Eissing (14 Apr 2023)
-
-- cf-socket: Disable socket receive buffer by default
-
- - Disable socket receive buffer unless USE_RECV_BEFORE_SEND_WORKAROUND
- is in place.
-
- While we would like to use the receive buffer, we have stalls in
- parallel transfers where not all buffered data is consumed and no socket
- events happen.
-
- Note USE_RECV_BEFORE_SEND_WORKAROUND is a Windows sockets workaround
- that has been disabled by default since b4b6e4f1, due to other bugs.
-
- Closes https://github.com/curl/curl/pull/10961
-
-- cf-h2-proxy: fix processing ingress to stop too early
-
- - progress ingress stopped too early, causing data
- from the underlying filters to not be processed and
- report that no tunnel data was available
- - this lead to "hangers" where no socket activity was
- seen but data rested in buffers
-
- Closes #10952
-
-- http3: check stream_ctx more thoroughly in all backends
-
- - callbacks and filter methods might be invoked at unexpected
- times, e.g. when the transfer's stream_ctx has not been initialized
- yet or, more likely, has already been taken down.
- - check for existance of stream_ctx in such places and return
- an error or silently succeed the call.
-
- Closes #10951
-
-Daniel Stenberg (13 Apr 2023)
-
-- ftp: fix 'portsock' variable was assigned the same value
-
- Pointed out by PVS
-
- Ref: #10929
- Closes #10955
-
-- ftp: remove dead code
-
- This condition can never be true here since it is handled already 28
- lines above.
-
- Pointed out by PVS.
-
- Ref: #10929
- Closes #10957
-
-- cf-h1-proxy: skip an extra NULL assign
-
- and use Curl_safefree() once to save another NULL assign. Found by PVS.
-
- Ref. #10929
- Closes #10953
-
-Philip Heiduck (13 Apr 2023)
-
-- GHA: suppress git clone output
-
- Follow-up: https://github.com/curl/curl/commit/8203aa6ed405ec832d2c62f18dfda2
- 93f89a23f9
-
- Closes #10949
-
-Stefan Eissing (13 Apr 2023)
-
-- cf-socket: remove dead code discovered by PVS
-
- Closes #10960
-
-Daniel Stenberg (13 Apr 2023)
-
-- http: skip a double NULL assign
-
- and also use a local variable to shorten the long names and increase
- readability in the function. Pointed out by PVS.
-
- Ref: #10929
- Closes #10950
-
-- mime: skip NULL assigns after Curl_safefree()
-
- Pointed out by PVS.
-
- Ref: #10929
- Closes #10947
-
-- rtsp: skip NULL assigns after Curl_safefree()
-
- ... since this is a macro that assigns NULL itself. Pointed out by PVS.
-
- Ref: #10929
- Closes #10946
-
-- smb: remove double assign
-
- The same value is assigned the same value already a few lines above.
- Pointed out by PVS.
-
- Ref: #10929
- Closes #10945
-
-- transfer: skip extra assign
-
- The 'result' variable already contains CURLE_OK at this point, no use in
- setting it again. Pointed out by PVS.
-
- Ref: #10929
- Closes #10944
-
-- urlapi: skip a pointless assign
-
- It stores a null byte after already having confirmed there is a null
- byte there. Detected by PVS.
-
- Ref: #10929
- Closes #10943
-
-Philip Heiduck (13 Apr 2023)
-
-- GHA: suppress git clone output
-
- Closes #10939
-
-Stefan Eissing (13 Apr 2023)
-
-- tests: make test_12_01 a bit more forgiving on connection counts
-
-- cf-socket: add socket recv buffering for most tcp cases
-
- - use bufq as recv buffer, also for Windows pre-receive handling
- - catch small reads followed by larger ones in a single socket
- call. A common pattern on TLS connections.
-
- Closes #10787
-
-Daniel Stenberg (13 Apr 2023)
-
-- urlapi: cleanups
-
- - move host checks together
- - simplify the scheme parser loop and the end of host name parser
- - avoid itermediate buffer storing in multiple places
- - reduce scope for several variables
- - skip the Curl_dyn_tail() call for speed
- - detect IPv6 earlier and skip extra checks for such hosts
- - normalize directly in dynbuf instead of itermediate buffer
- - split out the IPv6 parser into its own funciton
- - call the IPv6 parser directly for ipv6 addresses
- - remove (unused) special treatment of % in host names
- - junkscan() once in the beginning instead of scattered
- - make junkscan return error code
- - remove unused query management from dedotdotify()
- - make Curl_parse_login_details use memchr
- - more use of memchr() instead of strchr() and less strlen() calls
- - make junkscan check and return the URL length
-
- An optimized build runs one of my benchmark URL parsing programs ~41%
- faster using this branch. (compared against the shipped 7.88.1 library
- in Debian)
-
- Closes #10935
-
-Josh McCullough (13 Apr 2023)
-
-- http2: fix typo in infof() call
-
- Closes #10940
-
-Daniel Stenberg (12 Apr 2023)
-
-- noproxy: pointer to local array 'hostip' is stored outside scope
-
- Ref: #10929
- Closes #10933
-
-Stefan Eissing (12 Apr 2023)
-
-- connect: fix https connection setup to treat ssl_mode correctly
-
- - for HTTPS protocol, a disabled ssl should never be acceptables.
-
- Closes #10934
-
-Douglas R. Reno (12 Apr 2023)
-
-- CMakeLists.txt: fix typo for Haiku detection
-
- Closes #10937
-
-Dan Fandrich (11 Apr 2023)
-
-- pathhelp: use the cached $use_cygpath when available
-
-- runtests: eliminate unneeded variable
-
-- runtests: make the # of server start attempts a constant
-
-- runtests: on startup failure call displaylogs only in serverfortest
-
- This reduces the number of calls spread throughout the code.
-
- Ref: #10818
- Closes #10919
-
-- runtests: return an error code with startservers()
-
- The code indicates the kind of failure encountered in starting a server,
- which can be used by the caller to tailor the user experience.
-
- Ref: #10818
-
-- runtests: abort early if runpingpongserver is given a bad server type
-
-- runtests: don't use the SMB server verification time as reference
-
- %FTPTIME2 and %FTPTIME3 should be set by the FTP server only, for
- consistency.
-
-- tests: factor out the test server management code
-
- This now lives in servers.pm with some configuration variables moved to
- globalconfig.pm
-
- Ref: #10818
-
-- runtests: remove an inappropriate use of runclientoutput
-
- This function is intended for running client code, not servers.
-
-- runtests: only add $LIBDIR to the path for checktestcmd
-
- Since checkcmd is for finding servers, there will never be anything in
- this directory of interest to them.
-
- Ref: #10818
-
-- tests: log sshserver.pl messages to a file
-
- The logmsg messages were thrown away before, so they are now available
- for debugging.
-
-- runtests: also show DISABLED tests with -l
-
- Other reasons for skipping tests are ignored for -l, so being explicitly
- disabled should be too.
-
-- runtests: move the UNIX sockets into $PIDDIR
-
- These were missed when the other server files were moved there.
-
- Follow-up to 70d2fca2
-
- Ref: #10818
-
-- tests: tighten up perl exports
-
- This reduces namespace pollution a little.
-
- Ref: #10818
-
-- tests: turn perl modules into full packages
-
- This helps enforce more modularization and encapsulation. Enable and fix
- warnings on a few packages. Also, rename ftp.pm to processhelp.pm since
- there's really nothing ftp-specific in it.
-
- Ref: #10818
-
-Daniel Stenberg (11 Apr 2023)
-
-- multi: remove a few superfluous assigns
-
- PVS found these "The 'rc' variable was assigned the same value." cases.
-
- Ref: #10929
- Closes #10932
-
-- schannel: add clarifying comment
-
- Explaining how the PVS warning in #10929 is wrong: Dereferencing of the
- null pointer 'backend->cred' might take place.
-
- Closes #10931
-
-- cookie: clarify that init with data set to NULL reads no file
-
- ... and make Curl_cookie_add() require 'data' being set proper with an
- assert.
-
- The function has not worked with a NULL data for quite some time so this
- just corrects the code and comment.
-
- This is a different take than the proposed fixed in #10927
-
- Reported-by: Kvarec Lezki
- Ref: #10929
- Closes #10930
-
-Kvarec Lezki (11 Apr 2023)
-
-- vtls: remove int typecast for sizeof()
-
- V220 Suspicious sequence of types castings: memsize -> 32-bit integer ->
- memsize. The value being cast: 'sizeof
- (buf->data)'. curl\lib\vtls\vtls.c 2025
-
- https://pvs-studio.com/en/docs/warnings/v220/
-
- Closes #10928
-
-Stefan Eissing (11 Apr 2023)
-
-- http2: fix copynpaste error reported by coverity
-
- - move all code handling HTTP/2 frames for a particular
- stream into a separate function to keep from confusing
- the call `data` with the stream `data`.
-
- Closes #10924
-
-Dan Fandrich (11 Apr 2023)
-
-- tests: log a too-long Unix socket path in sws and socksd
-
- Ref: #10919
-
-Daniel Stenberg (11 Apr 2023)
-
-- gen.pl: error on duplicated See-Also fields
-
- Updated http2.d accordingly.
-
- Closes #10925
-
-- http2: avoid possible null pointer dereference
-
- Reported-by: Dan Fandrich
- Fixes #10920
- Closes #10923
-
-- lib1560: verify that more bad host names are rejected
-
- when setting the hostname component of a URL
-
- Closes #10922
-
-- curl_url_set.3: mention that users can set content rather freely
-
- ... which then might render bad URLs if you extract a URL later.
-
- Closes #10921
-
-Dan Fandrich (10 Apr 2023)
-
-- CI: retry failed downloads of aws-lc
-
- Don't fail the build in case of a temporary server problem.
-
-- test1169: fix so it works properly everywhere
-
- - Use an absolute path for the -L option since the module isn't in the
- perl path
- - Create the needed test file in a <file> section; <precheck> isn't
- intended for this
- - Fix the test number in the file name, which was wrong
-
- Follow-up to f754990a
-
- Ref: #10818
- Fixes #10889
- Closes #10917
-
-- tests: stop using strndup(), which isn't portable
-
- It's not available on Solaris 10, for example. Since this is just test
- code that doesn't need to use an optimized system version, replace it
- with the implementation copied from tool_cb_hdr.c.
-
-- runtests: fix an incorrect comment about the ld_preload feature
-
- Follow-up to 1f631864
-
- Ref: #10818
-
-Daniel Stenberg (9 Apr 2023)
-
-- urlapi: prevent setting invalid schemes with *url_set()
-
- A typical mistake would be to try to set "https://" - including the
- separator - this is now rejected as that would then lead to
- url_get(... URL...) would get an invalid URL extracted.
-
- Extended test 1560 to verify.
-
- Closes #10911
-
-Biswapriyo Nath (9 Apr 2023)
-
-- http2: remove unused Curl_http2_strerror function declaration
-
- Curl_http2_strerror was renamed to http2_strerror in
- 05b100aee247bb9bec8e9a1b0 and then http2_strerror was removed in
- 5808a0d0f5ea0399d4a2a2
-
- This also fixes the following compiler error
-
- lib/http2.h:41:33: error: unknown type name 'uint32_t'
- lib/http2.h:1:1: note: 'uint32_t' is defined in header '<stdint.h>'
-
- Closes #10912
-
-Daniel Stenberg (8 Apr 2023)
-
-- RELEASE-NOTES: synced
-
-SuperIlu on github (8 Apr 2023)
-
-- config-dos.h: fix SIZEOF_CURL_OFF_T for MS-DOS/DJGPP
-
- Fixes #10905
- Closes #10910
-
-Daniel Stenberg (8 Apr 2023)
-
-- lib: remove CURLX_NO_MEMORY_CALLBACKS
-
- The only user of this define was 'chkdecimalpoint' - a special purpose
- test tool that was built but not used anymore (since 17c18fbc3 - Apr
- 2020).
-
- Closes #10908
-
-- CURLPROXY_HTTPS2: for HTTPS proxy that may speak HTTP/2
-
- Setting this proxy type allows curl to negotiate and use HTTP/2 with
- HTTPS proxies.
-
- Closes #10900
-
-Ali Khodkar (8 Apr 2023)
-
-- write-out.d: add missing periods
-
- Closes #10897
-
-Daniel Stenberg (7 Apr 2023)
-
-- http2: remove check for !data after it was already dereferenced
-
- Pointed out by Coverity
-
- Closes #10906
diff --git a/libs/libcurl/docs/THANKS b/libs/libcurl/docs/THANKS
index b8e754e4ac..d7e05f07ef 100644
--- a/libs/libcurl/docs/THANKS
+++ b/libs/libcurl/docs/THANKS
@@ -71,6 +71,7 @@ Alessandro Vesely
Alex aka WindEagle
Alex Baines
Alex Bligh
+Alex Bozarth
Alex Chan
Alex Crichton
Alex Fishman
@@ -78,6 +79,7 @@ Alex Gaynor
Alex Grebenschikov
Alex Gruz
Alex Kiernan
+Alex Klyubin
Alex Konev
Alex Malinovich
Alex Mayorga
@@ -111,6 +113,7 @@ Alexandre Ferrieux
Alexandre Pion
Alexey Borzov
Alexey Eremikhin
+Alexey Larikov
Alexey Melnichuk
Alexey Pesternikov
Alexey Savchuk
@@ -130,6 +133,7 @@ Alona Rossen
Amaury Denoyelle
amishmm on github
Amit Katyal
+Ammar Faizi
Amol Pattekar
Amr Shahin
Anatol Belski
@@ -227,6 +231,7 @@ Antoni Villalonga
Antonio Larrosa
Antony74 on github
Antti Hätälä
+Anubhav Rai
apparentorder on github
April King
arainchik on github
@@ -349,6 +354,7 @@ Bob Schader
bobmitchell1956 on github
Bodo Bergmann
Bogdan Nicula
+boilingoden
Boris Kuschel
Boris Okunskiy
Boris Rasin
@@ -422,6 +428,7 @@ Carlo Cannas
Carlo Marcelo Arenas Belón
Carlo Teubner
Carlo Wood
+Carlos Henrique Lima Melara
Carlos ORyan
Carsten Lange
Casey Bodley
@@ -437,6 +444,7 @@ Chandrakant Bagul
Charles Cazabon
Charles Kerr
Charles Romestant
+Charlie C
Chen Prog
Cherish98 on github
Chester Liu
@@ -649,6 +657,7 @@ David Sanderson
David Schweikert
David Shaw
David Strauss
+David Suter
David Tarendash
David Thiel
David Walser
@@ -780,6 +789,7 @@ Edward Sheldrake
Edward Thomson
Eelco Dolstra
Eetu Ojanen
+eeverettrbx on github
Egon Eckert
Egor Pugin
Ehren Bendler
@@ -806,8 +816,10 @@ Emiliano Ida
Emilio Cobos Ãlvarez
Emilio López
Emmanuel Tychon
+Enno Boland
Enrico Scholz
Enrik Berkhan
+enWILLYado on github
eppesuig
Eramoto Masaya
Eric Cooper
@@ -868,6 +880,7 @@ Fabrice Fontaine
Fabrizio Ammollo
Fahim Chandurwala
Faizur Rahman
+Faraz Fallahi
Farzin on github
Fata Nugraha
Fawad Mirza
@@ -1048,6 +1061,7 @@ Hao Wu
Hardeep Singh
Haris Okanovic
Harold Stuart
+Harry Mallon
Harry Sarson
Harry Sintonen
Harshal Pradhan
@@ -1103,6 +1117,8 @@ Ian Lynagh
Ian Spence
Ian Turner
Ian Wilkes
+iconoclasthero
+icy17 on github
Ignacio Vazquez-Abrams
Igor Franchuk
Igor Khristophorov
@@ -1279,6 +1295,7 @@ Jesse Tan
jethrogb on github
jhoyla on github
Jie He
+Jiehong on github
Jilayne Lovejoy
Jim Beveridge
Jim Drash
@@ -1467,10 +1484,12 @@ Kane York
Kang Lin
Kang-Jin Lee
Kantanat Wannapaka
+Kareem
Kari Pahula
Karl Chen
Karl Moerder
Karol Pietrzak
+Kartatz on Github
Karthikdasari0423
Karthikdasari0423 on github
Kartik Mahajan
@@ -1512,6 +1531,7 @@ Kim Minjoong
Kim Rinnewitz
Kim Vandry
Kimmo Kinnunen
+kirbyn17 on hackerone
Kirill Efimov
Kirill Marchuk
Kjell Ericson
@@ -1570,6 +1590,7 @@ Lars J. Aas
Lars Johannesen
Lars Nilsson
Lars Torben Wilson
+Lau
Laurent Bonnans
Laurent Dufresne
Laurent Rabret
@@ -1615,15 +1636,18 @@ Litter White
Liviu Chircu
Liza Alenchery
lizhuang0630 on github
+lkordos on github
lllaffer on github
Lloyd Fournier
Lluís Batlle i Rossell
locpyl-tidnyd on github
Loganaden Velvindron
Loic Dachary
+LoRd_MuldeR
Loren Kirkby
Lorenzo Miniero
Loïc Yhuel
+lRoccoon on github
Luan Cestari
Luca Altea
Luca Boccassi
@@ -1667,6 +1691,7 @@ Maksim Arhipov
Maksim Kuzevanov
Maksim Sciepanienka
Maksim Stsepanenka
+Maksymilian Arciemowicz
Malik Idrees Hasan Khan
Mamoru Tasaka
Mamta Upadhyay
@@ -1693,6 +1718,7 @@ Marcelo Juchem
Marcin Adamski
Marcin Gryszkalis
Marcin Konicki
+Marcin Rataj
Marco Deckel
Marco G. Salvagno
Marco Kamner
@@ -1756,6 +1782,7 @@ Martin Jansen
Martin Kammerhofer
Martin Kepplinger
Martin Lemke
+Martin Schmatz
Martin Skinner
Martin Staael
Martin Storsjö
@@ -1995,6 +2022,7 @@ Nick Zitzmann
nick-telia on github
Nicklas Avén
Nico Baggus
+Nico Rieck
nico-abram on github
Nicolas Berloquin
Nicolas Croiset
@@ -2018,6 +2046,7 @@ nimaje on github
niner on github
Ning Dong
Nir Soffer
+Niracler Li
Niranjan Hasabnis
Nis Jorgensen
nk
@@ -2037,6 +2066,7 @@ Nuru on github
Octavio Schroeder
odek86 on github
Ofer
+ohyeaah on github
Okhin Vasilij
Ola Mork
Olaf Flebbe
@@ -2063,6 +2093,7 @@ omau on github
OndÅ™ej KoláÄek
opensignature on github
opensslonzos-github on github
+Ophir Lojkine
Orange Tsai
Oren Souroujon
Oren Tirosh
@@ -2346,6 +2377,7 @@ Ricky-Tigg on github
Rider Linden
RiderALT on github
Rikard Falkeborn
+rilysh
rl1987 on github
Rob Boeckermann
Rob Cotrone
@@ -2373,6 +2405,7 @@ Robert Prag
Robert Ronto
Robert Schumann
Robert Simpson
+Robert Southee
Robert Weaver
Robert Wruck
Robin A. Meade
@@ -2448,6 +2481,7 @@ Salvador Dávila
Salvatore Sorrentino
Sam Deane
Sam Hurst
+Sam James
Sam Roth
Sam Schanken
Samanta Navarro
@@ -2482,6 +2516,7 @@ Scott Barrett
Scott Cantor
Scott Davis
Scott McCreary
+sd0 on hackerone
Sean Boudreau
Sean Burford
Sean MacLennan
@@ -2559,10 +2594,12 @@ Simon Warta
simplerobot on github
Siva Sivaraman
SLDiggie on github
+Smackd0wn
Smackd0wn on github
smuellerDD on github
sn on hackerone
sofaboss on github
+Sohom Datta
Somnath Kundu
Song Ma
Sonia Subramanian
@@ -2629,6 +2666,7 @@ Steve Marx
Steve Oliphant
Steve Roskowski
Steve Walch
+Steven Allen
Steven Bazyl
Steven G. Johnson
Steven Gu
@@ -2714,6 +2752,7 @@ Tim Chen
Tim Costello
Tim Harder
Tim Heckman
+Tim Hill
Tim Mcdonough
Tim Newsome
Tim Rühsen
@@ -2793,6 +2832,7 @@ tonystz on Github
Toon Verwaest
Tor Arntsen
Torben Dannhauer
+Torben Dury
Torsten Foertsch
Toshio Kuratomi
Toshiyuki Maezawa
@@ -2809,6 +2849,7 @@ Tseng Jun
Tuomas Siipola
Tuomo Rinne
Tupone Alfredo
+Turiiya
Tyler Hall
Török Edwin
u20221022 on github
@@ -2976,6 +3017,7 @@ Zhang Xiuhua
zhanghu on xiaomi
Zhao Yisha
Zhaoyang Wu
+zhengqwe on github
Zhibiao Wu
zhihaoy on github
Zhouyihai Ding
diff --git a/libs/libcurl/include/curl/curl.h b/libs/libcurl/include/curl/curl.h
index 05c90b7ce3..1f6c5764c6 100644
--- a/libs/libcurl/include/curl/curl.h
+++ b/libs/libcurl/include/curl/curl.h
@@ -53,28 +53,19 @@
#include "curlver.h" /* libcurl version defines */
#include "system.h" /* determine things run-time */
-/*
- * Define CURL_WIN32 when build target is Win32 API
- */
-
-#if (defined(_WIN32) || defined(__WIN32__) || defined(WIN32)) && \
- !defined(__SYMBIAN32__)
-#define CURL_WIN32
-#endif
-
#include <stdio.h>
#include <limits.h>
-#if (defined(__FreeBSD__) && (__FreeBSD__ >= 2)) || defined(__MidnightBSD__)
+#if defined(__FreeBSD__) || defined(__MidnightBSD__)
/* Needed for __FreeBSD_version or __MidnightBSD_version symbol definition */
-#include <osreldate.h>
+#include <sys/param.h>
#endif
/* The include stuff here below is mainly for time_t! */
#include <sys/types.h>
#include <time.h>
-#if defined(CURL_WIN32) && !defined(_WIN32_WCE) && !defined(__CYGWIN__)
+#if defined(_WIN32) && !defined(_WIN32_WCE) && !defined(__CYGWIN__)
#if !(defined(_WINSOCKAPI_) || defined(_WINSOCK_H) || \
defined(__LWIP_OPT_H__) || defined(LWIP_HDR_OPT_H))
/* The check above prevents the winsock2 inclusion if winsock.h already was
@@ -88,7 +79,7 @@
libc5-based Linux systems. Only include it on systems that are known to
require it! */
#if defined(_AIX) || defined(__NOVELL_LIBC__) || defined(__NetBSD__) || \
- defined(__minix) || defined(__SYMBIAN32__) || defined(__INTEGRITY) || \
+ defined(__minix) || defined(__INTEGRITY) || \
defined(ANDROID) || defined(__ANDROID__) || defined(__OpenBSD__) || \
defined(__CYGWIN__) || defined(AMIGA) || defined(__NuttX__) || \
(defined(__FreeBSD_version) && (__FreeBSD_version < 800000)) || \
@@ -97,11 +88,11 @@
#include <sys/select.h>
#endif
-#if !defined(CURL_WIN32) && !defined(_WIN32_WCE)
+#if !defined(_WIN32) && !defined(_WIN32_WCE)
#include <sys/socket.h>
#endif
-#if !defined(CURL_WIN32)
+#if !defined(_WIN32)
#include <sys/time.h>
#endif
@@ -128,7 +119,7 @@ typedef void CURLSH;
#ifdef CURL_STATICLIB
# define CURL_EXTERN
-#elif defined(CURL_WIN32) || defined(__SYMBIAN32__) || \
+#elif defined(_WIN32) || \
(__has_declspec_attribute(dllexport) && \
__has_declspec_attribute(dllimport))
# if defined(BUILDING_LIBCURL)
@@ -144,7 +135,7 @@ typedef void CURLSH;
#ifndef curl_socket_typedef
/* socket typedef */
-#if defined(CURL_WIN32) && !defined(__LWIP_OPT_H__) && !defined(LWIP_HDR_OPT_H)
+#if defined(_WIN32) && !defined(__LWIP_OPT_H__) && !defined(LWIP_HDR_OPT_H)
typedef SOCKET curl_socket_t;
#define CURL_SOCKET_BAD INVALID_SOCKET
#else
@@ -3220,6 +3211,7 @@ CURL_EXTERN CURLcode curl_easy_pause(CURL *handle, int bitmask);
#include "options.h"
#include "header.h"
#include "websockets.h"
+#include "mprintf.h"
/* the typechecker doesn't work in C++ (yet) */
#if defined(__GNUC__) && defined(__GNUC_MINOR__) && \
diff --git a/libs/libcurl/include/curl/curlver.h b/libs/libcurl/include/curl/curlver.h
index 7d64b35c92..e54a5e6138 100644
--- a/libs/libcurl/include/curl/curlver.h
+++ b/libs/libcurl/include/curl/curlver.h
@@ -32,12 +32,12 @@
/* This is the version number of the libcurl package from which this header
file origins: */
-#define LIBCURL_VERSION "8.4.0"
+#define LIBCURL_VERSION "8.5.0"
/* The numeric version number is also available "in parts" by using these
defines: */
#define LIBCURL_VERSION_MAJOR 8
-#define LIBCURL_VERSION_MINOR 4
+#define LIBCURL_VERSION_MINOR 5
#define LIBCURL_VERSION_PATCH 0
/* This is the numeric version of the libcurl version number, meant for easier
@@ -59,7 +59,7 @@
CURL_VERSION_BITS() macro since curl's own configure script greps for it
and needs it to contain the full number.
*/
-#define LIBCURL_VERSION_NUM 0x080400
+#define LIBCURL_VERSION_NUM 0x080500
/*
* This is the date and time when the full source package was created. The
@@ -70,7 +70,7 @@
*
* "2007-11-23"
*/
-#define LIBCURL_TIMESTAMP "2023-10-11"
+#define LIBCURL_TIMESTAMP "2023-12-06"
#define CURL_VERSION_BITS(x,y,z) ((x)<<16|(y)<<8|(z))
#define CURL_AT_LEAST_VERSION(x,y,z) \
diff --git a/libs/libcurl/include/curl/system.h b/libs/libcurl/include/curl/system.h
index 9a32e26d63..40044a4ee3 100644
--- a/libs/libcurl/include/curl/system.h
+++ b/libs/libcurl/include/curl/system.h
@@ -141,29 +141,6 @@
# define CURL_TYPEOF_CURL_SOCKLEN_T int
# endif
-#elif defined(__SYMBIAN32__)
-# if defined(__EABI__) /* Treat all ARM compilers equally */
-# define CURL_TYPEOF_CURL_OFF_T long long
-# define CURL_FORMAT_CURL_OFF_T "lld"
-# define CURL_FORMAT_CURL_OFF_TU "llu"
-# define CURL_SUFFIX_CURL_OFF_T LL
-# define CURL_SUFFIX_CURL_OFF_TU ULL
-# elif defined(__CW32__)
-# pragma longlong on
-# define CURL_TYPEOF_CURL_OFF_T long long
-# define CURL_FORMAT_CURL_OFF_T "lld"
-# define CURL_FORMAT_CURL_OFF_TU "llu"
-# define CURL_SUFFIX_CURL_OFF_T LL
-# define CURL_SUFFIX_CURL_OFF_TU ULL
-# elif defined(__VC32__)
-# define CURL_TYPEOF_CURL_OFF_T __int64
-# define CURL_FORMAT_CURL_OFF_T "lld"
-# define CURL_FORMAT_CURL_OFF_TU "llu"
-# define CURL_SUFFIX_CURL_OFF_T LL
-# define CURL_SUFFIX_CURL_OFF_TU ULL
-# endif
-# define CURL_TYPEOF_CURL_SOCKLEN_T unsigned int
-
#elif defined(macintosh)
# include <ConditionalMacros.h>
# if TYPE_LONGLONG
@@ -201,9 +178,10 @@
# define CURL_TYPEOF_CURL_SOCKLEN_T int
#elif defined(__MINGW32__)
+# include <inttypes.h>
# define CURL_TYPEOF_CURL_OFF_T long long
-# define CURL_FORMAT_CURL_OFF_T "I64d"
-# define CURL_FORMAT_CURL_OFF_TU "I64u"
+# define CURL_FORMAT_CURL_OFF_T PRId64
+# define CURL_FORMAT_CURL_OFF_TU PRIu64
# define CURL_SUFFIX_CURL_OFF_T LL
# define CURL_SUFFIX_CURL_OFF_TU ULL
# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
@@ -370,7 +348,14 @@
/* ===================================== */
#elif defined(_MSC_VER)
-# if (_MSC_VER >= 900) && (_INTEGRAL_MAX_BITS >= 64)
+# if (_MSC_VER >= 1800)
+# include <inttypes.h>
+# define CURL_TYPEOF_CURL_OFF_T __int64
+# define CURL_FORMAT_CURL_OFF_T PRId64
+# define CURL_FORMAT_CURL_OFF_TU PRIu64
+# define CURL_SUFFIX_CURL_OFF_T i64
+# define CURL_SUFFIX_CURL_OFF_TU ui64
+# elif (_MSC_VER >= 900) && (_INTEGRAL_MAX_BITS >= 64)
# define CURL_TYPEOF_CURL_OFF_T __int64
# define CURL_FORMAT_CURL_OFF_T "I64d"
# define CURL_FORMAT_CURL_OFF_TU "I64u"
diff --git a/libs/libcurl/src/CMakeLists.txt b/libs/libcurl/src/CMakeLists.txt
index 283488e935..dd0e8dfe1a 100644
--- a/libs/libcurl/src/CMakeLists.txt
+++ b/libs/libcurl/src/CMakeLists.txt
@@ -47,20 +47,25 @@ if(USE_ARES)
include_directories(${CARES_INCLUDE_DIR})
endif()
-add_library(
- curlu # special libcurlu library just for unittests
- STATIC
- EXCLUDE_FROM_ALL
- ${HHEADERS} ${CSOURCES}
-)
-target_compile_definitions(curlu PUBLIC UNITTESTS CURL_STATICLIB)
+if(BUILD_TESTING)
+ add_library(
+ curlu # special libcurlu library just for unittests
+ STATIC
+ EXCLUDE_FROM_ALL
+ ${HHEADERS} ${CSOURCES}
+ )
+ target_compile_definitions(curlu PUBLIC UNITTESTS CURL_STATICLIB)
+endif()
if(ENABLE_CURLDEBUG)
# We must compile these sources separately to avoid memdebug.h redefinitions
# applying to them.
set_source_files_properties(memdebug.c curl_multibyte.c PROPERTIES SKIP_UNITY_BUILD_INCLUSION ON)
endif()
-target_link_libraries(curlu PRIVATE ${CURL_LIBS})
+
+if(BUILD_TESTING)
+ target_link_libraries(curlu PRIVATE ${CURL_LIBS})
+endif()
transform_makefile_inc("Makefile.soname" "${CMAKE_CURRENT_BINARY_DIR}/Makefile.soname.cmake")
include(${CMAKE_CURRENT_BINARY_DIR}/Makefile.soname.cmake)
diff --git a/libs/libcurl/src/Makefile.am b/libs/libcurl/src/Makefile.am
index cbc3487e80..5cab1cc00f 100644
--- a/libs/libcurl/src/Makefile.am
+++ b/libs/libcurl/src/Makefile.am
@@ -110,7 +110,7 @@ libcurl_la_CFLAGS_EXTRA += $(CFLAG_CURL_SYMBOL_HIDING)
endif
libcurl_la_CPPFLAGS = $(AM_CPPFLAGS) $(libcurl_la_CPPFLAGS_EXTRA)
-libcurl_la_LDFLAGS = $(AM_LDFLAGS) $(libcurl_la_LDFLAGS_EXTRA) $(LDFLAGS) $(LIBCURL_LIBS)
+libcurl_la_LDFLAGS = $(AM_LDFLAGS) $(libcurl_la_LDFLAGS_EXTRA) $(CURL_LDFLAGS_LIB) $(LIBCURL_LIBS)
libcurl_la_CFLAGS = $(AM_CFLAGS) $(libcurl_la_CFLAGS_EXTRA)
libcurlu_la_CPPFLAGS = $(AM_CPPFLAGS) -DCURL_STATICLIB -DUNITTESTS
diff --git a/libs/libcurl/src/Makefile.in b/libs/libcurl/src/Makefile.in
index 4d75b419c9..3beb50dc1f 100644
--- a/libs/libcurl/src/Makefile.in
+++ b/libs/libcurl/src/Makefile.in
@@ -1486,7 +1486,7 @@ libcurl_la_LDFLAGS_EXTRA = $(am__append_1) $(am__append_2) \
$(am__append_3) $(am__append_4) $(am__append_5)
libcurl_la_CFLAGS_EXTRA = $(am__append_9)
libcurl_la_CPPFLAGS = $(AM_CPPFLAGS) $(libcurl_la_CPPFLAGS_EXTRA)
-libcurl_la_LDFLAGS = $(AM_LDFLAGS) $(libcurl_la_LDFLAGS_EXTRA) $(LDFLAGS) $(LIBCURL_LIBS)
+libcurl_la_LDFLAGS = $(AM_LDFLAGS) $(libcurl_la_LDFLAGS_EXTRA) $(CURL_LDFLAGS_LIB) $(LIBCURL_LIBS)
libcurl_la_CFLAGS = $(AM_CFLAGS) $(libcurl_la_CFLAGS_EXTRA)
libcurlu_la_CPPFLAGS = $(AM_CPPFLAGS) -DCURL_STATICLIB -DUNITTESTS
libcurlu_la_LDFLAGS = $(AM_LDFLAGS) -static $(LIBCURL_LIBS)
diff --git a/libs/libcurl/src/altsvc.c b/libs/libcurl/src/altsvc.c
index ce2324a3d0..13d4f11b71 100644
--- a/libs/libcurl/src/altsvc.c
+++ b/libs/libcurl/src/altsvc.c
@@ -97,7 +97,7 @@ static struct altsvc *altsvc_createid(const char *srchost,
unsigned int srcport,
unsigned int dstport)
{
- struct altsvc *as = calloc(sizeof(struct altsvc), 1);
+ struct altsvc *as = calloc(1, sizeof(struct altsvc));
size_t hlen;
size_t dlen;
if(!as)
@@ -123,15 +123,13 @@ static struct altsvc *altsvc_createid(const char *srchost,
dlen -= 2;
}
- as->src.host = Curl_memdup(srchost, hlen + 1);
+ as->src.host = Curl_strndup(srchost, hlen);
if(!as->src.host)
goto error;
- as->src.host[hlen] = 0;
- as->dst.host = Curl_memdup(dsthost, dlen + 1);
+ as->dst.host = Curl_strndup(dsthost, dlen);
if(!as->dst.host)
goto error;
- as->dst.host[dlen] = 0;
as->src.alpnid = srcalpnid;
as->dst.alpnid = dstalpnid;
@@ -301,7 +299,7 @@ static CURLcode altsvc_out(struct altsvc *as, FILE *fp)
*/
struct altsvcinfo *Curl_altsvc_init(void)
{
- struct altsvcinfo *asi = calloc(sizeof(struct altsvcinfo), 1);
+ struct altsvcinfo *asi = calloc(1, sizeof(struct altsvcinfo));
if(!asi)
return NULL;
Curl_llist_init(&asi->list, NULL);
diff --git a/libs/libcurl/src/arpa_telnet.h b/libs/libcurl/src/arpa_telnet.h
index b1348a2447..85f739f414 100644
--- a/libs/libcurl/src/arpa_telnet.h
+++ b/libs/libcurl/src/arpa_telnet.h
@@ -56,12 +56,14 @@ static const char * const telnetoptions[]=
"TERM SPEED", "LFLOW", "LINEMODE", "XDISPLOC",
"OLD-ENVIRON", "AUTHENTICATION", "ENCRYPT", "NEW-ENVIRON"
};
+#define CURL_TELOPT(x) telnetoptions[x]
+#else
+#define CURL_TELOPT(x) ""
#endif
#define CURL_TELOPT_MAXIMUM CURL_TELOPT_NEW_ENVIRON
#define CURL_TELOPT_OK(x) ((x) <= CURL_TELOPT_MAXIMUM)
-#define CURL_TELOPT(x) telnetoptions[x]
#define CURL_NTELOPTS 40
@@ -103,7 +105,12 @@ static const char * const telnetcmds[]=
#define CURL_TELCMD_OK(x) ( ((unsigned int)(x) >= CURL_TELCMD_MINIMUM) && \
((unsigned int)(x) <= CURL_TELCMD_MAXIMUM) )
+
+#ifndef CURL_DISABLE_VERBOSE_STRINGS
#define CURL_TELCMD(x) telnetcmds[(x)-CURL_TELCMD_MINIMUM]
+#else
+#define CURL_TELCMD(x) ""
+#endif
#endif /* CURL_DISABLE_TELNET */
diff --git a/libs/libcurl/src/asyn-ares.c b/libs/libcurl/src/asyn-ares.c
index ffb4ecd367..f13ccb36cb 100644
--- a/libs/libcurl/src/asyn-ares.c
+++ b/libs/libcurl/src/asyn-ares.c
@@ -60,13 +60,13 @@
#include "progress.h"
#include "timediff.h"
-# if defined(CURL_STATICLIB) && !defined(CARES_STATICLIB) && \
- defined(WIN32)
-# define CARES_STATICLIB
-# endif
-# include <ares.h>
-# include <ares_version.h> /* really old c-ares didn't include this by
- itself */
+#if defined(CURL_STATICLIB) && !defined(CARES_STATICLIB) && \
+ defined(_WIN32)
+# define CARES_STATICLIB
+#endif
+#include <ares.h>
+#include <ares_version.h> /* really old c-ares didn't include this by
+ itself */
#if ARES_VERSION >= 0x010500
/* c-ares 1.5.0 or later, the callback proto is modified */
@@ -228,9 +228,9 @@ static void destroy_async_data(struct Curl_async *async);
void Curl_resolver_cancel(struct Curl_easy *data)
{
DEBUGASSERT(data);
- if(data->state.async.resolver)
- ares_cancel((ares_channel)data->state.async.resolver);
- destroy_async_data(&data->state.async);
+ if(data->conn->resolve_async.resolver)
+ ares_cancel((ares_channel)data->conn->resolve_async.resolver);
+ destroy_async_data(&data->conn->resolve_async);
}
/*
@@ -278,14 +278,14 @@ int Curl_resolver_getsock(struct Curl_easy *data,
struct timeval timebuf;
struct timeval *timeout;
long milli;
- int max = ares_getsock((ares_channel)data->state.async.resolver,
+ int max = ares_getsock((ares_channel)data->conn->resolve_async.resolver,
(ares_socket_t *)socks, MAX_SOCKSPEREASYHANDLE);
maxtime.tv_sec = CURL_TIMEOUT_RESOLVE;
maxtime.tv_usec = 0;
- timeout = ares_timeout((ares_channel)data->state.async.resolver, &maxtime,
- &timebuf);
+ timeout = ares_timeout((ares_channel)data->conn->resolve_async.resolver,
+ &maxtime, &timebuf);
milli = (long)curlx_tvtoms(timeout);
if(milli == 0)
milli += 10;
@@ -313,8 +313,8 @@ static int waitperform(struct Curl_easy *data, timediff_t timeout_ms)
int i;
int num = 0;
- bitmask = ares_getsock((ares_channel)data->state.async.resolver, socks,
- ARES_GETSOCK_MAXNUM);
+ bitmask = ares_getsock((ares_channel)data->conn->resolve_async.resolver,
+ socks, ARES_GETSOCK_MAXNUM);
for(i = 0; i < ARES_GETSOCK_MAXNUM; i++) {
pfd[i].events = 0;
@@ -344,12 +344,12 @@ static int waitperform(struct Curl_easy *data, timediff_t timeout_ms)
if(!nfds)
/* Call ares_process() unconditionally here, even if we simply timed out
above, as otherwise the ares name resolve won't timeout! */
- ares_process_fd((ares_channel)data->state.async.resolver, ARES_SOCKET_BAD,
- ARES_SOCKET_BAD);
+ ares_process_fd((ares_channel)data->conn->resolve_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.async.resolver,
+ ares_process_fd((ares_channel)data->conn->resolve_async.resolver,
(pfd[i].revents & (POLLRDNORM|POLLIN))?
pfd[i].fd:ARES_SOCKET_BAD,
(pfd[i].revents & (POLLWRNORM|POLLOUT))?
@@ -368,7 +368,7 @@ static int waitperform(struct Curl_easy *data, timediff_t timeout_ms)
CURLcode Curl_resolver_is_resolved(struct Curl_easy *data,
struct Curl_dns_entry **dns)
{
- struct thread_data *res = data->state.async.tdata;
+ struct thread_data *res = data->conn->resolve_async.tdata;
CURLcode result = CURLE_OK;
DEBUGASSERT(dns);
@@ -397,7 +397,7 @@ CURLcode Curl_resolver_is_resolved(struct Curl_easy *data,
ARES_ECANCELLED synchronously for all pending responses. This will
leave us with res->num_pending == 0, which is perfect for the next
block. */
- ares_cancel((ares_channel)data->state.async.resolver);
+ ares_cancel((ares_channel)data->conn->resolve_async.resolver);
DEBUGASSERT(res->num_pending == 0);
}
#endif
@@ -408,12 +408,12 @@ CURLcode Curl_resolver_is_resolved(struct Curl_easy *data,
them */
res->temp_ai = NULL;
- if(!data->state.async.dns)
+ if(!data->conn->resolve_async.dns)
result = Curl_resolver_error(data);
else
- *dns = data->state.async.dns;
+ *dns = data->conn->resolve_async.dns;
- destroy_async_data(&data->state.async);
+ destroy_async_data(&data->conn->resolve_async);
}
return result;
@@ -464,7 +464,8 @@ CURLcode Curl_resolver_wait_resolv(struct Curl_easy *data,
store.tv_sec = itimeout/1000;
store.tv_usec = (itimeout%1000)*1000;
- tvp = ares_timeout((ares_channel)data->state.async.resolver, &store, &tv);
+ tvp = ares_timeout((ares_channel)data->conn->resolve_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
@@ -478,7 +479,7 @@ CURLcode Curl_resolver_wait_resolv(struct Curl_easy *data,
return CURLE_UNRECOVERABLE_POLL;
result = Curl_resolver_is_resolved(data, entry);
- if(result || data->state.async.done)
+ if(result || data->conn->resolve_async.done)
break;
if(Curl_pgrsUpdate(data))
@@ -499,12 +500,12 @@ CURLcode Curl_resolver_wait_resolv(struct Curl_easy *data,
}
if(result)
/* failure, so we cancel the ares operation */
- ares_cancel((ares_channel)data->state.async.resolver);
+ ares_cancel((ares_channel)data->conn->resolve_async.resolver);
/* Operation complete, if the lookup was successful we now have the entry
in the cache. */
if(entry)
- *entry = data->state.async.dns;
+ *entry = data->conn->resolve_async.dns;
if(result)
/* close the connection, since we can't return failure here without
@@ -571,12 +572,13 @@ 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 = data->state.async.tdata;
+ res = data->conn->resolve_async.tdata;
if(res) {
res->num_pending--;
if(CURL_ASYNC_SUCCESS == status) {
- struct Curl_addrinfo *ai = Curl_he2ai(hostent, data->state.async.port);
+ struct Curl_addrinfo *ai = Curl_he2ai(hostent,
+ data->conn->resolve_async.port);
if(ai) {
compound_results(res, ai);
}
@@ -727,14 +729,16 @@ static void addrinfo_cb(void *arg, int status, int timeouts,
struct ares_addrinfo *result)
{
struct Curl_easy *data = (struct Curl_easy *)arg;
- struct thread_data *res = data->state.async.tdata;
- (void)timeouts;
- if(ARES_SUCCESS == status) {
- res->temp_ai = ares2addr(result->nodes);
- res->last_status = CURL_ASYNC_SUCCESS;
- ares_freeaddrinfo(result);
+ if(data->conn) {
+ struct thread_data *res = data->conn->resolve_async.tdata;
+ (void)timeouts;
+ if(ARES_SUCCESS == status) {
+ res->temp_ai = ares2addr(result->nodes);
+ res->last_status = CURL_ASYNC_SUCCESS;
+ ares_freeaddrinfo(result);
+ }
+ res->num_pending--;
}
- res->num_pending--;
}
#endif
@@ -755,15 +759,15 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data,
size_t namelen = strlen(hostname);
*waitp = 0; /* default to synchronous response */
- res = calloc(sizeof(struct thread_data) + namelen, 1);
+ res = calloc(1, sizeof(struct thread_data) + namelen);
if(res) {
strcpy(res->hostname, hostname);
- data->state.async.hostname = res->hostname;
- data->state.async.port = port;
- data->state.async.done = FALSE; /* not done */
- data->state.async.status = 0; /* clear */
- data->state.async.dns = NULL; /* clear */
- data->state.async.tdata = res;
+ data->conn->resolve_async.hostname = res->hostname;
+ data->conn->resolve_async.port = port;
+ data->conn->resolve_async.done = FALSE; /* not done */
+ data->conn->resolve_async.status = 0; /* clear */
+ data->conn->resolve_async.dns = NULL; /* clear */
+ data->conn->resolve_async.tdata = res;
/* initial status - failed */
res->last_status = ARES_ENOTFOUND;
@@ -793,8 +797,8 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data,
hints.ai_flags = ARES_AI_NUMERICSERV;
msnprintf(service, sizeof(service), "%d", port);
res->num_pending = 1;
- ares_getaddrinfo((ares_channel)data->state.async.resolver, hostname,
- service, &hints, addrinfo_cb, data);
+ ares_getaddrinfo((ares_channel)data->conn->resolve_async.resolver,
+ hostname, service, &hints, addrinfo_cb, data);
}
#else
@@ -804,10 +808,10 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data,
res->num_pending = 2;
/* areschannel is already setup in the Curl_open() function */
- ares_gethostbyname((ares_channel)data->state.async.resolver, hostname,
- PF_INET, query_completed_cb, data);
- ares_gethostbyname((ares_channel)data->state.async.resolver, hostname,
- PF_INET6, query_completed_cb, data);
+ ares_gethostbyname((ares_channel)data->conn->resolve_async.resolver,
+ hostname, PF_INET, query_completed_cb, data);
+ ares_gethostbyname((ares_channel)data->conn->resolve_async.resolver,
+ hostname, PF_INET6, query_completed_cb, data);
}
else
#endif
@@ -815,7 +819,7 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data,
res->num_pending = 1;
/* areschannel is already setup in the Curl_open() function */
- ares_gethostbyname((ares_channel)data->state.async.resolver,
+ ares_gethostbyname((ares_channel)data->conn->resolve_async.resolver,
hostname, PF_INET,
query_completed_cb, data);
}
@@ -829,6 +833,7 @@ CURLcode Curl_set_dns_servers(struct Curl_easy *data,
char *servers)
{
CURLcode result = CURLE_NOT_BUILT_IN;
+ ares_channel channel, lchannel = NULL;
int ares_result;
/* If server is NULL or empty, this would purge all DNS servers
@@ -841,11 +846,23 @@ CURLcode Curl_set_dns_servers(struct Curl_easy *data,
return CURLE_OK;
#ifdef HAVE_CARES_SERVERS_CSV
+ if(data->conn)
+ channel = data->conn->resolve_async.resolver;
+ else {
+ /* we are called by setopt on a data without a connection (yet). In that
+ * case we set the value on a local instance for checking.
+ * The configured data options are set when the connection for this
+ * transfer is created. */
+ result = Curl_resolver_init(data, (void **)&lchannel);
+ if(result)
+ goto out;
+ channel = lchannel;
+ }
+
#ifdef HAVE_CARES_PORTS_CSV
- ares_result = ares_set_servers_ports_csv(data->state.async.resolver,
- servers);
+ ares_result = ares_set_servers_ports_csv(channel, servers);
#else
- ares_result = ares_set_servers_csv(data->state.async.resolver, servers);
+ ares_result = ares_set_servers_csv(channel, servers);
#endif
switch(ares_result) {
case ARES_SUCCESS:
@@ -861,6 +878,9 @@ CURLcode Curl_set_dns_servers(struct Curl_easy *data,
result = CURLE_BAD_FUNCTION_ARGUMENT;
break;
}
+out:
+ if(lchannel)
+ Curl_resolver_cleanup(lchannel);
#else /* too old c-ares version! */
(void)data;
(void)(ares_result);
@@ -872,11 +892,14 @@ CURLcode Curl_set_dns_interface(struct Curl_easy *data,
const char *interf)
{
#ifdef HAVE_CARES_LOCAL_DEV
- if(!interf)
- interf = "";
-
- ares_set_local_dev((ares_channel)data->state.async.resolver, interf);
+ if(data->conn) {
+ /* not a setopt test run, set the value */
+ if(!interf)
+ interf = "";
+ ares_set_local_dev((ares_channel)data->conn->resolve_async.resolver,
+ interf);
+ }
return CURLE_OK;
#else /* c-ares version too old! */
(void)data;
@@ -900,8 +923,11 @@ CURLcode Curl_set_dns_local_ip4(struct Curl_easy *data,
}
}
- ares_set_local_ip4((ares_channel)data->state.async.resolver,
- ntohl(a4.s_addr));
+ if(data->conn) {
+ /* not a setopt test run, set the value */
+ ares_set_local_ip4((ares_channel)data->conn->resolve_async.resolver,
+ ntohl(a4.s_addr));
+ }
return CURLE_OK;
#else /* c-ares version too old! */
@@ -927,7 +953,10 @@ CURLcode Curl_set_dns_local_ip6(struct Curl_easy *data,
}
}
- ares_set_local_ip6((ares_channel)data->state.async.resolver, a6);
+ if(data->conn) {
+ /* not a setopt test run, set the value */
+ ares_set_local_ip6((ares_channel)data->conn->resolve_async.resolver, a6);
+ }
return CURLE_OK;
#else /* c-ares version too old! */
diff --git a/libs/libcurl/src/asyn-thread.c b/libs/libcurl/src/asyn-thread.c
index 5019fa44d9..493f009e34 100644
--- a/libs/libcurl/src/asyn-thread.c
+++ b/libs/libcurl/src/asyn-thread.c
@@ -136,7 +136,7 @@ static void destroy_async_data(struct Curl_async *);
*/
void Curl_resolver_cancel(struct Curl_easy *data)
{
- destroy_async_data(&data->state.async);
+ destroy_async_data(&data->conn->resolve_async);
}
/* This function is used to init a threaded resolve */
@@ -173,7 +173,7 @@ struct thread_data {
static struct thread_sync_data *conn_thread_sync_data(struct Curl_easy *data)
{
- return &(data->state.async.tdata->tsd);
+ return &(data->conn->resolve_async.tdata->tsd);
}
/* Destroy resolver thread synchronization data */
@@ -196,7 +196,7 @@ void destroy_thread_sync_data(struct thread_sync_data *tsd)
* the other end (for reading) is always closed in the parent thread.
*/
if(tsd->sock_pair[1] != CURL_SOCKET_BAD) {
- sclose(tsd->sock_pair[1]);
+ wakeup_close(tsd->sock_pair[1]);
}
#endif
memset(tsd, 0, sizeof(*tsd));
@@ -233,8 +233,8 @@ int init_thread_sync_data(struct thread_data *td,
Curl_mutex_init(tsd->mtx);
#ifndef CURL_DISABLE_SOCKETPAIR
- /* create socket pair, avoid AF_LOCAL since it doesn't build on Solaris */
- if(Curl_socketpair(AF_UNIX, SOCK_STREAM, 0, &tsd->sock_pair[0]) < 0) {
+ /* create socket pair or pipe */
+ if(wakeup_create(&tsd->sock_pair[0]) < 0) {
tsd->sock_pair[0] = CURL_SOCKET_BAD;
tsd->sock_pair[1] = CURL_SOCKET_BAD;
goto err_exit;
@@ -254,7 +254,7 @@ int init_thread_sync_data(struct thread_data *td,
err_exit:
#ifndef CURL_DISABLE_SOCKETPAIR
if(tsd->sock_pair[0] != CURL_SOCKET_BAD) {
- sclose(tsd->sock_pair[0]);
+ wakeup_close(tsd->sock_pair[0]);
tsd->sock_pair[0] = CURL_SOCKET_BAD;
}
#endif
@@ -320,7 +320,7 @@ static unsigned int CURL_STDCALL getaddrinfo_thread(void *arg)
if(tsd->sock_pair[1] != CURL_SOCKET_BAD) {
/* DNS has been resolved, signal client task */
buf[0] = 1;
- if(swrite(tsd->sock_pair[1], buf, sizeof(buf)) < 0) {
+ if(wakeup_write(tsd->sock_pair[1], buf, sizeof(buf)) < 0) {
/* update sock_erro to errno */
tsd->sock_error = SOCKERRNO;
}
@@ -428,9 +428,9 @@ static bool init_resolve_thread(struct Curl_easy *data,
{
struct thread_data *td = calloc(1, sizeof(struct thread_data));
int err = ENOMEM;
- struct Curl_async *asp = &data->state.async;
+ struct Curl_async *asp = &data->conn->resolve_async;
- data->state.async.tdata = td;
+ data->conn->resolve_async.tdata = td;
if(!td)
goto errno_exit;
@@ -488,7 +488,7 @@ static CURLcode thread_wait_resolv(struct Curl_easy *data,
CURLcode result = CURLE_OK;
DEBUGASSERT(data);
- td = data->state.async.tdata;
+ td = data->conn->resolve_async.tdata;
DEBUGASSERT(td);
DEBUGASSERT(td->thread_hnd != curl_thread_t_null);
@@ -500,18 +500,18 @@ static CURLcode thread_wait_resolv(struct Curl_easy *data,
else
DEBUGASSERT(0);
- data->state.async.done = TRUE;
+ data->conn->resolve_async.done = TRUE;
if(entry)
- *entry = data->state.async.dns;
+ *entry = data->conn->resolve_async.dns;
- if(!data->state.async.dns && report)
+ if(!data->conn->resolve_async.dns && report)
/* a name was not resolved, report error */
result = Curl_resolver_error(data);
- destroy_async_data(&data->state.async);
+ destroy_async_data(&data->conn->resolve_async);
- if(!data->state.async.dns && report)
+ if(!data->conn->resolve_async.dns && report)
connclose(data->conn, "asynch resolve failed");
return result;
@@ -524,7 +524,7 @@ static CURLcode thread_wait_resolv(struct Curl_easy *data,
*/
void Curl_resolver_kill(struct Curl_easy *data)
{
- struct thread_data *td = data->state.async.tdata;
+ struct thread_data *td = data->conn->resolve_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
@@ -563,7 +563,7 @@ CURLcode Curl_resolver_wait_resolv(struct Curl_easy *data,
CURLcode Curl_resolver_is_resolved(struct Curl_easy *data,
struct Curl_dns_entry **entry)
{
- struct thread_data *td = data->state.async.tdata;
+ struct thread_data *td = data->conn->resolve_async.tdata;
int done = 0;
DEBUGASSERT(entry);
@@ -581,13 +581,13 @@ CURLcode Curl_resolver_is_resolved(struct Curl_easy *data,
if(done) {
getaddrinfo_complete(data);
- if(!data->state.async.dns) {
+ if(!data->conn->resolve_async.dns) {
CURLcode result = Curl_resolver_error(data);
- destroy_async_data(&data->state.async);
+ destroy_async_data(&data->conn->resolve_async);
return result;
}
- destroy_async_data(&data->state.async);
- *entry = data->state.async.dns;
+ destroy_async_data(&data->conn->resolve_async);
+ *entry = data->conn->resolve_async.dns;
}
else {
/* poll for name lookup done with exponential backoff up to 250ms */
@@ -619,9 +619,9 @@ int Curl_resolver_getsock(struct Curl_easy *data, curl_socket_t *socks)
int ret_val = 0;
timediff_t milli;
timediff_t ms;
- struct resdata *reslv = (struct resdata *)data->state.async.resolver;
+ struct resdata *reslv = (struct resdata *)data->conn->resolve_async.resolver;
#ifndef CURL_DISABLE_SOCKETPAIR
- struct thread_data *td = data->state.async.tdata;
+ struct thread_data *td = data->conn->resolve_async.tdata;
#else
(void)socks;
#endif
@@ -662,7 +662,7 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data,
int port,
int *waitp)
{
- struct resdata *reslv = (struct resdata *)data->state.async.resolver;
+ struct resdata *reslv = (struct resdata *)data->conn->resolve_async.resolver;
*waitp = 0; /* default to synchronous response */
@@ -691,7 +691,7 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data,
{
struct addrinfo hints;
int pf = PF_INET;
- struct resdata *reslv = (struct resdata *)data->state.async.resolver;
+ struct resdata *reslv = (struct resdata *)data->conn->resolve_async.resolver;
*waitp = 0; /* default to synchronous response */
diff --git a/libs/libcurl/src/base64.c b/libs/libcurl/src/base64.c
index 1244677cb0..739c26f24b 100644
--- a/libs/libcurl/src/base64.c
+++ b/libs/libcurl/src/base64.c
@@ -31,6 +31,7 @@
!defined(CURL_DISABLE_SMTP) || \
!defined(CURL_DISABLE_POP3) || \
!defined(CURL_DISABLE_IMAP) || \
+ !defined(CURL_DISABLE_DIGEST_AUTH) || \
!defined(CURL_DISABLE_DOH) || defined(USE_SSL) || defined(BUILDING_CURL)
#include "curl/curl.h"
#include "warnless.h"
diff --git a/libs/libcurl/src/c-hyper.c b/libs/libcurl/src/c-hyper.c
index 74adf4e44b..efb534ccad 100644
--- a/libs/libcurl/src/c-hyper.c
+++ b/libs/libcurl/src/c-hyper.c
@@ -22,6 +22,10 @@
*
***************************************************************************/
+/* Curl's integration with Hyper. This replaces certain functions in http.c,
+ * based on configuration #defines. This implementation supports HTTP/1.1 but
+ * not HTTP/2.
+ */
#include "curl_setup.h"
#if !defined(CURL_DISABLE_HTTP) && defined(USE_HYPER)
@@ -172,17 +176,15 @@ static int hyper_each_header(void *userdata,
Curl_debug(data, CURLINFO_HEADER_IN, headp, len);
- if(!data->state.hconnect || !data->set.suppress_connect_headers) {
- writetype = CLIENTWRITE_HEADER;
- if(data->state.hconnect)
- writetype |= CLIENTWRITE_CONNECT;
- if(data->req.httpcode/100 == 1)
- writetype |= CLIENTWRITE_1XX;
- result = Curl_client_write(data, writetype, headp, len);
- if(result) {
- data->state.hresult = CURLE_ABORTED_BY_CALLBACK;
- return HYPER_ITER_BREAK;
- }
+ writetype = CLIENTWRITE_HEADER;
+ if(data->state.hconnect)
+ writetype |= CLIENTWRITE_CONNECT;
+ if(data->req.httpcode/100 == 1)
+ writetype |= CLIENTWRITE_1XX;
+ result = Curl_client_write(data, writetype, headp, len);
+ if(result) {
+ data->state.hresult = CURLE_ABORTED_BY_CALLBACK;
+ return HYPER_ITER_BREAK;
}
result = Curl_bump_headersize(data, len, FALSE);
@@ -201,7 +203,7 @@ static int hyper_body_chunk(void *userdata, const hyper_buf *chunk)
struct SingleRequest *k = &data->req;
CURLcode result = CURLE_OK;
- if(0 == k->bodywrites++) {
+ if(0 == k->bodywrites) {
bool done = FALSE;
#if defined(USE_NTLM)
struct connectdata *conn = data->conn;
@@ -241,11 +243,6 @@ static int hyper_body_chunk(void *userdata, const hyper_buf *chunk)
return HYPER_ITER_BREAK;
}
}
- if(k->ignorebody)
- return HYPER_ITER_CONTINUE;
- if(0 == len)
- return HYPER_ITER_CONTINUE;
- Curl_debug(data, CURLINFO_DATA_IN, buf, len);
result = Curl_client_write(data, CLIENTWRITE_BODY, buf, len);
if(result) {
@@ -253,12 +250,6 @@ static int hyper_body_chunk(void *userdata, const hyper_buf *chunk)
return HYPER_ITER_BREAK;
}
- data->req.bytecount += len;
- result = Curl_pgrsSetDownloadCounter(data, data->req.bytecount);
- if(result) {
- data->state.hresult = result;
- return HYPER_ITER_BREAK;
- }
return HYPER_ITER_CONTINUE;
}
@@ -310,13 +301,14 @@ static CURLcode status_line(struct Curl_easy *data,
Curl_debug(data, CURLINFO_HEADER_IN, Curl_dyn_ptr(&data->state.headerb),
len);
- if(!data->state.hconnect || !data->set.suppress_connect_headers) {
- writetype = CLIENTWRITE_HEADER|CLIENTWRITE_STATUS;
- result = Curl_client_write(data, writetype,
- Curl_dyn_ptr(&data->state.headerb), len);
- if(result)
- return result;
- }
+ writetype = CLIENTWRITE_HEADER|CLIENTWRITE_STATUS;
+ if(data->state.hconnect)
+ writetype |= CLIENTWRITE_CONNECT;
+ result = Curl_client_write(data, writetype,
+ Curl_dyn_ptr(&data->state.headerb), len);
+ if(result)
+ return result;
+
result = Curl_bump_headersize(data, len, FALSE);
return result;
}
@@ -551,11 +543,9 @@ CURLcode Curl_hyper_stream(struct Curl_easy *data,
static CURLcode debug_request(struct Curl_easy *data,
const char *method,
- const char *path,
- bool h2)
+ const char *path)
{
- char *req = aprintf("%s %s HTTP/%s\r\n", method, path,
- h2?"2":"1.1");
+ char *req = aprintf("%s %s HTTP/1.1\r\n", method, path);
if(!req)
return CURLE_OUT_OF_MEMORY;
Curl_debug(data, CURLINFO_HEADER_OUT, req, strlen(req));
@@ -637,7 +627,6 @@ CURLcode Curl_hyper_header(struct Curl_easy *data, hyper_headers *headers,
static CURLcode request_target(struct Curl_easy *data,
struct connectdata *conn,
const char *method,
- bool h2,
hyper_request *req)
{
CURLcode result;
@@ -649,26 +638,13 @@ static CURLcode request_target(struct Curl_easy *data,
if(result)
return result;
- if(h2 && hyper_request_set_uri_parts(req,
- /* scheme */
- (uint8_t *)data->state.up.scheme,
- strlen(data->state.up.scheme),
- /* authority */
- (uint8_t *)conn->host.name,
- strlen(conn->host.name),
- /* path_and_query */
- (uint8_t *)Curl_dyn_uptr(&r),
- Curl_dyn_len(&r))) {
- failf(data, "error setting uri parts to hyper");
- result = CURLE_OUT_OF_MEMORY;
- }
- else if(!h2 && hyper_request_set_uri(req, (uint8_t *)Curl_dyn_uptr(&r),
+ if(hyper_request_set_uri(req, (uint8_t *)Curl_dyn_uptr(&r),
Curl_dyn_len(&r))) {
failf(data, "error setting uri to hyper");
result = CURLE_OUT_OF_MEMORY;
}
else
- result = debug_request(data, method, Curl_dyn_ptr(&r), h2);
+ result = debug_request(data, method, Curl_dyn_ptr(&r));
Curl_dyn_free(&r);
@@ -899,7 +875,6 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
const char *p_accept; /* Accept: string */
const char *method;
Curl_HttpReq httpreq;
- bool h2 = FALSE;
const char *te = NULL; /* transfer-encoding */
hyper_code rc;
@@ -907,6 +882,7 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
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;
+ Curl_client_cleanup(data);
infof(data, "Time for the Hyper dance");
memset(h, 0, sizeof(struct hyptransfer));
@@ -917,6 +893,8 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
Curl_http_method(data, conn, &method, &httpreq);
+ DEBUGASSERT(data->req.bytecount == 0);
+
/* setup the authentication headers */
{
char *pq = NULL;
@@ -972,8 +950,9 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
goto error;
}
if(conn->alpn == CURL_HTTP_VERSION_2) {
- hyper_clientconn_options_http2(options, 1);
- h2 = TRUE;
+ failf(data, "ALPN protocol h2 not supported with Hyper");
+ result = CURLE_UNSUPPORTED_PROTOCOL;
+ goto error;
}
hyper_clientconn_options_set_preserve_header_case(options, 1);
hyper_clientconn_options_set_preserve_header_order(options, 1);
@@ -1024,7 +1003,7 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
}
}
else {
- if(!h2 && !data->state.disableexpect) {
+ if(!data->state.disableexpect) {
data->state.expect100header = TRUE;
}
}
@@ -1035,7 +1014,7 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
goto error;
}
- result = request_target(data, conn, method, h2, req);
+ result = request_target(data, conn, method, req);
if(result)
goto error;
@@ -1056,19 +1035,10 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
if(result)
goto error;
- if(!h2) {
- if(data->state.aptr.host) {
- result = Curl_hyper_header(data, headers, data->state.aptr.host);
- if(result)
- goto error;
- }
- }
- else {
- /* For HTTP/2, we show the Host: header as if we sent it, to make it look
- like for HTTP/1 but it isn't actually sent since :authority is then
- used. */
- Curl_debug(data, CURLINFO_HEADER_OUT, data->state.aptr.host,
- strlen(data->state.aptr.host));
+ if(data->state.aptr.host) {
+ result = Curl_hyper_header(data, headers, data->state.aptr.host);
+ if(result)
+ goto error;
}
if(data->state.aptr.proxyuserpwd) {
diff --git a/libs/libcurl/src/cf-h1-proxy.c b/libs/libcurl/src/cf-h1-proxy.c
index bec2d1dea4..a49d6869a6 100644
--- a/libs/libcurl/src/cf-h1-proxy.c
+++ b/libs/libcurl/src/cf-h1-proxy.c
@@ -374,7 +374,7 @@ static CURLcode recv_CONNECT_resp(struct Curl_cfilter *cf,
curl_socket_t tunnelsocket = Curl_conn_cf_get_socket(cf, data);
char *linep;
size_t perline;
- int error;
+ int error, writetype;
#define SELECT_OK 0
#define SELECT_ERROR 1
@@ -386,12 +386,12 @@ static CURLcode recv_CONNECT_resp(struct Curl_cfilter *cf,
return CURLE_OK;
while(ts->keepon) {
- ssize_t gotbytes;
+ ssize_t nread;
char byte;
/* 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(data, tunnelsocket, &byte, 1, &gotbytes);
+ result = Curl_read(data, tunnelsocket, &byte, 1, &nread);
if(result == CURLE_AGAIN)
/* socket buffer drained, return */
return CURLE_OK;
@@ -404,7 +404,7 @@ static CURLcode recv_CONNECT_resp(struct Curl_cfilter *cf,
break;
}
- if(gotbytes <= 0) {
+ if(nread <= 0) {
if(data->set.proxyauth && data->state.authproxy.avail &&
data->state.aptr.proxyuserpwd) {
/* proxy auth was requested and there was proxy auth available,
@@ -437,11 +437,11 @@ static CURLcode recv_CONNECT_resp(struct Curl_cfilter *cf,
properly to know when the end of the body is reached */
CHUNKcode r;
CURLcode extra;
- ssize_t tookcareof = 0;
+ size_t consumed = 0;
/* now parse the chunked piece of data so that we can
properly tell when the stream ends */
- r = Curl_httpchunk_read(data, &byte, 1, &tookcareof, &extra);
+ r = Curl_httpchunk_read(data, &byte, 1, &consumed, &extra);
if(r == CHUNKE_STOP) {
/* we're done reading chunks! */
infof(data, "chunk reading DONE");
@@ -467,15 +467,12 @@ static CURLcode recv_CONNECT_resp(struct Curl_cfilter *cf,
/* output debug if that is requested */
Curl_debug(data, CURLINFO_HEADER_IN, linep, perline);
- if(!data->set.suppress_connect_headers) {
- /* send the header to the callback */
- int writetype = CLIENTWRITE_HEADER | CLIENTWRITE_CONNECT |
- (ts->headerlines == 1 ? CLIENTWRITE_STATUS : 0);
-
- result = Curl_client_write(data, writetype, linep, perline);
- if(result)
- return result;
- }
+ /* send the header to the callback */
+ writetype = CLIENTWRITE_HEADER | CLIENTWRITE_CONNECT |
+ (ts->headerlines == 1 ? CLIENTWRITE_STATUS : 0);
+ result = Curl_client_write(data, writetype, linep, perline);
+ if(result)
+ return result;
result = Curl_bump_headersize(data, perline, TRUE);
if(result)
@@ -502,6 +499,7 @@ static CURLcode recv_CONNECT_resp(struct Curl_cfilter *cf,
else if(ts->chunked_encoding) {
CHUNKcode r;
CURLcode extra;
+ size_t consumed = 0;
infof(data, "Ignore chunked response-body");
@@ -516,8 +514,7 @@ static CURLcode recv_CONNECT_resp(struct Curl_cfilter *cf,
/* now parse the chunked piece of data so that we can properly
tell when the stream ends */
- r = Curl_httpchunk_read(data, linep + 1, 1, &gotbytes,
- &extra);
+ r = Curl_httpchunk_read(data, linep + 1, 1, &consumed, &extra);
if(r == CHUNKE_STOP) {
/* we're done reading chunks! */
infof(data, "chunk reading DONE");
@@ -1038,31 +1035,29 @@ out:
return result;
}
-static int cf_h1_proxy_get_select_socks(struct Curl_cfilter *cf,
+static void cf_h1_proxy_adjust_pollset(struct Curl_cfilter *cf,
struct Curl_easy *data,
- curl_socket_t *socks)
+ struct easy_pollset *ps)
{
struct h1_tunnel_state *ts = cf->ctx;
- int fds;
- fds = cf->next->cft->get_select_socks(cf->next, data, socks);
- if(!fds && cf->next->connected && !cf->connected) {
+ if(!cf->connected) {
/* If we are not connected, but the filter "below" is
* and not waiting on something, we are tunneling. */
- socks[0] = Curl_conn_cf_get_socket(cf, data);
+ curl_socket_t sock = Curl_conn_cf_get_socket(cf, data);
if(ts) {
/* when we've sent a CONNECT to a proxy, we should rather either
wait for the socket to become readable to be able to get the
response headers or if we're still sending the request, wait
for write. */
- if(ts->CONNECT.sending == HTTPSEND_REQUEST) {
- return GETSOCK_WRITESOCK(0);
- }
- return GETSOCK_READSOCK(0);
+ if(ts->CONNECT.sending == HTTPSEND_REQUEST)
+ Curl_pollset_set_out_only(data, ps, sock);
+ else
+ Curl_pollset_set_in_only(data, ps, sock);
}
- return GETSOCK_WRITESOCK(0);
+ else
+ Curl_pollset_set_out_only(data, ps, sock);
}
- return fds;
}
static void cf_h1_proxy_destroy(struct Curl_cfilter *cf,
@@ -1093,7 +1088,7 @@ struct Curl_cftype Curl_cft_h1_proxy = {
cf_h1_proxy_connect,
cf_h1_proxy_close,
Curl_cf_http_proxy_get_host,
- cf_h1_proxy_get_select_socks,
+ cf_h1_proxy_adjust_pollset,
Curl_cf_def_data_pending,
Curl_cf_def_send,
Curl_cf_def_recv,
diff --git a/libs/libcurl/src/cf-h2-proxy.c b/libs/libcurl/src/cf-h2-proxy.c
index aab4f4661b..f69098b704 100644
--- a/libs/libcurl/src/cf-h2-proxy.c
+++ b/libs/libcurl/src/cf-h2-proxy.c
@@ -688,12 +688,8 @@ static int proxy_h2_on_frame_recv(nghttp2_session *session,
* window and *assume* that we treat this like a WINDOW_UPDATE. Some
* servers send an explicit WINDOW_UPDATE, but not all seem to do that.
* To be safe, we UNHOLD a stream in order not to stall. */
- if((data->req.keepon & KEEP_SEND_HOLD) &&
- (data->req.keepon & KEEP_SEND)) {
- data->req.keepon &= ~KEEP_SEND_HOLD;
+ if(CURL_WANT_SEND(data)) {
drain_tunnel(cf, data, &ctx->tunnel);
- CURL_TRC_CF(data, cf, "[%d] un-holding after SETTINGS",
- stream_id);
}
break;
case NGHTTP2_GOAWAY:
@@ -727,12 +723,8 @@ static int proxy_h2_on_frame_recv(nghttp2_session *session,
}
break;
case NGHTTP2_WINDOW_UPDATE:
- if((data->req.keepon & KEEP_SEND_HOLD) &&
- (data->req.keepon & KEEP_SEND)) {
- data->req.keepon &= ~KEEP_SEND_HOLD;
- Curl_expire(data, 0, EXPIRE_RUN_NOW);
- CURL_TRC_CF(data, cf, "[%d] unpausing after win update",
- stream_id);
+ if(CURL_WANT_SEND(data)) {
+ drain_tunnel(cf, data, &ctx->tunnel);
}
break;
default:
@@ -909,7 +901,6 @@ static CURLcode proxy_h2_submit(int32_t *pstream_id,
{
struct dynhds h2_headers;
nghttp2_nv *nva = NULL;
- unsigned int i;
int32_t stream_id = -1;
size_t nheader;
CURLcode result;
@@ -920,22 +911,12 @@ static CURLcode proxy_h2_submit(int32_t *pstream_id,
if(result)
goto out;
- nheader = Curl_dynhds_count(&h2_headers);
- nva = malloc(sizeof(nghttp2_nv) * nheader);
+ nva = Curl_dynhds_to_nva(&h2_headers, &nheader);
if(!nva) {
result = CURLE_OUT_OF_MEMORY;
goto out;
}
- for(i = 0; i < nheader; ++i) {
- struct dynhds_entry *e = Curl_dynhds_getn(&h2_headers, i);
- nva[i].name = (unsigned char *)e->name;
- nva[i].namelen = e->namelen;
- nva[i].value = (unsigned char *)e->value;
- nva[i].valuelen = e->valuelen;
- nva[i].flags = NGHTTP2_NV_FLAG_NONE;
- }
-
if(read_callback) {
nghttp2_data_provider data_prd;
@@ -1187,25 +1168,31 @@ static bool cf_h2_proxy_data_pending(struct Curl_cfilter *cf,
return cf->next? cf->next->cft->has_data_pending(cf->next, data) : FALSE;
}
-static int cf_h2_proxy_get_select_socks(struct Curl_cfilter *cf,
- struct Curl_easy *data,
- curl_socket_t *sock)
+static void cf_h2_proxy_adjust_pollset(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ struct easy_pollset *ps)
{
struct cf_h2_proxy_ctx *ctx = cf->ctx;
- int bitmap = GETSOCK_BLANK;
- struct cf_call_data save;
-
- CF_DATA_SAVE(save, cf, data);
- sock[0] = Curl_conn_cf_get_socket(cf, data);
- bitmap |= GETSOCK_READSOCK(0);
+ curl_socket_t sock = Curl_conn_cf_get_socket(cf, data);
+ bool want_recv, want_send;
- /* HTTP/2 layer wants to send data) AND there's a window to send data in */
- if(nghttp2_session_want_write(ctx->h2) &&
- nghttp2_session_get_remote_window_size(ctx->h2))
- bitmap |= GETSOCK_WRITESOCK(0);
+ Curl_pollset_check(data, ps, sock, &want_recv, &want_send);
+ if(ctx->h2 && (want_recv || want_send)) {
+ struct cf_call_data save;
+ bool c_exhaust, s_exhaust;
- CF_DATA_RESTORE(cf, save);
- return bitmap;
+ CF_DATA_SAVE(save, cf, data);
+ c_exhaust = !nghttp2_session_get_remote_window_size(ctx->h2);
+ s_exhaust = ctx->tunnel.stream_id >= 0 &&
+ !nghttp2_session_get_stream_remote_window_size(
+ ctx->h2, ctx->tunnel.stream_id);
+ want_recv = (want_recv || c_exhaust || s_exhaust);
+ want_send = (!s_exhaust && want_send) ||
+ (!c_exhaust && nghttp2_session_want_write(ctx->h2));
+
+ Curl_pollset_set(data, ps, sock, want_recv, want_send);
+ CF_DATA_RESTORE(cf, save);
+ }
}
static ssize_t h2_handle_tunnel_close(struct Curl_cfilter *cf,
@@ -1542,7 +1529,7 @@ struct Curl_cftype Curl_cft_h2_proxy = {
cf_h2_proxy_connect,
cf_h2_proxy_close,
Curl_cf_http_proxy_get_host,
- cf_h2_proxy_get_select_socks,
+ cf_h2_proxy_adjust_pollset,
cf_h2_proxy_data_pending,
cf_h2_proxy_send,
cf_h2_proxy_recv,
@@ -1560,7 +1547,7 @@ CURLcode Curl_cf_h2_proxy_insert_after(struct Curl_cfilter *cf,
CURLcode result = CURLE_OUT_OF_MEMORY;
(void)data;
- ctx = calloc(sizeof(*ctx), 1);
+ ctx = calloc(1, sizeof(*ctx));
if(!ctx)
goto out;
diff --git a/libs/libcurl/src/cf-haproxy.c b/libs/libcurl/src/cf-haproxy.c
index 8ca38823c6..6036e028a5 100644
--- a/libs/libcurl/src/cf-haproxy.c
+++ b/libs/libcurl/src/cf-haproxy.c
@@ -171,23 +171,17 @@ static void cf_haproxy_close(struct Curl_cfilter *cf,
cf->next->cft->do_close(cf->next, data);
}
-static int cf_haproxy_get_select_socks(struct Curl_cfilter *cf,
- struct Curl_easy *data,
- curl_socket_t *socks)
+static void cf_haproxy_adjust_pollset(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ struct easy_pollset *ps)
{
- int fds;
-
- fds = cf->next->cft->get_select_socks(cf->next, data, socks);
- if(!fds && cf->next->connected && !cf->connected) {
+ if(cf->next->connected && !cf->connected) {
/* If we are not connected, but the filter "below" is
* and not waiting on something, we are sending. */
- socks[0] = Curl_conn_cf_get_socket(cf, data);
- return GETSOCK_WRITESOCK(0);
+ Curl_pollset_set_out_only(data, ps, Curl_conn_cf_get_socket(cf, data));
}
- return fds;
}
-
struct Curl_cftype Curl_cft_haproxy = {
"HAPROXY",
0,
@@ -196,7 +190,7 @@ struct Curl_cftype Curl_cft_haproxy = {
cf_haproxy_connect,
cf_haproxy_close,
Curl_cf_def_get_host,
- cf_haproxy_get_select_socks,
+ cf_haproxy_adjust_pollset,
Curl_cf_def_data_pending,
Curl_cf_def_send,
Curl_cf_def_recv,
@@ -214,7 +208,7 @@ static CURLcode cf_haproxy_create(struct Curl_cfilter **pcf,
CURLcode result;
(void)data;
- ctx = calloc(sizeof(*ctx), 1);
+ ctx = calloc(1, sizeof(*ctx));
if(!ctx) {
result = CURLE_OUT_OF_MEMORY;
goto out;
diff --git a/libs/libcurl/src/cf-https-connect.c b/libs/libcurl/src/cf-https-connect.c
index 5fe93e9c31..f2ae2cbee6 100644
--- a/libs/libcurl/src/cf-https-connect.c
+++ b/libs/libcurl/src/cf-https-connect.c
@@ -188,9 +188,6 @@ static CURLcode baller_connected(struct Curl_cfilter *cf,
#endif
infof(data, "using HTTP/2");
break;
- case CURL_HTTP_VERSION_1_1:
- infof(data, "using HTTP/1.1");
- break;
default:
infof(data, "using HTTP/1.x");
break;
@@ -325,42 +322,25 @@ out:
return result;
}
-static int cf_hc_get_select_socks(struct Curl_cfilter *cf,
+static void cf_hc_adjust_pollset(struct Curl_cfilter *cf,
struct Curl_easy *data,
- curl_socket_t *socks)
+ struct easy_pollset *ps)
{
- struct cf_hc_ctx *ctx = cf->ctx;
- size_t i, j, s;
- int brc, rc = GETSOCK_BLANK;
- curl_socket_t bsocks[MAX_SOCKSPEREASYHANDLE];
- struct cf_hc_baller *ballers[2];
-
- if(cf->connected)
- return cf->next->cft->get_select_socks(cf->next, data, socks);
-
- ballers[0] = &ctx->h3_baller;
- ballers[1] = &ctx->h21_baller;
- for(i = s = 0; i < sizeof(ballers)/sizeof(ballers[0]); i++) {
- struct cf_hc_baller *b = ballers[i];
- if(!cf_hc_baller_is_active(b))
- continue;
- brc = Curl_conn_cf_get_select_socks(b->cf, data, bsocks);
- CURL_TRC_CF(data, cf, "get_selected_socks(%s) -> %x", b->name, brc);
- if(!brc)
- continue;
- for(j = 0; j < MAX_SOCKSPEREASYHANDLE && s < MAX_SOCKSPEREASYHANDLE; ++j) {
- if((brc & GETSOCK_WRITESOCK(j)) || (brc & GETSOCK_READSOCK(j))) {
- socks[s] = bsocks[j];
- if(brc & GETSOCK_WRITESOCK(j))
- rc |= GETSOCK_WRITESOCK(s);
- if(brc & GETSOCK_READSOCK(j))
- rc |= GETSOCK_READSOCK(s);
- s++;
- }
+ if(!cf->connected) {
+ struct cf_hc_ctx *ctx = cf->ctx;
+ struct cf_hc_baller *ballers[2];
+ size_t i;
+
+ ballers[0] = &ctx->h3_baller;
+ ballers[1] = &ctx->h21_baller;
+ for(i = 0; i < sizeof(ballers)/sizeof(ballers[0]); i++) {
+ struct cf_hc_baller *b = ballers[i];
+ if(!cf_hc_baller_is_active(b))
+ continue;
+ Curl_conn_cf_adjust_pollset(b->cf, data, ps);
}
+ CURL_TRC_CF(data, cf, "adjust_pollset -> %d socks", ps->num);
}
- CURL_TRC_CF(data, cf, "get_selected_socks -> %x", rc);
- return rc;
}
static bool cf_hc_data_pending(struct Curl_cfilter *cf,
@@ -455,7 +435,7 @@ struct Curl_cftype Curl_cft_http_connect = {
cf_hc_connect,
cf_hc_close,
Curl_cf_def_get_host,
- cf_hc_get_select_socks,
+ cf_hc_adjust_pollset,
cf_hc_data_pending,
Curl_cf_def_send,
Curl_cf_def_recv,
@@ -475,7 +455,7 @@ static CURLcode cf_hc_create(struct Curl_cfilter **pcf,
CURLcode result = CURLE_OK;
(void)data;
- ctx = calloc(sizeof(*ctx), 1);
+ ctx = calloc(1, sizeof(*ctx));
if(!ctx) {
result = CURLE_OUT_OF_MEMORY;
goto out;
diff --git a/libs/libcurl/src/cf-socket.c b/libs/libcurl/src/cf-socket.c
index d815752089..8582fdff64 100644
--- a/libs/libcurl/src/cf-socket.c
+++ b/libs/libcurl/src/cf-socket.c
@@ -81,7 +81,7 @@
#include "memdebug.h"
-#if defined(ENABLE_IPV6) && defined(IPV6_V6ONLY) && defined(WIN32)
+#if defined(ENABLE_IPV6) && defined(IPV6_V6ONLY) && defined(_WIN32)
/* It makes support for IPv4-mapped IPv6 addresses.
* Linux kernel, NetBSD, FreeBSD and Darwin: default is off;
* Windows Vista and later: default is on;
@@ -102,11 +102,7 @@ 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)
char buffer[STRERROR_LEN];
-#else
- (void) data;
-#endif
if(setsockopt(sockfd, level, TCP_NODELAY, (void *)&onoff,
sizeof(onoff)) < 0)
@@ -127,6 +123,7 @@ static void nosigpipe(struct Curl_easy *data,
curl_socket_t sockfd)
{
int onoff = 1;
+ (void)data;
if(setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, (void *)&onoff,
sizeof(onoff)) < 0) {
#if !defined(CURL_DISABLE_VERBOSE_STRINGS)
@@ -662,7 +659,7 @@ static bool verifyconnect(curl_socket_t sockfd, int *error)
int err = 0;
curl_socklen_t errSize = sizeof(err);
-#ifdef WIN32
+#ifdef _WIN32
/*
* In October 2003 we effectively nullified this function on Windows due to
* problems with it using all CPU in multi-threaded cases.
@@ -883,34 +880,14 @@ static void cf_socket_close(struct Curl_cfilter *cf, struct Curl_easy *data)
struct cf_socket_ctx *ctx = cf->ctx;
if(ctx && CURL_SOCKET_BAD != ctx->sock) {
- if(ctx->active) {
- /* We share our socket at cf->conn->sock[cf->sockindex] when active.
- * If it is no longer there, someone has stolen (and hopefully
- * closed it) and we just forget about it.
- */
- if(ctx->sock == cf->conn->sock[cf->sockindex]) {
- CURL_TRC_CF(data, cf, "cf_socket_close(%" CURL_FORMAT_SOCKET_T
- ", active)", ctx->sock);
- socket_close(data, cf->conn, !ctx->accepted, ctx->sock);
- cf->conn->sock[cf->sockindex] = CURL_SOCKET_BAD;
- }
- else {
- CURL_TRC_CF(data, cf, "cf_socket_close(%" CURL_FORMAT_SOCKET_T
- ") no longer at conn->sock[], discarding", ctx->sock);
- /* TODO: we do not want this to happen. Need to check which
- * code is messing with conn->sock[cf->sockindex] */
- }
- ctx->sock = CURL_SOCKET_BAD;
- if(cf->sockindex == FIRSTSOCKET)
- cf->conn->remote_addr = NULL;
- }
- else {
- /* this is our local socket, we did never publish it */
- CURL_TRC_CF(data, cf, "cf_socket_close(%" CURL_FORMAT_SOCKET_T
- ", not active)", ctx->sock);
- socket_close(data, cf->conn, !ctx->accepted, ctx->sock);
- ctx->sock = CURL_SOCKET_BAD;
- }
+ CURL_TRC_CF(data, cf, "cf_socket_close(%" CURL_FORMAT_SOCKET_T
+ ")", ctx->sock);
+ if(ctx->sock == cf->conn->sock[cf->sockindex])
+ cf->conn->sock[cf->sockindex] = CURL_SOCKET_BAD;
+ socket_close(data, cf->conn, !ctx->accepted, ctx->sock);
+ ctx->sock = CURL_SOCKET_BAD;
+ if(ctx->active && cf->sockindex == FIRSTSOCKET)
+ cf->conn->remote_addr = NULL;
Curl_bufq_reset(&ctx->recvbuf);
ctx->active = FALSE;
ctx->buffer_recv = FALSE;
@@ -1169,6 +1146,7 @@ static CURLcode cf_tcp_connect(struct Curl_cfilter *cf,
*done = FALSE; /* a very negative world view is best */
if(ctx->sock == CURL_SOCKET_BAD) {
+ int error;
result = cf_socket_open(cf, data);
if(result)
@@ -1181,8 +1159,12 @@ static CURLcode cf_tcp_connect(struct Curl_cfilter *cf,
/* Connect TCP socket */
rc = do_connect(cf, data, cf->conn->bits.tcp_fastopen);
+ error = SOCKERRNO;
+ set_local_ip(cf, data);
+ CURL_TRC_CF(data, cf, "local address %s port %d...",
+ ctx->l_ip, ctx->l_port);
if(-1 == rc) {
- result = socket_connect_result(data, ctx->r_ip, SOCKERRNO);
+ result = socket_connect_result(data, ctx->r_ip, error);
goto out;
}
}
@@ -1220,13 +1202,14 @@ static CURLcode cf_tcp_connect(struct Curl_cfilter *cf,
out:
if(result) {
if(ctx->error) {
+ set_local_ip(cf, data);
data->state.os_errno = ctx->error;
SET_SOCKERRNO(ctx->error);
#ifndef CURL_DISABLE_VERBOSE_STRINGS
{
char buffer[STRERROR_LEN];
- infof(data, "connect to %s port %u failed: %s",
- ctx->r_ip, ctx->r_port,
+ infof(data, "connect to %s port %u from %s port %d failed: %s",
+ ctx->r_ip, ctx->r_port, ctx->l_ip, ctx->l_port,
Curl_strerror(ctx->error, buffer, sizeof(buffer)));
}
#endif
@@ -1252,20 +1235,19 @@ static void cf_socket_get_host(struct Curl_cfilter *cf,
*pport = cf->conn->port;
}
-static int cf_socket_get_select_socks(struct Curl_cfilter *cf,
+static void cf_socket_adjust_pollset(struct Curl_cfilter *cf,
struct Curl_easy *data,
- curl_socket_t *socks)
+ struct easy_pollset *ps)
{
struct cf_socket_ctx *ctx = cf->ctx;
- int rc = GETSOCK_BLANK;
- (void)data;
- if(!cf->connected && ctx->sock != CURL_SOCKET_BAD) {
- socks[0] = ctx->sock;
- rc |= GETSOCK_WRITESOCK(0);
+ if(ctx->sock != CURL_SOCKET_BAD) {
+ if(!cf->connected)
+ Curl_pollset_set_out_only(data, ps, ctx->sock);
+ else
+ Curl_pollset_add_in(data, ps, ctx->sock);
+ CURL_TRC_CF(data, cf, "adjust_pollset -> %d socks", ps->num);
}
-
- return rc;
}
static bool cf_socket_data_pending(struct Curl_cfilter *cf,
@@ -1518,6 +1500,9 @@ static CURLcode cf_socket_cntrl(struct Curl_cfilter *cf,
case CF_CTRL_DATA_SETUP:
Curl_persistconninfo(data, cf->conn, ctx->l_ip, ctx->l_port);
break;
+ case CF_CTRL_FORGET_SOCKET:
+ ctx->sock = CURL_SOCKET_BAD;
+ break;
}
return CURLE_OK;
}
@@ -1612,7 +1597,7 @@ struct Curl_cftype Curl_cft_tcp = {
cf_tcp_connect,
cf_socket_close,
cf_socket_get_host,
- cf_socket_get_select_socks,
+ cf_socket_adjust_pollset,
cf_socket_data_pending,
cf_socket_send,
cf_socket_recv,
@@ -1635,7 +1620,7 @@ CURLcode Curl_cf_tcp_create(struct Curl_cfilter **pcf,
(void)data;
(void)conn;
DEBUGASSERT(transport == TRNSPRT_TCP);
- ctx = calloc(sizeof(*ctx), 1);
+ ctx = calloc(1, sizeof(*ctx));
if(!ctx) {
result = CURLE_OUT_OF_MEMORY;
goto out;
@@ -1742,7 +1727,7 @@ struct Curl_cftype Curl_cft_udp = {
cf_udp_connect,
cf_socket_close,
cf_socket_get_host,
- cf_socket_get_select_socks,
+ cf_socket_adjust_pollset,
cf_socket_data_pending,
cf_socket_send,
cf_socket_recv,
@@ -1765,7 +1750,7 @@ CURLcode Curl_cf_udp_create(struct Curl_cfilter **pcf,
(void)data;
(void)conn;
DEBUGASSERT(transport == TRNSPRT_UDP || transport == TRNSPRT_QUIC);
- ctx = calloc(sizeof(*ctx), 1);
+ ctx = calloc(1, sizeof(*ctx));
if(!ctx) {
result = CURLE_OUT_OF_MEMORY;
goto out;
@@ -1793,7 +1778,7 @@ struct Curl_cftype Curl_cft_unix = {
cf_tcp_connect,
cf_socket_close,
cf_socket_get_host,
- cf_socket_get_select_socks,
+ cf_socket_adjust_pollset,
cf_socket_data_pending,
cf_socket_send,
cf_socket_recv,
@@ -1816,7 +1801,7 @@ CURLcode Curl_cf_unix_create(struct Curl_cfilter **pcf,
(void)data;
(void)conn;
DEBUGASSERT(transport == TRNSPRT_UNIX);
- ctx = calloc(sizeof(*ctx), 1);
+ ctx = calloc(1, sizeof(*ctx));
if(!ctx) {
result = CURLE_OUT_OF_MEMORY;
goto out;
@@ -1857,7 +1842,7 @@ struct Curl_cftype Curl_cft_tcp_accept = {
cf_tcp_accept_connect,
cf_socket_close,
cf_socket_get_host, /* TODO: not accurate */
- cf_socket_get_select_socks,
+ cf_socket_adjust_pollset,
cf_socket_data_pending,
cf_socket_send,
cf_socket_recv,
@@ -1879,7 +1864,7 @@ CURLcode Curl_conn_tcp_listen_set(struct Curl_easy *data,
Curl_conn_cf_discard_all(data, conn, sockindex);
DEBUGASSERT(conn->sock[sockindex] == CURL_SOCKET_BAD);
- ctx = calloc(sizeof(*ctx), 1);
+ ctx = calloc(1, sizeof(*ctx));
if(!ctx) {
result = CURLE_OUT_OF_MEMORY;
goto out;
diff --git a/libs/libcurl/src/cfilters.c b/libs/libcurl/src/cfilters.c
index 3121673ed1..72783eb53d 100644
--- a/libs/libcurl/src/cfilters.c
+++ b/libs/libcurl/src/cfilters.c
@@ -33,6 +33,7 @@
#include "sockaddr.h" /* required for Curl_sockaddr_storage */
#include "multiif.h"
#include "progress.h"
+#include "select.h"
#include "warnless.h"
/* The last 3 #include files should be in this order */
@@ -70,12 +71,14 @@ void Curl_cf_def_get_host(struct Curl_cfilter *cf, struct Curl_easy *data,
}
}
-int Curl_cf_def_get_select_socks(struct Curl_cfilter *cf,
+void Curl_cf_def_adjust_pollset(struct Curl_cfilter *cf,
struct Curl_easy *data,
- curl_socket_t *socks)
+ struct easy_pollset *ps)
{
- return cf->next?
- cf->next->cft->get_select_socks(cf->next, data, socks) : 0;
+ /* NOP */
+ (void)cf;
+ (void)data;
+ (void)ps;
}
bool Curl_cf_def_data_pending(struct Curl_cfilter *cf,
@@ -212,7 +215,7 @@ CURLcode Curl_cf_create(struct Curl_cfilter **pcf,
CURLcode result = CURLE_OUT_OF_MEMORY;
DEBUGASSERT(cft);
- cf = calloc(sizeof(*cf), 1);
+ cf = calloc(1, sizeof(*cf));
if(!cf)
goto out;
@@ -303,15 +306,6 @@ void Curl_conn_cf_close(struct Curl_cfilter *cf, struct Curl_easy *data)
cf->cft->do_close(cf, data);
}
-int Curl_conn_cf_get_select_socks(struct Curl_cfilter *cf,
- struct Curl_easy *data,
- curl_socket_t *socks)
-{
- if(cf)
- return cf->cft->get_select_socks(cf, data, socks);
- return 0;
-}
-
ssize_t Curl_conn_cf_send(struct Curl_cfilter *cf, struct Curl_easy *data,
const void *buf, size_t len, CURLcode *err)
{
@@ -433,22 +427,31 @@ bool Curl_conn_data_pending(struct Curl_easy *data, int sockindex)
return FALSE;
}
-int Curl_conn_get_select_socks(struct Curl_easy *data, int sockindex,
- curl_socket_t *socks)
+void Curl_conn_cf_adjust_pollset(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ struct easy_pollset *ps)
+{
+ /* Get the lowest not-connected filter, if there are any */
+ while(cf && !cf->connected && cf->next && !cf->next->connected)
+ cf = cf->next;
+ /* From there on, give all filters a chance to adjust the pollset.
+ * Lower filters are called later, so they may override */
+ while(cf) {
+ cf->cft->adjust_pollset(cf, data, ps);
+ cf = cf->next;
+ }
+}
+
+void Curl_conn_adjust_pollset(struct Curl_easy *data,
+ struct easy_pollset *ps)
{
- struct Curl_cfilter *cf;
+ int i;
DEBUGASSERT(data);
DEBUGASSERT(data->conn);
- cf = data->conn->cfilter[sockindex];
-
- /* if the next one is not yet connected, that's the one we want */
- while(cf && cf->next && !cf->next->connected)
- cf = cf->next;
- if(cf) {
- return cf->cft->get_select_socks(cf, data, socks);
+ for(i = 0; i < 2; ++i) {
+ Curl_conn_cf_adjust_pollset(data->conn->cfilter[i], data, ps);
}
- return GETSOCK_BLANK;
}
void Curl_conn_get_host(struct Curl_easy *data, int sockindex,
@@ -524,6 +527,18 @@ curl_socket_t Curl_conn_get_socket(struct Curl_easy *data, int sockindex)
return data->conn? data->conn->sock[sockindex] : CURL_SOCKET_BAD;
}
+void Curl_conn_forget_socket(struct Curl_easy *data, int sockindex)
+{
+ if(data->conn) {
+ struct Curl_cfilter *cf = data->conn->cfilter[sockindex];
+ if(cf)
+ (void)Curl_conn_cf_cntrl(cf, data, TRUE,
+ CF_CTRL_FORGET_SOCKET, 0, NULL);
+ fake_sclose(data->conn->sock[sockindex]);
+ data->conn->sock[sockindex] = CURL_SOCKET_BAD;
+ }
+}
+
static CURLcode cf_cntrl_all(struct connectdata *conn,
struct Curl_easy *data,
bool ignore_result,
@@ -646,3 +661,142 @@ size_t Curl_conn_get_max_concurrent(struct Curl_easy *data,
&n, NULL) : CURLE_UNKNOWN_OPTION;
return (result || n <= 0)? 1 : (size_t)n;
}
+
+
+void Curl_pollset_reset(struct Curl_easy *data,
+ struct easy_pollset *ps)
+{
+ size_t i;
+ (void)data;
+ memset(ps, 0, sizeof(*ps));
+ for(i = 0; i< MAX_SOCKSPEREASYHANDLE; i++)
+ ps->sockets[i] = CURL_SOCKET_BAD;
+}
+
+/**
+ *
+ */
+void Curl_pollset_change(struct Curl_easy *data,
+ struct easy_pollset *ps, curl_socket_t sock,
+ int add_flags, int remove_flags)
+{
+ unsigned int i;
+
+ (void)data;
+ DEBUGASSERT(VALID_SOCK(sock));
+ if(!VALID_SOCK(sock))
+ return;
+
+ DEBUGASSERT(add_flags <= (CURL_POLL_IN|CURL_POLL_OUT));
+ DEBUGASSERT(remove_flags <= (CURL_POLL_IN|CURL_POLL_OUT));
+ DEBUGASSERT((add_flags&remove_flags) == 0); /* no overlap */
+ for(i = 0; i < ps->num; ++i) {
+ if(ps->sockets[i] == sock) {
+ ps->actions[i] &= (unsigned char)(~remove_flags);
+ ps->actions[i] |= (unsigned char)add_flags;
+ /* all gone? remove socket */
+ if(!ps->actions[i]) {
+ if((i + 1) < ps->num) {
+ memmove(&ps->sockets[i], &ps->sockets[i + 1],
+ (ps->num - (i + 1)) * sizeof(ps->sockets[0]));
+ memmove(&ps->actions[i], &ps->actions[i + 1],
+ (ps->num - (i + 1)) * sizeof(ps->actions[0]));
+ }
+ --ps->num;
+ }
+ return;
+ }
+ }
+ /* not present */
+ if(add_flags) {
+ /* Having more SOCKETS per easy handle than what is defined
+ * is a programming error. This indicates that we need
+ * to raise this limit, making easy_pollset larger.
+ * Since we use this in tight loops, we do not want to make
+ * the pollset dynamic unnecessarily.
+ * The current maximum in practise is HTTP/3 eyeballing where
+ * we have up to 4 sockets involved in connection setup.
+ */
+ DEBUGASSERT(i < MAX_SOCKSPEREASYHANDLE);
+ if(i < MAX_SOCKSPEREASYHANDLE) {
+ ps->sockets[i] = sock;
+ ps->actions[i] = (unsigned char)add_flags;
+ ps->num = i + 1;
+ }
+ }
+}
+
+void Curl_pollset_set(struct Curl_easy *data,
+ struct easy_pollset *ps, curl_socket_t sock,
+ bool do_in, bool do_out)
+{
+ Curl_pollset_change(data, ps, sock,
+ (do_in?CURL_POLL_IN:0)|(do_out?CURL_POLL_OUT:0),
+ (!do_in?CURL_POLL_IN:0)|(!do_out?CURL_POLL_OUT:0));
+}
+
+static void ps_add(struct Curl_easy *data, struct easy_pollset *ps,
+ int bitmap, curl_socket_t *socks)
+{
+ if(bitmap) {
+ int i;
+ for(i = 0; i < MAX_SOCKSPEREASYHANDLE; ++i) {
+ if(!(bitmap & GETSOCK_MASK_RW(i)) || !VALID_SOCK((socks[i]))) {
+ break;
+ }
+ if(bitmap & GETSOCK_READSOCK(i)) {
+ if(bitmap & GETSOCK_WRITESOCK(i))
+ Curl_pollset_add_inout(data, ps, socks[i]);
+ else
+ /* is READ, since we checked MASK_RW above */
+ Curl_pollset_add_in(data, ps, socks[i]);
+ }
+ else
+ Curl_pollset_add_out(data, ps, socks[i]);
+ }
+ }
+}
+
+void Curl_pollset_add_socks(struct Curl_easy *data,
+ struct easy_pollset *ps,
+ int (*get_socks_cb)(struct Curl_easy *data,
+ struct connectdata *conn,
+ curl_socket_t *socks))
+{
+ curl_socket_t socks[MAX_SOCKSPEREASYHANDLE];
+ int bitmap;
+
+ DEBUGASSERT(data->conn);
+ bitmap = get_socks_cb(data, data->conn, socks);
+ ps_add(data, ps, bitmap, socks);
+}
+
+void Curl_pollset_add_socks2(struct Curl_easy *data,
+ struct easy_pollset *ps,
+ int (*get_socks_cb)(struct Curl_easy *data,
+ curl_socket_t *socks))
+{
+ curl_socket_t socks[MAX_SOCKSPEREASYHANDLE];
+ int bitmap;
+
+ bitmap = get_socks_cb(data, socks);
+ ps_add(data, ps, bitmap, socks);
+}
+
+void Curl_pollset_check(struct Curl_easy *data,
+ struct easy_pollset *ps, curl_socket_t sock,
+ bool *pwant_read, bool *pwant_write)
+{
+ unsigned int i;
+
+ (void)data;
+ DEBUGASSERT(VALID_SOCK(sock));
+ for(i = 0; i < ps->num; ++i) {
+ if(ps->sockets[i] == sock) {
+ *pwant_read = !!(ps->actions[i] & CURL_POLL_IN);
+ *pwant_write = !!(ps->actions[i] & CURL_POLL_OUT);
+ return;
+ }
+ }
+ *pwant_read = *pwant_write = FALSE;
+}
diff --git a/libs/libcurl/src/cfilters.h b/libs/libcurl/src/cfilters.h
index 829340a2af..a343ea5fb6 100644
--- a/libs/libcurl/src/cfilters.h
+++ b/libs/libcurl/src/cfilters.h
@@ -60,14 +60,34 @@ typedef void Curl_cft_get_host(struct Curl_cfilter *cf,
const char **pdisplay_host,
int *pport);
-/* Filters may return sockets and fdset flags they are waiting for.
- * The passes array has room for up to MAX_SOCKSPEREASYHANDLE sockets.
- * @return read/write fdset for index in socks
- * or GETSOCK_BLANK when nothing to wait on
+struct easy_pollset;
+
+/* Passing in an easy_pollset for monitoring of sockets, let
+ * filters add or remove sockets actions (CURL_POLL_OUT, CURL_POLL_IN).
+ * This may add a socket or, in case no actions remain, remove
+ * a socket from the set.
+ *
+ * Filter implementations need to call filters "below" *after* they have
+ * made their adjustments. This allows lower filters to override "upper"
+ * actions. If a "lower" filter is unable to write, it needs to be able
+ * to disallow POLL_OUT.
+ *
+ * A filter without own restrictions/preferences should not modify
+ * the pollset. Filters, whose filter "below" is not connected, should
+ * also do no adjustments.
+ *
+ * Examples: a TLS handshake, while ongoing, might remove POLL_IN
+ * when it needs to write, or vice versa. A HTTP/2 filter might remove
+ * POLL_OUT when a stream window is exhausted and a WINDOW_UPDATE needs
+ * to be received first and add instead POLL_IN.
+ *
+ * @param cf the filter to ask
+ * @param data the easy handle the pollset is about
+ * @param ps the pollset (inout) for the easy handle
*/
-typedef int Curl_cft_get_select_socks(struct Curl_cfilter *cf,
- struct Curl_easy *data,
- curl_socket_t *socks);
+typedef void Curl_cft_adjust_pollset(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ struct easy_pollset *ps);
typedef bool Curl_cft_data_pending(struct Curl_cfilter *cf,
const struct Curl_easy *data);
@@ -110,6 +130,7 @@ typedef CURLcode Curl_cft_conn_keep_alive(struct Curl_cfilter *cf,
#define CF_CTRL_DATA_DONE_SEND 8 /* 0 NULL ignored */
/* update conn info at connection and data */
#define CF_CTRL_CONN_INFO_UPDATE (256+0) /* 0 NULL ignored */
+#define CF_CTRL_FORGET_SOCKET (256+1) /* 0 NULL ignored */
/**
* Handle event/control for the filter.
@@ -171,7 +192,7 @@ struct Curl_cftype {
Curl_cft_connect *do_connect; /* establish connection */
Curl_cft_close *do_close; /* close conn */
Curl_cft_get_host *get_host; /* host filter talks to */
- Curl_cft_get_select_socks *get_select_socks;/* sockets to select on */
+ Curl_cft_adjust_pollset *adjust_pollset; /* adjust transfer poll set */
Curl_cft_data_pending *has_data_pending;/* conn has data pending */
Curl_cft_send *do_send; /* send data */
Curl_cft_recv *do_recv; /* receive data */
@@ -200,9 +221,9 @@ void Curl_cf_def_destroy_this(struct Curl_cfilter *cf,
void Curl_cf_def_get_host(struct Curl_cfilter *cf, struct Curl_easy *data,
const char **phost, const char **pdisplay_host,
int *pport);
-int Curl_cf_def_get_select_socks(struct Curl_cfilter *cf,
- struct Curl_easy *data,
- curl_socket_t *socks);
+void Curl_cf_def_adjust_pollset(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ struct easy_pollset *ps);
bool Curl_cf_def_data_pending(struct Curl_cfilter *cf,
const struct Curl_easy *data);
ssize_t Curl_cf_def_send(struct Curl_cfilter *cf, struct Curl_easy *data,
@@ -279,9 +300,6 @@ CURLcode Curl_conn_cf_connect(struct Curl_cfilter *cf,
struct Curl_easy *data,
bool blocking, bool *done);
void Curl_conn_cf_close(struct Curl_cfilter *cf, struct Curl_easy *data);
-int Curl_conn_cf_get_select_socks(struct Curl_cfilter *cf,
- struct Curl_easy *data,
- curl_socket_t *socks);
ssize_t Curl_conn_cf_send(struct Curl_cfilter *cf, struct Curl_easy *data,
const void *buf, size_t len, CURLcode *err);
ssize_t Curl_conn_cf_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
@@ -364,11 +382,22 @@ bool Curl_conn_data_pending(struct Curl_easy *data,
curl_socket_t Curl_conn_get_socket(struct Curl_easy *data, int sockindex);
/**
- * Get any select fd flags and the socket filters at chain `sockindex`
- * at connection `conn` might be waiting for.
+ * Tell filters to forget about the socket at sockindex.
*/
-int Curl_conn_get_select_socks(struct Curl_easy *data, int sockindex,
- curl_socket_t *socks);
+void Curl_conn_forget_socket(struct Curl_easy *data, int sockindex);
+
+/**
+ * Adjust the pollset for the filter chain startgin at `cf`.
+ */
+void Curl_conn_cf_adjust_pollset(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ struct easy_pollset *ps);
+
+/**
+ * Adjust pollset from filters installed at transfer's connection.
+ */
+void Curl_conn_adjust_pollset(struct Curl_easy *data,
+ struct easy_pollset *ps);
/**
* Receive data through the filter chain at `sockindex` for connection
@@ -468,6 +497,54 @@ size_t Curl_conn_get_max_concurrent(struct Curl_easy *data,
int sockindex);
+void Curl_pollset_reset(struct Curl_easy *data,
+ struct easy_pollset *ps);
+
+/* Change the poll flags (CURL_POLL_IN/CURL_POLL_OUT) to the poll set for
+ * socket `sock`. If the socket is not already part of the poll set, it
+ * will be added.
+ * If the socket is present and all poll flags are cleared, it will be removed.
+ */
+void Curl_pollset_change(struct Curl_easy *data,
+ struct easy_pollset *ps, curl_socket_t sock,
+ int add_flags, int remove_flags);
+
+void Curl_pollset_set(struct Curl_easy *data,
+ struct easy_pollset *ps, curl_socket_t sock,
+ bool do_in, bool do_out);
+
+#define Curl_pollset_add_in(data, ps, sock) \
+ Curl_pollset_change((data), (ps), (sock), CURL_POLL_IN, 0)
+#define Curl_pollset_add_out(data, ps, sock) \
+ Curl_pollset_change((data), (ps), (sock), CURL_POLL_OUT, 0)
+#define Curl_pollset_add_inout(data, ps, sock) \
+ Curl_pollset_change((data), (ps), (sock), \
+ CURL_POLL_IN|CURL_POLL_OUT, 0)
+#define Curl_pollset_set_in_only(data, ps, sock) \
+ Curl_pollset_change((data), (ps), (sock), \
+ CURL_POLL_IN, CURL_POLL_OUT)
+#define Curl_pollset_set_out_only(data, ps, sock) \
+ Curl_pollset_change((data), (ps), (sock), \
+ CURL_POLL_OUT, CURL_POLL_IN)
+
+void Curl_pollset_add_socks(struct Curl_easy *data,
+ struct easy_pollset *ps,
+ int (*get_socks_cb)(struct Curl_easy *data,
+ struct connectdata *conn,
+ curl_socket_t *socks));
+void Curl_pollset_add_socks2(struct Curl_easy *data,
+ struct easy_pollset *ps,
+ int (*get_socks_cb)(struct Curl_easy *data,
+ curl_socket_t *socks));
+
+/**
+ * Check if the pollset, as is, wants to read and/or write regarding
+ * the given socket.
+ */
+void Curl_pollset_check(struct Curl_easy *data,
+ struct easy_pollset *ps, curl_socket_t sock,
+ bool *pwant_read, bool *pwant_write);
+
/**
* Types and macros used to keep the current easy handle in filter calls,
* allowing for nested invocations. See #10336.
diff --git a/libs/libcurl/src/config-amigaos.h b/libs/libcurl/src/config-amigaos.h
index 26bd2a6b5f..ebb53eac06 100644
--- a/libs/libcurl/src/config-amigaos.h
+++ b/libs/libcurl/src/config-amigaos.h
@@ -32,7 +32,6 @@
#define HAVE_ARPA_INET_H 1
#define HAVE_CLOSESOCKET_CAMEL 1
-#define HAVE_INTTYPES_H 1
#define HAVE_IOCTLSOCKET_CAMEL 1
#define HAVE_IOCTLSOCKET_CAMEL_FIONBIO 1
#define HAVE_LONGLONG 1
diff --git a/libs/libcurl/src/config-dos.h b/libs/libcurl/src/config-dos.h
index 92bb083e04..1e0368b98a 100644
--- a/libs/libcurl/src/config-dos.h
+++ b/libs/libcurl/src/config-dos.h
@@ -122,7 +122,6 @@
#define HAVE_SIGSETJMP 1
#define HAVE_SYS_TIME_H 1
#define HAVE_TERMIOS_H 1
- #define HAVE_VARIADIC_MACROS_GCC 1
#elif defined(__HIGHC__)
#define HAVE_SYS_TIME_H 1
diff --git a/libs/libcurl/src/config-os400.h b/libs/libcurl/src/config-os400.h
index ff7b8afaa5..355399a1bc 100644
--- a/libs/libcurl/src/config-os400.h
+++ b/libs/libcurl/src/config-os400.h
@@ -104,9 +104,6 @@
/* Define if you have the `timeval' struct. */
#define HAVE_STRUCT_TIMEVAL
-/* Define if you have the <inttypes.h> header file. */
-#define HAVE_INTTYPES_H
-
/* Define if you have the <io.h> header file. */
#undef HAVE_IO_H
@@ -152,9 +149,6 @@
/* Define if you have the `socket' function. */
#define HAVE_SOCKET
-/* Define if you have the <stdint.h> header file. */
-#undef HAVE_STDINT_H
-
/* The following define is needed on OS400 to enable strcmpi(), stricmp() and
strdup(). */
diff --git a/libs/libcurl/src/config-plan9.h b/libs/libcurl/src/config-plan9.h
index e667cbd378..be30f883c6 100644
--- a/libs/libcurl/src/config-plan9.h
+++ b/libs/libcurl/src/config-plan9.h
@@ -91,7 +91,6 @@
#define HAVE_GMTIME_R 1
#define HAVE_INET_NTOP 1
#define HAVE_INET_PTON 1
-#define HAVE_INTTYPES_H 1
#define HAVE_LIBGEN_H 1
#define HAVE_LIBZ 1
#define HAVE_LOCALE_H 1
@@ -117,7 +116,6 @@
#define HAVE_SOCKET 1
#define HAVE_SSL_GET_SHUTDOWN 1
#define HAVE_STDBOOL_H 1
-#define HAVE_STDINT_H 1
#define HAVE_STRCASECMP 1
#define HAVE_STRDUP 1
#define HAVE_STRTOK_R 1
diff --git a/libs/libcurl/src/config-riscos.h b/libs/libcurl/src/config-riscos.h
index cab2472e32..7add4d42d5 100644
--- a/libs/libcurl/src/config-riscos.h
+++ b/libs/libcurl/src/config-riscos.h
@@ -108,9 +108,6 @@
/* Define if you have the `timeval' struct. */
#define HAVE_STRUCT_TIMEVAL
-/* Define if you have the <inttypes.h> header file. */
-#define HAVE_INTTYPES_H
-
/* Define if you have the <io.h> header file. */
#undef HAVE_IO_H
@@ -144,9 +141,6 @@
/* Define if you have the `socket' function. */
#define HAVE_SOCKET
-/* Define if you have the <stdint.h> header file. */
-#undef HAVE_STDINT_H
-
/* Define if you have the `strcasecmp' function. */
#undef HAVE_STRCASECMP
diff --git a/libs/libcurl/src/config-win32.h b/libs/libcurl/src/config-win32.h
index 486d5ccab1..d7856dd4b7 100644
--- a/libs/libcurl/src/config-win32.h
+++ b/libs/libcurl/src/config-win32.h
@@ -38,17 +38,6 @@
/* Define if you have the <fcntl.h> header file. */
#define HAVE_FCNTL_H 1
-/* Define to 1 if you have the <inttypes.h> header file. */
-#if (defined(_MSC_VER) && (_MSC_VER >= 1800)) || defined(__MINGW32__)
-#define HAVE_INTTYPES_H 1
-#endif
-
-/* Define to 1 if you have the <stdint.h> header file. */
-#if (defined(_MSC_VER) && (_MSC_VER >= 1600)) || defined(__MINGW32__) || \
- (defined(__BORLANDC__) && (__BORLANDC__ >= 0x0582)) || defined(__POCC__)
-#define HAVE_STDINT_H 1
-#endif
-
/* Define if you have the <io.h> header file. */
#define HAVE_IO_H 1
@@ -56,9 +45,7 @@
#define HAVE_LOCALE_H 1
/* Define if you need <malloc.h> header even with <stdlib.h> header file. */
-#if !defined(__SALFORDC__) && !defined(__POCC__)
#define NEED_MALLOC_H 1
-#endif
/* Define if you have the <netdb.h> header file. */
/* #define HAVE_NETDB_H 1 */
@@ -72,7 +59,9 @@
#endif
/* Define if you have the <sys/param.h> header file. */
-/* #define HAVE_SYS_PARAM_H 1 */
+#if defined(__MINGW32__)
+#define HAVE_SYS_PARAM_H 1
+#endif
/* Define if you have the <sys/select.h> header file. */
/* #define HAVE_SYS_SELECT_H 1 */
@@ -87,15 +76,15 @@
#define HAVE_SYS_STAT_H 1
/* Define if you have the <sys/time.h> header file. */
-/* #define HAVE_SYS_TIME_H 1 */
+#if defined(__MINGW32__)
+#define HAVE_SYS_TIME_H 1
+#endif
/* Define if you have the <sys/types.h> header file. */
#define HAVE_SYS_TYPES_H 1
/* Define if you have the <sys/utime.h> header file. */
-#ifndef __BORLANDC__
#define HAVE_SYS_UTIME_H 1
-#endif
/* Define if you have the <termio.h> header file. */
/* #define HAVE_TERMIO_H 1 */
@@ -104,7 +93,7 @@
/* #define HAVE_TERMIOS_H 1 */
/* Define if you have the <unistd.h> header file. */
-#if defined(__MINGW32__) || defined(__LCC__) || defined(__POCC__)
+#if defined(__MINGW32__)
#define HAVE_UNISTD_H 1
#endif
@@ -112,14 +101,10 @@
#define HAVE_WINDOWS_H 1
/* Define if you have the <winsock2.h> header file. */
-#ifndef __SALFORDC__
#define HAVE_WINSOCK2_H 1
-#endif
/* Define if you have the <ws2tcpip.h> header file. */
-#ifndef __SALFORDC__
#define HAVE_WS2TCPIP_H 1
-#endif
/* Define to 1 if you have the <libgen.h> header file. */
#if defined(__MINGW32__)
@@ -160,7 +145,9 @@
#define HAVE_GETHOSTNAME 1
/* Define if you have the gettimeofday function. */
-/* #define HAVE_GETTIMEOFDAY 1 */
+#if defined(__MINGW32__)
+#define HAVE_GETTIMEOFDAY 1
+#endif
/* Define if you have the ioctlsocket function. */
#define HAVE_IOCTLSOCKET 1
@@ -180,10 +167,6 @@
/* Define if you have the socket function. */
#define HAVE_SOCKET 1
-/* Define if libSSH2 is in use */
-#define USE_LIBSSH2 1
-#define HAVE_LIBSSH2_H 1
-
/* Define if you have the strcasecmp function. */
#if defined(__MINGW32__)
#define HAVE_STRCASECMP 1
@@ -196,15 +179,12 @@
#define HAVE_STRICMP 1
/* Define if you have the strtoll function. */
-#if defined(__MINGW32__) || defined(__POCC__) || \
- (defined(_MSC_VER) && (_MSC_VER >= 1800))
+#if (defined(_MSC_VER) && (_MSC_VER >= 1800)) || defined(__MINGW32__)
#define HAVE_STRTOLL 1
#endif
/* Define if you have the utime function. */
-#ifndef __BORLANDC__
#define HAVE_UTIME 1
-#endif
/* Define if you have the recv function. */
#define HAVE_RECV 1
@@ -246,7 +226,7 @@
#define SEND_TYPE_RETV int
/* Define to 1 if you have the snprintf function. */
-#if defined(_MSC_VER) && (_MSC_VER >= 1900)
+#if (defined(_MSC_VER) && (_MSC_VER >= 1900)) || defined(__MINGW32__)
#define HAVE_SNPRINTF 1
#endif
@@ -279,7 +259,7 @@
/* Define if ssize_t is not an available 'typedefed' type. */
#ifndef _SSIZE_T_DEFINED
-# if defined(__POCC__) || defined(__MINGW32__)
+# if defined(__MINGW32__)
# elif defined(_WIN64)
# define _SSIZE_T_DEFINED
# define ssize_t __int64
@@ -329,8 +309,6 @@
# undef RECV_TYPE_ARG3
# undef SEND_TYPE_ARG1
# undef SEND_TYPE_ARG3
-# define HAVE_FREEADDRINFO
-# define HAVE_GETADDRINFO
# define HAVE_GETHOSTBYNAME_R
# define HAVE_GETHOSTBYNAME_R_6
# define LWIP_POSIX_SOCKETS_IO_NAMES 0
@@ -351,13 +329,11 @@
#undef USE_WINSOCK
#undef HAVE_WINSOCK2_H
#undef HAVE_WS2TCPIP_H
- #define HAVE_GETADDRINFO
#define HAVE_SYS_IOCTL_H
#define HAVE_SYS_SOCKET_H
#define HAVE_NETINET_IN_H
#define HAVE_NETDB_H
#define HAVE_ARPA_INET_H
- #define HAVE_FREEADDRINFO
#define SOCKET int
#endif
@@ -375,15 +351,8 @@
/* Windows should not have HAVE_GMTIME_R defined */
/* #undef HAVE_GMTIME_R */
-/* Define if the compiler supports C99 variadic macro style. */
-#if defined(_MSC_VER) && (_MSC_VER >= 1400)
-#define HAVE_VARIADIC_MACROS_C99 1
-#endif
-
/* Define if the compiler supports the 'long long' data type. */
-#if defined(__MINGW32__) || \
- (defined(_MSC_VER) && (_MSC_VER >= 1310)) || \
- (defined(__BORLANDC__) && (__BORLANDC__ >= 0x561))
+#if (defined(_MSC_VER) && (_MSC_VER >= 1310)) || defined(__MINGW32__)
#define HAVE_LONGLONG 1
#endif
@@ -465,53 +434,17 @@ Vista
# endif
#endif
-/* When no build target is specified Pelles C 5.00 and later default build
- target is Windows Vista. We override default target to be Windows 2000. */
-#if defined(__POCC__) && (__POCC__ >= 500)
-# ifndef _WIN32_WINNT
-# define _WIN32_WINNT 0x0500
-# endif
-# ifndef WINVER
-# define WINVER 0x0500
-# endif
-#endif
-
-/* Availability of freeaddrinfo, getaddrinfo, and if_nametoindex
- functions is quite convoluted, compiler dependent and even build target
- dependent. */
-#if defined(HAVE_WS2TCPIP_H)
-# if defined(__POCC__)
-# define HAVE_FREEADDRINFO 1
-# define HAVE_GETADDRINFO 1
-# define HAVE_GETADDRINFO_THREADSAFE 1
-# elif defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0501)
-# define HAVE_FREEADDRINFO 1
-# define HAVE_GETADDRINFO 1
-# define HAVE_GETADDRINFO_THREADSAFE 1
-# elif defined(_MSC_VER) && (_MSC_VER >= 1200)
-# define HAVE_FREEADDRINFO 1
-# define HAVE_GETADDRINFO 1
-# define HAVE_GETADDRINFO_THREADSAFE 1
-# endif
-#endif
-
-#if defined(__POCC__)
-# ifndef _MSC_VER
-# error Microsoft extensions /Ze compiler option is required
-# endif
-# ifndef __POCC__OLDNAMES
-# error Compatibility names /Go compiler option is required
-# endif
-#endif
+/* Windows XP is required for freeaddrinfo, getaddrinfo */
+#define HAVE_FREEADDRINFO 1
+#define HAVE_GETADDRINFO 1
+#define HAVE_GETADDRINFO_THREADSAFE 1
/* ---------------------------------------------------------------- */
/* STRUCT RELATED */
/* ---------------------------------------------------------------- */
/* Define if you have struct sockaddr_storage. */
-#if !defined(__SALFORDC__) && !defined(__BORLANDC__)
#define HAVE_STRUCT_SOCKADDR_STORAGE 1
-#endif
/* Define if you have struct timeval. */
#define HAVE_STRUCT_TIMEVAL 1
@@ -535,10 +468,6 @@ Vista
# define USE_WIN32_LARGE_FILES
#endif
-#if defined(__POCC__)
-# undef USE_WIN32_LARGE_FILES
-#endif
-
#if !defined(USE_WIN32_LARGE_FILES) && !defined(USE_WIN32_SMALL_FILES)
# define USE_WIN32_SMALL_FILES
#endif
@@ -600,13 +529,6 @@ Vista
#define USE_WIN32_LDAP 1
#endif
-#if defined(__POCC__) && defined(USE_WIN32_LDAP)
-# define CURL_DISABLE_LDAP 1
-#endif
-
-/* if SSL is enabled */
-#define USE_OPENSSL 1
-
/* Define to use the Windows crypto library. */
#if !defined(CURL_WINDOWS_APP)
#define USE_WIN32_CRYPTO
@@ -642,7 +564,7 @@ Vista
/* If you want to build curl with the built-in manual */
#define USE_MANUAL 1
-#if defined(__POCC__) || defined(USE_IPV6)
+#if defined(USE_IPV6)
# define ENABLE_IPV6 1
#endif
diff --git a/libs/libcurl/src/config-win32ce.h b/libs/libcurl/src/config-win32ce.h
index 6898be9575..70a95d0411 100644
--- a/libs/libcurl/src/config-win32ce.h
+++ b/libs/libcurl/src/config-win32ce.h
@@ -81,7 +81,7 @@
/* #define HAVE_TERMIOS_H 1 */
/* Define if you have the <unistd.h> header file. */
-#if defined(__MINGW32__) || defined(__LCC__)
+#if defined(__MINGW32__)
#define HAVE_UNISTD_H 1
#endif
@@ -190,8 +190,7 @@
#define in_addr_t unsigned long
/* Define ssize_t if it is not an available 'typedefed' type */
-#if defined(__POCC__)
-#elif defined(_WIN64)
+#if defined(_WIN64)
#define ssize_t __int64
#else
#define ssize_t int
diff --git a/libs/libcurl/src/conncache.c b/libs/libcurl/src/conncache.c
index fae7c0b057..de05e7494f 100644
--- a/libs/libcurl/src/conncache.c
+++ b/libs/libcurl/src/conncache.c
@@ -107,7 +107,7 @@ int Curl_conncache_init(struct conncache *connc, int size)
connc->closure_handle = curl_easy_init();
if(!connc->closure_handle)
return 1; /* bad */
- connc->closure_handle->internal = true;
+ connc->closure_handle->state.internal = true;
Curl_hash_init(&connc->hash, size, Curl_hash_str,
Curl_str_key_compare, free_bundle_hash_entry);
@@ -243,7 +243,7 @@ CURLcode Curl_conncache_add_conn(struct Curl_easy *data)
conn->connection_id = connc->next_connection_id++;
connc->num_conn++;
- DEBUGF(infof(data, "Added connection %ld. "
+ DEBUGF(infof(data, "Added connection %" CURL_FORMAT_CURL_OFF_T ". "
"The cache now contains %zu members",
conn->connection_id, connc->num_conn));
@@ -379,21 +379,26 @@ conncache_find_first_connection(struct conncache *connc)
bool Curl_conncache_return_conn(struct Curl_easy *data,
struct connectdata *conn)
{
- /* data->multi->maxconnects can be negative, deal with it. */
- size_t maxconnects =
- (data->multi->maxconnects < 0) ? data->multi->num_easy * 4:
- data->multi->maxconnects;
+ unsigned int maxconnects = !data->multi->maxconnects ?
+ data->multi->num_easy * 4: data->multi->maxconnects;
struct connectdata *conn_candidate = NULL;
conn->lastused = Curl_now(); /* it was used up until now */
- if(maxconnects > 0 &&
- Curl_conncache_size(data) > maxconnects) {
+ if(maxconnects && Curl_conncache_size(data) > maxconnects) {
infof(data, "Connection cache is full, closing the oldest one");
conn_candidate = Curl_conncache_extract_oldest(data);
if(conn_candidate) {
- /* the winner gets the honour of being disconnected */
- Curl_disconnect(data, conn_candidate, /* dead_connection */ FALSE);
+ /* Use the closure handle for this disconnect so that anything that
+ happens during the disconnect is not stored and associated with the
+ 'data' handle which already just finished a transfer and it is
+ important that details from this (unrelated) disconnect does not
+ taint meta-data in the data handle. */
+ struct conncache *connc = data->state.conn_cache;
+ connc->closure_handle->state.buffer = data->state.buffer;
+ connc->closure_handle->set.buffer_size = data->set.buffer_size;
+ Curl_disconnect(connc->closure_handle, conn_candidate,
+ /* dead_connection */ FALSE);
}
}
diff --git a/libs/libcurl/src/connect.c b/libs/libcurl/src/connect.c
index ccc7bcda96..4e77d275e5 100644
--- a/libs/libcurl/src/connect.c
+++ b/libs/libcurl/src/connect.c
@@ -84,6 +84,9 @@
#include "curl_memory.h"
#include "memdebug.h"
+#ifndef ARRAYSIZE
+#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0]))
+#endif
/*
* Curl_timeleft() returns the amount of milliseconds left allowed for the
@@ -348,6 +351,7 @@ void Curl_conncontrol(struct connectdata *conn,
*/
struct eyeballer {
const char *name;
+ const struct Curl_addrinfo *first; /* complete address list, not owned */
const struct Curl_addrinfo *addr; /* List of addresses to try, not owned */
int ai_family; /* matching address family only */
cf_ip_connect_create *cf_create; /* for creating cf */
@@ -359,9 +363,12 @@ struct eyeballer {
expire_id timeout_id; /* ID for Curl_expire() */
CURLcode result;
int error;
+ BIT(rewinded); /* if we rewinded the addr list */
BIT(has_started); /* attempts have started */
BIT(is_done); /* out of addresses/time */
BIT(connected); /* cf has connected */
+ BIT(inconclusive); /* connect was not a hard failure, we
+ * might talk to a restarting server */
};
@@ -408,7 +415,7 @@ static CURLcode eyeballer_new(struct eyeballer **pballer,
#endif
"ip"));
baller->cf_create = cf_create;
- baller->addr = addr;
+ baller->first = baller->addr = addr;
baller->ai_family = ai_family;
baller->primary = primary;
baller->delay_ms = delay_ms;
@@ -438,6 +445,13 @@ static void baller_free(struct eyeballer *baller,
}
}
+static void baller_rewind(struct eyeballer *baller)
+{
+ baller->rewinded = TRUE;
+ baller->addr = baller->first;
+ baller->inconclusive = FALSE;
+}
+
static void baller_next_addr(struct eyeballer *baller)
{
baller->addr = addr_next_match(baller->addr, baller->ai_family);
@@ -528,6 +542,10 @@ static CURLcode baller_start_next(struct Curl_cfilter *cf,
{
if(cf->sockindex == FIRSTSOCKET) {
baller_next_addr(baller);
+ /* If we get inconclusive answers from the server(s), we make
+ * a second iteration over the address list */
+ if(!baller->addr && baller->inconclusive && !baller->rewinded)
+ baller_rewind(baller);
baller_start(cf, data, baller, timeoutms);
}
else {
@@ -566,6 +584,8 @@ static CURLcode baller_connect(struct Curl_cfilter *cf,
baller->result = CURLE_OPERATION_TIMEDOUT;
}
}
+ else if(baller->result == CURLE_WEIRD_SERVER_REPLY)
+ baller->inconclusive = TRUE;
}
return baller->result;
}
@@ -595,7 +615,7 @@ evaluate:
*connected = FALSE; /* a very negative world view is best */
now = Curl_now();
ongoing = not_started = 0;
- for(i = 0; i < sizeof(ctx->baller)/sizeof(ctx->baller[0]); i++) {
+ for(i = 0; i < ARRAYSIZE(ctx->baller); i++) {
struct eyeballer *baller = ctx->baller[i];
if(!baller || baller->is_done)
@@ -656,7 +676,7 @@ evaluate:
if(not_started > 0) {
int added = 0;
- for(i = 0; i < sizeof(ctx->baller)/sizeof(ctx->baller[0]); i++) {
+ for(i = 0; i < ARRAYSIZE(ctx->baller); i++) {
struct eyeballer *baller = ctx->baller[i];
if(!baller || baller->has_started)
@@ -691,13 +711,13 @@ evaluate:
/* all ballers have failed to connect. */
CURL_TRC_CF(data, cf, "all eyeballers failed");
result = CURLE_COULDNT_CONNECT;
- for(i = 0; i < sizeof(ctx->baller)/sizeof(ctx->baller[0]); i++) {
+ for(i = 0; i < ARRAYSIZE(ctx->baller); i++) {
struct eyeballer *baller = ctx->baller[i];
+ if(!baller)
+ continue;
CURL_TRC_CF(data, cf, "%s assess started=%d, result=%d",
- baller?baller->name:NULL,
- baller?baller->has_started:0,
- baller?baller->result:0);
- if(baller && baller->has_started && baller->result) {
+ baller->name, baller->has_started, baller->result);
+ if(baller->has_started && baller->result) {
result = baller->result;
break;
}
@@ -838,7 +858,7 @@ static void cf_he_ctx_clear(struct Curl_cfilter *cf, struct Curl_easy *data)
DEBUGASSERT(ctx);
DEBUGASSERT(data);
- for(i = 0; i < sizeof(ctx->baller)/sizeof(ctx->baller[0]); i++) {
+ for(i = 0; i < ARRAYSIZE(ctx->baller); i++) {
baller_free(ctx->baller[i], data);
ctx->baller[i] = NULL;
}
@@ -846,35 +866,22 @@ static void cf_he_ctx_clear(struct Curl_cfilter *cf, struct Curl_easy *data)
ctx->winner = NULL;
}
-static int cf_he_get_select_socks(struct Curl_cfilter *cf,
+static void cf_he_adjust_pollset(struct Curl_cfilter *cf,
struct Curl_easy *data,
- curl_socket_t *socks)
+ struct easy_pollset *ps)
{
struct cf_he_ctx *ctx = cf->ctx;
- size_t i, s;
- int wrc, rc = GETSOCK_BLANK;
- curl_socket_t wsocks[MAX_SOCKSPEREASYHANDLE];
-
- if(cf->connected)
- return cf->next->cft->get_select_socks(cf->next, data, socks);
-
- for(i = s = 0; i < sizeof(ctx->baller)/sizeof(ctx->baller[0]); i++) {
- struct eyeballer *baller = ctx->baller[i];
- if(!baller || !baller->cf)
- continue;
+ size_t i;
- wrc = Curl_conn_cf_get_select_socks(baller->cf, data, wsocks);
- if(wrc) {
- /* TODO: we assume we get at most one socket back */
- socks[s] = wsocks[0];
- if(wrc & GETSOCK_WRITESOCK(0))
- rc |= GETSOCK_WRITESOCK(s);
- if(wrc & GETSOCK_READSOCK(0))
- rc |= GETSOCK_READSOCK(s);
- s++;
+ if(!cf->connected) {
+ for(i = 0; i < ARRAYSIZE(ctx->baller); i++) {
+ struct eyeballer *baller = ctx->baller[i];
+ if(!baller || !baller->cf)
+ continue;
+ Curl_conn_cf_adjust_pollset(baller->cf, data, ps);
}
+ CURL_TRC_CF(data, cf, "adjust_pollset -> %d socks", ps->num);
}
- return rc;
}
static CURLcode cf_he_connect(struct Curl_cfilter *cf,
@@ -956,7 +963,7 @@ static bool cf_he_data_pending(struct Curl_cfilter *cf,
if(cf->connected)
return cf->next->cft->has_data_pending(cf->next, data);
- for(i = 0; i < sizeof(ctx->baller)/sizeof(ctx->baller[0]); i++) {
+ for(i = 0; i < ARRAYSIZE(ctx->baller); i++) {
struct eyeballer *baller = ctx->baller[i];
if(!baller || !baller->cf)
continue;
@@ -975,7 +982,7 @@ static struct curltime get_max_baller_time(struct Curl_cfilter *cf,
size_t i;
memset(&tmax, 0, sizeof(tmax));
- for(i = 0; i < sizeof(ctx->baller)/sizeof(ctx->baller[0]); i++) {
+ for(i = 0; i < ARRAYSIZE(ctx->baller); i++) {
struct eyeballer *baller = ctx->baller[i];
memset(&t, 0, sizeof(t));
@@ -1000,7 +1007,7 @@ static CURLcode cf_he_query(struct Curl_cfilter *cf,
int reply_ms = -1;
size_t i;
- for(i = 0; i < sizeof(ctx->baller)/sizeof(ctx->baller[0]); i++) {
+ for(i = 0; i < ARRAYSIZE(ctx->baller); i++) {
struct eyeballer *baller = ctx->baller[i];
int breply_ms;
@@ -1055,7 +1062,7 @@ struct Curl_cftype Curl_cft_happy_eyeballs = {
cf_he_connect,
cf_he_close,
Curl_cf_def_get_host,
- cf_he_get_select_socks,
+ cf_he_adjust_pollset,
cf_he_data_pending,
Curl_cf_def_send,
Curl_cf_def_recv,
@@ -1089,7 +1096,7 @@ cf_happy_eyeballs_create(struct Curl_cfilter **pcf,
(void)data;
(void)conn;
*pcf = NULL;
- ctx = calloc(sizeof(*ctx), 1);
+ ctx = calloc(1, sizeof(*ctx));
if(!ctx) {
result = CURLE_OUT_OF_MEMORY;
goto out;
@@ -1122,13 +1129,13 @@ struct transport_provider transport_providers[] = {
#ifdef ENABLE_QUIC
{ TRNSPRT_QUIC, Curl_cf_quic_create },
#endif
+#ifndef CURL_DISABLE_TFTP
{ TRNSPRT_UDP, Curl_cf_udp_create },
+#endif
+#ifdef USE_UNIX_SOCKETS
{ TRNSPRT_UNIX, Curl_cf_unix_create },
-};
-
-#ifndef ARRAYSIZE
-#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0]))
#endif
+};
static cf_ip_connect_create *get_cf_create(int transport)
{
@@ -1319,7 +1326,7 @@ struct Curl_cftype Curl_cft_setup = {
cf_setup_connect,
cf_setup_close,
Curl_cf_def_get_host,
- Curl_cf_def_get_select_socks,
+ Curl_cf_def_adjust_pollset,
Curl_cf_def_data_pending,
Curl_cf_def_send,
Curl_cf_def_recv,
@@ -1340,7 +1347,7 @@ static CURLcode cf_setup_create(struct Curl_cfilter **pcf,
CURLcode result = CURLE_OK;
(void)data;
- ctx = calloc(sizeof(*ctx), 1);
+ ctx = calloc(1, sizeof(*ctx));
if(!ctx) {
result = CURLE_OUT_OF_MEMORY;
goto out;
diff --git a/libs/libcurl/src/content_encoding.c b/libs/libcurl/src/content_encoding.c
index b1a64ebd52..2ea5e140be 100644
--- a/libs/libcurl/src/content_encoding.c
+++ b/libs/libcurl/src/content_encoding.c
@@ -63,6 +63,9 @@
#ifndef CURL_DISABLE_HTTP
+/* allow no more than 5 "chained" compression steps */
+#define MAX_ENCODE_STACK 5
+
#define DSIZ CURL_MAX_WRITE_SIZE /* buffer size for decompressed data */
@@ -95,7 +98,7 @@ typedef enum {
/* Deflate and gzip writer. */
struct zlib_writer {
- struct contenc_writer super;
+ struct Curl_cwriter super;
zlibInitState zlib_init; /* zlib init state */
uInt trailerlen; /* Remaining trailer byte count. */
z_stream z; /* State structure for zlib. */
@@ -171,7 +174,7 @@ static CURLcode process_trailer(struct Curl_easy *data,
}
static CURLcode inflate_stream(struct Curl_easy *data,
- struct contenc_writer *writer,
+ struct Curl_cwriter *writer, int type,
zlibInitState started)
{
struct zlib_writer *zp = (struct zlib_writer *) writer;
@@ -196,7 +199,7 @@ static CURLcode inflate_stream(struct Curl_easy *data,
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. */
+ the client via next_write function. */
while(!done) {
int status; /* zlib status */
done = TRUE;
@@ -217,7 +220,7 @@ static CURLcode inflate_stream(struct Curl_easy *data,
if(z->avail_out != DSIZ) {
if(status == Z_OK || status == Z_STREAM_END) {
zp->zlib_init = started; /* Data started. */
- result = Curl_unencode_write(data, writer->downstream, decomp,
+ result = Curl_cwriter_write(data, writer->next, type, decomp,
DSIZ - z->avail_out);
if(result) {
exit_zlib(data, z, &zp->zlib_init, result);
@@ -274,8 +277,8 @@ static CURLcode inflate_stream(struct Curl_easy *data,
/* Deflate handler. */
-static CURLcode deflate_init_writer(struct Curl_easy *data,
- struct contenc_writer *writer)
+static CURLcode deflate_do_init(struct Curl_easy *data,
+ struct Curl_cwriter *writer)
{
struct zlib_writer *zp = (struct zlib_writer *) writer;
z_stream *z = &zp->z; /* zlib state structure */
@@ -290,13 +293,16 @@ static CURLcode deflate_init_writer(struct Curl_easy *data,
return CURLE_OK;
}
-static CURLcode deflate_unencode_write(struct Curl_easy *data,
- struct contenc_writer *writer,
+static CURLcode deflate_do_write(struct Curl_easy *data,
+ struct Curl_cwriter *writer, int type,
const char *buf, size_t nbytes)
{
struct zlib_writer *zp = (struct zlib_writer *) writer;
z_stream *z = &zp->z; /* zlib state structure */
+ if(!(type & CLIENTWRITE_BODY))
+ return Curl_cwriter_write(data, writer->next, type, buf, nbytes);
+
/* Set the compressed input when this function is called */
z->next_in = (Bytef *) buf;
z->avail_in = (uInt) nbytes;
@@ -305,11 +311,11 @@ static CURLcode deflate_unencode_write(struct Curl_easy *data,
return process_trailer(data, zp);
/* Now uncompress the data */
- return inflate_stream(data, writer, ZLIB_INFLATING);
+ return inflate_stream(data, writer, type, ZLIB_INFLATING);
}
-static void deflate_close_writer(struct Curl_easy *data,
- struct contenc_writer *writer)
+static void deflate_do_close(struct Curl_easy *data,
+ struct Curl_cwriter *writer)
{
struct zlib_writer *zp = (struct zlib_writer *) writer;
z_stream *z = &zp->z; /* zlib state structure */
@@ -317,19 +323,19 @@ static void deflate_close_writer(struct Curl_easy *data,
exit_zlib(data, z, &zp->zlib_init, CURLE_OK);
}
-static const struct content_encoding deflate_encoding = {
+static const struct Curl_cwtype deflate_encoding = {
"deflate",
NULL,
- deflate_init_writer,
- deflate_unencode_write,
- deflate_close_writer,
+ deflate_do_init,
+ deflate_do_write,
+ deflate_do_close,
sizeof(struct zlib_writer)
};
/* Gzip handler. */
-static CURLcode gzip_init_writer(struct Curl_easy *data,
- struct contenc_writer *writer)
+static CURLcode gzip_do_init(struct Curl_easy *data,
+ struct Curl_cwriter *writer)
{
struct zlib_writer *zp = (struct zlib_writer *) writer;
z_stream *z = &zp->z; /* zlib state structure */
@@ -441,19 +447,22 @@ static enum {
}
#endif
-static CURLcode gzip_unencode_write(struct Curl_easy *data,
- struct contenc_writer *writer,
+static CURLcode gzip_do_write(struct Curl_easy *data,
+ struct Curl_cwriter *writer, int type,
const char *buf, size_t nbytes)
{
struct zlib_writer *zp = (struct zlib_writer *) writer;
z_stream *z = &zp->z; /* zlib state structure */
+ if(!(type & CLIENTWRITE_BODY))
+ return Curl_cwriter_write(data, writer->next, type, buf, nbytes);
+
if(zp->zlib_init == ZLIB_INIT_GZIP) {
/* Let zlib handle the gzip decompression entirely */
z->next_in = (Bytef *) buf;
z->avail_in = (uInt) nbytes;
/* Now uncompress the data */
- return inflate_stream(data, writer, ZLIB_INIT_GZIP);
+ return inflate_stream(data, writer, type, ZLIB_INIT_GZIP);
}
#ifndef OLD_ZLIB_SUPPORT
@@ -565,12 +574,12 @@ static CURLcode gzip_unencode_write(struct Curl_easy *data,
}
/* We've parsed the header, now uncompress the data */
- return inflate_stream(data, writer, ZLIB_GZIP_INFLATING);
+ return inflate_stream(data, writer, type, ZLIB_GZIP_INFLATING);
#endif
}
-static void gzip_close_writer(struct Curl_easy *data,
- struct contenc_writer *writer)
+static void gzip_do_close(struct Curl_easy *data,
+ struct Curl_cwriter *writer)
{
struct zlib_writer *zp = (struct zlib_writer *) writer;
z_stream *z = &zp->z; /* zlib state structure */
@@ -578,12 +587,12 @@ static void gzip_close_writer(struct Curl_easy *data,
exit_zlib(data, z, &zp->zlib_init, CURLE_OK);
}
-static const struct content_encoding gzip_encoding = {
+static const struct Curl_cwtype gzip_encoding = {
"gzip",
"x-gzip",
- gzip_init_writer,
- gzip_unencode_write,
- gzip_close_writer,
+ gzip_do_init,
+ gzip_do_write,
+ gzip_do_close,
sizeof(struct zlib_writer)
};
@@ -593,7 +602,7 @@ static const struct content_encoding gzip_encoding = {
#ifdef HAVE_BROTLI
/* Brotli writer. */
struct brotli_writer {
- struct contenc_writer super;
+ struct Curl_cwriter super;
BrotliDecoderState *br; /* State structure for brotli. */
};
@@ -635,8 +644,8 @@ static CURLcode brotli_map_error(BrotliDecoderErrorCode be)
return CURLE_WRITE_ERROR;
}
-static CURLcode brotli_init_writer(struct Curl_easy *data,
- struct contenc_writer *writer)
+static CURLcode brotli_do_init(struct Curl_easy *data,
+ struct Curl_cwriter *writer)
{
struct brotli_writer *bp = (struct brotli_writer *) writer;
(void) data;
@@ -645,8 +654,8 @@ static CURLcode brotli_init_writer(struct Curl_easy *data,
return bp->br? CURLE_OK: CURLE_OUT_OF_MEMORY;
}
-static CURLcode brotli_unencode_write(struct Curl_easy *data,
- struct contenc_writer *writer,
+static CURLcode brotli_do_write(struct Curl_easy *data,
+ struct Curl_cwriter *writer, int type,
const char *buf, size_t nbytes)
{
struct brotli_writer *bp = (struct brotli_writer *) writer;
@@ -657,6 +666,9 @@ static CURLcode brotli_unencode_write(struct Curl_easy *data,
CURLcode result = CURLE_OK;
BrotliDecoderResult r = BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT;
+ if(!(type & CLIENTWRITE_BODY))
+ return Curl_cwriter_write(data, writer->next, type, buf, nbytes);
+
if(!bp->br)
return CURLE_WRITE_ERROR; /* Stream already ended. */
@@ -670,7 +682,7 @@ static CURLcode brotli_unencode_write(struct Curl_easy *data,
dstleft = DSIZ;
r = BrotliDecoderDecompressStream(bp->br,
&nbytes, &src, &dstleft, &dst, NULL);
- result = Curl_unencode_write(data, writer->downstream,
+ result = Curl_cwriter_write(data, writer->next, type,
decomp, DSIZ - dstleft);
if(result)
break;
@@ -693,8 +705,8 @@ static CURLcode brotli_unencode_write(struct Curl_easy *data,
return result;
}
-static void brotli_close_writer(struct Curl_easy *data,
- struct contenc_writer *writer)
+static void brotli_do_close(struct Curl_easy *data,
+ struct Curl_cwriter *writer)
{
struct brotli_writer *bp = (struct brotli_writer *) writer;
@@ -706,12 +718,12 @@ static void brotli_close_writer(struct Curl_easy *data,
}
}
-static const struct content_encoding brotli_encoding = {
+static const struct Curl_cwtype brotli_encoding = {
"br",
NULL,
- brotli_init_writer,
- brotli_unencode_write,
- brotli_close_writer,
+ brotli_do_init,
+ brotli_do_write,
+ brotli_do_close,
sizeof(struct brotli_writer)
};
#endif
@@ -720,13 +732,13 @@ static const struct content_encoding brotli_encoding = {
#ifdef HAVE_ZSTD
/* Zstd writer. */
struct zstd_writer {
- struct contenc_writer super;
+ struct Curl_cwriter super;
ZSTD_DStream *zds; /* State structure for zstd. */
void *decomp;
};
-static CURLcode zstd_init_writer(struct Curl_easy *data,
- struct contenc_writer *writer)
+static CURLcode zstd_do_init(struct Curl_easy *data,
+ struct Curl_cwriter *writer)
{
struct zstd_writer *zp = (struct zstd_writer *) writer;
@@ -737,8 +749,8 @@ static CURLcode zstd_init_writer(struct Curl_easy *data,
return zp->zds ? CURLE_OK : CURLE_OUT_OF_MEMORY;
}
-static CURLcode zstd_unencode_write(struct Curl_easy *data,
- struct contenc_writer *writer,
+static CURLcode zstd_do_write(struct Curl_easy *data,
+ struct Curl_cwriter *writer, int type,
const char *buf, size_t nbytes)
{
CURLcode result = CURLE_OK;
@@ -747,6 +759,9 @@ static CURLcode zstd_unencode_write(struct Curl_easy *data,
ZSTD_outBuffer out;
size_t errorCode;
+ if(!(type & CLIENTWRITE_BODY))
+ return Curl_cwriter_write(data, writer->next, type, buf, nbytes);
+
if(!zp->decomp) {
zp->decomp = malloc(DSIZ);
if(!zp->decomp)
@@ -766,7 +781,7 @@ static CURLcode zstd_unencode_write(struct Curl_easy *data,
return CURLE_BAD_CONTENT_ENCODING;
}
if(out.pos > 0) {
- result = Curl_unencode_write(data, writer->downstream,
+ result = Curl_cwriter_write(data, writer->next, type,
zp->decomp, out.pos);
if(result)
break;
@@ -778,8 +793,8 @@ static CURLcode zstd_unencode_write(struct Curl_easy *data,
return result;
}
-static void zstd_close_writer(struct Curl_easy *data,
- struct contenc_writer *writer)
+static void zstd_do_close(struct Curl_easy *data,
+ struct Curl_cwriter *writer)
{
struct zstd_writer *zp = (struct zstd_writer *) writer;
@@ -795,52 +810,30 @@ static void zstd_close_writer(struct Curl_easy *data,
}
}
-static const struct content_encoding zstd_encoding = {
+static const struct Curl_cwtype zstd_encoding = {
"zstd",
NULL,
- zstd_init_writer,
- zstd_unencode_write,
- zstd_close_writer,
+ zstd_do_init,
+ zstd_do_write,
+ zstd_do_close,
sizeof(struct zstd_writer)
};
#endif
/* Identity handler. */
-static CURLcode identity_init_writer(struct Curl_easy *data,
- struct contenc_writer *writer)
-{
- (void)data;
- (void)writer;
- return CURLE_OK;
-}
-
-static CURLcode identity_unencode_write(struct Curl_easy *data,
- struct contenc_writer *writer,
- const char *buf, size_t nbytes)
-{
- return Curl_unencode_write(data, writer->downstream, buf, nbytes);
-}
-
-static void identity_close_writer(struct Curl_easy *data,
- struct contenc_writer *writer)
-{
- (void) data;
- (void) writer;
-}
-
-static const struct content_encoding identity_encoding = {
+static const struct Curl_cwtype identity_encoding = {
"identity",
"none",
- identity_init_writer,
- identity_unencode_write,
- identity_close_writer,
- sizeof(struct contenc_writer)
+ Curl_cwriter_def_init,
+ Curl_cwriter_def_write,
+ Curl_cwriter_def_close,
+ sizeof(struct Curl_cwriter)
};
/* supported content encodings table. */
-static const struct content_encoding * const encodings[] = {
+static const struct Curl_cwtype * const encodings[] = {
&identity_encoding,
#ifdef HAVE_LIBZ
&deflate_encoding,
@@ -856,13 +849,17 @@ static const struct content_encoding * const encodings[] = {
};
-/* Return a list of comma-separated names of supported encodings. */
-char *Curl_all_content_encodings(void)
+/* Provide a list of comma-separated names of supported encodings.
+*/
+void Curl_all_content_encodings(char *buf, size_t blen)
{
size_t len = 0;
- const struct content_encoding * const *cep;
- const struct content_encoding *ce;
- char *ace;
+ const struct Curl_cwtype * const *cep;
+ const struct Curl_cwtype *ce;
+
+ DEBUGASSERT(buf);
+ DEBUGASSERT(blen);
+ buf[0] = 0;
for(cep = encodings; *cep; cep++) {
ce = *cep;
@@ -870,12 +867,12 @@ char *Curl_all_content_encodings(void)
len += strlen(ce->name) + 2;
}
- if(!len)
- return strdup(CONTENT_ENCODING_DEFAULT);
-
- ace = malloc(len);
- if(ace) {
- char *p = ace;
+ if(!len) {
+ if(blen >= sizeof(CONTENT_ENCODING_DEFAULT))
+ strcpy(buf, CONTENT_ENCODING_DEFAULT);
+ }
+ else if(blen > len) {
+ char *p = buf;
for(cep = encodings; *cep; cep++) {
ce = *cep;
if(!strcasecompare(ce->name, CONTENT_ENCODING_DEFAULT)) {
@@ -887,75 +884,60 @@ char *Curl_all_content_encodings(void)
}
p[-2] = '\0';
}
-
- return ace;
}
-
/* Deferred error dummy writer. */
-static CURLcode error_init_writer(struct Curl_easy *data,
- struct contenc_writer *writer)
+static CURLcode error_do_init(struct Curl_easy *data,
+ struct Curl_cwriter *writer)
{
(void)data;
(void)writer;
return CURLE_OK;
}
-static CURLcode error_unencode_write(struct Curl_easy *data,
- struct contenc_writer *writer,
+static CURLcode error_do_write(struct Curl_easy *data,
+ struct Curl_cwriter *writer, int type,
const char *buf, size_t nbytes)
{
- char *all = Curl_all_content_encodings();
+ char all[256];
+ (void)Curl_all_content_encodings(all, sizeof(all));
(void) writer;
(void) buf;
(void) nbytes;
- if(!all)
- return CURLE_OUT_OF_MEMORY;
+ if(!(type & CLIENTWRITE_BODY))
+ return Curl_cwriter_write(data, writer->next, type, buf, nbytes);
+
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 Curl_easy *data,
- struct contenc_writer *writer)
+static void error_do_close(struct Curl_easy *data,
+ struct Curl_cwriter *writer)
{
(void) data;
(void) writer;
}
-static const struct content_encoding error_encoding = {
- NULL,
+static const struct Curl_cwtype error_writer = {
+ "ce-error",
NULL,
- error_init_writer,
- error_unencode_write,
- error_close_writer,
- sizeof(struct contenc_writer)
+ error_do_init,
+ error_do_write,
+ error_do_close,
+ sizeof(struct Curl_cwriter)
};
-/* Write data using an unencoding writer stack. "nbytes" is not
- allowed to be 0. */
-CURLcode Curl_unencode_write(struct Curl_easy *data,
- struct contenc_writer *writer,
- const char *buf, size_t nbytes)
-{
- if(!nbytes)
- return CURLE_OK;
- if(!writer)
- return CURLE_WRITE_ERROR;
- return writer->handler->unencode_write(data, writer, buf, nbytes);
-}
-
/* Find the content encoding by name. */
-static const struct content_encoding *find_encoding(const char *name,
+static const struct Curl_cwtype *find_encoding(const char *name,
size_t len)
{
- const struct content_encoding * const *cep;
+ const struct Curl_cwtype * const *cep;
for(cep = encodings; *cep; cep++) {
- const struct content_encoding *ce = *cep;
+ const struct Curl_cwtype *ce = *cep;
if((strncasecompare(name, ce->name, len) && !ce->name[len]) ||
(ce->alias && strncasecompare(name, ce->alias, len) && !ce->alias[len]))
return ce;
@@ -969,7 +951,8 @@ CURLcode Curl_build_unencoding_stack(struct Curl_easy *data,
const char *enclist, int is_transfer)
{
struct SingleRequest *k = &data->req;
- unsigned int order = is_transfer? 2: 1;
+ Curl_cwriter_phase phase = is_transfer?
+ CURL_CW_TRANSFER_DECODE:CURL_CW_CONTENT_DECODE;
CURLcode result;
do {
@@ -992,23 +975,32 @@ CURLcode Curl_build_unencoding_stack(struct Curl_easy *data,
Curl_httpchunk_init(data); /* init our chunky engine. */
}
else if(namelen) {
- const struct content_encoding *encoding;
- struct contenc_writer *writer;
- if(is_transfer && !data->set.http_transfer_encoding)
+ const struct Curl_cwtype *cwt;
+ struct Curl_cwriter *writer;
+
+ if((is_transfer && !data->set.http_transfer_encoding) ||
+ (!is_transfer && data->set.http_ce_skip)) {
/* not requested, ignore */
return CURLE_OK;
+ }
- encoding = find_encoding(name, namelen);
- if(!encoding)
- encoding = &error_encoding; /* Defer error at stack use. */
+ if(Curl_cwriter_count(data, phase) + 1 >= MAX_ENCODE_STACK) {
+ failf(data, "Reject response due to more than %u content encodings",
+ MAX_ENCODE_STACK);
+ return CURLE_BAD_CONTENT_ENCODING;
+ }
+
+ cwt = find_encoding(name, namelen);
+ if(!cwt)
+ cwt = &error_writer; /* Defer error at use. */
- result = Curl_client_create_writer(&writer, data, encoding, order);
+ result = Curl_cwriter_create(&writer, data, cwt, phase);
if(result)
return result;
- result = Curl_client_add_writer(data, writer);
+ result = Curl_cwriter_add(data, writer);
if(result) {
- Curl_client_free_writer(data, writer);
+ Curl_cwriter_free(data, writer);
return result;
}
}
@@ -1028,20 +1020,15 @@ CURLcode Curl_build_unencoding_stack(struct Curl_easy *data,
return CURLE_NOT_BUILT_IN;
}
-CURLcode Curl_unencode_write(struct Curl_easy *data,
- struct contenc_writer *writer,
- const char *buf, size_t nbytes)
+void Curl_all_content_encodings(char *buf, size_t blen)
{
- (void) data;
- (void) writer;
- (void) buf;
- (void) nbytes;
- return CURLE_NOT_BUILT_IN;
+ DEBUGASSERT(buf);
+ DEBUGASSERT(blen);
+ if(blen < sizeof(CONTENT_ENCODING_DEFAULT))
+ buf[0] = 0;
+ else
+ strcpy(buf, CONTENT_ENCODING_DEFAULT);
}
-char *Curl_all_content_encodings(void)
-{
- return strdup(CONTENT_ENCODING_DEFAULT); /* Satisfy caller. */
-}
#endif /* CURL_DISABLE_HTTP */
diff --git a/libs/libcurl/src/content_encoding.h b/libs/libcurl/src/content_encoding.h
index 4b50e9b8da..4ca176abb6 100644
--- a/libs/libcurl/src/content_encoding.h
+++ b/libs/libcurl/src/content_encoding.h
@@ -25,15 +25,10 @@
***************************************************************************/
#include "curl_setup.h"
-struct contenc_writer;
+struct Curl_cwriter;
-char *Curl_all_content_encodings(void);
+void Curl_all_content_encodings(char *buf, size_t blen);
CURLcode Curl_build_unencoding_stack(struct Curl_easy *data,
const char *enclist, int is_transfer);
-CURLcode Curl_unencode_write(struct Curl_easy *data,
- struct contenc_writer *writer,
- const char *buf, size_t nbytes);
-void Curl_unencode_cleanup(struct Curl_easy *data);
-
#endif /* HEADER_CURL_CONTENT_ENCODING_H */
diff --git a/libs/libcurl/src/cookie.c b/libs/libcurl/src/cookie.c
index cc698af53b..03f9699bd4 100644
--- a/libs/libcurl/src/cookie.c
+++ b/libs/libcurl/src/cookie.c
@@ -330,7 +330,7 @@ static char *sanitize_cookie_path(const char *cookie_path)
*/
void Curl_cookie_loadfiles(struct Curl_easy *data)
{
- struct curl_slist *list = data->set.cookielist;
+ struct curl_slist *list = data->state.cookielist;
if(list) {
Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
while(list) {
@@ -365,9 +365,7 @@ static void strstore(char **str, const char *newstr, size_t len)
DEBUGASSERT(newstr);
DEBUGASSERT(str);
free(*str);
- *str = Curl_memdup(newstr, len + 1);
- if(*str)
- (*str)[len] = 0;
+ *str = Curl_strndup(newstr, len);
}
/*
@@ -1029,15 +1027,23 @@ Curl_cookie_add(struct Curl_easy *data,
* dereference it.
*/
if(data && (domain && co->domain && !Curl_host_is_ipnum(co->domain))) {
- const psl_ctx_t *psl = Curl_psl_use(data);
- int acceptable;
-
- if(psl) {
- acceptable = psl_is_cookie_domain_acceptable(psl, domain, co->domain);
- Curl_psl_release(data);
+ bool acceptable = FALSE;
+ char lcase[256];
+ char lcookie[256];
+ size_t dlen = strlen(domain);
+ size_t clen = strlen(co->domain);
+ if((dlen < sizeof(lcase)) && (clen < sizeof(lcookie))) {
+ const psl_ctx_t *psl = Curl_psl_use(data);
+ if(psl) {
+ /* the PSL check requires lowercase domain name and pattern */
+ Curl_strntolower(lcase, domain, dlen + 1);
+ Curl_strntolower(lcookie, co->domain, clen + 1);
+ acceptable = psl_is_cookie_domain_acceptable(psl, lcase, lcookie);
+ Curl_psl_release(data);
+ }
+ else
+ acceptable = !bad_domain(domain, strlen(domain));
}
- else
- acceptable = !bad_domain(domain, strlen(domain));
if(!acceptable) {
infof(data, "cookie '%s' dropped, domain '%s' must not "
@@ -1347,7 +1353,7 @@ static int cookie_sort_ct(const void *p1, const void *p2)
static struct Cookie *dup_cookie(struct Cookie *src)
{
- struct Cookie *d = calloc(sizeof(struct Cookie), 1);
+ struct Cookie *d = calloc(1, sizeof(struct Cookie));
if(d) {
CLONE(domain);
CLONE(path);
diff --git a/libs/libcurl/src/curl_config.h.cmake b/libs/libcurl/src/curl_config.h.cmake
index a3774a05c1..11fa806dd1 100644
--- a/libs/libcurl/src/curl_config.h.cmake
+++ b/libs/libcurl/src/curl_config.h.cmake
@@ -74,9 +74,15 @@
/* disables FTP */
#cmakedefine CURL_DISABLE_FTP 1
+/* disables curl_easy_options API for existing options to curl_easy_setopt */
+#cmakedefine CURL_DISABLE_GETOPTIONS 1
+
/* disables GOPHER */
#cmakedefine CURL_DISABLE_GOPHER 1
+/* disables headers-api support */
+#cmakedefine CURL_DISABLE_HEADERS_API 1
+
/* disables HSTS support */
#cmakedefine CURL_DISABLE_HSTS 1
@@ -98,6 +104,9 @@
/* disables MIME support */
#cmakedefine CURL_DISABLE_MIME 1
+/* disables local binding support */
+#cmakedefine CURL_DISABLE_BINDLOCAL 1
+
/* disables MQTT */
#cmakedefine CURL_DISABLE_MQTT 1
@@ -168,9 +177,6 @@
/* Define to 1 if you have _Atomic support. */
#cmakedefine HAVE_ATOMIC 1
-/* Define to 1 if you have the `fchmod' function. */
-#cmakedefine HAVE_FCHMOD 1
-
/* Define to 1 if you have the `fnmatch' function. */
#cmakedefine HAVE_FNMATCH 1
@@ -208,6 +214,9 @@
/* Define to 1 if you have the fseeko function. */
#cmakedefine HAVE_FSEEKO 1
+/* Define to 1 if you have the fseeko declaration. */
+#cmakedefine HAVE_DECL_FSEEKO 1
+
/* Define to 1 if you have the _fseeki64 function. */
#cmakedefine HAVE__FSEEKI64 1
@@ -313,9 +322,6 @@
/* Define to 1 if symbol `ADDRESS_FAMILY' exists */
#cmakedefine HAVE_ADDRESS_FAMILY 1
-/* Define to 1 if you have the <inttypes.h> header file. */
-#cmakedefine HAVE_INTTYPES_H 1
-
/* Define to 1 if you have the ioctlsocket function. */
#cmakedefine HAVE_IOCTLSOCKET 1
@@ -497,9 +503,6 @@
/* Define to 1 if you have the <stdbool.h> header file. */
#cmakedefine HAVE_STDBOOL_H 1
-/* Define to 1 if you have the <stdint.h> header file. */
-#cmakedefine HAVE_STDINT_H 1
-
/* Define to 1 if you have the strcasecmp function. */
#cmakedefine HAVE_STRCASECMP 1
@@ -596,12 +599,6 @@
/* Define to 1 if you have the <utime.h> header file. */
#cmakedefine HAVE_UTIME_H 1
-/* Define to 1 if compiler supports C99 variadic macro style. */
-#cmakedefine HAVE_VARIADIC_MACROS_C99 1
-
-/* Define to 1 if compiler supports old gcc variadic macro style. */
-#cmakedefine HAVE_VARIADIC_MACROS_GCC 1
-
/* Define to 1 if you have the windows.h header file. */
#cmakedefine HAVE_WINDOWS_H 1
diff --git a/libs/libcurl/src/curl_config.h.in b/libs/libcurl/src/curl_config.h.in
index 8aa193abb6..ee2c680f6d 100644
--- a/libs/libcurl/src/curl_config.h.in
+++ b/libs/libcurl/src/curl_config.h.in
@@ -199,6 +199,9 @@
/* Define to 1 if you have the <crypto.h> header file. */
#undef HAVE_CRYPTO_H
+/* Define to 1 if you have the fseeko declaration */
+#undef HAVE_DECL_FSEEKO
+
/* Define to 1 if you have the declaration of `getpwuid_r', and to 0 if you
don't. */
#undef HAVE_DECL_GETPWUID_R
@@ -212,9 +215,6 @@
/* Define to 1 if you have the <err.h> header file. */
#undef HAVE_ERR_H
-/* Define to 1 if you have the `fchmod' function. */
-#undef HAVE_FCHMOD
-
/* Define to 1 if you have the fcntl function. */
#undef HAVE_FCNTL
@@ -722,12 +722,6 @@
/* Define to 1 if you have the <utime.h> header file. */
#undef HAVE_UTIME_H
-/* Define to 1 if compiler supports C99 variadic macro style. */
-#undef HAVE_VARIADIC_MACROS_C99
-
-/* Define to 1 if compiler supports old gcc variadic macro style. */
-#undef HAVE_VARIADIC_MACROS_GCC
-
/* Define to 1 if you have the windows.h header file. */
#undef HAVE_WINDOWS_H
diff --git a/libs/libcurl/src/curl_hmac.h b/libs/libcurl/src/curl_hmac.h
index 50b3052de8..7d7a83711f 100644
--- a/libs/libcurl/src/curl_hmac.h
+++ b/libs/libcurl/src/curl_hmac.h
@@ -25,7 +25,8 @@
***************************************************************************/
#if (defined(USE_CURL_NTLM_CORE) && !defined(USE_WINDOWS_SSPI)) \
- || !defined(CURL_DISABLE_AWS) || !defined(CURL_DISABLE_DIGEST_AUTH)
+ || !defined(CURL_DISABLE_AWS) || !defined(CURL_DISABLE_DIGEST_AUTH) \
+ || defined(USE_LIBSSH2)
#include <curl/curl.h>
diff --git a/libs/libcurl/src/curl_memory.h b/libs/libcurl/src/curl_memory.h
index 0340c142db..57e719e770 100644
--- a/libs/libcurl/src/curl_memory.h
+++ b/libs/libcurl/src/curl_memory.h
@@ -68,7 +68,7 @@
#undef send
#undef recv
-#ifdef WIN32
+#ifdef _WIN32
# ifdef UNICODE
# undef wcsdup
# undef _wcsdup
@@ -134,7 +134,7 @@ extern curl_free_callback Curl_cfree;
extern curl_realloc_callback Curl_crealloc;
extern curl_strdup_callback Curl_cstrdup;
extern curl_calloc_callback Curl_ccalloc;
-#if defined(WIN32) && defined(UNICODE)
+#if defined(_WIN32) && defined(UNICODE)
extern curl_wcsdup_callback Curl_cwcsdup;
#endif
@@ -160,7 +160,7 @@ extern curl_wcsdup_callback Curl_cwcsdup;
#undef free
#define free(ptr) Curl_cfree(ptr)
-#ifdef WIN32
+#ifdef _WIN32
# ifdef UNICODE
# undef wcsdup
# define wcsdup(ptr) Curl_cwcsdup(ptr)
diff --git a/libs/libcurl/src/curl_multibyte.c b/libs/libcurl/src/curl_multibyte.c
index 6180cb4e33..7448f51f3a 100644
--- a/libs/libcurl/src/curl_multibyte.c
+++ b/libs/libcurl/src/curl_multibyte.c
@@ -32,7 +32,7 @@
#include "curl_setup.h"
-#if defined(WIN32)
+#if defined(_WIN32)
#include "curl_multibyte.h"
@@ -84,7 +84,7 @@ char *curlx_convert_wchar_to_UTF8(const wchar_t *str_w)
return str_utf8;
}
-#endif /* WIN32 */
+#endif /* _WIN32 */
#if defined(USE_WIN32_LARGE_FILES) || defined(USE_WIN32_SMALL_FILES)
diff --git a/libs/libcurl/src/curl_multibyte.h b/libs/libcurl/src/curl_multibyte.h
index f0748b8ecd..e1f6a81451 100644
--- a/libs/libcurl/src/curl_multibyte.h
+++ b/libs/libcurl/src/curl_multibyte.h
@@ -25,7 +25,7 @@
***************************************************************************/
#include "curl_setup.h"
-#if defined(WIN32)
+#if defined(_WIN32)
/*
* MultiByte conversions using Windows kernel32 library.
@@ -33,7 +33,7 @@
wchar_t *curlx_convert_UTF8_to_wchar(const char *str_utf8);
char *curlx_convert_wchar_to_UTF8(const wchar_t *str_w);
-#endif /* WIN32 */
+#endif /* _WIN32 */
/*
* Macros curlx_convert_UTF8_to_tchar(), curlx_convert_tchar_to_UTF8()
@@ -54,7 +54,7 @@ char *curlx_convert_wchar_to_UTF8(const wchar_t *str_w);
* ensure that the curl memdebug override macros do not replace them.
*/
-#if defined(UNICODE) && defined(WIN32)
+#if defined(UNICODE) && defined(_WIN32)
#define curlx_convert_UTF8_to_tchar(ptr) curlx_convert_UTF8_to_wchar((ptr))
#define curlx_convert_tchar_to_UTF8(ptr) curlx_convert_wchar_to_UTF8((ptr))
@@ -78,7 +78,7 @@ typedef union {
const unsigned char *const_tbyte_ptr;
} xcharp_u;
-#endif /* UNICODE && WIN32 */
+#endif /* UNICODE && _WIN32 */
#define curlx_unicodefree(ptr) \
do { \
diff --git a/libs/libcurl/src/curl_ntlm_core.c b/libs/libcurl/src/curl_ntlm_core.c
index d9c3acb7d8..c11b4b8a11 100644
--- a/libs/libcurl/src/curl_ntlm_core.c
+++ b/libs/libcurl/src/curl_ntlm_core.c
@@ -111,6 +111,7 @@
# include <wincrypt.h>
#else
# error "Can't compile NTLM support without a crypto library with DES."
+# define CURL_NTLM_NOT_SUPPORTED
#endif
#include "urldata.h"
@@ -130,6 +131,7 @@
#define NTLMv2_BLOB_SIGNATURE "\x01\x01\x00\x00"
#define NTLMv2_BLOB_LEN (44 -16 + ntlm->target_info_len + 4)
+#if !defined(CURL_NTLM_NOT_SUPPORTED)
/*
* Turns a 56-bit key into being 64-bit wide.
*/
@@ -144,6 +146,7 @@ static void extend_key_56_to_64(const unsigned char *key_56, char *key)
key[6] = (unsigned char)(((key_56[5] << 2) & 0xFF) | (key_56[6] >> 6));
key[7] = (unsigned char) ((key_56[6] << 1) & 0xFF);
}
+#endif
#if defined(USE_OPENSSL_DES) || defined(USE_WOLFSSL)
/*
@@ -337,6 +340,10 @@ void Curl_ntlm_core_lm_resp(const unsigned char *keys,
encrypt_des(plaintext, results, keys);
encrypt_des(plaintext, results + 8, keys + 7);
encrypt_des(plaintext, results + 16, keys + 14);
+#else
+ (void)keys;
+ (void)plaintext;
+ (void)results;
#endif
}
@@ -347,9 +354,11 @@ CURLcode Curl_ntlm_core_mk_lm_hash(const char *password,
unsigned char *lmbuffer /* 21 bytes */)
{
unsigned char pw[14];
+#if !defined(CURL_NTLM_NOT_SUPPORTED)
static const unsigned char magic[] = {
0x4B, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25 /* i.e. KGS!@#$% */
};
+#endif
size_t len = CURLMIN(strlen(password), 14);
Curl_strntoupper((char *)pw, password, len);
diff --git a/libs/libcurl/src/curl_ntlm_wb.c b/libs/libcurl/src/curl_ntlm_wb.c
index 93a1d5b3b0..3103b9e3f4 100644
--- a/libs/libcurl/src/curl_ntlm_wb.c
+++ b/libs/libcurl/src/curl_ntlm_wb.c
@@ -68,7 +68,9 @@
/* Portable 'sclose_nolog' used only in child process instead of 'sclose'
to avoid fooling the socket leak detector */
-#if defined(HAVE_CLOSESOCKET)
+#ifdef HAVE_PIPE
+# define sclose_nolog(x) close((x))
+#elif defined(HAVE_CLOSESOCKET)
# define sclose_nolog(x) closesocket((x))
#elif defined(HAVE_CLOSESOCKET_CAMEL)
# define sclose_nolog(x) CloseSocket((x))
@@ -189,7 +191,7 @@ static CURLcode ntlm_wb_init(struct Curl_easy *data, struct ntlmdata *ntlm,
goto done;
}
- if(Curl_socketpair(AF_UNIX, SOCK_STREAM, 0, sockfds)) {
+ if(wakeup_create(sockfds)) {
failf(data, "Could not open socket pair. errno %d: %s",
errno, Curl_strerror(errno, buffer, sizeof(buffer)));
goto done;
@@ -197,8 +199,8 @@ static CURLcode ntlm_wb_init(struct Curl_easy *data, struct ntlmdata *ntlm,
child_pid = fork();
if(child_pid == -1) {
- sclose(sockfds[0]);
- sclose(sockfds[1]);
+ wakeup_close(sockfds[0]);
+ wakeup_close(sockfds[1]);
failf(data, "Could not fork. errno %d: %s",
errno, Curl_strerror(errno, buffer, sizeof(buffer)));
goto done;
@@ -268,7 +270,7 @@ static CURLcode ntlm_wb_response(struct Curl_easy *data, struct ntlmdata *ntlm,
Curl_dyn_init(&b, MAX_NTLM_WB_RESPONSE);
while(len_in > 0) {
- ssize_t written = swrite(ntlm->ntlm_auth_hlpr_socket, input, len_in);
+ ssize_t written = wakeup_write(ntlm->ntlm_auth_hlpr_socket, input, len_in);
if(written == -1) {
/* Interrupted by a signal, retry it */
if(errno == EINTR)
@@ -282,7 +284,7 @@ static CURLcode ntlm_wb_response(struct Curl_easy *data, struct ntlmdata *ntlm,
/* Read one line */
while(1) {
ssize_t size =
- sread(ntlm->ntlm_auth_hlpr_socket, buf, data->set.buffer_size);
+ wakeup_read(ntlm->ntlm_auth_hlpr_socket, buf, data->set.buffer_size);
if(size == -1) {
if(errno == EINTR)
continue;
diff --git a/libs/libcurl/src/curl_path.h b/libs/libcurl/src/curl_path.h
index 039348c2ff..3c0d0b7480 100644
--- a/libs/libcurl/src/curl_path.h
+++ b/libs/libcurl/src/curl_path.h
@@ -28,7 +28,7 @@
#include <curl/curl.h>
#include "urldata.h"
-#ifdef WIN32
+#ifdef _WIN32
# undef PATH_MAX
# define PATH_MAX MAX_PATH
# ifndef R_OK
diff --git a/libs/libcurl/src/curl_rtmp.c b/libs/libcurl/src/curl_rtmp.c
index 4b675d6f82..0af8cdeb1a 100644
--- a/libs/libcurl/src/curl_rtmp.c
+++ b/libs/libcurl/src/curl_rtmp.c
@@ -39,7 +39,7 @@
/* The last #include file should be: */
#include "memdebug.h"
-#if defined(WIN32) && !defined(USE_LWIPSOCK)
+#if defined(_WIN32) && !defined(USE_LWIPSOCK)
#define setsockopt(a,b,c,d,e) (setsockopt)(a,b,c,(const char *)d,(int)e)
#define SET_RCVTIMEO(tv,s) int tv = s*1000
#elif defined(LWIP_SO_SNDRCVTIMEO_NONSTANDARD)
diff --git a/libs/libcurl/src/curl_sasl.c b/libs/libcurl/src/curl_sasl.c
index 42de215900..8d78d49129 100644
--- a/libs/libcurl/src/curl_sasl.c
+++ b/libs/libcurl/src/curl_sasl.c
@@ -262,6 +262,8 @@ static void sasl_state(struct SASL *sasl, struct Curl_easy *data,
sasl->state = newstate;
}
+#if defined(USE_NTLM) || defined(USE_GSASL) || defined(USE_KERBEROS5) || \
+ !defined(CURL_DISABLE_DIGEST_AUTH)
/* Get the SASL server message and convert it to binary. */
static CURLcode get_server_message(struct SASL *sasl, struct Curl_easy *data,
struct bufref *out)
@@ -284,6 +286,7 @@ static CURLcode get_server_message(struct SASL *sasl, struct Curl_easy *data,
}
return result;
}
+#endif
/* Encode the outgoing SASL message. */
static CURLcode build_message(struct SASL *sasl, struct bufref *msg)
diff --git a/libs/libcurl/src/curl_setup.h b/libs/libcurl/src/curl_setup.h
index b3995b87c6..2505a6e47c 100644
--- a/libs/libcurl/src/curl_setup.h
+++ b/libs/libcurl/src/curl_setup.h
@@ -28,6 +28,11 @@
#define CURL_NO_OLDIES
#endif
+/* Set default _WIN32_WINNT */
+#ifdef __MINGW32__
+#include <_mingw.h>
+#endif
+
/*
* Disable Visual Studio warnings:
* 4127 "conditional expression is constant"
@@ -36,15 +41,7 @@
#pragma warning(disable:4127)
#endif
-/*
- * Define WIN32 when build target is Win32 API
- */
-
-#if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32)
-#define WIN32
-#endif
-
-#ifdef WIN32
+#ifdef _WIN32
/*
* Don't include unneeded stuff in Windows headers to avoid compiler
* warnings and macro clashes.
@@ -56,6 +53,16 @@
# ifndef NOGDI
# define NOGDI
# endif
+/* Detect Windows App environment which has a restricted access
+ * to the Win32 APIs. */
+# if (defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0602)) || \
+ defined(WINAPI_FAMILY)
+# include <winapifamily.h>
+# if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) && \
+ !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
+# define CURL_WINDOWS_APP
+# endif
+# endif
#endif
/*
@@ -72,7 +79,7 @@
#ifdef _WIN32_WCE
# include "config-win32ce.h"
#else
-# ifdef WIN32
+# ifdef _WIN32
# include "config-win32.h"
# endif
#endif
@@ -204,6 +211,23 @@
# define CURL_DISABLE_RTSP
#endif
+/*
+ * When HTTP is disabled, disable HTTP-only features
+ */
+
+#if defined(CURL_DISABLE_HTTP)
+# define CURL_DISABLE_ALTSVC 1
+# define CURL_DISABLE_COOKIES 1
+# define CURL_DISABLE_BASIC_AUTH 1
+# define CURL_DISABLE_BEARER_AUTH 1
+# define CURL_DISABLE_AWS 1
+# define CURL_DISABLE_DOH 1
+# define CURL_DISABLE_FORM_API 1
+# define CURL_DISABLE_HEADERS_API 1
+# define CURL_DISABLE_HSTS 1
+# define CURL_DISABLE_HTTP_AUTH 1
+#endif
+
/* ================================================================ */
/* No system header file shall be included in this file before this */
/* point. */
@@ -321,23 +345,6 @@
#include <curl/stdcheaders.h>
#endif
-#ifdef __POCC__
-# include <sys/types.h>
-# include <unistd.h>
-# define sys_nerr EILSEQ
-#endif
-
-/*
- * Salford-C kludge section (mostly borrowed from wxWidgets).
- */
-#ifdef __SALFORDC__
- #pragma suppress 353 /* Possible nested comments */
- #pragma suppress 593 /* Define not used */
- #pragma suppress 61 /* enum has no name */
- #pragma suppress 106 /* unnamed, unused parameter */
- #include <clib.h>
-#endif
-
/*
* Large file (>2Gb) support using WIN32 functions.
*/
@@ -490,11 +497,11 @@
5. set dir/file naming defines
*/
-#ifdef WIN32
+#ifdef _WIN32
# define DIR_CHAR "\\"
-#else /* WIN32 */
+#else /* _WIN32 */
# ifdef MSDOS /* Watt-32 */
@@ -519,27 +526,7 @@
# define DIR_CHAR "/"
-# ifndef fileno /* sunos 4 have this as a macro! */
- int fileno(FILE *stream);
-# endif
-
-#endif /* WIN32 */
-
-/*
- * msvc 6.0 requires PSDK in order to have INET6_ADDRSTRLEN
- * defined in ws2tcpip.h as well as to provide IPv6 support.
- * Does not apply if lwIP is used.
- */
-
-#if defined(_MSC_VER) && !defined(__POCC__) && !defined(USE_LWIPSOCK)
-# if !defined(HAVE_WS2TCPIP_H) || \
- ((_MSC_VER < 1300) && !defined(INET6_ADDRSTRLEN))
-# undef HAVE_GETADDRINFO_THREADSAFE
-# undef HAVE_FREEADDRINFO
-# undef HAVE_GETADDRINFO
-# undef ENABLE_IPV6
-# endif
-#endif
+#endif /* _WIN32 */
/* ---------------------------------------------------------------- */
/* resolver specialty compile-time defines */
@@ -547,20 +534,11 @@
/* ---------------------------------------------------------------- */
/*
- * lcc-win32 doesn't have _beginthreadex(), lacks threads support.
- */
-
-#if defined(__LCC__) && defined(WIN32)
-# undef USE_THREADS_POSIX
-# undef USE_THREADS_WIN32
-#endif
-
-/*
* MSVC threads support requires a multi-threaded runtime library.
* _beginthreadex() is not available in single-threaded ones.
*/
-#if defined(_MSC_VER) && !defined(__POCC__) && !defined(_MT)
+#if defined(_MSC_VER) && !defined(_MT)
# undef USE_THREADS_POSIX
# undef USE_THREADS_WIN32
#endif
@@ -571,6 +549,9 @@
#if defined(ENABLE_IPV6) && defined(HAVE_GETADDRINFO)
# define CURLRES_IPV6
+#elif defined(ENABLE_IPV6) && (defined(_WIN32) || defined(__CYGWIN__))
+/* assume on Windows that IPv6 without getaddrinfo is a broken build */
+# error "Unexpected build: IPv6 is enabled but getaddrinfo was not found."
#else
# define CURLRES_IPV4
#endif
@@ -590,35 +571,6 @@
/* ---------------------------------------------------------------- */
-/*
- * 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.
- */
-
-#if defined(_MSC_VER) && !defined(__POCC__)
-# if !defined(HAVE_WINSOCK2_H) || ((_MSC_VER < 1300) && !defined(IPPROTO_ESP))
-# undef HAVE_STRUCT_SOCKADDR_STORAGE
-# endif
-#endif
-
-/*
- * Intentionally fail to build when using msvc 6.0 without PSDK installed.
- * The brave of heart can circumvent this, defining ALLOW_MSVC6_WITHOUT_PSDK
- * in lib/config-win32.h although absolutely discouraged and unsupported.
- */
-
-#if defined(_MSC_VER) && !defined(__POCC__)
-# if !defined(HAVE_WINDOWS_H) || ((_MSC_VER < 1300) && !defined(_FILETIME_))
-# if !defined(ALLOW_MSVC6_WITHOUT_PSDK)
-# error MSVC 6.0 requires "February 2003 Platform SDK" a.k.a. \
- "Windows Server 2003 PSDK"
-# else
-# define CURL_DISABLE_LDAP 1
-# endif
-# endif
-#endif
-
#if defined(HAVE_LIBIDN2) && defined(HAVE_IDN2_H) && !defined(USE_WIN32_IDN)
/* The lib and header are present */
#define USE_LIBIDN2
@@ -684,6 +636,18 @@
# define WARN_UNUSED_RESULT
#endif
+/* noreturn attribute */
+
+#if !defined(CURL_NORETURN)
+#if (defined(__GNUC__) && (__GNUC__ >= 3)) || defined(__clang__)
+# define CURL_NORETURN __attribute__((__noreturn__))
+#elif defined(_MSC_VER) && (_MSC_VER >= 1200)
+# define CURL_NORETURN __declspec(noreturn)
+#else
+# define CURL_NORETURN
+#endif
+#endif
+
/*
* Include macros and defines that should only be processed once.
*/
@@ -742,7 +706,7 @@
/* In Windows the default file mode is text but an application can override it.
Therefore we specify it explicitly. https://github.com/curl/curl/pull/258
*/
-#if defined(WIN32) || defined(MSDOS)
+#if defined(_WIN32) || defined(MSDOS)
#define FOPEN_READTEXT "rt"
#define FOPEN_WRITETEXT "wt"
#define FOPEN_APPENDTEXT "at"
@@ -797,7 +761,8 @@ int getpwuid_r(uid_t uid, struct passwd *pwd, char *buf,
#define UNITTEST static
#endif
-#if defined(USE_NGHTTP2) || defined(USE_HYPER)
+/* Hyper supports HTTP2 also, but Curl's integration with Hyper does not */
+#if defined(USE_NGHTTP2)
#define USE_HTTP2
#endif
@@ -810,11 +775,11 @@ int getpwuid_r(uid_t uid, struct passwd *pwd, char *buf,
/* Certain Windows implementations are not aligned with what curl expects,
so always use the local one on this platform. E.g. the mingw-w64
implementation can return wrong results for non-ASCII inputs. */
-#if defined(HAVE_BASENAME) && defined(WIN32)
+#if defined(HAVE_BASENAME) && defined(_WIN32)
#undef HAVE_BASENAME
#endif
-#if defined(USE_UNIX_SOCKETS) && defined(WIN32)
+#if defined(USE_UNIX_SOCKETS) && defined(_WIN32)
# if !defined(UNIX_PATH_MAX)
/* Replicating logic present in afunix.h
(distributed with newer Windows 10 SDK versions only) */
diff --git a/libs/libcurl/src/curl_setup_once.h b/libs/libcurl/src/curl_setup_once.h
index df1d35e961..2d92332eed 100644
--- a/libs/libcurl/src/curl_setup_once.h
+++ b/libs/libcurl/src/curl_setup_once.h
@@ -56,7 +56,7 @@
#include <sys/time.h>
#endif
-#ifdef WIN32
+#ifdef _WIN32
#include <io.h>
#include <fcntl.h>
#endif
@@ -70,11 +70,7 @@
#endif
#ifdef USE_WOLFSSL
-# if defined(HAVE_STDINT_H)
-# include <stdint.h>
-# elif defined(HAVE_INTTYPES_H)
-# include <inttypes.h>
-# endif
+#include <stdint.h>
#endif
#ifdef USE_SCHANNEL
diff --git a/libs/libcurl/src/curl_sspi.h b/libs/libcurl/src/curl_sspi.h
index 33b0129c36..d1f89720dd 100644
--- a/libs/libcurl/src/curl_sspi.h
+++ b/libs/libcurl/src/curl_sspi.h
@@ -88,6 +88,22 @@ extern PSecurityFunctionTable s_pSecFn;
# define CRYPT_E_REVOKED ((HRESULT)0x80092010L)
#endif
+#ifndef CRYPT_E_NO_REVOCATION_DLL
+# define CRYPT_E_NO_REVOCATION_DLL ((HRESULT)0x80092011L)
+#endif
+
+#ifndef CRYPT_E_NO_REVOCATION_CHECK
+# define CRYPT_E_NO_REVOCATION_CHECK ((HRESULT)0x80092012L)
+#endif
+
+#ifndef CRYPT_E_REVOCATION_OFFLINE
+# define CRYPT_E_REVOCATION_OFFLINE ((HRESULT)0x80092013L)
+#endif
+
+#ifndef CRYPT_E_NOT_IN_REVOCATION_DATABASE
+# define CRYPT_E_NOT_IN_REVOCATION_DATABASE ((HRESULT)0x80092014L)
+#endif
+
#ifdef UNICODE
# define SECFLAG_WINNT_AUTH_IDENTITY \
(unsigned long)SEC_WINNT_AUTH_IDENTITY_UNICODE
diff --git a/libs/libcurl/src/curl_trc.c b/libs/libcurl/src/curl_trc.c
index f4946ed337..9913ceaf9a 100644
--- a/libs/libcurl/src/curl_trc.c
+++ b/libs/libcurl/src/curl_trc.c
@@ -61,10 +61,6 @@ void Curl_debug(struct Curl_easy *data, curl_infotype type,
"* ", "< ", "> ", "{ ", "} ", "{ ", "} " };
if(data->set.fdebug) {
bool inCallback = Curl_is_in_callback(data);
- /* CURLOPT_DEBUGFUNCTION doc says the user may set CURLOPT_PRIVATE to
- distinguish their handle from internal handles. */
- if(data->internal)
- DEBUGASSERT(!data->set.private_data);
Curl_set_in_callback(data, true);
(void)(*data->set.fdebug)(data, type, ptr, size, data->set.debugdata);
Curl_set_in_callback(data, inCallback);
@@ -109,6 +105,8 @@ void Curl_failf(struct Curl_easy *data, const char *fmt, ...)
}
}
+#if !defined(CURL_DISABLE_VERBOSE_STRINGS)
+
/* Curl_infof() is for info message along the way */
#define MAXINFO 2048
@@ -128,13 +126,11 @@ void Curl_infof(struct Curl_easy *data, const char *fmt, ...)
}
}
-#if !defined(CURL_DISABLE_VERBOSE_STRINGS)
-
void Curl_trc_cf_infof(struct Curl_easy *data, struct Curl_cfilter *cf,
const char *fmt, ...)
{
DEBUGASSERT(cf);
- if(data && Curl_trc_cf_is_verbose(cf, data)) {
+ if(Curl_trc_cf_is_verbose(cf, data)) {
va_list ap;
int len;
char buffer[MAXINFO + 2];
@@ -232,24 +228,14 @@ CURLcode Curl_trc_init(void)
if(config) {
return Curl_trc_opt(config);
}
-#endif
+#endif /* DEBUGBUILD */
return CURLE_OK;
}
-#else /* !CURL_DISABLE_VERBOSE_STRINGS) */
+#else /* defined(CURL_DISABLE_VERBOSE_STRINGS) */
CURLcode Curl_trc_init(void)
{
return CURLE_OK;
}
-#if !defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L)
-void Curl_trc_cf_infof(struct Curl_easy *data, struct Curl_cfilter *cf,
- const char *fmt, ...)
-{
- (void)data;
- (void)cf;
- (void)fmt;
-}
-#endif
-
-#endif /* !DEBUGBUILD */
+#endif /* !defined(CURL_DISABLE_VERBOSE_STRINGS) */
diff --git a/libs/libcurl/src/curl_trc.h b/libs/libcurl/src/curl_trc.h
index f9288a6a64..27fc8fc769 100644
--- a/libs/libcurl/src/curl_trc.h
+++ b/libs/libcurl/src/curl_trc.h
@@ -55,19 +55,6 @@ void Curl_debug(struct Curl_easy *data, curl_infotype type,
char *ptr, size_t size);
/**
- * Output an informational message when transfer's verbose logging is enabled.
- */
-void Curl_infof(struct Curl_easy *data,
-#if defined(__GNUC__) && !defined(printf) && \
- defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \
- !defined(__MINGW32__)
- const char *fmt, ...)
- __attribute__((format(printf, 2, 3)));
-#else
- const char *fmt, ...);
-#endif
-
-/**
* Output a failure message on registered callbacks for transfer.
*/
void Curl_failf(struct Curl_easy *data,
@@ -82,39 +69,15 @@ void Curl_failf(struct Curl_easy *data,
#define failf Curl_failf
-/**
- * Output an informational message when both transfer's verbose logging
- * and connection filters verbose logging are enabled.
- */
-void Curl_trc_cf_infof(struct Curl_easy *data, struct Curl_cfilter *cf,
-#if defined(__GNUC__) && !defined(printf) && \
- defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \
- !defined(__MINGW32__)
- const char *fmt, ...)
- __attribute__((format(printf, 3, 4)));
-#else
- const char *fmt, ...);
-#endif
-
#define CURL_LOG_LVL_NONE 0
#define CURL_LOG_LVL_INFO 1
-#if !defined(CURL_DISABLE_VERBOSE_STRINGS)
-/* informational messages enabled */
-
-#define Curl_trc_is_verbose(data) ((data) && (data)->set.verbose)
-#define Curl_trc_cf_is_verbose(cf, data) \
- ((data) && (data)->set.verbose && \
- (cf) && (cf)->cft->log_level >= CURL_LOG_LVL_INFO)
-
-/* explainer: we have some mix configuration and werror settings
- * that define HAVE_VARIADIC_MACROS_C99 even though C89 is enforced
- * on gnuc and some other compiler. Need to treat carefully.
- */
-#if defined(HAVE_VARIADIC_MACROS_C99) && \
- defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
+#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+#define CURL_HAVE_C99
+#endif
+#ifdef CURL_HAVE_C99
#define infof(data, ...) \
do { if(Curl_trc_is_verbose(data)) \
Curl_infof(data, __VA_ARGS__); } while(0)
@@ -122,29 +85,62 @@ void Curl_trc_cf_infof(struct Curl_easy *data, struct Curl_cfilter *cf,
do { if(Curl_trc_cf_is_verbose(cf, data)) \
Curl_trc_cf_infof(data, cf, __VA_ARGS__); } while(0)
-#else /* no variadic macro args */
+#else
#define infof Curl_infof
#define CURL_TRC_CF Curl_trc_cf_infof
-#endif /* variadic macro args */
+#endif
+
+#ifndef CURL_DISABLE_VERBOSE_STRINGS
+/* informational messages enabled */
-#else /* !CURL_DISABLE_VERBOSE_STRINGS */
+#define Curl_trc_is_verbose(data) ((data) && (data)->set.verbose)
+#define Curl_trc_cf_is_verbose(cf, data) \
+ ((data) && (data)->set.verbose && \
+ (cf) && (cf)->cft->log_level >= CURL_LOG_LVL_INFO)
+
+/**
+ * Output an informational message when transfer's verbose logging is enabled.
+ */
+void Curl_infof(struct Curl_easy *data,
+#if defined(__GNUC__) && !defined(printf) && defined(CURL_HAVE_C99) && \
+ !defined(__MINGW32__)
+ const char *fmt, ...)
+ __attribute__((format(printf, 2, 3)));
+#else
+ const char *fmt, ...);
+#endif
+
+/**
+ * Output an informational message when both transfer's verbose logging
+ * and connection filters verbose logging are enabled.
+ */
+void Curl_trc_cf_infof(struct Curl_easy *data, struct Curl_cfilter *cf,
+#if defined(__GNUC__) && !defined(printf) && defined(CURL_HAVE_C99) && \
+ !defined(__MINGW32__)
+ const char *fmt, ...)
+ __attribute__((format(printf, 3, 4)));
+#else
+ const char *fmt, ...);
+#endif
+
+#else /* defined(CURL_DISABLE_VERBOSE_STRINGS) */
/* All informational messages are not compiled in for size savings */
#define Curl_trc_is_verbose(d) ((void)(d), FALSE)
#define Curl_trc_cf_is_verbose(x,y) ((void)(x), (void)(y), FALSE)
-#if defined(HAVE_VARIADIC_MACROS_C99)
-#define infof(...) Curl_nop_stmt
-#define CURL_TRC_CF(...) Curl_nop_stmt
-#define Curl_trc_cf_infof(...) Curl_nop_stmt
-#elif defined(HAVE_VARIADIC_MACROS_GCC)
-#define infof(x...) Curl_nop_stmt
-#define CURL_TRC_CF(x...) Curl_nop_stmt
-#define Curl_trc_cf_infof(x...) Curl_nop_stmt
-#else
-#error "missing VARIADIC macro define, fix and rebuild!"
-#endif
+static void Curl_infof(struct Curl_easy *data, const char *fmt, ...)
+{
+ (void)data; (void)fmt;
+}
+
+static void Curl_trc_cf_infof(struct Curl_easy *data,
+ struct Curl_cfilter *cf,
+ const char *fmt, ...)
+{
+ (void)data; (void)cf; (void)fmt;
+}
-#endif /* CURL_DISABLE_VERBOSE_STRINGS */
+#endif /* !defined(CURL_DISABLE_VERBOSE_STRINGS) */
#endif /* HEADER_CURL_TRC_H */
diff --git a/libs/libcurl/src/doh.c b/libs/libcurl/src/doh.c
index 06c9eb17e3..0abeb965cd 100644
--- a/libs/libcurl/src/doh.c
+++ b/libs/libcurl/src/doh.c
@@ -242,7 +242,7 @@ static CURLcode dohprobe(struct Curl_easy *data,
/* pass in the struct pointer via a local variable to please coverity and
the gcc typecheck helpers */
struct dynbuf *resp = &p->serverdoh;
- doh->internal = true;
+ doh->state.internal = true;
ERROR_CHECK_SETOPT(CURLOPT_URL, url);
ERROR_CHECK_SETOPT(CURLOPT_DEFAULT_PROTOCOL, "https");
ERROR_CHECK_SETOPT(CURLOPT_WRITEFUNCTION, doh_write_cb);
@@ -252,6 +252,7 @@ static CURLcode dohprobe(struct Curl_easy *data,
ERROR_CHECK_SETOPT(CURLOPT_HTTPHEADER, headers);
#ifdef USE_HTTP2
ERROR_CHECK_SETOPT(CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2TLS);
+ ERROR_CHECK_SETOPT(CURLOPT_PIPEWAIT, 1L);
#endif
#ifndef CURLDEBUG
/* enforce HTTPS if not debug */
@@ -339,9 +340,10 @@ static CURLcode dohprobe(struct Curl_easy *data,
doh->set.dohfor = data; /* identify for which transfer this is done */
p->easy = doh;
- /* DoH private_data must be null because the user must have a way to
- distinguish their transfer's handle from DoH handles in user
- callbacks (ie SSL CTX callback). */
+ /* DoH handles must not inherit private_data. The handles may be passed to
+ the user via callbacks and the user will be able to identify them as
+ internal handles because private data is not set. The user can then set
+ private_data via CURLOPT_PRIVATE if they so choose. */
DEBUGASSERT(!doh->set.private_data);
if(curl_multi_add_handle(multi, doh))
@@ -372,7 +374,7 @@ struct Curl_addrinfo *Curl_doh(struct Curl_easy *data,
int slot;
struct dohdata *dohp;
struct connectdata *conn = data->conn;
- *waitp = TRUE; /* this never returns synchronously */
+ *waitp = FALSE;
(void)hostname;
(void)port;
@@ -380,7 +382,7 @@ struct Curl_addrinfo *Curl_doh(struct Curl_easy *data,
DEBUGASSERT(conn);
/* start clean, consider allocating this struct on demand */
- dohp = data->req.doh = calloc(sizeof(struct dohdata), 1);
+ dohp = data->req.doh = calloc(1, sizeof(struct dohdata));
if(!dohp)
return NULL;
@@ -412,12 +414,14 @@ struct Curl_addrinfo *Curl_doh(struct Curl_easy *data,
dohp->pending++;
}
#endif
+ *waitp = TRUE; /* this never returns synchronously */
return NULL;
error:
curl_slist_free_all(dohp->headers);
data->req.doh->headers = NULL;
for(slot = 0; slot < DOH_PROBE_SLOTS; slot++) {
+ (void)curl_multi_remove_handle(data->multi, dohp->probe[slot].easy);
Curl_close(&dohp->probe[slot].easy);
}
Curl_safefree(data->req.doh);
@@ -787,8 +791,8 @@ static void showdoh(struct Curl_easy *data,
* must be an associated call later to Curl_freeaddrinfo().
*/
-static struct Curl_addrinfo *
-doh2ai(const struct dohentry *de, const char *hostname, int port)
+static CURLcode doh2ai(const struct dohentry *de, const char *hostname,
+ int port, struct Curl_addrinfo **aip)
{
struct Curl_addrinfo *ai;
struct Curl_addrinfo *prevai = NULL;
@@ -801,9 +805,10 @@ doh2ai(const struct dohentry *de, const char *hostname, int port)
int i;
size_t hostlen = strlen(hostname) + 1; /* include null-terminator */
- if(!de)
- /* no input == no output! */
- return NULL;
+ DEBUGASSERT(de);
+
+ if(!de->numaddr)
+ return CURLE_COULDNT_RESOLVE_HOST;
for(i = 0; i < de->numaddr; i++) {
size_t ss_size;
@@ -876,8 +881,9 @@ doh2ai(const struct dohentry *de, const char *hostname, int port)
Curl_freeaddrinfo(firstai);
firstai = NULL;
}
+ *aip = firstai;
- return firstai;
+ return result;
}
#ifndef CURL_DISABLE_VERBOSE_STRINGS
@@ -898,6 +904,7 @@ UNITTEST void de_cleanup(struct dohentry *d)
CURLcode Curl_doh_is_resolved(struct Curl_easy *data,
struct Curl_dns_entry **dnsp)
{
+ struct connectdata *conn = data->conn;
CURLcode result;
struct dohdata *dohp = data->req.doh;
*dnsp = NULL; /* defaults to no response */
@@ -906,7 +913,7 @@ CURLcode Curl_doh_is_resolved(struct Curl_easy *data,
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);
+ failf(data, "Could not DoH-resolve: %s", conn->resolve_async.hostname);
return CONN_IS_PROXIED(data->conn)?CURLE_COULDNT_RESOLVE_PROXY:
CURLE_COULDNT_RESOLVE_HOST;
}
@@ -932,10 +939,12 @@ CURLcode Curl_doh_is_resolved(struct Curl_easy *data,
p->dnstype,
&de);
Curl_dyn_free(&p->serverdoh);
+#ifndef CURL_DISABLE_VERBOSE_STRINGS
if(rc[slot]) {
infof(data, "DoH: %s type %s for %s", doh_strerror(rc[slot]),
type2name(p->dnstype), dohp->host);
}
+#endif
} /* next slot */
result = CURLE_COULDNT_RESOLVE_HOST; /* until we know better */
@@ -947,10 +956,10 @@ CURLcode Curl_doh_is_resolved(struct Curl_easy *data,
infof(data, "DoH Host name: %s", dohp->host);
showdoh(data, &de);
- ai = doh2ai(&de, dohp->host, dohp->port);
- if(!ai) {
+ result = doh2ai(&de, dohp->host, dohp->port, &ai);
+ if(result) {
de_cleanup(&de);
- return CURLE_OUT_OF_MEMORY;
+ return result;
}
if(data->share)
@@ -967,7 +976,7 @@ CURLcode Curl_doh_is_resolved(struct Curl_easy *data,
Curl_freeaddrinfo(ai);
}
else {
- data->state.async.dns = dns;
+ conn->resolve_async.dns = dns;
*dnsp = dns;
result = CURLE_OK; /* address resolution OK */
}
diff --git a/libs/libcurl/src/dynbuf.c b/libs/libcurl/src/dynbuf.c
index fc376a4e4b..dcf3da23ac 100644
--- a/libs/libcurl/src/dynbuf.c
+++ b/libs/libcurl/src/dynbuf.c
@@ -77,6 +77,7 @@ static CURLcode dyn_nappend(struct dynbuf *s,
DEBUGASSERT(indx < s->toobig);
DEBUGASSERT(!s->leng || s->bufr);
DEBUGASSERT(a <= s->toobig);
+ DEBUGASSERT(!len || mem);
if(fit > s->toobig) {
Curl_dyn_free(s);
@@ -174,10 +175,12 @@ CURLcode Curl_dyn_addn(struct dynbuf *s, const void *mem, size_t len)
*/
CURLcode Curl_dyn_add(struct dynbuf *s, const char *str)
{
- size_t n = strlen(str);
+ size_t n;
+ DEBUGASSERT(str);
DEBUGASSERT(s);
DEBUGASSERT(s->init == DYNINIT);
DEBUGASSERT(!s->leng || s->bufr);
+ n = strlen(str);
return dyn_nappend(s, (unsigned char *)str, n);
}
@@ -191,6 +194,7 @@ CURLcode Curl_dyn_vaddf(struct dynbuf *s, const char *fmt, va_list ap)
DEBUGASSERT(s);
DEBUGASSERT(s->init == DYNINIT);
DEBUGASSERT(!s->leng || s->bufr);
+ DEBUGASSERT(fmt);
rc = Curl_dyn_vprintf(s, fmt, ap);
if(!rc)
diff --git a/libs/libcurl/src/dynhds.c b/libs/libcurl/src/dynhds.c
index 95e0b32227..465c09baca 100644
--- a/libs/libcurl/src/dynhds.c
+++ b/libs/libcurl/src/dynhds.c
@@ -27,6 +27,10 @@
#include "strcase.h"
/* The last 3 #include files should be in this order */
+#ifdef USE_NGHTTP2
+#include <stdint.h>
+#include <nghttp2/nghttp2.h>
+#endif /* USE_NGHTTP2 */
#include "curl_printf.h"
#include "curl_memory.h"
#include "memdebug.h"
@@ -365,3 +369,28 @@ CURLcode Curl_dynhds_h1_dprint(struct dynhds *dynhds, struct dynbuf *dbuf)
return result;
}
+#ifdef USE_NGHTTP2
+
+nghttp2_nv *Curl_dynhds_to_nva(struct dynhds *dynhds, size_t *pcount)
+{
+ nghttp2_nv *nva = calloc(1, sizeof(nghttp2_nv) * dynhds->hds_len);
+ size_t i;
+
+ *pcount = 0;
+ if(!nva)
+ return NULL;
+
+ for(i = 0; i < dynhds->hds_len; ++i) {
+ struct dynhds_entry *e = dynhds->hds[i];
+ DEBUGASSERT(e);
+ nva[i].name = (unsigned char *)e->name;
+ nva[i].namelen = e->namelen;
+ nva[i].value = (unsigned char *)e->value;
+ nva[i].valuelen = e->valuelen;
+ nva[i].flags = NGHTTP2_NV_FLAG_NONE;
+ }
+ *pcount = dynhds->hds_len;
+ return nva;
+}
+
+#endif /* USE_NGHTTP2 */
diff --git a/libs/libcurl/src/dynhds.h b/libs/libcurl/src/dynhds.h
index 8cb5e6bc56..215087c6f4 100644
--- a/libs/libcurl/src/dynhds.h
+++ b/libs/libcurl/src/dynhds.h
@@ -171,4 +171,13 @@ CURLcode Curl_dynhds_h1_add_line(struct dynhds *dynhds,
*/
CURLcode Curl_dynhds_h1_dprint(struct dynhds *dynhds, struct dynbuf *dbuf);
+#ifdef USE_NGHTTP2
+
+#include <stdint.h>
+#include <nghttp2/nghttp2.h>
+
+nghttp2_nv *Curl_dynhds_to_nva(struct dynhds *dynhds, size_t *pcount);
+
+#endif /* USE_NGHTTP2 */
+
#endif /* HEADER_CURL_DYNHDS_H */
diff --git a/libs/libcurl/src/easy.c b/libs/libcurl/src/easy.c
index 807b6391d3..f5ffe259de 100644
--- a/libs/libcurl/src/easy.c
+++ b/libs/libcurl/src/easy.c
@@ -112,7 +112,7 @@ static curl_simple_lock s_lock = CURL_SIMPLE_LOCK_INIT;
#define system_strdup strdup
#endif
-#if defined(_MSC_VER) && defined(_DLL) && !defined(__POCC__)
+#if defined(_MSC_VER) && defined(_DLL)
# pragma warning(disable:4232) /* MSVC extension, dllimport identity */
#endif
@@ -125,11 +125,11 @@ curl_free_callback Curl_cfree = (curl_free_callback)free;
curl_realloc_callback Curl_crealloc = (curl_realloc_callback)realloc;
curl_strdup_callback Curl_cstrdup = (curl_strdup_callback)system_strdup;
curl_calloc_callback Curl_ccalloc = (curl_calloc_callback)calloc;
-#if defined(WIN32) && defined(UNICODE)
+#if defined(_WIN32) && defined(UNICODE)
curl_wcsdup_callback Curl_cwcsdup = Curl_wcsdup;
#endif
-#if defined(_MSC_VER) && defined(_DLL) && !defined(__POCC__)
+#if defined(_MSC_VER) && defined(_DLL)
# pragma warning(default:4232) /* MSVC extension, dllimport identity */
#endif
@@ -153,7 +153,7 @@ static CURLcode global_init(long flags, bool memoryfuncs)
Curl_crealloc = (curl_realloc_callback)realloc;
Curl_cstrdup = (curl_strdup_callback)system_strdup;
Curl_ccalloc = (curl_calloc_callback)calloc;
-#if defined(WIN32) && defined(UNICODE)
+#if defined(_WIN32) && defined(UNICODE)
Curl_cwcsdup = (curl_wcsdup_callback)_wcsdup;
#endif
}
@@ -188,18 +188,10 @@ static CURLcode global_init(long flags, bool memoryfuncs)
goto fail;
}
-#if defined(USE_SSH)
if(Curl_ssh_init()) {
+ DEBUGF(fprintf(stderr, "Error: Curl_ssh_init failed\n"));
goto fail;
}
-#endif
-
-#ifdef USE_WOLFSSH
- if(WS_SUCCESS != wolfSSH_Init()) {
- DEBUGF(fprintf(stderr, "Error: wolfSSH_Init failed\n"));
- return CURLE_FAILED_INIT;
- }
-#endif
easy_init_flags = flags;
@@ -295,7 +287,7 @@ void curl_global_cleanup(void)
Curl_ssl_cleanup();
Curl_resolver_global_cleanup();
-#ifdef WIN32
+#ifdef _WIN32
Curl_win32_cleanup(easy_init_flags);
#endif
@@ -752,7 +744,7 @@ static CURLcode easy_perform(struct Curl_easy *data, bool events)
return CURLE_RECURSIVE_API_CALL;
/* Copy the MAXCONNECTS option to the multi handle */
- curl_multi_setopt(multi, CURLMOPT_MAXCONNECTS, data->set.maxconnects);
+ curl_multi_setopt(multi, CURLMOPT_MAXCONNECTS, (long)data->set.maxconnects);
mcode = curl_multi_add_handle(multi, data);
if(mcode) {
@@ -845,8 +837,10 @@ static CURLcode dupset(struct Curl_easy *dst, struct Curl_easy *src)
dst->set = src->set;
Curl_mime_initpart(&dst->set.mimepost);
- /* clear all string pointers first */
+ /* clear all dest string and blob pointers first, in case we error out
+ mid-function */
memset(dst->set.str, 0, STRING_LAST * sizeof(char *));
+ memset(dst->set.blobs, 0, BLOB_LAST * sizeof(struct curl_blob *));
/* duplicate all strings */
for(i = (enum dupstring)0; i< STRING_LASTZEROTERMINATED; i++) {
@@ -855,8 +849,6 @@ static CURLcode dupset(struct Curl_easy *dst, struct Curl_easy *src)
return result;
}
- /* clear all blob pointers first */
- memset(dst->set.blobs, 0, BLOB_LAST * sizeof(struct curl_blob *));
/* duplicate all blobs */
for(j = (enum dupblob)0; j < BLOB_LAST; j++) {
result = Curl_setblobopt(&dst->set.blobs[j], src->set.blobs[j]);
@@ -866,10 +858,13 @@ static CURLcode dupset(struct Curl_easy *dst, struct Curl_easy *src)
/* duplicate memory areas pointed to */
i = STRING_COPYPOSTFIELDS;
- if(src->set.postfieldsize && src->set.str[i]) {
- /* postfieldsize is curl_off_t, Curl_memdup() takes a size_t ... */
- dst->set.str[i] = Curl_memdup(src->set.str[i],
- curlx_sotouz(src->set.postfieldsize));
+ if(src->set.str[i]) {
+ if(src->set.postfieldsize == -1)
+ dst->set.str[i] = strdup(src->set.str[i]);
+ else
+ /* postfieldsize is curl_off_t, Curl_memdup() takes a size_t ... */
+ dst->set.str[i] = Curl_memdup(src->set.str[i],
+ curlx_sotouz(src->set.postfieldsize));
if(!dst->set.str[i])
return CURLE_OUT_OF_MEMORY;
/* point to the new copy */
@@ -919,18 +914,19 @@ struct Curl_easy *curl_easy_duphandle(struct Curl_easy *data)
outcurl->progress.callback = data->progress.callback;
#ifndef CURL_DISABLE_COOKIES
- if(data->cookies) {
+ outcurl->state.cookielist = NULL;
+ if(data->cookies && data->state.cookie_engine) {
/* If cookies are enabled in the parent handle, we enable them
in the clone as well! */
- outcurl->cookies = Curl_cookie_init(data, NULL, outcurl->cookies,
+ outcurl->cookies = Curl_cookie_init(outcurl, NULL, outcurl->cookies,
data->set.cookiesession);
if(!outcurl->cookies)
goto fail;
}
- if(data->set.cookielist) {
- outcurl->set.cookielist = Curl_slist_duplicate(data->set.cookielist);
- if(!outcurl->set.cookielist)
+ if(data->state.cookielist) {
+ outcurl->state.cookielist = Curl_slist_duplicate(data->state.cookielist);
+ if(!outcurl->state.cookielist)
goto fail;
}
#endif
@@ -976,33 +972,6 @@ struct Curl_easy *curl_easy_duphandle(struct Curl_easy *data)
(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.async.resolver,
- data->state.async.resolver))
- goto fail;
-
-#ifdef USE_ARES
- {
- CURLcode rc;
-
- rc = Curl_set_dns_servers(outcurl, data->set.str[STRING_DNS_SERVERS]);
- if(rc && rc != CURLE_NOT_BUILT_IN)
- goto fail;
-
- rc = Curl_set_dns_interface(outcurl, data->set.str[STRING_DNS_INTERFACE]);
- if(rc && rc != CURLE_NOT_BUILT_IN)
- goto fail;
-
- rc = Curl_set_dns_local_ip4(outcurl, data->set.str[STRING_DNS_LOCAL_IP4]);
- if(rc && rc != CURLE_NOT_BUILT_IN)
- goto fail;
-
- rc = Curl_set_dns_local_ip6(outcurl, data->set.str[STRING_DNS_LOCAL_IP6]);
- if(rc && rc != CURLE_NOT_BUILT_IN)
- goto fail;
- }
-#endif /* USE_ARES */
Curl_initinfo(outcurl);
@@ -1016,13 +985,10 @@ fail:
if(outcurl) {
#ifndef CURL_DISABLE_COOKIES
- curl_slist_free_all(outcurl->set.cookielist);
- outcurl->set.cookielist = NULL;
+ free(outcurl->cookies);
#endif
- Curl_safefree(outcurl->state.buffer);
+ free(outcurl->state.buffer);
Curl_dyn_free(&outcurl->state.headerb);
- Curl_safefree(outcurl->state.url);
- Curl_safefree(outcurl->state.referer);
Curl_altsvc_cleanup(&outcurl->asi);
Curl_hsts_cleanup(&outcurl->hsts);
Curl_freeset(outcurl);
diff --git a/libs/libcurl/src/easy_lock.h b/libs/libcurl/src/easy_lock.h
index 49c5e58c86..52f63dd874 100644
--- a/libs/libcurl/src/easy_lock.h
+++ b/libs/libcurl/src/easy_lock.h
@@ -93,6 +93,15 @@ static inline void curl_simple_lock_unlock(curl_simple_lock *lock)
atomic_store_explicit(lock, false, memory_order_release);
}
+#elif defined(USE_THREADS_POSIX) && defined(HAVE_PTHREAD_H)
+
+#include <pthread.h>
+
+#define curl_simple_lock pthread_mutex_t
+#define CURL_SIMPLE_LOCK_INIT PTHREAD_MUTEX_INITIALIZER
+#define curl_simple_lock_lock(m) pthread_mutex_lock(m)
+#define curl_simple_lock_unlock(m) pthread_mutex_unlock(m)
+
#else
#undef GLOBAL_INIT_IS_THREADSAFE
diff --git a/libs/libcurl/src/file.c b/libs/libcurl/src/file.c
index 925372cf3f..7e0570d9f9 100644
--- a/libs/libcurl/src/file.c
+++ b/libs/libcurl/src/file.c
@@ -69,7 +69,7 @@
#include "curl_memory.h"
#include "memdebug.h"
-#if defined(WIN32) || defined(MSDOS) || defined(__EMX__)
+#if defined(_WIN32) || defined(MSDOS) || defined(__EMX__)
#define DOS_FILESYSTEM 1
#elif defined(__amigaos4__)
#define AMIGA_FILESYSTEM 1
@@ -414,7 +414,6 @@ static CURLcode file_do(struct Curl_easy *data, bool *done)
bool size_known;
bool fstated = FALSE;
char *buf = data->state.buffer;
- curl_off_t bytecount = 0;
int fd;
struct FILEPROTO *file;
@@ -563,7 +562,6 @@ static CURLcode file_do(struct Curl_easy *data, bool *done)
if(nread <= 0 || (size_known && (expected_size == 0)))
break;
- bytecount += nread;
if(size_known)
expected_size -= nread;
@@ -571,10 +569,6 @@ static CURLcode file_do(struct Curl_easy *data, bool *done)
if(result)
return result;
- result = Curl_pgrsSetDownloadCounter(data, bytecount);
- if(result)
- return result;
-
if(Curl_pgrsUpdate(data))
result = CURLE_ABORTED_BY_CALLBACK;
else
diff --git a/libs/libcurl/src/fopen.c b/libs/libcurl/src/fopen.c
index d1b2c57e31..444ebd090c 100644
--- a/libs/libcurl/src/fopen.c
+++ b/libs/libcurl/src/fopen.c
@@ -40,6 +40,51 @@
#include "memdebug.h"
/*
+ The dirslash() function breaks a null-terminated pathname string into
+ directory and filename components then returns the directory component up
+ to, *AND INCLUDING*, a final '/'. If there is no directory in the path,
+ this instead returns a "" string.
+
+ This function returns a pointer to malloc'ed memory.
+
+ The input path to this function is expected to have a file name part.
+*/
+
+#ifdef _WIN32
+#define PATHSEP "\\"
+#define IS_SEP(x) (((x) == '/') || ((x) == '\\'))
+#elif defined(MSDOS) || defined(__EMX__) || defined(OS2)
+#define PATHSEP "\\"
+#define IS_SEP(x) ((x) == '\\')
+#else
+#define PATHSEP "/"
+#define IS_SEP(x) ((x) == '/')
+#endif
+
+static char *dirslash(const char *path)
+{
+ size_t n;
+ struct dynbuf out;
+ DEBUGASSERT(path);
+ Curl_dyn_init(&out, CURL_MAX_INPUT_LENGTH);
+ n = strlen(path);
+ if(n) {
+ /* find the rightmost path separator, if any */
+ while(n && !IS_SEP(path[n-1]))
+ --n;
+ /* skip over all the path separators, if any */
+ while(n && IS_SEP(path[n-1]))
+ --n;
+ }
+ if(Curl_dyn_addn(&out, path, n))
+ return NULL;
+ /* if there was a directory, append a single trailing slash */
+ if(n && Curl_dyn_addn(&out, PATHSEP, 1))
+ return NULL;
+ return Curl_dyn_ptr(&out);
+}
+
+/*
* Curl_fopen() opens a file for writing with a temp name, to be renamed
* to the final name when completed. If there is an existing file using this
* name at the time of the open, this function will clone the mode from that
@@ -50,47 +95,44 @@ CURLcode Curl_fopen(struct Curl_easy *data, const char *filename,
FILE **fh, char **tempname)
{
CURLcode result = CURLE_WRITE_ERROR;
- unsigned char randsuffix[9];
+ unsigned char randbuf[41];
char *tempstore = NULL;
struct_stat sb;
int fd = -1;
+ char *dir = NULL;
*tempname = NULL;
*fh = fopen(filename, FOPEN_WRITETEXT);
if(!*fh)
goto fail;
- if(fstat(fileno(*fh), &sb) == -1 || !S_ISREG(sb.st_mode))
+ if(fstat(fileno(*fh), &sb) == -1 || !S_ISREG(sb.st_mode)) {
return CURLE_OK;
+ }
fclose(*fh);
*fh = NULL;
- result = Curl_rand_alnum(data, randsuffix, sizeof(randsuffix));
+ result = Curl_rand_alnum(data, randbuf, sizeof(randbuf));
if(result)
goto fail;
- tempstore = aprintf("%s.%s.tmp", filename, randsuffix);
+ dir = dirslash(filename);
+ if(dir) {
+ /* The temp file name should not end up too long for the target file
+ system */
+ tempstore = aprintf("%s%s.tmp", dir, randbuf);
+ free(dir);
+ }
+
if(!tempstore) {
result = CURLE_OUT_OF_MEMORY;
goto fail;
}
result = CURLE_WRITE_ERROR;
- fd = open(tempstore, O_WRONLY | O_CREAT | O_EXCL, 0600);
+ fd = open(tempstore, O_WRONLY | O_CREAT | O_EXCL, 0600|sb.st_mode);
if(fd == -1)
goto fail;
-#ifdef HAVE_FCHMOD
- {
- struct_stat nsb;
- if((fstat(fd, &nsb) != -1) &&
- (nsb.st_uid == sb.st_uid) && (nsb.st_gid == sb.st_gid)) {
- /* if the user and group are the same, clone the original mode */
- if(fchmod(fd, (mode_t)sb.st_mode) == -1)
- goto fail;
- }
- }
-#endif
-
*fh = fdopen(fd, FOPEN_WRITETEXT);
if(!*fh)
goto fail;
@@ -105,7 +147,6 @@ fail:
}
free(tempstore);
-
return result;
}
diff --git a/libs/libcurl/src/formdata.c b/libs/libcurl/src/formdata.c
index 337cd3b2c5..88901c6bdd 100644
--- a/libs/libcurl/src/formdata.c
+++ b/libs/libcurl/src/formdata.c
@@ -603,9 +603,9 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost,
app passed in a bad combo, so we better check for that first. */
if(form->name) {
/* copy name (without strdup; possibly not null-terminated) */
- form->name = Curl_memdup(form->name, form->namelength?
- form->namelength:
- strlen(form->name) + 1);
+ form->name = Curl_strndup(form->name, form->namelength?
+ form->namelength:
+ strlen(form->name));
}
if(!form->name) {
return_value = CURL_FORMADD_MEMORY;
@@ -792,7 +792,7 @@ static CURLcode setname(curl_mimepart *part, const char *name, size_t len)
/* wrap call to fseeko so it matches the calling convention of callback */
static int fseeko_wrapper(void *stream, curl_off_t offset, int whence)
{
-#if defined(HAVE_FSEEKO)
+#if defined(HAVE_FSEEKO) && defined(HAVE_DECL_FSEEKO)
return fseeko(stream, (off_t)offset, whence);
#elif defined(HAVE__FSEEKI64)
return _fseeki64(stream, (__int64)offset, whence);
diff --git a/libs/libcurl/src/ftp.c b/libs/libcurl/src/ftp.c
index a4e0045122..cee0d97c59 100644
--- a/libs/libcurl/src/ftp.c
+++ b/libs/libcurl/src/ftp.c
@@ -819,7 +819,7 @@ static int ftp_domore_getsock(struct Curl_easy *data,
DEBUGF(infof(data, "ftp_domore_getsock()"));
if(conn->cfilter[SECONDARYSOCKET]
&& !Curl_conn_is_connected(conn, SECONDARYSOCKET))
- return Curl_conn_get_select_socks(data, SECONDARYSOCKET, socks);
+ return 0;
if(FTP_STOP == ftpc->state) {
int bits = GETSOCK_READSOCK(0);
@@ -947,7 +947,7 @@ static CURLcode ftp_state_use_port(struct Curl_easy *data,
char *port_start = NULL;
char *port_sep = NULL;
- addr = calloc(addrlen + 1, 1);
+ addr = calloc(1, addrlen + 1);
if(!addr) {
result = CURLE_OUT_OF_MEMORY;
goto out;
@@ -4379,7 +4379,7 @@ static CURLcode ftp_setup_connection(struct Curl_easy *data,
CURLcode result = CURLE_OK;
struct ftp_conn *ftpc = &conn->proto.ftpc;
- ftp = calloc(sizeof(struct FTP), 1);
+ ftp = calloc(1, sizeof(struct FTP));
if(!ftp)
return CURLE_OUT_OF_MEMORY;
diff --git a/libs/libcurl/src/ftplistparser.c b/libs/libcurl/src/ftplistparser.c
index 4d54379acc..403a019b21 100644
--- a/libs/libcurl/src/ftplistparser.c
+++ b/libs/libcurl/src/ftplistparser.c
@@ -55,9 +55,6 @@
/* The last #include file should be: */
#include "memdebug.h"
-/* allocs buffer which will contain one line of LIST command response */
-#define FTP_BUFFER_ALLOCSIZE 160
-
typedef enum {
PL_UNIX_TOTALSIZE = 0,
PL_UNIX_FILETYPE,
diff --git a/libs/libcurl/src/functypes.h b/libs/libcurl/src/functypes.h
index 9cfbd8a63f..2ee699f7a5 100644
--- a/libs/libcurl/src/functypes.h
+++ b/libs/libcurl/src/functypes.h
@@ -38,7 +38,7 @@
2. For systems with config-*.h files, define them there.
*/
-#ifdef WIN32
+#ifdef _WIN32
/* int recv(SOCKET, char *, int, int) */
#define RECV_TYPE_ARG1 SOCKET
#define RECV_TYPE_ARG2 char *
diff --git a/libs/libcurl/src/getenv.c b/libs/libcurl/src/getenv.c
index 79aed96fb3..51faaad73b 100644
--- a/libs/libcurl/src/getenv.c
+++ b/libs/libcurl/src/getenv.c
@@ -31,10 +31,11 @@
static char *GetEnv(const char *variable)
{
-#if defined(_WIN32_WCE) || defined(CURL_WINDOWS_APP)
+#if defined(_WIN32_WCE) || defined(CURL_WINDOWS_APP) || \
+ defined(__ORBIS__) || defined(__PROSPERO__) /* PlayStation 4 and 5 */
(void)variable;
return NULL;
-#elif defined(WIN32)
+#elif defined(_WIN32)
/* This uses Windows API instead of C runtime getenv() to get the environment
variable since some changes aren't always visible to the latter. #4774 */
char *buf = NULL;
diff --git a/libs/libcurl/src/hostasyn.c b/libs/libcurl/src/hostasyn.c
index 59a009ce33..326aa29983 100644
--- a/libs/libcurl/src/hostasyn.c
+++ b/libs/libcurl/src/hostasyn.c
@@ -67,10 +67,11 @@ CURLcode Curl_addrinfo_callback(struct Curl_easy *data,
int status,
struct Curl_addrinfo *ai)
{
+ struct connectdata *conn = data->conn;
struct Curl_dns_entry *dns = NULL;
CURLcode result = CURLE_OK;
- data->state.async.status = status;
+ conn->resolve_async.status = status;
if(CURL_ASYNC_SUCCESS == status) {
if(ai) {
@@ -78,8 +79,8 @@ CURLcode Curl_addrinfo_callback(struct Curl_easy *data,
Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);
dns = Curl_cache_addr(data, ai,
- data->state.async.hostname, 0,
- data->state.async.port);
+ conn->resolve_async.hostname, 0,
+ conn->resolve_async.port);
if(data->share)
Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
@@ -94,12 +95,12 @@ CURLcode Curl_addrinfo_callback(struct Curl_easy *data,
}
}
- data->state.async.dns = dns;
+ conn->resolve_async.dns = dns;
/* Set async.done TRUE last in this function since it may be used multi-
threaded and once this is TRUE the other thread may read fields from the
async struct */
- data->state.async.done = TRUE;
+ conn->resolve_async.done = TRUE;
/* IPv4: The input hostent struct will be freed by ares when we return from
this function */
diff --git a/libs/libcurl/src/hostip.c b/libs/libcurl/src/hostip.c
index 5490650ee9..8d84708a26 100644
--- a/libs/libcurl/src/hostip.c
+++ b/libs/libcurl/src/hostip.c
@@ -117,6 +117,13 @@
static void freednsentry(void *freethis);
+#ifndef CURL_DISABLE_VERBOSE_STRINGS
+static void show_resolve_info(struct Curl_easy *data,
+ struct Curl_dns_entry *dns);
+#else
+#define show_resolve_info(x,y) Curl_nop_stmt
+#endif
+
/*
* Curl_printable_address() stores a printable version of the 1st address
* given in the 'ai' argument. The result will be stored in the buf that is
@@ -481,9 +488,11 @@ Curl_cache_addr(struct Curl_easy *data,
return NULL;
}
#endif
+ if(!hostlen)
+ hostlen = strlen(hostname);
/* Create a new cache entry */
- dns = calloc(1, sizeof(struct Curl_dns_entry));
+ dns = calloc(1, sizeof(struct Curl_dns_entry) + hostlen);
if(!dns) {
return NULL;
}
@@ -497,6 +506,9 @@ Curl_cache_addr(struct Curl_easy *data,
time(&dns->timestamp);
if(dns->timestamp == 0)
dns->timestamp = 1; /* zero indicates permanent CURLOPT_RESOLVE entry */
+ dns->hostport = port;
+ if(hostlen)
+ memcpy(dns->hostname, hostname, hostlen);
/* Store the resolved data in our DNS cache. */
dns2 = Curl_hash_add(data->dns.hostcache, entry_id, entry_len + 1,
@@ -521,7 +533,7 @@ static struct Curl_addrinfo *get_localhost6(int port, const char *name)
struct sockaddr_in6 sa6;
unsigned char ipv6[16];
unsigned short port16 = (unsigned short)(port & 0xffff);
- ca = calloc(sizeof(struct Curl_addrinfo) + ss_size + hostlen + 1, 1);
+ ca = calloc(1, sizeof(struct Curl_addrinfo) + ss_size + hostlen + 1);
if(!ca)
return NULL;
@@ -568,7 +580,7 @@ static struct Curl_addrinfo *get_localhost(int port, const char *name)
return NULL;
memcpy(&sa.sin_addr, &ipv4, sizeof(ipv4));
- ca = calloc(sizeof(struct Curl_addrinfo) + ss_size + hostlen + 1, 1);
+ ca = calloc(1, sizeof(struct Curl_addrinfo) + ss_size + hostlen + 1);
if(!ca)
return NULL;
ca->ai_flags = 0;
@@ -729,7 +741,7 @@ enum resolve_t Curl_resolv(struct Curl_easy *data,
Curl_set_in_callback(data, true);
st = data->set.resolver_start(
#ifdef USE_CURL_ASYNC
- data->state.async.resolver,
+ conn->resolve_async.resolver,
#else
NULL,
#endif
@@ -823,8 +835,10 @@ enum resolve_t Curl_resolv(struct Curl_easy *data,
if(!dns)
/* returned failure, bail out nicely */
Curl_freeaddrinfo(addr);
- else
+ else {
rc = CURLRESOLV_RESOLVED;
+ show_resolve_info(data, dns);
+ }
}
}
@@ -839,7 +853,7 @@ enum resolve_t Curl_resolv(struct Curl_easy *data,
* execution. This effectively causes the remainder of the application to run
* within a signal handler which is nonportable and could lead to problems.
*/
-static
+CURL_NORETURN static
void alarmfunc(int sig)
{
(void)sig;
@@ -1269,9 +1283,11 @@ err:
Curl_freeaddrinfo(head);
return CURLE_OUT_OF_MEMORY;
}
+#ifndef CURL_DISABLE_VERBOSE_STRINGS
infof(data, "Added %.*s:%d:%s to DNS cache%s",
(int)hlen, host_begin, port, addresses,
permanent ? "" : " (non-permanent)");
+#endif
/* Wildcard hostname */
if((hlen == 1) && (host_begin[0] == '*')) {
@@ -1285,18 +1301,89 @@ err:
return CURLE_OK;
}
+#ifndef CURL_DISABLE_VERBOSE_STRINGS
+static void show_resolve_info(struct Curl_easy *data,
+ struct Curl_dns_entry *dns)
+{
+ struct Curl_addrinfo *a;
+ CURLcode result = CURLE_OK;
+#ifdef CURLRES_IPV6
+ struct dynbuf out[2];
+#else
+ struct dynbuf out[1];
+#endif
+ DEBUGASSERT(data);
+ DEBUGASSERT(dns);
+
+ if(!data->set.verbose ||
+ /* ignore no name or numerical IP addresses */
+ !dns->hostname[0] || Curl_host_is_ipnum(dns->hostname))
+ return;
+
+ a = dns->addr;
+
+ infof(data, "Host %s:%d was resolved.",
+ (dns->hostname[0] ? dns->hostname : "(none)"), dns->hostport);
+
+ Curl_dyn_init(&out[0], 1024);
+#ifdef CURLRES_IPV6
+ Curl_dyn_init(&out[1], 1024);
+#endif
+
+ while(a) {
+ if(
+#ifdef CURLRES_IPV6
+ a->ai_family == PF_INET6 ||
+#endif
+ a->ai_family == PF_INET) {
+ char buf[MAX_IPADR_LEN];
+ struct dynbuf *d = &out[(a->ai_family != PF_INET)];
+ Curl_printable_address(a, buf, sizeof(buf));
+ if(Curl_dyn_len(d))
+ result = Curl_dyn_addn(d, ", ", 2);
+ if(!result)
+ result = Curl_dyn_add(d, buf);
+ if(result) {
+ infof(data, "too many IP, can't show");
+ goto fail;
+ }
+ }
+ a = a->ai_next;
+ }
+
+#ifdef CURLRES_IPV6
+ infof(data, "IPv6: %s",
+ (Curl_dyn_len(&out[1]) ? Curl_dyn_ptr(&out[1]) : "(none)"));
+#endif
+ infof(data, "IPv4: %s",
+ (Curl_dyn_len(&out[0]) ? Curl_dyn_ptr(&out[0]) : "(none)"));
+
+fail:
+ Curl_dyn_free(&out[0]);
+#ifdef CURLRES_IPV6
+ Curl_dyn_free(&out[1]);
+#endif
+}
+#endif
+
CURLcode Curl_resolv_check(struct Curl_easy *data,
struct Curl_dns_entry **dns)
{
+ CURLcode result;
#if defined(CURL_DISABLE_DOH) && !defined(CURLRES_ASYNCH)
(void)data;
(void)dns;
#endif
#ifndef CURL_DISABLE_DOH
- if(data->conn->bits.doh)
- return Curl_doh_is_resolved(data, dns);
+ if(data->conn->bits.doh) {
+ result = Curl_doh_is_resolved(data, dns);
+ }
+ else
#endif
- return Curl_resolver_is_resolved(data, dns);
+ result = Curl_resolver_is_resolved(data, dns);
+ if(*dns)
+ show_resolve_info(data, *dns);
+ return result;
}
int Curl_resolv_getsock(struct Curl_easy *data,
@@ -1328,9 +1415,9 @@ CURLcode Curl_once_resolved(struct Curl_easy *data, bool *protocol_done)
struct connectdata *conn = data->conn;
#ifdef USE_CURL_ASYNC
- if(data->state.async.dns) {
- conn->dns_entry = data->state.async.dns;
- data->state.async.dns = NULL;
+ if(conn->resolve_async.dns) {
+ conn->dns_entry = conn->resolve_async.dns;
+ conn->resolve_async.dns = NULL;
}
#endif
@@ -1352,11 +1439,11 @@ CURLcode Curl_once_resolved(struct Curl_easy *data, bool *protocol_done)
#ifdef USE_CURL_ASYNC
CURLcode Curl_resolver_error(struct Curl_easy *data)
{
+ struct connectdata *conn = data->conn;
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;
@@ -1369,7 +1456,7 @@ CURLcode Curl_resolver_error(struct Curl_easy *data)
}
failf(data, "Could not resolve %s: %s", host_or_proxy,
- data->state.async.hostname);
+ conn->resolve_async.hostname);
return result;
}
diff --git a/libs/libcurl/src/hostip.h b/libs/libcurl/src/hostip.h
index 756d55c1d3..f47e3abaf9 100644
--- a/libs/libcurl/src/hostip.h
+++ b/libs/libcurl/src/hostip.h
@@ -64,6 +64,10 @@ struct Curl_dns_entry {
time_t timestamp;
/* use-counter, use Curl_resolv_unlock to release reference */
long inuse;
+ /* hostname port number that resolved to addr. */
+ int hostport;
+ /* hostname that resolved to addr. may be NULL (unix domain sockets). */
+ char hostname[1];
};
bool Curl_host_is_ipnum(const char *hostname);
diff --git a/libs/libcurl/src/hostip6.c b/libs/libcurl/src/hostip6.c
index 4b33e3e8e4..5e8c3abbda 100644
--- a/libs/libcurl/src/hostip6.c
+++ b/libs/libcurl/src/hostip6.c
@@ -71,8 +71,7 @@ bool Curl_ipvalid(struct Curl_easy *data, struct connectdata *conn)
#if defined(CURLRES_SYNCH)
#ifdef DEBUG_ADDRINFO
-static void dump_addrinfo(struct connectdata *conn,
- const struct Curl_addrinfo *ai)
+static void dump_addrinfo(const struct Curl_addrinfo *ai)
{
printf("dump_addrinfo:\n");
for(; ai; ai = ai->ai_next) {
@@ -84,7 +83,7 @@ static void dump_addrinfo(struct connectdata *conn,
}
}
#else
-#define dump_addrinfo(x,y) Curl_nop_stmt
+#define dump_addrinfo(x) Curl_nop_stmt
#endif
/*
@@ -149,7 +148,7 @@ struct Curl_addrinfo *Curl_getaddrinfo(struct Curl_easy *data,
Curl_addrinfo_set_port(res, port);
}
- dump_addrinfo(conn, res);
+ dump_addrinfo(res);
return res;
}
diff --git a/libs/libcurl/src/hsts.c b/libs/libcurl/src/hsts.c
index baf308874a..9ccfa14905 100644
--- a/libs/libcurl/src/hsts.c
+++ b/libs/libcurl/src/hsts.c
@@ -40,6 +40,7 @@
#include "fopen.h"
#include "rename.h"
#include "share.h"
+#include "strdup.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
@@ -76,7 +77,7 @@ static time_t hsts_debugtime(void *unused)
struct hsts *Curl_hsts_init(void)
{
- struct hsts *h = calloc(sizeof(struct hsts), 1);
+ struct hsts *h = calloc(1, sizeof(struct hsts));
if(h) {
Curl_llist_init(&h->list, NULL);
}
@@ -108,7 +109,7 @@ void Curl_hsts_cleanup(struct hsts **hp)
static struct stsentry *hsts_entry(void)
{
- return calloc(sizeof(struct stsentry), 1);
+ return calloc(1, sizeof(struct stsentry));
}
static CURLcode hsts_create(struct hsts *h,
@@ -116,23 +117,30 @@ static CURLcode hsts_create(struct hsts *h,
bool subdomains,
curl_off_t expires)
{
- struct stsentry *sts = hsts_entry();
+ struct stsentry *sts;
char *duphost;
size_t hlen;
+ DEBUGASSERT(h);
+ DEBUGASSERT(hostname);
+
+ hlen = strlen(hostname);
+ if(hlen && (hostname[hlen - 1] == '.'))
+ /* strip off any trailing dot */
+ --hlen;
+ if(!hlen)
+ /* no host name left */
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+
+ sts = hsts_entry();
if(!sts)
return CURLE_OUT_OF_MEMORY;
- duphost = strdup(hostname);
+ duphost = Curl_strndup(hostname, hlen);
if(!duphost) {
free(sts);
return CURLE_OUT_OF_MEMORY;
}
- hlen = strlen(duphost);
- if(duphost[hlen - 1] == '.')
- /* strip off trailing any dot */
- duphost[--hlen] = 0;
-
sts->host = duphost;
sts->expires = expires;
sts->includeSubDomains = subdomains;
@@ -564,7 +572,7 @@ CURLcode Curl_hsts_loadcb(struct Curl_easy *data, struct hsts *h)
void Curl_hsts_loadfiles(struct Curl_easy *data)
{
- struct curl_slist *l = data->set.hstslist;
+ struct curl_slist *l = data->state.hstslist;
if(l) {
Curl_share_lock(data, CURL_LOCK_DATA_HSTS, CURL_LOCK_ACCESS_SINGLE);
diff --git a/libs/libcurl/src/http.c b/libs/libcurl/src/http.c
index 9b935d88e1..d27c300bd3 100644
--- a/libs/libcurl/src/http.c
+++ b/libs/libcurl/src/http.c
@@ -836,6 +836,7 @@ output_auth_headers(struct Curl_easy *data,
(data->state.aptr.user ?
data->state.aptr.user : ""));
#else
+ (void)proxy;
infof(data, "Server auth using %s with user '%s'",
auth, data->state.aptr.user ?
data->state.aptr.user : "");
@@ -845,7 +846,7 @@ output_auth_headers(struct Curl_easy *data,
else
authstatus->multipass = FALSE;
- return CURLE_OK;
+ return result;
}
/**
@@ -970,17 +971,21 @@ Curl_http_output_auth(struct Curl_easy *data,
}
#endif
-/*
- * Curl_http_input_auth() deals with Proxy-Authenticate: and WWW-Authenticate:
- * headers. They are dealt with both in the transfer.c main loop and in the
- * proxy CONNECT loop.
- */
-
+#if defined(USE_SPNEGO) || defined(USE_NTLM) || \
+ !defined(CURL_DISABLE_DIGEST_AUTH) || \
+ !defined(CURL_DISABLE_BASIC_AUTH) || \
+ !defined(CURL_DISABLE_BEARER_AUTH)
static int is_valid_auth_separator(char ch)
{
return ch == '\0' || ch == ',' || ISSPACE(ch);
}
+#endif
+/*
+ * Curl_http_input_auth() deals with Proxy-Authenticate: and WWW-Authenticate:
+ * headers. They are dealt with both in the transfer.c main loop and in the
+ * proxy CONNECT loop.
+ */
CURLcode Curl_http_input_auth(struct Curl_easy *data, bool proxy,
const char *auth) /* the first non-space */
{
@@ -992,11 +997,15 @@ CURLcode Curl_http_input_auth(struct Curl_easy *data, bool proxy,
curlnegotiate *negstate = proxy ? &conn->proxy_negotiate_state :
&conn->http_negotiate_state;
#endif
+#if defined(USE_SPNEGO) || \
+ defined(USE_NTLM) || \
+ !defined(CURL_DISABLE_DIGEST_AUTH) || \
+ !defined(CURL_DISABLE_BASIC_AUTH) || \
+ !defined(CURL_DISABLE_BEARER_AUTH)
+
unsigned long *availp;
struct auth *authp;
- (void) conn; /* In case conditionals make it unused. */
-
if(proxy) {
availp = &data->info.proxyauthavail;
authp = &data->state.authproxy;
@@ -1005,6 +1014,11 @@ CURLcode Curl_http_input_auth(struct Curl_easy *data, bool proxy,
availp = &data->info.httpauthavail;
authp = &data->state.authhost;
}
+#else
+ (void) proxy;
+#endif
+
+ (void) conn; /* In case conditionals make it unused. */
/*
* Here we check if we want the specific single authentication (using ==) and
@@ -1140,7 +1154,14 @@ CURLcode Curl_http_input_auth(struct Curl_easy *data, bool proxy,
}
}
#else
- ;
+ {
+ /*
+ * Empty block to terminate the if-else chain correctly.
+ *
+ * A semicolon would yield the same result here, but can cause a
+ * compiler warning when -Wextra is enabled.
+ */
+ }
#endif
/* there may be multiple methods on one line, so keep reading */
@@ -1403,7 +1424,7 @@ CURLcode Curl_buffer_send(struct dynbuf *in,
* and install our own `data->state.fread_func` that
* on subsequent calls reads `in` empty.
* - when the whisked away `in` is empty, the `fread_func`
- * is restored ot its original state.
+ * is restored to its original state.
* The problem is that `fread_func` can only return
* `upload_buffer_size` lengths. If the send we do here
* is larger and blocks, we do re-sending with smaller
@@ -1678,8 +1699,6 @@ static CURLcode expect100(struct Curl_easy *data,
struct dynbuf *req)
{
CURLcode result = CURLE_OK;
- data->state.expect100header = FALSE; /* default to false unless it is set
- to TRUE below */
if(!data->state.disableexpect && Curl_use_http_1_1plus(data, conn) &&
(conn->httpversion < 20)) {
/* if not doing HTTP 1.0 or version 2, or disabled explicitly, we add an
@@ -2414,14 +2433,16 @@ CURLcode Curl_http_body(struct Curl_easy *data, struct connectdata *conn,
/* Convert the form structure into a mime structure, then keep
the conversion */
if(!data->state.formp) {
- data->state.formp = calloc(sizeof(curl_mimepart), 1);
+ data->state.formp = calloc(1, sizeof(curl_mimepart));
if(!data->state.formp)
return CURLE_OUT_OF_MEMORY;
Curl_mime_cleanpart(data->state.formp);
result = Curl_getformdata(data, data->state.formp, data->set.httppost,
data->state.fread_func);
- if(result)
+ if(result) {
+ Curl_safefree(data->state.formp);
return result;
+ }
data->state.mimepost = data->state.formp;
}
break;
@@ -2494,6 +2515,29 @@ CURLcode Curl_http_body(struct Curl_easy *data, struct connectdata *conn,
return result;
}
+static CURLcode addexpect(struct Curl_easy *data, struct connectdata *conn,
+ struct dynbuf *r)
+{
+ data->state.expect100header = FALSE;
+ /* Avoid Expect: 100-continue if Upgrade: is used */
+ if(data->req.upgr101 == UPGR101_INIT) {
+ struct HTTP *http = data->req.p.http;
+ /* For really small puts we don't use Expect: headers at all, and for
+ 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. */
+ char *ptr = Curl_checkheaders(data, STRCONST("Expect"));
+ if(ptr) {
+ data->state.expect100header =
+ Curl_compareheader(ptr, STRCONST("Expect:"),
+ STRCONST("100-continue"));
+ }
+ else if(http->postsize > EXPECT_100_THRESHOLD || http->postsize < 0)
+ return expect100(data, conn, r);
+ }
+ return CURLE_OK;
+}
+
CURLcode Curl_http_bodysend(struct Curl_easy *data, struct connectdata *conn,
struct dynbuf *r, Curl_HttpReq httpreq)
{
@@ -2506,14 +2550,8 @@ CURLcode Curl_http_bodysend(struct Curl_easy *data, struct connectdata *conn,
#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
- data yet. */
switch(httpreq) {
-
case HTTPREQ_PUT: /* Let's PUT the data to the server! */
if(conn->bits.authneg)
@@ -2531,20 +2569,9 @@ CURLcode Curl_http_bodysend(struct Curl_easy *data, struct connectdata *conn,
return result;
}
- /* For really small puts we don't use Expect: headers at all, and for
- 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(data, STRCONST("Expect"));
- if(ptr) {
- data->state.expect100header =
- Curl_compareheader(ptr, STRCONST("Expect:"), STRCONST("100-continue"));
- }
- else if(http->postsize > EXPECT_100_THRESHOLD || http->postsize < 0) {
- result = expect100(data, conn, r);
- if(result)
- return result;
- }
+ result = addexpect(data, conn, r);
+ if(result)
+ return result;
/* end of headers */
result = Curl_dyn_addn(r, STRCONST("\r\n"));
@@ -2617,22 +2644,9 @@ CURLcode Curl_http_bodysend(struct Curl_easy *data, struct connectdata *conn,
}
#endif
- /* For really small posts we don't use Expect: headers at all, and for
- 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(data, STRCONST("Expect"));
- if(ptr) {
- data->state.expect100header =
- Curl_compareheader(ptr, STRCONST("Expect:"), STRCONST("100-continue"));
- }
- else if(http->postsize > EXPECT_100_THRESHOLD || http->postsize < 0) {
- result = expect100(data, conn, r);
- if(result)
- return result;
- }
- else
- data->state.expect100header = FALSE;
+ result = addexpect(data, conn, r);
+ if(result)
+ return result;
/* make the request end in a true CRLF */
result = Curl_dyn_addn(r, STRCONST("\r\n"));
@@ -2692,22 +2706,9 @@ CURLcode Curl_http_bodysend(struct Curl_easy *data, struct connectdata *conn,
return result;
}
- /* For really small posts we don't use Expect: headers at all, and for
- 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(data, STRCONST("Expect"));
- if(ptr) {
- data->state.expect100header =
- Curl_compareheader(ptr, STRCONST("Expect:"), STRCONST("100-continue"));
- }
- else if(http->postsize > EXPECT_100_THRESHOLD || http->postsize < 0) {
- result = expect100(data, conn, r);
- if(result)
- return result;
- }
- else
- data->state.expect100header = FALSE;
+ result = addexpect(data, conn, r);
+ if(result)
+ return result;
#ifndef USE_HYPER
/* With Hyper the body is always passed on separately */
@@ -3193,7 +3194,7 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
DEBUGASSERT(Curl_conn_is_http2(data, conn, FIRSTSOCKET));
break;
case CURL_HTTP_VERSION_1_1:
- /* continue with HTTP/1.1 when explicitly requested */
+ /* continue with HTTP/1.x when explicitly requested */
break;
default:
/* Check if user wants to use HTTP/2 with clear TCP */
@@ -3685,7 +3686,7 @@ CURLcode Curl_http_header(struct Curl_easy *data, struct connectdata *conn,
k->content_range = TRUE;
}
}
- else
+ else if(k->httpcode < 300)
data->state.resume_from = 0; /* get everything */
}
#if !defined(CURL_DISABLE_COOKIES)
@@ -3996,35 +3997,30 @@ CURLcode Curl_bump_headersize(struct Curl_easy *data,
*/
CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
struct connectdata *conn,
- ssize_t *nread,
- bool *stop_reading)
+ const char *buf, size_t blen,
+ size_t *pconsumed)
{
CURLcode result;
struct SingleRequest *k = &data->req;
- ssize_t onread = *nread;
- char *ostr = k->str;
char *headp;
- char *str_start;
char *end_ptr;
/* header line within buffer loop */
+ *pconsumed = 0;
do {
- size_t rest_length;
- size_t full_length;
+ size_t line_length;
int writetype;
- /* str_start is start of line within buf */
- str_start = k->str;
-
/* data is in network encoding so use 0x0a instead of '\n' */
- end_ptr = memchr(str_start, 0x0a, *nread);
+ end_ptr = memchr(buf, 0x0a, blen);
if(!end_ptr) {
/* Not a complete header line within buffer, append the data to
the end of the headerbuff. */
- result = Curl_dyn_addn(&data->state.headerb, str_start, *nread);
+ result = Curl_dyn_addn(&data->state.headerb, buf, blen);
if(result)
return result;
+ *pconsumed += blen;
if(!k->headerline) {
/* check if this looks like a protocol header */
@@ -4036,31 +4032,28 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
if(st == STATUS_BAD) {
/* this is not the beginning of a protocol first header line */
k->header = FALSE;
- k->badheader = HEADER_ALLBAD;
+ k->badheader = TRUE;
streamclose(conn, "bad HTTP: No end-of-message indicator");
if(!data->set.http09_allowed) {
failf(data, "Received HTTP/0.9 when not allowed");
return CURLE_UNSUPPORTED_PROTOCOL;
}
- break;
+ goto out;
}
}
-
- break; /* read more and try again */
+ goto out; /* read more and try again */
}
/* decrease the size of the remaining (supposed) header line */
- rest_length = (end_ptr - k->str) + 1;
- *nread -= (ssize_t)rest_length;
-
- k->str = end_ptr + 1; /* move past new line */
-
- full_length = k->str - str_start;
-
- result = Curl_dyn_addn(&data->state.headerb, str_start, full_length);
+ line_length = (end_ptr - buf) + 1;
+ result = Curl_dyn_addn(&data->state.headerb, buf, line_length);
if(result)
return result;
+ blen -= line_length;
+ buf += line_length;
+ *pconsumed += line_length;
+
/****
* We now have a FULL header line in 'headerb'.
*****/
@@ -4078,14 +4071,12 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
return CURLE_UNSUPPORTED_PROTOCOL;
}
k->header = FALSE;
- if(*nread)
+ if(blen)
/* since there's more, this is a partial bad header */
- k->badheader = HEADER_PARTHEADER;
+ k->badheader = TRUE;
else {
/* this was all we read so it's all a bad header */
- k->badheader = HEADER_ALLBAD;
- *nread = onread;
- k->str = ostr;
+ k->badheader = TRUE;
return CURLE_OK;
}
break;
@@ -4139,22 +4130,23 @@ 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_upgrade(data, conn, FIRSTSOCKET,
- k->str, *nread);
+ result = Curl_http2_upgrade(data, conn, FIRSTSOCKET, buf, blen);
if(result)
return result;
- *nread = 0;
+ *pconsumed += blen;
+ blen = 0;
}
#ifdef USE_WEBSOCKETS
else if(k->upgr101 == UPGR101_WS) {
/* verify the response */
- result = Curl_ws_accept(data, k->str, *nread);
+ result = Curl_ws_accept(data, buf, blen);
if(result)
return result;
k->header = FALSE; /* no more header to parse! */
if(data->set.connect_only) {
k->keepon &= ~KEEP_RECV; /* read no more content */
- *nread = 0;
+ *pconsumed += blen;
+ blen = 0;
}
}
#endif
@@ -4366,7 +4358,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
* out and return home.
*/
if(data->req.no_body)
- *stop_reading = TRUE;
+ k->download_done = TRUE;
#ifndef CURL_DISABLE_RTSP
else if((conn->handler->protocol & CURLPROTO_RTSP) &&
(data->set.rtspreq == RTSPREQ_DESCRIBE) &&
@@ -4375,7 +4367,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
absent, a length 0 must be assumed. It will prevent libcurl from
hanging on DESCRIBE request that got refused for whatever
reason */
- *stop_reading = TRUE;
+ k->download_done = TRUE;
#endif
/* If max download size is *zero* (nothing) we already have
@@ -4386,15 +4378,12 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
if(0 == k->maxdownload
&& !Curl_conn_is_http2(data, conn, FIRSTSOCKET)
&& !Curl_conn_is_http3(data, conn, FIRSTSOCKET))
- *stop_reading = TRUE;
+ k->download_done = TRUE;
- if(*stop_reading) {
- /* we make sure that this socket isn't read more now */
- k->keepon &= ~KEEP_RECV;
- }
-
- Curl_debug(data, CURLINFO_HEADER_IN, str_start, headerlen);
- break; /* exit header line loop */
+ Curl_debug(data, CURLINFO_HEADER_IN,
+ Curl_dyn_ptr(&data->state.headerb),
+ Curl_dyn_len(&data->state.headerb));
+ goto out; /* exit header line loop */
}
/* We continue reading headers, reset the line-based header */
@@ -4583,12 +4572,12 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
Curl_dyn_reset(&data->state.headerb);
}
- while(*k->str); /* header line within buffer */
+ while(blen);
/* We might have reached the end of the header part here, but
there might be a non-header part left in the end of the read
buffer. */
-
+out:
return CURLE_OK;
}
@@ -4618,17 +4607,6 @@ out:
return result;
}
-/* simple implementation of strndup(), which isn't portable */
-static char *my_strndup(const char *ptr, size_t len)
-{
- char *copy = malloc(len + 1);
- if(!copy)
- return NULL;
- memcpy(copy, ptr, len);
- copy[len] = '\0';
- return copy;
-}
-
CURLcode Curl_http_req_make(struct httpreq **preq,
const char *method, size_t m_len,
const char *scheme, size_t s_len,
@@ -4647,17 +4625,17 @@ CURLcode Curl_http_req_make(struct httpreq **preq,
goto out;
memcpy(req->method, method, m_len);
if(scheme) {
- req->scheme = my_strndup(scheme, s_len);
+ req->scheme = Curl_strndup(scheme, s_len);
if(!req->scheme)
goto out;
}
if(authority) {
- req->authority = my_strndup(authority, a_len);
+ req->authority = Curl_strndup(authority, a_len);
if(!req->authority)
goto out;
}
if(path) {
- req->path = my_strndup(path, p_len);
+ req->path = Curl_strndup(path, p_len);
if(!req->path)
goto out;
}
diff --git a/libs/libcurl/src/http.h b/libs/libcurl/src/http.h
index fc4f518530..f7571ebdb0 100644
--- a/libs/libcurl/src/http.h
+++ b/libs/libcurl/src/http.h
@@ -227,8 +227,8 @@ CURLcode Curl_http_size(struct Curl_easy *data);
CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
struct connectdata *conn,
- ssize_t *nread,
- bool *stop_reading);
+ const char *buf, size_t blen,
+ size_t *pconsumed);
/**
* Curl_http_output_auth() setups the authentication headers for the
@@ -263,7 +263,7 @@ CURLcode Curl_http_decode_status(int *pstatus, const char *s, size_t len);
* All about a core HTTP request, excluding body and trailers
*/
struct httpreq {
- char method[12];
+ char method[24];
char *scheme;
char *authority;
char *path;
diff --git a/libs/libcurl/src/http2.c b/libs/libcurl/src/http2.c
index ba3bfef61c..6a7d18379d 100644
--- a/libs/libcurl/src/http2.c
+++ b/libs/libcurl/src/http2.c
@@ -107,14 +107,14 @@ static int populate_settings(nghttp2_settings_entry *iv,
return 3;
}
-static size_t populate_binsettings(uint8_t *binsettings,
- struct Curl_easy *data)
+static ssize_t populate_binsettings(uint8_t *binsettings,
+ struct Curl_easy *data)
{
nghttp2_settings_entry iv[H2_SETTINGS_IV_LEN];
int ivlen;
ivlen = populate_settings(iv, data);
- /* this returns number of bytes it wrote */
+ /* this returns number of bytes it wrote or a negative number on error. */
return nghttp2_pack_settings_payload(binsettings, H2_BINSETTINGS_LEN,
iv, ivlen);
}
@@ -369,12 +369,15 @@ static ssize_t nw_out_writer(void *writer_ctx,
{
struct Curl_cfilter *cf = writer_ctx;
struct Curl_easy *data = CF_DATA_CURRENT(cf);
- ssize_t nwritten;
- nwritten = Curl_conn_cf_send(cf->next, data, (const char *)buf, buflen, err);
- if(nwritten > 0)
- CURL_TRC_CF(data, cf, "[0] egress: wrote %zd bytes", nwritten);
- return nwritten;
+ if(data) {
+ ssize_t nwritten = Curl_conn_cf_send(cf->next, data,
+ (const char *)buf, buflen, err);
+ if(nwritten > 0)
+ CURL_TRC_CF(data, cf, "[0] egress: wrote %zd bytes", nwritten);
+ return nwritten;
+ }
+ return 0;
}
static ssize_t send_callback(nghttp2_session *h2,
@@ -452,9 +455,14 @@ static CURLcode cf_h2_ctx_init(struct Curl_cfilter *cf,
* in the H1 request and we upgrade from there. This stream
* is opened implicitly as #1. */
uint8_t binsettings[H2_BINSETTINGS_LEN];
- size_t binlen; /* length of the binsettings data */
+ ssize_t binlen; /* length of the binsettings data */
binlen = populate_binsettings(binsettings, data);
+ if(binlen <= 0) {
+ failf(data, "nghttp2 unexpectedly failed on pack_settings_payload");
+ result = CURLE_FAILED_INIT;
+ goto out;
+ }
result = http2_data_setup(cf, data, &stream);
if(result)
@@ -1076,16 +1084,11 @@ static CURLcode on_stream_frame(struct Curl_cfilter *cf,
stream->reset = TRUE;
}
stream->send_closed = TRUE;
- data->req.keepon &= ~KEEP_SEND_HOLD;
drain_stream(cf, data, stream);
break;
case NGHTTP2_WINDOW_UPDATE:
- if((data->req.keepon & KEEP_SEND_HOLD) &&
- (data->req.keepon & KEEP_SEND)) {
- data->req.keepon &= ~KEEP_SEND_HOLD;
+ if(CURL_WANT_SEND(data)) {
drain_stream(cf, data, stream);
- CURL_TRC_CF(data, cf, "[%d] un-holding after win update",
- stream_id);
}
break;
default:
@@ -1230,15 +1233,10 @@ static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame,
* window and *assume* that we treat this like a WINDOW_UPDATE. Some
* servers send an explicit WINDOW_UPDATE, but not all seem to do that.
* To be safe, we UNHOLD a stream in order not to stall. */
- if((data->req.keepon & KEEP_SEND_HOLD) &&
- (data->req.keepon & KEEP_SEND)) {
+ if(CURL_WANT_SEND(data)) {
struct stream_ctx *stream = H2_STREAM_CTX(data);
- data->req.keepon &= ~KEEP_SEND_HOLD;
- if(stream) {
+ if(stream)
drain_stream(cf, data, stream);
- CURL_TRC_CF(data, cf, "[%d] un-holding after SETTINGS",
- stream_id);
- }
}
}
break;
@@ -1338,7 +1336,6 @@ static int on_stream_close(nghttp2_session *session, int32_t stream_id,
stream->error = error_code;
if(stream->error)
stream->reset = TRUE;
- data_s->req.keepon &= ~KEEP_SEND_HOLD;
if(stream->error)
CURL_TRC_CF(data_s, cf, "[%d] RESET: %s (err %d)",
@@ -1602,10 +1599,10 @@ static int error_callback(nghttp2_session *session,
size_t len,
void *userp)
{
+ struct Curl_cfilter *cf = userp;
+ struct Curl_easy *data = CF_DATA_CURRENT(cf);
(void)session;
- (void)msg;
- (void)len;
- (void)userp;
+ failf(data, "%.*s", (int)len, msg);
return 0;
}
#endif
@@ -1621,7 +1618,7 @@ CURLcode Curl_http2_request_upgrade(struct dynbuf *req,
size_t blen;
struct SingleRequest *k = &data->req;
uint8_t binsettings[H2_BINSETTINGS_LEN];
- size_t binlen; /* length of the binsettings data */
+ ssize_t binlen; /* length of the binsettings data */
binlen = populate_binsettings(binsettings, data);
if(binlen <= 0) {
@@ -2052,23 +2049,13 @@ static ssize_t h2_submit(struct stream_ctx **pstream,
/* no longer needed */
Curl_h1_req_parse_free(&stream->h1);
- nheader = Curl_dynhds_count(&h2_headers);
- nva = malloc(sizeof(nghttp2_nv) * nheader);
+ nva = Curl_dynhds_to_nva(&h2_headers, &nheader);
if(!nva) {
*err = CURLE_OUT_OF_MEMORY;
nwritten = -1;
goto out;
}
- for(i = 0; i < nheader; ++i) {
- struct dynhds_entry *e = Curl_dynhds_getn(&h2_headers, i);
- nva[i].name = (unsigned char *)e->name;
- nva[i].namelen = e->namelen;
- nva[i].value = (unsigned char *)e->value;
- nva[i].valuelen = e->valuelen;
- nva[i].flags = NGHTTP2_NV_FLAG_NONE;
- }
-
h2_pri_spec(data, &pri_spec);
if(!nghttp2_session_check_request_allowed(ctx->h2))
CURL_TRC_CF(data, cf, "send request NOT allowed (via nghttp2)");
@@ -2272,14 +2259,6 @@ static ssize_t cf_h2_send(struct Curl_cfilter *cf, struct Curl_easy *data,
* frame buffer or our network out buffer. */
size_t rwin = nghttp2_session_get_stream_remote_window_size(ctx->h2,
stream->id);
- if(rwin == 0) {
- /* H2 flow window exhaustion. We need to HOLD upload until we get
- * a WINDOW_UPDATE from the server. */
- data->req.keepon |= KEEP_SEND_HOLD;
- CURL_TRC_CF(data, cf, "[%d] holding send as remote flow "
- "window is exhausted", stream->id);
- }
-
/* Whatever the cause, we need to return CURL_EAGAIN for this call.
* We have unwritten state that needs us being invoked again and EAGAIN
* is the only way to ensure that. */
@@ -2331,38 +2310,34 @@ out:
return nwritten;
}
-static int cf_h2_get_select_socks(struct Curl_cfilter *cf,
- struct Curl_easy *data,
- curl_socket_t *sock)
+static void cf_h2_adjust_pollset(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ struct easy_pollset *ps)
{
struct cf_h2_ctx *ctx = cf->ctx;
- struct SingleRequest *k = &data->req;
- struct stream_ctx *stream = H2_STREAM_CTX(data);
- int bitmap = GETSOCK_BLANK;
- struct cf_call_data save;
+ bool want_recv = CURL_WANT_RECV(data);
+ bool want_send = CURL_WANT_SEND(data);
- CF_DATA_SAVE(save, cf, data);
- sock[0] = Curl_conn_cf_get_socket(cf, data);
-
- if(!(k->keepon & (KEEP_RECV_PAUSE|KEEP_RECV_HOLD)))
- /* Unless paused - in an HTTP/2 connection we can basically always get a
- frame so we should always be ready for one */
- bitmap |= GETSOCK_READSOCK(0);
-
- /* we're (still uploading OR the HTTP/2 layer wants to send data) AND
- there's a window to send data in */
- if((((k->keepon & KEEP_SENDBITS) == KEEP_SEND) ||
- nghttp2_session_want_write(ctx->h2)) &&
- (nghttp2_session_get_remote_window_size(ctx->h2) &&
- nghttp2_session_get_stream_remote_window_size(ctx->h2,
- stream->id)))
- bitmap |= GETSOCK_WRITESOCK(0);
+ if(ctx->h2 && (want_recv || want_send)) {
+ struct stream_ctx *stream = H2_STREAM_CTX(data);
+ curl_socket_t sock = Curl_conn_cf_get_socket(cf, data);
+ struct cf_call_data save;
+ bool c_exhaust, s_exhaust;
- CF_DATA_RESTORE(cf, save);
- return bitmap;
+ CF_DATA_SAVE(save, cf, data);
+ c_exhaust = !nghttp2_session_get_remote_window_size(ctx->h2);
+ s_exhaust = stream && stream->id >= 0 &&
+ !nghttp2_session_get_stream_remote_window_size(ctx->h2,
+ stream->id);
+ want_recv = (want_recv || c_exhaust || s_exhaust);
+ want_send = (!s_exhaust && want_send) ||
+ (!c_exhaust && nghttp2_session_want_write(ctx->h2));
+
+ Curl_pollset_set(data, ps, sock, want_recv, want_send);
+ CF_DATA_RESTORE(cf, save);
+ }
}
-
static CURLcode cf_h2_connect(struct Curl_cfilter *cf,
struct Curl_easy *data,
bool blocking, bool *done)
@@ -2511,14 +2486,15 @@ static CURLcode cf_h2_cntrl(struct Curl_cfilter *cf,
case CF_CTRL_DATA_PAUSE:
result = http2_data_pause(cf, data, (arg1 != 0));
break;
- case CF_CTRL_DATA_DONE_SEND: {
+ case CF_CTRL_DATA_DONE_SEND:
result = http2_data_done_send(cf, data);
break;
- }
- case CF_CTRL_DATA_DONE: {
+ case CF_CTRL_DATA_DETACH:
+ http2_data_done(cf, data, TRUE);
+ break;
+ case CF_CTRL_DATA_DONE:
http2_data_done(cf, data, arg1 != 0);
break;
- }
default:
break;
}
@@ -2606,7 +2582,7 @@ struct Curl_cftype Curl_cft_nghttp2 = {
cf_h2_connect,
cf_h2_close,
Curl_cf_def_get_host,
- cf_h2_get_select_socks,
+ cf_h2_adjust_pollset,
cf_h2_data_pending,
cf_h2_send,
cf_h2_recv,
@@ -2626,7 +2602,7 @@ static CURLcode http2_cfilter_add(struct Curl_cfilter **pcf,
CURLcode result = CURLE_OUT_OF_MEMORY;
DEBUGASSERT(data->conn);
- ctx = calloc(sizeof(*ctx), 1);
+ ctx = calloc(1, sizeof(*ctx));
if(!ctx)
goto out;
@@ -2652,7 +2628,7 @@ static CURLcode http2_cfilter_insert_after(struct Curl_cfilter *cf,
CURLcode result = CURLE_OUT_OF_MEMORY;
(void)data;
- ctx = calloc(sizeof(*ctx), 1);
+ ctx = calloc(1, sizeof(*ctx));
if(!ctx)
goto out;
diff --git a/libs/libcurl/src/http_aws_sigv4.c b/libs/libcurl/src/http_aws_sigv4.c
index 8bbc022511..0313026562 100644
--- a/libs/libcurl/src/http_aws_sigv4.c
+++ b/libs/libcurl/src/http_aws_sigv4.c
@@ -456,6 +456,7 @@ static CURLcode canon_query(struct Curl_easy *data,
for(i = 0; !result && (i < entry); i++, ap++) {
size_t len;
const char *q = ap->p;
+ bool found_equals = false;
if(!ap->len)
continue;
for(len = ap->len; len && !result; q++, len--) {
@@ -467,9 +468,13 @@ static CURLcode canon_query(struct Curl_easy *data,
case '.':
case '_':
case '~':
+ /* allowed as-is */
+ result = Curl_dyn_addn(dq, q, 1);
+ break;
case '=':
/* allowed as-is */
result = Curl_dyn_addn(dq, q, 1);
+ found_equals = true;
break;
case '%':
/* uppercase the following if hexadecimal */
@@ -497,7 +502,11 @@ static CURLcode canon_query(struct Curl_easy *data,
}
}
}
- if(i < entry - 1) {
+ if(!result && !found_equals) {
+ /* queries without value still need an equals */
+ result = Curl_dyn_addn(dq, "=", 1);
+ }
+ if(!result && i < entry - 1) {
/* insert ampersands between query pairs */
result = Curl_dyn_addn(dq, "&", 1);
}
diff --git a/libs/libcurl/src/http_chunks.c b/libs/libcurl/src/http_chunks.c
index 5541dd5b1b..0d6d6302a4 100644
--- a/libs/libcurl/src/http_chunks.c
+++ b/libs/libcurl/src/http_chunks.c
@@ -75,8 +75,6 @@
*/
-#define isxdigit_ascii(x) Curl_isxdigit(x)
-
void Curl_httpchunk_init(struct Curl_easy *data)
{
struct connectdata *conn = data->conn;
@@ -98,9 +96,9 @@ void Curl_httpchunk_init(struct Curl_easy *data)
* For example, 0x0d and 0x0a are used instead of '\r' and '\n'.
*/
CHUNKcode Curl_httpchunk_read(struct Curl_easy *data,
- char *datap,
- ssize_t datalen,
- ssize_t *wrote,
+ char *buf,
+ size_t blen,
+ size_t *pconsumed,
CURLcode *extrap)
{
CURLcode result = CURLE_OK;
@@ -108,28 +106,27 @@ CHUNKcode Curl_httpchunk_read(struct Curl_easy *data,
struct Curl_chunker *ch = &conn->chunk;
struct SingleRequest *k = &data->req;
size_t piece;
- curl_off_t length = (curl_off_t)datalen;
- *wrote = 0; /* nothing's written yet */
+ *pconsumed = 0; /* nothing's written yet */
/* 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(data, CLIENTWRITE_BODY, datap, datalen);
+ result = Curl_client_write(data, CLIENTWRITE_BODY, buf, blen);
if(result) {
*extrap = result;
return CHUNKE_PASSTHRU_ERROR;
}
}
- while(length) {
+ while(blen) {
switch(ch->state) {
case CHUNK_HEX:
- if(ISXDIGIT(*datap)) {
+ if(ISXDIGIT(*buf)) {
if(ch->hexindex < CHUNK_MAXNUM_LEN) {
- ch->hexbuffer[ch->hexindex] = *datap;
- datap++;
- length--;
+ ch->hexbuffer[ch->hexindex] = *buf;
+ buf++;
+ blen--;
ch->hexindex++;
}
else {
@@ -143,7 +140,7 @@ CHUNKcode Curl_httpchunk_read(struct Curl_easy *data,
a hexadecimal digit. */
return CHUNKE_ILLEGAL_HEX;
- /* length and datap are unmodified */
+ /* blen and buf are unmodified */
ch->hexbuffer[ch->hexindex] = 0;
if(curlx_strtoofft(ch->hexbuffer, &endptr, 16, &ch->datasize))
@@ -154,7 +151,7 @@ CHUNKcode Curl_httpchunk_read(struct Curl_easy *data,
case CHUNK_LF:
/* waiting for the LF after a chunk size */
- if(*datap == 0x0a) {
+ if(*buf == 0x0a) {
/* we're now expecting data to come, unless size was zero! */
if(0 == ch->datasize) {
ch->state = CHUNK_TRAILER; /* now check for trailers */
@@ -163,19 +160,21 @@ CHUNKcode Curl_httpchunk_read(struct Curl_easy *data,
ch->state = CHUNK_DATA;
}
- datap++;
- length--;
+ buf++;
+ blen--;
break;
case CHUNK_DATA:
- /* We expect 'datasize' of data. We have 'length' right now, it can be
+ /* We expect 'datasize' of data. We have 'blen' right now, it can be
more or less than 'datasize'. Get the smallest piece.
*/
- piece = curlx_sotouz((ch->datasize >= length)?length:ch->datasize);
+ piece = blen;
+ if(ch->datasize < (curl_off_t)blen)
+ piece = curlx_sotouz(ch->datasize);
/* Write the data portion available */
if(!data->set.http_te_skip && !k->ignorebody) {
- result = Curl_client_write(data, CLIENTWRITE_BODY, datap, piece);
+ result = Curl_client_write(data, CLIENTWRITE_BODY, buf, piece);
if(result) {
*extrap = result;
@@ -183,10 +182,10 @@ CHUNKcode Curl_httpchunk_read(struct Curl_easy *data,
}
}
- *wrote += piece;
+ *pconsumed += piece;
ch->datasize -= piece; /* decrease amount left to expect */
- datap += piece; /* move read pointer forward */
- length -= piece; /* decrease space left in this round */
+ buf += piece; /* move read pointer forward */
+ blen -= piece; /* decrease space left in this round */
if(0 == ch->datasize)
/* end of data this round, we now expect a trailing CRLF */
@@ -194,18 +193,18 @@ CHUNKcode Curl_httpchunk_read(struct Curl_easy *data,
break;
case CHUNK_POSTLF:
- if(*datap == 0x0a) {
+ if(*buf == 0x0a) {
/* The last one before we go back to hex state and start all over. */
Curl_httpchunk_init(data); /* sets state back to CHUNK_HEX */
}
- else if(*datap != 0x0d)
+ else if(*buf != 0x0d)
return CHUNKE_BAD_CHUNK;
- datap++;
- length--;
+ buf++;
+ blen--;
break;
case CHUNK_TRAILER:
- if((*datap == 0x0d) || (*datap == 0x0a)) {
+ if((*buf == 0x0d) || (*buf == 0x0a)) {
char *tr = Curl_dyn_ptr(&conn->trailer);
/* this is the end of a trailer, but if the trailer was zero bytes
there was no trailer and we move on */
@@ -229,7 +228,7 @@ CHUNKcode Curl_httpchunk_read(struct Curl_easy *data,
}
Curl_dyn_reset(&conn->trailer);
ch->state = CHUNK_TRAILER_CR;
- if(*datap == 0x0a)
+ if(*buf == 0x0a)
/* already on the LF */
break;
}
@@ -240,19 +239,19 @@ CHUNKcode Curl_httpchunk_read(struct Curl_easy *data,
}
}
else {
- result = Curl_dyn_addn(&conn->trailer, datap, 1);
+ result = Curl_dyn_addn(&conn->trailer, buf, 1);
if(result)
return CHUNKE_OUT_OF_MEMORY;
}
- datap++;
- length--;
+ buf++;
+ blen--;
break;
case CHUNK_TRAILER_CR:
- if(*datap == 0x0a) {
+ if(*buf == 0x0a) {
ch->state = CHUNK_TRAILER_POSTCR;
- datap++;
- length--;
+ buf++;
+ blen--;
}
else
return CHUNKE_BAD_CHUNK;
@@ -261,27 +260,27 @@ CHUNKcode Curl_httpchunk_read(struct Curl_easy *data,
case CHUNK_TRAILER_POSTCR:
/* We enter this state when a CR should arrive so we expect to
have to first pass a CR before we wait for LF */
- if((*datap != 0x0d) && (*datap != 0x0a)) {
+ if((*buf != 0x0d) && (*buf != 0x0a)) {
/* not a CR then it must be another header in the trailer */
ch->state = CHUNK_TRAILER;
break;
}
- if(*datap == 0x0d) {
+ if(*buf == 0x0d) {
/* skip if CR */
- datap++;
- length--;
+ buf++;
+ blen--;
}
/* now wait for the final LF */
ch->state = CHUNK_STOP;
break;
case CHUNK_STOP:
- if(*datap == 0x0a) {
- length--;
+ if(*buf == 0x0a) {
+ blen--;
/* Record the length of any data left in the end of the buffer
even if there's no more chunks to read */
- ch->datasize = curlx_sotouz(length);
+ ch->datasize = blen;
return CHUNKE_STOP; /* return stop */
}
diff --git a/libs/libcurl/src/http_chunks.h b/libs/libcurl/src/http_chunks.h
index 5a84b92695..3c228f84eb 100644
--- a/libs/libcurl/src/http_chunks.h
+++ b/libs/libcurl/src/http_chunks.h
@@ -93,8 +93,8 @@ struct Curl_chunker {
/* The following functions are defined in http_chunks.c */
void Curl_httpchunk_init(struct Curl_easy *data);
-CHUNKcode Curl_httpchunk_read(struct Curl_easy *data, char *datap,
- ssize_t length, ssize_t *wrote,
+CHUNKcode Curl_httpchunk_read(struct Curl_easy *data, char *buf,
+ size_t blen, size_t *pconsumed,
CURLcode *passthru);
#endif /* HEADER_CURL_HTTP_CHUNKS_H */
diff --git a/libs/libcurl/src/http_proxy.c b/libs/libcurl/src/http_proxy.c
index 4c247cc96e..56bf385e70 100644
--- a/libs/libcurl/src/http_proxy.c
+++ b/libs/libcurl/src/http_proxy.c
@@ -299,7 +299,7 @@ struct Curl_cftype Curl_cft_http_proxy = {
http_proxy_cf_connect,
http_proxy_cf_close,
Curl_cf_http_proxy_get_host,
- Curl_cf_def_get_select_socks,
+ Curl_cf_def_adjust_pollset,
Curl_cf_def_data_pending,
Curl_cf_def_send,
Curl_cf_def_recv,
diff --git a/libs/libcurl/src/idn.c b/libs/libcurl/src/idn.c
index b409039ade..493cc59c1c 100644
--- a/libs/libcurl/src/idn.c
+++ b/libs/libcurl/src/idn.c
@@ -36,7 +36,7 @@
#ifdef USE_LIBIDN2
#include <idn2.h>
-#if defined(WIN32) && defined(UNICODE)
+#if defined(_WIN32) && defined(UNICODE)
#define IDN2_LOOKUP(name, host, flags) \
idn2_lookup_u8((const uint8_t *)name, (uint8_t **)host, flags)
#else
diff --git a/libs/libcurl/src/imap.c b/libs/libcurl/src/imap.c
index e444457442..d4abe3568c 100644
--- a/libs/libcurl/src/imap.c
+++ b/libs/libcurl/src/imap.c
@@ -1194,8 +1194,6 @@ static CURLcode imap_state_fetch_resp(struct Curl_easy *data,
if(result)
return result;
- data->req.bytecount += chunk;
-
infof(data, "Written %zu bytes, %" CURL_FORMAT_CURL_OFF_TU
" bytes are left for transfer", chunk, size - chunk);
@@ -1430,7 +1428,7 @@ static CURLcode imap_init(struct Curl_easy *data)
CURLcode result = CURLE_OK;
struct IMAP *imap;
- imap = data->req.p.imap = calloc(sizeof(struct IMAP), 1);
+ imap = data->req.p.imap = calloc(1, sizeof(struct IMAP));
if(!imap)
result = CURLE_OUT_OF_MEMORY;
diff --git a/libs/libcurl/src/ldap.c b/libs/libcurl/src/ldap.c
index a67a487a89..16e851dcec 100644
--- a/libs/libcurl/src/ldap.c
+++ b/libs/libcurl/src/ldap.c
@@ -313,7 +313,6 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done)
int ldap_ssl = 0;
char *val_b64 = NULL;
size_t val_b64_sz = 0;
- curl_off_t dlsize = 0;
#ifdef LDAP_OPT_NETWORK_TIMEOUT
struct timeval ldap_timeout = {10, 0}; /* 10 sec connection/search timeout */
#endif
@@ -327,7 +326,7 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done)
*done = TRUE; /* unconditionally */
infof(data, "LDAP local: LDAP Vendor = %s ; LDAP Version = %d",
- LDAP_VENDOR_NAME, LDAP_VENDOR_VERSION);
+ LDAP_VENDOR_NAME, LDAP_VENDOR_VERSION);
infof(data, "LDAP local: %s", data->state.url);
#ifdef HAVE_LDAP_URL_PARSE
@@ -345,7 +344,7 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done)
if(conn->given->flags & PROTOPT_SSL)
ldap_ssl = 1;
infof(data, "LDAP local: trying to establish %s connection",
- ldap_ssl ? "encrypted" : "cleartext");
+ ldap_ssl ? "encrypted" : "cleartext");
#if defined(USE_WIN32_LDAP)
host = curlx_convert_UTF8_to_tchar(conn->host.name);
@@ -535,6 +534,7 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done)
goto quit;
}
+ Curl_pgrsSetDownloadCounter(data, 0);
rc = ldap_search_s(server, ludp->lud_dn, ludp->lud_scope,
ludp->lud_filter, ludp->lud_attrs, 0, &ldapmsg);
@@ -596,8 +596,6 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done)
goto quit;
}
- dlsize += name_len + 5;
-
FREE_ON_WINLDAP(name);
ldap_memfree(dn);
}
@@ -659,8 +657,6 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done)
goto quit;
}
- dlsize += attr_len + 3;
-
if((attr_len > 7) &&
(strcmp(";binary", attr + (attr_len - 7)) == 0)) {
/* Binary attribute, encode to base64. */
@@ -689,8 +685,6 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done)
goto quit;
}
-
- dlsize += val_b64_sz;
}
}
else {
@@ -705,8 +699,6 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done)
goto quit;
}
-
- dlsize += vals[i]->bv_len;
}
result = Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\n", 1);
@@ -719,8 +711,6 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done)
goto quit;
}
-
- dlsize++;
}
/* Free memory used to store values */
@@ -734,10 +724,6 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done)
result = Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\n", 1);
if(result)
goto quit;
- dlsize++;
- result = Curl_pgrsSetDownloadCounter(data, dlsize);
- if(result)
- goto quit;
}
if(ber)
diff --git a/libs/libcurl/src/libcurl.plist b/libs/libcurl/src/libcurl.plist
index 216f07a612..7c4364f8d8 100644
--- a/libs/libcurl/src/libcurl.plist
+++ b/libs/libcurl/src/libcurl.plist
@@ -15,7 +15,7 @@
<string>se.curl.libcurl</string>
<key>CFBundleVersion</key>
- <string>8.4.0</string>
+ <string>8.5.0</string>
<key>CFBundleName</key>
<string>libcurl</string>
@@ -27,9 +27,9 @@
<string>????</string>
<key>CFBundleShortVersionString</key>
- <string>libcurl 8.4.0</string>
+ <string>libcurl 8.5.0</string>
<key>CFBundleGetInfoString</key>
- <string>libcurl.plist 8.4.0</string>
+ <string>libcurl.plist 8.5.0</string>
</dict>
</plist>
diff --git a/libs/libcurl/src/md4.c b/libs/libcurl/src/md4.c
index c7ce9e6d80..7aae719266 100644
--- a/libs/libcurl/src/md4.c
+++ b/libs/libcurl/src/md4.c
@@ -32,9 +32,8 @@
#include "warnless.h"
#ifdef USE_OPENSSL
-#include <openssl/opensslconf.h>
-#if defined(OPENSSL_VERSION_MAJOR) && (OPENSSL_VERSION_MAJOR >= 3) && \
- !defined(USE_AMISSL)
+#include <openssl/opensslv.h>
+#if (OPENSSL_VERSION_NUMBER >= 0x30000000L) && !defined(USE_AMISSL)
/* OpenSSL 3.0.0 marks the MD4 functions as deprecated */
#define OPENSSL_NO_MD4
#endif
diff --git a/libs/libcurl/src/memdebug.c b/libs/libcurl/src/memdebug.c
index 88f0ee81b2..869d9ca54d 100644
--- a/libs/libcurl/src/memdebug.c
+++ b/libs/libcurl/src/memdebug.c
@@ -208,7 +208,7 @@ ALLOC_FUNC char *curl_dbg_strdup(const char *str,
return mem;
}
-#if defined(WIN32) && defined(UNICODE)
+#if defined(_WIN32) && defined(UNICODE)
ALLOC_FUNC wchar_t *curl_dbg_wcsdup(const wchar_t *str,
int line, const char *source)
{
diff --git a/libs/libcurl/src/memdebug.h b/libs/libcurl/src/memdebug.h
index 412744fba5..a3a701011e 100644
--- a/libs/libcurl/src/memdebug.h
+++ b/libs/libcurl/src/memdebug.h
@@ -64,7 +64,7 @@ CURL_EXTERN ALLOC_SIZE(2) void *curl_dbg_realloc(void *ptr,
CURL_EXTERN void curl_dbg_free(void *ptr, int line, const char *source);
CURL_EXTERN ALLOC_FUNC char *curl_dbg_strdup(const char *str, int line,
const char *src);
-#if defined(WIN32) && defined(UNICODE)
+#if defined(_WIN32) && defined(UNICODE)
CURL_EXTERN ALLOC_FUNC wchar_t *curl_dbg_wcsdup(const wchar_t *str,
int line,
const char *source);
@@ -121,7 +121,7 @@ CURL_EXTERN int curl_dbg_fclose(FILE *file, int line, const char *source);
#define send(a,b,c,d) curl_dbg_send(a,b,c,d, __LINE__, __FILE__)
#define recv(a,b,c,d) curl_dbg_recv(a,b,c,d, __LINE__, __FILE__)
-#ifdef WIN32
+#ifdef _WIN32
# ifdef UNICODE
# undef wcsdup
# define wcsdup(ptr) curl_dbg_wcsdup(ptr, __LINE__, __FILE__)
diff --git a/libs/libcurl/src/mime.c b/libs/libcurl/src/mime.c
index 19ac72c49f..007a187bf5 100644
--- a/libs/libcurl/src/mime.c
+++ b/libs/libcurl/src/mime.c
@@ -48,7 +48,7 @@
#include "curl_memory.h"
#include "memdebug.h"
-#ifdef WIN32
+#ifdef _WIN32
# ifndef R_OK
# define R_OK 4
# endif
@@ -311,8 +311,7 @@ static char *escape_string(struct Curl_easy *data,
table = formtable;
/* data can be NULL when this function is called indirectly from
curl_formget(). */
- if(strategy == MIMESTRATEGY_MAIL ||
- (data && (data->set.mime_options & CURLMIMEOPT_FORMESCAPE)))
+ if(strategy == MIMESTRATEGY_MAIL || (data && (data->set.mime_formescape)))
table = mimetable;
Curl_dyn_init(&db, CURL_MAX_INPUT_LENGTH);
diff --git a/libs/libcurl/src/mprintf.c b/libs/libcurl/src/mprintf.c
index c4eeb8c836..cb91b6429a 100644
--- a/libs/libcurl/src/mprintf.c
+++ b/libs/libcurl/src/mprintf.c
@@ -66,9 +66,7 @@
* Non-ANSI integer extensions
*/
-#if (defined(__BORLANDC__) && (__BORLANDC__ >= 0x520)) || \
- (defined(__POCC__) && defined(_MSC_VER)) || \
- (defined(_WIN32_WCE)) || \
+#if (defined(_WIN32_WCE)) || \
(defined(__MINGW32__)) || \
(defined(_MSC_VER) && (_MSC_VER >= 900) && (_INTEGRAL_MAX_BITS >= 64))
# define MP_HAVE_INT_EXTENSIONS
@@ -1071,9 +1069,6 @@ static int alloc_addbyter(int output, FILE *data)
return outc; /* fputc() returns like this on success */
}
-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)
{
diff --git a/libs/libcurl/src/mqtt.c b/libs/libcurl/src/mqtt.c
index 712b736250..530d929e5e 100644
--- a/libs/libcurl/src/mqtt.c
+++ b/libs/libcurl/src/mqtt.c
@@ -616,9 +616,6 @@ static void mqstate(struct Curl_easy *data,
}
-/* for the publish packet */
-#define MQTT_HEADER_LEN 5 /* max 5 bytes */
-
static CURLcode mqtt_read_publish(struct Curl_easy *data, bool *done)
{
CURLcode result = CURLE_OK;
@@ -677,7 +674,6 @@ MQTT_SUBACK_COMING:
/* FALLTHROUGH */
case MQTT_PUB_REMAIN: {
/* read rest of packet, but no more. Cap to buffer size */
- struct SingleRequest *k = &data->req;
size_t rest = mq->npacket;
if(rest > (size_t)data->set.buffer_size)
rest = (size_t)data->set.buffer_size;
@@ -693,13 +689,8 @@ MQTT_SUBACK_COMING:
result = CURLE_PARTIAL_FILE;
goto end;
}
- Curl_debug(data, CURLINFO_DATA_IN, (char *)pkt, (size_t)nread);
mq->npacket -= nread;
- k->bytecount += nread;
- result = Curl_pgrsSetDownloadCounter(data, k->bytecount);
- if(result)
- goto end;
/* if QoS is set, message contains packet id */
diff --git a/libs/libcurl/src/multi.c b/libs/libcurl/src/multi.c
index c655e3ae48..8e6f2c739d 100644
--- a/libs/libcurl/src/multi.c
+++ b/libs/libcurl/src/multi.c
@@ -55,22 +55,6 @@
#include "curl_memory.h"
#include "memdebug.h"
-#ifdef __APPLE__
-
-#define wakeup_write write
-#define wakeup_read read
-#define wakeup_close close
-#define wakeup_create pipe
-
-#else /* __APPLE__ */
-
-#define wakeup_write swrite
-#define wakeup_read sread
-#define wakeup_close sclose
-#define wakeup_create(p) Curl_socketpair(AF_UNIX, SOCK_STREAM, 0, p)
-
-#endif /* __APPLE__ */
-
/*
CURL_SOCKET_HASH_TABLE_SIZE should be a prime number. Increasing it from 97
to 911 takes on a 32-bit machine 4 x 804 = 3211 more bytes. Still, every
@@ -231,10 +215,6 @@ struct Curl_sh_entry {
unsigned int readers; /* this many transfers want to read */
unsigned int writers; /* this many transfers want to write */
};
-/* bits for 'action' having no bits means this socket is not expecting any
- action */
-#define SH_READ 1
-#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,
@@ -416,9 +396,6 @@ struct Curl_multi *Curl_multi_handle(int hashsize, /* socket hash */
Curl_llist_init(&multi->msgsent, NULL);
multi->multiplexing = TRUE;
-
- /* -1 means it not set by user, use the default value */
- multi->maxconnects = -1;
multi->max_concurrent_streams = 100;
#ifdef USE_WINSOCK
@@ -1040,49 +1017,61 @@ static int protocol_getsock(struct Curl_easy *data,
{
if(conn->handler->proto_getsock)
return conn->handler->proto_getsock(data, conn, socks);
- return Curl_conn_get_select_socks(data, FIRSTSOCKET, socks);
+ return GETSOCK_BLANK;
}
-/* returns bitmapped flags for this handle and its sockets. The 'socks[]'
- array contains MAX_SOCKSPEREASYHANDLE entries. */
-static int multi_getsock(struct Curl_easy *data,
- curl_socket_t *socks)
+/* Initializes `poll_set` with the current socket poll actions needed
+ * for transfer `data`. */
+static void multi_getsock(struct Curl_easy *data,
+ struct easy_pollset *ps)
{
- struct connectdata *conn = data->conn;
/* The no connection case can happen when this is called from
curl_multi_remove_handle() => singlesocket() => multi_getsock().
*/
- if(!conn)
- return 0;
+ Curl_pollset_reset(data, ps);
+ if(!data->conn)
+ return;
switch(data->mstate) {
default:
- return 0;
+ break;
case MSTATE_RESOLVING:
- return Curl_resolv_getsock(data, socks);
+ Curl_pollset_add_socks2(data, ps, Curl_resolv_getsock);
+ /* connection filters are not involved in this phase */
+ return;
case MSTATE_PROTOCONNECTING:
case MSTATE_PROTOCONNECT:
- return protocol_getsock(data, conn, socks);
+ Curl_pollset_add_socks(data, ps, protocol_getsock);
+ break;
case MSTATE_DO:
case MSTATE_DOING:
- return doing_getsock(data, conn, socks);
+ Curl_pollset_add_socks(data, ps, doing_getsock);
+ break;
case MSTATE_TUNNELING:
case MSTATE_CONNECTING:
- return Curl_conn_get_select_socks(data, FIRSTSOCKET, socks);
+ break;
case MSTATE_DOING_MORE:
- return domore_getsock(data, conn, socks);
+ Curl_pollset_add_socks(data, ps, domore_getsock);
+ break;
case MSTATE_DID: /* since is set after DO is completed, we switch to
waiting for the same as the PERFORMING state */
case MSTATE_PERFORMING:
- return Curl_single_getsock(data, conn, socks);
+ Curl_pollset_add_socks(data, ps, Curl_single_getsock);
+ break;
+
+ case MSTATE_RATELIMITING:
+ /* nothing to wait for */
+ return;
}
+ /* Let connection filters add/remove as needed */
+ Curl_conn_adjust_pollset(data, ps);
}
CURLMcode curl_multi_fdset(struct Curl_multi *multi,
@@ -1094,8 +1083,8 @@ CURLMcode curl_multi_fdset(struct Curl_multi *multi,
and then we must make sure that is done. */
struct Curl_easy *data;
int this_max_fd = -1;
- curl_socket_t sockbunch[MAX_SOCKSPEREASYHANDLE];
- int i;
+ struct easy_pollset ps;
+ unsigned int i;
(void)exc_fd_set; /* not used */
if(!GOOD_MULTI_HANDLE(multi))
@@ -1104,29 +1093,20 @@ CURLMcode curl_multi_fdset(struct Curl_multi *multi,
if(multi->in_callback)
return CURLM_RECURSIVE_API_CALL;
+ memset(&ps, 0, sizeof(ps));
for(data = multi->easyp; data; data = data->next) {
- int bitmap;
-#ifdef __clang_analyzer_
- /* to prevent "The left operand of '>=' is a garbage value" warnings */
- memset(sockbunch, 0, sizeof(sockbunch));
-#endif
- bitmap = multi_getsock(data, sockbunch);
-
- for(i = 0; i< MAX_SOCKSPEREASYHANDLE; i++) {
- if((bitmap & GETSOCK_MASK_RW(i)) && VALID_SOCK((sockbunch[i]))) {
- if(!FDSET_SOCK(sockbunch[i]))
- /* pretend it doesn't exist */
- continue;
- if(bitmap & GETSOCK_READSOCK(i))
- FD_SET(sockbunch[i], read_fd_set);
- if(bitmap & GETSOCK_WRITESOCK(i))
- FD_SET(sockbunch[i], write_fd_set);
- if((int)sockbunch[i] > this_max_fd)
- this_max_fd = (int)sockbunch[i];
- }
- else {
- break;
- }
+ multi_getsock(data, &ps);
+
+ for(i = 0; i < ps.num; i++) {
+ if(!FDSET_SOCK(ps.sockets[i]))
+ /* pretend it doesn't exist */
+ continue;
+ if(ps.actions[i] & CURL_POLL_IN)
+ FD_SET(ps.sockets[i], read_fd_set);
+ if(ps.actions[i] & CURL_POLL_OUT)
+ FD_SET(ps.sockets[i], write_fd_set);
+ if((int)ps.sockets[i] > this_max_fd)
+ this_max_fd = (int)ps.sockets[i];
}
}
@@ -1162,9 +1142,8 @@ static CURLMcode multi_wait(struct Curl_multi *multi,
bool use_wakeup)
{
struct Curl_easy *data;
- curl_socket_t sockbunch[MAX_SOCKSPEREASYHANDLE];
- int bitmap;
- unsigned int i;
+ struct easy_pollset ps;
+ size_t i;
unsigned int nfds = 0;
unsigned int curlfds;
long timeout_internal;
@@ -1190,17 +1169,10 @@ static CURLMcode multi_wait(struct Curl_multi *multi,
return CURLM_BAD_FUNCTION_ARGUMENT;
/* Count up how many fds we have from the multi handle */
+ memset(&ps, 0, sizeof(ps));
for(data = multi->easyp; data; data = data->next) {
- bitmap = multi_getsock(data, sockbunch);
-
- for(i = 0; i < MAX_SOCKSPEREASYHANDLE; i++) {
- if((bitmap & GETSOCK_MASK_RW(i)) && VALID_SOCK((sockbunch[i]))) {
- ++nfds;
- }
- else {
- break;
- }
- }
+ multi_getsock(data, &ps);
+ nfds += ps.num;
}
/* If the internally desired timeout is actually shorter than requested from
@@ -1241,40 +1213,35 @@ static CURLMcode multi_wait(struct Curl_multi *multi,
if(curlfds) {
/* Add the curl handles to our pollfds first */
for(data = multi->easyp; data; data = data->next) {
- bitmap = multi_getsock(data, sockbunch);
+ multi_getsock(data, &ps);
- for(i = 0; i < MAX_SOCKSPEREASYHANDLE; i++) {
- if((bitmap & GETSOCK_MASK_RW(i)) && VALID_SOCK((sockbunch[i]))) {
- struct pollfd *ufd = &ufds[nfds++];
-#ifdef USE_WINSOCK
- long mask = 0;
-#endif
- ufd->fd = sockbunch[i];
- ufd->events = 0;
- if(bitmap & GETSOCK_READSOCK(i)) {
+ for(i = 0; i < ps.num; i++) {
+ struct pollfd *ufd = &ufds[nfds++];
#ifdef USE_WINSOCK
- mask |= FD_READ|FD_ACCEPT|FD_CLOSE;
+ long mask = 0;
#endif
- ufd->events |= POLLIN;
- }
- if(bitmap & GETSOCK_WRITESOCK(i)) {
+ ufd->fd = ps.sockets[i];
+ ufd->events = 0;
+ if(ps.actions[i] & CURL_POLL_IN) {
#ifdef USE_WINSOCK
- mask |= FD_WRITE|FD_CONNECT|FD_CLOSE;
- reset_socket_fdwrite(sockbunch[i]);
+ mask |= FD_READ|FD_ACCEPT|FD_CLOSE;
#endif
- ufd->events |= POLLOUT;
- }
+ ufd->events |= POLLIN;
+ }
+ if(ps.actions[i] & CURL_POLL_OUT) {
#ifdef USE_WINSOCK
- if(WSAEventSelect(sockbunch[i], multi->wsa_event, mask) != 0) {
- if(ufds_malloc)
- free(ufds);
- return CURLM_INTERNAL_ERROR;
- }
+ mask |= FD_WRITE|FD_CONNECT|FD_CLOSE;
+ reset_socket_fdwrite(ps.sockets[i]);
#endif
+ ufd->events |= POLLOUT;
}
- else {
- break;
+#ifdef USE_WINSOCK
+ if(WSAEventSelect(ps.sockets[i], multi->wsa_event, mask) != 0) {
+ if(ufds_malloc)
+ free(ufds);
+ return CURLM_INTERNAL_ERROR;
}
+#endif
}
}
}
@@ -1386,21 +1353,16 @@ static CURLMcode multi_wait(struct Curl_multi *multi,
if(curlfds) {
for(data = multi->easyp; data; data = data->next) {
- bitmap = multi_getsock(data, sockbunch);
-
- for(i = 0; i < MAX_SOCKSPEREASYHANDLE; i++) {
- if(bitmap & (GETSOCK_READSOCK(i) | GETSOCK_WRITESOCK(i))) {
- wsa_events.lNetworkEvents = 0;
- if(WSAEnumNetworkEvents(sockbunch[i], NULL, &wsa_events) == 0) {
- if(ret && !pollrc && wsa_events.lNetworkEvents)
- retcode++;
- }
- WSAEventSelect(sockbunch[i], multi->wsa_event, 0);
- }
- else {
- /* break on entry not checked for being readable or writable */
- break;
+ multi_getsock(data, &ps);
+
+ for(i = 0; i < ps.num; i++) {
+ wsa_events.lNetworkEvents = 0;
+ if(WSAEnumNetworkEvents(ps.sockets[i], NULL,
+ &wsa_events) == 0) {
+ if(ret && !pollrc && wsa_events.lNetworkEvents)
+ retcode++;
}
+ WSAEventSelect(ps.sockets[i], multi->wsa_event, 0);
}
}
}
@@ -2021,8 +1983,8 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
if(dns) {
#ifdef CURLRES_ASYNCH
- data->state.async.dns = dns;
- data->state.async.done = TRUE;
+ conn->resolve_async.dns = dns;
+ conn->resolve_async.done = TRUE;
#endif
result = CURLE_OK;
infof(data, "Hostname '%s' was found in DNS cache", hostname);
@@ -2895,53 +2857,36 @@ CURLMsg *curl_multi_info_read(struct Curl_multi *multi, int *msgs_in_queue)
static CURLMcode singlesocket(struct Curl_multi *multi,
struct Curl_easy *data)
{
- curl_socket_t socks[MAX_SOCKSPEREASYHANDLE];
- int i;
+ struct easy_pollset cur_poll;
+ unsigned int i;
struct Curl_sh_entry *entry;
curl_socket_t s;
- int num;
- unsigned int curraction;
- unsigned char actions[MAX_SOCKSPEREASYHANDLE];
int rc;
- for(i = 0; i< MAX_SOCKSPEREASYHANDLE; i++)
- socks[i] = CURL_SOCKET_BAD;
-
/* Fill in the 'current' struct with the state as it is now: what sockets to
supervise and for what actions */
- curraction = multi_getsock(data, socks);
+ multi_getsock(data, &cur_poll);
/* We have 0 .. N sockets already and we get to know about the 0 .. M
sockets we should have from now on. Detect the differences, remove no
longer supervised ones and add new ones */
/* walk over the sockets we got right now */
- for(i = 0; (i< MAX_SOCKSPEREASYHANDLE) &&
- (curraction & GETSOCK_MASK_RW(i));
- i++) {
- unsigned char action = CURL_POLL_NONE;
- unsigned char prevaction = 0;
+ for(i = 0; i < cur_poll.num; i++) {
+ unsigned char cur_action = cur_poll.actions[i];
+ unsigned char last_action = 0;
int comboaction;
- bool sincebefore = FALSE;
- s = socks[i];
+ s = cur_poll.sockets[i];
/* get it from the hash */
entry = sh_getentry(&multi->sockhash, s);
-
- if(curraction & GETSOCK_READSOCK(i))
- action |= CURL_POLL_IN;
- if(curraction & GETSOCK_WRITESOCK(i))
- action |= CURL_POLL_OUT;
-
- actions[i] = action;
if(entry) {
/* check if new for this transfer */
- int j;
- for(j = 0; j< data->numsocks; j++) {
- if(s == data->sockets[j]) {
- prevaction = data->actions[j];
- sincebefore = TRUE;
+ unsigned int j;
+ for(j = 0; j< data->last_poll.num; j++) {
+ if(s == data->last_poll.sockets[j]) {
+ last_action = data->last_poll.actions[j];
break;
}
}
@@ -2953,23 +2898,23 @@ static CURLMcode singlesocket(struct Curl_multi *multi,
/* fatal */
return CURLM_OUT_OF_MEMORY;
}
- if(sincebefore && (prevaction != action)) {
+ if(last_action && (last_action != cur_action)) {
/* Socket was used already, but different action now */
- if(prevaction & CURL_POLL_IN)
+ if(last_action & CURL_POLL_IN)
entry->readers--;
- if(prevaction & CURL_POLL_OUT)
+ if(last_action & CURL_POLL_OUT)
entry->writers--;
- if(action & CURL_POLL_IN)
+ if(cur_action & CURL_POLL_IN)
entry->readers++;
- if(action & CURL_POLL_OUT)
+ if(cur_action & CURL_POLL_OUT)
entry->writers++;
}
- else if(!sincebefore) {
- /* a new user */
+ else if(!last_action) {
+ /* a new transfer using this socket */
entry->users++;
- if(action & CURL_POLL_IN)
+ if(cur_action & CURL_POLL_IN)
entry->readers++;
- if(action & CURL_POLL_OUT)
+ if(cur_action & CURL_POLL_OUT)
entry->writers++;
/* add 'data' to the transfer hash on this socket! */
@@ -2980,11 +2925,11 @@ static CURLMcode singlesocket(struct Curl_multi *multi,
}
}
- comboaction = (entry->writers? CURL_POLL_OUT : 0) |
+ comboaction = (entry->writers ? CURL_POLL_OUT : 0) |
(entry->readers ? CURL_POLL_IN : 0);
/* socket existed before and has the same action set as before */
- if(sincebefore && ((int)entry->action == comboaction))
+ if(last_action && ((int)entry->action == comboaction))
/* same, continue */
continue;
@@ -2992,6 +2937,7 @@ static CURLMcode singlesocket(struct Curl_multi *multi,
set_in_callback(multi, TRUE);
rc = multi->socket_cb(data, s, comboaction, multi->socket_userp,
entry->socketp);
+
set_in_callback(multi, FALSE);
if(rc == -1) {
multi->dead = TRUE;
@@ -3002,16 +2948,15 @@ static CURLMcode singlesocket(struct Curl_multi *multi,
entry->action = comboaction; /* store the current action state */
}
- num = i; /* number of sockets */
-
- /* when we've walked over all the sockets we should have right now, we must
- make sure to detect sockets that are removed */
- for(i = 0; i< data->numsocks; i++) {
- int j;
+ /* Check for last_poll.sockets that no longer appear in cur_poll.sockets.
+ * Need to remove the easy handle from the multi->sockhash->transfers and
+ * remove multi->sockhash entry when this was the last transfer */
+ for(i = 0; i< data->last_poll.num; i++) {
+ unsigned int j;
bool stillused = FALSE;
- s = data->sockets[i];
- for(j = 0; j < num; j++) {
- if(s == socks[j]) {
+ s = data->last_poll.sockets[i];
+ for(j = 0; j < cur_poll.num; j++) {
+ if(s == cur_poll.sockets[j]) {
/* this is still supervised */
stillused = TRUE;
break;
@@ -3024,7 +2969,7 @@ static CURLMcode singlesocket(struct Curl_multi *multi,
/* if this is NULL here, the socket has been closed and notified so
already by Curl_multi_closed() */
if(entry) {
- unsigned char oldactions = data->actions[i];
+ unsigned char oldactions = data->last_poll.actions[i];
/* this socket has been removed. Decrease user count */
entry->users--;
if(oldactions & CURL_POLL_OUT)
@@ -3052,11 +2997,10 @@ static CURLMcode singlesocket(struct Curl_multi *multi,
}
}
}
- } /* for loop over numsocks */
+ } /* for loop over num */
- memcpy(data->sockets, socks, num*sizeof(curl_socket_t));
- memcpy(data->actions, actions, num*sizeof(char));
- data->numsocks = num;
+ /* Remember for next time */
+ memcpy(&data->last_poll, &cur_poll, sizeof(data->last_poll));
return CURLM_OK;
}
@@ -3296,6 +3240,7 @@ CURLMcode curl_multi_setopt(struct Curl_multi *multi,
{
CURLMcode res = CURLM_OK;
va_list param;
+ unsigned long uarg;
if(!GOOD_MULTI_HANDLE(multi))
return CURLM_BAD_HANDLE;
@@ -3328,7 +3273,9 @@ CURLMcode curl_multi_setopt(struct Curl_multi *multi,
multi->timer_userp = va_arg(param, void *);
break;
case CURLMOPT_MAXCONNECTS:
- multi->maxconnects = va_arg(param, long);
+ uarg = va_arg(param, unsigned long);
+ if(uarg <= UINT_MAX)
+ multi->maxconnects = (unsigned int)uarg;
break;
case CURLMOPT_MAX_HOST_CONNECTIONS:
multi->max_host_connections = va_arg(param, long);
@@ -3350,9 +3297,9 @@ CURLMcode curl_multi_setopt(struct Curl_multi *multi,
case CURLMOPT_MAX_CONCURRENT_STREAMS:
{
long streams = va_arg(param, long);
- if(streams < 1)
+ if((streams < 1) || (streams > INT_MAX))
streams = 100;
- multi->max_concurrent_streams = curlx_sltoui(streams);
+ multi->max_concurrent_streams = (unsigned int)streams;
}
break;
default:
@@ -3782,11 +3729,11 @@ struct Curl_easy **curl_multi_get_handles(struct Curl_multi *multi)
struct Curl_easy **a = malloc(sizeof(struct Curl_easy *) *
(multi->num_easy + 1));
if(a) {
- int i = 0;
+ unsigned int i = 0;
struct Curl_easy *e = multi->easyp;
while(e) {
DEBUGASSERT(i < multi->num_easy);
- if(!e->internal)
+ if(!e->state.internal)
a[i++] = e;
e = e->next;
}
diff --git a/libs/libcurl/src/multihandle.h b/libs/libcurl/src/multihandle.h
index 771c04d226..ec57304a38 100644
--- a/libs/libcurl/src/multihandle.h
+++ b/libs/libcurl/src/multihandle.h
@@ -93,9 +93,9 @@ struct Curl_multi {
struct Curl_easy *easyp;
struct Curl_easy *easylp; /* last node */
- int num_easy; /* amount of entries in the linked list above. */
- int num_alive; /* amount of easy handles that are added but have not yet
- reached COMPLETE state */
+ unsigned int num_easy; /* amount of entries in the linked list above. */
+ unsigned int num_alive; /* amount of easy handles that are added but have
+ not yet reached COMPLETE state */
struct Curl_llist msglist; /* a list of messages from completed transfers */
@@ -136,9 +136,6 @@ struct Curl_multi {
/* Shared connection cache (bundles)*/
struct conncache conn_cache;
- long maxconnects; /* if >0, a fixed limit of the maximum number of entries
- we're allowed to grow the connection cache to */
-
long max_host_connections; /* if >0, a fixed limit of the maximum number
of connections per host */
@@ -150,8 +147,6 @@ struct Curl_multi {
void *timer_userp;
struct curltime timer_lastcall; /* the fixed time for the timeout for the
previous callback */
- unsigned int max_concurrent_streams;
-
#ifdef USE_WINSOCK
WSAEVENT wsa_event; /* winsock event used for waits */
#else
@@ -160,6 +155,10 @@ struct Curl_multi {
0 is used for read, 1 is used for write */
#endif
#endif
+ unsigned int max_concurrent_streams;
+ unsigned int maxconnects; /* if >0, a fixed limit of the maximum number of
+ entries we're allowed to grow the connection
+ cache to */
#define IPV6_UNKNOWN 0
#define IPV6_DEAD 1
#define IPV6_WORKS 2
diff --git a/libs/libcurl/src/netrc.c b/libs/libcurl/src/netrc.c
index 3163a60a1f..72680af665 100644
--- a/libs/libcurl/src/netrc.c
+++ b/libs/libcurl/src/netrc.c
@@ -327,7 +327,7 @@ int Curl_parsenetrc(const char *host, char **loginp, char **passwordp,
}
retcode = parsenetrc(host, loginp, passwordp, filealloc);
free(filealloc);
-#ifdef WIN32
+#ifdef _WIN32
if(retcode == NETRC_FILE_MISSING) {
/* fallback to the old-style "_netrc" file */
filealloc = curl_maprintf("%s%s_netrc", home, DIR_CHAR);
diff --git a/libs/libcurl/src/openldap.c b/libs/libcurl/src/openldap.c
index fb612660da..bd5a5f88c8 100644
--- a/libs/libcurl/src/openldap.c
+++ b/libs/libcurl/src/openldap.c
@@ -319,31 +319,12 @@ static CURLcode oldap_setup_connection(struct Curl_easy *data,
{
CURLcode result;
LDAPURLDesc *lud;
- struct ldapconninfo *li;
+ (void)conn;
/* Early URL syntax check. */
result = oldap_url_parse(data, &lud);
ldap_free_urldesc(lud);
- if(!result) {
- li = calloc(1, sizeof(struct ldapconninfo));
- if(!li)
- result = CURLE_OUT_OF_MEMORY;
- else {
- li->proto = ldap_pvt_url_scheme2proto(data->state.up.scheme);
- conn->proto.ldapc = li;
- connkeep(conn, "OpenLDAP default");
-
- /* Initialize the SASL storage */
- Curl_sasl_init(&li->sasl, data, &saslldap);
-
- /* Clear the TLS upgraded flag */
- conn->bits.tls_upgraded = FALSE;
-
- result = oldap_parse_login_options(conn);
- }
- }
-
return result;
}
@@ -537,7 +518,7 @@ static CURLcode oldap_perform_starttls(struct Curl_easy *data)
static CURLcode oldap_connect(struct Curl_easy *data, bool *done)
{
struct connectdata *conn = data->conn;
- struct ldapconninfo *li = conn->proto.ldapc;
+ struct ldapconninfo *li;
static const int version = LDAP_VERSION3;
int rc;
char *hosturl;
@@ -547,6 +528,26 @@ static CURLcode oldap_connect(struct Curl_easy *data, bool *done)
(void)done;
+ DEBUGASSERT(!conn->proto.ldapc);
+ li = calloc(1, sizeof(struct ldapconninfo));
+ if(!li)
+ return CURLE_OUT_OF_MEMORY;
+ else {
+ CURLcode result;
+ li->proto = ldap_pvt_url_scheme2proto(data->state.up.scheme);
+ conn->proto.ldapc = li;
+
+ /* Initialize the SASL storage */
+ Curl_sasl_init(&li->sasl, data, &saslldap);
+
+ /* Clear the TLS upgraded flag */
+ conn->bits.tls_upgraded = FALSE;
+
+ result = oldap_parse_login_options(conn);
+ if(result)
+ return result;
+ }
+
hosturl = aprintf("ldap%s://%s:%d",
conn->handler->flags & PROTOPT_SSL? "s": "",
conn->host.name, conn->remote_port);
@@ -886,6 +887,11 @@ static CURLcode oldap_do(struct Curl_easy *data, bool *done)
result = oldap_url_parse(data, &lud);
if(!result) {
+ Sockbuf *sb;
+ /* re-install the libcurl SSL handlers into the sockbuf. */
+ ldap_get_option(li->ld, LDAP_OPT_SOCKBUF, &sb);
+ ber_sockbuf_add_io(sb, &ldapsb_tls, LBER_SBIOD_LEVEL_TRANSPORT, data);
+
rc = ldap_search_ext(li->ld, lud->lud_dn, lud->lud_scope,
lud->lud_filter, lud->lud_attrs, 0,
NULL, NULL, NULL, 0, &msgid);
@@ -947,18 +953,12 @@ static CURLcode client_write(struct Curl_easy *data,
if(!len && plen && prefix[plen - 1] == ' ')
plen--;
result = Curl_client_write(data, CLIENTWRITE_BODY, (char *) prefix, plen);
- if(!result)
- data->req.bytecount += plen;
}
if(!result && value) {
result = Curl_client_write(data, CLIENTWRITE_BODY, (char *) value, len);
- if(!result)
- data->req.bytecount += len;
}
if(!result && suffix) {
result = Curl_client_write(data, CLIENTWRITE_BODY, (char *) suffix, slen);
- if(!result)
- data->req.bytecount += slen;
}
return result;
}
diff --git a/libs/libcurl/src/pop3.c b/libs/libcurl/src/pop3.c
index 32e410f79f..b6ad724c10 100644
--- a/libs/libcurl/src/pop3.c
+++ b/libs/libcurl/src/pop3.c
@@ -1088,7 +1088,7 @@ static CURLcode pop3_init(struct Curl_easy *data)
CURLcode result = CURLE_OK;
struct POP3 *pop3;
- pop3 = data->req.p.pop3 = calloc(sizeof(struct POP3), 1);
+ pop3 = data->req.p.pop3 = calloc(1, sizeof(struct POP3));
if(!pop3)
result = CURLE_OUT_OF_MEMORY;
diff --git a/libs/libcurl/src/progress.c b/libs/libcurl/src/progress.c
index 86d8a4dc6e..a151cd2889 100644
--- a/libs/libcurl/src/progress.c
+++ b/libs/libcurl/src/progress.c
@@ -304,7 +304,7 @@ timediff_t Curl_pgrsLimitWaitTime(curl_off_t cursize,
* 'actual' is the time in milliseconds it took to actually download the
* last 'size' bytes.
*/
- actual = Curl_timediff(now, start);
+ actual = Curl_timediff_ceil(now, start);
if(actual < minimum) {
/* if it downloaded the data faster than the limit, make it wait the
difference */
@@ -319,12 +319,6 @@ timediff_t Curl_pgrsLimitWaitTime(curl_off_t cursize,
*/
CURLcode Curl_pgrsSetDownloadCounter(struct Curl_easy *data, curl_off_t size)
{
- if(data->set.max_filesize && (size > data->set.max_filesize)) {
- failf(data, "Exceeded the maximum allowed file size "
- "(%" CURL_FORMAT_CURL_OFF_T ")",
- data->set.max_filesize);
- return CURLE_FILESIZE_EXCEEDED;
- }
data->progress.downloaded = size;
return CURLE_OK;
}
diff --git a/libs/libcurl/src/rand.c b/libs/libcurl/src/rand.c
index 22bb0e6ade..025f8bdf4f 100644
--- a/libs/libcurl/src/rand.c
+++ b/libs/libcurl/src/rand.c
@@ -32,10 +32,6 @@
#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
-#ifdef HAVE_ARC4RANDOM
-/* Some platforms might have the prototype missing (ubuntu + libressl) */
-uint32_t arc4random(void);
-#endif
#include <curl/curl.h>
#include "urldata.h"
@@ -50,7 +46,7 @@ uint32_t arc4random(void);
#include "curl_memory.h"
#include "memdebug.h"
-#ifdef WIN32
+#ifdef _WIN32
#if defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x600
# define HAVE_WIN_BCRYPTGENRANDOM
@@ -105,7 +101,6 @@ CURLcode Curl_win32_random(unsigned char *entropy, size_t length)
static CURLcode randit(struct Curl_easy *data, unsigned int *rnd)
{
- unsigned int r;
CURLcode result = CURLE_OK;
static unsigned int randseed;
static bool seeded = FALSE;
@@ -138,7 +133,7 @@ static CURLcode randit(struct Curl_easy *data, unsigned int *rnd)
/* ---- non-cryptographic version following ---- */
-#ifdef WIN32
+#ifdef _WIN32
if(!seeded) {
result = Curl_win32_random((unsigned char *)rnd, sizeof(*rnd));
if(result != CURLE_NOT_BUILT_IN)
@@ -146,12 +141,14 @@ static CURLcode randit(struct Curl_easy *data, unsigned int *rnd)
}
#endif
-#ifdef HAVE_ARC4RANDOM
- *rnd = (unsigned int)arc4random();
- return CURLE_OK;
+#if defined(HAVE_ARC4RANDOM) && !defined(USE_OPENSSL)
+ if(!seeded) {
+ *rnd = (unsigned int)arc4random();
+ return CURLE_OK;
+ }
#endif
-#if defined(RANDOM_FILE) && !defined(WIN32)
+#if defined(RANDOM_FILE) && !defined(_WIN32)
if(!seeded) {
/* if there's a random file to read a seed from, use it */
int fd = open(RANDOM_FILE, O_RDONLY);
@@ -175,9 +172,12 @@ static CURLcode randit(struct Curl_easy *data, unsigned int *rnd)
seeded = TRUE;
}
- /* Return an unsigned 32-bit pseudo-random number. */
- r = randseed = randseed * 1103515245 + 12345;
- *rnd = (r << 16) | ((r >> 16) & 0xFFFF);
+ {
+ unsigned int r;
+ /* Return an unsigned 32-bit pseudo-random number. */
+ r = randseed = randseed * 1103515245 + 12345;
+ *rnd = (r << 16) | ((r >> 16) & 0xFFFF);
+ }
return CURLE_OK;
}
diff --git a/libs/libcurl/src/rand.h b/libs/libcurl/src/rand.h
index bb3d0addd7..5984de9b38 100644
--- a/libs/libcurl/src/rand.h
+++ b/libs/libcurl/src/rand.h
@@ -41,7 +41,7 @@ CURLcode Curl_rand_hex(struct Curl_easy *data, unsigned char *rnd,
CURLcode Curl_rand_alnum(struct Curl_easy *data, unsigned char *rnd,
size_t num);
-#ifdef WIN32
+#ifdef _WIN32
/* Random generator shared between the Schannel vtls and Curl_rand*()
functions */
CURLcode Curl_win32_random(unsigned char *entropy, size_t length);
diff --git a/libs/libcurl/src/rename.c b/libs/libcurl/src/rename.c
index 8f9b0731c7..9eb7b41076 100644
--- a/libs/libcurl/src/rename.c
+++ b/libs/libcurl/src/rename.c
@@ -40,7 +40,7 @@
/* return 0 on success, 1 on error */
int Curl_rename(const char *oldpath, const char *newpath)
{
-#ifdef WIN32
+#ifdef _WIN32
/* rename() on Windows doesn't overwrite, so we can't use it here.
MoveFileEx() will overwrite and is usually atomic, however it fails
when there are open handles to the file. */
diff --git a/libs/libcurl/src/rtsp.c b/libs/libcurl/src/rtsp.c
index bb9708f11b..3ad2efb690 100644
--- a/libs/libcurl/src/rtsp.c
+++ b/libs/libcurl/src/rtsp.c
@@ -45,8 +45,8 @@
#include "curl_memory.h"
#include "memdebug.h"
-#define RTP_PKT_LENGTH(p) ((((int)((unsigned char)((p)[2]))) << 8) | \
- ((int)((unsigned char)((p)[3]))))
+#define RTP_PKT_LENGTH(p) ((((unsigned int)((unsigned char)((p)[2]))) << 8) | \
+ ((unsigned int)((unsigned char)((p)[3]))))
/* protocol-specific functions set up to be called by the main engine */
static CURLcode rtsp_do(struct Curl_easy *data, bool *done);
@@ -59,14 +59,19 @@ static int rtsp_getsock_do(struct Curl_easy *data,
/*
* Parse and write out any available RTP data.
- *
- * nread: amount of data left after k->str. will be modified if RTP
- * data is parsed and k->str is moved up
- * readmore: whether or not the RTP parser needs more data right away
+ * @param data the transfer
+ * @param conn the connection
+ * @param buf data read from connection
+ * @param blen amount of data in buf
+ * @param consumed out, number of blen consumed
+ * @param readmore out, TRUE iff complete buf was consumed and more data
+ * is needed
*/
static CURLcode rtsp_rtp_readwrite(struct Curl_easy *data,
struct connectdata *conn,
- ssize_t *nread,
+ const char *buf,
+ size_t blen,
+ size_t *pconsumed,
bool *readmore);
static CURLcode rtsp_setup_connection(struct Curl_easy *data,
@@ -88,7 +93,7 @@ static int rtsp_getsock_do(struct Curl_easy *data, struct connectdata *conn,
}
static
-CURLcode rtp_client_write(struct Curl_easy *data, char *ptr, size_t len);
+CURLcode rtp_client_write(struct Curl_easy *data, const char *ptr, size_t len);
static
CURLcode rtsp_parse_transport(struct Curl_easy *data, char *transport);
@@ -585,153 +590,249 @@ static CURLcode rtsp_do(struct Curl_easy *data, bool *done)
return result;
}
-
-static CURLcode rtsp_rtp_readwrite(struct Curl_easy *data,
- struct connectdata *conn,
- ssize_t *nread,
- bool *readmore) {
- struct SingleRequest *k = &data->req;
+static CURLcode rtsp_filter_rtp(struct Curl_easy *data,
+ struct connectdata *conn,
+ const char *buf,
+ size_t blen,
+ bool in_body,
+ size_t *pconsumed)
+{
struct rtsp_conn *rtspc = &(conn->proto.rtspc);
- unsigned char *rtp_channel_mask = data->state.rtp_channel_mask;
+ CURLcode result = CURLE_OK;
- char *rtp; /* moving pointer to rtp data */
- ssize_t rtp_dataleft; /* how much data left to parse in this round */
- CURLcode result;
- bool interleaved = false;
- size_t skip_size = 0;
+ *pconsumed = 0;
+ while(blen) {
+ switch(rtspc->state) {
- if(Curl_dyn_len(&rtspc->buf)) {
- /* There was some leftover data the last time. Append new buffers */
- if(Curl_dyn_addn(&rtspc->buf, k->str, *nread))
- return CURLE_OUT_OF_MEMORY;
- rtp = Curl_dyn_ptr(&rtspc->buf);
- rtp_dataleft = Curl_dyn_len(&rtspc->buf);
- }
- else {
- /* Just parse the request buffer directly */
- rtp = k->str;
- rtp_dataleft = *nread;
- }
-
- while(rtp_dataleft > 0) {
- if(rtp[0] == '$') {
- if(rtp_dataleft > 4) {
- unsigned char rtp_channel;
- int rtp_length;
- int idx;
- int off;
-
- /* Parse the header */
- /* The channel identifier immediately follows and is 1 byte */
- rtp_channel = (unsigned char)rtp[1];
- idx = rtp_channel / 8;
- off = rtp_channel % 8;
- if(!(rtp_channel_mask[idx] & (1 << off))) {
- /* invalid channel number, maybe not an RTP packet */
- rtp++;
- rtp_dataleft--;
- skip_size++;
- continue;
+ case RTP_PARSE_SKIP: {
+ DEBUGASSERT(Curl_dyn_len(&rtspc->buf) == 0);
+ if(in_body && buf[0] != '$') {
+ /* in BODY and no valid start, do not consume and return */
+ goto out;
+ }
+ while(blen && buf[0] != '$') {
+ if(!in_body && buf[0] == 'R' &&
+ data->set.rtspreq != RTSPREQ_RECEIVE) {
+ if(strncmp(buf, "RTSP/", (blen < 5) ? blen : 5) == 0) {
+ /* This could be the next response, no consume and return */
+ if(*pconsumed) {
+ DEBUGF(infof(data, "RTP rtsp_filter_rtp[SKIP] RTSP/ prefix, "
+ "skipping %zd bytes of junk", *pconsumed));
+ }
+ rtspc->state = RTP_PARSE_SKIP;
+ rtspc->in_header = TRUE;
+ goto out;
+ }
}
- if(skip_size > 0) {
- DEBUGF(infof(data, "Skip the malformed interleaved data %lu "
- "bytes", skip_size));
+ /* junk, consume without buffering */
+ *pconsumed += 1;
+ ++buf;
+ --blen;
+ }
+ if(blen && buf[0] == '$') {
+ /* possible start of an RTP message, buffer */
+ if(Curl_dyn_addn(&rtspc->buf, buf, 1)) {
+ result = CURLE_OUT_OF_MEMORY;
+ goto out;
}
- skip_size = 0;
- rtspc->rtp_channel = rtp_channel;
-
- /* The length is two bytes */
- rtp_length = RTP_PKT_LENGTH(rtp);
+ *pconsumed += 1;
+ ++buf;
+ --blen;
+ rtspc->state = RTP_PARSE_CHANNEL;
+ }
+ break;
+ }
- if(rtp_dataleft < rtp_length + 4) {
- /* Need more - incomplete payload */
- *readmore = TRUE;
- break;
+ case RTP_PARSE_CHANNEL: {
+ int idx = ((unsigned char)buf[0]) / 8;
+ int off = ((unsigned char)buf[0]) % 8;
+ DEBUGASSERT(Curl_dyn_len(&rtspc->buf) == 1);
+ if(!(data->state.rtp_channel_mask[idx] & (1 << off))) {
+ /* invalid channel number, junk or BODY data */
+ rtspc->state = RTP_PARSE_SKIP;
+ if(in_body) {
+ /* we do not consume this byte, it is BODY data */
+ DEBUGF(infof(data, "RTSP: invalid RTP channel %d in BODY, "
+ "treating as BODY data", idx));
+ if(*pconsumed == 0) {
+ /* We did not consume the initial '$' in our buffer, but had
+ * it from an earlier call. We cannot un-consume it and have
+ * to write it directly as BODY data */
+ result = Curl_client_write(data, CLIENTWRITE_BODY,
+ Curl_dyn_ptr(&rtspc->buf), 1);
+ Curl_dyn_free(&rtspc->buf);
+ if(result)
+ goto out;
+ }
+ else {
+ /* un-consume the '$' and leave */
+ Curl_dyn_free(&rtspc->buf);
+ *pconsumed -= 1;
+ --buf;
+ ++blen;
+ goto out;
+ }
}
- interleaved = true;
- /* We have the full RTP interleaved packet
- * Write out the header including the leading '$' */
- DEBUGF(infof(data, "RTP write channel %d rtp_length %d",
- rtspc->rtp_channel, rtp_length));
- result = rtp_client_write(data, &rtp[0], rtp_length + 4);
- if(result) {
- *readmore = FALSE;
- return result;
+ else {
+ /* not BODY, forget the junk '$'. Do not consume this byte,
+ * it might be a start */
+ infof(data, "RTSP: invalid RTP channel %d, skipping", idx);
+ Curl_dyn_free(&rtspc->buf);
}
+ break;
+ }
+ /* a valid channel, so we expect this to be a real RTP message */
+ rtspc->rtp_channel = (unsigned char)buf[0];
+ if(Curl_dyn_addn(&rtspc->buf, buf, 1)) {
+ result = CURLE_OUT_OF_MEMORY;
+ goto out;
+ }
+ *pconsumed += 1;
+ ++buf;
+ --blen;
+ rtspc->state = RTP_PARSE_LEN;
+ break;
+ }
- /* Move forward in the buffer */
- rtp_dataleft -= rtp_length + 4;
- rtp += rtp_length + 4;
+ case RTP_PARSE_LEN: {
+ size_t rtp_len = Curl_dyn_len(&rtspc->buf);
+ const char *rtp_buf;
+ DEBUGASSERT(rtp_len >= 2 && rtp_len < 4);
+ if(Curl_dyn_addn(&rtspc->buf, buf, 1)) {
+ result = CURLE_OUT_OF_MEMORY;
+ goto out;
+ }
+ *pconsumed += 1;
+ ++buf;
+ --blen;
+ if(rtp_len == 2)
+ break;
+ rtp_buf = Curl_dyn_ptr(&rtspc->buf);
+ rtspc->rtp_len = RTP_PKT_LENGTH(rtp_buf) + 4;
+ rtspc->state = RTP_PARSE_DATA;
+ break;
+ }
- if(data->set.rtspreq == RTSPREQ_RECEIVE) {
- /* If we are in a passive receive, give control back
- * to the app as often as we can.
- */
- k->keepon &= ~KEEP_RECV;
+ case RTP_PARSE_DATA: {
+ size_t rtp_len = Curl_dyn_len(&rtspc->buf);
+ size_t needed;
+ DEBUGASSERT(rtp_len < rtspc->rtp_len);
+ needed = rtspc->rtp_len - rtp_len;
+ if(needed <= blen) {
+ if(Curl_dyn_addn(&rtspc->buf, buf, needed)) {
+ result = CURLE_OUT_OF_MEMORY;
+ goto out;
}
+ *pconsumed += needed;
+ buf += needed;
+ blen -= needed;
+ /* complete RTP message in buffer */
+ DEBUGF(infof(data, "RTP write channel %d rtp_len %zu",
+ rtspc->rtp_channel, rtspc->rtp_len));
+ result = rtp_client_write(data, Curl_dyn_ptr(&rtspc->buf),
+ rtspc->rtp_len);
+ Curl_dyn_free(&rtspc->buf);
+ rtspc->state = RTP_PARSE_SKIP;
+ if(result)
+ goto out;
}
else {
- /* Need more - incomplete header */
- *readmore = TRUE;
- break;
- }
- }
- else {
- /* If the following data begins with 'RTSP/', which might be an RTSP
- message, we should stop skipping the data. */
- /* If `k-> headerline> 0 && !interleaved` is true, we are maybe in the
- middle of an RTSP message. It is difficult to determine this, so we
- stop skipping. */
- size_t prefix_len = (rtp_dataleft < 5) ? rtp_dataleft : 5;
- if((k->headerline > 0 && !interleaved) ||
- strncmp(rtp, "RTSP/", prefix_len) == 0) {
- if(skip_size > 0) {
- DEBUGF(infof(data, "Skip the malformed interleaved data %lu "
- "bytes", skip_size));
+ if(Curl_dyn_addn(&rtspc->buf, buf, blen)) {
+ result = CURLE_OUT_OF_MEMORY;
+ goto out;
}
- break; /* maybe is an RTSP message */
+ *pconsumed += blen;
+ buf += blen;
+ blen = 0;
}
- /* Skip incorrect data util the next RTP packet or RTSP message */
- do {
- rtp++;
- rtp_dataleft--;
- skip_size++;
- } while(rtp_dataleft > 0 && rtp[0] != '$' && rtp[0] != 'R');
+ break;
+ }
+
+ default:
+ DEBUGASSERT(0);
+ return CURLE_RECV_ERROR;
}
}
+out:
+ return result;
+}
+
+static CURLcode rtsp_rtp_readwrite(struct Curl_easy *data,
+ struct connectdata *conn,
+ const char *buf,
+ size_t blen,
+ size_t *pconsumed,
+ bool *readmore)
+{
+ struct rtsp_conn *rtspc = &(conn->proto.rtspc);
+ CURLcode result = CURLE_OK;
+ size_t consumed = 0;
+ bool in_body;
- if(rtp_dataleft && rtp[0] == '$') {
- DEBUGF(infof(data, "RTP Rewinding %zd %s", rtp_dataleft,
- *readmore ? "(READMORE)" : ""));
+ if(!data->req.header)
+ rtspc->in_header = FALSE;
+ in_body = (data->req.headerline && !rtspc->in_header) &&
+ (data->req.size >= 0) &&
+ (data->req.bytecount < data->req.size);
- /* Store the incomplete RTP packet for a "rewind" */
- if(!Curl_dyn_len(&rtspc->buf)) {
- /* nothing was stored, add this data */
- if(Curl_dyn_addn(&rtspc->buf, rtp, rtp_dataleft))
- return CURLE_OUT_OF_MEMORY;
- }
- else {
- /* keep the remainder */
- Curl_dyn_tail(&rtspc->buf, rtp_dataleft);
- }
+ *readmore = FALSE;
+ *pconsumed = 0;
+ if(!blen) {
+ goto out;
+ }
- /* As far as the transfer is concerned, this data is consumed */
- *nread = 0;
- return CURLE_OK;
+ /* If header parsing is not onging, extract RTP messages */
+ if(!rtspc->in_header) {
+ result = rtsp_filter_rtp(data, conn, buf, blen, in_body, &consumed);
+ if(result)
+ goto out;
+ *pconsumed += consumed;
+ buf += consumed;
+ blen -= consumed;
}
- /* Fix up k->str to point just after the last RTP packet */
- k->str += *nread - rtp_dataleft;
- *nread = rtp_dataleft;
+ /* we want to parse headers, do so */
+ if(data->req.header && blen) {
+ rtspc->in_header = TRUE;
+ result = Curl_http_readwrite_headers(data, conn, buf, blen,
+ &consumed);
+ if(result)
+ goto out;
+
+ *pconsumed += consumed;
+ buf += consumed;
+ blen -= consumed;
+
+ if(!data->req.header)
+ rtspc->in_header = FALSE;
+
+ if(!rtspc->in_header) {
+ /* If header parsing is done and data left, extract RTP messages */
+ in_body = (data->req.headerline && !rtspc->in_header) &&
+ (data->req.size >= 0) &&
+ (data->req.bytecount < data->req.size);
+ result = rtsp_filter_rtp(data, conn, buf, blen, in_body, &consumed);
+ if(result)
+ goto out;
+ *pconsumed += consumed;
+ }
+ }
- /* If we get here, we have finished with the leftover/merge buffer */
- Curl_dyn_free(&rtspc->buf);
+ if(rtspc->state != RTP_PARSE_SKIP)
+ *readmore = TRUE;
- return CURLE_OK;
+out:
+ if(!*readmore && data->set.rtspreq == RTSPREQ_RECEIVE) {
+ /* In special mode RECEIVE, we just process one chunk of network
+ * data, so we stop the transfer here, if we have no incomplete
+ * RTP message pending. */
+ data->req.keepon &= ~KEEP_RECV;
+ }
+ return result;
}
static
-CURLcode rtp_client_write(struct Curl_easy *data, char *ptr, size_t len)
+CURLcode rtp_client_write(struct Curl_easy *data, const char *ptr, size_t len)
{
size_t wrote;
curl_write_callback writeit;
@@ -756,7 +857,7 @@ CURLcode rtp_client_write(struct Curl_easy *data, char *ptr, size_t len)
}
Curl_set_in_callback(data, true);
- wrote = writeit(ptr, 1, len, user_ptr);
+ wrote = writeit((char *)ptr, 1, len, user_ptr);
Curl_set_in_callback(data, false);
if(CURL_WRITEFUNC_PAUSE == wrote) {
diff --git a/libs/libcurl/src/rtsp.h b/libs/libcurl/src/rtsp.h
index e084cdaa35..15419e7f9f 100644
--- a/libs/libcurl/src/rtsp.h
+++ b/libs/libcurl/src/rtsp.h
@@ -39,6 +39,12 @@ CURLcode Curl_rtsp_parseheader(struct Curl_easy *data, char *header);
#endif /* CURL_DISABLE_RTSP */
+typedef enum {
+ RTP_PARSE_SKIP,
+ RTP_PARSE_CHANNEL,
+ RTP_PARSE_LEN,
+ RTP_PARSE_DATA
+} rtp_parse_st;
/*
* RTSP Connection data
*
@@ -47,6 +53,9 @@ CURLcode Curl_rtsp_parseheader(struct Curl_easy *data, char *header);
struct rtsp_conn {
struct dynbuf buf;
int rtp_channel;
+ size_t rtp_len;
+ rtp_parse_st state;
+ BIT(in_header);
};
/****************************************************************************
diff --git a/libs/libcurl/src/select.c b/libs/libcurl/src/select.c
index d0aa2a764b..64ff9c2eed 100644
--- a/libs/libcurl/src/select.c
+++ b/libs/libcurl/src/select.c
@@ -76,7 +76,7 @@ int Curl_wait_ms(timediff_t timeout_ms)
}
#if defined(MSDOS)
delay(timeout_ms);
-#elif defined(WIN32)
+#elif defined(_WIN32)
/* prevent overflow, timeout_ms is typecast to ULONG/DWORD. */
#if TIMEDIFF_T_MAX >= ULONG_MAX
if(timeout_ms >= ULONG_MAX)
diff --git a/libs/libcurl/src/sendf.c b/libs/libcurl/src/sendf.c
index 90f7e86e16..efd1723f17 100644
--- a/libs/libcurl/src/sendf.c
+++ b/libs/libcurl/src/sendf.c
@@ -50,6 +50,7 @@
#include "strdup.h"
#include "http2.h"
#include "headers.h"
+#include "progress.h"
#include "ws.h"
/* The last 3 #include files should be in this order */
@@ -57,6 +58,9 @@
#include "curl_memory.h"
#include "memdebug.h"
+
+static CURLcode do_init_stack(struct Curl_easy *data);
+
#if defined(CURL_DO_LINEEND_CONV) && !defined(CURL_DISABLE_FTP)
/*
* convert_lineends() changes CRLF (\r\n) end-of-line markers to a single LF
@@ -385,17 +389,17 @@ static CURLcode chop_write(struct Curl_easy *data,
the future to leave the original data alone.
*/
CURLcode Curl_client_write(struct Curl_easy *data,
- int type,
- char *ptr,
- size_t len)
+ int type, char *buf, size_t blen)
{
+ CURLcode result;
+
#if !defined(CURL_DISABLE_FTP) && defined(CURL_DO_LINEEND_CONV)
/* FTP data may need conversion. */
if((type & CLIENTWRITE_BODY) &&
(data->conn->handler->protocol & PROTO_FAMILY_FTP) &&
data->conn->proto.ftpc.transfertype == 'A') {
/* convert end-of-line markers */
- len = convert_lineends(data, ptr, len);
+ blen = convert_lineends(data, buf, blen);
}
#endif
/* it is one of those, at least */
@@ -405,14 +409,14 @@ CURLcode Curl_client_write(struct Curl_easy *data,
/* INFO is only INFO */
DEBUGASSERT(!(type & CLIENTWRITE_INFO) || (type == CLIENTWRITE_INFO));
- if(type == CLIENTWRITE_BODY) {
- if(data->req.ignorebody)
- return CURLE_OK;
-
- if(data->req.writer_stack && !data->set.http_ce_skip)
- return Curl_unencode_write(data, data->req.writer_stack, ptr, len);
+ if(!data->req.writer_stack) {
+ result = do_init_stack(data);
+ if(result)
+ return result;
+ DEBUGASSERT(data->req.writer_stack);
}
- return chop_write(data, type, FALSE, ptr, len);
+
+ return Curl_cwriter_write(data, data->req.writer_stack, type, buf, blen);
}
CURLcode Curl_client_unpause(struct Curl_easy *data)
@@ -449,12 +453,12 @@ CURLcode Curl_client_unpause(struct Curl_easy *data)
void Curl_client_cleanup(struct Curl_easy *data)
{
- struct contenc_writer *writer = data->req.writer_stack;
+ struct Curl_cwriter *writer = data->req.writer_stack;
size_t i;
while(writer) {
- data->req.writer_stack = writer->downstream;
- writer->handler->close_writer(data, writer);
+ data->req.writer_stack = writer->next;
+ writer->cwt->do_close(data, writer);
free(writer);
writer = data->req.writer_stack;
}
@@ -463,61 +467,222 @@ void Curl_client_cleanup(struct Curl_easy *data)
Curl_dyn_free(&data->state.tempwrite[i].b);
}
data->state.tempcount = 0;
+ data->req.bytecount = 0;
+ data->req.headerline = 0;
+}
+/* Write data using an unencoding writer stack. "nbytes" is not
+ allowed to be 0. */
+CURLcode Curl_cwriter_write(struct Curl_easy *data,
+ struct Curl_cwriter *writer, int type,
+ const char *buf, size_t nbytes)
+{
+ if(!nbytes)
+ return CURLE_OK;
+ if(!writer)
+ return CURLE_WRITE_ERROR;
+ return writer->cwt->do_write(data, writer, type, buf, nbytes);
}
-/* Real client writer: no downstream. */
-static CURLcode client_cew_init(struct Curl_easy *data,
- struct contenc_writer *writer)
+CURLcode Curl_cwriter_def_init(struct Curl_easy *data,
+ struct Curl_cwriter *writer)
{
- (void) data;
+ (void)data;
(void)writer;
return CURLE_OK;
}
-static CURLcode client_cew_write(struct Curl_easy *data,
- struct contenc_writer *writer,
- const char *buf, size_t nbytes)
+CURLcode Curl_cwriter_def_write(struct Curl_easy *data,
+ struct Curl_cwriter *writer, int type,
+ const char *buf, size_t nbytes)
{
- (void)writer;
- if(!nbytes || data->req.ignorebody)
- return CURLE_OK;
- return chop_write(data, CLIENTWRITE_BODY, FALSE, (char *)buf, nbytes);
+ return Curl_cwriter_write(data, writer->next, type, buf, nbytes);
}
-static void client_cew_close(struct Curl_easy *data,
- struct contenc_writer *writer)
+void Curl_cwriter_def_close(struct Curl_easy *data,
+ struct Curl_cwriter *writer)
{
(void) data;
(void) writer;
}
-static const struct content_encoding client_cew = {
+/* Real client writer to installed callbacks. */
+static CURLcode cw_client_write(struct Curl_easy *data,
+ struct Curl_cwriter *writer, int type,
+ const char *buf, size_t nbytes)
+{
+ (void)writer;
+ if(!nbytes)
+ return CURLE_OK;
+ return chop_write(data, type, FALSE, (char *)buf, nbytes);
+}
+
+static const struct Curl_cwtype cw_client = {
+ "client",
NULL,
+ Curl_cwriter_def_init,
+ cw_client_write,
+ Curl_cwriter_def_close,
+ sizeof(struct Curl_cwriter)
+};
+
+static size_t get_max_body_write_len(struct Curl_easy *data, curl_off_t limit)
+{
+ if(limit != -1) {
+ /* How much more are we allowed to write? */
+ curl_off_t remain_diff;
+ remain_diff = limit - data->req.bytecount;
+ if(remain_diff < 0) {
+ /* already written too much! */
+ return 0;
+ }
+#if SIZEOF_CURL_OFF_T > SIZEOF_SIZE_T
+ else if(remain_diff > SSIZE_T_MAX) {
+ return SIZE_T_MAX;
+ }
+#endif
+ else {
+ return (size_t)remain_diff;
+ }
+ }
+ return SIZE_T_MAX;
+}
+
+/* Download client writer in phase CURL_CW_PROTOCOL that
+ * sees the "real" download body data. */
+static CURLcode cw_download_write(struct Curl_easy *data,
+ struct Curl_cwriter *writer, int type,
+ const char *buf, size_t nbytes)
+{
+ CURLcode result;
+ size_t nwrite, excess_len = 0;
+ const char *excess_data = NULL;
+
+ if(!(type & CLIENTWRITE_BODY)) {
+ if((type & CLIENTWRITE_CONNECT) && data->set.suppress_connect_headers)
+ return CURLE_OK;
+ return Curl_cwriter_write(data, writer->next, type, buf, nbytes);
+ }
+
+ nwrite = nbytes;
+ if(-1 != data->req.maxdownload) {
+ size_t wmax = get_max_body_write_len(data, data->req.maxdownload);
+ if(nwrite > wmax) {
+ excess_len = nbytes - wmax;
+ nwrite = wmax;
+ excess_data = buf + nwrite;
+ }
+
+ if(nwrite == wmax) {
+ data->req.download_done = TRUE;
+ }
+ }
+
+ if(data->set.max_filesize) {
+ size_t wmax = get_max_body_write_len(data, data->set.max_filesize);
+ if(nwrite > wmax) {
+ nwrite = wmax;
+ }
+ }
+
+ data->req.bytecount += nwrite;
+ ++data->req.bodywrites;
+ if(!data->req.ignorebody && nwrite) {
+ result = Curl_cwriter_write(data, writer->next, type, buf, nwrite);
+ if(result)
+ return result;
+ }
+ result = Curl_pgrsSetDownloadCounter(data, data->req.bytecount);
+ if(result)
+ return result;
+
+ if(excess_len) {
+ if(data->conn->handler->readwrite) {
+ /* RTSP hack moved from transfer loop to here */
+ bool readmore = FALSE; /* indicates data is incomplete, need more */
+ size_t consumed = 0;
+ result = data->conn->handler->readwrite(data, data->conn,
+ excess_data, excess_len,
+ &consumed, &readmore);
+ if(result)
+ return result;
+ DEBUGASSERT(consumed <= excess_len);
+ excess_len -= consumed;
+ if(readmore) {
+ data->req.download_done = FALSE;
+ data->req.keepon |= KEEP_RECV; /* we're not done reading */
+ }
+ }
+ if(excess_len && !data->req.ignorebody) {
+ infof(data,
+ "Excess found writing body:"
+ " excess = %zu"
+ ", size = %" CURL_FORMAT_CURL_OFF_T
+ ", maxdownload = %" CURL_FORMAT_CURL_OFF_T
+ ", bytecount = %" CURL_FORMAT_CURL_OFF_T,
+ excess_len, data->req.size, data->req.maxdownload,
+ data->req.bytecount);
+ connclose(data->conn, "excess found in a read");
+ }
+ }
+ else if(nwrite < nbytes) {
+ failf(data, "Exceeded the maximum allowed file size "
+ "(%" CURL_FORMAT_CURL_OFF_T ") with %"
+ CURL_FORMAT_CURL_OFF_T " bytes",
+ data->set.max_filesize, data->req.bytecount);
+ return CURLE_FILESIZE_EXCEEDED;
+ }
+
+ return CURLE_OK;
+}
+
+static const struct Curl_cwtype cw_download = {
+ "download",
NULL,
- client_cew_init,
- client_cew_write,
- client_cew_close,
- sizeof(struct contenc_writer)
+ Curl_cwriter_def_init,
+ cw_download_write,
+ Curl_cwriter_def_close,
+ sizeof(struct Curl_cwriter)
+};
+
+/* RAW client writer in phase CURL_CW_RAW that
+ * enabled tracing of raw data. */
+static CURLcode cw_raw_write(struct Curl_easy *data,
+ struct Curl_cwriter *writer, int type,
+ const char *buf, size_t nbytes)
+{
+ if(type & CLIENTWRITE_BODY && data->set.verbose && !data->req.ignorebody) {
+ Curl_debug(data, CURLINFO_DATA_IN, (char *)buf, nbytes);
+ }
+ return Curl_cwriter_write(data, writer->next, type, buf, nbytes);
+}
+
+static const struct Curl_cwtype cw_raw = {
+ "raw",
+ NULL,
+ Curl_cwriter_def_init,
+ cw_raw_write,
+ Curl_cwriter_def_close,
+ sizeof(struct Curl_cwriter)
};
/* Create an unencoding writer stage using the given handler. */
-CURLcode Curl_client_create_writer(struct contenc_writer **pwriter,
+CURLcode Curl_cwriter_create(struct Curl_cwriter **pwriter,
struct Curl_easy *data,
- const struct content_encoding *ce_handler,
- int order)
+ const struct Curl_cwtype *cwt,
+ Curl_cwriter_phase phase)
{
- struct contenc_writer *writer;
+ struct Curl_cwriter *writer;
CURLcode result = CURLE_OUT_OF_MEMORY;
- DEBUGASSERT(ce_handler->writersize >= sizeof(struct contenc_writer));
- writer = (struct contenc_writer *) calloc(1, ce_handler->writersize);
+ DEBUGASSERT(cwt->cwriter_size >= sizeof(struct Curl_cwriter));
+ writer = (struct Curl_cwriter *) calloc(1, cwt->cwriter_size);
if(!writer)
goto out;
- writer->handler = ce_handler;
- writer->order = order;
- result = ce_handler->init_writer(data, writer);
+ writer->cwt = cwt;
+ writer->phase = phase;
+ result = cwt->do_init(data, writer);
out:
*pwriter = result? NULL : writer;
@@ -526,55 +691,74 @@ out:
return result;
}
-void Curl_client_free_writer(struct Curl_easy *data,
- struct contenc_writer *writer)
+void Curl_cwriter_free(struct Curl_easy *data,
+ struct Curl_cwriter *writer)
{
if(writer) {
- writer->handler->close_writer(data, writer);
+ writer->cwt->do_close(data, writer);
free(writer);
}
}
-/* allow no more than 5 "chained" compression steps */
-#define MAX_ENCODE_STACK 5
+size_t Curl_cwriter_count(struct Curl_easy *data, Curl_cwriter_phase phase)
+{
+ struct Curl_cwriter *w;
+ size_t n = 0;
+ for(w = data->req.writer_stack; w; w = w->next) {
+ if(w->phase == phase)
+ ++n;
+ }
+ return n;
+}
-static CURLcode init_writer_stack(struct Curl_easy *data)
+static CURLcode do_init_stack(struct Curl_easy *data)
{
+ struct Curl_cwriter *writer;
+ CURLcode result;
+
DEBUGASSERT(!data->req.writer_stack);
- return Curl_client_create_writer(&data->req.writer_stack,
- data, &client_cew, 0);
+ result = Curl_cwriter_create(&data->req.writer_stack,
+ data, &cw_client, CURL_CW_CLIENT);
+ if(result)
+ return result;
+
+ result = Curl_cwriter_create(&writer, data, &cw_download, CURL_CW_PROTOCOL);
+ if(result)
+ return result;
+ result = Curl_cwriter_add(data, writer);
+ if(result) {
+ Curl_cwriter_free(data, writer);
+ }
+
+ result = Curl_cwriter_create(&writer, data, &cw_raw, CURL_CW_RAW);
+ if(result)
+ return result;
+ result = Curl_cwriter_add(data, writer);
+ if(result) {
+ Curl_cwriter_free(data, writer);
+ }
+ return result;
}
-CURLcode Curl_client_add_writer(struct Curl_easy *data,
- struct contenc_writer *writer)
+CURLcode Curl_cwriter_add(struct Curl_easy *data,
+ struct Curl_cwriter *writer)
{
CURLcode result;
+ struct Curl_cwriter **anchor = &data->req.writer_stack;
- if(!data->req.writer_stack) {
- result = init_writer_stack(data);
+ if(!*anchor) {
+ result = do_init_stack(data);
if(result)
return result;
}
- if(data->req.writer_stack_depth++ >= MAX_ENCODE_STACK) {
- failf(data, "Reject response due to more than %u content encodings",
- MAX_ENCODE_STACK);
- return CURLE_BAD_CONTENT_ENCODING;
- }
-
- /* Stack the unencoding stage. */
- if(writer->order >= data->req.writer_stack->order) {
- writer->downstream = data->req.writer_stack;
- data->req.writer_stack = writer;
- }
- else {
- struct contenc_writer *w = data->req.writer_stack;
- while(w->downstream && writer->order < w->downstream->order)
- w = w->downstream;
- writer->downstream = w->downstream;
- w->downstream = writer;
- }
+ /* Insert the writer as first in its phase.
+ * Skip existing writers of lower phases. */
+ while(*anchor && (*anchor)->phase < writer->phase)
+ anchor = &((*anchor)->next);
+ writer->next = *anchor;
+ *anchor = writer;
return CURLE_OK;
}
diff --git a/libs/libcurl/src/sendf.h b/libs/libcurl/src/sendf.h
index 90efb61ace..a871b8d098 100644
--- a/libs/libcurl/src/sendf.h
+++ b/libs/libcurl/src/sendf.h
@@ -50,43 +50,122 @@
#define CLIENTWRITE_1XX (1<<5) /* a 1xx response related HEADER */
#define CLIENTWRITE_TRAILER (1<<6) /* a trailer HEADER */
+/**
+ * Write `len` bytes at `prt` to the client. `type` indicates what
+ * kind of data is being written.
+ */
CURLcode Curl_client_write(struct Curl_easy *data, int type, char *ptr,
size_t len) WARN_UNUSED_RESULT;
+/**
+ * For a paused transfer, there might be buffered data held back.
+ * Attempt to flush this data to the client. This *may* trigger
+ * another pause of the transfer.
+ */
CURLcode Curl_client_unpause(struct Curl_easy *data);
+
+/**
+ * Free all resources related to client writing.
+ */
void Curl_client_cleanup(struct Curl_easy *data);
-struct contenc_writer {
- const struct content_encoding *handler; /* Encoding handler. */
- struct contenc_writer *downstream; /* Downstream writer. */
- unsigned int order; /* Ordering within writer stack. */
+/**
+ * Client Writers - a chain passing transfer BODY data to the client.
+ * Main application: HTTP and related protocols
+ * Other uses: monitoring of download progress
+ *
+ * Writers in the chain are order by their `phase`. First come all
+ * writers in CURL_CW_RAW, followed by any in CURL_CW_TRANSFER_DECODE,
+ * followed by any in CURL_CW_PROTOCOL, etc.
+ *
+ * When adding a writer, it is inserted as first in its phase. This means
+ * the order of adding writers of the same phase matters, but writers for
+ * different phases may be added in any order.
+ *
+ * Writers which do modify the BODY data written are expected to be of
+ * phases TRANSFER_DECODE or CONTENT_DECODE. The other phases are intended
+ * for monitoring writers. Which do *not* modify the data but gather
+ * statistics or update progress reporting.
+ */
+
+/* Phase a writer operates at. */
+typedef enum {
+ CURL_CW_RAW, /* raw data written, before any decoding */
+ CURL_CW_TRANSFER_DECODE, /* remove transfer-encodings */
+ CURL_CW_PROTOCOL, /* after transfer, but before content decoding */
+ CURL_CW_CONTENT_DECODE, /* remove content-encodings */
+ CURL_CW_CLIENT /* data written to client */
+} Curl_cwriter_phase;
+
+/* Client Writer Type, provides the implementation */
+struct Curl_cwtype {
+ const char *name; /* writer name. */
+ const char *alias; /* writer name alias, maybe NULL. */
+ CURLcode (*do_init)(struct Curl_easy *data,
+ struct Curl_cwriter *writer);
+ CURLcode (*do_write)(struct Curl_easy *data,
+ struct Curl_cwriter *writer, int type,
+ const char *buf, size_t nbytes);
+ void (*do_close)(struct Curl_easy *data,
+ struct Curl_cwriter *writer);
+ size_t cwriter_size; /* sizeof() allocated struct Curl_cwriter */
};
-/* Content encoding writer. */
-struct content_encoding {
- const char *name; /* Encoding name. */
- const char *alias; /* Encoding name alias. */
- CURLcode (*init_writer)(struct Curl_easy *data,
- struct contenc_writer *writer);
- CURLcode (*unencode_write)(struct Curl_easy *data,
- struct contenc_writer *writer,
- const char *buf, size_t nbytes);
- void (*close_writer)(struct Curl_easy *data,
- struct contenc_writer *writer);
- size_t writersize;
+/* Client writer instance */
+struct Curl_cwriter {
+ const struct Curl_cwtype *cwt; /* type implementation */
+ struct Curl_cwriter *next; /* Downstream writer. */
+ Curl_cwriter_phase phase; /* phase at which it operates */
};
+/**
+ * Create a new cwriter instance with given type and phase. Is not
+ * inserted into the writer chain by this call.
+ * Invokes `writer->do_init()`.
+ */
+CURLcode Curl_cwriter_create(struct Curl_cwriter **pwriter,
+ struct Curl_easy *data,
+ const struct Curl_cwtype *ce_handler,
+ Curl_cwriter_phase phase);
-CURLcode Curl_client_create_writer(struct contenc_writer **pwriter,
- struct Curl_easy *data,
- const struct content_encoding *ce_handler,
- int order);
+/**
+ * Free a cwriter instance.
+ * Invokes `writer->do_close()`.
+ */
+void Curl_cwriter_free(struct Curl_easy *data,
+ struct Curl_cwriter *writer);
-void Curl_client_free_writer(struct Curl_easy *data,
- struct contenc_writer *writer);
+/**
+ * Count the number of writers installed of the given phase.
+ */
+size_t Curl_cwriter_count(struct Curl_easy *data, Curl_cwriter_phase phase);
-CURLcode Curl_client_add_writer(struct Curl_easy *data,
- struct contenc_writer *writer);
+/**
+ * Adds a writer to the transfer's writer chain.
+ * The writers `phase` determines where in the chain it is inserted.
+ */
+CURLcode Curl_cwriter_add(struct Curl_easy *data,
+ struct Curl_cwriter *writer);
+
+/**
+ * Convenience method for calling `writer->do_write()` that
+ * checks for NULL writer.
+ */
+CURLcode Curl_cwriter_write(struct Curl_easy *data,
+ struct Curl_cwriter *writer, int type,
+ const char *buf, size_t nbytes);
+
+/**
+ * Default implementations for do_init, do_write, do_close that
+ * do nothing and pass the data through.
+ */
+CURLcode Curl_cwriter_def_init(struct Curl_easy *data,
+ struct Curl_cwriter *writer);
+CURLcode Curl_cwriter_def_write(struct Curl_easy *data,
+ struct Curl_cwriter *writer, int type,
+ const char *buf, size_t nbytes);
+void Curl_cwriter_def_close(struct Curl_easy *data,
+ struct Curl_cwriter *writer);
/* internal read-function, does plain socket, SSL and krb4 */
diff --git a/libs/libcurl/src/setopt.c b/libs/libcurl/src/setopt.c
index 01219c7c39..5ad3c9456b 100644
--- a/libs/libcurl/src/setopt.c
+++ b/libs/libcurl/src/setopt.c
@@ -50,6 +50,7 @@
#include "multiif.h"
#include "altsvc.h"
#include "hsts.h"
+#include "tftp.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
@@ -171,7 +172,7 @@ static CURLcode protocol2num(const char *str, curl_prot_t *val)
str = strchr(str, ',');
tlen = str? (size_t) (str - token): strlen(token);
if(tlen) {
- const struct Curl_handler *h = Curl_builtin_scheme(token, tlen);
+ const struct Curl_handler *h = Curl_getn_scheme_handler(token, tlen);
if(!h)
return CURLE_UNSUPPORTED_PROTOCOL;
@@ -261,43 +262,43 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
* Set the absolute number of maximum simultaneous alive connection that
* libcurl is allowed to have.
*/
- arg = va_arg(param, long);
- if(arg < 0)
+ uarg = va_arg(param, unsigned long);
+ if(uarg > UINT_MAX)
return CURLE_BAD_FUNCTION_ARGUMENT;
- data->set.maxconnects = arg;
+ data->set.maxconnects = (unsigned int)uarg;
break;
case CURLOPT_FORBID_REUSE:
/*
* When this transfer is done, it must not be left to be reused by a
* subsequent transfer but shall be closed immediately.
*/
- data->set.reuse_forbid = (0 != va_arg(param, long)) ? TRUE : FALSE;
+ data->set.reuse_forbid = (0 != va_arg(param, long));
break;
case CURLOPT_FRESH_CONNECT:
/*
* This transfer shall not use a previously cached connection but
* should be made with a fresh new connect!
*/
- data->set.reuse_fresh = (0 != va_arg(param, long)) ? TRUE : FALSE;
+ data->set.reuse_fresh = (0 != va_arg(param, long));
break;
case CURLOPT_VERBOSE:
/*
* Verbose means infof() calls that give a lot of information about
* the connection and transfer procedures as well as internal choices.
*/
- data->set.verbose = (0 != va_arg(param, long)) ? TRUE : FALSE;
+ data->set.verbose = (0 != va_arg(param, long));
break;
case CURLOPT_HEADER:
/*
* Set to include the header in the general data output stream.
*/
- data->set.include_header = (0 != va_arg(param, long)) ? TRUE : FALSE;
+ data->set.include_header = (0 != va_arg(param, long));
break;
case CURLOPT_NOPROGRESS:
/*
* Shut off the internal supported progress meter
*/
- data->set.hide_progress = (0 != va_arg(param, long)) ? TRUE : FALSE;
+ data->set.hide_progress = (0 != va_arg(param, long));
if(data->set.hide_progress)
data->progress.flags |= PGRS_HIDE;
else
@@ -307,7 +308,7 @@ 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;
+ data->set.opt_no_body = (0 != va_arg(param, long));
#ifndef CURL_DISABLE_HTTP
if(data->set.opt_no_body)
/* in HTTP lingo, no body means using the HEAD request... */
@@ -321,11 +322,10 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
* Don't output the >=400 error code HTML-page, but instead only
* return error.
*/
- data->set.http_fail_on_error = (0 != va_arg(param, long)) ? TRUE : FALSE;
+ data->set.http_fail_on_error = (0 != va_arg(param, long));
break;
case CURLOPT_KEEP_SENDING_ON_ERROR:
- data->set.http_keep_sending_on_error = (0 != va_arg(param, long)) ?
- TRUE : FALSE;
+ data->set.http_keep_sending_on_error = (0 != va_arg(param, long));
break;
case CURLOPT_UPLOAD:
case CURLOPT_PUT:
@@ -353,7 +353,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
* Try to get the file time of the remote document. The time will
* later (possibly) become available using curl_easy_getinfo().
*/
- data->set.get_filetime = (0 != va_arg(param, long)) ? TRUE : FALSE;
+ data->set.get_filetime = (0 != va_arg(param, long));
break;
case CURLOPT_SERVER_RESPONSE_TIMEOUT:
/*
@@ -379,7 +379,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
* TFTP option that specifies the block size to use for data transmission.
*/
arg = va_arg(param, long);
- if(arg < 0)
+ if(arg > TFTP_BLKSIZE_MAX || arg < TFTP_BLKSIZE_MIN)
return CURLE_BAD_FUNCTION_ARGUMENT;
data->set.tftp_blksize = arg;
break;
@@ -409,7 +409,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
*
* Transfer using ASCII (instead of BINARY).
*/
- data->set.prefer_ascii = (0 != va_arg(param, long)) ? TRUE : FALSE;
+ data->set.prefer_ascii = (0 != va_arg(param, long));
break;
case CURLOPT_TIMECONDITION:
/*
@@ -577,7 +577,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
/*
* Switch on automatic referer that gets set if curl follows locations.
*/
- data->set.http_auto_referer = (0 != va_arg(param, long)) ? TRUE : FALSE;
+ data->set.http_auto_referer = (0 != va_arg(param, long));
break;
case CURLOPT_ACCEPT_ENCODING:
@@ -592,28 +592,23 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
*/
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);
- }
+ char all[256];
+ Curl_all_content_encodings(all, sizeof(all));
+ result = Curl_setstropt(&data->set.str[STRING_ENCODING], all);
}
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;
+ data->set.http_transfer_encoding = (0 != va_arg(param, long));
break;
case CURLOPT_FOLLOWLOCATION:
/*
* Follow Location: header hints on an HTTP-server.
*/
- data->set.http_follow_location = (0 != va_arg(param, long)) ? TRUE : FALSE;
+ data->set.http_follow_location = (0 != va_arg(param, long));
break;
case CURLOPT_UNRESTRICTED_AUTH:
@@ -621,8 +616,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
* 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;
+ data->set.allow_auth_to_other_hosts = (0 != va_arg(param, long));
break;
case CURLOPT_MAXREDIRS:
@@ -736,7 +730,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
* Set header option.
*/
arg = va_arg(param, long);
- data->set.sep_headers = (bool)((arg & CURLHEADER_SEPARATE)? TRUE: FALSE);
+ data->set.sep_headers = !!(arg & CURLHEADER_SEPARATE);
break;
#if !defined(CURL_DISABLE_COOKIES)
@@ -760,18 +754,18 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
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->set.cookielist, argptr);
+ cl = curl_slist_append(data->state.cookielist, argptr);
if(!cl) {
- curl_slist_free_all(data->set.cookielist);
- data->set.cookielist = NULL;
+ curl_slist_free_all(data->state.cookielist);
+ data->state.cookielist = NULL;
return CURLE_OUT_OF_MEMORY;
}
- data->set.cookielist = cl; /* store the list for later use */
+ data->state.cookielist = cl; /* store the list for later use */
}
else {
/* clear the list of cookie files */
- curl_slist_free_all(data->set.cookielist);
- data->set.cookielist = NULL;
+ curl_slist_free_all(data->state.cookielist);
+ data->state.cookielist = NULL;
if(!data->share || !data->share->cookies) {
/* throw away all existing cookies if this isn't a shared cookie
@@ -811,17 +805,8 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
* prevent the forthcoming read-cookies-from-file actions to accept
* cookies that are marked as being session cookies, as they belong to a
* previous session.
- *
- * In the original Netscape cookie spec, "session cookies" are cookies
- * with no expire date set. RFC2109 describes the same action if no
- * 'Max-Age' is set and RFC2965 includes the RFC2109 description and adds
- * a 'Discard' action that can enforce the discard even for cookies that
- * have a Max-Age.
- *
- * We run mostly with the original cookie spec, as hardly anyone implements
- * anything else.
*/
- data->set.cookiesession = (0 != va_arg(param, long)) ? TRUE : FALSE;
+ data->set.cookiesession = (0 != va_arg(param, long));
break;
case CURLOPT_COOKIELIST:
@@ -956,7 +941,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
if(arg)
return CURLE_BAD_FUNCTION_ARGUMENT;
#else
- data->set.http09_allowed = arg ? TRUE : FALSE;
+ data->set.http09_allowed = !!arg;
#endif
break;
@@ -997,8 +982,9 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
break;
case CURLOPT_MIME_OPTIONS:
- data->set.mime_options = (unsigned int)va_arg(param, long);
- break;
+ arg = va_arg(param, long);
+ data->set.mime_formescape = !!(arg & CURLMIMEOPT_FORMESCAPE);
+ break;
# endif
#endif
@@ -1018,8 +1004,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
/* the DIGEST_IE bit is only used to set a special marker, for all the
rest we need to handle it as normal DIGEST */
- data->state.authhost.iestyle =
- (bool)((auth & CURLAUTH_DIGEST_IE) ? TRUE : FALSE);
+ data->state.authhost.iestyle = !!(auth & CURLAUTH_DIGEST_IE);
if(auth & CURLAUTH_DIGEST_IE) {
auth |= CURLAUTH_DIGEST; /* set standard digest bit */
@@ -1072,8 +1057,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
/*
* Tunnel operations through the proxy instead of normal proxy use
*/
- data->set.tunnel_thru_httpproxy = (0 != va_arg(param, long)) ?
- TRUE : FALSE;
+ data->set.tunnel_thru_httpproxy = (0 != va_arg(param, long));
break;
case CURLOPT_PROXYPORT:
@@ -1102,8 +1086,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
/* the DIGEST_IE bit is only used to set a special marker, for all the
rest we need to handle it as normal DIGEST */
- data->state.authproxy.iestyle =
- (bool)((auth & CURLAUTH_DIGEST_IE) ? TRUE : FALSE);
+ data->state.authproxy.iestyle = !!(auth & CURLAUTH_DIGEST_IE);
if(auth & CURLAUTH_DIGEST_IE) {
auth |= CURLAUTH_DIGEST; /* set standard digest bit */
@@ -1203,7 +1186,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
/*
* Set flag for NEC SOCK5 support
*/
- data->set.socks5_gssapi_nec = (0 != va_arg(param, long)) ? TRUE : FALSE;
+ data->set.socks5_gssapi_nec = (0 != va_arg(param, long));
break;
#endif
#ifndef CURL_DISABLE_PROXY
@@ -1251,7 +1234,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
* An option that changes the command to one that asks for a list only, no
* file info details. Used for FTP, POP3 and SFTP.
*/
- data->set.list_only = (0 != va_arg(param, long)) ? TRUE : FALSE;
+ data->set.list_only = (0 != va_arg(param, long));
break;
#endif
case CURLOPT_APPEND:
@@ -1259,7 +1242,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
* We want to upload and append to an existing file. Used for FTP and
* SFTP.
*/
- data->set.remote_append = (0 != va_arg(param, long)) ? TRUE : FALSE;
+ data->set.remote_append = (0 != va_arg(param, long));
break;
#ifndef CURL_DISABLE_FTP
@@ -1270,7 +1253,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
arg = va_arg(param, long);
if((arg < CURLFTPMETHOD_DEFAULT) || (arg >= CURLFTPMETHOD_LAST))
return CURLE_BAD_FUNCTION_ARGUMENT;
- data->set.ftp_filemethod = (unsigned char)(curl_ftpfile)arg;
+ data->set.ftp_filemethod = (unsigned char)arg;
break;
case CURLOPT_FTPPORT:
/*
@@ -1278,26 +1261,26 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
*/
result = Curl_setstropt(&data->set.str[STRING_FTPPORT],
va_arg(param, char *));
- data->set.ftp_use_port = (data->set.str[STRING_FTPPORT]) ? TRUE : FALSE;
+ data->set.ftp_use_port = !!(data->set.str[STRING_FTPPORT]);
break;
case CURLOPT_FTP_USE_EPRT:
- data->set.ftp_use_eprt = (0 != va_arg(param, long)) ? TRUE : FALSE;
+ data->set.ftp_use_eprt = (0 != va_arg(param, long));
break;
case CURLOPT_FTP_USE_EPSV:
- data->set.ftp_use_epsv = (0 != va_arg(param, long)) ? TRUE : FALSE;
+ data->set.ftp_use_epsv = (0 != va_arg(param, long));
break;
case CURLOPT_FTP_USE_PRET:
- data->set.ftp_use_pret = (0 != va_arg(param, long)) ? TRUE : FALSE;
+ data->set.ftp_use_pret = (0 != va_arg(param, long));
break;
case CURLOPT_FTP_SSL_CCC:
arg = va_arg(param, long);
if((arg < CURLFTPSSL_CCC_NONE) || (arg >= CURLFTPSSL_CCC_LAST))
return CURLE_BAD_FUNCTION_ARGUMENT;
- data->set.ftp_ccc = (unsigned char)(curl_ftpccc)arg;
+ data->set.ftp_ccc = (unsigned char)arg;
break;
case CURLOPT_FTP_SKIP_PASV_IP:
@@ -1305,7 +1288,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
* Enable or disable FTP_SKIP_PASV_IP, which will disable/enable the
* bypass of the IP address in PASV responses.
*/
- data->set.ftp_skip_ip = (0 != va_arg(param, long)) ? TRUE : FALSE;
+ data->set.ftp_skip_ip = (0 != va_arg(param, long));
break;
case CURLOPT_FTP_ACCOUNT:
@@ -1333,7 +1316,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
*/
result = Curl_setstropt(&data->set.str[STRING_KRB_LEVEL],
va_arg(param, char *));
- data->set.krb = (data->set.str[STRING_KRB_LEVEL]) ? TRUE : FALSE;
+ data->set.krb = !!(data->set.str[STRING_KRB_LEVEL]);
break;
#endif
#if !defined(CURL_DISABLE_FTP) || defined(USE_SSH)
@@ -1867,14 +1850,14 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
/*
* Kludgy option to enable CRLF conversions. Subject for removal.
*/
- data->set.crlf = (0 != va_arg(param, long)) ? TRUE : FALSE;
+ data->set.crlf = (0 != va_arg(param, long));
break;
#ifndef CURL_DISABLE_PROXY
case CURLOPT_HAPROXYPROTOCOL:
/*
* Set to send the HAProxy Proxy Protocol header
*/
- data->set.haproxyprotocol = (0 != va_arg(param, long)) ? TRUE : FALSE;
+ data->set.haproxyprotocol = (0 != va_arg(param, long));
break;
case CURLOPT_HAPROXY_CLIENT_IP:
/*
@@ -1926,22 +1909,17 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
/*
* Enable peer SSL verifying.
*/
- data->set.ssl.primary.verifypeer = (0 != va_arg(param, long)) ?
- TRUE : FALSE;
+ data->set.ssl.primary.verifypeer = (0 != va_arg(param, long));
/* Update the current connection ssl_config. */
- if(data->conn) {
- data->conn->ssl_config.verifypeer =
- data->set.ssl.primary.verifypeer;
- }
+ Curl_ssl_conn_config_update(data, FALSE);
break;
#ifndef CURL_DISABLE_DOH
case CURLOPT_DOH_SSL_VERIFYPEER:
/*
* Enable peer SSL verifying for DoH.
*/
- data->set.doh_verifypeer = (0 != va_arg(param, long)) ?
- TRUE : FALSE;
+ data->set.doh_verifypeer = (0 != va_arg(param, long));
break;
#endif
#ifndef CURL_DISABLE_PROXY
@@ -1953,10 +1931,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
(0 != va_arg(param, long))?TRUE:FALSE;
/* Update the current connection proxy_ssl_config. */
- if(data->conn) {
- data->conn->proxy_ssl_config.verifypeer =
- data->set.proxy_ssl.primary.verifypeer;
- }
+ Curl_ssl_conn_config_update(data, TRUE);
break;
#endif
case CURLOPT_SSL_VERIFYHOST:
@@ -1968,13 +1943,10 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
/* Obviously people are not reading documentation and too many thought
this argument took a boolean when it wasn't and misused it.
Treat 1 and 2 the same */
- data->set.ssl.primary.verifyhost = (bool)((arg & 3) ? TRUE : FALSE);
+ data->set.ssl.primary.verifyhost = !!(arg & 3);
/* Update the current connection ssl_config. */
- if(data->conn) {
- data->conn->ssl_config.verifyhost =
- data->set.ssl.primary.verifyhost;
- }
+ Curl_ssl_conn_config_update(data, FALSE);
break;
#ifndef CURL_DISABLE_DOH
case CURLOPT_DOH_SSL_VERIFYHOST:
@@ -1984,7 +1956,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
arg = va_arg(param, long);
/* Treat both 1 and 2 as TRUE */
- data->set.doh_verifyhost = (bool)((arg & 3) ? TRUE : FALSE);
+ data->set.doh_verifyhost = !!(arg & 3);
break;
#endif
#ifndef CURL_DISABLE_PROXY
@@ -1996,12 +1968,8 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
/* Treat both 1 and 2 as TRUE */
data->set.proxy_ssl.primary.verifyhost = (bool)((arg & 3)?TRUE:FALSE);
-
/* Update the current connection proxy_ssl_config. */
- if(data->conn) {
- data->conn->proxy_ssl_config.verifyhost =
- data->set.proxy_ssl.primary.verifyhost;
- }
+ Curl_ssl_conn_config_update(data, TRUE);
break;
#endif
case CURLOPT_SSL_VERIFYSTATUS:
@@ -2013,14 +1981,10 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
break;
}
- data->set.ssl.primary.verifystatus = (0 != va_arg(param, long)) ?
- TRUE : FALSE;
+ data->set.ssl.primary.verifystatus = (0 != va_arg(param, long));
/* Update the current connection ssl_config. */
- if(data->conn) {
- data->conn->ssl_config.verifystatus =
- data->set.ssl.primary.verifystatus;
- }
+ Curl_ssl_conn_config_update(data, FALSE);
break;
#ifndef CURL_DISABLE_DOH
case CURLOPT_DOH_SSL_VERIFYSTATUS:
@@ -2032,8 +1996,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
break;
}
- data->set.doh_verifystatus = (0 != va_arg(param, long)) ?
- TRUE : FALSE;
+ data->set.doh_verifystatus = (0 != va_arg(param, long));
break;
#endif
case CURLOPT_SSL_CTX_FUNCTION:
@@ -2067,12 +2030,12 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
break;
}
- data->set.ssl.falsestart = (0 != va_arg(param, long)) ? TRUE : FALSE;
+ data->set.ssl.falsestart = (0 != va_arg(param, long));
break;
case CURLOPT_CERTINFO:
#ifdef USE_SSL
if(Curl_ssl_supports(data, SSLSUPP_CERTINFO))
- data->set.ssl.certinfo = (0 != va_arg(param, long)) ? TRUE : FALSE;
+ data->set.ssl.certinfo = (0 != va_arg(param, long));
else
#endif
result = CURLE_NOT_BUILT_IN;
@@ -2118,14 +2081,14 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
* Specify entire PEM of the CA certificate
*/
#ifdef USE_SSL
- if(Curl_ssl_supports(data, SSLSUPP_CAINFO_BLOB))
+ if(Curl_ssl_supports(data, SSLSUPP_CAINFO_BLOB)) {
result = Curl_setblobopt(&data->set.blobs[BLOB_CAINFO],
va_arg(param, struct curl_blob *));
+ break;
+ }
else
#endif
return CURLE_NOT_BUILT_IN;
-
- break;
#ifndef CURL_DISABLE_PROXY
case CURLOPT_PROXY_CAINFO:
/*
@@ -2141,13 +2104,14 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
* Specify entire PEM of the CA certificate
*/
#ifdef USE_SSL
- if(Curl_ssl_supports(data, SSLSUPP_CAINFO_BLOB))
+ if(Curl_ssl_supports(data, SSLSUPP_CAINFO_BLOB)) {
result = Curl_setblobopt(&data->set.blobs[BLOB_CAINFO_PROXY],
va_arg(param, struct curl_blob *));
+ break;
+ }
else
#endif
return CURLE_NOT_BUILT_IN;
- break;
#endif
case CURLOPT_CAPATH:
/*
@@ -2278,7 +2242,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
* The application asks not to set any signal() or alarm() handlers,
* even when using a timeout.
*/
- data->set.no_signal = (0 != va_arg(param, long)) ? TRUE : FALSE;
+ data->set.no_signal = (0 != va_arg(param, long));
break;
case CURLOPT_SHARE:
@@ -2453,11 +2417,11 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
* Enable or disable TCP_NODELAY, which will disable/enable the Nagle
* algorithm
*/
- data->set.tcp_nodelay = (0 != va_arg(param, long)) ? TRUE : FALSE;
+ data->set.tcp_nodelay = (0 != va_arg(param, long));
break;
case CURLOPT_IGNORE_CONTENT_LENGTH:
- data->set.ignorecl = (0 != va_arg(param, long)) ? TRUE : FALSE;
+ data->set.ignorecl = (0 != va_arg(param, long));
break;
case CURLOPT_CONNECT_ONLY:
@@ -2532,8 +2496,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
break;
case CURLOPT_SSL_SESSIONID_CACHE:
- data->set.ssl.primary.sessionid = (0 != va_arg(param, long)) ?
- TRUE : FALSE;
+ data->set.ssl.primary.sessionid = (0 != va_arg(param, long));
#ifndef CURL_DISABLE_PROXY
data->set.proxy_ssl.primary.sessionid = data->set.ssl.primary.sessionid;
#endif
@@ -2622,7 +2585,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
* disable libcurl transfer encoding is used
*/
#ifndef USE_HYPER
- data->set.http_te_skip = (0 == va_arg(param, long)) ? TRUE : FALSE;
+ data->set.http_te_skip = (0 == va_arg(param, long));
break;
#else
return CURLE_NOT_BUILT_IN; /* hyper doesn't support */
@@ -2632,7 +2595,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
/*
* raw data passed to the application when content encoding is used
*/
- data->set.http_ce_skip = (0 == va_arg(param, long)) ? TRUE : FALSE;
+ data->set.http_ce_skip = (0 == va_arg(param, long));
break;
#if !defined(CURL_DISABLE_FTP) || defined(USE_SSH)
@@ -2733,7 +2696,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
break;
case CURLOPT_MAIL_RCPT_ALLOWFAILS:
/* allow RCPT TO command to fail for some recipients */
- data->set.mail_rcpt_allowfails = (0 != va_arg(param, long)) ? TRUE : FALSE;
+ data->set.mail_rcpt_allowfails = (0 != va_arg(param, long));
break;
#endif
@@ -2745,7 +2708,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
case CURLOPT_SASL_IR:
/* Enable/disable SASL initial response */
- data->set.sasl_ir = (0 != va_arg(param, long)) ? TRUE : FALSE;
+ data->set.sasl_ir = (0 != va_arg(param, long));
break;
#ifndef CURL_DISABLE_RTSP
case CURLOPT_RTSP_REQUEST:
@@ -2859,7 +2822,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
#endif
#ifndef CURL_DISABLE_FTP
case CURLOPT_WILDCARDMATCH:
- data->set.wildcard_enabled = (0 != va_arg(param, long)) ? TRUE : FALSE;
+ data->set.wildcard_enabled = (0 != va_arg(param, long));
break;
case CURLOPT_CHUNK_BGN_FUNCTION:
data->set.chunk_bgn = va_arg(param, curl_chunk_bgn_callback);
@@ -2942,7 +2905,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
break;
#endif
case CURLOPT_TCP_KEEPALIVE:
- data->set.tcp_keepalive = (0 != va_arg(param, long)) ? TRUE : FALSE;
+ data->set.tcp_keepalive = (0 != va_arg(param, long));
break;
case CURLOPT_TCP_KEEPIDLE:
arg = va_arg(param, long);
@@ -2971,7 +2934,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
case CURLOPT_SSL_ENABLE_NPN:
break;
case CURLOPT_SSL_ENABLE_ALPN:
- data->set.ssl_enable_alpn = (0 != va_arg(param, long)) ? TRUE : FALSE;
+ data->set.ssl_enable_alpn = (0 != va_arg(param, long));
break;
#ifdef USE_UNIX_SOCKETS
case CURLOPT_UNIX_SOCKET_PATH:
@@ -2987,10 +2950,10 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
#endif
case CURLOPT_PATH_AS_IS:
- data->set.path_as_is = (0 != va_arg(param, long)) ? TRUE : FALSE;
+ data->set.path_as_is = (0 != va_arg(param, long));
break;
case CURLOPT_PIPEWAIT:
- data->set.pipewait = (0 != va_arg(param, long)) ? TRUE : FALSE;
+ data->set.pipewait = (0 != va_arg(param, long));
break;
case CURLOPT_STREAM_WEIGHT:
#if defined(USE_HTTP2) || defined(USE_HTTP3)
@@ -3025,12 +2988,11 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
break;
#ifndef CURL_DISABLE_SHUFFLE_DNS
case CURLOPT_DNS_SHUFFLE_ADDRESSES:
- data->set.dns_shuffle_addresses = (0 != va_arg(param, long)) ? TRUE:FALSE;
+ data->set.dns_shuffle_addresses = (0 != va_arg(param, long));
break;
#endif
case CURLOPT_DISALLOW_USERNAME_IN_URL:
- data->set.disallow_username_in_url =
- (0 != va_arg(param, long)) ? TRUE : FALSE;
+ data->set.disallow_username_in_url = (0 != va_arg(param, long));
break;
#ifndef CURL_DISABLE_DOH
case CURLOPT_DOH_URL:
@@ -3095,18 +3057,18 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
/* this needs to build a list of file names to read from, so that it can
read them later, as we might get a shared HSTS handle to load them
into */
- h = curl_slist_append(data->set.hstslist, argptr);
+ h = curl_slist_append(data->state.hstslist, argptr);
if(!h) {
- curl_slist_free_all(data->set.hstslist);
- data->set.hstslist = NULL;
+ curl_slist_free_all(data->state.hstslist);
+ data->state.hstslist = NULL;
return CURLE_OUT_OF_MEMORY;
}
- data->set.hstslist = h; /* store the list for later use */
+ data->state.hstslist = h; /* store the list for later use */
}
else {
/* clear the list of HSTS files */
- curl_slist_free_all(data->set.hstslist);
- data->set.hstslist = NULL;
+ curl_slist_free_all(data->state.hstslist);
+ data->state.hstslist = NULL;
if(!data->share || !data->share->hsts)
/* throw away the HSTS cache unless shared */
Curl_hsts_cleanup(&data->hsts);
diff --git a/libs/libcurl/src/setup-win32.h b/libs/libcurl/src/setup-win32.h
index 43701e20bf..2203c46a55 100644
--- a/libs/libcurl/src/setup-win32.h
+++ b/libs/libcurl/src/setup-win32.h
@@ -53,14 +53,14 @@
# ifndef NOGDI
# define NOGDI
# endif
-# include <winerror.h>
-# include <windows.h>
# ifdef HAVE_WINSOCK2_H
# include <winsock2.h>
# ifdef HAVE_WS2TCPIP_H
# include <ws2tcpip.h>
# endif
# endif
+# include <windows.h>
+# include <winerror.h>
# include <tchar.h>
# ifdef UNICODE
typedef wchar_t *(*curl_wcsdup_callback)(const wchar_t *str);
@@ -96,18 +96,12 @@
#ifndef _WIN32_WINNT_WS03
#define _WIN32_WINNT_WS03 0x0502 /* Windows Server 2003 */
#endif
-#ifndef _WIN32_WINNT_WIN6
-#define _WIN32_WINNT_WIN6 0x0600 /* Windows Vista */
-#endif
#ifndef _WIN32_WINNT_VISTA
#define _WIN32_WINNT_VISTA 0x0600 /* Windows Vista */
#endif
#ifndef _WIN32_WINNT_WS08
#define _WIN32_WINNT_WS08 0x0600 /* Windows Server 2008 */
#endif
-#ifndef _WIN32_WINNT_LONGHORN
-#define _WIN32_WINNT_LONGHORN 0x0600 /* Windows Vista */
-#endif
#ifndef _WIN32_WINNT_WIN7
#define _WIN32_WINNT_WIN7 0x0601 /* Windows 7 */
#endif
@@ -117,9 +111,6 @@
#ifndef _WIN32_WINNT_WINBLUE
#define _WIN32_WINNT_WINBLUE 0x0603 /* Windows 8.1 */
#endif
-#ifndef _WIN32_WINNT_WINTHRESHOLD
-#define _WIN32_WINNT_WINTHRESHOLD 0x0A00 /* Windows 10 */
-#endif
#ifndef _WIN32_WINNT_WIN10
#define _WIN32_WINNT_WIN10 0x0A00 /* Windows 10 */
#endif
diff --git a/libs/libcurl/src/share.h b/libs/libcurl/src/share.h
index 0f4d6a31b3..e3e130daed 100644
--- a/libs/libcurl/src/share.h
+++ b/libs/libcurl/src/share.h
@@ -31,14 +31,6 @@
#include "urldata.h"
#include "conncache.h"
-/* SalfordC says "A structure member may not be volatile". Hence:
- */
-#ifdef __SALFORDC__
-#define CURL_VOLATILE
-#else
-#define CURL_VOLATILE volatile
-#endif
-
#define CURL_GOOD_SHARE 0x7e117a1e
#define GOOD_SHARE_HANDLE(x) ((x) && (x)->magic == CURL_GOOD_SHARE)
@@ -46,7 +38,7 @@
struct Curl_share {
unsigned int magic; /* CURL_GOOD_SHARE */
unsigned int specifier;
- CURL_VOLATILE unsigned int dirty;
+ volatile unsigned int dirty;
curl_lock_function lockfunc;
curl_unlock_function unlockfunc;
diff --git a/libs/libcurl/src/smb.c b/libs/libcurl/src/smb.c
index f708ded3ca..130382c740 100644
--- a/libs/libcurl/src/smb.c
+++ b/libs/libcurl/src/smb.c
@@ -27,7 +27,7 @@
#if !defined(CURL_DISABLE_SMB) && defined(USE_CURL_NTLM_CORE)
-#ifdef WIN32
+#ifdef _WIN32
#define getpid GetCurrentProcessId
#endif
@@ -1047,14 +1047,7 @@ static CURLcode smb_request_state(struct Curl_easy *data, bool *done)
break;
}
}
- data->req.bytecount += len;
data->req.offset += len;
- result = Curl_pgrsSetDownloadCounter(data, data->req.bytecount);
- if(result) {
- req->result = result;
- next_state = SMB_CLOSE;
- break;
- }
next_state = (len < MAX_PAYLOAD_SIZE) ? SMB_CLOSE : SMB_DOWNLOAD;
break;
diff --git a/libs/libcurl/src/smtp.c b/libs/libcurl/src/smtp.c
index 10a4b9c038..b6da9ba679 100644
--- a/libs/libcurl/src/smtp.c
+++ b/libs/libcurl/src/smtp.c
@@ -1320,7 +1320,7 @@ static CURLcode smtp_init(struct Curl_easy *data)
CURLcode result = CURLE_OK;
struct SMTP *smtp;
- smtp = data->req.p.smtp = calloc(sizeof(struct SMTP), 1);
+ smtp = data->req.p.smtp = calloc(1, sizeof(struct SMTP));
if(!smtp)
result = CURLE_OUT_OF_MEMORY;
diff --git a/libs/libcurl/src/socketpair.c b/libs/libcurl/src/socketpair.c
index 7733ab3322..9d4020426f 100644
--- a/libs/libcurl/src/socketpair.c
+++ b/libs/libcurl/src/socketpair.c
@@ -28,7 +28,7 @@
#include "rand.h"
#if !defined(HAVE_SOCKETPAIR) && !defined(CURL_DISABLE_SOCKETPAIR)
-#ifdef WIN32
+#ifdef _WIN32
/*
* This is a socketpair() implementation for Windows.
*/
@@ -50,7 +50,7 @@
#ifndef INADDR_LOOPBACK
#define INADDR_LOOPBACK 0x7f000001
#endif /* !INADDR_LOOPBACK */
-#endif /* !WIN32 */
+#endif /* !_WIN32 */
#include "nonblock.h" /* for curlx_nonblock */
#include "timeval.h" /* needed before select.h */
@@ -87,7 +87,7 @@ int Curl_socketpair(int domain, int type, int protocol,
socks[0] = socks[1] = CURL_SOCKET_BAD;
-#if defined(WIN32) || defined(__CYGWIN__)
+#if defined(_WIN32) || defined(__CYGWIN__)
/* don't set SO_REUSEADDR on Windows */
(void)reuse;
#ifdef SO_EXCLUSIVEADDRUSE
diff --git a/libs/libcurl/src/socketpair.h b/libs/libcurl/src/socketpair.h
index cd6faf788a..08f076d916 100644
--- a/libs/libcurl/src/socketpair.h
+++ b/libs/libcurl/src/socketpair.h
@@ -25,6 +25,23 @@
***************************************************************************/
#include "curl_setup.h"
+
+#ifdef HAVE_PIPE
+
+#define wakeup_write write
+#define wakeup_read read
+#define wakeup_close close
+#define wakeup_create pipe
+
+#else /* HAVE_PIPE */
+
+#define wakeup_write swrite
+#define wakeup_read sread
+#define wakeup_close sclose
+#define wakeup_create(p) Curl_socketpair(AF_UNIX, SOCK_STREAM, 0, p)
+
+#endif /* HAVE_PIPE */
+
#ifndef HAVE_SOCKETPAIR
#include <curl/curl.h>
diff --git a/libs/libcurl/src/socks.c b/libs/libcurl/src/socks.c
index 487f26d2c4..2a8f106510 100644
--- a/libs/libcurl/src/socks.c
+++ b/libs/libcurl/src/socks.c
@@ -339,8 +339,8 @@ static CURLproxycode do_SOCKS4(struct Curl_cfilter *cf,
if(dns) {
#ifdef CURLRES_ASYNCH
- data->state.async.dns = dns;
- data->state.async.done = TRUE;
+ conn->resolve_async.dns = dns;
+ conn->resolve_async.done = TRUE;
#endif
infof(data, "Hostname '%s' was found", sx->hostname);
sxstate(sx, data, CONNECT_RESOLVED);
@@ -402,8 +402,11 @@ CONNECT_REQ_INIT:
socksreq[8] = 0; /* ensure empty userid is NUL-terminated */
if(sx->proxy_user) {
size_t plen = strlen(sx->proxy_user);
- if(plen >= (size_t)data->set.buffer_size - 8) {
- failf(data, "Too long SOCKS proxy user name, can't use");
+ if(plen > 255) {
+ /* there is no real size limit to this field in the protocol, but
+ SOCKS5 limits the proxy user field to 255 bytes and it seems likely
+ that a longer field is either a mistake or malicious input */
+ failf(data, "Too long SOCKS proxy user name");
return CURLPX_LONG_USER;
}
/* copy the proxy name WITH trailing zero */
@@ -426,7 +429,8 @@ CONNECT_REQ_INIT:
socksreq[7] = 1;
/* append hostname */
hostnamelen = strlen(sx->hostname) + 1; /* length including NUL */
- if(hostnamelen <= 255)
+ if((hostnamelen <= 255) &&
+ (packetsize + hostnamelen < data->set.buffer_size))
strcpy((char *)socksreq + packetsize, sx->hostname);
else {
failf(data, "SOCKS4: too long host name");
@@ -802,8 +806,8 @@ CONNECT_REQ_INIT:
if(dns) {
#ifdef CURLRES_ASYNCH
- data->state.async.dns = dns;
- data->state.async.done = TRUE;
+ conn->resolve_async.dns = dns;
+ conn->resolve_async.done = TRUE;
#endif
infof(data, "SOCKS5: hostname '%s' found", sx->hostname);
}
@@ -819,10 +823,19 @@ CONNECT_REQ_INIT:
/* FALLTHROUGH */
CONNECT_RESOLVED:
case CONNECT_RESOLVED: {
- char dest[MAX_IPADR_LEN] = "unknown"; /* printable address */
+ char dest[MAX_IPADR_LEN]; /* printable address */
struct Curl_addrinfo *hp = NULL;
if(dns)
hp = dns->addr;
+#ifdef ENABLE_IPV6
+ if(data->set.ipver != CURL_IPRESOLVE_WHATEVER) {
+ int wanted_family = data->set.ipver == CURL_IPRESOLVE_V4 ?
+ AF_INET : AF_INET6;
+ /* scan for the first proper address */
+ while(hp && (hp->ai_family != wanted_family))
+ hp = hp->ai_next;
+ }
+#endif
if(!hp) {
failf(data, "Failed to resolve \"%s\" for SOCKS5 connect.",
sx->hostname);
@@ -1119,7 +1132,7 @@ static CURLcode socks_proxy_cf_connect(struct Curl_cfilter *cf,
return result;
if(!sx) {
- sx = calloc(sizeof(*sx), 1);
+ sx = calloc(1, sizeof(*sx));
if(!sx)
return CURLE_OUT_OF_MEMORY;
cf->ctx = sx;
@@ -1157,32 +1170,29 @@ static CURLcode socks_proxy_cf_connect(struct Curl_cfilter *cf,
return result;
}
-static int socks_cf_get_select_socks(struct Curl_cfilter *cf,
+static void socks_cf_adjust_pollset(struct Curl_cfilter *cf,
struct Curl_easy *data,
- curl_socket_t *socks)
+ struct easy_pollset *ps)
{
struct socks_state *sx = cf->ctx;
- int fds;
- fds = cf->next->cft->get_select_socks(cf->next, data, socks);
- if(!fds && cf->next->connected && !cf->connected && sx) {
+ if(!cf->connected && sx) {
/* If we are not connected, the filter below is and has nothing
* to wait on, we determine what to wait for. */
- socks[0] = Curl_conn_cf_get_socket(cf, data);
+ curl_socket_t sock = Curl_conn_cf_get_socket(cf, data);
switch(sx->state) {
case CONNECT_RESOLVING:
case CONNECT_SOCKS_READ:
case CONNECT_AUTH_READ:
case CONNECT_REQ_READ:
case CONNECT_REQ_READ_MORE:
- fds = GETSOCK_READSOCK(0);
+ Curl_pollset_set_in_only(data, ps, sock);
break;
default:
- fds = GETSOCK_WRITESOCK(0);
+ Curl_pollset_set_out_only(data, ps, sock);
break;
}
}
- return fds;
}
static void socks_proxy_cf_close(struct Curl_cfilter *cf,
@@ -1227,7 +1237,7 @@ struct Curl_cftype Curl_cft_socks_proxy = {
socks_proxy_cf_connect,
socks_proxy_cf_close,
socks_cf_get_host,
- socks_cf_get_select_socks,
+ socks_cf_adjust_pollset,
Curl_cf_def_data_pending,
Curl_cf_def_send,
Curl_cf_def_recv,
diff --git a/libs/libcurl/src/strdup.c b/libs/libcurl/src/strdup.c
index 1008d94fe5..ee341ef27e 100644
--- a/libs/libcurl/src/strdup.c
+++ b/libs/libcurl/src/strdup.c
@@ -26,7 +26,7 @@
#include <curl/curl.h>
-#ifdef WIN32
+#ifdef _WIN32
#include <wchar.h>
#endif
@@ -56,7 +56,7 @@ char *Curl_strdup(const char *str)
}
#endif
-#ifdef WIN32
+#ifdef _WIN32
/***************************************************************************
*
* Curl_wcsdup(source)
@@ -101,6 +101,30 @@ void *Curl_memdup(const void *src, size_t length)
/***************************************************************************
*
+ * Curl_strndup(source, length)
+ *
+ * Copies the 'source' string to a newly allocated buffer (that is returned).
+ * Copies not more than 'length' bytes (up to a null terminator) then adds a
+ * null terminator.
+ *
+ * Returns the new pointer or NULL on failure.
+ *
+ ***************************************************************************/
+void *Curl_strndup(const char *src, size_t length)
+{
+ char *buf = memchr(src, '\0', length);
+ if(buf)
+ length = buf - src;
+ buf = malloc(length + 1);
+ if(!buf)
+ return NULL;
+ memcpy(buf, src, length);
+ buf[length] = 0;
+ return buf;
+}
+
+/***************************************************************************
+ *
* Curl_saferealloc(ptr, size)
*
* Does a normal realloc(), but will free the data pointer if the realloc
diff --git a/libs/libcurl/src/strdup.h b/libs/libcurl/src/strdup.h
index 8bf1c9a8d3..7c7862db45 100644
--- a/libs/libcurl/src/strdup.h
+++ b/libs/libcurl/src/strdup.h
@@ -28,10 +28,11 @@
#ifndef HAVE_STRDUP
char *Curl_strdup(const char *str);
#endif
-#ifdef WIN32
+#ifdef _WIN32
wchar_t* Curl_wcsdup(const wchar_t* src);
#endif
void *Curl_memdup(const void *src, size_t buffer_length);
void *Curl_saferealloc(void *ptr, size_t size);
+void *Curl_strndup(const char *src, size_t length);
#endif /* HEADER_CURL_STRDUP_H */
diff --git a/libs/libcurl/src/strerror.c b/libs/libcurl/src/strerror.c
index 2d64a277eb..57105759d2 100644
--- a/libs/libcurl/src/strerror.c
+++ b/libs/libcurl/src/strerror.c
@@ -48,7 +48,7 @@
#include "curl_memory.h"
#include "memdebug.h"
-#if defined(WIN32) || defined(_WIN32_WCE)
+#if defined(_WIN32) || defined(_WIN32_WCE)
#define PRESERVE_WINDOWS_ERROR_CODE
#endif
@@ -762,7 +762,7 @@ get_winsock_error (int err, char *buf, size_t len)
}
#endif /* USE_WINSOCK */
-#if defined(WIN32) || defined(_WIN32_WCE)
+#if defined(_WIN32) || defined(_WIN32_WCE)
/* This is a helper function for Curl_strerror that converts Windows API error
* codes (GetLastError) to error messages.
* Returns NULL if no error message was found for error code.
@@ -804,7 +804,7 @@ get_winapi_error(int err, char *buf, size_t buflen)
return (*buf ? buf : NULL);
}
-#endif /* WIN32 || _WIN32_WCE */
+#endif /* _WIN32 || _WIN32_WCE */
/*
* Our thread-safe and smart strerror() replacement.
@@ -837,15 +837,15 @@ const char *Curl_strerror(int err, char *buf, size_t buflen)
if(!buflen)
return NULL;
-#ifndef WIN32
+#ifndef _WIN32
DEBUGASSERT(err >= 0);
#endif
max = buflen - 1;
*buf = '\0';
-#if defined(WIN32) || defined(_WIN32_WCE)
-#if defined(WIN32)
+#if defined(_WIN32) || defined(_WIN32_WCE)
+#if defined(_WIN32)
/* 'sys_nerr' is the maximum errno number, it is not widely portable */
if(err >= 0 && err < sys_nerr)
strncpy(buf, sys_errlist[err], max);
@@ -923,7 +923,7 @@ const char *Curl_strerror(int err, char *buf, size_t buflen)
* Curl_winapi_strerror:
* Variant of Curl_strerror if the error code is definitely Windows API.
*/
-#if defined(WIN32) || defined(_WIN32_WCE)
+#if defined(_WIN32) || defined(_WIN32_WCE)
const char *Curl_winapi_strerror(DWORD err, char *buf, size_t buflen)
{
#ifdef PRESERVE_WINDOWS_ERROR_CODE
@@ -958,7 +958,7 @@ const char *Curl_winapi_strerror(DWORD err, char *buf, size_t buflen)
return buf;
}
-#endif /* WIN32 || _WIN32_WCE */
+#endif /* _WIN32 || _WIN32_WCE */
#ifdef USE_WINDOWS_SSPI
/*
@@ -986,6 +986,10 @@ const char *Curl_sspi_strerror(int err, char *buf, size_t buflen)
break;
#define SEC2TXT(sec) case sec: txt = #sec; break
SEC2TXT(CRYPT_E_REVOKED);
+ SEC2TXT(CRYPT_E_NO_REVOCATION_DLL);
+ SEC2TXT(CRYPT_E_NO_REVOCATION_CHECK);
+ SEC2TXT(CRYPT_E_REVOCATION_OFFLINE);
+ SEC2TXT(CRYPT_E_NOT_IN_REVOCATION_DATABASE);
SEC2TXT(SEC_E_ALGORITHM_MISMATCH);
SEC2TXT(SEC_E_BAD_BINDINGS);
SEC2TXT(SEC_E_BAD_PKGID);
diff --git a/libs/libcurl/src/strerror.h b/libs/libcurl/src/strerror.h
index e0fd369d47..1fd423fc17 100644
--- a/libs/libcurl/src/strerror.h
+++ b/libs/libcurl/src/strerror.h
@@ -29,7 +29,7 @@
#define STRERROR_LEN 256 /* a suitable length */
const char *Curl_strerror(int err, char *buf, size_t buflen);
-#if defined(WIN32) || defined(_WIN32_WCE)
+#if defined(_WIN32) || defined(_WIN32_WCE)
const char *Curl_winapi_strerror(DWORD err, char *buf, size_t buflen);
#endif
#ifdef USE_WINDOWS_SSPI
diff --git a/libs/libcurl/src/system_win32.c b/libs/libcurl/src/system_win32.c
index f4a03cfea4..10d7fa9c27 100644
--- a/libs/libcurl/src/system_win32.c
+++ b/libs/libcurl/src/system_win32.c
@@ -24,7 +24,7 @@
#include "curl_setup.h"
-#if defined(WIN32)
+#if defined(_WIN32)
#include <curl/curl.h>
#include "system_win32.h"
@@ -238,4 +238,4 @@ HMODULE Curl_load_library(LPCTSTR filename)
#endif
}
-#endif /* WIN32 */
+#endif /* _WIN32 */
diff --git a/libs/libcurl/src/system_win32.h b/libs/libcurl/src/system_win32.h
index 33169a129d..f14ae8e4e5 100644
--- a/libs/libcurl/src/system_win32.h
+++ b/libs/libcurl/src/system_win32.h
@@ -26,7 +26,7 @@
#include "curl_setup.h"
-#if defined(WIN32)
+#if defined(_WIN32)
extern LARGE_INTEGER Curl_freq;
extern bool Curl_isVistaOrGreater;
@@ -42,8 +42,8 @@ extern IF_NAMETOINDEX_FN Curl_if_nametoindex;
/* This is used to dynamically load DLLs */
HMODULE Curl_load_library(LPCTSTR filename);
-#else /* WIN32 */
+#else /* _WIN32 */
#define Curl_win32_init(x) CURLE_OK
-#endif /* !WIN32 */
+#endif /* !_WIN32 */
#endif /* HEADER_CURL_SYSTEM_WIN32_H */
diff --git a/libs/libcurl/src/tftp.c b/libs/libcurl/src/tftp.c
index 028fc2af6d..9f0877cbf2 100644
--- a/libs/libcurl/src/tftp.c
+++ b/libs/libcurl/src/tftp.c
@@ -70,8 +70,6 @@
/* RFC2348 allows the block size to be negotiated */
#define TFTP_BLKSIZE_DEFAULT 512
-#define TFTP_BLKSIZE_MIN 8
-#define TFTP_BLKSIZE_MAX 65464
#define TFTP_OPTION_BLKSIZE "blksize"
/* from RFC2349: */
@@ -978,11 +976,9 @@ static CURLcode tftp_connect(struct Curl_easy *data, bool *done)
return CURLE_OUT_OF_MEMORY;
/* alloc pkt buffers based on specified blksize */
- if(data->set.tftp_blksize) {
+ if(data->set.tftp_blksize)
+ /* range checked when set */
blksize = (int)data->set.tftp_blksize;
- if(blksize > TFTP_BLKSIZE_MAX || blksize < TFTP_BLKSIZE_MIN)
- return CURLE_TFTP_ILLEGAL;
- }
need_blksize = blksize;
/* default size is the fallback when no OACK is received */
@@ -1107,7 +1103,6 @@ static CURLcode tftp_receive_packet(struct Curl_easy *data)
CURLcode result = CURLE_OK;
struct connectdata *conn = data->conn;
struct tftp_state_data *state = conn->proto.tftpc;
- struct SingleRequest *k = &data->req;
/* Receive the packet */
fromlen = sizeof(fromaddr);
@@ -1141,11 +1136,6 @@ static CURLcode tftp_receive_packet(struct Curl_easy *data)
result = Curl_client_write(data, CLIENTWRITE_BODY,
(char *)state->rpacket.data + 4,
state->rbytes-4);
- if(!result) {
- k->bytecount += state->rbytes-4;
- result = Curl_pgrsSetDownloadCounter(data,
- (curl_off_t) k->bytecount);
- }
if(result) {
tftp_state_machine(state, TFTP_EVENT_ERROR);
return result;
diff --git a/libs/libcurl/src/tftp.h b/libs/libcurl/src/tftp.h
index acdde26a68..47d0db76b6 100644
--- a/libs/libcurl/src/tftp.h
+++ b/libs/libcurl/src/tftp.h
@@ -25,6 +25,9 @@
***************************************************************************/
#ifndef CURL_DISABLE_TFTP
extern const struct Curl_handler Curl_handler_tftp;
+
+#define TFTP_BLKSIZE_MIN 8
+#define TFTP_BLKSIZE_MAX 65464
#endif
#endif /* HEADER_CURL_TFTP_H */
diff --git a/libs/libcurl/src/timediff.c b/libs/libcurl/src/timediff.c
index c044b96680..a98d5782c1 100644
--- a/libs/libcurl/src/timediff.c
+++ b/libs/libcurl/src/timediff.c
@@ -53,7 +53,7 @@ struct timeval *curlx_mstotv(struct timeval *tv, timediff_t ms)
#endif
tv->tv_sec = (time_t)tv_sec;
tv->tv_usec = (suseconds_t)tv_usec;
-#elif defined(WIN32) /* maybe also others in the future */
+#elif defined(_WIN32) /* maybe also others in the future */
#if TIMEDIFF_T_MAX > LONG_MAX
/* tv_sec overflow check on Windows there we know it is long */
if(tv_sec > LONG_MAX)
diff --git a/libs/libcurl/src/timeval.c b/libs/libcurl/src/timeval.c
index 8989c5b8b9..a15e138e25 100644
--- a/libs/libcurl/src/timeval.c
+++ b/libs/libcurl/src/timeval.c
@@ -24,11 +24,10 @@
#include "timeval.h"
-#if defined(WIN32) && !defined(MSDOS)
+#if defined(_WIN32)
-/* set in win32_init() */
-extern LARGE_INTEGER Curl_freq;
-extern bool Curl_isVistaOrGreater;
+#include <curl/curl.h>
+#include "system_win32.h"
/* In case of bug fix this function has a counterpart in tool_util.c */
struct curltime Curl_now(void)
diff --git a/libs/libcurl/src/transfer.c b/libs/libcurl/src/transfer.c
index 44e5f03cea..1fe0bbae06 100644
--- a/libs/libcurl/src/transfer.c
+++ b/libs/libcurl/src/transfer.c
@@ -163,9 +163,9 @@ CURLcode Curl_fillreadbuffer(struct Curl_easy *data, size_t bytes,
{
size_t buffersize = bytes;
size_t nread;
-
curl_read_callback readfunc = NULL;
void *extra_data = NULL;
+ int eof_index = 0;
#ifndef CURL_DISABLE_HTTP
if(data->state.trailers_state == TRAILERS_INITIALIZED) {
@@ -223,6 +223,7 @@ CURLcode Curl_fillreadbuffer(struct Curl_easy *data, size_t bytes,
*/
readfunc = trailers_read;
extra_data = (void *)data;
+ eof_index = 1;
}
else
#endif
@@ -231,10 +232,15 @@ CURLcode Curl_fillreadbuffer(struct Curl_easy *data, size_t bytes,
extra_data = data->state.in;
}
- Curl_set_in_callback(data, true);
- nread = readfunc(data->req.upload_fromhere, 1,
- buffersize, extra_data);
- Curl_set_in_callback(data, false);
+ if(!data->req.fread_eof[eof_index]) {
+ Curl_set_in_callback(data, true);
+ nread = readfunc(data->req.upload_fromhere, 1, buffersize, extra_data);
+ Curl_set_in_callback(data, false);
+ /* make sure the callback is not called again after EOF */
+ data->req.fread_eof[eof_index] = !nread;
+ }
+ else
+ nread = 0;
if(nread == CURL_READFUNC_ABORT) {
failf(data, "operation aborted by callback");
@@ -422,16 +428,15 @@ static CURLcode readwrite_data(struct Curl_easy *data,
bool *comeback)
{
CURLcode result = CURLE_OK;
- ssize_t nread; /* number of bytes read */
- size_t excess = 0; /* excess bytes read */
- bool readmore = FALSE; /* used by RTP to signal for more data */
+ char *buf;
+ size_t blen;
+ size_t consumed;
int maxloops = 100;
curl_off_t max_recv = data->set.max_recv_speed?
data->set.max_recv_speed : CURL_OFF_T_MAX;
- char *buf = data->state.buffer;
bool data_eof_handled = FALSE;
- DEBUGASSERT(buf);
+ DEBUGASSERT(data->state.buffer);
*done = FALSE;
*comeback = FALSE;
@@ -439,8 +444,7 @@ static CURLcode readwrite_data(struct Curl_easy *data,
read or we get a CURLE_AGAIN */
do {
bool is_empty_data = FALSE;
- size_t buffersize = data->set.buffer_size;
- size_t bytestoread = buffersize;
+ size_t bytestoread = data->set.buffer_size;
/* For HTTP/2 and HTTP/3, read data without caring about the content
length. This is safe because body in HTTP/2 is always segmented
thanks to its framing layer. Meanwhile, we have to call Curl_read
@@ -449,31 +453,38 @@ static CURLcode readwrite_data(struct Curl_easy *data,
bool is_http3 = Curl_conn_is_http3(data, conn, FIRSTSOCKET);
data_eof_handled = is_http3 || Curl_conn_is_http2(data, conn, FIRSTSOCKET);
- if(!data_eof_handled && k->size != -1 && !k->header) {
- /* make sure we don't read too much */
+ /* Each loop iteration starts with a fresh buffer and handles
+ * all data read into it. */
+ buf = data->state.buffer;
+ blen = 0;
+
+ /* If we are reading BODY data and the connection does NOT handle EOF
+ * and we know the size of the BODY data, limit the read amount */
+ if(!k->header && !data_eof_handled && k->size != -1) {
curl_off_t totalleft = k->size - k->bytecount;
- if(totalleft < (curl_off_t)bytestoread)
+ if(totalleft <= 0)
+ bytestoread = 0;
+ else if(totalleft < (curl_off_t)bytestoread)
bytestoread = (size_t)totalleft;
}
if(bytestoread) {
/* receive data from the network! */
+ ssize_t nread; /* number of bytes read */
result = Curl_read(data, conn->sockfd, buf, bytestoread, &nread);
-
- /* read would've blocked */
if(CURLE_AGAIN == result) {
result = CURLE_OK;
break; /* get out of loop */
}
-
- if(result>0)
+ else if(result)
goto out;
+ DEBUGASSERT(nread >= 0);
+ blen = (size_t)nread;
}
else {
/* read nothing but since we wanted nothing we consider this an OK
situation to proceed from */
DEBUGF(infof(data, "readwrite_data: we're done"));
- nread = 0;
}
if(!k->bytecount) {
@@ -485,12 +496,17 @@ static CURLcode readwrite_data(struct Curl_easy *data,
*didwhat |= KEEP_RECV;
/* indicates data of zero size, i.e. empty file */
- is_empty_data = ((nread == 0) && (k->bodywrites == 0)) ? TRUE : FALSE;
-
- if(0 < nread || is_empty_data) {
- buf[nread] = 0;
+ is_empty_data = ((blen == 0) && (k->bodywrites == 0)) ? TRUE : FALSE;
+
+ if(0 < blen || is_empty_data) {
+ /* data->state.buffer is allocated 1 byte larger than
+ * data->set.buffer_size admits. *wink* */
+ /* TODO: we should really not rely on this being 0-terminated, since
+ * the actual data read might contain 0s. */
+ buf[blen] = 0;
}
- if(!nread) {
+
+ if(!blen) {
/* if we receive 0 or less here, either the data transfer is done or the
server closed the connection and we bail out from this! */
if(data_eof_handled)
@@ -502,48 +518,70 @@ static CURLcode readwrite_data(struct Curl_easy *data,
break;
}
- /* Default buffer to use when we write the buffer, it may be changed
- in the flow below before the actual storing is done. */
- k->str = buf;
-
if(conn->handler->readwrite) {
- result = conn->handler->readwrite(data, conn, &nread, &readmore);
+ bool readmore = FALSE; /* indicates data is incomplete, need more */
+ consumed = 0;
+ result = conn->handler->readwrite(data, conn, buf, blen,
+ &consumed, &readmore);
if(result)
goto out;
if(readmore)
break;
+ buf += consumed;
+ blen -= consumed;
+ if(k->download_done) {
+ /* We've stopped dealing with input, get out of the do-while loop */
+ if(blen > 0) {
+ infof(data,
+ "Excess found:"
+ " excess = %zu"
+ " url = %s (zero-length body)",
+ blen, data->state.up.path);
+ }
+
+ /* we make sure that this socket isn't read more now */
+ k->keepon &= ~KEEP_RECV;
+ break;
+ }
}
#ifndef CURL_DISABLE_HTTP
/* Since this is a two-state thing, we check if we are parsing
headers at the moment or not. */
if(k->header) {
- /* we are in parse-the-header-mode */
- bool stop_reading = FALSE;
- result = Curl_http_readwrite_headers(data, conn, &nread, &stop_reading);
+ consumed = 0;
+ result = Curl_http_readwrite_headers(data, conn, buf, blen, &consumed);
if(result)
goto out;
+ buf += consumed;
+ blen -= consumed;
if(conn->handler->readwrite &&
- (k->maxdownload <= 0 && nread > 0)) {
- result = conn->handler->readwrite(data, conn, &nread, &readmore);
+ (k->maxdownload <= 0 && blen > 0)) {
+ bool readmore = FALSE; /* indicates data is incomplete, need more */
+ consumed = 0;
+ result = conn->handler->readwrite(data, conn, buf, blen,
+ &consumed, &readmore);
if(result)
goto out;
if(readmore)
break;
+ buf += consumed;
+ blen -= consumed;
}
- if(stop_reading) {
+ if(k->download_done) {
/* We've stopped dealing with input, get out of the do-while loop */
-
- if(nread > 0) {
+ if(blen > 0) {
infof(data,
"Excess found:"
- " excess = %zd"
+ " excess = %zu"
" url = %s (zero-length body)",
- nread, data->state.up.path);
+ blen, data->state.up.path);
}
+ /* we make sure that this socket isn't read more now */
+ k->keepon &= ~KEEP_RECV;
break;
}
}
@@ -553,11 +591,13 @@ static CURLcode readwrite_data(struct Curl_easy *data,
/* This is not an 'else if' since it may be a rest from the header
parsing, where the beginning of the buffer is headers and the end
is non-headers. */
- if(!k->header && (nread > 0 || is_empty_data)) {
+ if(!k->header && (blen > 0 || is_empty_data)) {
- if(data->req.no_body) {
+ if(data->req.no_body && blen > 0) {
/* data arrives although we want none, bail out */
streamclose(conn, "ignoring body");
+ DEBUGF(infof(data, "did not want a BODY, but seeing %zu bytes",
+ blen));
*done = TRUE;
result = CURLE_WEIRD_SERVER_REPLY;
goto out;
@@ -576,34 +616,18 @@ static CURLcode readwrite_data(struct Curl_easy *data,
} /* this is the first time we write a body part */
#endif /* CURL_DISABLE_HTTP */
- k->bodywrites++;
-
- /* pass data to the debug function before it gets "dechunked" */
- if(data->set.verbose) {
- if(k->badheader) {
- Curl_debug(data, CURLINFO_DATA_IN,
- Curl_dyn_ptr(&data->state.headerb),
- Curl_dyn_len(&data->state.headerb));
- if(k->badheader == HEADER_PARTHEADER)
- Curl_debug(data, CURLINFO_DATA_IN,
- k->str, (size_t)nread);
- }
- else
- Curl_debug(data, CURLINFO_DATA_IN,
- k->str, (size_t)nread);
- }
-
#ifndef CURL_DISABLE_HTTP
if(k->chunk) {
/*
* Here comes a chunked transfer flying and we need to decode this
* properly. While the name says read, this function both reads
- * and writes away the data. The returned 'nread' holds the number
- * of actual data it wrote to the client.
+ * and writes away the data.
*/
CURLcode extra;
- CHUNKcode res =
- Curl_httpchunk_read(data, k->str, nread, &nread, &extra);
+ CHUNKcode res;
+
+ consumed = 0;
+ res = Curl_httpchunk_read(data, buf, blen, &consumed, &extra);
if(CHUNKE_OK < res) {
if(CHUNKE_PASSTHRU_ERROR == res) {
@@ -615,9 +639,14 @@ static CURLcode readwrite_data(struct Curl_easy *data,
result = CURLE_RECV_ERROR;
goto out;
}
- if(CHUNKE_STOP == res) {
+
+ buf += consumed;
+ blen -= consumed;
+ if(CHUNKE_STOP == res) {
/* we're done reading chunks! */
k->keepon &= ~KEEP_RECV; /* read no more */
+ /* chunks read successfully, download is complete */
+ k->download_done = TRUE;
/* N number of bytes at the end of the str buffer that weren't
written to the client. */
@@ -631,117 +660,57 @@ static CURLcode readwrite_data(struct Curl_easy *data,
}
#endif /* CURL_DISABLE_HTTP */
- /* Account for body content stored in the header buffer */
- if((k->badheader == HEADER_PARTHEADER) && !k->ignorebody) {
- size_t headlen = Curl_dyn_len(&data->state.headerb);
- DEBUGF(infof(data, "Increasing bytecount by %zu", headlen));
- k->bytecount += headlen;
- }
-
- if((-1 != k->maxdownload) &&
- (k->bytecount + nread >= k->maxdownload)) {
+ max_recv -= blen;
- excess = (size_t)(k->bytecount + nread - k->maxdownload);
- if(excess > 0 && !k->ignorebody) {
- infof(data,
- "Excess found in a read:"
- " excess = %zu"
- ", size = %" CURL_FORMAT_CURL_OFF_T
- ", maxdownload = %" CURL_FORMAT_CURL_OFF_T
- ", bytecount = %" CURL_FORMAT_CURL_OFF_T,
- excess, k->size, k->maxdownload, k->bytecount);
- connclose(conn, "excess found in a read");
- }
-
- nread = (ssize_t) (k->maxdownload - k->bytecount);
- if(nread < 0) /* this should be unusual */
- nread = 0;
-
- /* HTTP/3 over QUIC should keep reading until QUIC connection
- is closed. In contrast to HTTP/2 which can stop reading
- from TCP connection, HTTP/3 over QUIC needs ACK from server
- to ensure stream closure. It should keep reading. */
- if(!is_http3) {
- k->keepon &= ~KEEP_RECV; /* we're done reading */
- }
- }
-
- k->bytecount += nread;
- max_recv -= nread;
-
- result = Curl_pgrsSetDownloadCounter(data, k->bytecount);
- if(result)
- goto out;
-
- if(!k->chunk && (nread || k->badheader || is_empty_data)) {
+ if(!k->chunk && (blen || k->badheader || is_empty_data)) {
/* If this is chunky transfer, it was already written */
- if(k->badheader && !k->ignorebody) {
+ if(k->badheader) {
/* we parsed a piece of data wrongly assuming it was a header
and now we output it as body instead */
size_t headlen = Curl_dyn_len(&data->state.headerb);
/* Don't let excess data pollute body writes */
- if(k->maxdownload == -1 || (curl_off_t)headlen <= k->maxdownload)
- result = Curl_client_write(data, CLIENTWRITE_BODY,
- Curl_dyn_ptr(&data->state.headerb),
- headlen);
- else
- result = Curl_client_write(data, CLIENTWRITE_BODY,
- Curl_dyn_ptr(&data->state.headerb),
- (size_t)k->maxdownload);
+ if(k->maxdownload != -1 && (curl_off_t)headlen > k->maxdownload)
+ headlen = (size_t)k->maxdownload;
+ result = Curl_client_write(data, CLIENTWRITE_BODY,
+ Curl_dyn_ptr(&data->state.headerb),
+ headlen);
if(result)
goto out;
}
- if(k->badheader < HEADER_ALLBAD) {
- /* This switch handles various content encodings. If there's an
- error here, be sure to check over the almost identical code
- in http_chunks.c.
- Make sure that ALL_CONTENT_ENCODINGS contains all the
- encodings handled here. */
- if(!k->ignorebody && nread) {
+
+ if(blen) {
#ifndef CURL_DISABLE_POP3
- if(conn->handler->protocol & PROTO_FAMILY_POP3)
- result = Curl_pop3_write(data, k->str, nread);
- else
-#endif /* CURL_DISABLE_POP3 */
- result = Curl_client_write(data, CLIENTWRITE_BODY, k->str,
- nread);
+ if(conn->handler->protocol & PROTO_FAMILY_POP3) {
+ result = k->ignorebody? CURLE_OK :
+ Curl_pop3_write(data, buf, blen);
}
+ else
+#endif /* CURL_DISABLE_POP3 */
+ result = Curl_client_write(data, CLIENTWRITE_BODY, buf, blen);
}
- k->badheader = HEADER_NORMAL; /* taken care of now */
+ k->badheader = FALSE; /* taken care of now */
if(result)
goto out;
}
- } /* if(!header and data to read) */
-
- if(conn->handler->readwrite && excess) {
- /* Parse the excess data */
- k->str += nread;
-
- if(&k->str[excess] > &buf[data->set.buffer_size]) {
- /* the excess amount was too excessive(!), make sure
- it doesn't read out of buffer */
- excess = &buf[data->set.buffer_size] - k->str;
+ if(k->download_done && !is_http3) {
+ /* HTTP/3 over QUIC should keep reading until QUIC connection
+ is closed. In contrast to HTTP/2 which can stop reading
+ from TCP connection, HTTP/3 over QUIC needs ACK from server
+ to ensure stream closure. It should keep reading. */
+ k->keepon &= ~KEEP_RECV; /* we're done reading */
}
- nread = (ssize_t)excess;
-
- result = conn->handler->readwrite(data, conn, &nread, &readmore);
- if(result)
- goto out;
-
- if(readmore)
- k->keepon |= KEEP_RECV; /* we're not done reading */
- break;
- }
+ } /* if(!header and data to read) */
if(is_empty_data) {
/* if we received nothing, the server closed the connection and we
are done */
k->keepon &= ~KEEP_RECV;
+ k->download_done = TRUE;
}
if((k->keepon & KEEP_RECV_PAUSE) || !(k->keepon & KEEP_RECV)) {
@@ -764,6 +733,7 @@ static CURLcode readwrite_data(struct Curl_easy *data,
on from our side, we need to stop that immediately. */
infof(data, "we are done reading and this is set to close, stop send");
k->keepon &= ~KEEP_SEND; /* no writing anymore either */
+ k->keepon &= ~KEEP_SEND_PAUSE; /* no pausing anymore either */
}
out:
@@ -783,7 +753,7 @@ CURLcode Curl_done_sending(struct Curl_easy *data,
return CURLE_OK;
}
-#if defined(WIN32) && defined(USE_WINSOCK)
+#if defined(_WIN32) && defined(USE_WINSOCK)
#ifndef SIO_IDEAL_SEND_BACKLOG_QUERY
#define SIO_IDEAL_SEND_BACKLOG_QUERY 0x4004747B
#endif
@@ -977,7 +947,7 @@ static CURLcode readwrite_upload(struct Curl_easy *data,
if(result)
return result;
-#if defined(WIN32) && defined(USE_WINSOCK)
+#if defined(_WIN32) && defined(USE_WINSOCK)
{
struct curltime n = Curl_now();
if(Curl_timediff(n, k->last_sndbuf_update) > 1000) {
@@ -1430,8 +1400,7 @@ CURLcode Curl_pretransfer(struct Curl_easy *data)
return CURLE_OUT_OF_MEMORY;
}
wc = data->wildcard;
- if((wc->state < CURLWC_INIT) ||
- (wc->state >= CURLWC_CLEAN)) {
+ if(wc->state < CURLWC_INIT) {
if(wc->ftpwc)
wc->dtor(wc->ftpwc);
Curl_safefree(wc->pattern);
@@ -1635,7 +1604,7 @@ CURLcode Curl_follow(struct Curl_easy *data,
return Curl_uc_to_curlcode(uc);
}
- p = Curl_builtin_scheme(scheme, CURL_ZERO_TERMINATED);
+ p = Curl_get_scheme_handler(scheme);
if(p && (p->protocol != data->info.conn_protocol)) {
infof(data, "Clear auth, redirects scheme from %s to %s",
data->info.conn_scheme, scheme);
diff --git a/libs/libcurl/src/url.c b/libs/libcurl/src/url.c
index 1746a51ca9..243a603c8b 100644
--- a/libs/libcurl/src/url.c
+++ b/libs/libcurl/src/url.c
@@ -168,130 +168,6 @@ static curl_prot_t get_protocol_family(const struct Curl_handler *h)
return h->family;
}
-
-/*
- * Protocol table. Schemes (roughly) in 2019 popularity order:
- *
- * HTTPS, HTTP, FTP, FTPS, SFTP, FILE, SCP, SMTP, LDAP, IMAPS, TELNET, IMAP,
- * LDAPS, SMTPS, TFTP, SMB, POP3, GOPHER POP3S, RTSP, RTMP, SMBS, DICT
- */
-static const struct Curl_handler * const protocols[] = {
-
-#if defined(USE_SSL) && !defined(CURL_DISABLE_HTTP)
- &Curl_handler_https,
-#endif
-
-#ifndef CURL_DISABLE_HTTP
- &Curl_handler_http,
-#endif
-
-#ifdef USE_WEBSOCKETS
-#if defined(USE_SSL) && !defined(CURL_DISABLE_HTTP)
- &Curl_handler_wss,
-#endif
-
-#ifndef CURL_DISABLE_HTTP
- &Curl_handler_ws,
-#endif
-#endif
-
-#ifndef CURL_DISABLE_FTP
- &Curl_handler_ftp,
-#endif
-
-#if defined(USE_SSL) && !defined(CURL_DISABLE_FTP)
- &Curl_handler_ftps,
-#endif
-
-#if defined(USE_SSH)
- &Curl_handler_sftp,
-#endif
-
-#ifndef CURL_DISABLE_FILE
- &Curl_handler_file,
-#endif
-
-#if defined(USE_SSH) && !defined(USE_WOLFSSH)
- &Curl_handler_scp,
-#endif
-
-#ifndef CURL_DISABLE_SMTP
- &Curl_handler_smtp,
-#ifdef USE_SSL
- &Curl_handler_smtps,
-#endif
-#endif
-
-#ifndef CURL_DISABLE_LDAP
- &Curl_handler_ldap,
-#if !defined(CURL_DISABLE_LDAPS) && \
- ((defined(USE_OPENLDAP) && defined(USE_SSL)) || \
- (!defined(USE_OPENLDAP) && defined(HAVE_LDAP_SSL)))
- &Curl_handler_ldaps,
-#endif
-#endif
-
-#ifndef CURL_DISABLE_IMAP
- &Curl_handler_imap,
-#ifdef USE_SSL
- &Curl_handler_imaps,
-#endif
-#endif
-
-#ifndef CURL_DISABLE_TELNET
- &Curl_handler_telnet,
-#endif
-
-#ifndef CURL_DISABLE_TFTP
- &Curl_handler_tftp,
-#endif
-
-#ifndef CURL_DISABLE_POP3
- &Curl_handler_pop3,
-#ifdef USE_SSL
- &Curl_handler_pop3s,
-#endif
-#endif
-
-#if !defined(CURL_DISABLE_SMB) && defined(USE_CURL_NTLM_CORE) && \
- (SIZEOF_CURL_OFF_T > 4)
- &Curl_handler_smb,
-#ifdef USE_SSL
- &Curl_handler_smbs,
-#endif
-#endif
-
-#ifndef CURL_DISABLE_RTSP
- &Curl_handler_rtsp,
-#endif
-
-#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
- &Curl_handler_rtmp,
- &Curl_handler_rtmpt,
- &Curl_handler_rtmpe,
- &Curl_handler_rtmpte,
- &Curl_handler_rtmps,
- &Curl_handler_rtmpts,
-#endif
-
-#ifndef CURL_DISABLE_DICT
- &Curl_handler_dict,
-#endif
-
- (struct Curl_handler *) NULL
-};
-
void Curl_freeset(struct Curl_easy *data)
{
/* Free all dynamic strings stored in the data->set substructure. */
@@ -320,8 +196,8 @@ void Curl_freeset(struct Curl_easy *data)
Curl_mime_cleanpart(&data->set.mimepost);
#ifndef CURL_DISABLE_COOKIES
- curl_slist_free_all(data->set.cookielist);
- data->set.cookielist = NULL;
+ curl_slist_free_all(data->state.cookielist);
+ data->state.cookielist = NULL;
#endif
}
@@ -363,16 +239,18 @@ CURLcode Curl_close(struct Curl_easy **datap)
/* 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_connection(data);
- if(data->multi)
- /* This handle is still part of a multi handle, take care of this first
- and detach this handle from there. */
- curl_multi_remove_handle(data->multi, data);
+ if(!data->state.internal) {
+ if(data->multi)
+ /* This handle is still part of a multi handle, take care of this first
+ and detach this handle from there. */
+ curl_multi_remove_handle(data->multi, data);
- if(data->multi_easy) {
- /* when curl_easy_perform() is used, it creates its own multi handle to
- use and this is the one */
- curl_multi_cleanup(data->multi_easy);
- data->multi_easy = NULL;
+ if(data->multi_easy) {
+ /* when curl_easy_perform() is used, it creates its own multi handle to
+ use and this is the one */
+ curl_multi_cleanup(data->multi_easy);
+ data->multi_easy = NULL;
+ }
}
data->magic = 0; /* force a clear AFTER the possibly enforced removal from
@@ -412,7 +290,7 @@ CURLcode Curl_close(struct Curl_easy **datap)
#ifndef CURL_DISABLE_HSTS
if(!data->share || !data->share->hsts)
Curl_hsts_cleanup(&data->hsts);
- curl_slist_free_all(data->set.hstslist); /* clean up list */
+ curl_slist_free_all(data->state.hstslist); /* clean up list */
#endif
#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_DIGEST_AUTH)
Curl_http_auth_cleanup_digest(data);
@@ -420,10 +298,6 @@ CURLcode Curl_close(struct Curl_easy **datap)
Curl_safefree(data->info.contenttype);
Curl_safefree(data->info.wouldredirect);
- /* this destroys the channel and we cannot use it anymore after this */
- Curl_resolver_cancel(data);
- Curl_resolver_cleanup(data->state.async.resolver);
-
data_priority_cleanup(data);
/* No longer a dirty share, if it exists */
@@ -457,8 +331,8 @@ CURLcode Curl_close(struct Curl_easy **datap)
}
#endif
- Curl_mime_cleanpart(data->state.formp);
#ifndef CURL_DISABLE_HTTP
+ Curl_mime_cleanpart(data->state.formp);
Curl_safefree(data->state.formp);
#endif
@@ -530,26 +404,16 @@ CURLcode Curl_init_userdefined(struct Curl_easy *data)
Curl_mime_initpart(&set->mimepost);
- /*
- * libcurl 7.10 introduced SSL verification *by default*! This needs to be
- * switched off unless wanted.
- */
+ Curl_ssl_easy_config_init(data);
#ifndef CURL_DISABLE_DOH
set->doh_verifyhost = TRUE;
set->doh_verifypeer = TRUE;
#endif
- set->ssl.primary.verifypeer = TRUE;
- set->ssl.primary.verifyhost = TRUE;
#ifdef USE_SSH
/* defaults to any auth type */
set->ssh_auth_types = CURLSSH_AUTH_DEFAULT;
set->new_directory_perms = 0755; /* Default permissions */
#endif
- set->ssl.primary.sessionid = TRUE; /* session ID caching enabled by
- default */
-#ifndef CURL_DISABLE_PROXY
- set->proxy_ssl = set->ssl;
-#endif
set->new_file_perms = 0644; /* Default permissions */
set->allowed_protocols = (curl_prot_t) CURLPROTO_ALL;
@@ -650,13 +514,6 @@ CURLcode Curl_open(struct Curl_easy **curl)
data->magic = CURLEASY_MAGIC_NUMBER;
- result = Curl_resolver_init(data, &data->state.async.resolver);
- if(result) {
- DEBUGF(fprintf(stderr, "Error: resolver_init failed\n"));
- free(data);
- return result;
- }
-
result = Curl_init_userdefined(data);
if(!result) {
Curl_dyn_init(&data->state.headerb, CURL_MAX_HTTP_HEADER);
@@ -673,7 +530,6 @@ CURLcode Curl_open(struct Curl_easy **curl)
}
if(result) {
- Curl_resolver_cleanup(data->state.async.resolver);
Curl_dyn_free(&data->state.headerb);
Curl_freeset(data);
free(data);
@@ -707,6 +563,7 @@ static void conn_free(struct Curl_easy *data, struct connectdata *conn)
Curl_conn_cf_discard_all(data, conn, (int)i);
}
+ Curl_resolver_cleanup(conn->resolve_async.resolver);
Curl_free_idnconverted_hostname(&conn->host);
Curl_free_idnconverted_hostname(&conn->conn_to_host);
#ifndef CURL_DISABLE_PROXY
@@ -718,7 +575,6 @@ static void conn_free(struct Curl_easy *data, struct connectdata *conn)
Curl_safefree(conn->socks_proxy.passwd);
Curl_safefree(conn->http_proxy.host.rawalloc); /* http proxy name buffer */
Curl_safefree(conn->socks_proxy.host.rawalloc); /* socks proxy name buffer */
- Curl_free_primary_ssl_config(&conn->proxy_ssl_config);
#endif
Curl_safefree(conn->user);
Curl_safefree(conn->passwd);
@@ -733,7 +589,7 @@ static void conn_free(struct Curl_easy *data, struct connectdata *conn)
Curl_safefree(conn->hostname_resolve);
Curl_safefree(conn->secondaryhostname);
Curl_safefree(conn->localdev);
- Curl_free_primary_ssl_config(&conn->ssl_config);
+ Curl_ssl_conn_config_cleanup(conn);
#ifdef USE_UNIX_SOCKETS
Curl_safefree(conn->unix_domain_socket);
@@ -807,6 +663,7 @@ void Curl_disconnect(struct Curl_easy *data,
conn->handler->disconnect(data, conn, dead_connection);
conn_shutdown(data);
+ Curl_resolver_cancel(data);
/* detach it again */
Curl_detach_connection(data);
@@ -1059,11 +916,11 @@ ConnectionExists(struct Curl_easy *data,
bool *force_reuse,
bool *waitpipe)
{
- struct connectdata *check;
- struct connectdata *chosen = 0;
+ struct connectdata *chosen = NULL;
bool foundPendingCandidate = FALSE;
- bool canmultiplex = IsMultiplexingPossible(data, needle);
+ bool canmultiplex = FALSE;
struct connectbundle *bundle;
+ struct Curl_llist_element *curr;
#ifdef USE_NTLM
bool wantNTLMhttp = ((data->state.authhost.want &
@@ -1082,395 +939,368 @@ ConnectionExists(struct Curl_easy *data,
bool h2upgrade = (data->state.httpwant == CURL_HTTP_VERSION_2_0) &&
(needle->handler->protocol & CURLPROTO_HTTP);
+ *usethis = NULL;
*force_reuse = FALSE;
*waitpipe = FALSE;
/* 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(data, needle, data->state.conn_cache);
- if(bundle) {
- /* Max pipe length is zero (unlimited) for multiplexed connections */
- struct Curl_llist_element *curr;
-
- infof(data, "Found bundle for host: %p [%s]",
- (void *)bundle, (bundle->multiuse == BUNDLE_MULTIPLEX ?
- "can multiplex" : "serially"));
-
- /* We can't multiplex if we don't know anything about the server */
- if(canmultiplex) {
- if(bundle->multiuse == BUNDLE_UNKNOWN) {
- if(data->set.pipewait) {
- infof(data, "Server doesn't support multiplex yet, wait");
- *waitpipe = TRUE;
- CONNCACHE_UNLOCK(data);
- return FALSE; /* no reuse */
- }
-
- infof(data, "Server doesn't support multiplex (yet)");
- canmultiplex = FALSE;
+ if(!bundle) {
+ CONNCACHE_UNLOCK(data);
+ return FALSE;
+ }
+ infof(data, "Found bundle for host: %p [%s]",
+ (void *)bundle, (bundle->multiuse == BUNDLE_MULTIPLEX ?
+ "can multiplex" : "serially"));
+
+ /* We can only multiplex iff the transfer allows it AND we know
+ * that the server we want to talk to supports it as well. */
+ canmultiplex = FALSE;
+ if(IsMultiplexingPossible(data, needle)) {
+ if(bundle->multiuse == BUNDLE_UNKNOWN) {
+ if(data->set.pipewait) {
+ infof(data, "Server doesn't support multiplex yet, wait");
+ *waitpipe = TRUE;
+ CONNCACHE_UNLOCK(data);
+ return FALSE; /* no reuse */
}
- if((bundle->multiuse == BUNDLE_MULTIPLEX) &&
- !Curl_multiplex_wanted(data->multi)) {
+ infof(data, "Server doesn't support multiplex (yet)");
+ }
+ else if(bundle->multiuse == BUNDLE_MULTIPLEX) {
+ if(Curl_multiplex_wanted(data->multi))
+ canmultiplex = TRUE;
+ else
infof(data, "Could multiplex, but not asked to");
- canmultiplex = FALSE;
- }
- if(bundle->multiuse == BUNDLE_NO_MULTIUSE) {
- infof(data, "Can not multiplex, even if we wanted to");
- canmultiplex = FALSE;
- }
}
+ else if(bundle->multiuse == BUNDLE_NO_MULTIUSE) {
+ infof(data, "Can not multiplex, even if we wanted to");
+ }
+ }
- curr = bundle->conn_list.head;
- while(curr) {
- bool match = FALSE;
- size_t multiplexed = 0;
+ curr = bundle->conn_list.head;
+ while(curr) {
+ struct connectdata *check = curr->ptr;
+ /* Get next node now. We might remove a dead `check` connection which
+ * would invalidate `curr` as well. */
+ curr = curr->next;
- /*
- * Note that if we use an HTTP proxy in normal mode (no tunneling), we
- * check connections to that proxy and not to the actual remote server.
- */
- check = curr->ptr;
- curr = curr->next;
+ /* Note that if we use an HTTP proxy in normal mode (no tunneling), we
+ * check connections to that proxy and not to the actual remote server.
+ */
+ if(check->connect_only || check->bits.close)
+ /* connect-only or to-be-closed connections will not be reused */
+ continue;
- if(check->connect_only || check->bits.close)
- /* connect-only or to-be-closed connections will not be reused */
- continue;
+ if(data->set.ipver != CURL_IPRESOLVE_WHATEVER
+ && data->set.ipver != check->ip_version) {
+ /* skip because the connection is not via the requested IP version */
+ continue;
+ }
- if(extract_if_dead(check, data)) {
- /* disconnect it */
- Curl_disconnect(data, check, TRUE);
+ if(!canmultiplex) {
+ if(Curl_resolver_asynch() &&
+ /* primary_ip[0] is NUL only if the resolving of the name hasn't
+ completed yet and until then we don't reuse this connection */
+ !check->primary_ip[0])
continue;
- }
+ }
- if(data->set.ipver != CURL_IPRESOLVE_WHATEVER
- && data->set.ipver != check->ip_version) {
- /* skip because the connection is not via the requested IP version */
+ if(CONN_INUSE(check)) {
+ if(!canmultiplex) {
+ /* transfer can't be multiplexed and check is in use */
continue;
}
-
- if(bundle->multiuse == BUNDLE_MULTIPLEX)
- multiplexed = CONN_INUSE(check);
-
- if(!canmultiplex) {
- if(multiplexed) {
- /* can only happen within multi handles, and means that another easy
- handle is using this connection */
- continue;
- }
-
- if(Curl_resolver_asynch() &&
- /* primary_ip[0] is NUL only if the resolving of the name hasn't
- completed yet and until then we don't reuse this connection */
- !check->primary_ip[0])
+ else {
+ /* Could multiplex, but not when check belongs to another multi */
+ struct Curl_llist_element *e = check->easyq.head;
+ struct Curl_easy *entry = e->ptr;
+ if(entry->multi != data->multi)
continue;
}
+ }
- if(!Curl_conn_is_connected(check, FIRSTSOCKET)) {
- foundPendingCandidate = TRUE;
- /* Don't pick a connection that hasn't connected yet */
- infof(data, "Connection #%" CURL_FORMAT_CURL_OFF_T
- " isn't open enough, can't reuse", check->connection_id);
- continue;
- }
+ if(!Curl_conn_is_connected(check, FIRSTSOCKET)) {
+ foundPendingCandidate = TRUE;
+ /* Don't pick a connection that hasn't connected yet */
+ infof(data, "Connection #%" CURL_FORMAT_CURL_OFF_T
+ " isn't open enough, can't reuse", check->connection_id);
+ continue;
+ }
+
+ /* `check` is connected. if it is in use and does not support multiplex,
+ * we cannot use it. */
+ if(!check->bits.multiplex && CONN_INUSE(check))
+ continue;
#ifdef USE_UNIX_SOCKETS
- if(needle->unix_domain_socket) {
- if(!check->unix_domain_socket)
- continue;
- if(strcmp(needle->unix_domain_socket, check->unix_domain_socket))
- continue;
- if(needle->bits.abstract_unix_socket !=
- check->bits.abstract_unix_socket)
- continue;
- }
- else if(check->unix_domain_socket)
+ if(needle->unix_domain_socket) {
+ if(!check->unix_domain_socket)
continue;
-#endif
-
- 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) !=
- needle->handler->protocol || !check->bits.tls_upgraded)
- /* except protocols that have been upgraded via TLS */
- continue;
-
-#ifndef CURL_DISABLE_PROXY
- if(needle->bits.httpproxy != check->bits.httpproxy ||
- needle->bits.socksproxy != check->bits.socksproxy)
+ if(strcmp(needle->unix_domain_socket, check->unix_domain_socket))
continue;
-
- if(needle->bits.socksproxy &&
- !socks_proxy_info_matches(&needle->socks_proxy,
- &check->socks_proxy))
+ if(needle->bits.abstract_unix_socket !=
+ check->bits.abstract_unix_socket)
continue;
+ }
+ else if(check->unix_domain_socket)
+ continue;
#endif
- if(needle->bits.conn_to_host != check->bits.conn_to_host)
- /* don't mix connections that use the "connect to host" feature and
- * connections that don't use this feature */
- continue;
- if(needle->bits.conn_to_port != check->bits.conn_to_port)
- /* don't mix connections that use the "connect to port" feature and
- * connections that don't use this feature */
+ 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) !=
+ needle->handler->protocol || !check->bits.tls_upgraded)
+ /* except protocols that have been upgraded via TLS */
continue;
-#ifndef CURL_DISABLE_PROXY
- if(needle->bits.httpproxy) {
- if(!proxy_info_matches(&needle->http_proxy, &check->http_proxy))
- continue;
+ if(needle->bits.conn_to_host != check->bits.conn_to_host)
+ /* don't mix connections that use the "connect to host" feature and
+ * connections that don't use this feature */
+ continue;
- if(needle->bits.tunnel_proxy != check->bits.tunnel_proxy)
- continue;
+ if(needle->bits.conn_to_port != check->bits.conn_to_port)
+ /* don't mix connections that use the "connect to port" feature and
+ * connections that don't use this feature */
+ continue;
- if(IS_HTTPS_PROXY(needle->http_proxy.proxytype)) {
- /* use https proxy */
- if(needle->http_proxy.proxytype !=
- check->http_proxy.proxytype)
- continue;
- else if(needle->handler->flags&PROTOPT_SSL) {
- /* use double layer ssl */
- if(!Curl_ssl_config_matches(&needle->proxy_ssl_config,
- &check->proxy_ssl_config))
- continue;
- }
- else if(!Curl_ssl_config_matches(&needle->ssl_config,
- &check->ssl_config))
- continue;
- }
- }
-#endif
+#ifndef CURL_DISABLE_PROXY
+ if(needle->bits.httpproxy != check->bits.httpproxy ||
+ needle->bits.socksproxy != check->bits.socksproxy)
+ continue;
- if(h2upgrade && !check->httpversion && canmultiplex) {
- if(data->set.pipewait) {
- infof(data, "Server upgrade doesn't support multiplex yet, wait");
- *waitpipe = TRUE;
- CONNCACHE_UNLOCK(data);
- return FALSE; /* no reuse */
- }
- infof(data, "Server upgrade cannot be used");
- continue; /* can't be used atm */
- }
+ if(needle->bits.socksproxy &&
+ !socks_proxy_info_matches(&needle->socks_proxy,
+ &check->socks_proxy))
+ continue;
- if(!canmultiplex && CONN_INUSE(check))
- /* this request can't be multiplexed but the checked connection is
- already in use so we skip it */
+ if(needle->bits.httpproxy) {
+ if(needle->bits.tunnel_proxy != check->bits.tunnel_proxy)
continue;
- if(CONN_INUSE(check)) {
- /* Subject for multiplex use if 'checks' belongs to the same multi
- handle as 'data' is. */
- struct Curl_llist_element *e = check->easyq.head;
- struct Curl_easy *entry = e->ptr;
- if(entry->multi != data->multi)
- continue;
- }
+ if(!proxy_info_matches(&needle->http_proxy, &check->http_proxy))
+ continue;
- if(needle->localdev || needle->localport) {
- /* If we are bound to a specific local end (IP+port), we must not
- reuse a random other one, although if we didn't ask for a
- particular one we can reuse one that was bound.
-
- This comparison is a bit rough and too strict. Since the input
- parameters can be specified in numerous ways and still end up the
- same it would take a lot of processing to make it really accurate.
- Instead, this matching will assume that reuses of bound connections
- will most likely also reuse the exact same binding parameters and
- missing out a few edge cases shouldn't hurt anyone very much.
- */
- if((check->localport != needle->localport) ||
- (check->localportrange != needle->localportrange) ||
- (needle->localdev &&
- (!check->localdev || strcmp(check->localdev, needle->localdev))))
+ if(IS_HTTPS_PROXY(needle->http_proxy.proxytype)) {
+ /* https proxies come in different types, http/1.1, h2, ... */
+ if(needle->http_proxy.proxytype != check->http_proxy.proxytype)
continue;
- }
-
- if(!(needle->handler->flags & PROTOPT_CREDSPERREQUEST)) {
- /* This protocol requires credentials per connection,
- so verify that we're using the same name and password as well */
- if(Curl_timestrcmp(needle->user, check->user) ||
- Curl_timestrcmp(needle->passwd, check->passwd) ||
- Curl_timestrcmp(needle->sasl_authzid, check->sasl_authzid) ||
- Curl_timestrcmp(needle->oauth_bearer, check->oauth_bearer)) {
- /* one of them was different */
+ /* match SSL config to proxy */
+ if(!Curl_ssl_conn_config_match(data, check, TRUE)) {
+ DEBUGF(infof(data,
+ "Connection #%" CURL_FORMAT_CURL_OFF_T
+ " has different SSL proxy parameters, can't reuse",
+ check->connection_id));
continue;
}
+ /* the SSL config to the server, which may apply here is checked
+ * further below */
}
+ }
+#endif
- /* GSS delegation differences do not actually affect every connection
- and auth method, but this check takes precaution before efficiency */
- if(needle->gssapi_delegation != check->gssapi_delegation)
+ if(h2upgrade && !check->httpversion && canmultiplex) {
+ if(data->set.pipewait) {
+ infof(data, "Server upgrade doesn't support multiplex yet, wait");
+ *waitpipe = TRUE;
+ CONNCACHE_UNLOCK(data);
+ return FALSE; /* no reuse */
+ }
+ infof(data, "Server upgrade cannot be used");
+ continue; /* can't be used atm */
+ }
+
+ if(needle->localdev || needle->localport) {
+ /* If we are bound to a specific local end (IP+port), we must not
+ reuse a random other one, although if we didn't ask for a
+ particular one we can reuse one that was bound.
+
+ This comparison is a bit rough and too strict. Since the input
+ parameters can be specified in numerous ways and still end up the
+ same it would take a lot of processing to make it really accurate.
+ Instead, this matching will assume that reuses of bound connections
+ will most likely also reuse the exact same binding parameters and
+ missing out a few edge cases shouldn't hurt anyone very much.
+ */
+ if((check->localport != needle->localport) ||
+ (check->localportrange != needle->localportrange) ||
+ (needle->localdev &&
+ (!check->localdev || strcmp(check->localdev, needle->localdev))))
continue;
+ }
- /* If multiplexing isn't enabled on the h2 connection and h1 is
- explicitly requested, handle it: */
- if((needle->handler->protocol & PROTO_FAMILY_HTTP) &&
- (((check->httpversion >= 20) &&
- (data->state.httpwant < CURL_HTTP_VERSION_2_0))
- || ((check->httpversion >= 30) &&
- (data->state.httpwant < CURL_HTTP_VERSION_3))))
+ if(!(needle->handler->flags & PROTOPT_CREDSPERREQUEST)) {
+ /* This protocol requires credentials per connection,
+ so verify that we're using the same name and password as well */
+ if(Curl_timestrcmp(needle->user, check->user) ||
+ Curl_timestrcmp(needle->passwd, check->passwd) ||
+ Curl_timestrcmp(needle->sasl_authzid, check->sasl_authzid) ||
+ Curl_timestrcmp(needle->oauth_bearer, check->oauth_bearer)) {
+ /* one of them was different */
continue;
-#ifdef USE_SSH
- else if(get_protocol_family(needle->handler) & PROTO_FAMILY_SSH) {
- if(!ssh_config_matches(needle, check))
- continue;
}
+ }
+
+ /* GSS delegation differences do not actually affect every connection
+ and auth method, but this check takes precaution before efficiency */
+ if(needle->gssapi_delegation != check->gssapi_delegation)
+ continue;
+
+ /* If looking for HTTP and the HTTP version we want is less
+ * than the HTTP version of the check connection, continue looking */
+ if((needle->handler->protocol & PROTO_FAMILY_HTTP) &&
+ (((check->httpversion >= 20) &&
+ (data->state.httpwant < CURL_HTTP_VERSION_2_0))
+ || ((check->httpversion >= 30) &&
+ (data->state.httpwant < CURL_HTTP_VERSION_3))))
+ continue;
+#ifdef USE_SSH
+ else if(get_protocol_family(needle->handler) & PROTO_FAMILY_SSH) {
+ if(!ssh_config_matches(needle, check))
+ continue;
+ }
#endif
#ifndef CURL_DISABLE_FTP
- else if(get_protocol_family(needle->handler) & PROTO_FAMILY_FTP) {
- /* Also match ACCOUNT, ALTERNATIVE-TO-USER, USE_SSL and CCC options */
- if(Curl_timestrcmp(needle->proto.ftpc.account,
- check->proto.ftpc.account) ||
- Curl_timestrcmp(needle->proto.ftpc.alternative_to_user,
- check->proto.ftpc.alternative_to_user) ||
- (needle->proto.ftpc.use_ssl != check->proto.ftpc.use_ssl) ||
- (needle->proto.ftpc.ccc != check->proto.ftpc.ccc))
- continue;
- }
+ else if(get_protocol_family(needle->handler) & PROTO_FAMILY_FTP) {
+ /* Also match ACCOUNT, ALTERNATIVE-TO-USER, USE_SSL and CCC options */
+ if(Curl_timestrcmp(needle->proto.ftpc.account,
+ check->proto.ftpc.account) ||
+ Curl_timestrcmp(needle->proto.ftpc.alternative_to_user,
+ check->proto.ftpc.alternative_to_user) ||
+ (needle->proto.ftpc.use_ssl != check->proto.ftpc.use_ssl) ||
+ (needle->proto.ftpc.ccc != check->proto.ftpc.ccc))
+ continue;
+ }
#endif
- if((needle->handler->flags&PROTOPT_SSL)
+ /* Additional match requirements if talking TLS OR
+ * not talking to a HTTP proxy OR using a tunnel through a proxy */
+ if((needle->handler->flags&PROTOPT_SSL)
#ifndef CURL_DISABLE_PROXY
- || !needle->bits.httpproxy || needle->bits.tunnel_proxy
-#endif
- ) {
- /* The requested connection does not use an HTTP proxy or it uses SSL
- or it is a non-SSL protocol tunneled or it is a non-SSL protocol
- which is allowed to be upgraded via TLS */
-
- if((strcasecompare(needle->handler->scheme, check->handler->scheme) ||
- (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)) &&
- (!needle->bits.conn_to_port ||
- needle->conn_to_port == check->conn_to_port) &&
- strcasecompare(needle->host.name, check->host.name) &&
- needle->remote_port == check->remote_port) {
- /* The schemes match or the protocol family is the same and the
- previous connection was TLS upgraded, and the hostname and host
- port match */
- if(needle->handler->flags & PROTOPT_SSL) {
- /* This is a SSL connection so verify that we're using the same
- SSL options as well */
- if(!Curl_ssl_config_matches(&needle->ssl_config,
- &check->ssl_config)) {
- DEBUGF(infof(data,
- "Connection #%" CURL_FORMAT_CURL_OFF_T
- " has different SSL parameters, can't reuse",
- check->connection_id));
- continue;
- }
- }
- match = TRUE;
- }
- }
- else {
- /* The requested connection is using the same HTTP proxy in normal
- mode (no tunneling) */
- match = TRUE;
+ || !needle->bits.httpproxy || needle->bits.tunnel_proxy
+#endif
+ ) {
+ /* Talking the same protocol scheme or a TLS upgraded protocol in the
+ * same protocol family? */
+ if(!strcasecompare(needle->handler->scheme, check->handler->scheme) &&
+ (get_protocol_family(check->handler) !=
+ needle->handler->protocol || !check->bits.tls_upgraded))
+ continue;
+
+ /* If needle has "conn_to_*" set, check must match this */
+ if((needle->bits.conn_to_host && !strcasecompare(
+ needle->conn_to_host.name, check->conn_to_host.name)) ||
+ (needle->bits.conn_to_port &&
+ needle->conn_to_port != check->conn_to_port))
+ continue;
+
+ /* hostname and port must match */
+ if(!strcasecompare(needle->host.name, check->host.name) ||
+ needle->remote_port != check->remote_port)
+ continue;
+
+ /* If talking TLS, check needs to use the same SSL options. */
+ if((needle->handler->flags & PROTOPT_SSL) &&
+ !Curl_ssl_conn_config_match(data, check, FALSE)) {
+ DEBUGF(infof(data,
+ "Connection #%" CURL_FORMAT_CURL_OFF_T
+ " has different SSL parameters, can't reuse",
+ check->connection_id));
+ continue;
}
+ }
- if(match) {
#if defined(USE_NTLM)
- /* If we are looking for an HTTP+NTLM connection, check if this is
- already authenticating with the right credentials. If not, keep
- looking so that we can reuse NTLM connections if
- possible. (Especially we must not reuse the same connection if
- partway through a handshake!) */
- if(wantNTLMhttp) {
- if(Curl_timestrcmp(needle->user, check->user) ||
- Curl_timestrcmp(needle->passwd, check->passwd)) {
-
- /* we prefer a credential match, but this is at least a connection
- that can be reused and "upgraded" to NTLM */
- if(check->http_ntlm_state == NTLMSTATE_NONE)
- chosen = check;
- continue;
- }
- }
- else if(check->http_ntlm_state != NTLMSTATE_NONE) {
- /* Connection is using NTLM auth but we don't want NTLM */
- continue;
- }
-
-#ifndef CURL_DISABLE_PROXY
- /* Same for Proxy NTLM authentication */
- if(wantProxyNTLMhttp) {
- /* Both check->http_proxy.user and check->http_proxy.passwd can be
- * NULL */
- if(!check->http_proxy.user || !check->http_proxy.passwd)
- continue;
-
- if(Curl_timestrcmp(needle->http_proxy.user,
- check->http_proxy.user) ||
- Curl_timestrcmp(needle->http_proxy.passwd,
- check->http_proxy.passwd))
- continue;
- }
- else if(check->proxy_ntlm_state != NTLMSTATE_NONE) {
- /* Proxy connection is using NTLM auth but we don't want NTLM */
- continue;
- }
-#endif
- if(wantNTLMhttp || wantProxyNTLMhttp) {
- /* Credentials are already checked, we can use this connection */
+ /* If we are looking for an HTTP+NTLM connection, check if this is
+ already authenticating with the right credentials. If not, keep
+ looking so that we can reuse NTLM connections if
+ possible. (Especially we must not reuse the same connection if
+ partway through a handshake!) */
+ if(wantNTLMhttp) {
+ if(Curl_timestrcmp(needle->user, check->user) ||
+ Curl_timestrcmp(needle->passwd, check->passwd)) {
+
+ /* we prefer a credential match, but this is at least a connection
+ that can be reused and "upgraded" to NTLM */
+ if(check->http_ntlm_state == NTLMSTATE_NONE)
chosen = check;
+ continue;
+ }
+ }
+ else if(check->http_ntlm_state != NTLMSTATE_NONE) {
+ /* Connection is using NTLM auth but we don't want NTLM */
+ continue;
+ }
- if((wantNTLMhttp &&
- (check->http_ntlm_state != NTLMSTATE_NONE)) ||
- (wantProxyNTLMhttp &&
- (check->proxy_ntlm_state != NTLMSTATE_NONE))) {
- /* We must use this connection, no other */
- *force_reuse = TRUE;
- break;
- }
+#ifndef CURL_DISABLE_PROXY
+ /* Same for Proxy NTLM authentication */
+ if(wantProxyNTLMhttp) {
+ /* Both check->http_proxy.user and check->http_proxy.passwd can be
+ * NULL */
+ if(!check->http_proxy.user || !check->http_proxy.passwd)
+ continue;
- /* Continue look up for a better connection */
- continue;
- }
+ if(Curl_timestrcmp(needle->http_proxy.user,
+ check->http_proxy.user) ||
+ Curl_timestrcmp(needle->http_proxy.passwd,
+ check->http_proxy.passwd))
+ continue;
+ }
+ else if(check->proxy_ntlm_state != NTLMSTATE_NONE) {
+ /* Proxy connection is using NTLM auth but we don't want NTLM */
+ continue;
+ }
+#endif
+ if(wantNTLMhttp || wantProxyNTLMhttp) {
+ /* Credentials are already checked, we may use this connection.
+ * With NTLM being weird as it is, we MUST use a
+ * connection where it has already been fully negotiated.
+ * If it has not, we keep on looking for a better one. */
+ chosen = check;
+
+ if((wantNTLMhttp &&
+ (check->http_ntlm_state != NTLMSTATE_NONE)) ||
+ (wantProxyNTLMhttp &&
+ (check->proxy_ntlm_state != NTLMSTATE_NONE))) {
+ /* We must use this connection, no other */
+ *force_reuse = TRUE;
+ break;
+ }
+ /* Continue look up for a better connection */
+ continue;
+ }
#endif
- if(canmultiplex) {
- /* We can multiplex if we want to. Let's continue looking for
- the optimal connection to use. */
-
- if(!multiplexed) {
- /* We have the optimal connection. Let's stop looking. */
- chosen = check;
- break;
- }
-#ifdef USE_NGHTTP2
- /* If multiplexed, make sure we don't go over concurrency limit */
- if(check->bits.multiplex) {
- if(multiplexed >= Curl_conn_get_max_concurrent(data, check,
- FIRSTSOCKET)) {
- infof(data, "MAX_CONCURRENT_STREAMS reached, skip (%zu)",
- multiplexed);
- continue;
- }
- else if(multiplexed >=
- Curl_multi_max_concurrent_streams(data->multi)) {
- infof(data, "client side MAX_CONCURRENT_STREAMS reached"
- ", skip (%zu)",
- multiplexed);
- continue;
- }
- }
-#endif
- /* When not multiplexed, we have a match here! */
- chosen = check;
- infof(data, "Multiplexed connection found");
- break;
- }
- else {
- /* We have found a connection. Let's stop searching. */
- chosen = check;
- break;
- }
+ if(CONN_INUSE(check)) {
+ DEBUGASSERT(canmultiplex);
+ DEBUGASSERT(check->bits.multiplex);
+ /* If multiplexed, make sure we don't go over concurrency limit */
+ if(CONN_INUSE(check) >=
+ Curl_multi_max_concurrent_streams(data->multi)) {
+ infof(data, "client side MAX_CONCURRENT_STREAMS reached"
+ ", skip (%zu)", CONN_INUSE(check));
+ continue;
}
+ if(CONN_INUSE(check) >=
+ Curl_conn_get_max_concurrent(data, check, FIRSTSOCKET)) {
+ infof(data, "MAX_CONCURRENT_STREAMS reached, skip (%zu)",
+ CONN_INUSE(check));
+ continue;
+ }
+ /* When not multiplexed, we have a match here! */
+ infof(data, "Multiplexed connection found");
+ }
+ else if(extract_if_dead(check, data)) {
+ /* disconnect it */
+ Curl_disconnect(data, check, TRUE);
+ continue;
}
- }
+
+ /* We have found a connection. Let's stop searching. */
+ chosen = check;
+ break;
+ } /* loop over connection bundle */
if(chosen) {
/* mark it as used before releasing the lock */
@@ -1561,17 +1391,6 @@ static struct connectdata *allocate_conn(struct Curl_easy *data)
conn->bits.ftp_use_epsv = data->set.ftp_use_epsv;
conn->bits.ftp_use_eprt = data->set.ftp_use_eprt;
#endif
- conn->ssl_config.verifystatus = data->set.ssl.primary.verifystatus;
- conn->ssl_config.verifypeer = data->set.ssl.primary.verifypeer;
- conn->ssl_config.verifyhost = data->set.ssl.primary.verifyhost;
- conn->ssl_config.ssl_options = data->set.ssl.primary.ssl_options;
-#ifndef CURL_DISABLE_PROXY
- conn->proxy_ssl_config.verifystatus =
- data->set.proxy_ssl.primary.verifystatus;
- conn->proxy_ssl_config.verifypeer = data->set.proxy_ssl.primary.verifypeer;
- conn->proxy_ssl_config.verifyhost = data->set.proxy_ssl.primary.verifyhost;
- conn->proxy_ssl_config.ssl_options = data->set.proxy_ssl.primary.ssl_options;
-#endif
conn->ip_version = data->set.ipver;
conn->connect_only = data->set.connect_only;
conn->transport = TRNSPRT_TCP; /* most of them are TCP streams */
@@ -1615,30 +1434,231 @@ error:
return NULL;
}
-/* returns the handler if the given scheme is built-in */
-const struct Curl_handler *Curl_builtin_scheme(const char *scheme,
- size_t schemelen)
+const struct Curl_handler *Curl_get_scheme_handler(const char *scheme)
{
- const struct Curl_handler * const *pp;
- const struct Curl_handler *p;
- /* Scan protocol handler table and match against 'scheme'. The handler may
- be changed later when the protocol specific setup function is called. */
- if(schemelen == CURL_ZERO_TERMINATED)
- schemelen = strlen(scheme);
- for(pp = protocols; (p = *pp) != NULL; pp++)
- if(strncasecompare(p->scheme, scheme, schemelen) && !p->scheme[schemelen])
- /* Protocol found in table. */
- return p;
- return NULL; /* not found */
+ return Curl_getn_scheme_handler(scheme, strlen(scheme));
}
+/* returns the handler if the given scheme is built-in */
+const struct Curl_handler *Curl_getn_scheme_handler(const char *scheme,
+ size_t len)
+{
+ /* table generated by schemetable.c:
+ 1. gcc schemetable.c && ./a.out
+ 2. check how small the table gets
+ 3. tweak the hash algorithm, then rerun from 1
+ 4. when the table is good enough
+ 5. copy the table into this source code
+ 6. make sure this function uses the same hash function that worked for
+ schemetable.c
+ 7. if needed, adjust the #ifdefs in schemetable.c and rerun
+ */
+ static const struct Curl_handler * const protocols[67] = {
+#ifndef CURL_DISABLE_FILE
+ &Curl_handler_file,
+#else
+ NULL,
+#endif
+ NULL, NULL,
+#if defined(USE_SSL) && !defined(CURL_DISABLE_GOPHER)
+ &Curl_handler_gophers,
+#else
+ NULL,
+#endif
+ NULL,
+#ifdef USE_LIBRTMP
+ &Curl_handler_rtmpe,
+#else
+ NULL,
+#endif
+#ifndef CURL_DISABLE_SMTP
+ &Curl_handler_smtp,
+#else
+ NULL,
+#endif
+#if defined(USE_SSH)
+ &Curl_handler_sftp,
+#else
+ NULL,
+#endif
+#if !defined(CURL_DISABLE_SMB) && defined(USE_CURL_NTLM_CORE) && \
+ (SIZEOF_CURL_OFF_T > 4)
+ &Curl_handler_smb,
+#else
+ NULL,
+#endif
+#if defined(USE_SSL) && !defined(CURL_DISABLE_SMTP)
+ &Curl_handler_smtps,
+#else
+ NULL,
+#endif
+#ifndef CURL_DISABLE_TELNET
+ &Curl_handler_telnet,
+#else
+ NULL,
+#endif
+#ifndef CURL_DISABLE_GOPHER
+ &Curl_handler_gopher,
+#else
+ NULL,
+#endif
+#ifndef CURL_DISABLE_TFTP
+ &Curl_handler_tftp,
+#else
+ NULL,
+#endif
+ NULL, NULL, NULL,
+#if defined(USE_SSL) && !defined(CURL_DISABLE_FTP)
+ &Curl_handler_ftps,
+#else
+ NULL,
+#endif
+#ifndef CURL_DISABLE_HTTP
+ &Curl_handler_http,
+#else
+ NULL,
+#endif
+#ifndef CURL_DISABLE_IMAP
+ &Curl_handler_imap,
+#else
+ NULL,
+#endif
+#ifdef USE_LIBRTMP
+ &Curl_handler_rtmps,
+#else
+ NULL,
+#endif
+#ifdef USE_LIBRTMP
+ &Curl_handler_rtmpt,
+#else
+ NULL,
+#endif
+ NULL, NULL, NULL,
+#if !defined(CURL_DISABLE_LDAP) && \
+ !defined(CURL_DISABLE_LDAPS) && \
+ ((defined(USE_OPENLDAP) && defined(USE_SSL)) || \
+ (!defined(USE_OPENLDAP) && defined(HAVE_LDAP_SSL)))
+ &Curl_handler_ldaps,
+#else
+ NULL,
+#endif
+#if defined(USE_WEBSOCKETS) && \
+ defined(USE_SSL) && !defined(CURL_DISABLE_HTTP)
+ &Curl_handler_wss,
+#else
+ NULL,
+#endif
+#if defined(USE_SSL) && !defined(CURL_DISABLE_HTTP)
+ &Curl_handler_https,
+#else
+ NULL,
+#endif
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+#ifndef CURL_DISABLE_RTSP
+ &Curl_handler_rtsp,
+#else
+ NULL,
+#endif
+#if defined(USE_SSL) && !defined(CURL_DISABLE_SMB) && \
+ defined(USE_CURL_NTLM_CORE) && (SIZEOF_CURL_OFF_T > 4)
+ &Curl_handler_smbs,
+#else
+ NULL,
+#endif
+#if defined(USE_SSH) && !defined(USE_WOLFSSH)
+ &Curl_handler_scp,
+#else
+ NULL,
+#endif
+ NULL, NULL, NULL,
+#ifndef CURL_DISABLE_POP3
+ &Curl_handler_pop3,
+#else
+ NULL,
+#endif
+ NULL, NULL,
+#ifdef USE_LIBRTMP
+ &Curl_handler_rtmp,
+#else
+ NULL,
+#endif
+ NULL, NULL, NULL,
+#ifdef USE_LIBRTMP
+ &Curl_handler_rtmpte,
+#else
+ NULL,
+#endif
+ NULL, NULL, NULL,
+#ifndef CURL_DISABLE_DICT
+ &Curl_handler_dict,
+#else
+ NULL,
+#endif
+ NULL, NULL, NULL,
+#ifndef CURL_DISABLE_MQTT
+ &Curl_handler_mqtt,
+#else
+ NULL,
+#endif
+#if defined(USE_SSL) && !defined(CURL_DISABLE_POP3)
+ &Curl_handler_pop3s,
+#else
+ NULL,
+#endif
+#if defined(USE_SSL) && !defined(CURL_DISABLE_IMAP)
+ &Curl_handler_imaps,
+#else
+ NULL,
+#endif
+ NULL,
+#if defined(USE_WEBSOCKETS) && !defined(CURL_DISABLE_HTTP)
+ &Curl_handler_ws,
+#else
+ NULL,
+#endif
+ NULL,
+#ifdef USE_LIBRTMP
+ &Curl_handler_rtmpts,
+#else
+ NULL,
+#endif
+#ifndef CURL_DISABLE_LDAP
+ &Curl_handler_ldap,
+#else
+ NULL,
+#endif
+ NULL, NULL,
+#ifndef CURL_DISABLE_FTP
+ &Curl_handler_ftp,
+#else
+ NULL,
+#endif
+ };
+
+ if(len && (len <= 7)) {
+ const char *s = scheme;
+ size_t l = len;
+ const struct Curl_handler *h;
+ unsigned int c = 978;
+ while(l) {
+ c <<= 5;
+ c += Curl_raw_tolower(*s);
+ s++;
+ l--;
+ }
+
+ h = protocols[c % 67];
+ if(h && strncasecompare(scheme, h->scheme, len) && !h->scheme[len])
+ return h;
+ }
+ return NULL;
+}
static CURLcode findprotocol(struct Curl_easy *data,
struct connectdata *conn,
const char *protostr)
{
- const struct Curl_handler *p = Curl_builtin_scheme(protostr,
- CURL_ZERO_TERMINATED);
+ const struct Curl_handler *p = Curl_get_scheme_handler(protostr);
if(p && /* Protocol found in table. Check if allowed */
(data->set.allowed_protocols & p->protocol)) {
@@ -1652,7 +1672,6 @@ static CURLcode findprotocol(struct Curl_easy *data,
else {
/* Perform setup complement if some. */
conn->handler = conn->given = p;
-
/* 'port' and 'remote_port' are set in setup_connection_internals() */
return CURLE_OK;
}
@@ -1705,14 +1724,14 @@ static void zonefrom_url(CURLU *uh, struct Curl_easy *data,
conn->scope_id = (unsigned int)scope;
#if defined(HAVE_IF_NAMETOINDEX)
else {
-#elif defined(WIN32)
+#elif defined(_WIN32)
else if(Curl_if_nametoindex) {
#endif
-#if defined(HAVE_IF_NAMETOINDEX) || defined(WIN32)
+#if defined(HAVE_IF_NAMETOINDEX) || defined(_WIN32)
/* Zone identifier is not numeric */
unsigned int scopeidx = 0;
-#if defined(WIN32)
+#if defined(_WIN32)
scopeidx = Curl_if_nametoindex(zoneid);
#else
scopeidx = if_nametoindex(zoneid);
@@ -1727,7 +1746,7 @@ static void zonefrom_url(CURLU *uh, struct Curl_easy *data,
else
conn->scope_id = scopeidx;
}
-#endif /* HAVE_IF_NAMETOINDEX || WIN32 */
+#endif /* HAVE_IF_NAMETOINDEX || _WIN32 */
free(zoneid);
}
@@ -3596,85 +3615,10 @@ static CURLcode create_conn(struct Curl_easy *data,
conn->send[SECONDARYSOCKET] = Curl_conn_send;
conn->bits.tcp_fastopen = data->set.tcp_fastopen;
- /* Get a cloned copy of the SSL config situation stored in the
- connection struct. But to get this going nicely, we must first make
- sure that the strings in the master copy are pointing to the correct
- strings in the session handle strings array!
-
- Keep in mind that the pointers in the master copy are pointing to strings
- that will be freed as part of the Curl_easy struct, but all cloned
- copies will be separately allocated.
- */
- data->set.ssl.primary.CApath = data->set.str[STRING_SSL_CAPATH];
- data->set.ssl.primary.CAfile = data->set.str[STRING_SSL_CAFILE];
- data->set.ssl.primary.issuercert = data->set.str[STRING_SSL_ISSUERCERT];
- data->set.ssl.primary.issuercert_blob = data->set.blobs[BLOB_SSL_ISSUERCERT];
- data->set.ssl.primary.cipher_list =
- data->set.str[STRING_SSL_CIPHER_LIST];
- data->set.ssl.primary.cipher_list13 =
- data->set.str[STRING_SSL_CIPHER13_LIST];
- data->set.ssl.primary.pinned_key =
- data->set.str[STRING_SSL_PINNEDPUBLICKEY];
- data->set.ssl.primary.cert_blob = data->set.blobs[BLOB_CERT];
- data->set.ssl.primary.ca_info_blob = data->set.blobs[BLOB_CAINFO];
- 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];
- data->set.proxy_ssl.primary.CAfile = data->set.str[STRING_SSL_CAFILE_PROXY];
- data->set.proxy_ssl.primary.cipher_list =
- data->set.str[STRING_SSL_CIPHER_LIST_PROXY];
- data->set.proxy_ssl.primary.cipher_list13 =
- data->set.str[STRING_SSL_CIPHER13_LIST_PROXY];
- data->set.proxy_ssl.primary.pinned_key =
- data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY];
- data->set.proxy_ssl.primary.cert_blob = data->set.blobs[BLOB_CERT_PROXY];
- data->set.proxy_ssl.primary.ca_info_blob =
- data->set.blobs[BLOB_CAINFO_PROXY];
- data->set.proxy_ssl.primary.issuercert =
- data->set.str[STRING_SSL_ISSUERCERT_PROXY];
- data->set.proxy_ssl.primary.issuercert_blob =
- data->set.blobs[BLOB_SSL_ISSUERCERT_PROXY];
- data->set.proxy_ssl.primary.CRLfile =
- data->set.str[STRING_SSL_CRLFILE_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.key_blob = data->set.blobs[BLOB_KEY_PROXY];
-#endif
- data->set.ssl.primary.CRLfile = data->set.str[STRING_SSL_CRLFILE];
- data->set.ssl.cert_type = data->set.str[STRING_CERT_TYPE];
- data->set.ssl.key = data->set.str[STRING_KEY];
- data->set.ssl.key_type = data->set.str[STRING_KEY_TYPE];
- data->set.ssl.key_passwd = data->set.str[STRING_KEY_PASSWD];
- data->set.ssl.primary.clientcert = data->set.str[STRING_CERT];
-#ifdef USE_TLS_SRP
- data->set.ssl.primary.username = data->set.str[STRING_TLSAUTH_USERNAME];
- data->set.ssl.primary.password = data->set.str[STRING_TLSAUTH_PASSWORD];
-#ifndef CURL_DISABLE_PROXY
- data->set.proxy_ssl.primary.username =
- data->set.str[STRING_TLSAUTH_USERNAME_PROXY];
- data->set.proxy_ssl.primary.password =
- data->set.str[STRING_TLSAUTH_PASSWORD_PROXY];
-#endif
-#endif
- data->set.ssl.key_blob = data->set.blobs[BLOB_KEY];
-
- if(!Curl_clone_primary_ssl_config(&data->set.ssl.primary,
- &conn->ssl_config)) {
- result = CURLE_OUT_OF_MEMORY;
- goto out;
- }
-
-#ifndef CURL_DISABLE_PROXY
- if(!Curl_clone_primary_ssl_config(&data->set.proxy_ssl.primary,
- &conn->proxy_ssl_config)) {
- result = CURLE_OUT_OF_MEMORY;
+ /* Complete the easy's SSL configuration for connection cache matching */
+ result = Curl_ssl_easy_config_complete(data);
+ if(result)
goto out;
- }
-#endif
prune_dead_connections(data);
@@ -3789,7 +3733,41 @@ static CURLcode create_conn(struct Curl_easy *data,
* This is a brand new connection, so let's store it in the connection
* cache of ours!
*/
+ result = Curl_ssl_conn_config_init(data, conn);
+ if(result) {
+ DEBUGF(fprintf(stderr, "Error: init connection ssl config\n"));
+ goto out;
+ }
+
+ result = Curl_resolver_init(data, &conn->resolve_async.resolver);
+ if(result) {
+ DEBUGF(fprintf(stderr, "Error: resolver_init failed\n"));
+ goto out;
+ }
+
Curl_attach_connection(data, conn);
+
+#ifdef USE_ARES
+ result = Curl_set_dns_servers(data, data->set.str[STRING_DNS_SERVERS]);
+ if(result && result != CURLE_NOT_BUILT_IN)
+ goto out;
+
+ result = Curl_set_dns_interface(data,
+ data->set.str[STRING_DNS_INTERFACE]);
+ if(result && result != CURLE_NOT_BUILT_IN)
+ goto out;
+
+ result = Curl_set_dns_local_ip4(data,
+ data->set.str[STRING_DNS_LOCAL_IP4]);
+ if(result && result != CURLE_NOT_BUILT_IN)
+ goto out;
+
+ result = Curl_set_dns_local_ip6(data,
+ data->set.str[STRING_DNS_LOCAL_IP6]);
+ if(result && result != CURLE_NOT_BUILT_IN)
+ goto out;
+#endif /* USE_ARES */
+
result = Curl_conncache_add_conn(data);
if(result)
goto out;
@@ -3976,6 +3954,7 @@ CURLcode Curl_init_do(struct Curl_easy *data, struct connectdata *conn)
k->bytecount = 0;
k->ignorebody = FALSE;
+ Curl_client_cleanup(data);
Curl_speedinit(data);
Curl_pgrsSetUploadCounter(data, 0);
Curl_pgrsSetDownloadCounter(data, 0);
diff --git a/libs/libcurl/src/url.h b/libs/libcurl/src/url.h
index 8603d3ff02..65b04db079 100644
--- a/libs/libcurl/src/url.h
+++ b/libs/libcurl/src/url.h
@@ -46,8 +46,13 @@ CURLcode Curl_parse_login_details(const char *login, const size_t len,
char **userptr, char **passwdptr,
char **optionsptr);
-const struct Curl_handler *Curl_builtin_scheme(const char *scheme,
- size_t schemelen);
+/* Get protocol handler for a URI scheme
+ * @param scheme URI scheme, case-insensitive
+ * @return NULL of handler not found
+ */
+const struct Curl_handler *Curl_get_scheme_handler(const char *scheme);
+const struct Curl_handler *Curl_getn_scheme_handler(const char *scheme,
+ size_t len);
#define CURL_DEFAULT_PROXY_PORT 1080 /* default proxy port unless specified */
#define CURL_DEFAULT_HTTPS_PROXY_PORT 443 /* default https proxy port unless
diff --git a/libs/libcurl/src/urlapi.c b/libs/libcurl/src/urlapi.c
index 37dabba3e0..1a94e7f4cf 100644
--- a/libs/libcurl/src/urlapi.c
+++ b/libs/libcurl/src/urlapi.c
@@ -206,7 +206,7 @@ size_t Curl_is_absolute_url(const char *url, char *buf, size_t buflen,
(void)buflen; /* only used in debug-builds */
if(buf)
buf[0] = 0; /* always leave a defined value in buf */
-#ifdef WIN32
+#ifdef _WIN32
if(guess_scheme && STARTS_WITH_DRIVE_PREFIX(url))
return 0;
#endif
@@ -446,7 +446,7 @@ static CURLUcode parse_hostname_login(struct Curl_URL *u,
/* if this is a known scheme, get some details */
if(u->scheme)
- h = Curl_builtin_scheme(u->scheme, CURL_ZERO_TERMINATED);
+ h = Curl_get_scheme_handler(u->scheme);
/* We could use the login information in the URL so extract it. Only parse
options if the handler says we should. Note that 'h' might be NULL! */
@@ -1056,7 +1056,7 @@ static CURLUcode parseurl(const char *url, CURLU *u, unsigned int flags)
ptr += 9; /* now points to the slash after the host */
}
else {
-#if defined(WIN32)
+#if defined(_WIN32)
size_t len;
/* the host name, NetBIOS computer name, can not contain disallowed
@@ -1095,7 +1095,7 @@ static CURLUcode parseurl(const char *url, CURLU *u, unsigned int flags)
/* no host for file: URLs by default */
Curl_dyn_reset(&host);
-#if !defined(MSDOS) && !defined(WIN32) && !defined(__CYGWIN__)
+#if !defined(_WIN32) && !defined(MSDOS) && !defined(__CYGWIN__)
/* Don't allow Windows drive letters when not in Windows.
* This catches both "file:/c:" and "file:c:" */
if(('/' == path[0] && STARTS_WITH_URL_DRIVE_PREFIX(&path[1])) ||
@@ -1129,7 +1129,7 @@ static CURLUcode parseurl(const char *url, CURLU *u, unsigned int flags)
}
schemep = schemebuf;
- if(!Curl_builtin_scheme(schemep, CURL_ZERO_TERMINATED) &&
+ if(!Curl_get_scheme_handler(schemep) &&
!(flags & CURLU_NON_SUPPORT_SCHEME)) {
result = CURLUE_UNSUPPORTED_SCHEME;
goto fail;
@@ -1224,14 +1224,14 @@ static CURLUcode parseurl(const char *url, CURLU *u, unsigned int flags)
if(flags & CURLU_URLENCODE) {
struct dynbuf enc;
Curl_dyn_init(&enc, CURL_MAX_INPUT_LENGTH);
- if(urlencode_str(&enc, fragment + 1, fraglen, TRUE, FALSE)) {
+ if(urlencode_str(&enc, fragment + 1, fraglen - 1, TRUE, FALSE)) {
result = CURLUE_OUT_OF_MEMORY;
goto fail;
}
u->fragment = Curl_dyn_ptr(&enc);
}
else {
- u->fragment = Curl_memdup(fragment + 1, fraglen);
+ u->fragment = Curl_strndup(fragment + 1, fraglen - 1);
if(!u->fragment) {
result = CURLUE_OUT_OF_MEMORY;
goto fail;
@@ -1260,12 +1260,11 @@ static CURLUcode parseurl(const char *url, CURLU *u, unsigned int flags)
u->query = Curl_dyn_ptr(&enc);
}
else {
- u->query = Curl_memdup(query + 1, qlen);
+ u->query = Curl_strndup(query + 1, qlen - 1);
if(!u->query) {
result = CURLUE_OUT_OF_MEMORY;
goto fail;
}
- u->query[qlen - 1] = 0;
}
}
else {
@@ -1295,12 +1294,11 @@ static CURLUcode parseurl(const char *url, CURLU *u, unsigned int flags)
}
else {
if(!u->path) {
- u->path = Curl_memdup(path, pathlen + 1);
+ u->path = Curl_strndup(path, pathlen);
if(!u->path) {
result = CURLUE_OUT_OF_MEMORY;
goto fail;
}
- u->path[pathlen] = 0;
path = u->path;
}
else if(flags & CURLU_URLENCODE)
@@ -1352,7 +1350,7 @@ static CURLUcode parseurl_and_replace(const char *url, CURLU *u,
*/
CURLU *curl_url(void)
{
- return calloc(sizeof(struct Curl_URL), 1);
+ return calloc(1, sizeof(struct Curl_URL));
}
void curl_url_cleanup(CURLU *u)
@@ -1374,7 +1372,7 @@ void curl_url_cleanup(CURLU *u)
CURLU *curl_url_dup(const CURLU *in)
{
- struct Curl_URL *u = calloc(sizeof(struct Curl_URL), 1);
+ struct Curl_URL *u = calloc(1, sizeof(struct Curl_URL));
if(u) {
DUP(u, in, scheme);
DUP(u, in, user);
@@ -1447,8 +1445,7 @@ CURLUcode curl_url_get(const CURLU *u, CURLUPart what,
if(!ptr && (flags & CURLU_DEFAULT_PORT) && u->scheme) {
/* there's no stored port number, but asked to deliver
a default one for the scheme */
- const struct Curl_handler *h =
- Curl_builtin_scheme(u->scheme, CURL_ZERO_TERMINATED);
+ const struct Curl_handler *h = Curl_get_scheme_handler(u->scheme);
if(h) {
msnprintf(portbuf, sizeof(portbuf), "%u", h->defport);
ptr = portbuf;
@@ -1457,8 +1454,7 @@ CURLUcode curl_url_get(const CURLU *u, CURLUPart what,
else if(ptr && u->scheme) {
/* there is a stored port number, but ask to inhibit if
it matches the default one for the scheme */
- const struct Curl_handler *h =
- Curl_builtin_scheme(u->scheme, CURL_ZERO_TERMINATED);
+ const struct Curl_handler *h = Curl_get_scheme_handler(u->scheme);
if(h && (h->defport == u->portnum) &&
(flags & CURLU_NO_DEFAULT_PORT))
ptr = NULL;
@@ -1503,7 +1499,7 @@ CURLUcode curl_url_get(const CURLU *u, CURLUPart what,
else
return CURLUE_NO_SCHEME;
- h = Curl_builtin_scheme(scheme, CURL_ZERO_TERMINATED);
+ h = Curl_get_scheme_handler(scheme);
if(!port && (flags & CURLU_DEFAULT_PORT)) {
/* there's no stored port number, but asked to deliver
a default one for the scheme */
@@ -1596,7 +1592,7 @@ CURLUcode curl_url_get(const CURLU *u, CURLUPart what,
if(ptr) {
size_t partlen = strlen(ptr);
size_t i = 0;
- *part = Curl_memdup(ptr, partlen + 1);
+ *part = Curl_strndup(ptr, partlen);
if(!*part)
return CURLUE_OUT_OF_MEMORY;
if(plusdecode) {
@@ -1743,9 +1739,8 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what,
if((plen > MAX_SCHEME_LEN) || (plen < 1))
/* too long or too short */
return CURLUE_BAD_SCHEME;
- if(!(flags & CURLU_NON_SUPPORT_SCHEME) &&
- /* verify that it is a fine scheme */
- !Curl_builtin_scheme(part, CURL_ZERO_TERMINATED))
+ /* verify that it is a fine scheme */
+ if(!(flags & CURLU_NON_SUPPORT_SCHEME) && !Curl_get_scheme_handler(part))
return CURLUE_UNSUPPORTED_SCHEME;
storep = &u->scheme;
urlencode = FALSE; /* never */
@@ -1905,7 +1900,7 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what,
}
newp = Curl_dyn_ptr(&enc);
- if(appendquery) {
+ if(appendquery && newp) {
/* Append the 'newp' string onto the old query. Add a '&' separator if
none is present at the end of the existing query already */
@@ -1934,8 +1929,8 @@ nomem:
}
}
- if(what == CURLUPART_HOST) {
- size_t n = strlen(newp);
+ else if(what == CURLUPART_HOST) {
+ size_t n = Curl_dyn_len(&enc);
if(!n && (flags & CURLU_NO_AUTHORITY)) {
/* Skip hostname check, it's allowed to be empty. */
}
diff --git a/libs/libcurl/src/urldata.h b/libs/libcurl/src/urldata.h
index 6710314c55..b5b6bf866b 100644
--- a/libs/libcurl/src/urldata.h
+++ b/libs/libcurl/src/urldata.h
@@ -266,6 +266,13 @@ typedef enum {
/* SSL backend-specific data; declared differently by each SSL backend */
struct ssl_backend_data;
+struct ssl_peer {
+ char *hostname; /* hostname for verification */
+ char *dispname; /* display version of hostname */
+ char *sni; /* SNI version of hostname or NULL if not usable */
+ BIT(is_ip_address); /* if hostname is an IPv4|6 address */
+};
+
struct ssl_primary_config {
char *CApath; /* certificate dir (doesn't work on windows) */
char *CAfile; /* certificate to verify peer against */
@@ -571,6 +578,13 @@ struct hostname {
#define KEEP_RECVBITS (KEEP_RECV | KEEP_RECV_HOLD | KEEP_RECV_PAUSE)
#define KEEP_SENDBITS (KEEP_SEND | KEEP_SEND_HOLD | KEEP_SEND_PAUSE)
+/* transfer wants to send is not PAUSE or HOLD */
+#define CURL_WANT_SEND(data) \
+ (((data)->req.keepon & KEEP_SENDBITS) == KEEP_SEND)
+/* transfer receive is not on PAUSE or HOLD */
+#define CURL_WANT_RECV(data) \
+ (!((data)->req.keepon & (KEEP_RECV_PAUSE|KEEP_RECV_HOLD)))
+
#if defined(CURLRES_ASYNCH) || !defined(CURL_DISABLE_DOH)
#define USE_CURL_ASYNC
struct Curl_async {
@@ -589,6 +603,15 @@ struct Curl_async {
#define FIRSTSOCKET 0
#define SECONDARYSOCKET 1
+/* Polling requested by an easy handle.
+ * `action` is CURL_POLL_IN, CURL_POLL_OUT or CURL_POLL_INOUT.
+ */
+struct easy_pollset {
+ curl_socket_t sockets[MAX_SOCKSPEREASYHANDLE];
+ unsigned int num;
+ unsigned char actions[MAX_SOCKSPEREASYHANDLE];
+};
+
enum expect100 {
EXP100_SEND_DATA, /* enough waiting, just send the body now */
EXP100_AWAITING_CONTINUE, /* waiting for the 100 Continue header */
@@ -649,16 +672,8 @@ struct SingleRequest {
counter to make only a 100 reply (without
a following second response code) result
in a CURLE_GOT_NOTHING error code */
- enum {
- HEADER_NORMAL, /* no bad header at all */
- HEADER_PARTHEADER, /* part of the chunk is a bad header, the rest
- is normal data */
- HEADER_ALLBAD /* all was believed to be header */
- } badheader; /* the header was deemed bad and will be
- written as body */
int headerline; /* counts header lines to better track the
first one */
- char *str; /* within buf */
curl_off_t offset; /* possible resume offset read from the
Content-Range: header */
int httpcode; /* error code from the 'HTTP/1.? XXX' or
@@ -669,7 +684,7 @@ struct SingleRequest {
enum upgrade101 upgr101; /* 101 upgrade state */
/* Content unencoding stack. See sec 3.5, RFC2616. */
- struct contenc_writer *writer_stack;
+ struct Curl_cwriter *writer_stack;
time_t timeofdoc;
long bodywrites;
char *location; /* This points to an allocated version of the Location:
@@ -706,16 +721,20 @@ struct SingleRequest {
#ifndef CURL_DISABLE_DOH
struct dohdata *doh; /* DoH specific data for this request */
#endif
-#if defined(WIN32) && defined(USE_WINSOCK)
+#if defined(_WIN32) && defined(USE_WINSOCK)
struct curltime last_sndbuf_update; /* last time readwrite_upload called
win_update_buffer_size */
#endif
+ char fread_eof[2]; /* the body read callback (index 0) returned EOF or
+ the trailer read callback (index 1) returned EOF */
#ifndef CURL_DISABLE_COOKIES
unsigned char setcookies;
#endif
unsigned char writer_stack_depth; /* Unencoding stack depth. */
BIT(header); /* incoming data has HTTP header */
+ BIT(badheader); /* header parsing found sth not a header */
BIT(content_range); /* set TRUE if Content-Range: was found */
+ BIT(download_done); /* set to TRUE when download is complete */
BIT(upload_done); /* set to TRUE when doing chunked transfer-encoding
upload and we're uploading the last chunk */
BIT(ignorebody); /* we read a response-body but we ignore it! */
@@ -799,7 +818,8 @@ struct Curl_handler {
/* If used, this function gets called from transfer.c:readwrite_data() to
allow the protocol to do extra reads/writes */
CURLcode (*readwrite)(struct Curl_easy *data, struct connectdata *conn,
- ssize_t *nread, bool *readmore);
+ const char *buf, size_t blen,
+ size_t *pconsumed, bool *readmore);
/* This function can perform various checks on the connection. See
CONNCHECK_* for more information about the checks that can be performed,
@@ -901,6 +921,9 @@ struct connectdata {
multi_done(). This entry will be NULL if the connection is reused as then
there is no name resolve done. */
struct Curl_dns_entry *dns_entry;
+#ifdef USE_CURL_ASYNC
+ struct Curl_async resolve_async; /* asynchronous name resolver data */
+#endif
/* 'remote_addr' is the particular IP we connected to. it is owned, set
* and NULLed by the connected socket filter (if there is one). */
@@ -1325,7 +1348,8 @@ struct UrlState {
curl_off_t recent_conn_id; /* The most recent connection used, might no
* longer exist */
struct dynbuf headerb; /* buffer to store headers in */
-
+ struct curl_slist *hstslist; /* list of HSTS files set by
+ curl_easy_setopt(HSTS) calls */
char *buffer; /* download buffer */
char *ulbuf; /* allocated upload buffer or NULL */
curl_off_t current_speed; /* the ProgressShow() function sets this,
@@ -1358,9 +1382,6 @@ struct UrlState {
#endif
struct auth authhost; /* auth details for host */
struct auth authproxy; /* auth details for proxy */
-#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 */
@@ -1373,7 +1394,7 @@ struct UrlState {
/* a place to store the most recently set (S)FTP entrypath */
char *most_recent_ftp_entrypath;
-#if !defined(WIN32) && !defined(MSDOS) && !defined(__EMX__)
+#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 */
@@ -1411,7 +1432,7 @@ struct UrlState {
this should be dealt with in pretransfer */
#ifndef CURL_DISABLE_HTTP
curl_mimepart *mimepost;
- curl_mimepart *formp; /* storage for old API form-posting, alloced on
+ curl_mimepart *formp; /* storage for old API form-posting, allocated on
demand */
size_t trailers_bytes_sent;
struct dynbuf trailers_buf; /* a buffer containing the compiled trailing
@@ -1422,6 +1443,10 @@ struct UrlState {
trailers_state trailers_state; /* whether we are sending trailers
and what stage are we at */
#endif
+#ifndef CURL_DISABLE_COOKIES
+ struct curl_slist *cookielist; /* list of cookie files set by
+ curl_easy_setopt(COOKIEFILE) calls */
+#endif
#ifdef USE_HYPER
bool hconnect; /* set if a CONNECT request */
CURLcode hresult; /* used to pass return codes back from hyper callbacks */
@@ -1498,6 +1523,9 @@ struct UrlState {
though it will be discarded. We must call the data
rewind callback before trying to send again. */
BIT(upload); /* upload request */
+ BIT(internal); /* internal: true if this easy handle was created for
+ internal use and the user does not have ownership of the
+ handle. */
};
/*
@@ -1674,13 +1702,7 @@ struct UserDefined {
void *prereq_userp; /* pre-initial request user data */
void *seek_client; /* pointer to pass to the seek callback */
-#ifndef CURL_DISABLE_COOKIES
- struct curl_slist *cookielist; /* list of cookie files set by
- curl_easy_setopt(COOKIEFILE) calls */
-#endif
#ifndef CURL_DISABLE_HSTS
- struct curl_slist *hstslist; /* list of HSTS files set by
- curl_easy_setopt(HSTS) calls */
curl_hstsread_callback hsts_read;
void *hsts_read_userp;
curl_hstswrite_callback hsts_write;
@@ -1780,9 +1802,6 @@ struct UserDefined {
#endif
curl_prot_t allowed_protocols;
curl_prot_t redir_protocols;
-#ifndef CURL_DISABLE_MIME
- unsigned int mime_options; /* Mime option flags. */
-#endif
#ifndef CURL_DISABLE_RTSP
void *rtp_out; /* write RTP to this if non-NULL */
/* Common RTSP header options */
@@ -1805,8 +1824,6 @@ struct UserDefined {
int tcp_keepidle; /* seconds in idle before sending keepalive probe */
int tcp_keepintvl; /* seconds between TCP keepalive probes */
- size_t maxconnects; /* Max idle connections in the connection cache */
-
long expect_100_timeout; /* in milliseconds */
#if defined(USE_HTTP2) || defined(USE_HTTP3)
struct Curl_data_priority priority;
@@ -1831,10 +1848,14 @@ struct UserDefined {
BIT(mail_rcpt_allowfails); /* allow RCPT TO command to fail for some
recipients */
#endif
+ unsigned int maxconnects; /* Max idle connections in the connection cache */
unsigned char use_ssl; /* if AUTH TLS is to be attempted etc, for FTP or
IMAP or POP3 or others! (type: curl_usessl)*/
unsigned char connect_only; /* make connection/request, then let
application use the socket */
+#ifndef CURL_DISABLE_MIME
+ BIT(mime_formescape);
+#endif
BIT(is_fread_set); /* has read callback been set to non-NULL? */
#ifndef CURL_DISABLE_TFTP
BIT(tftp_no_options); /* do not send TFTP options requests */
@@ -1971,10 +1992,7 @@ struct Curl_easy {
particular order. Note that all sockets are added to the sockhash, where
the state etc are also kept. This array is mostly used to detect when a
socket is to be removed from the hash. See singlesocket(). */
- curl_socket_t sockets[MAX_SOCKSPEREASYHANDLE];
- unsigned char actions[MAX_SOCKSPEREASYHANDLE]; /* action for each socket in
- sockets[] */
- int numsocks;
+ struct easy_pollset last_poll;
struct Names dns;
struct Curl_multi *multi; /* if non-NULL, points to the multi handle
@@ -2013,10 +2031,6 @@ struct Curl_easy {
#ifdef USE_HYPER
struct hyptransfer hyp;
#endif
-
- /* internal: true if this easy handle was created for internal use and the
- user does not have ownership of the handle. */
- bool internal;
};
#define LIBCURL_NAME "libcurl"
diff --git a/libs/libcurl/src/vauth/digest.c b/libs/libcurl/src/vauth/digest.c
index e73302ff6a..166b66e0fb 100644
--- a/libs/libcurl/src/vauth/digest.c
+++ b/libs/libcurl/src/vauth/digest.c
@@ -125,7 +125,6 @@ bool Curl_auth_digest_get_pair(const char *str, char *value, char *content,
}
else
return FALSE;
- break;
}
}
diff --git a/libs/libcurl/src/version.c b/libs/libcurl/src/version.c
index 97de3340c4..86c8aff13b 100644
--- a/libs/libcurl/src/version.c
+++ b/libs/libcurl/src/version.c
@@ -39,7 +39,7 @@
#ifdef USE_ARES
# if defined(CURL_STATICLIB) && !defined(CARES_STATICLIB) && \
- defined(WIN32)
+ defined(_WIN32)
# define CARES_STATICLIB
# endif
# include <ares.h>
@@ -409,7 +409,8 @@ static int idn_present(curl_version_info_data *info)
#define idn_present NULL
#endif
-#if defined(USE_SSL) && !defined(CURL_DISABLE_PROXY)
+#if defined(USE_SSL) && !defined(CURL_DISABLE_PROXY) && \
+ !defined(CURL_DISABLE_HTTP)
static int https_proxy_present(curl_version_info_data *info)
{
(void) info;
@@ -454,13 +455,14 @@ static const struct feat features_table[] = {
#ifndef CURL_DISABLE_HSTS
FEATURE("HSTS", NULL, CURL_VERSION_HSTS),
#endif
-#if defined(USE_NGHTTP2) || defined(USE_HYPER)
+#if defined(USE_NGHTTP2)
FEATURE("HTTP2", NULL, CURL_VERSION_HTTP2),
#endif
#if defined(ENABLE_QUIC)
FEATURE("HTTP3", NULL, CURL_VERSION_HTTP3),
#endif
-#if defined(USE_SSL) && !defined(CURL_DISABLE_PROXY)
+#if defined(USE_SSL) && !defined(CURL_DISABLE_PROXY) && \
+ !defined(CURL_DISABLE_HTTP)
FEATURE("HTTPS-proxy", https_proxy_present, CURL_VERSION_HTTPS_PROXY),
#endif
#if defined(USE_LIBIDN2) || defined(USE_WIN32_IDN)
@@ -510,7 +512,7 @@ static const struct feat features_table[] = {
#ifdef CURLDEBUG
FEATURE("TrackMemory", NULL, CURL_VERSION_CURLDEBUG),
#endif
-#if defined(WIN32) && defined(UNICODE) && defined(_UNICODE)
+#if defined(_WIN32) && defined(UNICODE) && defined(_UNICODE)
FEATURE("Unicode", NULL, CURL_VERSION_UNICODE),
#endif
#ifdef USE_UNIX_SOCKETS
diff --git a/libs/libcurl/src/version_win32.c b/libs/libcurl/src/version_win32.c
index 042c1ba13f..8759dcc325 100644
--- a/libs/libcurl/src/version_win32.c
+++ b/libs/libcurl/src/version_win32.c
@@ -24,7 +24,7 @@
#include "curl_setup.h"
-#if defined(WIN32)
+#if defined(_WIN32)
#include <curl/curl.h>
#include "version_win32.h"
@@ -316,4 +316,4 @@ bool curlx_verify_windows_version(const unsigned int majorVersion,
return matched;
}
-#endif /* WIN32 */
+#endif /* _WIN32 */
diff --git a/libs/libcurl/src/version_win32.h b/libs/libcurl/src/version_win32.h
index 9a8c317fb3..f45270c8f4 100644
--- a/libs/libcurl/src/version_win32.h
+++ b/libs/libcurl/src/version_win32.h
@@ -26,7 +26,7 @@
#include "curl_setup.h"
-#if defined(WIN32)
+#if defined(_WIN32)
/* Version condition */
typedef enum {
@@ -51,6 +51,6 @@ bool curlx_verify_windows_version(const unsigned int majorVersion,
const PlatformIdentifier platform,
const VersionCondition condition);
-#endif /* WIN32 */
+#endif /* _WIN32 */
#endif /* HEADER_CURL_VERSION_WIN32_H */
diff --git a/libs/libcurl/src/vquic/curl_msh3.c b/libs/libcurl/src/vquic/curl_msh3.c
index 5d31e234d8..bf8220470c 100644
--- a/libs/libcurl/src/vquic/curl_msh3.c
+++ b/libs/libcurl/src/vquic/curl_msh3.c
@@ -38,6 +38,7 @@
#include "http1.h"
#include "curl_msh3.h"
#include "socketpair.h"
+#include "vtls/vtls.h"
#include "vquic/vquic.h"
/* The last 3 #include files should be in this order */
@@ -45,6 +46,10 @@
#include "curl_memory.h"
#include "memdebug.h"
+#ifdef CURL_DISABLE_SOCKETPAIR
+#error "MSH3 cannot be build with CURL_DISABLE_SOCKETPAIR set"
+#endif
+
#define H3_STREAM_WINDOW_SIZE (128 * 1024)
#define H3_STREAM_CHUNK_SIZE (16 * 1024)
#define H3_STREAM_RECV_CHUNKS \
@@ -672,31 +677,25 @@ out:
return nwritten;
}
-static int cf_msh3_get_select_socks(struct Curl_cfilter *cf,
- struct Curl_easy *data,
- curl_socket_t *socks)
+static void cf_msh3_adjust_pollset(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ struct easy_pollset *ps)
{
struct cf_msh3_ctx *ctx = cf->ctx;
struct stream_ctx *stream = H3_STREAM_CTX(data);
- int bitmap = GETSOCK_BLANK;
struct cf_call_data save;
CF_DATA_SAVE(save, cf, data);
if(stream && ctx->sock[SP_LOCAL] != CURL_SOCKET_BAD) {
- socks[0] = ctx->sock[SP_LOCAL];
-
if(stream->recv_error) {
- bitmap |= GETSOCK_READSOCK(0);
+ Curl_pollset_add_in(data, ps, ctx->sock[SP_LOCAL]);
drain_stream(cf, data);
}
else if(stream->req) {
- bitmap |= GETSOCK_READSOCK(0);
+ Curl_pollset_add_out(data, ps, ctx->sock[SP_LOCAL]);
drain_stream(cf, data);
}
}
- CURL_TRC_CF(data, cf, "select_sock -> %d", bitmap);
- CF_DATA_RESTORE(cf, save);
- return bitmap;
}
static bool cf_msh3_data_pending(struct Curl_cfilter *cf,
@@ -802,14 +801,20 @@ static CURLcode cf_connect_start(struct Curl_cfilter *cf,
struct Curl_easy *data)
{
struct cf_msh3_ctx *ctx = cf->ctx;
- bool verify = !!cf->conn->ssl_config.verifypeer;
+ struct ssl_primary_config *conn_config;
MSH3_ADDR addr = {0};
CURLcode result;
+ bool verify;
+
+ conn_config = Curl_ssl_cf_get_primary_config(cf);
+ if(!conn_config)
+ return CURLE_FAILED_INIT;
+ verify = !!conn_config->verifypeer;
memcpy(&addr, &ctx->addr.sa_addr, ctx->addr.addrlen);
MSH3_SET_PORT(&addr, (uint16_t)cf->conn->remote_port);
- if(verify && (cf->conn->ssl_config.CAfile || cf->conn->ssl_config.CApath)) {
+ if(verify && (conn_config->CAfile || conn_config->CApath)) {
/* TODO: need a way to provide trust anchors to MSH3 */
#ifdef DEBUGBUILD
/* we need this for our test cases to run */
@@ -1025,7 +1030,7 @@ struct Curl_cftype Curl_cft_http3 = {
cf_msh3_connect,
cf_msh3_close,
Curl_cf_def_get_host,
- cf_msh3_get_select_socks,
+ cf_msh3_adjust_pollset,
cf_msh3_data_pending,
cf_msh3_send,
cf_msh3_recv,
@@ -1047,7 +1052,7 @@ CURLcode Curl_cf_msh3_create(struct Curl_cfilter **pcf,
(void)data;
(void)conn;
(void)ai; /* TODO: msh3 resolves itself? */
- ctx = calloc(sizeof(*ctx), 1);
+ ctx = calloc(1, sizeof(*ctx));
if(!ctx) {
result = CURLE_OUT_OF_MEMORY;
goto out;
diff --git a/libs/libcurl/src/vquic/curl_ngtcp2.c b/libs/libcurl/src/vquic/curl_ngtcp2.c
index 1be49f389b..9584065f5a 100644
--- a/libs/libcurl/src/vquic/curl_ngtcp2.c
+++ b/libs/libcurl/src/vquic/curl_ngtcp2.c
@@ -78,7 +78,6 @@
#define QUIC_MAX_STREAMS (256*1024)
#define QUIC_MAX_DATA (1*1024*1024)
-#define QUIC_IDLE_TIMEOUT (60*NGTCP2_SECONDS)
#define QUIC_HANDSHAKE_TIMEOUT (10*NGTCP2_SECONDS)
/* A stream window is the maximum amount we need to buffer for
@@ -134,6 +133,7 @@ void Curl_ngtcp2_ver(char *p, size_t len)
struct cf_ngtcp2_ctx {
struct cf_quic_ctx q;
+ struct ssl_peer peer;
ngtcp2_path connected_path;
ngtcp2_conn *qconn;
ngtcp2_cid dcid;
@@ -161,6 +161,7 @@ struct cf_ngtcp2_ctx {
struct curltime reconnect_at; /* time the next attempt should start */
struct bufc_pool stream_bufcp; /* chunk pool for streams */
size_t max_stream_window; /* max flow window for one stream */
+ uint64_t max_idle_ms; /* max idle time for QUIC connection */
int qlogfd;
BIT(got_first_byte); /* if first byte was received */
#ifdef USE_OPENSSL
@@ -191,6 +192,7 @@ struct h3_stream_ctx {
bool closed; /* TRUE on stream close */
bool reset; /* TRUE on stream reset */
bool send_closed; /* stream is local closed */
+ BIT(quic_flow_blocked); /* stream is blocked by QUIC flow control */
};
#define H3_STREAM_CTX(d) ((struct h3_stream_ctx *)(((d) && (d)->req.p.http)? \
@@ -236,11 +238,21 @@ static CURLcode h3_data_setup(struct Curl_cfilter *cf,
static void h3_data_done(struct Curl_cfilter *cf, struct Curl_easy *data)
{
+ struct cf_ngtcp2_ctx *ctx = cf->ctx;
struct h3_stream_ctx *stream = H3_STREAM_CTX(data);
(void)cf;
if(stream) {
CURL_TRC_CF(data, cf, "[%"PRId64"] easy handle is done", stream->id);
+ if(ctx->h3conn && !stream->closed) {
+ nghttp3_conn_shutdown_stream_read(ctx->h3conn, stream->id);
+ nghttp3_conn_close_stream(ctx->h3conn, stream->id,
+ NGHTTP3_H3_REQUEST_CANCELLED);
+ nghttp3_conn_set_stream_user_data(ctx->h3conn, stream->id, NULL);
+ ngtcp2_conn_set_stream_user_data(ctx->qconn, stream->id, NULL);
+ stream->closed = TRUE;
+ }
+
Curl_bufq_free(&stream->sendbuf);
Curl_bufq_free(&stream->recvbuf);
Curl_h1_req_parse_free(&stream->h1);
@@ -249,6 +261,43 @@ static void h3_data_done(struct Curl_cfilter *cf, struct Curl_easy *data)
}
}
+static struct Curl_easy *get_stream_easy(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ int64_t stream_id)
+{
+ struct Curl_easy *sdata;
+
+ (void)cf;
+ if(H3_STREAM_ID(data) == stream_id) {
+ return data;
+ }
+ else {
+ DEBUGASSERT(data->multi);
+ for(sdata = data->multi->easyp; sdata; sdata = sdata->next) {
+ if((sdata->conn == data->conn) && H3_STREAM_ID(sdata) == stream_id) {
+ return sdata;
+ }
+ }
+ }
+ return NULL;
+}
+
+static void h3_drain_stream(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
+{
+ struct h3_stream_ctx *stream = H3_STREAM_CTX(data);
+ unsigned char bits;
+
+ (void)cf;
+ bits = CURL_CSELECT_IN;
+ if(stream && stream->upload_left && !stream->send_closed)
+ bits |= CURL_CSELECT_OUT;
+ if(data->state.dselect_bits != bits) {
+ data->state.dselect_bits = bits;
+ Curl_expire(data, 0, EXPIRE_RUN_NOW);
+ }
+}
+
/* ngtcp2 default congestion controller does not perform pacing. Limit
the maximum packet burst to MAX_PKT_BURST packets. */
#define MAX_PKT_BURST 10
@@ -261,10 +310,14 @@ struct pkt_io_ctx {
ngtcp2_path_storage ps;
};
-static ngtcp2_tstamp timestamp(void)
+static void pktx_update_time(struct pkt_io_ctx *pktx,
+ struct Curl_cfilter *cf)
{
- struct curltime ct = Curl_now();
- return ct.tv_sec * NGTCP2_SECONDS + ct.tv_usec * NGTCP2_MICROSECONDS;
+ struct cf_ngtcp2_ctx *ctx = cf->ctx;
+
+ vquic_ctx_update_time(&ctx->q);
+ pktx->ts = ctx->q.last_op.tv_sec * NGTCP2_SECONDS +
+ ctx->q.last_op.tv_usec * NGTCP2_MICROSECONDS;
}
static void pktx_init(struct pkt_io_ctx *pktx,
@@ -273,9 +326,9 @@ static void pktx_init(struct pkt_io_ctx *pktx,
{
pktx->cf = cf;
pktx->data = data;
- pktx->ts = timestamp();
pktx->pkt_count = 0;
ngtcp2_path_storage_zero(&pktx->ps);
+ pktx_update_time(pktx, cf);
}
static CURLcode cf_progress_ingress(struct Curl_cfilter *cf,
@@ -354,7 +407,7 @@ static void quic_settings(struct cf_ngtcp2_ctx *ctx,
t->initial_max_stream_data_uni = ctx->max_stream_window;
t->initial_max_streams_bidi = QUIC_MAX_STREAMS;
t->initial_max_streams_uni = QUIC_MAX_STREAMS;
- t->max_idle_timeout = QUIC_IDLE_TIMEOUT;
+ t->max_idle_timeout = (ctx->max_idle_ms * NGTCP2_MILLISECONDS);
if(ctx->qlogfd != -1) {
s->qlog_write = qlog_callback;
}
@@ -398,14 +451,19 @@ static CURLcode quic_ssl_ctx(SSL_CTX **pssl_ctx,
struct Curl_cfilter *cf, struct Curl_easy *data)
{
struct cf_ngtcp2_ctx *ctx = cf->ctx;
- struct connectdata *conn = cf->conn;
+ struct ssl_primary_config *conn_config;
CURLcode result = CURLE_FAILED_INIT;
- SSL_CTX *ssl_ctx = SSL_CTX_new(TLS_method());
+ SSL_CTX *ssl_ctx = SSL_CTX_new(TLS_method());
if(!ssl_ctx) {
result = CURLE_OUT_OF_MEMORY;
goto out;
}
+ conn_config = Curl_ssl_cf_get_primary_config(cf);
+ if(!conn_config) {
+ result = CURLE_FAILED_INIT;
+ goto out;
+ }
#if defined(OPENSSL_IS_BORINGSSL) || defined(OPENSSL_IS_AWSLC)
if(ngtcp2_crypto_boringssl_configure_client_context(ssl_ctx) != 0) {
@@ -422,8 +480,8 @@ static CURLcode quic_ssl_ctx(SSL_CTX **pssl_ctx,
SSL_CTX_set_default_verify_paths(ssl_ctx);
{
- const char *curves = conn->ssl_config.curves ?
- conn->ssl_config.curves : QUIC_GROUPS;
+ const char *curves = conn_config->curves ?
+ conn_config->curves : QUIC_GROUPS;
if(!SSL_CTX_set1_curves_list(ssl_ctx, curves)) {
failf(data, "failed setting curves list for QUIC: '%s'", curves);
return CURLE_SSL_CIPHER;
@@ -432,8 +490,8 @@ static CURLcode quic_ssl_ctx(SSL_CTX **pssl_ctx,
#ifndef OPENSSL_IS_BORINGSSL
{
- const char *ciphers13 = conn->ssl_config.cipher_list13 ?
- conn->ssl_config.cipher_list13 : QUIC_CIPHERS;
+ const char *ciphers13 = conn_config->cipher_list13 ?
+ conn_config->cipher_list13 : QUIC_CIPHERS;
if(SSL_CTX_set_ciphersuites(ssl_ctx, ciphers13) != 1) {
failf(data, "failed setting QUIC cipher suite: %s", ciphers13);
return CURLE_SSL_CIPHER;
@@ -452,7 +510,7 @@ static CURLcode quic_ssl_ctx(SSL_CTX **pssl_ctx,
* fail to connect if the verification fails, or if it should continue
* anyway. In the latter case the result of the verification is checked with
* SSL_get_verify_result() below. */
- SSL_CTX_set_verify(ssl_ctx, conn->ssl_config.verifypeer ?
+ SSL_CTX_set_verify(ssl_ctx, conn_config->verifypeer ?
SSL_VERIFY_PEER : SSL_VERIFY_NONE, NULL);
/* give application a chance to interfere with SSL set up. */
@@ -491,7 +549,7 @@ static CURLcode quic_set_client_cert(struct Curl_cfilter *cf,
SSL_CTX *ssl_ctx = ctx->sslctx;
const struct ssl_config_data *ssl_config;
- ssl_config = Curl_ssl_get_config(data, FIRSTSOCKET);
+ ssl_config = Curl_ssl_cf_get_config(cf, data);
DEBUGASSERT(ssl_config);
if(ssl_config->primary.clientcert || ssl_config->primary.cert_blob
@@ -514,7 +572,6 @@ static CURLcode quic_init_ssl(struct Curl_cfilter *cf,
struct cf_ngtcp2_ctx *ctx = cf->ctx;
const uint8_t *alpn = NULL;
size_t alpnlen = 0;
- unsigned char checkip[16];
DEBUGASSERT(!ctx->ssl);
ctx->ssl = SSL_new(ctx->sslctx);
@@ -529,13 +586,8 @@ static CURLcode quic_init_ssl(struct Curl_cfilter *cf,
SSL_set_alpn_protos(ctx->ssl, alpn, (int)alpnlen);
/* set SNI */
- if((0 == Curl_inet_pton(AF_INET, cf->conn->host.name, checkip))
-#ifdef ENABLE_IPV6
- && (0 == Curl_inet_pton(AF_INET6, cf->conn->host.name, checkip))
-#endif
- ) {
- char *snihost = Curl_ssl_snihost(data, cf->conn->host.name, NULL);
- if(!snihost || !SSL_set_tlsext_host_name(ctx->ssl, snihost)) {
+ if(ctx->peer.sni) {
+ if(!SSL_set_tlsext_host_name(ctx->ssl, ctx->peer.sni)) {
failf(data, "Failed set SNI");
SSL_free(ctx->ssl);
ctx->ssl = NULL;
@@ -549,20 +601,24 @@ static CURLcode quic_init_ssl(struct Curl_cfilter *cf,
struct Curl_easy *data)
{
struct cf_ngtcp2_ctx *ctx = cf->ctx;
+ struct ssl_primary_config *conn_config;
CURLcode result;
gnutls_datum_t alpn[2];
/* this will need some attention when HTTPS proxy over QUIC get fixed */
- const char * const hostname = cf->conn->host.name;
long * const pverifyresult = &data->set.ssl.certverifyresult;
int rc;
+ conn_config = Curl_ssl_cf_get_primary_config(cf);
+ if(!conn_config)
+ return CURLE_FAILED_INIT;
+
DEBUGASSERT(ctx->gtls == NULL);
ctx->gtls = calloc(1, sizeof(*(ctx->gtls)));
if(!ctx->gtls)
return CURLE_OUT_OF_MEMORY;
- result = gtls_client_init(data, &cf->conn->ssl_config, &data->set.ssl,
- hostname, ctx->gtls, pverifyresult);
+ result = gtls_client_init(data, conn_config, &data->set.ssl,
+ &ctx->peer, ctx->gtls, pverifyresult);
if(result)
return result;
@@ -602,10 +658,17 @@ static CURLcode quic_init_ssl(struct Curl_cfilter *cf,
static CURLcode quic_ssl_ctx(WOLFSSL_CTX **pssl_ctx,
struct Curl_cfilter *cf, struct Curl_easy *data)
{
- struct connectdata *conn = cf->conn;
CURLcode result = CURLE_FAILED_INIT;
- WOLFSSL_CTX *ssl_ctx = wolfSSL_CTX_new(wolfTLSv1_3_client_method());
+ struct ssl_primary_config *conn_config;
+ WOLFSSL_CTX *ssl_ctx = NULL;
+ conn_config = Curl_ssl_cf_get_primary_config(cf);
+ if(!conn_config) {
+ result = CURLE_FAILED_INIT;
+ goto out;
+ }
+
+ ssl_ctx = wolfSSL_CTX_new(wolfTLSv1_3_client_method());
if(!ssl_ctx) {
result = CURLE_OUT_OF_MEMORY;
goto out;
@@ -613,13 +676,14 @@ static CURLcode quic_ssl_ctx(WOLFSSL_CTX **pssl_ctx,
if(ngtcp2_crypto_wolfssl_configure_client_context(ssl_ctx) != 0) {
failf(data, "ngtcp2_crypto_wolfssl_configure_client_context failed");
+ result = CURLE_FAILED_INIT;
goto out;
}
wolfSSL_CTX_set_default_verify_paths(ssl_ctx);
- if(wolfSSL_CTX_set_cipher_list(ssl_ctx, conn->ssl_config.cipher_list13 ?
- conn->ssl_config.cipher_list13 :
+ if(wolfSSL_CTX_set_cipher_list(ssl_ctx, conn_config->cipher_list13 ?
+ conn_config->cipher_list13 :
QUIC_CIPHERS) != 1) {
char error_buffer[256];
ERR_error_string_n(ERR_get_error(), error_buffer, sizeof(error_buffer));
@@ -627,8 +691,8 @@ static CURLcode quic_ssl_ctx(WOLFSSL_CTX **pssl_ctx,
goto out;
}
- if(wolfSSL_CTX_set1_groups_list(ssl_ctx, conn->ssl_config.curves ?
- conn->ssl_config.curves :
+ if(wolfSSL_CTX_set1_groups_list(ssl_ctx, conn_config->curves ?
+ conn_config->curves :
(char *)QUIC_GROUPS) != 1) {
failf(data, "wolfSSL failed to set curves");
goto out;
@@ -645,9 +709,9 @@ static CURLcode quic_ssl_ctx(WOLFSSL_CTX **pssl_ctx,
#endif
}
- if(conn->ssl_config.verifypeer) {
- const char * const ssl_cafile = conn->ssl_config.CAfile;
- const char * const ssl_capath = conn->ssl_config.CApath;
+ if(conn_config->verifypeer) {
+ const char * const ssl_cafile = conn_config->CAfile;
+ const char * const ssl_capath = conn_config->CApath;
wolfSSL_CTX_set_verify(ssl_ctx, SSL_VERIFY_PEER, NULL);
if(ssl_cafile || ssl_capath) {
@@ -786,6 +850,12 @@ static int cb_recv_stream_data(ngtcp2_conn *tconn, uint32_t flags,
CURL_TRC_CF(data, cf, "[%" PRId64 "] read_stream(len=%zu) -> %zd",
stream_id, buflen, nconsumed);
if(nconsumed < 0) {
+ if(!data) {
+ struct Curl_easy *cdata = CF_DATA_CURRENT(cf);
+ CURL_TRC_CF(cdata, cf, "[%" PRId64 "] nghttp3 error on stream not "
+ "used by us, ignored", stream_id);
+ return 0;
+ }
ngtcp2_ccerr_set_application_error(
&ctx->last_error,
nghttp3_err_infer_quic_app_error_code((int)nconsumed), NULL, 0);
@@ -816,7 +886,7 @@ cb_acked_stream_data_offset(ngtcp2_conn *tconn, int64_t stream_id,
(void)stream_user_data;
rv = nghttp3_conn_add_ack_offset(ctx->h3conn, stream_id, datalen);
- if(rv) {
+ if(rv && rv != NGHTTP3_ERR_STREAM_NOT_FOUND) {
return NGTCP2_ERR_CALLBACK_FAILURE;
}
@@ -844,7 +914,7 @@ static int cb_stream_close(ngtcp2_conn *tconn, uint32_t flags,
app_error_code);
CURL_TRC_CF(data, cf, "[%" PRId64 "] quic close(err=%"
PRIu64 ") -> %d", stream3_id, app_error_code, rv);
- if(rv) {
+ if(rv && rv != NGHTTP3_ERR_STREAM_NOT_FOUND) {
ngtcp2_ccerr_set_application_error(
&ctx->last_error, nghttp3_err_infer_quic_app_error_code(rv), NULL, 0);
return NGTCP2_ERR_CALLBACK_FAILURE;
@@ -868,7 +938,7 @@ static int cb_stream_reset(ngtcp2_conn *tconn, int64_t stream_id,
rv = nghttp3_conn_shutdown_stream_read(ctx->h3conn, stream_id);
CURL_TRC_CF(data, cf, "[%" PRId64 "] reset -> %d", stream_id, rv);
- if(rv) {
+ if(rv && rv != NGHTTP3_ERR_STREAM_NOT_FOUND) {
return NGTCP2_ERR_CALLBACK_FAILURE;
}
@@ -887,7 +957,7 @@ static int cb_stream_stop_sending(ngtcp2_conn *tconn, int64_t stream_id,
(void)stream_user_data;
rv = nghttp3_conn_shutdown_stream_read(ctx->h3conn, stream_id);
- if(rv) {
+ if(rv && rv != NGHTTP3_ERR_STREAM_NOT_FOUND) {
return NGTCP2_ERR_CALLBACK_FAILURE;
}
@@ -911,16 +981,25 @@ static int cb_extend_max_stream_data(ngtcp2_conn *tconn, int64_t stream_id,
{
struct Curl_cfilter *cf = user_data;
struct cf_ngtcp2_ctx *ctx = cf->ctx;
+ struct Curl_easy *data = CF_DATA_CURRENT(cf);
+ struct Curl_easy *s_data;
+ struct h3_stream_ctx *stream;
int rv;
(void)tconn;
(void)max_data;
(void)stream_user_data;
rv = nghttp3_conn_unblock_stream(ctx->h3conn, stream_id);
- if(rv) {
+ if(rv && rv != NGHTTP3_ERR_STREAM_NOT_FOUND) {
return NGTCP2_ERR_CALLBACK_FAILURE;
}
-
+ s_data = get_stream_easy(cf, data, stream_id);
+ stream = H3_STREAM_CTX(s_data);
+ if(stream && stream->quic_flow_blocked) {
+ CURL_TRC_CF(data, cf, "[%" PRId64 "] unblock quic flow", stream_id);
+ stream->quic_flow_blocked = FALSE;
+ h3_drain_stream(cf, data);
+ }
return 0;
}
@@ -1038,7 +1117,7 @@ static CURLcode check_and_set_expiry(struct Curl_cfilter *cf,
pktx = &local_pktx;
}
else {
- pktx->ts = timestamp();
+ pktx_update_time(pktx, cf);
}
expiry = ngtcp2_conn_get_expiry(ctx->qconn);
@@ -1073,46 +1152,29 @@ static CURLcode check_and_set_expiry(struct Curl_cfilter *cf,
return CURLE_OK;
}
-static int cf_ngtcp2_get_select_socks(struct Curl_cfilter *cf,
+static void cf_ngtcp2_adjust_pollset(struct Curl_cfilter *cf,
struct Curl_easy *data,
- curl_socket_t *socks)
+ struct easy_pollset *ps)
{
struct cf_ngtcp2_ctx *ctx = cf->ctx;
- struct SingleRequest *k = &data->req;
- int rv = GETSOCK_BLANK;
- struct h3_stream_ctx *stream = H3_STREAM_CTX(data);
- struct cf_call_data save;
-
- CF_DATA_SAVE(save, cf, data);
- socks[0] = ctx->q.sockfd;
+ bool want_recv = CURL_WANT_RECV(data);
+ bool want_send = CURL_WANT_SEND(data);
- /* in HTTP/3 we can always get a frame, so check read */
- rv |= GETSOCK_READSOCK(0);
-
- /* we're still uploading or the HTTP/2 layer wants to send data */
- if((k->keepon & KEEP_SENDBITS) == KEEP_SEND &&
- ngtcp2_conn_get_cwnd_left(ctx->qconn) &&
- ngtcp2_conn_get_max_data_left(ctx->qconn) &&
- stream && nghttp3_conn_is_stream_writable(ctx->h3conn, stream->id))
- rv |= GETSOCK_WRITESOCK(0);
-
- CF_DATA_RESTORE(cf, save);
- return rv;
-}
-
-static void h3_drain_stream(struct Curl_cfilter *cf,
- struct Curl_easy *data)
-{
- struct h3_stream_ctx *stream = H3_STREAM_CTX(data);
- unsigned char bits;
+ if(ctx->qconn && (want_recv || want_send)) {
+ struct h3_stream_ctx *stream = H3_STREAM_CTX(data);
+ struct cf_call_data save;
+ bool c_exhaust, s_exhaust;
- (void)cf;
- bits = CURL_CSELECT_IN;
- if(stream && stream->upload_left && !stream->send_closed)
- bits |= CURL_CSELECT_OUT;
- if(data->state.dselect_bits != bits) {
- data->state.dselect_bits = bits;
- Curl_expire(data, 0, EXPIRE_RUN_NOW);
+ CF_DATA_SAVE(save, cf, data);
+ c_exhaust = !ngtcp2_conn_get_cwnd_left(ctx->qconn) ||
+ !ngtcp2_conn_get_max_data_left(ctx->qconn);
+ s_exhaust = stream && stream->id >= 0 && stream->quic_flow_blocked;
+ want_recv = (want_recv || c_exhaust || s_exhaust);
+ want_send = (!s_exhaust && want_send) ||
+ !Curl_bufq_is_empty(&ctx->q.sendbuf);
+
+ Curl_pollset_set(data, ps, ctx->q.sockfd, want_recv, want_send);
+ CF_DATA_RESTORE(cf, save);
}
}
@@ -1141,7 +1203,6 @@ static int cb_h3_stream_close(nghttp3_conn *conn, int64_t stream_id,
else {
CURL_TRC_CF(data, cf, "[%" PRId64 "] CLOSED", stream->id);
}
- data->req.keepon &= ~KEEP_SEND_HOLD;
h3_drain_stream(cf, data);
return 0;
}
@@ -1570,15 +1631,9 @@ static int cb_h3_acked_req_body(nghttp3_conn *conn, int64_t stream_id,
/* Everything ACKed, we resume upload processing */
if(!stream->sendbuf_len_in_flight) {
int rv = nghttp3_conn_resume_stream(conn, stream_id);
- if(rv) {
+ if(rv && rv != NGHTTP3_ERR_STREAM_NOT_FOUND) {
return NGTCP2_ERR_CALLBACK_FAILURE;
}
- if((data->req.keepon & KEEP_SEND_HOLD) &&
- (data->req.keepon & KEEP_SEND)) {
- data->req.keepon &= ~KEEP_SEND_HOLD;
- h3_drain_stream(cf, data);
- CURL_TRC_CF(data, cf, "[%" PRId64 "] unpausing acks", stream_id);
- }
}
return 0;
}
@@ -1676,6 +1731,10 @@ static ssize_t h3_stream_open(struct Curl_cfilter *cf,
goto out;
stream = H3_STREAM_CTX(data);
DEBUGASSERT(stream);
+ if(!stream) {
+ *err = CURLE_FAILED_INIT;
+ goto out;
+ }
nwritten = Curl_h1_req_parse_read(&stream->h1, buf, len, NULL, 0, err);
if(nwritten < 0)
@@ -1711,7 +1770,7 @@ static ssize_t h3_stream_open(struct Curl_cfilter *cf,
nva[i].flags = NGHTTP3_NV_FLAG_NONE;
}
- rc = ngtcp2_conn_open_bidi_stream(ctx->qconn, &stream->id, NULL);
+ rc = ngtcp2_conn_open_bidi_stream(ctx->qconn, &stream->id, data);
if(rc) {
failf(data, "can get bidi streams");
*err = CURLE_SEND_ERROR;
@@ -1860,15 +1919,13 @@ static ssize_t cf_ngtcp2_send(struct Curl_cfilter *cf, struct Curl_easy *data,
if(stream && sent > 0 && stream->sendbuf_len_in_flight) {
/* We have unacknowledged DATA and cannot report success to our
* caller. Instead we EAGAIN and remember how much we have already
- * "written" into our various internal connection buffers.
- * We put the stream upload on HOLD, until this gets ACKed. */
+ * "written" into our various internal connection buffers. */
stream->upload_blocked_len = sent;
CURL_TRC_CF(data, cf, "[%" PRId64 "] cf_send(len=%zu), "
"%zu bytes in flight -> EGAIN", stream->id, len,
stream->sendbuf_len_in_flight);
*err = CURLE_AGAIN;
sent = -1;
- data->req.keepon |= KEEP_SEND_HOLD;
}
out:
@@ -1887,40 +1944,37 @@ static CURLcode qng_verify_peer(struct Curl_cfilter *cf,
struct Curl_easy *data)
{
struct cf_ngtcp2_ctx *ctx = cf->ctx;
+ struct ssl_primary_config *conn_config;
CURLcode result = CURLE_OK;
- const char *hostname, *disp_hostname;
- int port;
- char *snihost;
- Curl_conn_get_host(data, cf->sockindex, &hostname, &disp_hostname, &port);
- snihost = Curl_ssl_snihost(data, hostname, NULL);
- if(!snihost)
- return CURLE_PEER_FAILED_VERIFICATION;
+ conn_config = Curl_ssl_cf_get_primary_config(cf);
+ if(!conn_config)
+ return CURLE_FAILED_INIT;
cf->conn->bits.multiplex = TRUE; /* at least potentially multiplexed */
cf->conn->httpversion = 30;
cf->conn->bundle->multiuse = BUNDLE_MULTIPLEX;
- if(cf->conn->ssl_config.verifyhost) {
+ if(conn_config->verifyhost) {
#ifdef USE_OPENSSL
X509 *server_cert;
- server_cert = SSL_get_peer_certificate(ctx->ssl);
+ server_cert = SSL_get1_peer_certificate(ctx->ssl);
if(!server_cert) {
return CURLE_PEER_FAILED_VERIFICATION;
}
- result = Curl_ossl_verifyhost(data, cf->conn, server_cert);
+ result = Curl_ossl_verifyhost(data, cf->conn, &ctx->peer, server_cert);
X509_free(server_cert);
if(result)
return result;
#elif defined(USE_GNUTLS)
result = Curl_gtls_verifyserver(data, ctx->gtls->session,
- &cf->conn->ssl_config, &data->set.ssl,
- hostname, disp_hostname,
+ conn_config, &data->set.ssl, &ctx->peer,
data->set.str[STRING_SSL_PINNEDPUBLICKEY]);
if(result)
return result;
#elif defined(USE_WOLFSSL)
- if(wolfSSL_check_domain_name(ctx->ssl, snihost) == SSL_FAILURE)
+ if(!ctx->peer.sni ||
+ wolfSSL_check_domain_name(ctx->ssl, ctx->peer.sni) == SSL_FAILURE)
return CURLE_PEER_FAILED_VERIFICATION;
#endif
infof(data, "Verified certificate just fine");
@@ -1955,8 +2009,8 @@ static CURLcode recv_pkt(const unsigned char *pkt, size_t pktlen,
rv = ngtcp2_conn_read_pkt(ctx->qconn, &path, &pi, pkt, pktlen, pktx->ts);
if(rv) {
- CURL_TRC_CF(pktx->data, pktx->cf, "ingress, read_pkt -> %s",
- ngtcp2_strerror(rv));
+ CURL_TRC_CF(pktx->data, pktx->cf, "ingress, read_pkt -> %s (%d)",
+ ngtcp2_strerror(rv), rv);
if(!ctx->last_error.error_code) {
if(rv == NGTCP2_ERR_CRYPTO) {
ngtcp2_ccerr_set_tls_alert(&ctx->last_error,
@@ -1993,7 +2047,7 @@ static CURLcode cf_progress_ingress(struct Curl_cfilter *cf,
pktx = &local_pktx;
}
else {
- pktx->ts = timestamp();
+ pktx_update_time(pktx, cf);
}
#ifdef USE_OPENSSL
@@ -2081,11 +2135,18 @@ static ssize_t read_pkt_to_send(void *userp,
}
else if(n < 0) {
switch(n) {
- case NGTCP2_ERR_STREAM_DATA_BLOCKED:
+ case NGTCP2_ERR_STREAM_DATA_BLOCKED: {
+ struct h3_stream_ctx *stream = H3_STREAM_CTX(x->data);
DEBUGASSERT(ndatalen == -1);
nghttp3_conn_block_stream(ctx->h3conn, stream_id);
+ CURL_TRC_CF(x->data, x->cf, "[%" PRId64 "] block quic flow",
+ stream_id);
+ DEBUGASSERT(stream);
+ if(stream)
+ stream->quic_flow_blocked = TRUE;
n = 0;
break;
+ }
case NGTCP2_ERR_STREAM_SHUT_WR:
DEBUGASSERT(ndatalen == -1);
nghttp3_conn_shutdown_stream_write(ctx->h3conn, stream_id);
@@ -2145,7 +2206,7 @@ static CURLcode cf_progress_egress(struct Curl_cfilter *cf,
pktx = &local_pktx;
}
else {
- pktx->ts = timestamp();
+ pktx_update_time(pktx, cf);
ngtcp2_path_storage_zero(&pktx->ps);
}
@@ -2282,10 +2343,12 @@ static CURLcode cf_ngtcp2_data_event(struct Curl_cfilter *cf,
case CF_CTRL_DATA_PAUSE:
result = h3_data_pause(cf, data, (arg1 != 0));
break;
- case CF_CTRL_DATA_DONE: {
+ case CF_CTRL_DATA_DETACH:
+ h3_data_done(cf, data);
+ break;
+ case CF_CTRL_DATA_DONE:
h3_data_done(cf, data);
break;
- }
case CF_CTRL_DATA_DONE_SEND: {
struct h3_stream_ctx *stream = H3_STREAM_CTX(data);
if(stream && !stream->send_closed) {
@@ -2344,6 +2407,7 @@ static void cf_ngtcp2_ctx_clear(struct cf_ngtcp2_ctx *ctx)
if(ctx->qconn)
ngtcp2_conn_del(ctx->qconn);
Curl_bufcp_free(&ctx->stream_bufcp);
+ Curl_ssl_peer_cleanup(&ctx->peer);
memset(ctx, 0, sizeof(*ctx));
ctx->qlogfd = -1;
@@ -2358,15 +2422,15 @@ static void cf_ngtcp2_close(struct Curl_cfilter *cf, struct Curl_easy *data)
CF_DATA_SAVE(save, cf, data);
if(ctx && ctx->qconn) {
char buffer[NGTCP2_MAX_UDP_PAYLOAD_SIZE];
- ngtcp2_tstamp ts;
+ struct pkt_io_ctx pktx;
ngtcp2_ssize rc;
CURL_TRC_CF(data, cf, "close");
- ts = timestamp();
+ pktx_init(&pktx, cf, data);
rc = ngtcp2_conn_write_connection_close(ctx->qconn, NULL, /* path */
NULL, /* pkt_info */
(uint8_t *)buffer, sizeof(buffer),
- &ctx->last_error, ts);
+ &ctx->last_error, pktx.ts);
if(rc > 0) {
while((send(ctx->q.sockfd, buffer, (SEND_TYPE_ARG3)rc, 0) == -1) &&
SOCKERRNO == EINTR);
@@ -2411,9 +2475,14 @@ static CURLcode cf_connect_start(struct Curl_cfilter *cf,
ctx->version = NGTCP2_PROTO_VER_MAX;
ctx->max_stream_window = H3_STREAM_WINDOW_SIZE;
+ ctx->max_idle_ms = CURL_QUIC_MAX_IDLE_MS;
Curl_bufcp_init(&ctx->stream_bufcp, H3_STREAM_CHUNK_SIZE,
H3_STREAM_POOL_SPARES);
+ result = Curl_ssl_peer_init(&ctx->peer, cf);
+ if(result)
+ return result;
+
#ifdef USE_OPENSSL
result = quic_ssl_ctx(&ctx->sslctx, cf, data);
if(result)
@@ -2559,27 +2628,9 @@ out:
ngtcp2_conn_in_draining_period(ctx->qconn)) {
/* When a QUIC server instance is shutting down, it may send us a
* CONNECTION_CLOSE right away. Our connection then enters the DRAINING
- * state.
- * This may be a stopping of the service or it may be that the server
- * is reloading and a new instance will start serving soon.
- * In any case, we tear down our socket and start over with a new one.
- * We re-open the underlying UDP cf right now, but do not start
- * connecting until called again.
- */
- int reconn_delay_ms = 200;
-
- CURL_TRC_CF(data, cf, "connect, remote closed, reconnect after %dms",
- reconn_delay_ms);
- Curl_conn_cf_close(cf->next, data);
- cf_ngtcp2_ctx_clear(ctx);
- result = Curl_conn_cf_connect(cf->next, data, FALSE, done);
- if(!result && *done) {
- *done = FALSE;
- ctx->reconnect_at = now;
- ctx->reconnect_at.tv_usec += reconn_delay_ms * 1000;
- Curl_expire(data, reconn_delay_ms, EXPIRE_QUIC);
- result = CURLE_OK;
- }
+ * state. The CONNECT may work in the near future again. Indicate
+ * that as a "weird" reply. */
+ result = CURLE_WEIRD_SERVER_REPLY;
}
#ifndef CURL_DISABLE_VERBOSE_STRINGS
@@ -2657,24 +2708,51 @@ static bool cf_ngtcp2_conn_is_alive(struct Curl_cfilter *cf,
struct Curl_easy *data,
bool *input_pending)
{
- bool alive = TRUE;
+ struct cf_ngtcp2_ctx *ctx = cf->ctx;
+ bool alive = FALSE;
+ const ngtcp2_transport_params *rp;
+ struct cf_call_data save;
+ CF_DATA_SAVE(save, cf, data);
*input_pending = FALSE;
+ if(!ctx->qconn)
+ goto out;
+
+ /* Both sides of the QUIC connection announce they max idle times in
+ * the transport parameters. Look at the minimum of both and if
+ * we exceed this, regard the connection as dead. The other side
+ * may have completely purged it and will no longer respond
+ * to any packets from us. */
+ rp = ngtcp2_conn_get_remote_transport_params(ctx->qconn);
+ if(rp) {
+ timediff_t idletime;
+ uint64_t idle_ms = ctx->max_idle_ms;
+
+ if(rp->max_idle_timeout &&
+ (rp->max_idle_timeout / NGTCP2_MILLISECONDS) < idle_ms)
+ idle_ms = (rp->max_idle_timeout / NGTCP2_MILLISECONDS);
+ idletime = Curl_timediff(Curl_now(), ctx->q.last_io);
+ if(idletime > 0 && (uint64_t)idletime > idle_ms)
+ goto out;
+ }
+
if(!cf->next || !cf->next->cft->is_alive(cf->next, data, input_pending))
- return FALSE;
+ goto out;
+ alive = TRUE;
if(*input_pending) {
+ CURLcode result;
/* This happens before we've sent off a request and the connection is
not in use by any other transfer, there shouldn't be any data here,
only "protocol frames" */
*input_pending = FALSE;
- if(cf_progress_ingress(cf, data, NULL))
- alive = FALSE;
- else {
- alive = TRUE;
- }
+ result = cf_progress_ingress(cf, data, NULL);
+ CURL_TRC_CF(data, cf, "is_alive, progress ingress -> %d", result);
+ alive = result? FALSE : TRUE;
}
+out:
+ CF_DATA_RESTORE(cf, save);
return alive;
}
@@ -2686,7 +2764,7 @@ struct Curl_cftype Curl_cft_http3 = {
cf_ngtcp2_connect,
cf_ngtcp2_close,
Curl_cf_def_get_host,
- cf_ngtcp2_get_select_socks,
+ cf_ngtcp2_adjust_pollset,
cf_ngtcp2_data_pending,
cf_ngtcp2_send,
cf_ngtcp2_recv,
@@ -2706,7 +2784,7 @@ CURLcode Curl_cf_ngtcp2_create(struct Curl_cfilter **pcf,
CURLcode result;
(void)data;
- ctx = calloc(sizeof(*ctx), 1);
+ ctx = calloc(1, sizeof(*ctx));
if(!ctx) {
result = CURLE_OUT_OF_MEMORY;
goto out;
diff --git a/libs/libcurl/src/vquic/curl_quiche.c b/libs/libcurl/src/vquic/curl_quiche.c
index d15b3983e9..9cf0617f11 100644
--- a/libs/libcurl/src/vquic/curl_quiche.c
+++ b/libs/libcurl/src/vquic/curl_quiche.c
@@ -55,10 +55,10 @@
#include "curl_memory.h"
#include "memdebug.h"
-/* #define DEBUG_QUICHE */
+/* HTTP/3 error values defined in RFC 9114, ch. 8.1 */
+#define CURL_H3_NO_ERROR (0x0100)
#define QUIC_MAX_STREAMS (100)
-#define QUIC_IDLE_TIMEOUT (60 * 1000) /* milliseconds */
#define H3_STREAM_WINDOW_SIZE (128 * 1024)
#define H3_STREAM_CHUNK_SIZE (16 * 1024)
@@ -92,6 +92,7 @@ static void keylog_callback(const SSL *ssl, const char *line)
struct cf_quiche_ctx {
struct cf_quic_ctx q;
+ struct ssl_peer peer;
quiche_conn *qconn;
quiche_config *cfg;
quiche_h3_conn *h3c;
@@ -105,7 +106,7 @@ struct cf_quiche_ctx {
struct curltime reconnect_at; /* time the next attempt should start */
struct bufc_pool stream_bufcp; /* chunk pool for streams */
curl_off_t data_recvd;
- size_t sends_on_hold; /* # of streams with SEND_HOLD set */
+ uint64_t max_idle_ms; /* max idle time for QUIC conn */
BIT(goaway); /* got GOAWAY from server */
BIT(got_first_byte); /* if first byte was received */
BIT(x509_store_setup); /* if x509 store has been set up */
@@ -132,6 +133,8 @@ static void cf_quiche_ctx_clear(struct cf_quiche_ctx *ctx)
if(ctx->cfg)
quiche_config_free(ctx->cfg);
Curl_bufcp_free(&ctx->stream_bufcp);
+ Curl_ssl_peer_cleanup(&ctx->peer);
+
memset(ctx, 0, sizeof(*ctx));
}
}
@@ -140,11 +143,16 @@ static CURLcode quic_x509_store_setup(struct Curl_cfilter *cf,
struct Curl_easy *data)
{
struct cf_quiche_ctx *ctx = cf->ctx;
+ struct ssl_primary_config *conn_config;
+
+ conn_config = Curl_ssl_cf_get_primary_config(cf);
+ if(!conn_config)
+ return CURLE_FAILED_INIT;
if(!ctx->x509_store_setup) {
- if(cf->conn->ssl_config.verifypeer) {
- const char * const ssl_cafile = cf->conn->ssl_config.CAfile;
- const char * const ssl_capath = cf->conn->ssl_config.CApath;
+ if(conn_config->verifypeer) {
+ const char * const ssl_cafile = conn_config->CAfile;
+ const char * const ssl_capath = conn_config->CApath;
if(ssl_cafile || ssl_capath) {
SSL_CTX_set_verify(ctx->sslctx, SSL_VERIFY_PEER, NULL);
/* tell OpenSSL where to find CA certificates that are used to verify
@@ -177,9 +185,16 @@ static CURLcode quic_x509_store_setup(struct Curl_cfilter *cf,
static CURLcode quic_ssl_setup(struct Curl_cfilter *cf, struct Curl_easy *data)
{
struct cf_quiche_ctx *ctx = cf->ctx;
- unsigned char checkip[16];
- struct connectdata *conn = data->conn;
- const char *curves = conn->ssl_config.curves;
+ struct ssl_primary_config *conn_config;
+ CURLcode result;
+
+ conn_config = Curl_ssl_cf_get_primary_config(cf);
+ if(!conn_config)
+ return CURLE_FAILED_INIT;
+
+ result = Curl_ssl_peer_init(&ctx->peer, cf);
+ if(result)
+ return result;
DEBUGASSERT(!ctx->sslctx);
ctx->sslctx = SSL_CTX_new(TLS_method());
@@ -198,8 +213,10 @@ static CURLcode quic_ssl_setup(struct Curl_cfilter *cf, struct Curl_easy *data)
SSL_CTX_set_keylog_callback(ctx->sslctx, keylog_callback);
}
- if(curves && !SSL_CTX_set1_curves_list(ctx->sslctx, curves)) {
- failf(data, "failed setting curves list for QUIC: '%s'", curves);
+ if(conn_config->curves &&
+ !SSL_CTX_set1_curves_list(ctx->sslctx, conn_config->curves)) {
+ failf(data, "failed setting curves list for QUIC: '%s'",
+ conn_config->curves);
return CURLE_SSL_CIPHER;
}
@@ -209,13 +226,8 @@ static CURLcode quic_ssl_setup(struct Curl_cfilter *cf, struct Curl_easy *data)
SSL_set_app_data(ctx->ssl, cf);
- if((0 == Curl_inet_pton(AF_INET, cf->conn->host.name, checkip))
-#ifdef ENABLE_IPV6
- && (0 == Curl_inet_pton(AF_INET6, cf->conn->host.name, checkip))
-#endif
- ) {
- char *snihost = Curl_ssl_snihost(data, cf->conn->host.name, NULL);
- if(!snihost || !SSL_set_tlsext_host_name(ctx->ssl, snihost)) {
+ if(ctx->peer.sni) {
+ if(!SSL_set_tlsext_host_name(ctx->ssl, ctx->peer.sni)) {
failf(data, "Failed set SNI");
SSL_free(ctx->ssl);
ctx->ssl = NULL;
@@ -240,6 +252,7 @@ struct stream_ctx {
bool send_closed; /* stream is locally closed */
bool resp_hds_complete; /* complete, final response has been received */
bool resp_got_header; /* TRUE when h3 stream has recvd some HEADER */
+ BIT(quic_flow_blocked); /* stream is blocked by QUIC flow control */
};
#define H3_STREAM_CTX(d) ((struct stream_ctx *)(((d) && (d)->req.p.http)? \
@@ -249,56 +262,20 @@ struct stream_ctx {
#define H3_STREAM_ID(d) (H3_STREAM_CTX(d)? \
H3_STREAM_CTX(d)->id : -2)
-static bool stream_send_is_suspended(struct Curl_easy *data)
-{
- return (data->req.keepon & KEEP_SEND_HOLD);
-}
-
-static void stream_send_suspend(struct Curl_cfilter *cf,
- struct Curl_easy *data)
-{
- struct cf_quiche_ctx *ctx = cf->ctx;
-
- if((data->req.keepon & KEEP_SENDBITS) == KEEP_SEND) {
- data->req.keepon |= KEEP_SEND_HOLD;
- ++ctx->sends_on_hold;
- if(H3_STREAM_ID(data) >= 0)
- CURL_TRC_CF(data, cf, "[%"PRId64"] suspend sending",
- H3_STREAM_ID(data));
- else
- CURL_TRC_CF(data, cf, "[%s] suspend sending", data->state.url);
- }
-}
-
-static void stream_send_resume(struct Curl_cfilter *cf,
- struct Curl_easy *data)
-{
- struct cf_quiche_ctx *ctx = cf->ctx;
-
- if(stream_send_is_suspended(data)) {
- data->req.keepon &= ~KEEP_SEND_HOLD;
- --ctx->sends_on_hold;
- if(H3_STREAM_ID(data) >= 0)
- CURL_TRC_CF(data, cf, "[%"PRId64"] resume sending",
- H3_STREAM_ID(data));
- else
- CURL_TRC_CF(data, cf, "[%s] resume sending", data->state.url);
- Curl_expire(data, 0, EXPIRE_RUN_NOW);
- }
-}
-
static void check_resumes(struct Curl_cfilter *cf,
struct Curl_easy *data)
{
- struct cf_quiche_ctx *ctx = cf->ctx;
struct Curl_easy *sdata;
-
- if(ctx->sends_on_hold) {
- DEBUGASSERT(data->multi);
- for(sdata = data->multi->easyp;
- sdata && ctx->sends_on_hold; sdata = sdata->next) {
- if(stream_send_is_suspended(sdata)) {
- stream_send_resume(cf, sdata);
+ struct stream_ctx *stream;
+
+ DEBUGASSERT(data->multi);
+ for(sdata = data->multi->easyp; sdata; sdata = sdata->next) {
+ if(sdata->conn == data->conn) {
+ stream = H3_STREAM_CTX(sdata);
+ if(stream && stream->quic_flow_blocked) {
+ stream->quic_flow_blocked = FALSE;
+ Curl_expire(data, 0, EXPIRE_RUN_NOW);
+ CURL_TRC_CF(data, cf, "[%"PRId64"] unblock", stream->id);
}
}
}
@@ -333,9 +310,15 @@ static void h3_data_done(struct Curl_cfilter *cf, struct Curl_easy *data)
(void)cf;
if(stream) {
CURL_TRC_CF(data, cf, "[%"PRId64"] easy handle is done", stream->id);
- if(stream_send_is_suspended(data)) {
- data->req.keepon &= ~KEEP_SEND_HOLD;
- --ctx->sends_on_hold;
+ if(ctx->qconn && !stream->closed) {
+ quiche_conn_stream_shutdown(ctx->qconn, stream->id,
+ QUICHE_SHUTDOWN_READ, CURL_H3_NO_ERROR);
+ if(!stream->send_closed) {
+ quiche_conn_stream_shutdown(ctx->qconn, stream->id,
+ QUICHE_SHUTDOWN_WRITE, CURL_H3_NO_ERROR);
+ stream->send_closed = TRUE;
+ }
+ stream->closed = TRUE;
}
Curl_bufq_free(&stream->recvbuf);
Curl_h1_req_parse_free(&stream->h1);
@@ -590,7 +573,6 @@ static CURLcode h3_process_event(struct Curl_cfilter *cf,
}
stream->closed = TRUE;
streamclose(cf->conn, "End of stream");
- data->req.keepon &= ~KEEP_SEND_HOLD;
break;
case QUICHE_H3_EVENT_GOAWAY:
@@ -883,6 +865,8 @@ static ssize_t cf_quiche_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
ssize_t nread = -1;
CURLcode result;
+ vquic_ctx_update_time(&ctx->q);
+
if(!stream) {
*err = CURLE_RECV_ERROR;
return -1;
@@ -1035,9 +1019,8 @@ static ssize_t h3_open_stream(struct Curl_cfilter *cf,
if(QUICHE_H3_ERR_STREAM_BLOCKED == stream3_id) {
/* quiche seems to report this error if the connection window is
* exhausted. Which happens frequently and intermittent. */
- CURL_TRC_CF(data, cf, "send_request(%s) rejected with BLOCKED",
- data->state.url);
- stream_send_suspend(cf, data);
+ CURL_TRC_CF(data, cf, "[%"PRId64"] blocked", stream->id);
+ stream->quic_flow_blocked = TRUE;
*err = CURLE_AGAIN;
nwritten = -1;
goto out;
@@ -1081,6 +1064,8 @@ static ssize_t cf_quiche_send(struct Curl_cfilter *cf, struct Curl_easy *data,
CURLcode result;
ssize_t nwritten;
+ vquic_ctx_update_time(&ctx->q);
+
*err = cf_process_ingress(cf, data);
if(*err) {
nwritten = -1;
@@ -1104,7 +1089,7 @@ static ssize_t cf_quiche_send(struct Curl_cfilter *cf, struct Curl_easy *data,
if(!quiche_conn_stream_writable(ctx->qconn, stream->id, len)) {
CURL_TRC_CF(data, cf, "[%" PRId64 "] send_body(len=%zu) "
"-> window exhausted", stream->id, len);
- stream_send_suspend(cf, data);
+ stream->quic_flow_blocked = TRUE;
}
*err = CURLE_AGAIN;
nwritten = -1;
@@ -1173,30 +1158,32 @@ static bool stream_is_writeable(struct Curl_cfilter *cf,
struct cf_quiche_ctx *ctx = cf->ctx;
struct stream_ctx *stream = H3_STREAM_CTX(data);
- return stream &&
- quiche_conn_stream_writable(ctx->qconn, (uint64_t)stream->id, 1);
+ return stream && (quiche_conn_stream_writable(ctx->qconn,
+ (uint64_t)stream->id, 1) > 0);
}
-static int cf_quiche_get_select_socks(struct Curl_cfilter *cf,
- struct Curl_easy *data,
- curl_socket_t *socks)
+static void cf_quiche_adjust_pollset(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ struct easy_pollset *ps)
{
struct cf_quiche_ctx *ctx = cf->ctx;
- struct SingleRequest *k = &data->req;
- int rv = GETSOCK_BLANK;
-
- socks[0] = ctx->q.sockfd;
+ bool want_recv = CURL_WANT_RECV(data);
+ bool want_send = CURL_WANT_SEND(data);
- /* in an HTTP/3 connection we can basically always get a frame so we should
- always be ready for one */
- rv |= GETSOCK_READSOCK(0);
+ if(ctx->qconn && (want_recv || want_send)) {
+ struct stream_ctx *stream = H3_STREAM_CTX(data);
+ bool c_exhaust, s_exhaust;
- /* we're still uploading or the HTTP/3 layer wants to send data */
- if(((k->keepon & KEEP_SENDBITS) == KEEP_SEND)
- && stream_is_writeable(cf, data))
- rv |= GETSOCK_WRITESOCK(0);
+ c_exhaust = FALSE; /* Have not found any call in quiche that tells
+ us if the connection itself is blocked */
+ s_exhaust = stream && stream->id >= 0 &&
+ (stream->quic_flow_blocked || !stream_is_writeable(cf, data));
+ want_recv = (want_recv || c_exhaust || s_exhaust);
+ want_send = (!s_exhaust && want_send) ||
+ !Curl_bufq_is_empty(&ctx->q.sendbuf);
- return rv;
+ Curl_pollset_set(data, ps, ctx->q.sockfd, want_recv, want_send);
+ }
}
/*
@@ -1238,10 +1225,12 @@ static CURLcode cf_quiche_data_event(struct Curl_cfilter *cf,
case CF_CTRL_DATA_PAUSE:
result = h3_data_pause(cf, data, (arg1 != 0));
break;
- case CF_CTRL_DATA_DONE: {
+ case CF_CTRL_DATA_DETACH:
+ h3_data_done(cf, data);
+ break;
+ case CF_CTRL_DATA_DONE:
h3_data_done(cf, data);
break;
- }
case CF_CTRL_DATA_DONE_SEND: {
struct stream_ctx *stream = H3_STREAM_CTX(data);
if(stream && !stream->send_closed) {
@@ -1276,20 +1265,25 @@ static CURLcode cf_verify_peer(struct Curl_cfilter *cf,
struct Curl_easy *data)
{
struct cf_quiche_ctx *ctx = cf->ctx;
+ struct ssl_primary_config *conn_config;
CURLcode result = CURLE_OK;
+ conn_config = Curl_ssl_cf_get_primary_config(cf);
+ if(!conn_config)
+ return CURLE_FAILED_INIT;
+
cf->conn->bits.multiplex = TRUE; /* at least potentially multiplexed */
cf->conn->httpversion = 30;
cf->conn->bundle->multiuse = BUNDLE_MULTIPLEX;
- if(cf->conn->ssl_config.verifyhost) {
+ if(conn_config->verifyhost) {
X509 *server_cert;
server_cert = SSL_get_peer_certificate(ctx->ssl);
if(!server_cert) {
result = CURLE_PEER_FAILED_VERIFICATION;
goto out;
}
- result = Curl_ossl_verifyhost(data, cf->conn, server_cert);
+ result = Curl_ossl_verifyhost(data, cf->conn, &ctx->peer, server_cert);
X509_free(server_cert);
if(result)
goto out;
@@ -1345,6 +1339,7 @@ static CURLcode cf_connect_start(struct Curl_cfilter *cf,
debug_log_init = 1;
}
#endif
+ ctx->max_idle_ms = CURL_QUIC_MAX_IDLE_MS;
Curl_bufcp_init(&ctx->stream_bufcp, H3_STREAM_CHUNK_SIZE,
H3_STREAM_POOL_SPARES);
ctx->data_recvd = 0;
@@ -1359,7 +1354,7 @@ static CURLcode cf_connect_start(struct Curl_cfilter *cf,
return CURLE_FAILED_INIT;
}
quiche_config_enable_pacing(ctx->cfg, false);
- quiche_config_set_max_idle_timeout(ctx->cfg, QUIC_IDLE_TIMEOUT);
+ quiche_config_set_max_idle_timeout(ctx->cfg, ctx->max_idle_ms * 1000);
quiche_config_set_initial_max_data(ctx->cfg, (1 * 1024 * 1024)
/* (QUIC_MAX_STREAMS/2) * H3_STREAM_WINDOW_SIZE */);
quiche_config_set_initial_max_streams_bidi(ctx->cfg, QUIC_MAX_STREAMS);
@@ -1411,7 +1406,7 @@ static CURLcode cf_connect_start(struct Curl_cfilter *cf,
}
/* Known to not work on Windows */
-#if !defined(WIN32) && defined(HAVE_QUICHE_CONN_SET_QLOG_FD)
+#if !defined(_WIN32) && defined(HAVE_QUICHE_CONN_SET_QLOG_FD)
{
int qfd;
(void)Curl_qlogdir(data, ctx->scid, sizeof(ctx->scid), &qfd);
@@ -1449,7 +1444,6 @@ static CURLcode cf_quiche_connect(struct Curl_cfilter *cf,
{
struct cf_quiche_ctx *ctx = cf->ctx;
CURLcode result = CURLE_OK;
- struct curltime now;
if(cf->connected) {
*done = TRUE;
@@ -1464,9 +1458,10 @@ static CURLcode cf_quiche_connect(struct Curl_cfilter *cf,
}
*done = FALSE;
- now = Curl_now();
+ vquic_ctx_update_time(&ctx->q);
- if(ctx->reconnect_at.tv_sec && Curl_timediff(now, ctx->reconnect_at) < 0) {
+ if(ctx->reconnect_at.tv_sec &&
+ Curl_timediff(ctx->q.last_op, ctx->reconnect_at) < 0) {
/* Not time yet to attempt the next connect */
CURL_TRC_CF(data, cf, "waiting for reconnect time");
goto out;
@@ -1476,7 +1471,7 @@ static CURLcode cf_quiche_connect(struct Curl_cfilter *cf,
result = cf_connect_start(cf, data);
if(result)
goto out;
- ctx->started_at = now;
+ ctx->started_at = ctx->q.last_op;
result = cf_flush_egress(cf, data);
/* we do not expect to be able to recv anything yet */
goto out;
@@ -1491,9 +1486,9 @@ static CURLcode cf_quiche_connect(struct Curl_cfilter *cf,
goto out;
if(quiche_conn_is_established(ctx->qconn)) {
+ ctx->handshake_at = ctx->q.last_op;
CURL_TRC_CF(data, cf, "handshake complete after %dms",
- (int)Curl_timediff(now, ctx->started_at));
- ctx->handshake_at = now;
+ (int)Curl_timediff(ctx->handshake_at, ctx->started_at));
result = cf_verify_peer(cf, data);
if(!result) {
CURL_TRC_CF(data, cf, "peer verified");
@@ -1506,27 +1501,9 @@ static CURLcode cf_quiche_connect(struct Curl_cfilter *cf,
else if(quiche_conn_is_draining(ctx->qconn)) {
/* When a QUIC server instance is shutting down, it may send us a
* CONNECTION_CLOSE right away. Our connection then enters the DRAINING
- * state.
- * This may be a stopping of the service or it may be that the server
- * is reloading and a new instance will start serving soon.
- * In any case, we tear down our socket and start over with a new one.
- * We re-open the underlying UDP cf right now, but do not start
- * connecting until called again.
- */
- int reconn_delay_ms = 200;
-
- CURL_TRC_CF(data, cf, "connect, remote closed, reconnect after %dms",
- reconn_delay_ms);
- Curl_conn_cf_close(cf->next, data);
- cf_quiche_ctx_clear(ctx);
- result = Curl_conn_cf_connect(cf->next, data, FALSE, done);
- if(!result && *done) {
- *done = FALSE;
- ctx->reconnect_at = Curl_now();
- ctx->reconnect_at.tv_usec += reconn_delay_ms * 1000;
- Curl_expire(data, reconn_delay_ms, EXPIRE_QUIC);
- result = CURLE_OK;
- }
+ * state. The CONNECT may work in the near future again. Indicate
+ * that as a "weird" reply. */
+ result = CURLE_WEIRD_SERVER_REPLY;
}
out:
@@ -1550,6 +1527,7 @@ static void cf_quiche_close(struct Curl_cfilter *cf, struct Curl_easy *data)
if(ctx) {
if(ctx->qconn) {
+ vquic_ctx_update_time(&ctx->q);
(void)quiche_conn_close(ctx->qconn, 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... */
@@ -1617,9 +1595,32 @@ static bool cf_quiche_conn_is_alive(struct Curl_cfilter *cf,
struct Curl_easy *data,
bool *input_pending)
{
+ struct cf_quiche_ctx *ctx = cf->ctx;
bool alive = TRUE;
*input_pending = FALSE;
+ if(!ctx->qconn)
+ return FALSE;
+
+ /* Both sides of the QUIC connection announce they max idle times in
+ * the transport parameters. Look at the minimum of both and if
+ * we exceed this, regard the connection as dead. The other side
+ * may have completely purged it and will no longer respond
+ * to any packets from us. */
+ {
+ quiche_transport_params qpeerparams;
+ timediff_t idletime;
+ uint64_t idle_ms = ctx->max_idle_ms;
+
+ if(quiche_conn_peer_transport_params(ctx->qconn, &qpeerparams) &&
+ qpeerparams.peer_max_idle_timeout &&
+ qpeerparams.peer_max_idle_timeout < idle_ms)
+ idle_ms = qpeerparams.peer_max_idle_timeout;
+ idletime = Curl_timediff(Curl_now(), cf->conn->lastused);
+ if(idletime > 0 && (uint64_t)idletime > idle_ms)
+ return FALSE;
+ }
+
if(!cf->next || !cf->next->cft->is_alive(cf->next, data, input_pending))
return FALSE;
@@ -1646,7 +1647,7 @@ struct Curl_cftype Curl_cft_http3 = {
cf_quiche_connect,
cf_quiche_close,
Curl_cf_def_get_host,
- cf_quiche_get_select_socks,
+ cf_quiche_adjust_pollset,
cf_quiche_data_pending,
cf_quiche_send,
cf_quiche_recv,
@@ -1667,7 +1668,7 @@ CURLcode Curl_cf_quiche_create(struct Curl_cfilter **pcf,
(void)data;
(void)conn;
- ctx = calloc(sizeof(*ctx), 1);
+ ctx = calloc(1, sizeof(*ctx));
if(!ctx) {
result = CURLE_OUT_OF_MEMORY;
goto out;
diff --git a/libs/libcurl/src/vquic/vquic.c b/libs/libcurl/src/vquic/vquic.c
index e49b6567ad..8b9c1ae223 100644
--- a/libs/libcurl/src/vquic/vquic.c
+++ b/libs/libcurl/src/vquic/vquic.c
@@ -100,6 +100,7 @@ CURLcode vquic_ctx_init(struct cf_quic_ctx *qctx)
}
}
#endif
+ vquic_ctx_update_time(qctx);
return CURLE_OK;
}
@@ -109,6 +110,11 @@ void vquic_ctx_free(struct cf_quic_ctx *qctx)
Curl_bufq_free(&qctx->sendbuf);
}
+void vquic_ctx_update_time(struct cf_quic_ctx *qctx)
+{
+ qctx->last_op = Curl_now();
+}
+
static CURLcode send_packet_no_gso(struct Curl_cfilter *cf,
struct Curl_easy *data,
struct cf_quic_ctx *qctx,
@@ -242,6 +248,7 @@ static CURLcode vquic_send_packets(struct Curl_cfilter *cf,
const uint8_t *pkt, size_t pktlen,
size_t gsolen, size_t *psent)
{
+ CURLcode result;
#ifdef DEBUGBUILD
/* simulate network blocking/partial writes */
if(qctx->wblock_percent > 0) {
@@ -254,10 +261,14 @@ static CURLcode vquic_send_packets(struct Curl_cfilter *cf,
}
#endif
if(qctx->no_gso && pktlen > gsolen) {
- return send_packet_no_gso(cf, data, qctx, pkt, pktlen, gsolen, psent);
+ result = send_packet_no_gso(cf, data, qctx, pkt, pktlen, gsolen, psent);
}
-
- return do_sendmsg(cf, data, qctx, pkt, pktlen, gsolen, psent);
+ else {
+ result = do_sendmsg(cf, data, qctx, pkt, pktlen, gsolen, psent);
+ }
+ if(!result)
+ qctx->last_io = qctx->last_op;
+ return result;
}
CURLcode vquic_flush(struct Curl_cfilter *cf, struct Curl_easy *data,
@@ -524,13 +535,17 @@ CURLcode vquic_recv_packets(struct Curl_cfilter *cf,
size_t max_pkts,
vquic_recv_pkt_cb *recv_cb, void *userp)
{
+ CURLcode result;
#if defined(HAVE_SENDMMSG)
- return recvmmsg_packets(cf, data, qctx, max_pkts, recv_cb, userp);
+ result = recvmmsg_packets(cf, data, qctx, max_pkts, recv_cb, userp);
#elif defined(HAVE_SENDMSG)
- return recvmsg_packets(cf, data, qctx, max_pkts, recv_cb, userp);
+ result = recvmsg_packets(cf, data, qctx, max_pkts, recv_cb, userp);
#else
- return recvfrom_packets(cf, data, qctx, max_pkts, recv_cb, userp);
+ result = recvfrom_packets(cf, data, qctx, max_pkts, recv_cb, userp);
#endif
+ if(!result)
+ qctx->last_io = qctx->last_op;
+ return result;
}
/*
diff --git a/libs/libcurl/src/vquic/vquic_int.h b/libs/libcurl/src/vquic/vquic_int.h
index 3fe06fb9c9..dc50593cd9 100644
--- a/libs/libcurl/src/vquic/vquic_int.h
+++ b/libs/libcurl/src/vquic/vquic_int.h
@@ -31,6 +31,8 @@
#define MAX_PKT_BURST 10
#define MAX_UDP_PAYLOAD_SIZE 1452
+/* Default QUIC connection timeout we announce from our side */
+#define CURL_QUIC_MAX_IDLE_MS (120 * 1000)
struct cf_quic_ctx {
curl_socket_t sockfd; /* connected UDP socket */
@@ -38,6 +40,8 @@ struct cf_quic_ctx {
socklen_t local_addrlen; /* length of local address */
struct bufq sendbuf; /* buffer for sending one or more packets */
+ struct curltime last_op; /* last (attempted) send/recv operation */
+ struct curltime last_io; /* last successful socket IO */
size_t gsolen; /* length of individual packets in send buf */
size_t split_len; /* if != 0, buffer length after which GSO differs */
size_t split_gsolen; /* length of individual packets after split_len */
@@ -50,6 +54,8 @@ struct cf_quic_ctx {
CURLcode vquic_ctx_init(struct cf_quic_ctx *qctx);
void vquic_ctx_free(struct cf_quic_ctx *qctx);
+void vquic_ctx_update_time(struct cf_quic_ctx *qctx);
+
void vquic_push_blocked_pkt(struct Curl_cfilter *cf,
struct cf_quic_ctx *qctx,
const uint8_t *pkt, size_t pktlen, size_t gsolen);
diff --git a/libs/libcurl/src/vssh/libssh.c b/libs/libcurl/src/vssh/libssh.c
index 93e87e9c63..71a64cd5e8 100644
--- a/libs/libcurl/src/vssh/libssh.c
+++ b/libs/libcurl/src/vssh/libssh.c
@@ -93,6 +93,7 @@
#if defined(__GNUC__) && \
(LIBSSH_VERSION_MINOR >= 10) || \
(LIBSSH_VERSION_MAJOR > 0)
+#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#endif
@@ -1159,13 +1160,23 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
break;
}
else if(statvfs) {
+ #ifdef _MSC_VER
+ #define LIBSSH_VFS_SIZE_MASK "I64u"
+ #else
+ #define LIBSSH_VFS_SIZE_MASK PRIu64
+ #endif
char *tmp = aprintf("statvfs:\n"
- "f_bsize: %llu\n" "f_frsize: %llu\n"
- "f_blocks: %llu\n" "f_bfree: %llu\n"
- "f_bavail: %llu\n" "f_files: %llu\n"
- "f_ffree: %llu\n" "f_favail: %llu\n"
- "f_fsid: %llu\n" "f_flag: %llu\n"
- "f_namemax: %llu\n",
+ "f_bsize: %" LIBSSH_VFS_SIZE_MASK "\n"
+ "f_frsize: %" LIBSSH_VFS_SIZE_MASK "\n"
+ "f_blocks: %" LIBSSH_VFS_SIZE_MASK "\n"
+ "f_bfree: %" LIBSSH_VFS_SIZE_MASK "\n"
+ "f_bavail: %" LIBSSH_VFS_SIZE_MASK "\n"
+ "f_files: %" LIBSSH_VFS_SIZE_MASK "\n"
+ "f_ffree: %" LIBSSH_VFS_SIZE_MASK "\n"
+ "f_favail: %" LIBSSH_VFS_SIZE_MASK "\n"
+ "f_fsid: %" LIBSSH_VFS_SIZE_MASK "\n"
+ "f_flag: %" LIBSSH_VFS_SIZE_MASK "\n"
+ "f_namemax: %" LIBSSH_VFS_SIZE_MASK "\n",
statvfs->f_bsize, statvfs->f_frsize,
statvfs->f_blocks, statvfs->f_bfree,
statvfs->f_bavail, statvfs->f_files,
@@ -1466,13 +1477,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
state(data, SSH_STOP);
break;
}
- /* since this counts what we send to the client, we include the
- newline in this counter */
- data->req.bytecount += sshc->readdir_len + 1;
- /* output debug output if that is requested */
- Curl_debug(data, CURLINFO_DATA_OUT, (char *)sshc->readdir_filename,
- sshc->readdir_len);
}
else {
if(Curl_dyn_add(&sshc->readdir_buf, sshc->readdir_longentry)) {
@@ -1564,12 +1569,6 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
Curl_dyn_ptr(&sshc->readdir_buf),
Curl_dyn_len(&sshc->readdir_buf));
- if(!result) {
- /* output debug output if that is requested */
- Curl_debug(data, CURLINFO_DATA_OUT, Curl_dyn_ptr(&sshc->readdir_buf),
- Curl_dyn_len(&sshc->readdir_buf));
- data->req.bytecount += Curl_dyn_len(&sshc->readdir_buf);
- }
ssh_string_free_char(sshc->readdir_tmp);
sshc->readdir_tmp = NULL;
@@ -1963,10 +1962,9 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
ssh_disconnect(sshc->ssh_session);
if(!ssh_version(SSH_VERSION_INT(0, 10, 0))) {
/* conn->sock[FIRSTSOCKET] is closed by ssh_disconnect behind our back,
- explicitly mark it as closed with the memdebug macro. This libssh
+ tell the connection to forget about it. This libssh
bug is fixed in 0.10.0. */
- fake_sclose(conn->sock[FIRSTSOCKET]);
- conn->sock[FIRSTSOCKET] = CURL_SOCKET_BAD;
+ Curl_conn_forget_socket(data, FIRSTSOCKET);
}
SSH_STRING_FREE_CHAR(sshc->homedir);
@@ -2959,4 +2957,10 @@ void Curl_ssh_version(char *buffer, size_t buflen)
(void)msnprintf(buffer, buflen, "libssh/%s", ssh_version(0));
}
+#if defined(__GNUC__) && \
+ (LIBSSH_VERSION_MINOR >= 10) || \
+ (LIBSSH_VERSION_MAJOR > 0)
+#pragma GCC diagnostic pop
+#endif
+
#endif /* USE_LIBSSH */
diff --git a/libs/libcurl/src/vssh/libssh2.c b/libs/libcurl/src/vssh/libssh2.c
index 056041db38..430f4e2ef3 100644
--- a/libs/libcurl/src/vssh/libssh2.c
+++ b/libs/libcurl/src/vssh/libssh2.c
@@ -1537,139 +1537,137 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block)
state(data, SSH_SFTP_NEXT_QUOTE);
break;
}
- {
- /*
- * the arguments following the command must be separated from the
- * command with a space so we can check for it unconditionally
- */
- cp = strchr(cmd, ' ');
- if(!cp) {
- failf(data, "Syntax error command '%s', missing parameter",
- cmd);
+
+ /*
+ * the arguments following the command must be separated from the
+ * command with a space so we can check for it unconditionally
+ */
+ cp = strchr(cmd, ' ');
+ if(!cp) {
+ failf(data, "Syntax error command '%s', missing parameter",
+ cmd);
+ state(data, SSH_SFTP_CLOSE);
+ sshc->nextstate = SSH_NO_STATE;
+ sshc->actualcode = CURLE_QUOTE_ERROR;
+ break;
+ }
+
+ /*
+ * also, every command takes at least one argument so we get that
+ * first argument right now
+ */
+ result = Curl_get_pathname(&cp, &sshc->quote_path1, sshc->homedir);
+ if(result) {
+ if(result == CURLE_OUT_OF_MEMORY)
+ failf(data, "Out of memory");
+ else
+ failf(data, "Syntax error: Bad first parameter to '%s'", cmd);
+ state(data, SSH_SFTP_CLOSE);
+ sshc->nextstate = SSH_NO_STATE;
+ sshc->actualcode = result;
+ break;
+ }
+
+ /*
+ * SFTP is a binary protocol, so we don't send text commands
+ * to the server. Instead, we scan for commands used by
+ * OpenSSH's sftp program and call the appropriate libssh2
+ * functions.
+ */
+ if(strncasecompare(cmd, "chgrp ", 6) ||
+ strncasecompare(cmd, "chmod ", 6) ||
+ strncasecompare(cmd, "chown ", 6) ||
+ strncasecompare(cmd, "atime ", 6) ||
+ strncasecompare(cmd, "mtime ", 6)) {
+ /* attribute change */
+
+ /* sshc->quote_path1 contains the mode to set */
+ /* get the destination */
+ result = Curl_get_pathname(&cp, &sshc->quote_path2, sshc->homedir);
+ if(result) {
+ if(result == CURLE_OUT_OF_MEMORY)
+ failf(data, "Out of memory");
+ else
+ failf(data, "Syntax error in %s: Bad second parameter", cmd);
+ Curl_safefree(sshc->quote_path1);
state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
- sshc->actualcode = CURLE_QUOTE_ERROR;
+ sshc->actualcode = result;
break;
}
-
- /*
- * also, every command takes at least one argument so we get that
- * first argument right now
- */
- result = Curl_get_pathname(&cp, &sshc->quote_path1, sshc->homedir);
+ memset(&sshp->quote_attrs, 0, sizeof(LIBSSH2_SFTP_ATTRIBUTES));
+ state(data, SSH_SFTP_QUOTE_STAT);
+ break;
+ }
+ if(strncasecompare(cmd, "ln ", 3) ||
+ strncasecompare(cmd, "symlink ", 8)) {
+ /* symbolic linking */
+ /* sshc->quote_path1 is the source */
+ /* get the destination */
+ result = Curl_get_pathname(&cp, &sshc->quote_path2, sshc->homedir);
if(result) {
if(result == CURLE_OUT_OF_MEMORY)
failf(data, "Out of memory");
else
- failf(data, "Syntax error: Bad first parameter to '%s'", cmd);
+ failf(data,
+ "Syntax error in ln/symlink: Bad second parameter");
+ Curl_safefree(sshc->quote_path1);
state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = result;
break;
}
-
- /*
- * SFTP is a binary protocol, so we don't send text commands
- * to the server. Instead, we scan for commands used by
- * OpenSSH's sftp program and call the appropriate libssh2
- * functions.
- */
- if(strncasecompare(cmd, "chgrp ", 6) ||
- strncasecompare(cmd, "chmod ", 6) ||
- strncasecompare(cmd, "chown ", 6) ||
- strncasecompare(cmd, "atime ", 6) ||
- strncasecompare(cmd, "mtime ", 6)) {
- /* attribute change */
-
- /* sshc->quote_path1 contains the mode to set */
- /* get the destination */
- result = Curl_get_pathname(&cp, &sshc->quote_path2, sshc->homedir);
- if(result) {
- if(result == CURLE_OUT_OF_MEMORY)
- failf(data, "Out of memory");
- else
- failf(data, "Syntax error in %s: Bad second parameter", cmd);
- Curl_safefree(sshc->quote_path1);
- state(data, SSH_SFTP_CLOSE);
- sshc->nextstate = SSH_NO_STATE;
- sshc->actualcode = result;
- break;
- }
- memset(&sshp->quote_attrs, 0, sizeof(LIBSSH2_SFTP_ATTRIBUTES));
- state(data, SSH_SFTP_QUOTE_STAT);
- break;
- }
- if(strncasecompare(cmd, "ln ", 3) ||
- strncasecompare(cmd, "symlink ", 8)) {
- /* symbolic linking */
- /* sshc->quote_path1 is the source */
- /* get the destination */
- result = Curl_get_pathname(&cp, &sshc->quote_path2, sshc->homedir);
- if(result) {
- if(result == CURLE_OUT_OF_MEMORY)
- failf(data, "Out of memory");
- else
- failf(data,
- "Syntax error in ln/symlink: Bad second parameter");
- Curl_safefree(sshc->quote_path1);
- state(data, SSH_SFTP_CLOSE);
- sshc->nextstate = SSH_NO_STATE;
- sshc->actualcode = result;
- break;
- }
- state(data, SSH_SFTP_QUOTE_SYMLINK);
- break;
- }
- else if(strncasecompare(cmd, "mkdir ", 6)) {
- /* create dir */
- state(data, SSH_SFTP_QUOTE_MKDIR);
- break;
- }
- else if(strncasecompare(cmd, "rename ", 7)) {
- /* rename file */
- /* first param is the source path */
- /* second param is the dest. path */
- result = Curl_get_pathname(&cp, &sshc->quote_path2, sshc->homedir);
- if(result) {
- if(result == CURLE_OUT_OF_MEMORY)
- failf(data, "Out of memory");
- else
- failf(data, "Syntax error in rename: Bad second parameter");
- Curl_safefree(sshc->quote_path1);
- state(data, SSH_SFTP_CLOSE);
- sshc->nextstate = SSH_NO_STATE;
- sshc->actualcode = result;
- break;
- }
- state(data, SSH_SFTP_QUOTE_RENAME);
- break;
- }
- else if(strncasecompare(cmd, "rmdir ", 6)) {
- /* delete dir */
- state(data, SSH_SFTP_QUOTE_RMDIR);
- break;
- }
- else if(strncasecompare(cmd, "rm ", 3)) {
- state(data, SSH_SFTP_QUOTE_UNLINK);
+ state(data, SSH_SFTP_QUOTE_SYMLINK);
+ break;
+ }
+ else if(strncasecompare(cmd, "mkdir ", 6)) {
+ /* create dir */
+ state(data, SSH_SFTP_QUOTE_MKDIR);
+ break;
+ }
+ else if(strncasecompare(cmd, "rename ", 7)) {
+ /* rename file */
+ /* first param is the source path */
+ /* second param is the dest. path */
+ result = Curl_get_pathname(&cp, &sshc->quote_path2, sshc->homedir);
+ if(result) {
+ if(result == CURLE_OUT_OF_MEMORY)
+ failf(data, "Out of memory");
+ else
+ failf(data, "Syntax error in rename: Bad second parameter");
+ Curl_safefree(sshc->quote_path1);
+ state(data, SSH_SFTP_CLOSE);
+ sshc->nextstate = SSH_NO_STATE;
+ sshc->actualcode = result;
break;
}
+ state(data, SSH_SFTP_QUOTE_RENAME);
+ break;
+ }
+ else if(strncasecompare(cmd, "rmdir ", 6)) {
+ /* delete dir */
+ state(data, SSH_SFTP_QUOTE_RMDIR);
+ break;
+ }
+ else if(strncasecompare(cmd, "rm ", 3)) {
+ state(data, SSH_SFTP_QUOTE_UNLINK);
+ break;
+ }
#ifdef HAS_STATVFS_SUPPORT
- else if(strncasecompare(cmd, "statvfs ", 8)) {
- state(data, SSH_SFTP_QUOTE_STATVFS);
- break;
- }
-#endif
-
- failf(data, "Unknown SFTP command");
- Curl_safefree(sshc->quote_path1);
- Curl_safefree(sshc->quote_path2);
- state(data, SSH_SFTP_CLOSE);
- sshc->nextstate = SSH_NO_STATE;
- sshc->actualcode = CURLE_QUOTE_ERROR;
+ else if(strncasecompare(cmd, "statvfs ", 8)) {
+ state(data, SSH_SFTP_QUOTE_STATVFS);
break;
}
+#endif
+
+ failf(data, "Unknown SFTP command");
+ Curl_safefree(sshc->quote_path1);
+ Curl_safefree(sshc->quote_path2);
+ state(data, SSH_SFTP_CLOSE);
+ sshc->nextstate = SSH_NO_STATE;
+ sshc->actualcode = CURLE_QUOTE_ERROR;
+ break;
}
- break;
case SSH_SFTP_NEXT_QUOTE:
Curl_safefree(sshc->quote_path1);
@@ -1962,13 +1960,23 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block)
break;
}
else if(rc == 0) {
+ #ifdef _MSC_VER
+ #define LIBSSH2_VFS_SIZE_MASK "I64u"
+ #else
+ #define LIBSSH2_VFS_SIZE_MASK "llu"
+ #endif
char *tmp = aprintf("statvfs:\n"
- "f_bsize: %llu\n" "f_frsize: %llu\n"
- "f_blocks: %llu\n" "f_bfree: %llu\n"
- "f_bavail: %llu\n" "f_files: %llu\n"
- "f_ffree: %llu\n" "f_favail: %llu\n"
- "f_fsid: %llu\n" "f_flag: %llu\n"
- "f_namemax: %llu\n",
+ "f_bsize: %" LIBSSH2_VFS_SIZE_MASK "\n"
+ "f_frsize: %" LIBSSH2_VFS_SIZE_MASK "\n"
+ "f_blocks: %" LIBSSH2_VFS_SIZE_MASK "\n"
+ "f_bfree: %" LIBSSH2_VFS_SIZE_MASK "\n"
+ "f_bavail: %" LIBSSH2_VFS_SIZE_MASK "\n"
+ "f_files: %" LIBSSH2_VFS_SIZE_MASK "\n"
+ "f_ffree: %" LIBSSH2_VFS_SIZE_MASK "\n"
+ "f_favail: %" LIBSSH2_VFS_SIZE_MASK "\n"
+ "f_fsid: %" LIBSSH2_VFS_SIZE_MASK "\n"
+ "f_flag: %" LIBSSH2_VFS_SIZE_MASK "\n"
+ "f_namemax: %" LIBSSH2_VFS_SIZE_MASK "\n",
statvfs.f_bsize, statvfs.f_frsize,
statvfs.f_blocks, statvfs.f_bfree,
statvfs.f_bavail, statvfs.f_files,
@@ -2341,14 +2349,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block)
state(data, SSH_STOP);
break;
}
- /* since this counts what we send to the client, we include the
- newline in this counter */
- data->req.bytecount += readdir_len + 1;
- /* output debug output if that is requested */
- 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(&sshp->readdir, sshp->readdir_longentry);
@@ -2427,13 +2428,6 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block)
Curl_dyn_ptr(&sshp->readdir),
Curl_dyn_len(&sshp->readdir));
- if(!result) {
- /* output debug output if that is requested */
- 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(&sshp->readdir);
state(data, SSH_STOP);
diff --git a/libs/libcurl/src/vssh/ssh.h b/libs/libcurl/src/vssh/ssh.h
index d310066369..ab9ac759d5 100644
--- a/libs/libcurl/src/vssh/ssh.h
+++ b/libs/libcurl/src/vssh/ssh.h
@@ -267,6 +267,7 @@ void Curl_ssh_attach(struct Curl_easy *data,
/* for non-SSH builds */
#define Curl_ssh_cleanup()
#define Curl_ssh_attach(x,y)
+#define Curl_ssh_init() 0
#endif
#endif /* HEADER_CURL_SSH_H */
diff --git a/libs/libcurl/src/vssh/wolfssh.c b/libs/libcurl/src/vssh/wolfssh.c
index b806845cb0..346d1875b0 100644
--- a/libs/libcurl/src/vssh/wolfssh.c
+++ b/libs/libcurl/src/vssh/wolfssh.c
@@ -343,9 +343,6 @@ static CURLcode wssh_setup_connection(struct Curl_easy *data,
return CURLE_OK;
}
-static Curl_recv wscp_recv, wsftp_recv;
-static Curl_send wscp_send, wsftp_send;
-
static int userauth(byte authtype,
WS_UserAuthData* authdata,
void *ctx)
diff --git a/libs/libcurl/src/vtls/bearssl.c b/libs/libcurl/src/vtls/bearssl.c
index 33f566931c..3bda30328c 100644
--- a/libs/libcurl/src/vtls/bearssl.c
+++ b/libs/libcurl/src/vtls/bearssl.c
@@ -582,17 +582,12 @@ static CURLcode bearssl_connect_step1(struct Curl_cfilter *cf,
const char * const ssl_cafile =
/* CURLOPT_CAINFO_BLOB overrides CURLOPT_CAINFO */
(ca_info_blob ? NULL : conn_config->CAfile);
- const char *hostname = connssl->hostname;
+ const char *hostname = connssl->peer.hostname;
const bool verifypeer = conn_config->verifypeer;
const bool verifyhost = conn_config->verifyhost;
CURLcode ret;
unsigned version_min, version_max;
int session_set = 0;
-#ifdef ENABLE_IPV6
- struct in6_addr addr;
-#else
- struct in_addr addr;
-#endif
DEBUGASSERT(backend);
CURL_TRC_CF(data, cf, "connect_step1");
@@ -706,11 +701,7 @@ static CURLcode bearssl_connect_step1(struct Curl_cfilter *cf,
infof(data, VTLS_INFOF_ALPN_OFFER_1STR, proto.data);
}
- if((1 == Curl_inet_pton(AF_INET, hostname, &addr))
-#ifdef ENABLE_IPV6
- || (1 == Curl_inet_pton(AF_INET6, hostname, &addr))
-#endif
- ) {
+ if(connssl->peer.is_ip_address) {
if(verifyhost) {
failf(data, "BearSSL: "
"host verification of IP address is not supported");
@@ -719,12 +710,11 @@ static CURLcode bearssl_connect_step1(struct Curl_cfilter *cf,
hostname = NULL;
}
else {
- char *snihost = Curl_ssl_snihost(data, hostname, NULL);
- if(!snihost) {
+ if(!connssl->peer.sni) {
failf(data, "Failed to set SNI");
return CURLE_SSL_CONNECT_ERROR;
}
- hostname = snihost;
+ hostname = connssl->peer.sni;
CURL_TRC_CF(data, cf, "connect_step1, SNI set");
}
@@ -749,26 +739,26 @@ static CURLcode bearssl_connect_step1(struct Curl_cfilter *cf,
return CURLE_OK;
}
-static int bearssl_get_select_socks(struct Curl_cfilter *cf,
- struct Curl_easy *data,
- curl_socket_t *socks)
+static void bearssl_adjust_pollset(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ struct easy_pollset *ps)
{
- struct ssl_connect_data *connssl = cf->ctx;
- curl_socket_t sock = Curl_conn_cf_get_socket(cf->next, data);
-
- if(sock == CURL_SOCKET_BAD)
- return GETSOCK_BLANK;
- else {
- struct bearssl_ssl_backend_data *backend =
- (struct bearssl_ssl_backend_data *)connssl->backend;
- unsigned state = br_ssl_engine_current_state(&backend->ctx.eng);
- if(state & BR_SSL_SENDREC) {
- socks[0] = sock;
- return GETSOCK_WRITESOCK(0);
+ if(!cf->connected) {
+ curl_socket_t sock = Curl_conn_cf_get_socket(cf->next, data);
+ if(sock != CURL_SOCKET_BAD) {
+ struct ssl_connect_data *connssl = cf->ctx;
+ struct bearssl_ssl_backend_data *backend =
+ (struct bearssl_ssl_backend_data *)connssl->backend;
+ unsigned state = br_ssl_engine_current_state(&backend->ctx.eng);
+
+ if(state & BR_SSL_SENDREC) {
+ Curl_pollset_set_out_only(data, ps, sock);
+ }
+ else {
+ Curl_pollset_set_in_only(data, ps, sock);
+ }
}
}
- socks[0] = sock;
- return GETSOCK_READSOCK(0);
}
static CURLcode bearssl_run_until(struct Curl_cfilter *cf,
@@ -1210,7 +1200,7 @@ const struct Curl_ssl Curl_ssl_bearssl = {
Curl_none_cert_status_request, /* cert_status_request */
bearssl_connect, /* connect */
bearssl_connect_nonblocking, /* connect_nonblocking */
- bearssl_get_select_socks, /* getsock */
+ bearssl_adjust_pollset, /* adjust_pollset */
bearssl_get_internals, /* get_internals */
bearssl_close, /* close_one */
Curl_none_close_all, /* close_all */
diff --git a/libs/libcurl/src/vtls/gtls.c b/libs/libcurl/src/vtls/gtls.c
index cc30cb0f55..bd78eb5030 100644
--- a/libs/libcurl/src/vtls/gtls.c
+++ b/libs/libcurl/src/vtls/gtls.c
@@ -402,18 +402,13 @@ set_ssl_version_min_max(struct Curl_easy *data,
CURLcode gtls_client_init(struct Curl_easy *data,
struct ssl_primary_config *config,
struct ssl_config_data *ssl_config,
- const char *hostname,
+ struct ssl_peer *peer,
struct gtls_instance *gtls,
long *pverifyresult)
{
unsigned int init_flags;
int rc;
bool sni = TRUE; /* default is SNI enabled */
-#ifdef ENABLE_IPV6
- struct in6_addr addr;
-#else
- struct in_addr addr;
-#endif
const char *prioritylist;
const char *err = NULL;
const char *tls13support;
@@ -460,50 +455,60 @@ CURLcode gtls_client_init(struct Curl_easy *data,
}
#endif
- if(config->CAfile) {
- /* set the trusted CA cert bundle file */
- gnutls_certificate_set_verify_flags(gtls->cred,
- GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT);
+ if(config->verifypeer) {
+ bool imported_native_ca = false;
- rc = gnutls_certificate_set_x509_trust_file(gtls->cred,
- config->CAfile,
- GNUTLS_X509_FMT_PEM);
- if(rc < 0) {
- infof(data, "error reading ca cert file %s (%s)",
- config->CAfile, gnutls_strerror(rc));
- if(config->verifypeer) {
- *pverifyresult = rc;
- return CURLE_SSL_CACERT_BADFILE;
+ if(ssl_config->native_ca_store) {
+ rc = gnutls_certificate_set_x509_system_trust(gtls->cred);
+ if(rc < 0)
+ infof(data, "error reading native ca store (%s), continuing anyway",
+ gnutls_strerror(rc));
+ else {
+ infof(data, "found %d certificates in native ca store", rc);
+ if(rc > 0)
+ imported_native_ca = true;
}
}
- else
- infof(data, "found %d certificates in %s", rc, config->CAfile);
- }
- if(config->CApath) {
- /* set the trusted CA cert directory */
- rc = gnutls_certificate_set_x509_trust_dir(gtls->cred,
- config->CApath,
- GNUTLS_X509_FMT_PEM);
- if(rc < 0) {
- infof(data, "error reading ca cert file %s (%s)",
- config->CApath, gnutls_strerror(rc));
- if(config->verifypeer) {
- *pverifyresult = rc;
- return CURLE_SSL_CACERT_BADFILE;
+ if(config->CAfile) {
+ /* set the trusted CA cert bundle file */
+ gnutls_certificate_set_verify_flags(gtls->cred,
+ GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT);
+
+ rc = gnutls_certificate_set_x509_trust_file(gtls->cred,
+ config->CAfile,
+ GNUTLS_X509_FMT_PEM);
+ if(rc < 0) {
+ infof(data, "error reading ca cert file %s (%s)%s",
+ config->CAfile, gnutls_strerror(rc),
+ (imported_native_ca ? ", continuing anyway" : ""));
+ if(!imported_native_ca) {
+ *pverifyresult = rc;
+ return CURLE_SSL_CACERT_BADFILE;
+ }
}
+ else
+ infof(data, "found %d certificates in %s", rc, config->CAfile);
}
- else
- infof(data, "found %d certificates in %s", rc, config->CApath);
- }
-#ifdef CURL_CA_FALLBACK
- /* use system ca certificate store as fallback */
- if(config->verifypeer && !(config->CAfile || config->CApath)) {
- /* this ignores errors on purpose */
- gnutls_certificate_set_x509_system_trust(gtls->cred);
+ if(config->CApath) {
+ /* set the trusted CA cert directory */
+ rc = gnutls_certificate_set_x509_trust_dir(gtls->cred,
+ config->CApath,
+ GNUTLS_X509_FMT_PEM);
+ if(rc < 0) {
+ infof(data, "error reading ca cert file %s (%s)%s",
+ config->CApath, gnutls_strerror(rc),
+ (imported_native_ca ? ", continuing anyway" : ""));
+ if(!imported_native_ca) {
+ *pverifyresult = rc;
+ return CURLE_SSL_CACERT_BADFILE;
+ }
+ }
+ else
+ infof(data, "found %d certificates in %s", rc, config->CApath);
+ }
}
-#endif
if(config->CRLfile) {
/* set the CRL list file */
@@ -537,15 +542,9 @@ CURLcode gtls_client_init(struct Curl_easy *data,
return CURLE_SSL_CONNECT_ERROR;
}
- if((0 == Curl_inet_pton(AF_INET, hostname, &addr)) &&
-#ifdef ENABLE_IPV6
- (0 == Curl_inet_pton(AF_INET6, hostname, &addr)) &&
-#endif
- sni) {
- size_t snilen;
- char *snihost = Curl_ssl_snihost(data, hostname, &snilen);
- if(!snihost || gnutls_server_name_set(gtls->session, GNUTLS_NAME_DNS,
- snihost, snilen) < 0) {
+ if(sni && peer->sni) {
+ if(gnutls_server_name_set(gtls->session, GNUTLS_NAME_DNS,
+ peer->sni, strlen(peer->sni)) < 0) {
failf(data, "Failed to set SNI");
return CURLE_SSL_CONNECT_ERROR;
}
@@ -699,7 +698,7 @@ gtls_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
return CURLE_OK;
result = gtls_client_init(data, conn_config, ssl_config,
- connssl->hostname,
+ &connssl->peer,
&backend->gtls, pverifyresult);
if(result)
return result;
@@ -811,8 +810,7 @@ Curl_gtls_verifyserver(struct Curl_easy *data,
gnutls_session_t session,
struct ssl_primary_config *config,
struct ssl_config_data *ssl_config,
- const char *hostname,
- const char *dispname,
+ struct ssl_peer *peer,
const char *pinned_key)
{
unsigned int cert_list_size;
@@ -1068,7 +1066,7 @@ Curl_gtls_verifyserver(struct Curl_easy *data,
in RFC2818 (HTTPS), which takes into account wildcards, and the subject
alternative name PKIX extension. Returns non zero on success, and zero on
failure. */
- rc = gnutls_x509_crt_check_hostname(x509_cert, hostname);
+ rc = gnutls_x509_crt_check_hostname(x509_cert, peer->hostname);
#if GNUTLS_VERSION_NUMBER < 0x030306
/* Before 3.3.6, gnutls_x509_crt_check_hostname() didn't check IP
addresses. */
@@ -1081,10 +1079,10 @@ Curl_gtls_verifyserver(struct Curl_easy *data,
unsigned char addrbuf[sizeof(struct use_addr)];
size_t addrlen = 0;
- if(Curl_inet_pton(AF_INET, hostname, addrbuf) > 0)
+ if(Curl_inet_pton(AF_INET, peer->hostname, addrbuf) > 0)
addrlen = 4;
#ifdef ENABLE_IPV6
- else if(Curl_inet_pton(AF_INET6, hostname, addrbuf) > 0)
+ else if(Curl_inet_pton(AF_INET6, peer->hostname, addrbuf) > 0)
addrlen = 16;
#endif
@@ -1114,13 +1112,13 @@ Curl_gtls_verifyserver(struct Curl_easy *data,
if(!rc) {
if(config->verifyhost) {
failf(data, "SSL: certificate subject name (%s) does not match "
- "target host name '%s'", certname, dispname);
+ "target host name '%s'", certname, peer->dispname);
gnutls_x509_crt_deinit(x509_cert);
return CURLE_PEER_FAILED_VERIFICATION;
}
else
infof(data, " common name: %s (does not match '%s')",
- certname, dispname);
+ certname, peer->dispname);
}
else
infof(data, " common name: %s (matched)", certname);
@@ -1253,8 +1251,7 @@ static CURLcode gtls_verifyserver(struct Curl_cfilter *cf,
CURLcode result;
result = Curl_gtls_verifyserver(data, session, conn_config, ssl_config,
- connssl->hostname, connssl->dispname,
- pinned_key);
+ &connssl->peer, pinned_key);
if(result)
goto out;
@@ -1662,7 +1659,7 @@ const struct Curl_ssl Curl_ssl_gnutls = {
gtls_cert_status_request, /* cert_status_request */
gtls_connect, /* connect */
gtls_connect_nonblocking, /* connect_nonblocking */
- Curl_ssl_get_select_socks, /* getsock */
+ Curl_ssl_adjust_pollset, /* adjust_pollset */
gtls_get_internals, /* get_internals */
gtls_close, /* close_one */
Curl_none_close_all, /* close_all */
diff --git a/libs/libcurl/src/vtls/gtls.h b/libs/libcurl/src/vtls/gtls.h
index 64f13b3b2a..998957e689 100644
--- a/libs/libcurl/src/vtls/gtls.h
+++ b/libs/libcurl/src/vtls/gtls.h
@@ -43,6 +43,7 @@ struct Curl_easy;
struct Curl_cfilter;
struct ssl_primary_config;
struct ssl_config_data;
+struct ssl_peer;
struct gtls_instance {
gnutls_session_t session;
@@ -56,7 +57,7 @@ CURLcode
gtls_client_init(struct Curl_easy *data,
struct ssl_primary_config *config,
struct ssl_config_data *ssl_config,
- const char *hostname,
+ struct ssl_peer *peer,
struct gtls_instance *gtls,
long *pverifyresult);
@@ -65,8 +66,7 @@ Curl_gtls_verifyserver(struct Curl_easy *data,
gnutls_session_t session,
struct ssl_primary_config *config,
struct ssl_config_data *ssl_config,
- const char *hostname,
- const char *dispname,
+ struct ssl_peer *peer,
const char *pinned_key);
extern const struct Curl_ssl Curl_ssl_gnutls;
diff --git a/libs/libcurl/src/vtls/keylog.c b/libs/libcurl/src/vtls/keylog.c
index dfa033d154..4a1f8ce74b 100644
--- a/libs/libcurl/src/vtls/keylog.c
+++ b/libs/libcurl/src/vtls/keylog.c
@@ -23,6 +23,11 @@
***************************************************************************/
#include "curl_setup.h"
+#if defined(USE_OPENSSL) || \
+ defined(USE_WOLFSSL) || \
+ (defined(USE_NGTCP2) && defined(USE_NGHTTP3)) || \
+ defined(USE_QUICHE)
+
#include "keylog.h"
#include <curl/curl.h>
@@ -55,7 +60,7 @@ Curl_tls_keylog_open(void)
if(keylog_file_name) {
keylog_file_fp = fopen(keylog_file_name, FOPEN_APPENDTEXT);
if(keylog_file_fp) {
-#ifdef WIN32
+#ifdef _WIN32
if(setvbuf(keylog_file_fp, NULL, _IONBF, 0))
#else
if(setvbuf(keylog_file_fp, NULL, _IOLBF, 4096))
@@ -157,3 +162,5 @@ Curl_tls_keylog_write(const char *label,
fputs(line, keylog_file_fp);
return true;
}
+
+#endif /* TLS or QUIC backend */
diff --git a/libs/libcurl/src/vtls/mbedtls.c b/libs/libcurl/src/vtls/mbedtls.c
index 496cac0ab4..292c933291 100644
--- a/libs/libcurl/src/vtls/mbedtls.c
+++ b/libs/libcurl/src/vtls/mbedtls.c
@@ -322,7 +322,7 @@ mbed_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
char * const ssl_cert = ssl_config->primary.clientcert;
const struct curl_blob *ssl_cert_blob = ssl_config->primary.cert_blob;
const char * const ssl_crlfile = ssl_config->primary.CRLfile;
- const char *hostname = connssl->hostname;
+ const char *hostname = connssl->peer.hostname;
int ret = -1;
char errorbuf[128];
@@ -639,9 +639,9 @@ mbed_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
mbedtls_ssl_conf_own_cert(&backend->config,
&backend->clicert, &backend->pk);
}
- {
- char *snihost = Curl_ssl_snihost(data, hostname, NULL);
- if(!snihost || mbedtls_ssl_set_hostname(&backend->ssl, snihost)) {
+
+ if(connssl->peer.sni) {
+ if(mbedtls_ssl_set_hostname(&backend->ssl, connssl->peer.sni)) {
/* mbedtls_ssl_set_hostname() sets the name to use in CN/SAN checks and
the name to set in the SNI extension. So even if curl connects to a
host specified as an IP address, this function must be used. */
@@ -1274,7 +1274,7 @@ const struct Curl_ssl Curl_ssl_mbedtls = {
Curl_none_cert_status_request, /* cert_status_request */
mbedtls_connect, /* connect */
mbedtls_connect_nonblocking, /* connect_nonblocking */
- Curl_ssl_get_select_socks, /* getsock */
+ Curl_ssl_adjust_pollset, /* adjust_pollset */
mbedtls_get_internals, /* get_internals */
mbedtls_close, /* close_one */
mbedtls_close_all, /* close_all */
diff --git a/libs/libcurl/src/vtls/mbedtls_threadlock.c b/libs/libcurl/src/vtls/mbedtls_threadlock.c
index 935d0e1d66..757d19f003 100644
--- a/libs/libcurl/src/vtls/mbedtls_threadlock.c
+++ b/libs/libcurl/src/vtls/mbedtls_threadlock.c
@@ -51,7 +51,7 @@ int Curl_mbedtlsthreadlock_thread_setup(void)
{
int i;
- mutex_buf = calloc(NUMT * sizeof(MBEDTLS_MUTEX_T), 1);
+ mutex_buf = calloc(1, NUMT * sizeof(MBEDTLS_MUTEX_T));
if(!mutex_buf)
return 0; /* error, no number of threads defined */
diff --git a/libs/libcurl/src/vtls/openssl.c b/libs/libcurl/src/vtls/openssl.c
index b2f201ef13..fcc4e4eb0b 100644
--- a/libs/libcurl/src/vtls/openssl.c
+++ b/libs/libcurl/src/vtls/openssl.c
@@ -79,6 +79,8 @@
#include <openssl/bio.h>
#include <openssl/buffer.h>
#include <openssl/pkcs12.h>
+#include <openssl/tls1.h>
+#include <openssl/evp.h>
#if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_OCSP)
#include <openssl/ocsp.h>
@@ -96,6 +98,9 @@
#include "curl_memory.h"
#include "memdebug.h"
+#ifndef ARRAYSIZE
+#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0]))
+#endif
/* Uncomment the ALLOW_RENEG line to a real #define if you want to allow TLS
renegotiations when built with BoringSSL. Renegotiating is non-compliant
@@ -173,8 +178,6 @@
#if (OPENSSL_VERSION_NUMBER >= 0x30000000L)
#define HAVE_EVP_PKEY_GET_PARAMS 1
-#else
-#define SSL_get1_peer_certificate SSL_get_peer_certificate
#endif
#ifdef HAVE_EVP_PKEY_GET_PARAMS
@@ -235,7 +238,11 @@
#elif defined(OPENSSL_IS_AWSLC)
#define OSSL_PACKAGE "AWS-LC"
#else
-#define OSSL_PACKAGE "OpenSSL"
+# if defined(USE_NGTCP2) && defined(USE_NGHTTP3)
+# define OSSL_PACKAGE "quictls"
+# else
+# define OSSL_PACKAGE "OpenSSL"
+#endif
#endif
#if (OPENSSL_VERSION_NUMBER >= 0x10100000L)
@@ -538,9 +545,9 @@ CURLcode Curl_ossl_certchain(struct Curl_easy *data, SSL *ssl)
#else
RSA_get0_key(rsa, &n, &e, NULL);
#endif /* HAVE_EVP_PKEY_GET_PARAMS */
- BIO_printf(mem, "%d", BN_num_bits(n));
+ BIO_printf(mem, "%d", n ? BN_num_bits(n) : 0);
#else
- BIO_printf(mem, "%d", BN_num_bits(rsa->n));
+ BIO_printf(mem, "%d", rsa->n ? BN_num_bits(rsa->n) : 0);
#endif /* HAVE_OPAQUE_RSA_DSA_DH */
push_certinfo("RSA Public Key", i);
print_pubkey_BN(rsa, n, i);
@@ -2098,22 +2105,6 @@ static bool subj_alt_hostcheck(struct Curl_easy *data,
return FALSE;
}
-static CURLcode
-ossl_verifyhost(struct Curl_easy *data, struct connectdata *conn,
- X509 *server_cert, const char *hostname,
- const char *dispname);
-
-CURLcode Curl_ossl_verifyhost(struct Curl_easy *data, struct connectdata *conn,
- X509 *server_cert)
-{
- const char *hostname, *dispname;
- int port;
-
- (void)conn;
- Curl_conn_get_host(data, FIRSTSOCKET, &hostname, &dispname, &port);
- return ossl_verifyhost(data, conn, server_cert, hostname, dispname);
-}
-
/* Quote from RFC2818 section 3.1 "Server Identity"
If a subjectAltName extension of type dNSName is present, that MUST
@@ -2136,10 +2127,8 @@ CURLcode Curl_ossl_verifyhost(struct Curl_easy *data, struct connectdata *conn,
This function is now used from ngtcp2 (QUIC) as well.
*/
-static CURLcode
-ossl_verifyhost(struct Curl_easy *data, struct connectdata *conn,
- X509 *server_cert, const char *hostname,
- const char *dispname)
+CURLcode Curl_ossl_verifyhost(struct Curl_easy *data, struct connectdata *conn,
+ struct ssl_peer *peer, X509 *server_cert)
{
bool matched = FALSE;
int target = GEN_DNS; /* target type, GEN_DNS or GEN_IPADD */
@@ -2156,25 +2145,21 @@ ossl_verifyhost(struct Curl_easy *data, struct connectdata *conn,
size_t hostlen;
(void)conn;
- hostlen = strlen(hostname);
-
-#ifndef ENABLE_IPV6
- /* Silence compiler warnings for unused params */
- (void) conn;
-#endif
-
+ hostlen = strlen(peer->hostname);
+ if(peer->is_ip_address) {
#ifdef ENABLE_IPV6
- if(conn->bits.ipv6_ip &&
- Curl_inet_pton(AF_INET6, hostname, &addr)) {
- target = GEN_IPADD;
- addrlen = sizeof(struct in6_addr);
- }
- else
-#endif
- if(Curl_inet_pton(AF_INET, hostname, &addr)) {
+ if(conn->bits.ipv6_ip &&
+ Curl_inet_pton(AF_INET6, peer->hostname, &addr)) {
target = GEN_IPADD;
- addrlen = sizeof(struct in_addr);
+ addrlen = sizeof(struct in6_addr);
}
+ else
+#endif
+ if(Curl_inet_pton(AF_INET, peer->hostname, &addr)) {
+ target = GEN_IPADD;
+ addrlen = sizeof(struct in_addr);
+ }
+ }
/* get a "list" of alternative names */
altnames = X509_get_ext_d2i(server_cert, NID_subject_alt_name, NULL, NULL);
@@ -2224,9 +2209,9 @@ ossl_verifyhost(struct Curl_easy *data, struct connectdata *conn,
if((altlen == strlen(altptr)) &&
/* if this isn't true, there was an embedded zero in the name
string and we cannot match it. */
- subj_alt_hostcheck(data,
- altptr,
- altlen, hostname, hostlen, dispname)) {
+ subj_alt_hostcheck(data, altptr, altlen,
+ peer->hostname, hostlen,
+ peer->dispname)) {
dnsmatched = TRUE;
}
break;
@@ -2238,7 +2223,7 @@ ossl_verifyhost(struct Curl_easy *data, struct connectdata *conn,
ipmatched = TRUE;
infof(data,
" subjectAltName: host \"%s\" matched cert's IP address!",
- dispname);
+ peer->dispname);
}
break;
}
@@ -2254,9 +2239,9 @@ ossl_verifyhost(struct Curl_easy *data, struct connectdata *conn,
/* an alternative name matched */
;
else if(dNSName || iPAddress) {
- infof(data, " subjectAltName does not match %s", dispname);
+ infof(data, " subjectAltName does not match %s", peer->dispname);
failf(data, "SSL: no alternative certificate subject name matches "
- "target host name '%s'", dispname);
+ "target host name '%s'", peer->dispname);
result = CURLE_PEER_FAILED_VERIFICATION;
}
else {
@@ -2320,9 +2305,9 @@ ossl_verifyhost(struct Curl_easy *data, struct connectdata *conn,
result = CURLE_PEER_FAILED_VERIFICATION;
}
else if(!Curl_cert_hostcheck((const char *)peer_CN,
- peerlen, hostname, hostlen)) {
+ peerlen, peer->hostname, hostlen)) {
failf(data, "SSL: certificate subject name '%s' does not match "
- "target host name '%s'", peer_CN, dispname);
+ "target host name '%s'", peer_CN, peer->dispname);
result = CURLE_PEER_FAILED_VERIFICATION;
}
else {
@@ -2731,12 +2716,6 @@ static void ossl_trace(int direction, int ssl_ver, int content_type,
#ifdef USE_OPENSSL
/* ====================================================== */
-#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
-# define use_sni(x) sni = (x)
-#else
-# define use_sni(x) Curl_nop_stmt
-#endif
-
/* Check for OpenSSL 1.0.2 which has ALPN support. */
#undef HAS_ALPN
#if OPENSSL_VERSION_NUMBER >= 0x10002000L \
@@ -3032,6 +3011,151 @@ static CURLcode load_cacert_from_memory(X509_STORE *store,
return (count > 0) ? CURLE_OK : CURLE_SSL_CACERT_BADFILE;
}
+#if defined(USE_WIN32_CRYPTO)
+static CURLcode import_windows_cert_store(struct Curl_easy *data,
+ const char *name,
+ X509_STORE *store,
+ bool *imported)
+{
+ CURLcode result = CURLE_OK;
+ HCERTSTORE hStore;
+
+ *imported = false;
+
+ hStore = CertOpenSystemStoreA(0, name);
+ if(hStore) {
+ PCCERT_CONTEXT pContext = NULL;
+ /* The array of enhanced key usage OIDs will vary per certificate and
+ is declared outside of the loop so that rather than malloc/free each
+ iteration we can grow it with realloc, when necessary. */
+ CERT_ENHKEY_USAGE *enhkey_usage = NULL;
+ DWORD enhkey_usage_size = 0;
+
+ /* This loop makes a best effort to import all valid certificates from
+ the MS root store. If a certificate cannot be imported it is
+ skipped. 'result' is used to store only hard-fail conditions (such
+ as out of memory) that cause an early break. */
+ result = CURLE_OK;
+ for(;;) {
+ X509 *x509;
+ FILETIME now;
+ BYTE key_usage[2];
+ DWORD req_size;
+ const unsigned char *encoded_cert;
+#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
+ char cert_name[256];
+#endif
+
+ pContext = CertEnumCertificatesInStore(hStore, pContext);
+ if(!pContext)
+ break;
+
+#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
+ if(!CertGetNameStringA(pContext, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0,
+ NULL, cert_name, sizeof(cert_name))) {
+ strcpy(cert_name, "Unknown");
+ }
+ infof(data, "SSL: Checking cert \"%s\"", cert_name);
+#endif
+ encoded_cert = (const unsigned char *)pContext->pbCertEncoded;
+ if(!encoded_cert)
+ continue;
+
+ GetSystemTimeAsFileTime(&now);
+ if(CompareFileTime(&pContext->pCertInfo->NotBefore, &now) > 0 ||
+ CompareFileTime(&now, &pContext->pCertInfo->NotAfter) > 0)
+ continue;
+
+ /* If key usage exists check for signing attribute */
+ if(CertGetIntendedKeyUsage(pContext->dwCertEncodingType,
+ pContext->pCertInfo,
+ key_usage, sizeof(key_usage))) {
+ if(!(key_usage[0] & CERT_KEY_CERT_SIGN_KEY_USAGE))
+ continue;
+ }
+ else if(GetLastError())
+ continue;
+
+ /* If enhanced key usage exists check for server auth attribute.
+ *
+ * Note "In a Microsoft environment, a certificate might also have
+ * EKU extended properties that specify valid uses for the
+ * certificate." The call below checks both, and behavior varies
+ * depending on what is found. For more details see
+ * CertGetEnhancedKeyUsage doc.
+ */
+ if(CertGetEnhancedKeyUsage(pContext, 0, NULL, &req_size)) {
+ if(req_size && req_size > enhkey_usage_size) {
+ void *tmp = realloc(enhkey_usage, req_size);
+
+ if(!tmp) {
+ failf(data, "SSL: Out of memory allocating for OID list");
+ result = CURLE_OUT_OF_MEMORY;
+ break;
+ }
+
+ enhkey_usage = (CERT_ENHKEY_USAGE *)tmp;
+ enhkey_usage_size = req_size;
+ }
+
+ if(CertGetEnhancedKeyUsage(pContext, 0, enhkey_usage, &req_size)) {
+ if(!enhkey_usage->cUsageIdentifier) {
+ /* "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((HRESULT)GetLastError() != CRYPT_E_NOT_FOUND)
+ continue;
+ }
+ else {
+ DWORD i;
+ bool found = false;
+
+ for(i = 0; i < enhkey_usage->cUsageIdentifier; ++i) {
+ if(!strcmp("1.3.6.1.5.5.7.3.1" /* OID server auth */,
+ enhkey_usage->rgpszUsageIdentifier[i])) {
+ found = true;
+ break;
+ }
+ }
+
+ if(!found)
+ continue;
+ }
+ }
+ else
+ continue;
+ }
+ else
+ continue;
+
+ x509 = d2i_X509(NULL, &encoded_cert, pContext->cbCertEncoded);
+ if(!x509)
+ continue;
+
+ /* Try to import the certificate. This may fail for legitimate
+ reasons such as duplicate certificate, which is allowed by MS but
+ not OpenSSL. */
+ if(X509_STORE_add_cert(store, x509) == 1) {
+#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
+ infof(data, "SSL: Imported cert \"%s\"", cert_name);
+#endif
+ *imported = true;
+ }
+ X509_free(x509);
+ }
+
+ free(enhkey_usage);
+ CertFreeCertificateContext(pContext);
+ CertCloseStore(hStore, 0);
+
+ if(result)
+ return result;
+ }
+
+ return result;
+}
+#endif
+
static CURLcode populate_x509_store(struct Curl_cfilter *cf,
struct Curl_easy *data,
X509_STORE *store)
@@ -3061,140 +3185,25 @@ static CURLcode populate_x509_store(struct Curl_cfilter *cf,
https://github.com/d3x0r/SACK/blob/master/src/netlib/ssl_layer.c#L1037
https://datatracker.ietf.org/doc/html/rfc5280 */
if(ssl_config->native_ca_store) {
- HCERTSTORE hStore = CertOpenSystemStore(0, TEXT("ROOT"));
-
- if(hStore) {
- PCCERT_CONTEXT pContext = NULL;
- /* The array of enhanced key usage OIDs will vary per certificate and
- is declared outside of the loop so that rather than malloc/free each
- iteration we can grow it with realloc, when necessary. */
- CERT_ENHKEY_USAGE *enhkey_usage = NULL;
- DWORD enhkey_usage_size = 0;
-
- /* This loop makes a best effort to import all valid certificates from
- the MS root store. If a certificate cannot be imported it is
- skipped. 'result' is used to store only hard-fail conditions (such
- as out of memory) that cause an early break. */
- result = CURLE_OK;
- for(;;) {
- X509 *x509;
- FILETIME now;
- BYTE key_usage[2];
- DWORD req_size;
- const unsigned char *encoded_cert;
-#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
- char cert_name[256];
-#endif
-
- pContext = CertEnumCertificatesInStore(hStore, pContext);
- if(!pContext)
- break;
-
-#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
- if(!CertGetNameStringA(pContext, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0,
- NULL, cert_name, sizeof(cert_name))) {
- strcpy(cert_name, "Unknown");
- }
- infof(data, "SSL: Checking cert \"%s\"", cert_name);
-#endif
- encoded_cert = (const unsigned char *)pContext->pbCertEncoded;
- if(!encoded_cert)
- continue;
-
- GetSystemTimeAsFileTime(&now);
- if(CompareFileTime(&pContext->pCertInfo->NotBefore, &now) > 0 ||
- CompareFileTime(&now, &pContext->pCertInfo->NotAfter) > 0)
- continue;
-
- /* If key usage exists check for signing attribute */
- if(CertGetIntendedKeyUsage(pContext->dwCertEncodingType,
- pContext->pCertInfo,
- key_usage, sizeof(key_usage))) {
- if(!(key_usage[0] & CERT_KEY_CERT_SIGN_KEY_USAGE))
- continue;
- }
- else if(GetLastError())
- continue;
-
- /* If enhanced key usage exists check for server auth attribute.
- *
- * Note "In a Microsoft environment, a certificate might also have
- * EKU extended properties that specify valid uses for the
- * certificate." The call below checks both, and behavior varies
- * depending on what is found. For more details see
- * CertGetEnhancedKeyUsage doc.
- */
- if(CertGetEnhancedKeyUsage(pContext, 0, NULL, &req_size)) {
- if(req_size && req_size > enhkey_usage_size) {
- void *tmp = realloc(enhkey_usage, req_size);
-
- if(!tmp) {
- failf(data, "SSL: Out of memory allocating for OID list");
- result = CURLE_OUT_OF_MEMORY;
- break;
- }
-
- enhkey_usage = (CERT_ENHKEY_USAGE *)tmp;
- enhkey_usage_size = req_size;
- }
-
- if(CertGetEnhancedKeyUsage(pContext, 0, enhkey_usage, &req_size)) {
- if(!enhkey_usage->cUsageIdentifier) {
- /* "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((HRESULT)GetLastError() != CRYPT_E_NOT_FOUND)
- continue;
- }
- else {
- DWORD i;
- bool found = false;
-
- for(i = 0; i < enhkey_usage->cUsageIdentifier; ++i) {
- if(!strcmp("1.3.6.1.5.5.7.3.1" /* OID server auth */,
- enhkey_usage->rgpszUsageIdentifier[i])) {
- found = true;
- break;
- }
- }
-
- if(!found)
- continue;
- }
- }
- else
- continue;
- }
- else
- continue;
-
- x509 = d2i_X509(NULL, &encoded_cert, pContext->cbCertEncoded);
- if(!x509)
- continue;
-
- /* Try to import the certificate. This may fail for legitimate
- reasons such as duplicate certificate, which is allowed by MS but
- not OpenSSL. */
- if(X509_STORE_add_cert(store, x509) == 1) {
-#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
- infof(data, "SSL: Imported cert \"%s\"", cert_name);
-#endif
- imported_native_ca = true;
- }
- X509_free(x509);
- }
-
- free(enhkey_usage);
- CertFreeCertificateContext(pContext);
- CertCloseStore(hStore, 0);
-
+ const char *storeNames[] = {
+ "ROOT", /* Trusted Root Certification Authorities */
+ "CA" /* Intermediate Certification Authorities */
+ };
+ size_t i;
+ for(i = 0; i < ARRAYSIZE(storeNames); ++i) {
+ bool imported = false;
+ result = import_windows_cert_store(data, storeNames[i], store,
+ &imported);
if(result)
return result;
+ if(imported) {
+ infof(data, "successfully imported Windows %s store", storeNames[i]);
+ imported_native_ca = true;
+ }
+ else
+ infof(data, "error importing Windows %s store, continuing anyway",
+ storeNames[i]);
}
- if(imported_native_ca)
- infof(data, "successfully imported Windows CA store");
- else
- infof(data, "error importing Windows CA store, continuing anyway");
}
#endif
if(ca_info_blob) {
@@ -3210,7 +3219,7 @@ static CURLcode populate_x509_store(struct Curl_cfilter *cf,
}
if(ssl_cafile || ssl_capath) {
-#if defined(OPENSSL_VERSION_MAJOR) && (OPENSSL_VERSION_MAJOR >= 3)
+#if (OPENSSL_VERSION_NUMBER >= 0x30000000L)
/* OpenSSL 3.0.0 has deprecated SSL_CTX_load_verify_locations */
if(ssl_cafile && !X509_STORE_load_file(store, ssl_cafile)) {
if(!imported_native_ca && !imported_ca_info_blob) {
@@ -3339,6 +3348,7 @@ static X509_STORE *get_cached_x509_store(struct Curl_cfilter *cf,
struct Curl_multi *multi = data->multi_easy ? data->multi_easy : data->multi;
X509_STORE *store = NULL;
+ DEBUGASSERT(multi);
if(multi &&
multi->ssl_backend_data &&
multi->ssl_backend_data->store &&
@@ -3358,6 +3368,7 @@ static void set_cached_x509_store(struct Curl_cfilter *cf,
struct Curl_multi *multi = data->multi_easy ? data->multi_easy : data->multi;
struct multi_ssl_backend_data *mbackend;
+ DEBUGASSERT(multi);
if(!multi)
return;
@@ -3449,17 +3460,6 @@ static CURLcode ossl_connect_step1(struct Curl_cfilter *cf,
struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
BIO *bio;
-
-#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
- bool sni;
- const char *hostname = connssl->hostname;
-
-#ifdef ENABLE_IPV6
- struct in6_addr addr;
-#else
- struct in_addr addr;
-#endif
-#endif
const long int ssl_version = conn_config->version;
char * const ssl_cert = ssl_config->primary.clientcert;
const struct curl_blob *ssl_cert_blob = ssl_config->primary.cert_blob;
@@ -3494,7 +3494,6 @@ static CURLcode ossl_connect_step1(struct Curl_cfilter *cf,
#else
req_method = SSLv23_client_method();
#endif
- use_sni(TRUE);
break;
case CURL_SSLVERSION_SSLv2:
failf(data, "No SSLv2 support");
@@ -3787,13 +3786,8 @@ static CURLcode ossl_connect_step1(struct Curl_cfilter *cf,
backend->server_cert = 0x0;
#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
- if((0 == Curl_inet_pton(AF_INET, hostname, &addr)) &&
-#ifdef ENABLE_IPV6
- (0 == Curl_inet_pton(AF_INET6, hostname, &addr)) &&
-#endif
- sni) {
- char *snihost = Curl_ssl_snihost(data, hostname, NULL);
- if(!snihost || !SSL_set_tlsext_host_name(backend->handle, snihost)) {
+ if(connssl->peer.sni) {
+ if(!SSL_set_tlsext_host_name(backend->handle, connssl->peer.sni)) {
failf(data, "Failed set SNI");
return CURLE_SSL_CONNECT_ERROR;
}
@@ -3802,6 +3796,7 @@ static CURLcode ossl_connect_step1(struct Curl_cfilter *cf,
SSL_set_app_data(backend->handle, cf);
+ connssl->reused_session = FALSE;
if(ssl_config->primary.sessionid) {
Curl_ssl_sessionid_lock(data);
if(!Curl_ssl_getsessionid(cf, data, &ssl_sessionid, NULL)) {
@@ -3815,6 +3810,7 @@ static CURLcode ossl_connect_step1(struct Curl_cfilter *cf,
}
/* Informational message */
infof(data, "SSL reusing session ID");
+ connssl->reused_session = TRUE;
}
Curl_ssl_sessionid_unlock(data);
}
@@ -3975,7 +3971,7 @@ static CURLcode ossl_connect_step2(struct Curl_cfilter *cf,
Curl_strerror(sockerr, extramsg, sizeof(extramsg));
failf(data, OSSL_PACKAGE " SSL_connect: %s in connection to %s:%d ",
extramsg[0] ? extramsg : SSL_ERROR_to_str(detail),
- connssl->hostname, connssl->port);
+ connssl->peer.hostname, connssl->port);
return result;
}
@@ -3986,13 +3982,28 @@ static CURLcode ossl_connect_step2(struct Curl_cfilter *cf,
}
}
else {
+ int psigtype_nid = NID_undef;
+ const char *negotiated_group_name = NULL;
+
/* we connected fine, we're not waiting for anything else. */
connssl->connecting_state = ssl_connect_3;
+#if (OPENSSL_VERSION_NUMBER >= 0x30000000L)
+ SSL_get_peer_signature_type_nid(backend->handle, &psigtype_nid);
+#if (OPENSSL_VERSION_NUMBER >= 0x30200000L)
+ negotiated_group_name = SSL_get0_group_name(backend->handle);
+#else
+ negotiated_group_name =
+ OBJ_nid2sn(SSL_get_negotiated_group(backend->handle) & 0x0000FFFF);
+#endif
+#endif
+
/* Informational message */
- infof(data, "SSL connection using %s / %s",
+ infof(data, "SSL connection using %s / %s / %s / %s",
SSL_get_version(backend->handle),
- SSL_get_cipher(backend->handle));
+ SSL_get_cipher(backend->handle),
+ negotiated_group_name? negotiated_group_name : "[blank]",
+ OBJ_nid2sn(psigtype_nid));
#ifdef HAS_ALPN
/* Sets data and len to negotiated protocol, len is 0 if no protocol was
@@ -4069,6 +4080,75 @@ static CURLcode ossl_pkp_pin_peer_pubkey(struct Curl_easy *data, X509* cert,
return result;
}
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && \
+ !(defined(LIBRESSL_VERSION_NUMBER) && \
+ LIBRESSL_VERSION_NUMBER < 0x3060000fL) && \
+ !defined(OPENSSL_IS_BORINGSSL) && \
+ !defined(OPENSSL_IS_AWSLC) && \
+ !defined(CURL_DISABLE_VERBOSE_STRINGS)
+static void infof_certstack(struct Curl_easy *data, const SSL *ssl)
+{
+ STACK_OF(X509) *certstack;
+ long verify_result;
+ int num_cert_levels;
+ int cert_level;
+
+ verify_result = SSL_get_verify_result(ssl);
+ if(verify_result != X509_V_OK)
+ certstack = SSL_get_peer_cert_chain(ssl);
+ else
+ certstack = SSL_get0_verified_chain(ssl);
+ num_cert_levels = sk_X509_num(certstack);
+
+ for(cert_level = 0; cert_level < num_cert_levels; cert_level++) {
+ char cert_algorithm[80] = "";
+ char group_name_final[80] = "";
+ const X509_ALGOR *palg_cert = NULL;
+ const ASN1_OBJECT *paobj_cert = NULL;
+ X509 *current_cert;
+ EVP_PKEY *current_pkey;
+ int key_bits;
+ int key_sec_bits;
+ int get_group_name;
+ const char *type_name;
+
+ current_cert = sk_X509_value(certstack, cert_level);
+
+ X509_get0_signature(NULL, &palg_cert, current_cert);
+ X509_ALGOR_get0(&paobj_cert, NULL, NULL, palg_cert);
+ OBJ_obj2txt(cert_algorithm, sizeof(cert_algorithm), paobj_cert, 0);
+
+ current_pkey = X509_get0_pubkey(current_cert);
+ key_bits = EVP_PKEY_bits(current_pkey);
+#if (OPENSSL_VERSION_NUMBER < 0x30000000L)
+#define EVP_PKEY_get_security_bits EVP_PKEY_security_bits
+#endif
+ key_sec_bits = EVP_PKEY_get_security_bits(current_pkey);
+#if (OPENSSL_VERSION_NUMBER >= 0x30000000L)
+ {
+ char group_name[80] = "";
+ get_group_name = EVP_PKEY_get_group_name(current_pkey, group_name,
+ sizeof(group_name), NULL);
+ msnprintf(group_name_final, sizeof(group_name_final), "/%s", group_name);
+ }
+ type_name = EVP_PKEY_get0_type_name(current_pkey);
+#else
+ get_group_name = 0;
+ type_name = NULL;
+#endif
+
+ infof(data,
+ " Certificate level %d: "
+ "Public key type %s%s (%d/%d Bits/secBits), signed using %s",
+ cert_level, type_name ? type_name : "?",
+ get_group_name == 0 ? "" : group_name_final,
+ key_bits, key_sec_bits, cert_algorithm);
+ }
+}
+#else
+#define infof_certstack(data, ssl)
+#endif
+
/*
* Get the server cert, verify it and show it, etc., only call failf() if the
* 'strict' argument is TRUE as otherwise all this is for informational
@@ -4147,8 +4227,8 @@ static CURLcode servercert(struct Curl_cfilter *cf,
BIO_free(mem);
if(conn_config->verifyhost) {
- result = ossl_verifyhost(data, conn, backend->server_cert,
- connssl->hostname, connssl->dispname);
+ result = Curl_ossl_verifyhost(data, conn, &connssl->peer,
+ backend->server_cert);
if(result) {
X509_free(backend->server_cert);
backend->server_cert = NULL;
@@ -4258,9 +4338,12 @@ static CURLcode servercert(struct Curl_cfilter *cf,
infof(data, " SSL certificate verify ok.");
}
+ infof_certstack(data, backend->handle);
+
#if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_TLSEXT) && \
!defined(OPENSSL_NO_OCSP)
- if(conn_config->verifystatus) {
+ if(conn_config->verifystatus && !connssl->reused_session) {
+ /* don't do this after Session ID reuse */
result = verifystatus(cf, data);
if(result) {
X509_free(backend->server_cert);
@@ -4522,22 +4605,9 @@ static ssize_t ossl_send(struct Curl_cfilter *cf,
case SSL_ERROR_SSL: {
/* A failure in the SSL library occurred, usually a protocol error.
The OpenSSL error queue contains more information on the error. */
- struct Curl_cfilter *cf_ssl_next = Curl_ssl_cf_get_ssl(cf->next);
- struct ssl_connect_data *connssl_next = cf_ssl_next?
- cf_ssl_next->ctx : NULL;
sslerror = ERR_get_error();
- if(ERR_GET_LIB(sslerror) == ERR_LIB_SSL &&
- ERR_GET_REASON(sslerror) == SSL_R_BIO_NOT_SET &&
- connssl->state == ssl_connection_complete &&
- (connssl_next && connssl_next->state == ssl_connection_complete)
- ) {
- char ver[120];
- (void)ossl_version(ver, sizeof(ver));
- failf(data, "Error: %s does not support double SSL tunneling.", ver);
- }
- else
- failf(data, "SSL_write() error: %s",
- ossl_strerror(sslerror, error_buffer, sizeof(error_buffer)));
+ failf(data, "SSL_write() error: %s",
+ ossl_strerror(sslerror, error_buffer, sizeof(error_buffer)));
*curlcode = CURLE_SEND_ERROR;
rc = -1;
goto out;
@@ -4842,7 +4912,7 @@ const struct Curl_ssl Curl_ssl_openssl = {
ossl_cert_status_request, /* cert_status_request */
ossl_connect, /* connect */
ossl_connect_nonblocking, /* connect_nonblocking */
- Curl_ssl_get_select_socks,/* getsock */
+ Curl_ssl_adjust_pollset, /* adjust_pollset */
ossl_get_internals, /* get_internals */
ossl_close, /* close_one */
ossl_close_all, /* close_all */
diff --git a/libs/libcurl/src/vtls/openssl.h b/libs/libcurl/src/vtls/openssl.h
index b88b83febe..df36a831b1 100644
--- a/libs/libcurl/src/vtls/openssl.h
+++ b/libs/libcurl/src/vtls/openssl.h
@@ -31,24 +31,21 @@
* This header should only be needed to get included by vtls.c, openssl.c
* and ngtcp2.c
*/
+#include <openssl/ossl_typ.h>
#include <openssl/ssl.h>
#include "urldata.h"
-/*
- * In an effort to avoid using 'X509 *' here, we instead use the struct
- * x509_st version of the type so that we can forward-declare it here without
- * having to include <openssl/x509v3.h>. Including that header causes name
- * conflicts when libcurl is built with both Schannel and OpenSSL support.
- */
-struct x509_st;
+#if (OPENSSL_VERSION_NUMBER < 0x30000000L)
+#define SSL_get1_peer_certificate SSL_get_peer_certificate
+#endif
+
CURLcode Curl_ossl_verifyhost(struct Curl_easy *data, struct connectdata *conn,
- struct x509_st *server_cert);
+ struct ssl_peer *peer, X509 *server_cert);
extern const struct Curl_ssl Curl_ssl_openssl;
-struct ssl_ctx_st;
CURLcode Curl_ossl_set_client_cert(struct Curl_easy *data,
- struct ssl_ctx_st *ctx, char *cert_file,
+ SSL_CTX *ctx, char *cert_file,
const struct curl_blob *cert_blob,
const char *cert_type, char *key_file,
const struct curl_blob *key_blob,
@@ -65,5 +62,9 @@ CURLcode Curl_ssl_setup_x509_store(struct Curl_cfilter *cf,
struct Curl_easy *data,
SSL_CTX *ssl_ctx);
+CURLcode Curl_ossl_ctx_configure(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ SSL_CTX *ssl_ctx);
+
#endif /* USE_OPENSSL */
#endif /* HEADER_CURL_SSLUSE_H */
diff --git a/libs/libcurl/src/vtls/rustls.c b/libs/libcurl/src/vtls/rustls.c
index 989954bf46..d30325d098 100644
--- a/libs/libcurl/src/vtls/rustls.c
+++ b/libs/libcurl/src/vtls/rustls.c
@@ -39,6 +39,7 @@
#include "select.h"
#include "strerror.h"
#include "multiif.h"
+#include "connect.h" /* for the connect timeout */
struct rustls_ssl_backend_data
{
@@ -75,14 +76,6 @@ cr_data_pending(struct Curl_cfilter *cf, const struct Curl_easy *data)
return backend->data_pending;
}
-static CURLcode
-cr_connect(struct Curl_cfilter *cf UNUSED_PARAM,
- struct Curl_easy *data UNUSED_PARAM)
-{
- infof(data, "rustls_connect: unimplemented");
- return CURLE_SSL_CONNECT_ERROR;
-}
-
struct io_ctx {
struct Curl_cfilter *cf;
struct Curl_easy *data;
@@ -386,7 +379,7 @@ cr_init_backend(struct Curl_cfilter *cf, struct Curl_easy *data,
/* CURLOPT_CAINFO_BLOB overrides CURLOPT_CAINFO */
(ca_info_blob ? NULL : conn_config->CAfile);
const bool verifypeer = conn_config->verifypeer;
- const char *hostname = connssl->hostname;
+ const char *hostname = connssl->peer.hostname;
char errorbuf[256];
size_t errorlen;
int result;
@@ -458,12 +451,11 @@ cr_init_backend(struct Curl_cfilter *cf, struct Curl_easy *data,
backend->config = rustls_client_config_builder_build(config_builder);
DEBUGASSERT(rconn == NULL);
{
- char *snihost = Curl_ssl_snihost(data, hostname, NULL);
- if(!snihost) {
- failf(data, "rustls: failed to get SNI");
- return CURLE_SSL_CONNECT_ERROR;
- }
- result = rustls_client_connection_new(backend->config, snihost, &rconn);
+ /* rustls claims to manage ip address hostnames as well here. So,
+ * if we have an SNI, we use it, otherwise we pass the hostname */
+ char *server = connssl->peer.sni?
+ connssl->peer.sni : connssl->peer.hostname;
+ result = rustls_client_connection_new(backend->config, server, &rconn);
}
if(result != RUSTLS_RESULT_OK) {
rustls_error(result, errorbuf, sizeof(errorbuf), &errorlen);
@@ -486,9 +478,20 @@ cr_set_negotiated_alpn(struct Curl_cfilter *cf, struct Curl_easy *data,
Curl_alpn_set_negotiated(cf, data, protocol, len);
}
+/* Given an established network connection, do a TLS handshake.
+ *
+ * If `blocking` is true, this function will block until the handshake is
+ * complete. Otherwise it will return as soon as I/O would block.
+ *
+ * For the non-blocking I/O case, this function will set `*done` to true
+ * once the handshake is complete. This function never reads the value of
+ * `*done*`.
+ */
static CURLcode
-cr_connect_nonblocking(struct Curl_cfilter *cf,
- struct Curl_easy *data, bool *done)
+cr_connect_common(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ bool blocking,
+ bool *done)
{
struct ssl_connect_data *const connssl = cf->ctx;
curl_socket_t sockfd = Curl_conn_cf_get_socket(cf, data);
@@ -502,6 +505,8 @@ cr_connect_nonblocking(struct Curl_cfilter *cf,
bool wants_write;
curl_socket_t writefd;
curl_socket_t readfd;
+ timediff_t timeout_ms;
+ timediff_t socket_check_timeout;
DEBUGASSERT(backend);
@@ -539,12 +544,29 @@ cr_connect_nonblocking(struct Curl_cfilter *cf,
writefd = wants_write?sockfd:CURL_SOCKET_BAD;
readfd = wants_read?sockfd:CURL_SOCKET_BAD;
- what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd, 0);
+ /* check allowed time left */
+ timeout_ms = Curl_timeleft(data, NULL, TRUE);
+
+ if(timeout_ms < 0) {
+ /* no need to continue if time already is up */
+ failf(data, "rustls: operation timed out before socket check");
+ return CURLE_OPERATION_TIMEDOUT;
+ }
+
+ socket_check_timeout = blocking?timeout_ms:0;
+
+ what = Curl_socket_check(
+ readfd, CURL_SOCKET_BAD, writefd, socket_check_timeout);
if(what < 0) {
/* fatal error */
failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
return CURLE_SSL_CONNECT_ERROR;
}
+ if(blocking && 0 == what) {
+ failf(data, "rustls connection timeout after %d ms",
+ socket_check_timeout);
+ return CURLE_OPERATION_TIMEDOUT;
+ }
if(0 == what) {
infof(data, "Curl_socket_check: %s would block",
wants_read&&wants_write ? "writing and reading" :
@@ -589,32 +611,43 @@ cr_connect_nonblocking(struct Curl_cfilter *cf,
DEBUGASSERT(false);
}
-/* returns a bitmap of flags for this connection's first socket indicating
- whether we want to read or write */
-static int
-cr_get_select_socks(struct Curl_cfilter *cf, struct Curl_easy *data,
- curl_socket_t *socks)
+static CURLcode
+cr_connect_nonblocking(struct Curl_cfilter *cf,
+ struct Curl_easy *data, bool *done)
{
- struct ssl_connect_data *const connssl = cf->ctx;
- curl_socket_t sockfd = Curl_conn_cf_get_socket(cf, data);
- struct rustls_ssl_backend_data *const backend =
- (struct rustls_ssl_backend_data *)connssl->backend;
- struct rustls_connection *rconn = NULL;
+ return cr_connect_common(cf, data, false, done);
+}
- (void)data;
- DEBUGASSERT(backend);
- rconn = backend->conn;
+static CURLcode
+cr_connect_blocking(struct Curl_cfilter *cf UNUSED_PARAM,
+ struct Curl_easy *data UNUSED_PARAM)
+{
+ bool done; /* unused */
+ return cr_connect_common(cf, data, true, &done);
+}
- if(rustls_connection_wants_write(rconn)) {
- socks[0] = sockfd;
- return GETSOCK_WRITESOCK(0);
- }
- if(rustls_connection_wants_read(rconn)) {
- socks[0] = sockfd;
- return GETSOCK_READSOCK(0);
+static void cr_adjust_pollset(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ struct easy_pollset *ps)
+{
+ if(!cf->connected) {
+ curl_socket_t sock = Curl_conn_cf_get_socket(cf->next, data);
+ struct ssl_connect_data *const connssl = cf->ctx;
+ struct rustls_ssl_backend_data *const backend =
+ (struct rustls_ssl_backend_data *)connssl->backend;
+ struct rustls_connection *rconn = NULL;
+
+ (void)data;
+ DEBUGASSERT(backend);
+ rconn = backend->conn;
+
+ if(rustls_connection_wants_write(rconn)) {
+ Curl_pollset_add_out(data, ps, sock);
+ }
+ if(rustls_connection_wants_read(rconn)) {
+ Curl_pollset_add_in(data, ps, sock);
+ }
}
-
- return GETSOCK_BLANK;
}
static void *
@@ -675,9 +708,9 @@ const struct Curl_ssl Curl_ssl_rustls = {
cr_data_pending, /* data_pending */
Curl_none_random, /* random */
Curl_none_cert_status_request, /* cert_status_request */
- cr_connect, /* connect */
+ cr_connect_blocking, /* connect */
cr_connect_nonblocking, /* connect_nonblocking */
- cr_get_select_socks, /* get_select_socks */
+ cr_adjust_pollset, /* adjust_pollset */
cr_get_internals, /* get_internals */
cr_close, /* close_one */
Curl_none_close_all, /* close_all */
diff --git a/libs/libcurl/src/vtls/schannel.c b/libs/libcurl/src/vtls/schannel.c
index 77ab43a9bf..c04f968f29 100644
--- a/libs/libcurl/src/vtls/schannel.c
+++ b/libs/libcurl/src/vtls/schannel.c
@@ -1063,17 +1063,12 @@ schannel_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
#endif
SECURITY_STATUS sspi_status = SEC_E_OK;
struct Curl_schannel_cred *old_cred = NULL;
- struct in_addr addr;
-#ifdef ENABLE_IPV6
- struct in6_addr addr6;
-#endif
CURLcode result;
- const char *hostname = connssl->hostname;
DEBUGASSERT(backend);
DEBUGF(infof(data,
"schannel: SSL/TLS connection with %s port %d (step 1/3)",
- hostname, connssl->port));
+ connssl->peer.hostname, connssl->port));
if(curlx_verify_windows_version(5, 1, 0, PLATFORM_WINNT,
VERSION_LESS_THAN_EQUAL)) {
@@ -1154,22 +1149,14 @@ schannel_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
/* A hostname associated with the credential is needed by
InitializeSecurityContext for SNI and other reasons. */
- snihost = Curl_ssl_snihost(data, hostname, NULL);
- if(!snihost) {
- failf(data, "Failed to set SNI");
- return CURLE_SSL_CONNECT_ERROR;
- }
+ snihost = connssl->peer.sni? connssl->peer.sni : connssl->peer.hostname;
backend->cred->sni_hostname = curlx_convert_UTF8_to_tchar(snihost);
if(!backend->cred->sni_hostname)
return CURLE_OUT_OF_MEMORY;
}
/* Warn if SNI is disabled due to use of an IP address */
- if(Curl_inet_pton(AF_INET, hostname, &addr)
-#ifdef ENABLE_IPV6
- || Curl_inet_pton(AF_INET6, hostname, &addr6)
-#endif
- ) {
+ if(connssl->peer.is_ip_address) {
infof(data, "schannel: using IP address, SNI is not supported by OS.");
}
@@ -1346,7 +1333,7 @@ schannel_connect_step2(struct Curl_cfilter *cf, struct Curl_easy *data)
DEBUGF(infof(data,
"schannel: SSL/TLS connection with %s port %d (step 2/3)",
- connssl->hostname, connssl->port));
+ connssl->peer.hostname, connssl->port));
if(!backend->cred || !backend->ctxt)
return CURLE_SSL_CONNECT_ERROR;
@@ -1700,7 +1687,7 @@ schannel_connect_step3(struct Curl_cfilter *cf, struct Curl_easy *data)
DEBUGF(infof(data,
"schannel: SSL/TLS connection with %s port %d (step 3/3)",
- connssl->hostname, connssl->port));
+ connssl->peer.hostname, connssl->port));
if(!backend->cred)
return CURLE_SSL_CONNECT_ERROR;
@@ -2498,7 +2485,7 @@ static int schannel_shutdown(struct Curl_cfilter *cf,
if(backend->ctxt) {
infof(data, "schannel: shutting down SSL/TLS connection with %s port %d",
- connssl->hostname, connssl->port);
+ connssl->peer.hostname, connssl->port);
}
if(backend->cred && backend->ctxt) {
@@ -2754,6 +2741,151 @@ static void *schannel_get_internals(struct ssl_connect_data *connssl,
return &backend->ctxt->ctxt_handle;
}
+HCERTSTORE Curl_schannel_get_cached_cert_store(struct Curl_cfilter *cf,
+ const struct Curl_easy *data)
+{
+ struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
+ struct Curl_multi *multi = data->multi_easy ? data->multi_easy : data->multi;
+ const struct curl_blob *ca_info_blob = conn_config->ca_info_blob;
+ struct schannel_multi_ssl_backend_data *mbackend;
+ const struct ssl_general_config *cfg = &data->set.general_ssl;
+ timediff_t timeout_ms;
+ timediff_t elapsed_ms;
+ struct curltime now;
+ unsigned char info_blob_digest[CURL_SHA256_DIGEST_LENGTH];
+
+ DEBUGASSERT(multi);
+
+ if(!multi || !multi->ssl_backend_data) {
+ return NULL;
+ }
+
+ mbackend = (struct schannel_multi_ssl_backend_data *)multi->ssl_backend_data;
+ if(!mbackend->cert_store) {
+ return NULL;
+ }
+
+ /* zero ca_cache_timeout completely disables caching */
+ if(!cfg->ca_cache_timeout) {
+ return NULL;
+ }
+
+ /* check for cache timeout by using the cached_x509_store_expired timediff
+ calculation pattern from openssl.c.
+ negative timeout means retain forever. */
+ timeout_ms = cfg->ca_cache_timeout * (timediff_t)1000;
+ if(timeout_ms >= 0) {
+ now = Curl_now();
+ elapsed_ms = Curl_timediff(now, mbackend->time);
+ if(elapsed_ms >= timeout_ms) {
+ return NULL;
+ }
+ }
+
+ if(ca_info_blob) {
+ if(!mbackend->CAinfo_blob_digest) {
+ return NULL;
+ }
+ if(mbackend->CAinfo_blob_size != ca_info_blob->len) {
+ return NULL;
+ }
+ schannel_sha256sum((const unsigned char *)ca_info_blob->data,
+ ca_info_blob->len,
+ info_blob_digest,
+ CURL_SHA256_DIGEST_LENGTH);
+ if(memcmp(mbackend->CAinfo_blob_digest,
+ info_blob_digest,
+ CURL_SHA256_DIGEST_LENGTH)) {
+ return NULL;
+ }
+ }
+ else {
+ if(!conn_config->CAfile || !mbackend->CAfile ||
+ strcmp(mbackend->CAfile, conn_config->CAfile)) {
+ return NULL;
+ }
+ }
+
+ return mbackend->cert_store;
+}
+
+bool Curl_schannel_set_cached_cert_store(struct Curl_cfilter *cf,
+ const struct Curl_easy *data,
+ HCERTSTORE cert_store)
+{
+ struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
+ struct Curl_multi *multi = data->multi_easy ? data->multi_easy : data->multi;
+ const struct curl_blob *ca_info_blob = conn_config->ca_info_blob;
+ struct schannel_multi_ssl_backend_data *mbackend;
+ unsigned char *CAinfo_blob_digest = NULL;
+ size_t CAinfo_blob_size = 0;
+ char *CAfile = NULL;
+
+ DEBUGASSERT(multi);
+
+ if(!multi) {
+ return false;
+ }
+
+ if(!multi->ssl_backend_data) {
+ multi->ssl_backend_data =
+ calloc(1, sizeof(struct schannel_multi_ssl_backend_data));
+ if(!multi->ssl_backend_data) {
+ return false;
+ }
+ }
+
+ mbackend = (struct schannel_multi_ssl_backend_data *)multi->ssl_backend_data;
+
+
+ if(ca_info_blob) {
+ CAinfo_blob_digest = malloc(CURL_SHA256_DIGEST_LENGTH);
+ if(!CAinfo_blob_digest) {
+ return false;
+ }
+ schannel_sha256sum((const unsigned char *)ca_info_blob->data,
+ ca_info_blob->len,
+ CAinfo_blob_digest,
+ CURL_SHA256_DIGEST_LENGTH);
+ CAinfo_blob_size = ca_info_blob->len;
+ }
+ else {
+ if(conn_config->CAfile) {
+ CAfile = strdup(conn_config->CAfile);
+ if(!CAfile) {
+ return false;
+ }
+ }
+ }
+
+ /* free old cache data */
+ if(mbackend->cert_store) {
+ CertCloseStore(mbackend->cert_store, 0);
+ }
+ free(mbackend->CAinfo_blob_digest);
+ free(mbackend->CAfile);
+
+ mbackend->time = Curl_now();
+ mbackend->cert_store = cert_store;
+ mbackend->CAinfo_blob_digest = CAinfo_blob_digest;
+ mbackend->CAinfo_blob_size = CAinfo_blob_size;
+ mbackend->CAfile = CAfile;
+ return true;
+}
+
+static void schannel_free_multi_ssl_backend_data(
+ struct multi_ssl_backend_data *msbd)
+{
+ struct schannel_multi_ssl_backend_data *mbackend =
+ (struct schannel_multi_ssl_backend_data*)msbd;
+ if(mbackend->cert_store) {
+ CertCloseStore(mbackend->cert_store, 0);
+ }
+ free(mbackend->CAinfo_blob_digest);
+ free(mbackend->CAfile);
+ free(mbackend);
+}
+
const struct Curl_ssl Curl_ssl_schannel = {
{ CURLSSLBACKEND_SCHANNEL, "schannel" }, /* info */
@@ -2777,7 +2909,7 @@ const struct Curl_ssl Curl_ssl_schannel = {
Curl_none_cert_status_request, /* cert_status_request */
schannel_connect, /* connect */
schannel_connect_nonblocking, /* connect_nonblocking */
- Curl_ssl_get_select_socks, /* getsock */
+ Curl_ssl_adjust_pollset, /* adjust_pollset */
schannel_get_internals, /* get_internals */
schannel_close, /* close_one */
Curl_none_close_all, /* close_all */
@@ -2789,7 +2921,7 @@ const struct Curl_ssl Curl_ssl_schannel = {
schannel_sha256sum, /* sha256sum */
NULL, /* associate_connection */
NULL, /* disassociate_connection */
- NULL, /* free_multi_ssl_backend_data */
+ schannel_free_multi_ssl_backend_data, /* free_multi_ssl_backend_data */
schannel_recv, /* recv decrypted data */
schannel_send, /* send data to encrypt */
};
diff --git a/libs/libcurl/src/vtls/schannel_int.h b/libs/libcurl/src/vtls/schannel_int.h
index 17a94d6e85..c460be63aa 100644
--- a/libs/libcurl/src/vtls/schannel_int.h
+++ b/libs/libcurl/src/vtls/schannel_int.h
@@ -149,5 +149,22 @@ struct schannel_ssl_backend_data {
#endif
};
+struct schannel_multi_ssl_backend_data {
+ unsigned char *CAinfo_blob_digest; /* CA info blob digest */
+ size_t CAinfo_blob_size; /* CA info blob size */
+ char *CAfile; /* CAfile path used to generate
+ certificate store */
+ HCERTSTORE cert_store; /* cached certificate store or
+ NULL if none */
+ struct curltime time; /* when the cached store was created */
+};
+
+HCERTSTORE Curl_schannel_get_cached_cert_store(struct Curl_cfilter *cf,
+ const struct Curl_easy *data);
+
+bool Curl_schannel_set_cached_cert_store(struct Curl_cfilter *cf,
+ const struct Curl_easy *data,
+ HCERTSTORE cert_store);
+
#endif /* USE_SCHANNEL */
#endif /* HEADER_CURL_SCHANNEL_INT_H */
diff --git a/libs/libcurl/src/vtls/schannel_verify.c b/libs/libcurl/src/vtls/schannel_verify.c
index 35ce35b789..0c9c00c16a 100644
--- a/libs/libcurl/src/vtls/schannel_verify.c
+++ b/libs/libcurl/src/vtls/schannel_verify.c
@@ -470,7 +470,7 @@ CURLcode Curl_verify_host(struct Curl_cfilter *cf,
CERT_CONTEXT *pCertContextServer = NULL;
TCHAR *cert_hostname_buff = NULL;
size_t cert_hostname_buff_index = 0;
- const char *conn_hostname = connssl->hostname;
+ const char *conn_hostname = connssl->peer.hostname;
size_t hostlen = strlen(conn_hostname);
DWORD len = 0;
DWORD actual_len = 0;
@@ -600,6 +600,7 @@ CURLcode Curl_verify_certificate(struct Curl_cfilter *cf,
const CERT_CHAIN_CONTEXT *pChainContext = NULL;
HCERTCHAINENGINE cert_chain_engine = NULL;
HCERTSTORE trust_store = NULL;
+ HCERTSTORE own_trust_store = NULL;
DEBUGASSERT(BACKEND);
@@ -630,31 +631,46 @@ CURLcode Curl_verify_certificate(struct Curl_cfilter *cf,
result = CURLE_SSL_CACERT_BADFILE;
}
else {
- /* Open the certificate store */
- trust_store = CertOpenStore(CERT_STORE_PROV_MEMORY,
- 0,
- (HCRYPTPROV)NULL,
- CERT_STORE_CREATE_NEW_FLAG,
- NULL);
- if(!trust_store) {
- char buffer[STRERROR_LEN];
- failf(data, "schannel: failed to create certificate store: %s",
- Curl_winapi_strerror(GetLastError(), buffer, sizeof(buffer)));
- result = CURLE_SSL_CACERT_BADFILE;
+ /* try cache */
+ trust_store = Curl_schannel_get_cached_cert_store(cf, data);
+
+ if(trust_store) {
+ infof(data, "schannel: reusing certificate store from cache");
}
else {
- const struct curl_blob *ca_info_blob = conn_config->ca_info_blob;
- if(ca_info_blob) {
- result = add_certs_data_to_store(trust_store,
- (const char *)ca_info_blob->data,
- ca_info_blob->len,
- "(memory blob)",
- data);
+ /* Open the certificate store */
+ trust_store = CertOpenStore(CERT_STORE_PROV_MEMORY,
+ 0,
+ (HCRYPTPROV)NULL,
+ CERT_STORE_CREATE_NEW_FLAG,
+ NULL);
+ if(!trust_store) {
+ char buffer[STRERROR_LEN];
+ failf(data, "schannel: failed to create certificate store: %s",
+ Curl_winapi_strerror(GetLastError(), buffer, sizeof(buffer)));
+ result = CURLE_SSL_CACERT_BADFILE;
}
else {
- result = add_certs_file_to_store(trust_store,
- conn_config->CAfile,
- data);
+ const struct curl_blob *ca_info_blob = conn_config->ca_info_blob;
+ own_trust_store = trust_store;
+
+ if(ca_info_blob) {
+ result = add_certs_data_to_store(trust_store,
+ (const char *)ca_info_blob->data,
+ ca_info_blob->len,
+ "(memory blob)",
+ data);
+ }
+ else {
+ result = add_certs_file_to_store(trust_store,
+ conn_config->CAfile,
+ data);
+ }
+ if(result == CURLE_OK) {
+ if(Curl_schannel_set_cached_cert_store(cf, data, trust_store)) {
+ own_trust_store = NULL;
+ }
+ }
}
}
}
@@ -754,8 +770,8 @@ CURLcode Curl_verify_certificate(struct Curl_cfilter *cf,
CertFreeCertificateChainEngine(cert_chain_engine);
}
- if(trust_store) {
- CertCloseStore(trust_store, 0);
+ if(own_trust_store) {
+ CertCloseStore(own_trust_store, 0);
}
if(pChainContext)
diff --git a/libs/libcurl/src/vtls/sectransp.c b/libs/libcurl/src/vtls/sectransp.c
index d941119de9..26b673016e 100644
--- a/libs/libcurl/src/vtls/sectransp.c
+++ b/libs/libcurl/src/vtls/sectransp.c
@@ -46,8 +46,10 @@
#endif /* __clang__ */
#ifdef __GNUC__
+#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Waddress"
#pragma GCC diagnostic ignored "-Wundef"
+#pragma GCC diagnostic ignored "-Wunreachable-code"
#endif
#include <limits.h>
@@ -1013,7 +1015,7 @@ static CURLcode CopyCertSubject(struct Curl_easy *data,
}
else {
size_t cbuf_size = ((size_t)CFStringGetLength(c) * 4) + 1;
- cbuf = calloc(cbuf_size, 1);
+ cbuf = calloc(1, cbuf_size);
if(cbuf) {
if(!CFStringGetCString(c, cbuf, cbuf_size,
kCFStringEncodingUTF8)) {
@@ -1651,11 +1653,6 @@ static CURLcode sectransp_connect_step1(struct Curl_cfilter *cf,
const bool verifypeer = conn_config->verifypeer;
char * const ssl_cert = ssl_config->primary.clientcert;
const struct curl_blob *ssl_cert_blob = ssl_config->primary.cert_blob;
-#ifdef ENABLE_IPV6
- struct in6_addr addr;
-#else
- struct in_addr addr;
-#endif /* ENABLE_IPV6 */
char *ciphers;
OSStatus err = noErr;
#if CURL_BUILD_MAC
@@ -2003,13 +2000,9 @@ static CURLcode sectransp_connect_step1(struct Curl_cfilter *cf,
* Both hostname check and SNI require SSLSetPeerDomainName().
* Also: the verifyhost setting influences SNI usage */
if(conn_config->verifyhost) {
- size_t snilen;
- char *snihost = Curl_ssl_snihost(data, connssl->hostname, &snilen);
- if(!snihost) {
- failf(data, "Failed to set SNI");
- return CURLE_SSL_CONNECT_ERROR;
- }
- err = SSLSetPeerDomainName(backend->ssl_ctx, snihost, snilen);
+ char *server = connssl->peer.sni?
+ connssl->peer.sni : connssl->peer.hostname;
+ err = SSLSetPeerDomainName(backend->ssl_ctx, server, strlen(server));
if(err != noErr) {
failf(data, "SSL: SSLSetPeerDomainName() failed: OSStatus %d",
@@ -2017,11 +2010,7 @@ static CURLcode sectransp_connect_step1(struct Curl_cfilter *cf,
return CURLE_SSL_CONNECT_ERROR;
}
- if((Curl_inet_pton(AF_INET, connssl->hostname, &addr))
- #ifdef ENABLE_IPV6
- || (Curl_inet_pton(AF_INET6, connssl->hostname, &addr))
- #endif
- ) {
+ if(connssl->peer.is_ip_address) {
infof(data, "WARNING: using IP address, SNI is being disabled by "
"the OS.");
}
@@ -2079,7 +2068,7 @@ static CURLcode sectransp_connect_step1(struct Curl_cfilter *cf,
ssl_sessionid =
aprintf("%s:%d:%d:%s:%d",
ssl_cafile ? ssl_cafile : "(blob memory)",
- verifypeer, conn_config->verifyhost, connssl->hostname,
+ verifypeer, conn_config->verifyhost, connssl->peer.hostname,
connssl->port);
ssl_sessionid_len = strlen(ssl_sessionid);
@@ -2665,7 +2654,7 @@ check_handshake:
host name: */
case errSSLHostNameMismatch:
failf(data, "SSL certificate peer verification failed, the "
- "certificate did not match \"%s\"\n", connssl->dispname);
+ "certificate did not match \"%s\"\n", connssl->peer.dispname);
return CURLE_PEER_FAILED_VERIFICATION;
/* Problem with SSL / TLS negotiation */
@@ -2757,7 +2746,7 @@ check_handshake:
default:
/* May also return codes listed in Security Framework Result Codes */
failf(data, "Unknown SSL protocol error in connection to %s:%d",
- connssl->hostname, err);
+ connssl->peer.hostname, err);
break;
}
return CURLE_SSL_CONNECT_ERROR;
@@ -3415,7 +3404,6 @@ again:
}
*curlcode = CURLE_AGAIN;
return -1L;
- break;
/* errSSLClosedGraceful - server gracefully shut down the SSL session
errSSLClosedNoNotify - server hung up on us instead of sending a
@@ -3425,7 +3413,6 @@ again:
case errSSLClosedNoNotify:
*curlcode = CURLE_OK;
return 0;
- break;
/* The below is errSSLPeerAuthCompleted; it's not defined in
Leopard's headers */
@@ -3445,7 +3432,6 @@ again:
failf(data, "SSLRead() return error %d", err);
*curlcode = CURLE_RECV_ERROR;
return -1L;
- break;
}
}
return (ssize_t)processed;
@@ -3483,7 +3469,7 @@ const struct Curl_ssl Curl_ssl_sectransp = {
Curl_none_cert_status_request, /* cert_status_request */
sectransp_connect, /* connect */
sectransp_connect_nonblocking, /* connect_nonblocking */
- Curl_ssl_get_select_socks, /* getsock */
+ Curl_ssl_adjust_pollset, /* adjust_pollset */
sectransp_get_internals, /* get_internals */
sectransp_close, /* close_one */
Curl_none_close_all, /* close_all */
@@ -3500,6 +3486,10 @@ const struct Curl_ssl Curl_ssl_sectransp = {
sectransp_send, /* send data to encrypt */
};
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
+
#ifdef __clang__
#pragma clang diagnostic pop
#endif
diff --git a/libs/libcurl/src/vtls/vtls.c b/libs/libcurl/src/vtls/vtls.c
index 6a45ccb6d8..f37907c494 100644
--- a/libs/libcurl/src/vtls/vtls.c
+++ b/libs/libcurl/src/vtls/vtls.c
@@ -67,6 +67,7 @@
#include "warnless.h"
#include "curl_base64.h"
#include "curl_printf.h"
+#include "inet_pton.h"
#include "strdup.h"
/* The last #include files should be: */
@@ -131,9 +132,6 @@ static bool blobcmp(struct curl_blob *first, struct curl_blob *second)
}
#ifdef USE_SSL
-static const struct alpn_spec ALPN_SPEC_H10 = {
- { ALPN_HTTP_1_0 }, 1
-};
static const struct alpn_spec ALPN_SPEC_H11 = {
{ ALPN_HTTP_1_1 }, 1
};
@@ -147,51 +145,83 @@ static const struct alpn_spec *alpn_get_spec(int httpwant, bool use_alpn)
{
if(!use_alpn)
return NULL;
- if(httpwant == CURL_HTTP_VERSION_1_0)
- return &ALPN_SPEC_H10;
#ifdef USE_HTTP2
if(httpwant >= CURL_HTTP_VERSION_2)
return &ALPN_SPEC_H2_H11;
+#else
+ (void)httpwant;
#endif
+ /* Use the ALPN protocol "http/1.1" for HTTP/1.x.
+ Avoid "http/1.0" because some servers don't support it. */
return &ALPN_SPEC_H11;
}
#endif /* USE_SSL */
-bool
-Curl_ssl_config_matches(struct ssl_primary_config *data,
- struct ssl_primary_config *needle)
-{
- if((data->version == needle->version) &&
- (data->version_max == needle->version_max) &&
- (data->ssl_options == needle->ssl_options) &&
- (data->verifypeer == needle->verifypeer) &&
- (data->verifyhost == needle->verifyhost) &&
- (data->verifystatus == needle->verifystatus) &&
- blobcmp(data->cert_blob, needle->cert_blob) &&
- blobcmp(data->ca_info_blob, needle->ca_info_blob) &&
- blobcmp(data->issuercert_blob, needle->issuercert_blob) &&
- Curl_safecmp(data->CApath, needle->CApath) &&
- Curl_safecmp(data->CAfile, needle->CAfile) &&
- Curl_safecmp(data->issuercert, needle->issuercert) &&
- Curl_safecmp(data->clientcert, needle->clientcert) &&
+void Curl_ssl_easy_config_init(struct Curl_easy *data)
+{
+ /*
+ * libcurl 7.10 introduced SSL verification *by default*! This needs to be
+ * switched off unless wanted.
+ */
+ data->set.ssl.primary.verifypeer = TRUE;
+ data->set.ssl.primary.verifyhost = TRUE;
+ data->set.ssl.primary.sessionid = TRUE; /* session ID caching by default */
+#ifndef CURL_DISABLE_PROXY
+ data->set.proxy_ssl = data->set.ssl;
+#endif
+}
+
+static bool
+match_ssl_primary_config(struct Curl_easy *data,
+ struct ssl_primary_config *c1,
+ struct ssl_primary_config *c2)
+{
+ (void)data;
+ if((c1->version == c2->version) &&
+ (c1->version_max == c2->version_max) &&
+ (c1->ssl_options == c2->ssl_options) &&
+ (c1->verifypeer == c2->verifypeer) &&
+ (c1->verifyhost == c2->verifyhost) &&
+ (c1->verifystatus == c2->verifystatus) &&
+ blobcmp(c1->cert_blob, c2->cert_blob) &&
+ blobcmp(c1->ca_info_blob, c2->ca_info_blob) &&
+ blobcmp(c1->issuercert_blob, c2->issuercert_blob) &&
+ Curl_safecmp(c1->CApath, c2->CApath) &&
+ Curl_safecmp(c1->CAfile, c2->CAfile) &&
+ Curl_safecmp(c1->issuercert, c2->issuercert) &&
+ Curl_safecmp(c1->clientcert, c2->clientcert) &&
#ifdef USE_TLS_SRP
- !Curl_timestrcmp(data->username, needle->username) &&
- !Curl_timestrcmp(data->password, needle->password) &&
+ !Curl_timestrcmp(c1->username, c2->username) &&
+ !Curl_timestrcmp(c1->password, c2->password) &&
#endif
- strcasecompare(data->cipher_list, needle->cipher_list) &&
- strcasecompare(data->cipher_list13, needle->cipher_list13) &&
- strcasecompare(data->curves, needle->curves) &&
- strcasecompare(data->CRLfile, needle->CRLfile) &&
- strcasecompare(data->pinned_key, needle->pinned_key))
+ strcasecompare(c1->cipher_list, c2->cipher_list) &&
+ strcasecompare(c1->cipher_list13, c2->cipher_list13) &&
+ strcasecompare(c1->curves, c2->curves) &&
+ strcasecompare(c1->CRLfile, c2->CRLfile) &&
+ strcasecompare(c1->pinned_key, c2->pinned_key))
return TRUE;
return FALSE;
}
-bool
-Curl_clone_primary_ssl_config(struct ssl_primary_config *source,
- struct ssl_primary_config *dest)
+bool Curl_ssl_conn_config_match(struct Curl_easy *data,
+ struct connectdata *candidate,
+ bool proxy)
+{
+#ifndef CURL_DISABLE_PROXY
+ if(proxy)
+ return match_ssl_primary_config(data, &data->set.proxy_ssl.primary,
+ &candidate->proxy_ssl_config);
+#else
+ (void)proxy;
+#endif
+ return match_ssl_primary_config(data, &data->set.ssl.primary,
+ &candidate->ssl_config);
+}
+
+static bool clone_ssl_primary_config(struct ssl_primary_config *source,
+ struct ssl_primary_config *dest)
{
dest->version = source->version;
dest->version_max = source->version_max;
@@ -221,7 +251,7 @@ Curl_clone_primary_ssl_config(struct ssl_primary_config *source,
return TRUE;
}
-void Curl_free_primary_ssl_config(struct ssl_primary_config *sslc)
+static void Curl_free_primary_ssl_config(struct ssl_primary_config *sslc)
{
Curl_safefree(sslc->CApath);
Curl_safefree(sslc->CAfile);
@@ -241,6 +271,111 @@ void Curl_free_primary_ssl_config(struct ssl_primary_config *sslc)
#endif
}
+CURLcode Curl_ssl_easy_config_complete(struct Curl_easy *data)
+{
+ data->set.ssl.primary.CApath = data->set.str[STRING_SSL_CAPATH];
+ data->set.ssl.primary.CAfile = data->set.str[STRING_SSL_CAFILE];
+ data->set.ssl.primary.CRLfile = data->set.str[STRING_SSL_CRLFILE];
+ data->set.ssl.primary.issuercert = data->set.str[STRING_SSL_ISSUERCERT];
+ data->set.ssl.primary.issuercert_blob = data->set.blobs[BLOB_SSL_ISSUERCERT];
+ data->set.ssl.primary.cipher_list =
+ data->set.str[STRING_SSL_CIPHER_LIST];
+ data->set.ssl.primary.cipher_list13 =
+ data->set.str[STRING_SSL_CIPHER13_LIST];
+ data->set.ssl.primary.pinned_key =
+ data->set.str[STRING_SSL_PINNEDPUBLICKEY];
+ data->set.ssl.primary.cert_blob = data->set.blobs[BLOB_CERT];
+ data->set.ssl.primary.ca_info_blob = data->set.blobs[BLOB_CAINFO];
+ data->set.ssl.primary.curves = data->set.str[STRING_SSL_EC_CURVES];
+#ifdef USE_TLS_SRP
+ data->set.ssl.primary.username = data->set.str[STRING_TLSAUTH_USERNAME];
+ data->set.ssl.primary.password = data->set.str[STRING_TLSAUTH_PASSWORD];
+#endif
+ data->set.ssl.cert_type = data->set.str[STRING_CERT_TYPE];
+ data->set.ssl.key = data->set.str[STRING_KEY];
+ data->set.ssl.key_type = data->set.str[STRING_KEY_TYPE];
+ data->set.ssl.key_passwd = data->set.str[STRING_KEY_PASSWD];
+ data->set.ssl.primary.clientcert = data->set.str[STRING_CERT];
+ data->set.ssl.key_blob = data->set.blobs[BLOB_KEY];
+
+#ifndef CURL_DISABLE_PROXY
+ data->set.proxy_ssl.primary.CApath = data->set.str[STRING_SSL_CAPATH_PROXY];
+ data->set.proxy_ssl.primary.CAfile = data->set.str[STRING_SSL_CAFILE_PROXY];
+ data->set.proxy_ssl.primary.cipher_list =
+ data->set.str[STRING_SSL_CIPHER_LIST_PROXY];
+ data->set.proxy_ssl.primary.cipher_list13 =
+ data->set.str[STRING_SSL_CIPHER13_LIST_PROXY];
+ data->set.proxy_ssl.primary.pinned_key =
+ data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY];
+ data->set.proxy_ssl.primary.cert_blob = data->set.blobs[BLOB_CERT_PROXY];
+ data->set.proxy_ssl.primary.ca_info_blob =
+ data->set.blobs[BLOB_CAINFO_PROXY];
+ data->set.proxy_ssl.primary.issuercert =
+ data->set.str[STRING_SSL_ISSUERCERT_PROXY];
+ data->set.proxy_ssl.primary.issuercert_blob =
+ data->set.blobs[BLOB_SSL_ISSUERCERT_PROXY];
+ data->set.proxy_ssl.primary.CRLfile =
+ data->set.str[STRING_SSL_CRLFILE_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.key_blob = data->set.blobs[BLOB_KEY_PROXY];
+#ifdef USE_TLS_SRP
+ data->set.proxy_ssl.primary.username =
+ data->set.str[STRING_TLSAUTH_USERNAME_PROXY];
+ data->set.proxy_ssl.primary.password =
+ data->set.str[STRING_TLSAUTH_PASSWORD_PROXY];
+#endif
+#endif /* CURL_DISABLE_PROXY */
+
+ return CURLE_OK;
+}
+
+CURLcode Curl_ssl_conn_config_init(struct Curl_easy *data,
+ struct connectdata *conn)
+{
+ /* Clone "primary" SSL configurations from the esay handle to
+ * the connection. They are used for connection cache matching and
+ * probably outlive the easy handle */
+ if(!clone_ssl_primary_config(&data->set.ssl.primary, &conn->ssl_config))
+ return CURLE_OUT_OF_MEMORY;
+#ifndef CURL_DISABLE_PROXY
+ if(!clone_ssl_primary_config(&data->set.proxy_ssl.primary,
+ &conn->proxy_ssl_config))
+ return CURLE_OUT_OF_MEMORY;
+#endif
+ return CURLE_OK;
+}
+
+void Curl_ssl_conn_config_cleanup(struct connectdata *conn)
+{
+ Curl_free_primary_ssl_config(&conn->ssl_config);
+#ifndef CURL_DISABLE_PROXY
+ Curl_free_primary_ssl_config(&conn->proxy_ssl_config);
+#endif
+}
+
+void Curl_ssl_conn_config_update(struct Curl_easy *data, bool for_proxy)
+{
+ /* May be called on an easy that has no connection yet */
+ if(data->conn) {
+ struct ssl_primary_config *src, *dest;
+#ifndef CURL_DISABLE_PROXY
+ src = for_proxy? &data->set.proxy_ssl.primary : &data->set.ssl.primary;
+ dest = for_proxy? &data->conn->proxy_ssl_config : &data->conn->ssl_config;
+#else
+ (void)for_proxy;
+ src = &data->set.ssl.primary;
+ dest = &data->conn->ssl_config;
+#endif
+ dest->verifyhost = src->verifyhost;
+ dest->verifypeer = src->verifypeer;
+ dest->verifystatus = src->verifystatus;
+ }
+}
+
#ifdef USE_SSL
static int multissl_setup(const struct Curl_ssl *backend);
#endif
@@ -432,7 +567,7 @@ bool Curl_ssl_getsessionid(struct Curl_cfilter *cf,
if(!check->sessionid)
/* not session ID means blank entry */
continue;
- if(strcasecompare(connssl->hostname, check->name) &&
+ if(strcasecompare(connssl->peer.hostname, check->name) &&
((!cf->conn->bits.conn_to_host && !check->conn_to_host) ||
(cf->conn->bits.conn_to_host && check->conn_to_host &&
strcasecompare(cf->conn->conn_to_host.name, check->conn_to_host))) &&
@@ -441,7 +576,7 @@ bool Curl_ssl_getsessionid(struct Curl_cfilter *cf,
cf->conn->conn_to_port == check->conn_to_port)) &&
(connssl->port == check->remote_port) &&
strcasecompare(cf->conn->handler->scheme, check->scheme) &&
- Curl_ssl_config_matches(conn_config, &check->ssl_config)) {
+ match_ssl_primary_config(data, conn_config, &check->ssl_config)) {
/* yes, we have a session ID! */
(*general_age)++; /* increase general age */
check->age = *general_age; /* set this as used in this age */
@@ -456,7 +591,8 @@ bool Curl_ssl_getsessionid(struct Curl_cfilter *cf,
DEBUGF(infof(data, "%s Session ID in cache for %s %s://%s:%d",
no_match? "Didn't find": "Found",
Curl_ssl_cf_is_proxy(cf) ? "proxy" : "host",
- cf->conn->handler->scheme, connssl->hostname, connssl->port));
+ cf->conn->handler->scheme, connssl->peer.hostname,
+ connssl->port));
return no_match;
}
@@ -532,7 +668,7 @@ CURLcode Curl_ssl_addsessionid(struct Curl_cfilter *cf,
(void)ssl_config;
DEBUGASSERT(ssl_config->primary.sessionid);
- clone_host = strdup(connssl->hostname);
+ clone_host = strdup(connssl->peer.hostname);
if(!clone_host)
return CURLE_OUT_OF_MEMORY; /* bail out */
@@ -590,7 +726,7 @@ CURLcode Curl_ssl_addsessionid(struct Curl_cfilter *cf,
store->remote_port = connssl->port;
store->scheme = cf->conn->handler->scheme;
- if(!Curl_clone_primary_ssl_config(conn_config, &store->ssl_config)) {
+ if(!clone_ssl_primary_config(conn_config, &store->ssl_config)) {
Curl_free_primary_ssl_config(&store->ssl_config);
store->sessionid = NULL; /* let caller free sessionid */
free(clone_host);
@@ -629,22 +765,21 @@ void Curl_ssl_close_all(struct Curl_easy *data)
Curl_ssl->close_all(data);
}
-int Curl_ssl_get_select_socks(struct Curl_cfilter *cf, struct Curl_easy *data,
- curl_socket_t *socks)
+void Curl_ssl_adjust_pollset(struct Curl_cfilter *cf, struct Curl_easy *data,
+ struct easy_pollset *ps)
{
- struct ssl_connect_data *connssl = cf->ctx;
- curl_socket_t sock = Curl_conn_cf_get_socket(cf->next, data);
-
- if(sock == CURL_SOCKET_BAD)
- return GETSOCK_BLANK;
-
- if(connssl->connecting_state == ssl_connect_2_writing) {
- /* we are only interested in writing */
- socks[0] = sock;
- return GETSOCK_WRITESOCK(0);
+ if(!cf->connected) {
+ struct ssl_connect_data *connssl = cf->ctx;
+ curl_socket_t sock = Curl_conn_cf_get_socket(cf->next, data);
+ if(sock != CURL_SOCKET_BAD) {
+ if(connssl->connecting_state == ssl_connect_2_writing) {
+ Curl_pollset_set_out_only(data, ps, sock);
+ }
+ else {
+ Curl_pollset_set_in_only(data, ps, sock);
+ }
+ }
}
- socks[0] = sock;
- return GETSOCK_READSOCK(0);
}
/* Selects an SSL crypto engine
@@ -786,32 +921,6 @@ CURLcode Curl_ssl_random(struct Curl_easy *data,
}
/*
- * Curl_ssl_snihost() converts the input host name to a suitable SNI name put
- * in data->state.buffer. Returns a pointer to the name (or NULL if a problem)
- * and stores the new length in 'olen'.
- *
- * SNI fields must not have any trailing dot and while RFC 6066 section 3 says
- * the SNI field is case insensitive, browsers always send the data lowercase
- * and subsequently there are numerous servers out there that don't work
- * unless the name is lowercased.
- */
-
-char *Curl_ssl_snihost(struct Curl_easy *data, const char *host, size_t *olen)
-{
- size_t len = strlen(host);
- if(len && (host[len-1] == '.'))
- len--;
- if(len >= data->set.buffer_size)
- return NULL;
-
- Curl_strntolower(data->state.buffer, host, len);
- data->state.buffer[len] = 0;
- if(olen)
- *olen = len;
- return data->state.buffer;
-}
-
-/*
* Public key pem to der conversion
*/
@@ -1156,13 +1265,13 @@ static CURLcode multissl_connect_nonblocking(struct Curl_cfilter *cf,
return Curl_ssl->connect_nonblocking(cf, data, done);
}
-static int multissl_get_select_socks(struct Curl_cfilter *cf,
+static void multissl_adjust_pollset(struct Curl_cfilter *cf,
struct Curl_easy *data,
- curl_socket_t *socks)
+ struct easy_pollset *ps)
{
if(multissl_setup(NULL))
- return 0;
- return Curl_ssl->get_select_socks(cf, data, socks);
+ return;
+ Curl_ssl->adjust_pollset(cf, data, ps);
}
static void *multissl_get_internals(struct ssl_connect_data *connssl,
@@ -1214,7 +1323,7 @@ static const struct Curl_ssl Curl_ssl_multi = {
Curl_none_cert_status_request, /* cert_status_request */
multissl_connect, /* connect */
multissl_connect_nonblocking, /* connect_nonblocking */
- multissl_get_select_socks, /* getsock */
+ multissl_adjust_pollset, /* adjust_pollset */
multissl_get_internals, /* get_internals */
multissl_close, /* close_one */
Curl_none_close_all, /* close_all */
@@ -1409,12 +1518,14 @@ CURLsslset Curl_init_sslset_nolock(curl_sslbackend id, const char *name,
#ifdef USE_SSL
-static void free_hostname(struct ssl_connect_data *connssl)
+void Curl_ssl_peer_cleanup(struct ssl_peer *peer)
{
- if(connssl->dispname != connssl->hostname)
- free(connssl->dispname);
- free(connssl->hostname);
- connssl->hostname = connssl->dispname = NULL;
+ if(peer->dispname != peer->hostname)
+ free(peer->dispname);
+ free(peer->sni);
+ free(peer->hostname);
+ peer->hostname = peer->sni = peer->dispname = NULL;
+ peer->is_ip_address = FALSE;
}
static void cf_close(struct Curl_cfilter *cf, struct Curl_easy *data)
@@ -1423,12 +1534,26 @@ static void cf_close(struct Curl_cfilter *cf, struct Curl_easy *data)
if(connssl) {
Curl_ssl->close(cf, data);
connssl->state = ssl_connection_none;
- free_hostname(connssl);
+ Curl_ssl_peer_cleanup(&connssl->peer);
}
cf->connected = FALSE;
}
-static CURLcode reinit_hostname(struct Curl_cfilter *cf)
+static int is_ip_address(const char *hostname)
+{
+#ifdef ENABLE_IPV6
+ struct in6_addr addr;
+#else
+ struct in_addr addr;
+#endif
+ return (hostname && hostname[0] && (Curl_inet_pton(AF_INET, hostname, &addr)
+#ifdef ENABLE_IPV6
+ || Curl_inet_pton(AF_INET6, hostname, &addr)
+#endif
+ ));
+}
+
+CURLcode Curl_ssl_peer_init(struct ssl_peer *peer, struct Curl_cfilter *cf)
{
struct ssl_connect_data *connssl = cf->ctx;
const char *ehostname, *edispname;
@@ -1454,23 +1579,43 @@ static CURLcode reinit_hostname(struct Curl_cfilter *cf)
}
/* change if ehostname changed */
- if(ehostname && (!connssl->hostname
- || strcmp(ehostname, connssl->hostname))) {
- free_hostname(connssl);
- connssl->hostname = strdup(ehostname);
- if(!connssl->hostname) {
- free_hostname(connssl);
+ if(ehostname && (!peer->hostname
+ || strcmp(ehostname, peer->hostname))) {
+ Curl_ssl_peer_cleanup(peer);
+ peer->hostname = strdup(ehostname);
+ if(!peer->hostname) {
+ Curl_ssl_peer_cleanup(peer);
return CURLE_OUT_OF_MEMORY;
}
if(!edispname || !strcmp(ehostname, edispname))
- connssl->dispname = connssl->hostname;
+ peer->dispname = peer->hostname;
else {
- connssl->dispname = strdup(edispname);
- if(!connssl->dispname) {
- free_hostname(connssl);
+ peer->dispname = strdup(edispname);
+ if(!peer->dispname) {
+ Curl_ssl_peer_cleanup(peer);
return CURLE_OUT_OF_MEMORY;
}
}
+
+ peer->sni = NULL;
+ peer->is_ip_address = is_ip_address(peer->hostname)? TRUE : FALSE;
+ if(peer->hostname[0] && !peer->is_ip_address) {
+ /* not an IP address, normalize according to RCC 6066 ch. 3,
+ * max len of SNI is 2^16-1, no trailing dot */
+ size_t len = strlen(peer->hostname);
+ if(len && (peer->hostname[len-1] == '.'))
+ len--;
+ if(len < USHRT_MAX) {
+ peer->sni = calloc(1, len + 1);
+ if(!peer->sni) {
+ Curl_ssl_peer_cleanup(peer);
+ return CURLE_OUT_OF_MEMORY;
+ }
+ Curl_strntolower(peer->sni, peer->hostname, len);
+ peer->sni[len] = 0;
+ }
+ }
+
}
connssl->port = eport;
return CURLE_OK;
@@ -1525,7 +1670,7 @@ static CURLcode ssl_cf_connect(struct Curl_cfilter *cf,
goto out;
*done = FALSE;
- result = reinit_hostname(cf);
+ result = Curl_ssl_peer_init(&connssl->peer, cf);
if(result)
goto out;
@@ -1599,22 +1744,17 @@ static ssize_t ssl_cf_recv(struct Curl_cfilter *cf,
return nread;
}
-static int ssl_cf_get_select_socks(struct Curl_cfilter *cf,
+static void ssl_cf_adjust_pollset(struct Curl_cfilter *cf,
struct Curl_easy *data,
- curl_socket_t *socks)
+ struct easy_pollset *ps)
{
struct cf_call_data save;
- int fds = GETSOCK_BLANK;
- if(!cf->next->connected) {
- fds = cf->next->cft->get_select_socks(cf->next, data, socks);
- }
- else if(!cf->connected) {
+ if(!cf->connected) {
CF_DATA_SAVE(save, cf, data);
- fds = Curl_ssl->get_select_socks(cf, data, socks);
+ Curl_ssl->adjust_pollset(cf, data, ps);
CF_DATA_RESTORE(cf, save);
}
- return fds;
}
static CURLcode ssl_cf_cntrl(struct Curl_cfilter *cf,
@@ -1705,7 +1845,7 @@ struct Curl_cftype Curl_cft_ssl = {
ssl_cf_connect,
ssl_cf_close,
Curl_cf_def_get_host,
- ssl_cf_get_select_socks,
+ ssl_cf_adjust_pollset,
ssl_cf_data_pending,
ssl_cf_send,
ssl_cf_recv,
@@ -1723,7 +1863,7 @@ struct Curl_cftype Curl_cft_ssl_proxy = {
ssl_cf_connect,
ssl_cf_close,
Curl_cf_def_get_host,
- ssl_cf_get_select_socks,
+ ssl_cf_adjust_pollset,
ssl_cf_data_pending,
ssl_cf_send,
ssl_cf_recv,
@@ -1837,6 +1977,16 @@ bool Curl_ssl_supports(struct Curl_easy *data, int option)
return (Curl_ssl->supports & option)? TRUE : FALSE;
}
+static struct Curl_cfilter *get_ssl_filter(struct Curl_cfilter *cf)
+{
+ for(; cf; cf = cf->next) {
+ if(cf->cft == &Curl_cft_ssl || cf->cft == &Curl_cft_ssl_proxy)
+ return cf;
+ }
+ return NULL;
+}
+
+
void *Curl_ssl_get_internals(struct Curl_easy *data, int sockindex,
CURLINFO info, int n)
{
@@ -1844,8 +1994,8 @@ void *Curl_ssl_get_internals(struct Curl_easy *data, int sockindex,
(void)n;
if(data->conn) {
struct Curl_cfilter *cf;
- /* get first filter in chain, if any is present */
- cf = Curl_ssl_cf_get_ssl(data->conn->cfilter[sockindex]);
+ /* get first SSL filter in chain, if any is present */
+ cf = get_ssl_filter(data->conn->cfilter[sockindex]);
if(cf) {
struct cf_call_data save;
CF_DATA_SAVE(save, cf, data);
@@ -1875,23 +2025,6 @@ CURLcode Curl_ssl_cfilter_remove(struct Curl_easy *data,
return result;
}
-static struct Curl_cfilter *get_ssl_cf_engaged(struct connectdata *conn,
- int sockindex)
-{
- struct Curl_cfilter *cf, *lowest_ssl_cf = NULL;
-
- for(cf = conn->cfilter[sockindex]; cf; cf = cf->next) {
- if(cf->cft == &Curl_cft_ssl || cf->cft == &Curl_cft_ssl_proxy) {
- lowest_ssl_cf = cf;
- if(cf->connected || (cf->next && cf->next->connected)) {
- /* connected or about to start */
- return cf;
- }
- }
- }
- return lowest_ssl_cf;
-}
-
bool Curl_ssl_cf_is_proxy(struct Curl_cfilter *cf)
{
return (cf->cft == &Curl_cft_ssl_proxy);
@@ -1908,17 +2041,6 @@ Curl_ssl_cf_get_config(struct Curl_cfilter *cf, struct Curl_easy *data)
#endif
}
-struct ssl_config_data *
-Curl_ssl_get_config(struct Curl_easy *data, int sockindex)
-{
- struct Curl_cfilter *cf;
-
- (void)data;
- DEBUGASSERT(data->conn);
- cf = get_ssl_cf_engaged(data->conn, sockindex);
- return cf? Curl_ssl_cf_get_config(cf, data) : &data->set.ssl;
-}
-
struct ssl_primary_config *
Curl_ssl_cf_get_primary_config(struct Curl_cfilter *cf)
{
@@ -1930,15 +2052,6 @@ Curl_ssl_cf_get_primary_config(struct Curl_cfilter *cf)
#endif
}
-struct Curl_cfilter *Curl_ssl_cf_get_ssl(struct Curl_cfilter *cf)
-{
- for(; cf; cf = cf->next) {
- if(cf->cft == &Curl_cft_ssl || cf->cft == &Curl_cft_ssl_proxy)
- return cf;
- }
- return NULL;
-}
-
CURLcode Curl_alpn_to_proto_buf(struct alpn_proto_buf *buf,
const struct alpn_spec *spec)
{
@@ -2005,10 +2118,6 @@ CURLcode Curl_alpn_set_negotiated(struct Curl_cfilter *cf,
!memcmp(ALPN_HTTP_1_1, proto, ALPN_HTTP_1_1_LENGTH)) {
*palpn = CURL_HTTP_VERSION_1_1;
}
- else if(proto_len == ALPN_HTTP_1_0_LENGTH &&
- !memcmp(ALPN_HTTP_1_0, proto, ALPN_HTTP_1_0_LENGTH)) {
- *palpn = CURL_HTTP_VERSION_1_0;
- }
#ifdef USE_HTTP2
else if(proto_len == ALPN_H2_LENGTH &&
!memcmp(ALPN_H2, proto, ALPN_H2_LENGTH)) {
diff --git a/libs/libcurl/src/vtls/vtls.h b/libs/libcurl/src/vtls/vtls.h
index 2ec6162296..111d17f32c 100644
--- a/libs/libcurl/src/vtls/vtls.h
+++ b/libs/libcurl/src/vtls/vtls.h
@@ -65,15 +65,54 @@ CURLsslset Curl_init_sslset_nolock(curl_sslbackend id, const char *name,
#define CURL_SHA256_DIGEST_LENGTH 32 /* fixed size */
#endif
-char *Curl_ssl_snihost(struct Curl_easy *data, const char *host, size_t *olen);
-bool Curl_ssl_config_matches(struct ssl_primary_config *data,
- struct ssl_primary_config *needle);
-bool Curl_clone_primary_ssl_config(struct ssl_primary_config *source,
- struct ssl_primary_config *dest);
-void Curl_free_primary_ssl_config(struct ssl_primary_config *sslc);
-
curl_sslbackend Curl_ssl_backend(void);
+/**
+ * Init ssl config for a new easy handle.
+ */
+void Curl_ssl_easy_config_init(struct Curl_easy *data);
+
+/**
+ * Init the `data->set.ssl` and `data->set.proxy_ssl` for
+ * connection matching use.
+ */
+CURLcode Curl_ssl_easy_config_complete(struct Curl_easy *data);
+
+/**
+ * Init SSL configs (main + proxy) for a new connection from the easy handle.
+ */
+CURLcode Curl_ssl_conn_config_init(struct Curl_easy *data,
+ struct connectdata *conn);
+
+/**
+ * Free allocated resources in SSL configs (main + proxy) for
+ * the given connection.
+ */
+void Curl_ssl_conn_config_cleanup(struct connectdata *conn);
+
+/**
+ * Return TRUE iff SSL configuration from `conn` is functionally the
+ * same as the one on `candidate`.
+ * @param proxy match the proxy SSL config or the main one
+ */
+bool Curl_ssl_conn_config_match(struct Curl_easy *data,
+ struct connectdata *candidate,
+ bool proxy);
+
+/* Update certain connection SSL config flags after they have
+ * been changed on the easy handle. Will work for `verifypeer`,
+ * `verifyhost` and `verifystatus`. */
+void Curl_ssl_conn_config_update(struct Curl_easy *data, bool for_proxy);
+
+/**
+ * Init SSL peer information for filter. Can be called repeatedly.
+ */
+CURLcode Curl_ssl_peer_init(struct ssl_peer *peer, struct Curl_cfilter *cf);
+/**
+ * Free all allocated data and reset peer information.
+ */
+void Curl_ssl_peer_cleanup(struct ssl_peer *peer);
+
#ifdef USE_SSL
int Curl_ssl_init(void);
void Curl_ssl_cleanup(void);
@@ -160,18 +199,6 @@ CURLcode Curl_cf_ssl_proxy_insert_after(struct Curl_cfilter *cf_at,
#endif /* !CURL_DISABLE_PROXY */
/**
- * Get the SSL configuration that is used on the connection.
- * This returns NULL if no SSL is configured.
- * Otherwise it returns the config of the first (highest) one that is
- * either connected, in handshake or about to start
- * (e.g. all filters below it are connected). If SSL filters are present,
- * but neither can start operating, return the config of the lowest one
- * that will first come into effect when connecting.
- */
-struct ssl_config_data *Curl_ssl_get_config(struct Curl_easy *data,
- int sockindex);
-
-/**
* True iff the underlying SSL implementation supports the option.
* Option is one of the defined SSLSUPP_* values.
* `data` maybe NULL for the features of the default implementation.
@@ -188,6 +215,18 @@ bool Curl_ssl_supports(struct Curl_easy *data, int ssl_option);
void *Curl_ssl_get_internals(struct Curl_easy *data, int sockindex,
CURLINFO info, int n);
+/**
+ * Get the ssl_config_data in `data` that is relevant for cfilter `cf`.
+ */
+struct ssl_config_data *Curl_ssl_cf_get_config(struct Curl_cfilter *cf,
+ struct Curl_easy *data);
+
+/**
+ * Get the primary config relevant for the filter from its connection.
+ */
+struct ssl_primary_config *
+ Curl_ssl_cf_get_primary_config(struct Curl_cfilter *cf);
+
extern struct Curl_cftype Curl_cft_ssl;
extern struct Curl_cftype Curl_cft_ssl_proxy;
@@ -209,8 +248,9 @@ extern struct Curl_cftype Curl_cft_ssl_proxy;
#define Curl_ssl_get_internals(a,b,c,d) NULL
#define Curl_ssl_supports(a,b) FALSE
#define Curl_ssl_cfilter_add(a,b,c) CURLE_NOT_BUILT_IN
-#define Curl_ssl_get_config(a,b) NULL
#define Curl_ssl_cfilter_remove(a,b) CURLE_OK
+#define Curl_ssl_cf_get_config(a,b) NULL
+#define Curl_ssl_cf_get_primary_config(a) NULL
#endif
#endif /* HEADER_CURL_VTLS_H */
diff --git a/libs/libcurl/src/vtls/vtls_int.h b/libs/libcurl/src/vtls/vtls_int.h
index 7a78a56cc7..858a0de8e7 100644
--- a/libs/libcurl/src/vtls/vtls_int.h
+++ b/libs/libcurl/src/vtls/vtls_int.h
@@ -32,8 +32,6 @@
/* see https://www.iana.org/assignments/tls-extensiontype-values/ */
#define ALPN_HTTP_1_1_LENGTH 8
#define ALPN_HTTP_1_1 "http/1.1"
-#define ALPN_HTTP_1_0_LENGTH 8
-#define ALPN_HTTP_1_0 "http/1.0"
#define ALPN_H2_LENGTH 2
#define ALPN_H2 "h2"
#define ALPN_H3_LENGTH 2
@@ -70,14 +68,14 @@ CURLcode Curl_alpn_set_negotiated(struct Curl_cfilter *cf,
struct ssl_connect_data {
ssl_connection_state state;
ssl_connect_state connecting_state;
- char *hostname; /* hostname for verification */
- char *dispname; /* display version of hostname */
+ struct ssl_peer peer;
const struct alpn_spec *alpn; /* ALPN to use or NULL for none */
void *backend; /* vtls backend specific props */
struct cf_call_data call_data; /* data handle used in current call */
struct curltime handshake_done; /* time when handshake finished */
int port; /* remote port at origin */
BIT(use_alpn); /* if ALPN shall be used in handshake */
+ BIT(reused_session); /* session-ID was reused for this */
};
@@ -118,14 +116,11 @@ struct Curl_ssl {
struct Curl_easy *data,
bool *done);
- /* If the SSL backend wants to read or write on this connection during a
- handshake, set socks[0] to the connection's FIRSTSOCKET, and return
- a bitmap indicating read or write with GETSOCK_WRITESOCK(0) or
- GETSOCK_READSOCK(0). Otherwise return GETSOCK_BLANK.
- Mandatory. */
- int (*get_select_socks)(struct Curl_cfilter *cf, struct Curl_easy *data,
- curl_socket_t *socks);
-
+ /* During handshake, adjust the pollset to include the socket
+ * for POLLOUT or POLLIN as needed.
+ * Mandatory. */
+ void (*adjust_pollset)(struct Curl_cfilter *cf, struct Curl_easy *data,
+ struct easy_pollset *ps);
void *(*get_internals)(struct ssl_connect_data *connssl, CURLINFO info);
void (*close)(struct Curl_cfilter *cf, struct Curl_easy *data);
void (*close_all)(struct Curl_easy *data);
@@ -169,25 +164,8 @@ CURLcode Curl_none_set_engine(struct Curl_easy *data, const char *engine);
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);
-int Curl_ssl_get_select_socks(struct Curl_cfilter *cf, struct Curl_easy *data,
- curl_socket_t *socks);
-
-/**
- * Get the ssl_config_data in `data` that is relevant for cfilter `cf`.
- */
-struct ssl_config_data *Curl_ssl_cf_get_config(struct Curl_cfilter *cf,
- struct Curl_easy *data);
-
-/**
- * Get the primary config relevant for the filter from its connection.
- */
-struct ssl_primary_config *
- Curl_ssl_cf_get_primary_config(struct Curl_cfilter *cf);
-
-/**
- * Get the first SSL filter in the chain starting with `cf`, or NULL.
- */
-struct Curl_cfilter *Curl_ssl_cf_get_ssl(struct Curl_cfilter *cf);
+void Curl_ssl_adjust_pollset(struct Curl_cfilter *cf, struct Curl_easy *data,
+ struct easy_pollset *ps);
/**
* Get the SSL filter below the given one or NULL if there is none.
diff --git a/libs/libcurl/src/vtls/wolfssl.c b/libs/libcurl/src/vtls/wolfssl.c
index fad1f7a88e..32681520a0 100644
--- a/libs/libcurl/src/vtls/wolfssl.c
+++ b/libs/libcurl/src/vtls/wolfssl.c
@@ -480,6 +480,7 @@ wolfssl_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
return CURLE_SSL_CONNECT_ERROR;
}
#endif
+ default:
break;
}
@@ -513,7 +514,7 @@ wolfssl_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
}
}
-#ifndef NO_FILESYSTEM
+#if !defined(NO_FILESYSTEM) && defined(WOLFSSL_SYS_CA_CERTS)
/* load native CA certificates */
if(ssl_config->native_ca_store) {
if(wolfSSL_CTX_load_system_CA_certs(backend->ctx) != WOLFSSL_SUCCESS) {
@@ -608,24 +609,12 @@ wolfssl_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
SSL_VERIFY_NONE, NULL);
#ifdef HAVE_SNI
- if(sni) {
- struct in_addr addr4;
-#ifdef ENABLE_IPV6
- struct in6_addr addr6;
-#endif
- size_t hostname_len = strlen(connssl->hostname);
-
- if((hostname_len < USHRT_MAX) &&
- !Curl_inet_pton(AF_INET, connssl->hostname, &addr4)
-#ifdef ENABLE_IPV6
- && !Curl_inet_pton(AF_INET6, connssl->hostname, &addr6)
-#endif
- ) {
- size_t snilen;
- char *snihost = Curl_ssl_snihost(data, connssl->hostname, &snilen);
- if(!snihost ||
- wolfSSL_CTX_UseSNI(backend->ctx, WOLFSSL_SNI_HOST_NAME, snihost,
- (unsigned short)snilen) != 1) {
+ if(sni && connssl->peer.sni) {
+ size_t sni_len = strlen(connssl->peer.sni);
+ if((sni_len < USHRT_MAX)) {
+ if(wolfSSL_CTX_UseSNI(backend->ctx, WOLFSSL_SNI_HOST_NAME,
+ connssl->peer.sni,
+ (unsigned short)sni_len) != 1) {
failf(data, "Failed to set SNI");
return CURLE_SSL_CONNECT_ERROR;
}
@@ -763,9 +752,9 @@ wolfssl_connect_step2(struct Curl_cfilter *cf, struct Curl_easy *data)
/* Enable RFC2818 checks */
if(conn_config->verifyhost) {
- char *snihost = Curl_ssl_snihost(data, connssl->hostname, NULL);
- if(!snihost ||
- (wolfSSL_check_domain_name(backend->handle, snihost) == SSL_FAILURE))
+ char *snihost = connssl->peer.sni?
+ connssl->peer.sni : connssl->peer.hostname;
+ if(wolfSSL_check_domain_name(backend->handle, snihost) == SSL_FAILURE)
return CURLE_SSL_CONNECT_ERROR;
}
@@ -813,7 +802,7 @@ wolfssl_connect_step2(struct Curl_cfilter *cf, struct Curl_easy *data)
else if(DOMAIN_NAME_MISMATCH == detail) {
#if 1
failf(data, " subject alt name(s) or common name do not match \"%s\"",
- connssl->dispname);
+ connssl->peer.dispname);
return CURLE_PEER_FAILED_VERIFICATION;
#else
/* When the wolfssl_check_domain_name() is used and you desire to
@@ -1398,7 +1387,7 @@ const struct Curl_ssl Curl_ssl_wolfssl = {
Curl_none_cert_status_request, /* cert_status_request */
wolfssl_connect, /* connect */
wolfssl_connect_nonblocking, /* connect_nonblocking */
- Curl_ssl_get_select_socks, /* getsock */
+ Curl_ssl_adjust_pollset, /* adjust_pollset */
wolfssl_get_internals, /* get_internals */
wolfssl_close, /* close_one */
Curl_none_close_all, /* close_all */
diff --git a/libs/libcurl/src/vtls/x509asn1.c b/libs/libcurl/src/vtls/x509asn1.c
index a695922816..0ce971c7ba 100644
--- a/libs/libcurl/src/vtls/x509asn1.c
+++ b/libs/libcurl/src/vtls/x509asn1.c
@@ -1317,16 +1317,16 @@ CURLcode Curl_verifyhost(struct Curl_cfilter *cf,
if(Curl_parseX509(&cert, beg, end))
return CURLE_PEER_FAILED_VERIFICATION;
- hostlen = strlen(connssl->hostname);
+ hostlen = strlen(connssl->peer.hostname);
/* Get the server IP address. */
#ifdef ENABLE_IPV6
if(cf->conn->bits.ipv6_ip &&
- Curl_inet_pton(AF_INET6, connssl->hostname, &addr))
+ Curl_inet_pton(AF_INET6, connssl->peer.hostname, &addr))
addrlen = sizeof(struct in6_addr);
else
#endif
- if(Curl_inet_pton(AF_INET, connssl->hostname, &addr))
+ if(Curl_inet_pton(AF_INET, connssl->peer.hostname, &addr))
addrlen = sizeof(struct in_addr);
/* Process extensions. */
@@ -1361,7 +1361,7 @@ CURLcode Curl_verifyhost(struct Curl_cfilter *cf,
name.beg, name.end);
if(len > 0 && (size_t)len == strlen(dnsname))
matched = Curl_cert_hostcheck(dnsname, (size_t)len,
- connssl->hostname, hostlen);
+ connssl->peer.hostname, hostlen);
else
matched = 0;
free(dnsname);
@@ -1421,7 +1421,7 @@ CURLcode Curl_verifyhost(struct Curl_cfilter *cf,
if(strlen(dnsname) != (size_t) len) /* Nul byte in string ? */
failf(data, "SSL: illegal cert name field");
else if(Curl_cert_hostcheck((const char *) dnsname,
- len, connssl->hostname, hostlen)) {
+ len, connssl->peer.hostname, hostlen)) {
infof(data, " common name: %s (matched)", dnsname);
free(dnsname);
return CURLE_OK;
diff --git a/libs/libcurl/src/warnless.c b/libs/libcurl/src/warnless.c
index b28197d6cf..0fc4c268b2 100644
--- a/libs/libcurl/src/warnless.c
+++ b/libs/libcurl/src/warnless.c
@@ -37,7 +37,7 @@
#include "warnless.h"
-#ifdef WIN32
+#ifdef _WIN32
#undef read
#undef write
#endif
@@ -367,7 +367,7 @@ curl_socket_t curlx_sitosk(int i)
#endif /* USE_WINSOCK */
-#if defined(WIN32)
+#if defined(_WIN32)
ssize_t curlx_read(int fd, void *buf, size_t count)
{
@@ -379,8 +379,8 @@ ssize_t curlx_write(int fd, const void *buf, size_t count)
return (ssize_t)write(fd, buf, curlx_uztoui(count));
}
-/* Ensure that warnless.h continues to have an effect in "unity" builds. */
-#undef HEADER_CURL_WARNLESS_H
-
-#endif /* WIN32 */
+#endif /* _WIN32 */
+/* Ensure that warnless.h redefinitions continue to have an effect
+ in "unity" builds. */
+#undef HEADER_CURL_WARNLESS_H_REDEFS
diff --git a/libs/libcurl/src/warnless.h b/libs/libcurl/src/warnless.h
index 02301db792..7fa00af36c 100644
--- a/libs/libcurl/src/warnless.h
+++ b/libs/libcurl/src/warnless.h
@@ -69,18 +69,13 @@ curl_socket_t curlx_sitosk(int i);
#endif /* USE_WINSOCK */
-#if defined(WIN32)
+#if defined(_WIN32)
ssize_t curlx_read(int fd, void *buf, size_t count);
ssize_t curlx_write(int fd, const void *buf, size_t count);
-#undef read
-#define read(fd, buf, count) curlx_read(fd, buf, count)
-#undef write
-#define write(fd, buf, count) curlx_write(fd, buf, count)
-
-#endif /* WIN32 */
+#endif /* _WIN32 */
#if defined(__INTEL_COMPILER) && defined(__unix__)
@@ -97,3 +92,15 @@ unsigned short curlx_ntohs(unsigned short usnum);
#endif /* __INTEL_COMPILER && __unix__ */
#endif /* HEADER_CURL_WARNLESS_H */
+
+#ifndef HEADER_CURL_WARNLESS_H_REDEFS
+#define HEADER_CURL_WARNLESS_H_REDEFS
+
+#if defined(_WIN32)
+#undef read
+#define read(fd, buf, count) curlx_read(fd, buf, count)
+#undef write
+#define write(fd, buf, count) curlx_write(fd, buf, count)
+#endif
+
+#endif /* HEADER_CURL_WARNLESS_H_REDEFS */
diff --git a/libs/libcurl/src/ws.c b/libs/libcurl/src/ws.c
index 41eb5d526d..5c8db777f1 100644
--- a/libs/libcurl/src/ws.c
+++ b/libs/libcurl/src/ws.c
@@ -274,8 +274,8 @@ static CURLcode ws_dec_pass_payload(struct ws_decoder *dec,
dec->payload_offset += (curl_off_t)nwritten;
remain = dec->payload_len - dec->payload_offset;
/* infof(data, "WS-DEC: passed %zd bytes payload, %"
- CURL_FORMAT_CURL_OFF_T " remain",
- nwritten, remain); */
+ CURL_FORMAT_CURL_OFF_T " remain",
+ nwritten, remain); */
}
return remain? CURLE_AGAIN : CURLE_OK;
@@ -925,8 +925,8 @@ CURL_EXTERN CURLcode curl_ws_recv(struct Curl_easy *data, void *buffer,
*metap = &ws->frame;
*nread = ws->frame.len;
/* infof(data, "curl_ws_recv(len=%zu) -> %zu bytes (frame at %"
- CURL_FORMAT_CURL_OFF_T ", %" CURL_FORMAT_CURL_OFF_T " left)",
- buflen, *nread, ws->frame.offset, ws->frame.bytesleft); */
+ CURL_FORMAT_CURL_OFF_T ", %" CURL_FORMAT_CURL_OFF_T " left)",
+ buflen, *nread, ws->frame.offset, ws->frame.bytesleft); */
return CURLE_OK;
}