summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/curl-for-win.yml10
-rw-r--r--.github/workflows/distcheck.yml2
-rw-r--r--.github/workflows/http3-linux.yml2
-rw-r--r--.github/workflows/linux.yml2
-rw-r--r--.github/workflows/windows.yml8
-rw-r--r--docs/TODO6
-rw-r--r--docs/libcurl/curl_multi_get_offt.md29
-rw-r--r--docs/libcurl/opts/CURLMINFO_XFERS_ADDED.md63
-rw-r--r--docs/libcurl/opts/CURLMINFO_XFERS_CURRENT.md62
-rw-r--r--docs/libcurl/opts/CURLMINFO_XFERS_DONE.md58
-rw-r--r--docs/libcurl/opts/CURLMINFO_XFERS_PENDING.md60
-rw-r--r--docs/libcurl/opts/CURLMINFO_XFERS_RUNNING.md58
-rw-r--r--docs/libcurl/opts/CURLMOPT_NETWORK_CHANGED.md6
-rw-r--r--docs/libcurl/opts/CURLOPT_DNS_CACHE_TIMEOUT.md8
-rw-r--r--docs/libcurl/opts/Makefile.inc5
-rw-r--r--docs/libcurl/symbols-in-versions12
-rw-r--r--docs/tests/FILEFORMAT.md10
-rw-r--r--include/curl/multi.h18
-rw-r--r--lib/asyn-thrdd.c9
-rw-r--r--lib/cf-socket.c2
-rw-r--r--lib/curl_setup.h5
-rw-r--r--lib/hostip.c37
-rw-r--r--lib/http.c6
-rw-r--r--lib/multi.c14
-rw-r--r--lib/setopt.c257
-rw-r--r--lib/urldata.h16
-rw-r--r--lib/vquic/curl_ngtcp2.c12
-rw-r--r--lib/vquic/curl_osslq.c12
-rw-r--r--lib/vquic/curl_quiche.c12
-rw-r--r--lib/vquic/vquic.c3
-rw-r--r--lib/vtls/openssl.c4
-rw-r--r--lib/vtls/vtls.c26
-rw-r--r--lib/vtls/wolfssl.c12
-rw-r--r--src/tool_cb_hdr.c14
-rw-r--r--src/tool_cb_hdr.h1
-rw-r--r--src/tool_cb_wrt.c279
-rw-r--r--src/tool_operate.c1
-rw-r--r--src/tool_strdup.c12
-rw-r--r--src/tool_strdup.h1
-rw-r--r--src/tool_urlglob.c6
-rw-r--r--src/var.c16
-rw-r--r--tests/data/Makefile.am2
-rw-r--r--tests/data/test210449
-rw-r--r--tests/data/test6552
-rw-r--r--tests/libtest/lib3033.c2
-rw-r--r--tests/libtest/lib655.c5
-rwxr-xr-xtests/runtests.pl23
-rw-r--r--tests/server/dnsd.c27
-rw-r--r--tests/server/rtspd.c2
-rw-r--r--tests/server/sws.c8
50 files changed, 796 insertions, 500 deletions
diff --git a/.github/workflows/curl-for-win.yml b/.github/workflows/curl-for-win.yml
index 5b0d2e03c..c70ac13e9 100644
--- a/.github/workflows/curl-for-win.yml
+++ b/.github/workflows/curl-for-win.yml
@@ -45,7 +45,7 @@ env:
jobs:
linux-glibc-gcc:
- name: 'Linux gcc glibc'
+ name: 'Linux gcc glibc (amd64, arm64)'
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
@@ -74,7 +74,7 @@ jobs:
sh -c ./_ci-linux-debian.sh
linux-musl-llvm:
- name: 'Linux llvm MUSL'
+ name: 'Linux llvm MUSL (amd64, riscv64)'
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
@@ -101,7 +101,7 @@ jobs:
sh -c ./_ci-linux-debian.sh
mac-clang:
- name: 'macOS clang'
+ name: 'macOS clang (x86_64)'
runs-on: macos-latest
timeout-minutes: 10
env:
@@ -121,7 +121,7 @@ jobs:
sh -c ./_ci-mac-homebrew.sh
win-llvm:
- name: 'Windows llvm'
+ name: 'Windows llvm (x64)'
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
@@ -148,7 +148,7 @@ jobs:
sh -c ./_ci-linux-debian.sh
win-gcc-libssh-zlibold-x86:
- name: 'Windows gcc libssh zlib-classic x86'
+ name: 'Windows gcc libssh zlib-classic (x86)'
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
diff --git a/.github/workflows/distcheck.yml b/.github/workflows/distcheck.yml
index 42633ef04..3d5adc759 100644
--- a/.github/workflows/distcheck.yml
+++ b/.github/workflows/distcheck.yml
@@ -260,7 +260,7 @@ jobs:
strategy:
fail-fast: false
matrix:
- image: [ubuntu-latest, macos-latest, windows-latest]
+ image: [ubuntu-latest, macos-latest, windows-2022]
steps:
- uses: msys2/setup-msys2@40677d36a502eb2cf0fb808cc9dec31bf6152638 # v2
if: ${{ contains(matrix.image, 'windows') }}
diff --git a/.github/workflows/http3-linux.yml b/.github/workflows/http3-linux.yml
index a919ac90f..99e99332a 100644
--- a/.github/workflows/http3-linux.yml
+++ b/.github/workflows/http3-linux.yml
@@ -42,7 +42,7 @@ env:
MAKEFLAGS: -j 5
CURL_CI: github
# handled in renovate.json
- OPENSSL_VERSION: 3.5.1
+ OPENSSL_VERSION: 3.5.2
# handled in renovate.json
QUICTLS_VERSION: 3.3.0
# renovate: datasource=github-tags depName=gnutls/gnutls versioning=semver registryUrl=https://github.com
diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml
index be0468ff8..c0be95f43 100644
--- a/.github/workflows/linux.yml
+++ b/.github/workflows/linux.yml
@@ -52,7 +52,7 @@ env:
# renovate: datasource=github-tags depName=awslabs/aws-lc versioning=semver registryUrl=https://github.com
AWSLC_VERSION: 1.56.0
# handled in renovate.json
- OPENSSL_VERSION: 3.5.1
+ OPENSSL_VERSION: 3.5.2
# handled in renovate.json
QUICTLS_VERSION: 3.3.0
# renovate: datasource=github-tags depName=rustls/rustls-ffi versioning=semver registryUrl=https://github.com
diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml
index df918d54a..812bc9b79 100644
--- a/.github/workflows/windows.yml
+++ b/.github/workflows/windows.yml
@@ -43,7 +43,7 @@ env:
jobs:
cygwin:
name: "cygwin, ${{ matrix.build == 'cmake' && 'CM' || 'AM' }} ${{ matrix.platform }} ${{ matrix.name }}"
- runs-on: windows-latest
+ runs-on: windows-2022
timeout-minutes: 15
defaults:
run:
@@ -187,7 +187,7 @@ jobs:
msys2: # both msys and mingw-w64
name: "${{ matrix.sys == 'msys' && 'msys2' || 'mingw' }}, ${{ matrix.build == 'cmake' && 'CM' || 'AM' }} ${{ matrix.env }} ${{ matrix.name }} ${{ matrix.test }}"
- runs-on: ${{ matrix.image || 'windows-latest' }}
+ runs-on: ${{ matrix.image || 'windows-2022' }}
timeout-minutes: 15
defaults:
run:
@@ -414,7 +414,7 @@ jobs:
mingw-w64-standalone-downloads:
name: 'dl-mingw, CM ${{ matrix.ver }}-${{ matrix.env }} ${{ matrix.name }}'
- runs-on: windows-latest
+ runs-on: windows-2022
timeout-minutes: 15
defaults:
run:
@@ -697,7 +697,7 @@ jobs:
msvc:
name: 'msvc, CM ${{ matrix.arch }}-${{ matrix.plat }} ${{ matrix.name }}'
- runs-on: ${{ matrix.image || 'windows-latest' }}
+ runs-on: ${{ matrix.image || 'windows-2022' }}
timeout-minutes: 15
defaults:
run:
diff --git a/docs/TODO b/docs/TODO
index a350e1421..49674155d 100644
--- a/docs/TODO
+++ b/docs/TODO
@@ -24,7 +24,6 @@
1.5 get rid of PATH_MAX
1.6 thread-safe sharing
1.8 CURLOPT_RESOLVE for any port number
- 1.9 Cache negative name resolves
1.10 auto-detect proxy
1.11 minimize dependencies with dynamically loaded modules
1.12 updated DNS server while running
@@ -263,11 +262,6 @@
See https://github.com/curl/curl/issues/1264
-1.9 Cache negative name resolves
-
- A name resolve that has failed is likely to fail when made again within a
- short period of time. Currently we only cache positive responses.
-
1.10 auto-detect proxy
libcurl could be made to detect the system proxy setup automatically and use
diff --git a/docs/libcurl/curl_multi_get_offt.md b/docs/libcurl/curl_multi_get_offt.md
index cc7873df4..875fa7e33 100644
--- a/docs/libcurl/curl_multi_get_offt.md
+++ b/docs/libcurl/curl_multi_get_offt.md
@@ -28,8 +28,8 @@ CURLMcode curl_multi_get_offt(CURLM *multi_handle,
# DESCRIPTION
-Get the *info* kept in the *multi* handle for `CURLMI_OFFT_*`.
-If the *info* is not applicable, this function returns CURLM_UNKNOWN_OPTION.
+Get the *info* kept in the *multi* handle. If the *info* is not applicable,
+this function returns CURLM_UNKNOWN_OPTION.
# OPTIONS
@@ -37,38 +37,23 @@ The following information can be extracted:
## CURLMINFO_XFERS_CURRENT
-The number of easy handles currently added to the multi. This does not
-count handles removed. It does count internal handles that get
-added for tasks (like resolving via DoH, for example).
-
-For the total number of easy handles ever added to the multi, see
-*CURLMINFO_XFERS_ADDED*.
+See CURLMINFO_XFERS_CURRENT(3).
## CURLMINFO_XFERS_RUNNING
-The number of easy handles currently running, e.g. where the transfer
-has started but not finished yet.
+See CURLMINFO_XFERS_RUNNING(3).
## CURLMINFO_XFERS_PENDING
-The number of current easy handles waiting to start. An added transfer
-might become pending for various reasons: a connection limit forces it
-to wait, resolving DNS is not finished or it is not clear if an existing,
-matching connection may allow multiplexing (HTTP/2 or HTTP/3).
+See CURLMINFO_XFERS_PENDING(3).
## CURLMINFO_XFERS_DONE
-The number of easy handles currently finished, but not yet processed
-via curl_multi_info_read(3).
+See CURLMINFO_XFERS_DONE(3).
## CURLMINFO_XFERS_ADDED
-The cumulative number of all easy handles added to the multi, ever.
-This includes internal handles added for tasks (like resolving
-via DoH, for example).
-
-For the current number of easy handles managed by the multi, use
-*CURLMINFO_XFERS_CURRENT*.
+See CURLMINFO_XFERS_ADDED(3).
# %PROTOCOLS%
diff --git a/docs/libcurl/opts/CURLMINFO_XFERS_ADDED.md b/docs/libcurl/opts/CURLMINFO_XFERS_ADDED.md
new file mode 100644
index 000000000..c3869f649
--- /dev/null
+++ b/docs/libcurl/opts/CURLMINFO_XFERS_ADDED.md
@@ -0,0 +1,63 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLMINFO_XFERS_ADDED
+Section: 3
+Source: libcurl
+See-also:
+ - CURLMINFO_XFERS_CURRENT (3)
+ - CURLMINFO_XFERS_RUNNING (3)
+ - CURLMINFO_XFERS_DONE (3)
+Protocol:
+ - All
+Added-in: 8.16.0
+---
+
+# NAME
+
+CURLMINFO_XFERS_ADDED - Cumulative number of all easy handles added
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLMcode curl_multi_get_offt(CURLM *handle, CURLMINFO_XFERS_ADDED,
+ curl_off_t *pvalue);
+~~~
+
+# DESCRIPTION
+
+The cumulative number of all easy handles added to the multi, ever. This
+includes internal handles added for tasks (like resolving via DoH, for
+example).
+
+For the current number of easy handles managed by the multi, use
+CURLMINFO_XFERS_CURRENT(3).
+
+# DEFAULT
+
+n/a
+
+# %PROTOCOLS%
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURLM *m = curl_multi_init();
+ curl_off_t value;
+
+ curl_multi_get_offt(m, CURLMINFO_XFERS_ADDED, &value);
+}
+~~~
+
+# %AVAILABILITY%
+
+# RETURN VALUE
+
+curl_multi_get_offt(3) returns a CURLMcode indicating success or error.
+
+CURLM_OK (0) means everything was OK, non-zero means an error occurred, see
+libcurl-errors(3).
diff --git a/docs/libcurl/opts/CURLMINFO_XFERS_CURRENT.md b/docs/libcurl/opts/CURLMINFO_XFERS_CURRENT.md
new file mode 100644
index 000000000..2b29117e8
--- /dev/null
+++ b/docs/libcurl/opts/CURLMINFO_XFERS_CURRENT.md
@@ -0,0 +1,62 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLMINFO_XFERS_CURRENT
+Section: 3
+Source: libcurl
+See-also:
+ - CURLMINFO_XFERS_RUNNING (3)
+ - CURLMINFO_XFERS_PENDING (3)
+Protocol:
+ - All
+Added-in: 8.16.0
+---
+
+# NAME
+
+CURLMINFO_XFERS_CURRENT - Number of easy handles currently added
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLMcode curl_multi_get_offt(CURLM *handle, CURLMINFO_XFERS_CURRENT,
+ curl_off_t *pvalue);
+~~~
+
+# DESCRIPTION
+
+Returns the number of easy handles currently added to the multi handle. This
+does not include already removed handles. It does include internal handles
+that get added for tasks (like resolving via DoH, for example).
+
+For the total number of easy handles ever added to the multi, see
+CURLMINFO_XFERS_ADDED(3).
+
+# DEFAULT
+
+n/a
+
+# %PROTOCOLS%
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURLM *m = curl_multi_init();
+ curl_off_t value;
+
+ curl_multi_get_offt(m, CURLMINFO_XFERS_CURRENT, &value);
+}
+~~~
+
+# %AVAILABILITY%
+
+# RETURN VALUE
+
+curl_multi_get_offt(3) returns a CURLMcode indicating success or error.
+
+CURLM_OK (0) means everything was OK, non-zero means an error occurred, see
+libcurl-errors(3).
diff --git a/docs/libcurl/opts/CURLMINFO_XFERS_DONE.md b/docs/libcurl/opts/CURLMINFO_XFERS_DONE.md
new file mode 100644
index 000000000..6097d5f30
--- /dev/null
+++ b/docs/libcurl/opts/CURLMINFO_XFERS_DONE.md
@@ -0,0 +1,58 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLMINFO_XFERS_DONE
+Section: 3
+Source: libcurl
+See-also:
+ - CURLMINFO_XFERS_CURRENT (3)
+ - CURLMINFO_XFERS_RUNNING (3)
+Protocol:
+ - All
+Added-in: 8.16.0
+---
+
+# NAME
+
+CURLMINFO_XFERS_DONE - Number of finished unprocessed easy handles
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLMcode curl_multi_get_offt(CURLM *handle, CURLMINFO_XFERS_DONE,
+ curl_off_t *pvalue);
+~~~
+
+# DESCRIPTION
+
+The number of easy handles currently finished, but not yet processed via
+curl_multi_info_read(3).
+
+# DEFAULT
+
+n/a
+
+# %PROTOCOLS%
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURLM *m = curl_multi_init();
+ curl_off_t value;
+
+ curl_multi_get_offt(m, CURLMINFO_XFERS_DONE, &value);
+}
+~~~
+
+# %AVAILABILITY%
+
+# RETURN VALUE
+
+curl_multi_get_offt(3) returns a CURLMcode indicating success or error.
+
+CURLM_OK (0) means everything was OK, non-zero means an error occurred, see
+libcurl-errors(3).
diff --git a/docs/libcurl/opts/CURLMINFO_XFERS_PENDING.md b/docs/libcurl/opts/CURLMINFO_XFERS_PENDING.md
new file mode 100644
index 000000000..acdc1f1c7
--- /dev/null
+++ b/docs/libcurl/opts/CURLMINFO_XFERS_PENDING.md
@@ -0,0 +1,60 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLMINFO_XFERS_PENDING
+Section: 3
+Source: libcurl
+See-also:
+ - CURLMINFO_XFERS_CURRENT (3)
+ - CURLMINFO_XFERS_RUNNING (3)
+Protocol:
+ - All
+Added-in: 8.16.0
+---
+
+# NAME
+
+CURLMINFO_XFERS_PENDING - Number of easy handles waiting to start
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLMcode curl_multi_get_offt(CURLM *handle, CURLMINFO_XFERS_PENDING,
+ curl_off_t *pvalue);
+~~~
+
+# DESCRIPTION
+
+The number of current easy handles waiting to start. An added transfer might
+become pending for various reasons: a connection limit forces it to wait,
+resolving DNS is not finished or it is not clear if an existing, matching
+connection may allow multiplexing (HTTP/2 or HTTP/3).
+
+# DEFAULT
+
+n/a
+
+# %PROTOCOLS%
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURLM *m = curl_multi_init();
+ curl_off_t value;
+
+ curl_multi_get_offt(m, CURLMINFO_XFERS_PENDING, &value);
+}
+~~~
+
+# %AVAILABILITY%
+
+# RETURN VALUE
+
+curl_multi_get_offt(3) returns a CURLMcode indicating success or error.
+
+CURLM_OK (0) means everything was OK, non-zero means an error occurred, see
+libcurl-errors(3).
diff --git a/docs/libcurl/opts/CURLMINFO_XFERS_RUNNING.md b/docs/libcurl/opts/CURLMINFO_XFERS_RUNNING.md
new file mode 100644
index 000000000..eeedb7518
--- /dev/null
+++ b/docs/libcurl/opts/CURLMINFO_XFERS_RUNNING.md
@@ -0,0 +1,58 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLMINFO_XFERS_RUNNING
+Section: 3
+Source: libcurl
+See-also:
+ - CURLMINFO_XFERS_CURRENT (3)
+ - CURLMINFO_XFERS_PENDING (3)
+Protocol:
+ - All
+Added-in: 8.16.0
+---
+
+# NAME
+
+CURLMINFO_XFERS_RUNNING - Number of easy handles currently running
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLMcode curl_multi_get_offt(CURLM *handle, CURLMINFO_XFERS_RUNNING,
+ curl_off_t *pvalue);
+~~~
+
+# DESCRIPTION
+
+The number of easy handles currently running, e.g. where the transfer has
+started but not finished yet.
+
+# DEFAULT
+
+n/a
+
+# %PROTOCOLS%
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURLM *m = curl_multi_init();
+ curl_off_t value;
+
+ curl_multi_get_offt(m, CURLMINFO_XFERS_RUNNING, &value);
+}
+~~~
+
+# %AVAILABILITY%
+
+# RETURN VALUE
+
+curl_multi_get_offt(3) returns a CURLMcode indicating success or error.
+
+CURLM_OK (0) means everything was OK, non-zero means an error occurred, see
+libcurl-errors(3).
diff --git a/docs/libcurl/opts/CURLMOPT_NETWORK_CHANGED.md b/docs/libcurl/opts/CURLMOPT_NETWORK_CHANGED.md
index bcfd1cdd3..a38a9a83b 100644
--- a/docs/libcurl/opts/CURLMOPT_NETWORK_CHANGED.md
+++ b/docs/libcurl/opts/CURLMOPT_NETWORK_CHANGED.md
@@ -42,13 +42,13 @@ to clear the caches.
The call affects only the connection and DNS cache of the multi handle
itself and not the ones owned by SHARE handles.
-## CURLM_NWCOPT_CLEAR_CONNS
+## CURLMNWC_CLEAR_CONNS
No longer reuse any existing connection in the multi handle's
connection cache. This closes all connections that are not in use.
Ongoing transfers continue on the connections they operate on.
-## CURLM_NWCOPT_CLEAR_DNS
+## CURLMNWC_CLEAR_DNS
Clear the multi handle's DNS cache.
@@ -66,7 +66,7 @@ int main(void)
CURLM *m = curl_multi_init();
/* do transfers on the multi handle */
/* do not reuse existing connections */
- curl_multi_setopt(m, CURLMOPT_NETWORK_CHANGED, CURLM_NWCOPT_CLEAR_CONNS);
+ curl_multi_setopt(m, CURLMOPT_NETWORK_CHANGED, CURLMNWC_CLEAR_CONNS);
}
~~~
diff --git a/docs/libcurl/opts/CURLOPT_DNS_CACHE_TIMEOUT.md b/docs/libcurl/opts/CURLOPT_DNS_CACHE_TIMEOUT.md
index 9cc9b03f3..4c40980cd 100644
--- a/docs/libcurl/opts/CURLOPT_DNS_CACHE_TIMEOUT.md
+++ b/docs/libcurl/opts/CURLOPT_DNS_CACHE_TIMEOUT.md
@@ -10,6 +10,7 @@ See-also:
- CURLOPT_DNS_USE_GLOBAL_CACHE (3)
- CURLOPT_MAXAGE_CONN (3)
- CURLOPT_RESOLVE (3)
+ - CURLMOPT_NETWORK_CHANGED (3)
Protocol:
- All
Added-in: 7.9.3
@@ -48,8 +49,11 @@ DNS entries have a "TTL" property but libcurl does not use that. This DNS
cache timeout is entirely speculative that a name resolves to the same address
for a small amount of time into the future.
-Since version 8.1.0, libcurl prunes entries from the DNS cache if it exceeds
-30,000 entries no matter which timeout value is used.
+libcurl prunes entries from the DNS cache if it exceeds 30,000 entries no
+matter which timeout value is used. (Added in version 8.1.0)
+
+Since curl 8.16.0, failed name resolves are stored in the DNS cache for half
+the set timeout period.
# DEFAULT
diff --git a/docs/libcurl/opts/Makefile.inc b/docs/libcurl/opts/Makefile.inc
index 1cf960e5e..98691cac3 100644
--- a/docs/libcurl/opts/Makefile.inc
+++ b/docs/libcurl/opts/Makefile.inc
@@ -101,6 +101,11 @@ man_MANS = \
CURLINFO_TOTAL_TIME_T.3 \
CURLINFO_USED_PROXY.3 \
CURLINFO_XFER_ID.3 \
+ CURLMINFO_XFERS_ADDED.3 \
+ CURLMINFO_XFERS_CURRENT.3 \
+ CURLMINFO_XFERS_DONE.3 \
+ CURLMINFO_XFERS_PENDING.3 \
+ CURLMINFO_XFERS_RUNNING.3 \
CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE.3 \
CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE.3 \
CURLMOPT_MAX_CONCURRENT_STREAMS.3 \
diff --git a/docs/libcurl/symbols-in-versions b/docs/libcurl/symbols-in-versions
index d2a4cc598..bfcf357bf 100644
--- a/docs/libcurl/symbols-in-versions
+++ b/docs/libcurl/symbols-in-versions
@@ -545,21 +545,21 @@ CURLM_BAD_SOCKET 7.15.4
CURLM_CALL_MULTI_PERFORM 7.9.6
CURLM_CALL_MULTI_SOCKET 7.15.5
CURLM_INTERNAL_ERROR 7.9.6
-CURLM_NWCOPT_CLEAR_CONNS 8.16.0
-CURLM_NWCOPT_CLEAR_DNS 8.16.0
CURLM_OK 7.9.6
CURLM_OUT_OF_MEMORY 7.9.6
CURLM_RECURSIVE_API_CALL 7.59.0
CURLM_UNKNOWN_OPTION 7.15.4
CURLM_UNRECOVERABLE_POLL 7.84.0
CURLM_WAKEUP_FAILURE 7.68.0
+CURLMIMEOPT_FORMESCAPE 7.81.0
CURLMINFO_NONE 8.16.0
+CURLMINFO_XFERS_ADDED 8.16.0
CURLMINFO_XFERS_CURRENT 8.16.0
-CURLMINFO_XFERS_RUNNING 8.16.0
-CURLMINFO_XFERS_PENDING 8.16.0
CURLMINFO_XFERS_DONE 8.16.0
-CURLMINFO_XFERS_ADDED 8.16.0
-CURLMIMEOPT_FORMESCAPE 7.81.0
+CURLMINFO_XFERS_PENDING 8.16.0
+CURLMINFO_XFERS_RUNNING 8.16.0
+CURLMNWC_CLEAR_CONNS 8.16.0
+CURLMNWC_CLEAR_DNS 8.16.0
CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE 7.30.0
CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE 7.30.0
CURLMOPT_MAX_CONCURRENT_STREAMS 7.67.0
diff --git a/docs/tests/FILEFORMAT.md b/docs/tests/FILEFORMAT.md
index 992717b19..a58eb1320 100644
--- a/docs/tests/FILEFORMAT.md
+++ b/docs/tests/FILEFORMAT.md
@@ -747,3 +747,13 @@ should be cut off from the upload data before comparing it.
### `<valgrind>`
disable - disables the valgrind log check for this test
+
+### `<dns [host="name"]>`
+
+This specify the input the DNS server is expected to get from curl. Because of
+differences in implementations, this section is sorted automatically before
+compared.
+
+Because of local configurations in machines running tests, there may be
+additional requests sent to `[host].[custom suffix]`. To prevent such requests
+to mess up comparisons, we can set the hostname to check in the `<dns>` tag.
diff --git a/include/curl/multi.h b/include/curl/multi.h
index e336c94a8..782541f1a 100644
--- a/include/curl/multi.h
+++ b/include/curl/multi.h
@@ -403,15 +403,15 @@ typedef enum {
/* Definition of bits for the CURLMOPT_NETWORK_CHANGED argument: */
-/* - CURLM_NWCOPT_CLEAR_CONNS tells libcurl to prevent further reuse
- of existing connections. Connections that are idle will be closed.
- Ongoing transfers will continue with the connection they have. */
-#define CURLM_NWCOPT_CLEAR_CONNS (1L<<0)
-
-/* - CURLM_NWCOPT_CLEAR_DNS tells libcurl to prevent further reuse
- of existing connections. Connections that are idle will be closed.
- Ongoing transfers will continue with the connection they have. */
-#define CURLM_NWCOPT_CLEAR_DNS (1L<<0)
+/* - CURLMNWC_CLEAR_CONNS tells libcurl to prevent further reuse of existing
+ connections. Connections that are idle will be closed. Ongoing transfers
+ will continue with the connection they have. */
+#define CURLMNWC_CLEAR_CONNS (1L<<0)
+
+/* - CURLMNWC_CLEAR_DNS tells libcurl to prevent further reuse of existing
+ connections. Connections that are idle will be closed. Ongoing transfers
+ will continue with the connection they have. */
+#define CURLMNWC_CLEAR_DNS (1L<<0)
/*
* Name: curl_multi_setopt()
diff --git a/lib/asyn-thrdd.c b/lib/asyn-thrdd.c
index 6a56f92c4..82ce2b046 100644
--- a/lib/asyn-thrdd.c
+++ b/lib/asyn-thrdd.c
@@ -368,6 +368,14 @@ static CURLcode async_rr_start(struct Curl_easy *data)
thrdd->rr.channel = NULL;
return CURLE_FAILED_INIT;
}
+#ifdef CURLDEBUG
+ if(getenv("CURL_DNS_SERVER")) {
+ const char *servers = getenv("CURL_DNS_SERVER");
+ status = ares_set_servers_ports_csv(thrdd->rr.channel, servers);
+ if(status)
+ return CURLE_FAILED_INIT;
+ }
+#endif
memset(&thrdd->rr.hinfo, 0, sizeof(thrdd->rr.hinfo));
thrdd->rr.hinfo.port = -1;
@@ -375,6 +383,7 @@ static CURLcode async_rr_start(struct Curl_easy *data)
data->conn->host.name, ARES_CLASS_IN,
ARES_REC_TYPE_HTTPS,
async_thrdd_rr_done, data, NULL);
+ CURL_TRC_DNS(data, "Issued HTTPS-RR request for %s", data->conn->host.name);
return CURLE_OK;
}
#endif
diff --git a/lib/cf-socket.c b/lib/cf-socket.c
index 7f3f8e60f..426caf82d 100644
--- a/lib/cf-socket.c
+++ b/lib/cf-socket.c
@@ -109,7 +109,7 @@ static void set_ipv6_v6only(curl_socket_t sockfd, int on)
static void tcpnodelay(struct Curl_easy *data, curl_socket_t sockfd)
{
-#ifdef TCP_NODELAY
+#if defined(TCP_NODELAY) && defined(CURL_TCP_NODELAY_SUPPORTED)
curl_socklen_t onoff = (curl_socklen_t) 1;
int level = IPPROTO_TCP;
char buffer[STRERROR_LEN];
diff --git a/lib/curl_setup.h b/lib/curl_setup.h
index 9b663fcb7..0a6591db8 100644
--- a/lib/curl_setup.h
+++ b/lib/curl_setup.h
@@ -1125,6 +1125,11 @@ int getpwuid_r(uid_t uid, struct passwd *pwd, char *buf,
#define USE_HTTP3
#endif
+/* WebAssembly builds have TCP_NODELAY, but runtime support is missing. */
+#ifndef __EMSCRIPTEN__
+#define CURL_TCP_NODELAY_SUPPORTED
+#endif
+
/* 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. */
diff --git a/lib/hostip.c b/lib/hostip.c
index 06fa3bc47..6ad961ff8 100644
--- a/lib/hostip.c
+++ b/lib/hostip.c
@@ -202,6 +202,8 @@ dnscache_entry_is_stale(void *datap, void *hc)
if(dns->timestamp.tv_sec || dns->timestamp.tv_usec) {
/* get age in milliseconds */
timediff_t age = curlx_timediff(prune->now, dns->timestamp);
+ if(!dns->addr)
+ age *= 2; /* negative entries age twice as fast */
if(age >= prune->max_age_ms)
return TRUE;
if(age > prune->oldest_ms)
@@ -215,7 +217,7 @@ dnscache_entry_is_stale(void *datap, void *hc)
* Returns the 'age' of the oldest still kept entry - in milliseconds.
*/
static timediff_t
-dnscache_prune(struct Curl_hash *hostcache, int cache_timeout_ms,
+dnscache_prune(struct Curl_hash *hostcache, timediff_t cache_timeout_ms,
struct curltime now)
{
struct dnscache_prune_data user;
@@ -263,7 +265,7 @@ void Curl_dnscache_prune(struct Curl_easy *data)
struct Curl_dnscache *dnscache = dnscache_get(data);
struct curltime now;
/* the timeout may be set -1 (forever) */
- int timeout_ms = data->set.dns_cache_timeout_ms;
+ timediff_t timeout_ms = data->set.dns_cache_timeout_ms;
if(!dnscache || (timeout_ms == -1))
/* NULL hostcache means we cannot do it */
@@ -798,6 +800,28 @@ static bool can_resolve_ip_version(struct Curl_easy *data, int ip_version)
return TRUE;
}
+static CURLcode store_negative_resolve(struct Curl_easy *data,
+ const char *host,
+ int port)
+{
+ struct Curl_dnscache *dnscache = dnscache_get(data);
+ struct Curl_dns_entry *dns;
+ DEBUGASSERT(dnscache);
+ if(!dnscache)
+ return CURLE_FAILED_INIT;
+
+ /* put this new host in the cache */
+ dns = dnscache_add_addr(data, dnscache, NULL, host, 0, port, FALSE);
+ if(dns) {
+ /* release the returned reference; the cache itself will keep the
+ * entry alive: */
+ dns->refcount--;
+ infof(data, "Store negative name resolve for %s:%d", host, port);
+ return CURLE_OK;
+ }
+ return CURLE_OUT_OF_MEMORY;
+}
+
/*
* Curl_resolv() is the main name resolve function within libcurl. It resolves
* a name and returns a pointer to the entry in the 'entry' argument (if one
@@ -917,6 +941,11 @@ out:
* or `respwait` is set for an async operation.
* Everything else is a failure to resolve. */
if(dns) {
+ if(!dns->addr) {
+ infof(data, "Negative DNS entry");
+ dns->refcount--;
+ return CURLE_COULDNT_RESOLVE_HOST;
+ }
*entry = dns;
return CURLE_OK;
}
@@ -942,6 +971,7 @@ error:
Curl_resolv_unlink(data, &dns);
*entry = NULL;
Curl_async_shutdown(data);
+ store_negative_resolve(data, hostname, port);
return CURLE_COULDNT_RESOLVE_HOST;
}
@@ -1523,6 +1553,9 @@ CURLcode Curl_resolv_check(struct Curl_easy *data,
result = Curl_async_is_resolved(data, dns);
if(*dns)
show_resolve_info(data, *dns);
+ if(result)
+ store_negative_resolve(data, data->state.async.hostname,
+ data->state.async.port);
return result;
}
#endif
diff --git a/lib/http.c b/lib/http.c
index 08daab6dc..8eb137885 100644
--- a/lib/http.c
+++ b/lib/http.c
@@ -1323,7 +1323,7 @@ CURLcode Curl_http_follow(struct Curl_easy *data, const char *newurl,
data->info.wouldredirect = follow_url;
if(reachedmax) {
- failf(data, "Maximum (%ld) redirects followed", data->set.maxredirs);
+ failf(data, "Maximum (%d) redirects followed", data->set.maxredirs);
return CURLE_TOO_MANY_REDIRECTS;
}
return CURLE_OK;
@@ -2704,6 +2704,8 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
if(result)
goto fail;
info_version = "HTTP/2";
+ /* There is no ALPN here, but the connection is now definitely h2 */
+ conn->httpversion_seen = 20;
}
else
info_version = "HTTP/1.x";
@@ -4785,7 +4787,7 @@ static CURLcode cr_exp100_read(struct Curl_easy *data,
/* We are now waiting for a reply from the server or
* a timeout on our side IFF the request has been fully sent. */
DEBUGF(infof(data, "cr_exp100_read, start AWAITING_CONTINUE, "
- "timeout %ldms", data->set.expect_100_timeout));
+ "timeout %dms", data->set.expect_100_timeout));
ctx->state = EXP100_AWAITING_CONTINUE;
ctx->start = curlx_now();
Curl_expire(data, data->set.expect_100_timeout, EXPIRE_100_TIMEOUT);
diff --git a/lib/multi.c b/lib/multi.c
index 9a653cf95..370cb97d5 100644
--- a/lib/multi.c
+++ b/lib/multi.c
@@ -3244,13 +3244,13 @@ CURLMcode curl_multi_setopt(CURLM *m,
}
break;
case CURLMOPT_NETWORK_CHANGED: {
- long val = va_arg(param, long);
- if(val & CURLM_NWCOPT_CLEAR_DNS) {
- Curl_dnscache_clear(multi->admin);
- }
- if(val & CURLM_NWCOPT_CLEAR_CONNS) {
- Curl_cpool_nw_changed(multi->admin);
- }
+ long val = va_arg(param, long);
+ if(val & CURLMNWC_CLEAR_DNS) {
+ Curl_dnscache_clear(multi->admin);
+ }
+ if(val & CURLMNWC_CLEAR_CONNS) {
+ Curl_cpool_nw_changed(multi->admin);
+ }
break;
}
default:
diff --git a/lib/setopt.c b/lib/setopt.c
index 394b5567e..168417738 100644
--- a/lib/setopt.c
+++ b/lib/setopt.c
@@ -60,7 +60,6 @@
#include "curl_memory.h"
#include "memdebug.h"
-
static CURLcode setopt_set_timeout_sec(timediff_t *ptimeout_ms, long secs)
{
if(secs < 0)
@@ -854,6 +853,17 @@ static CURLcode setopt_bool(struct Curl_easy *data, CURLoption option,
return CURLE_OK;
}
+static CURLcode value_range(long *value, long below_error, long min, long max)
+{
+ if(*value < below_error)
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ else if(*value < min)
+ *value = min;
+ else if(*value > max)
+ *value = max;
+ return CURLE_OK;
+}
+
static CURLcode setopt_long(struct Curl_easy *data, CURLoption option,
long arg)
{
@@ -866,21 +876,13 @@ static CURLcode setopt_long(struct Curl_easy *data, CURLoption option,
switch(option) {
case CURLOPT_DNS_CACHE_TIMEOUT:
- if(arg < -1)
- return CURLE_BAD_FUNCTION_ARGUMENT;
- else if(arg > INT_MAX/1000)
- arg = INT_MAX/1000;
+ return setopt_set_timeout_sec(&s->dns_cache_timeout_ms, arg);
- if(arg > 0)
- arg *= 1000;
- s->dns_cache_timeout_ms = (int)arg;
- break;
case CURLOPT_CA_CACHE_TIMEOUT:
if(Curl_ssl_supports(data, SSLSUPP_CA_CACHE)) {
- if(arg < -1)
- return CURLE_BAD_FUNCTION_ARGUMENT;
- else if(arg > INT_MAX)
- arg = INT_MAX;
+ result = value_range(&arg, -1, -1, INT_MAX);
+ if(result)
+ return result;
s->general_ssl.ca_cache_timeout = (int)arg;
}
@@ -888,64 +890,38 @@ static CURLcode setopt_long(struct Curl_easy *data, CURLoption option,
return CURLE_NOT_BUILT_IN;
break;
case CURLOPT_MAXCONNECTS:
- /*
- * Set the absolute number of maximum simultaneous alive connection that
- * libcurl is allowed to have.
- */
- if(uarg > UINT_MAX)
- return CURLE_BAD_FUNCTION_ARGUMENT;
- s->maxconnects = (unsigned int)uarg;
+ result = value_range(&arg, 1, 1, UINT_MAX);
+ if(result)
+ return result;
+ s->maxconnects = (unsigned int)arg;
break;
case CURLOPT_SERVER_RESPONSE_TIMEOUT:
- /*
- * Option that specifies how quickly a server response must be obtained
- * before it is considered failure. For pingpong protocols.
- */
return setopt_set_timeout_sec(&s->server_response_timeout, arg);
case CURLOPT_SERVER_RESPONSE_TIMEOUT_MS:
- /*
- * Option that specifies how quickly a server response must be obtained
- * before it is considered failure. For pingpong protocols.
- */
return setopt_set_timeout_ms(&s->server_response_timeout, arg);
#ifndef CURL_DISABLE_TFTP
case CURLOPT_TFTP_BLKSIZE:
- /*
- * TFTP option that specifies the block size to use for data transmission.
- */
- if(arg < TFTP_BLKSIZE_MIN)
- arg = 512;
- else if(arg > TFTP_BLKSIZE_MAX)
- arg = TFTP_BLKSIZE_MAX;
- s->tftp_blksize = arg;
+ result = value_range(&arg, 0, TFTP_BLKSIZE_MIN, TFTP_BLKSIZE_MAX);
+ if(result)
+ return result;
+ s->tftp_blksize = (unsigned short)arg;
break;
#endif
#ifndef CURL_DISABLE_NETRC
case CURLOPT_NETRC:
- /*
- * Parse the $HOME/.netrc file
- */
if((arg < CURL_NETRC_IGNORED) || (arg >= CURL_NETRC_LAST))
return CURLE_BAD_FUNCTION_ARGUMENT;
s->use_netrc = (unsigned char)arg;
break;
#endif
case CURLOPT_TIMECONDITION:
- /*
- * Set HTTP time condition. This must be one of the defines in the
- * curl/curl.h header file.
- */
if((arg < CURL_TIMECOND_NONE) || (arg >= CURL_TIMECOND_LAST))
return CURLE_BAD_FUNCTION_ARGUMENT;
s->timecondition = (unsigned char)arg;
break;
case CURLOPT_TIMEVALUE:
- /*
- * This is the value to compare with the remote document with the
- * method set with CURLOPT_TIMECONDITION
- */
s->timevalue = (time_t)arg;
break;
case CURLOPT_SSLVERSION:
@@ -955,10 +931,6 @@ static CURLcode setopt_long(struct Curl_easy *data, CURLoption option,
return Curl_setopt_SSLVERSION(data, option, arg);
case CURLOPT_POSTFIELDSIZE:
- /*
- * The size of the POSTFIELD data to prevent libcurl to do strlen() to
- * figure it out. Enables binary posts.
- */
if(arg < -1)
return CURLE_BAD_FUNCTION_ARGUMENT;
@@ -973,34 +945,19 @@ static CURLcode setopt_long(struct Curl_easy *data, CURLoption option,
break;
#ifndef CURL_DISABLE_HTTP
case CURLOPT_FOLLOWLOCATION:
- /*
- * Follow Location: header hints on an HTTP-server.
- */
if(uarg > 3)
return CURLE_BAD_FUNCTION_ARGUMENT;
s->http_follow_mode = (unsigned char)uarg;
break;
case CURLOPT_MAXREDIRS:
- /*
- * The maximum amount of hops you allow curl to follow Location:
- * headers. This should mostly be used to detect never-ending loops.
- */
- if(arg < -1)
- return CURLE_BAD_FUNCTION_ARGUMENT;
- s->maxredirs = arg;
+ result = value_range(&arg, -1, 0, 0x7fff);
+ if(result)
+ return result;
+ s->maxredirs = (short)arg;
break;
case CURLOPT_POSTREDIR:
- /*
- * Set the behavior of POST when redirecting
- * CURL_REDIR_GET_ALL - POST is changed to GET after 301 and 302
- * CURL_REDIR_POST_301 - POST is kept as POST after 301
- * CURL_REDIR_POST_302 - POST is kept as POST after 302
- * CURL_REDIR_POST_303 - POST is kept as POST after 303
- * CURL_REDIR_POST_ALL - POST is kept as POST after 301, 302 and 303
- * other - POST is kept as POST after 301 and 302
- */
if(arg < CURL_REDIR_GET_ALL)
/* no return error on too high numbers since the bitmask could be
extended in a future */
@@ -1009,9 +966,6 @@ static CURLcode setopt_long(struct Curl_easy *data, CURLoption option,
break;
case CURLOPT_HEADEROPT:
- /*
- * Set header option.
- */
s->sep_headers = !!(arg & CURLHEADER_SEPARATE);
break;
case CURLOPT_HTTPAUTH:
@@ -1021,13 +975,10 @@ static CURLcode setopt_long(struct Curl_easy *data, CURLoption option,
return setopt_HTTP_VERSION(data, arg);
case CURLOPT_EXPECT_100_TIMEOUT_MS:
- /*
- * Time to wait for a response to an HTTP request containing an
- * Expect: 100-continue header before sending the data anyway.
- */
- if(arg < 0)
- return CURLE_BAD_FUNCTION_ARGUMENT;
- s->expect_100_timeout = arg;
+ result = value_range(&arg, 0, 0, 0xffff);
+ if(result)
+ return result;
+ s->expect_100_timeout = (unsigned short)arg;
break;
#endif /* ! CURL_DISABLE_HTTP */
@@ -1039,9 +990,6 @@ static CURLcode setopt_long(struct Curl_easy *data, CURLoption option,
#endif
#ifndef CURL_DISABLE_PROXY
case CURLOPT_PROXYPORT:
- /*
- * Explicitly set HTTP proxy port number.
- */
if((arg < 0) || (arg > 65535))
return CURLE_BAD_FUNCTION_ARGUMENT;
s->proxyport = (unsigned short)arg;
@@ -1051,9 +999,6 @@ static CURLcode setopt_long(struct Curl_easy *data, CURLoption option,
return httpauth(data, TRUE, uarg);
case CURLOPT_PROXYTYPE:
- /*
- * Set proxy type.
- */
if((arg < CURLPROXY_HTTP) || (arg > CURLPROXY_SOCKS5_HOSTNAME))
return CURLE_BAD_FUNCTION_ARGUMENT;
s->proxytype = (unsigned char)arg;
@@ -1068,9 +1013,6 @@ static CURLcode setopt_long(struct Curl_easy *data, CURLoption option,
#ifndef CURL_DISABLE_FTP
case CURLOPT_FTP_FILEMETHOD:
- /*
- * How do access files over FTP.
- */
if((arg < CURLFTPMETHOD_DEFAULT) || (arg >= CURLFTPMETHOD_LAST))
return CURLE_BAD_FUNCTION_ARGUMENT;
s->ftp_filemethod = (unsigned char)arg;
@@ -1082,89 +1024,53 @@ static CURLcode setopt_long(struct Curl_easy *data, CURLoption option,
break;
case CURLOPT_FTPSSLAUTH:
- /*
- * Set a specific auth for FTP-SSL transfers.
- */
if((arg < CURLFTPAUTH_DEFAULT) || (arg >= CURLFTPAUTH_LAST))
return CURLE_BAD_FUNCTION_ARGUMENT;
s->ftpsslauth = (unsigned char)arg;
break;
case CURLOPT_ACCEPTTIMEOUT_MS:
- /*
- * The maximum time for curl to wait for FTP server connect
- */
return setopt_set_timeout_ms(&s->accepttimeout, arg);
#endif /* ! CURL_DISABLE_FTP */
#if !defined(CURL_DISABLE_FTP) || defined(USE_SSH)
case CURLOPT_FTP_CREATE_MISSING_DIRS:
- /*
- * An FTP/SFTP option that modifies an upload to create missing
- * directories on the server.
- */
- /* reserve other values for future use */
if((arg < CURLFTP_CREATE_DIR_NONE) || (arg > CURLFTP_CREATE_DIR_RETRY))
return CURLE_BAD_FUNCTION_ARGUMENT;
s->ftp_create_missing_dirs = (unsigned char)arg;
break;
#endif /* ! CURL_DISABLE_FTP || USE_SSH */
case CURLOPT_INFILESIZE:
- /*
- * If known, this should inform curl about the file size of the
- * to-be-uploaded file.
- */
if(arg < -1)
return CURLE_BAD_FUNCTION_ARGUMENT;
s->filesize = arg;
break;
case CURLOPT_LOW_SPEED_LIMIT:
- /*
- * The low speed limit that if transfers are below this for
- * CURLOPT_LOW_SPEED_TIME, the transfer is aborted.
- */
if(arg < 0)
return CURLE_BAD_FUNCTION_ARGUMENT;
s->low_speed_limit = arg;
break;
case CURLOPT_LOW_SPEED_TIME:
- /*
- * The low speed time that if transfers are below the set
- * CURLOPT_LOW_SPEED_LIMIT during this time, the transfer is aborted.
- */
if(arg < 0)
return CURLE_BAD_FUNCTION_ARGUMENT;
s->low_speed_time = arg;
break;
case CURLOPT_PORT:
- /*
- * The port number to use when getting the URL. 0 disables it.
- */
if((arg < 0) || (arg > 65535))
return CURLE_BAD_FUNCTION_ARGUMENT;
s->use_port = (unsigned short)arg;
break;
case CURLOPT_TIMEOUT:
- /*
- * The maximum time you allow curl to use for a single transfer
- * operation.
- */
return setopt_set_timeout_sec(&s->timeout, arg);
case CURLOPT_TIMEOUT_MS:
return setopt_set_timeout_ms(&s->timeout, arg);
case CURLOPT_CONNECTTIMEOUT:
- /*
- * The maximum time you allow curl to use to connect.
- */
return setopt_set_timeout_sec(&s->connecttimeout, arg);
case CURLOPT_CONNECTTIMEOUT_MS:
return setopt_set_timeout_ms(&s->connecttimeout, arg);
case CURLOPT_RESUME_FROM:
- /*
- * Resume transfer at the given file position
- */
if(arg < -1)
return CURLE_BAD_FUNCTION_ARGUMENT;
s->set_resume_from = arg;
@@ -1172,17 +1078,11 @@ static CURLcode setopt_long(struct Curl_easy *data, CURLoption option,
#ifndef CURL_DISABLE_BINDLOCAL
case CURLOPT_LOCALPORT:
- /*
- * Set what local port to bind the socket to when performing an operation.
- */
if((arg < 0) || (arg > 65535))
return CURLE_BAD_FUNCTION_ARGUMENT;
s->localport = curlx_sltous(arg);
break;
case CURLOPT_LOCALPORTRANGE:
- /*
- * Set number of local ports to try, starting with CURLOPT_LOCALPORT.
- */
if((arg < 0) || (arg > 65535))
return CURLE_BAD_FUNCTION_ARGUMENT;
s->localportrange = curlx_sltous(arg);
@@ -1191,51 +1091,28 @@ static CURLcode setopt_long(struct Curl_easy *data, CURLoption option,
#ifdef HAVE_GSSAPI
case CURLOPT_GSSAPI_DELEGATION:
- /*
- * GSS-API credential delegation bitmask
- */
s->gssapi_delegation = (unsigned char)uarg&
(CURLGSSAPI_DELEGATION_POLICY_FLAG|CURLGSSAPI_DELEGATION_FLAG);
break;
#endif
case CURLOPT_SSL_FALSESTART:
- /*
- * No TLS backends support false start anymore.
- */
return CURLE_NOT_BUILT_IN;
case CURLOPT_BUFFERSIZE:
- /*
- * The application kindly asks for a differently sized receive buffer.
- * If it seems reasonable, we will use it.
- */
- if(arg > READBUFFER_MAX)
- arg = READBUFFER_MAX;
- else if(arg < 1)
- arg = READBUFFER_SIZE;
- else if(arg < READBUFFER_MIN)
- arg = READBUFFER_MIN;
-
+ result = value_range(&arg, 0, READBUFFER_MIN, READBUFFER_MAX);
+ if(result)
+ return result;
s->buffer_size = (unsigned int)arg;
break;
case CURLOPT_UPLOAD_BUFFERSIZE:
- /*
- * The application kindly asks for a differently sized upload buffer.
- * Cap it to sensible.
- */
- if(arg > UPLOADBUFFER_MAX)
- arg = UPLOADBUFFER_MAX;
- else if(arg < UPLOADBUFFER_MIN)
- arg = UPLOADBUFFER_MIN;
-
+ result = value_range(&arg, 0, UPLOADBUFFER_MIN, UPLOADBUFFER_MAX);
+ if(result)
+ return result;
s->upload_buffer_size = (unsigned int)arg;
break;
case CURLOPT_MAXFILESIZE:
- /*
- * Set the maximum size of a file to download.
- */
if(arg < 0)
return CURLE_BAD_FUNCTION_ARGUMENT;
s->max_filesize = arg;
@@ -1243,9 +1120,6 @@ static CURLcode setopt_long(struct Curl_easy *data, CURLoption option,
#ifdef USE_SSL
case CURLOPT_USE_SSL:
- /*
- * Make transfers attempt to use SSL/TLS.
- */
if((arg < CURLUSESSL_NONE) || (arg >= CURLUSESSL_LAST))
return CURLE_BAD_FUNCTION_ARGUMENT;
s->use_ssl = (unsigned char)arg;
@@ -1268,12 +1142,7 @@ static CURLcode setopt_long(struct Curl_easy *data, CURLoption option,
break;
case CURLOPT_CONNECT_ONLY:
- /*
- * No data transfer.
- * (1) - only do connection
- * (2) - do first get request but get no content
- */
- if(arg > 2)
+ if(arg < 0 || arg > 2)
return CURLE_BAD_FUNCTION_ARGUMENT;
s->connect_only = !!arg;
s->connect_only_ws = (arg == 2);
@@ -1281,7 +1150,6 @@ static CURLcode setopt_long(struct Curl_easy *data, CURLoption option,
#ifdef USE_SSH
- /* we only include SSH options if explicitly built to support SSH */
case CURLOPT_SSH_AUTH_TYPES:
s->ssh_auth_types = (int)arg;
break;
@@ -1289,9 +1157,6 @@ static CURLcode setopt_long(struct Curl_easy *data, CURLoption option,
#if !defined(CURL_DISABLE_FTP) || defined(USE_SSH)
case CURLOPT_NEW_FILE_PERMS:
- /*
- * Uses these permissions instead of 0644
- */
if((arg < 0) || (arg > 0777))
return CURLE_BAD_FUNCTION_ARGUMENT;
s->new_file_perms = (unsigned int)arg;
@@ -1299,9 +1164,6 @@ static CURLcode setopt_long(struct Curl_easy *data, CURLoption option,
#endif
#ifdef USE_SSH
case CURLOPT_NEW_DIRECTORY_PERMS:
- /*
- * Uses these permissions instead of 0755
- */
if((arg < 0) || (arg > 0777))
return CURLE_BAD_FUNCTION_ARGUMENT;
s->new_directory_perms = (unsigned int)arg;
@@ -1309,11 +1171,6 @@ static CURLcode setopt_long(struct Curl_easy *data, CURLoption option,
#endif
#ifdef USE_IPV6
case CURLOPT_ADDRESS_SCOPE:
- /*
- * Use this scope id when using IPv6
- * We always get longs when passed plain numericals so we should check
- * that the value fits into an unsigned 32-bit integer.
- */
#if SIZEOF_LONG > 4
if(uarg > UINT_MAX)
return CURLE_BAD_FUNCTION_ARGUMENT;
@@ -1322,17 +1179,10 @@ static CURLcode setopt_long(struct Curl_easy *data, CURLoption option,
break;
#endif
case CURLOPT_PROTOCOLS:
- /* set the bitmask for the protocols that are allowed to be used for the
- transfer, which thus helps the app which takes URLs from users or other
- external inputs and want to restrict what protocol(s) to deal with.
- Defaults to CURLPROTO_ALL. */
s->allowed_protocols = (curl_prot_t)arg;
break;
case CURLOPT_REDIR_PROTOCOLS:
- /* set the bitmask for the protocols that libcurl is allowed to follow to,
- as a subset of the CURLOPT_PROTOCOLS ones. That means the protocol
- needs to be set in both bitmasks to be allowed to get redirected to. */
s->redir_protocols = (curl_prot_t)arg;
break;
@@ -1340,40 +1190,31 @@ static CURLcode setopt_long(struct Curl_easy *data, CURLoption option,
case CURLOPT_RTSP_REQUEST:
return setopt_RTSP_REQUEST(data, arg);
case CURLOPT_RTSP_CLIENT_CSEQ:
- /*
- * Set the CSEQ number to issue for the next RTSP request. Useful if the
- * application is resuming a previously broken connection. The CSEQ
- * will increment from this new number henceforth.
- */
data->state.rtsp_next_client_CSeq = arg;
break;
case CURLOPT_RTSP_SERVER_CSEQ:
- /* Same as the above, but for server-initiated requests */
data->state.rtsp_next_server_CSeq = arg;
break;
#endif /* ! CURL_DISABLE_RTSP */
case CURLOPT_TCP_KEEPIDLE:
- if(arg < 0)
- return CURLE_BAD_FUNCTION_ARGUMENT;
- else if(arg > INT_MAX)
- arg = INT_MAX;
+ result = value_range(&arg, 0, 0, INT_MAX);
+ if(result)
+ return result;
s->tcp_keepidle = (int)arg;
break;
case CURLOPT_TCP_KEEPINTVL:
- if(arg < 0)
- return CURLE_BAD_FUNCTION_ARGUMENT;
- else if(arg > INT_MAX)
- arg = INT_MAX;
+ result = value_range(&arg, 0, 0, INT_MAX);
+ if(result)
+ return result;
s->tcp_keepintvl = (int)arg;
break;
case CURLOPT_TCP_KEEPCNT:
- if(arg < 0)
- return CURLE_BAD_FUNCTION_ARGUMENT;
- else if(arg > INT_MAX)
- arg = INT_MAX;
+ result = value_range(&arg, 0, 0, INT_MAX);
+ if(result)
+ return result;
s->tcp_keepcnt = (int)arg;
break;
case CURLOPT_SSL_ENABLE_NPN:
@@ -1436,16 +1277,12 @@ static CURLcode setopt_long(struct Curl_easy *data, CURLoption option,
/* deprecated */
break;
case CURLOPT_SSLENGINE_DEFAULT:
- /*
- * flag to set engine as default.
- */
Curl_safefree(s->str[STRING_SSL_ENGINE]);
return Curl_ssl_set_engine_default(data);
case CURLOPT_UPLOAD_FLAGS:
s->upload_flags = (unsigned char)arg;
break;
default:
- /* unknown option */
return CURLE_UNKNOWN_OPTION;
}
return CURLE_OK;
diff --git a/lib/urldata.h b/lib/urldata.h
index ea31d9f5c..b9cc25b9b 100644
--- a/lib/urldata.h
+++ b/lib/urldata.h
@@ -768,7 +768,7 @@ struct connectdata {
and happy eyeballing. Use `Curl_conn_get_transport() for actual value
once the connection is set up. */
unsigned char ip_version; /* copied from the Curl_easy at creation time */
- /* HTTP version last responded with by the server.
+ /* HTTP version last responded with by the server or negotiated via ALPN.
* 0 at start, then one of 09, 10, 11, etc. */
unsigned char httpversion_seen;
unsigned char connect_only;
@@ -1348,8 +1348,6 @@ struct UserDefined {
void *writeheader; /* write the header to this if non-NULL */
unsigned long httpauth; /* kind of HTTP authentication to use (bitmask) */
unsigned long proxyauth; /* kind of proxy authentication to use (bitmask) */
- long maxredirs; /* maximum no. of http(s) redirects to follow, set to -1
- for infinity */
void *postfields; /* if POST, set the fields' values here */
curl_seek_callback seek_func; /* function that seeks the input */
curl_off_t postfieldsize; /* if POST, this might have a size to use instead
@@ -1388,9 +1386,6 @@ struct UserDefined {
is to be reused */
timediff_t conn_max_age_ms; /* max time since creation to allow a
connection that is to be reused */
-#ifndef CURL_DISABLE_TFTP
- long tftp_blksize; /* in bytes, 0 means use default */
-#endif
curl_off_t filesize; /* size of file to upload, -1 means unknown */
long low_speed_limit; /* bytes/second */
long low_speed_time; /* number of seconds */
@@ -1422,7 +1417,7 @@ struct UserDefined {
unsigned char socks5auth;/* kind of SOCKS5 authentication to use (bitmask) */
#endif
struct ssl_general_config general_ssl; /* general user defined SSL stuff */
- int dns_cache_timeout_ms; /* DNS cache timeout (milliseconds) */
+ timediff_t dns_cache_timeout_ms; /* DNS cache timeout (milliseconds) */
unsigned int buffer_size; /* size of receive buffer to use */
unsigned int upload_buffer_size; /* size of upload buffer to use,
keep it >= CURL_MAX_WRITE_SIZE */
@@ -1485,7 +1480,6 @@ struct UserDefined {
int tcp_keepintvl; /* seconds between TCP keepalive probes */
int tcp_keepcnt; /* maximum number of keepalive probes */
- long expect_100_timeout; /* in milliseconds */
#if defined(USE_HTTP2) || defined(USE_HTTP3)
struct Curl_data_priority priority;
#endif
@@ -1505,6 +1499,9 @@ struct UserDefined {
#ifdef USE_ECH
int tls_ech; /* TLS ECH configuration */
#endif
+ short maxredirs; /* maximum no. of http(s) redirects to follow,
+ set to -1 for infinity */
+ unsigned short expect_100_timeout; /* in milliseconds */
unsigned short use_port; /* which port to use (when not using default) */
#ifndef CURL_DISABLE_BINDLOCAL
unsigned short localport; /* local port number to bind to */
@@ -1512,6 +1509,9 @@ struct UserDefined {
in case the 'localport' one cannot be
bind()ed */
#endif
+#ifndef CURL_DISABLE_TFTP
+ unsigned short tftp_blksize; /* in bytes, 0 means use default */
+#endif
#ifndef CURL_DISABLE_NETRC
unsigned char use_netrc; /* enum CURL_NETRC_OPTION values */
#endif
diff --git a/lib/vquic/curl_ngtcp2.c b/lib/vquic/curl_ngtcp2.c
index 1cb99aaea..646702513 100644
--- a/lib/vquic/curl_ngtcp2.c
+++ b/lib/vquic/curl_ngtcp2.c
@@ -1955,9 +1955,9 @@ static CURLcode h3_data_pause(struct Curl_cfilter *cf,
return CURLE_OK;
}
-static CURLcode cf_ngtcp2_data_event(struct Curl_cfilter *cf,
- struct Curl_easy *data,
- int event, int arg1, void *arg2)
+static CURLcode cf_ngtcp2_cntrl(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ int event, int arg1, void *arg2)
{
struct cf_ngtcp2_ctx *ctx = cf->ctx;
CURLcode result = CURLE_OK;
@@ -1995,6 +1995,10 @@ static CURLcode cf_ngtcp2_data_event(struct Curl_cfilter *cf,
}
break;
}
+ case CF_CTRL_CONN_INFO_UPDATE:
+ if(!cf->sockindex && cf->connected)
+ cf->conn->httpversion_seen = 30;
+ break;
default:
break;
}
@@ -2733,7 +2737,7 @@ struct Curl_cftype Curl_cft_http3 = {
Curl_cf_def_data_pending,
cf_ngtcp2_send,
cf_ngtcp2_recv,
- cf_ngtcp2_data_event,
+ cf_ngtcp2_cntrl,
cf_ngtcp2_conn_is_alive,
Curl_cf_def_conn_keep_alive,
cf_ngtcp2_query,
diff --git a/lib/vquic/curl_osslq.c b/lib/vquic/curl_osslq.c
index c18801d81..fa2c0a289 100644
--- a/lib/vquic/curl_osslq.c
+++ b/lib/vquic/curl_osslq.c
@@ -2168,9 +2168,9 @@ static bool cf_osslq_data_pending(struct Curl_cfilter *cf,
return stream && !Curl_bufq_is_empty(&stream->recvbuf);
}
-static CURLcode cf_osslq_data_event(struct Curl_cfilter *cf,
- struct Curl_easy *data,
- int event, int arg1, void *arg2)
+static CURLcode cf_osslq_cntrl(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ int event, int arg1, void *arg2)
{
struct cf_osslq_ctx *ctx = cf->ctx;
CURLcode result = CURLE_OK;
@@ -2206,6 +2206,10 @@ static CURLcode cf_osslq_data_event(struct Curl_cfilter *cf,
}
break;
}
+ case CF_CTRL_CONN_INFO_UPDATE:
+ if(!cf->sockindex && cf->connected)
+ cf->conn->httpversion_seen = 30;
+ break;
default:
break;
}
@@ -2384,7 +2388,7 @@ struct Curl_cftype Curl_cft_http3 = {
cf_osslq_data_pending,
cf_osslq_send,
cf_osslq_recv,
- cf_osslq_data_event,
+ cf_osslq_cntrl,
cf_osslq_conn_is_alive,
Curl_cf_def_conn_keep_alive,
cf_osslq_query,
diff --git a/lib/vquic/curl_quiche.c b/lib/vquic/curl_quiche.c
index b981f4d78..f22566781 100644
--- a/lib/vquic/curl_quiche.c
+++ b/lib/vquic/curl_quiche.c
@@ -1197,9 +1197,9 @@ static CURLcode h3_data_pause(struct Curl_cfilter *cf,
return CURLE_OK;
}
-static CURLcode cf_quiche_data_event(struct Curl_cfilter *cf,
- struct Curl_easy *data,
- int event, int arg1, void *arg2)
+static CURLcode cf_quiche_cntrl(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ int event, int arg1, void *arg2)
{
struct cf_quiche_ctx *ctx = cf->ctx;
CURLcode result = CURLE_OK;
@@ -1238,6 +1238,10 @@ static CURLcode cf_quiche_data_event(struct Curl_cfilter *cf,
}
break;
}
+ case CF_CTRL_CONN_INFO_UPDATE:
+ if(!cf->sockindex && cf->connected)
+ cf->conn->httpversion_seen = 30;
+ break;
default:
break;
}
@@ -1621,7 +1625,7 @@ struct Curl_cftype Curl_cft_http3 = {
cf_quiche_data_pending,
cf_quiche_send,
cf_quiche_recv,
- cf_quiche_data_event,
+ cf_quiche_cntrl,
cf_quiche_conn_is_alive,
Curl_cf_def_conn_keep_alive,
cf_quiche_query,
diff --git a/lib/vquic/vquic.c b/lib/vquic/vquic.c
index bebe1df6f..f8ce34129 100644
--- a/lib/vquic/vquic.c
+++ b/lib/vquic/vquic.c
@@ -642,7 +642,7 @@ CURLcode Curl_qlogdir(struct Curl_easy *data,
size_t scidlen,
int *qlogfdp)
{
- const char *qlog_dir = getenv("QLOGDIR");
+ char *qlog_dir = curl_getenv("QLOGDIR");
*qlogfdp = -1;
if(qlog_dir) {
struct dynbuf fname;
@@ -667,6 +667,7 @@ CURLcode Curl_qlogdir(struct Curl_easy *data,
*qlogfdp = qlogfd;
}
curlx_dyn_free(&fname);
+ free(qlog_dir);
if(result)
return result;
}
diff --git a/lib/vtls/openssl.c b/lib/vtls/openssl.c
index 3cc0d8630..a2ab831f2 100644
--- a/lib/vtls/openssl.c
+++ b/lib/vtls/openssl.c
@@ -1856,8 +1856,10 @@ static CURLcode x509_name_oneline(X509_NAME *a, struct dynbuf *d)
CURLcode result = CURLE_OUT_OF_MEMORY;
if(bio_out) {
+ unsigned long flags = XN_FLAG_SEP_SPLUS_SPC |
+ (XN_FLAG_ONELINE & ~ASN1_STRFLGS_ESC_MSB & ~XN_FLAG_SPC_EQ);
curlx_dyn_reset(d);
- rc = X509_NAME_print_ex(bio_out, a, 0, XN_FLAG_SEP_SPLUS_SPC);
+ rc = X509_NAME_print_ex(bio_out, a, 0, flags);
if(rc != -1) {
BIO_get_mem_ptr(bio_out, &biomem);
result = curlx_dyn_addn(d, biomem->data, biomem->length);
diff --git a/lib/vtls/vtls.c b/lib/vtls/vtls.c
index 96d64dd60..f17f9142b 100644
--- a/lib/vtls/vtls.c
+++ b/lib/vtls/vtls.c
@@ -1605,6 +1605,30 @@ static CURLcode ssl_cf_query(struct Curl_cfilter *cf,
CURLE_UNKNOWN_OPTION;
}
+static CURLcode ssl_cf_cntrl(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ int event, int arg1, void *arg2)
+{
+ struct ssl_connect_data *connssl = cf->ctx;
+
+ (void)arg1;
+ (void)arg2;
+ (void)data;
+ switch(event) {
+ case CF_CTRL_CONN_INFO_UPDATE:
+ if(connssl->negotiated.alpn && !cf->sockindex) {
+ if(!strcmp("http/1.1", connssl->negotiated.alpn))
+ cf->conn->httpversion_seen = 11;
+ else if(!strcmp("h2", connssl->negotiated.alpn))
+ cf->conn->httpversion_seen = 20;
+ else if(!strcmp("h3", connssl->negotiated.alpn))
+ cf->conn->httpversion_seen = 30;
+ }
+ break;
+ }
+ return CURLE_OK;
+}
+
static bool cf_ssl_is_alive(struct Curl_cfilter *cf, struct Curl_easy *data,
bool *input_pending)
{
@@ -1628,7 +1652,7 @@ struct Curl_cftype Curl_cft_ssl = {
ssl_cf_data_pending,
ssl_cf_send,
ssl_cf_recv,
- Curl_cf_def_cntrl,
+ ssl_cf_cntrl,
cf_ssl_is_alive,
Curl_cf_def_conn_keep_alive,
ssl_cf_query,
diff --git a/lib/vtls/wolfssl.c b/lib/vtls/wolfssl.c
index e98cf8714..9a84b3384 100644
--- a/lib/vtls/wolfssl.c
+++ b/lib/vtls/wolfssl.c
@@ -243,12 +243,12 @@ static const struct group_name_map gnm[] = {
{ WOLFSSL_ML_KEM_512, "ML_KEM_512" },
{ WOLFSSL_ML_KEM_768, "ML_KEM_768" },
{ WOLFSSL_ML_KEM_1024, "ML_KEM_1024" },
- { WOLFSSL_P256_ML_KEM_512, "P256_ML_KEM_512" },
- { WOLFSSL_P384_ML_KEM_768, "P384_ML_KEM_768" },
- { WOLFSSL_P521_ML_KEM_1024, "P521_ML_KEM_1024" },
- { WOLFSSL_P256_ML_KEM_768, "P256_ML_KEM_768" },
- { WOLFSSL_P384_ML_KEM_1024, "P384_ML_KEM_1024" },
- { WOLFSSL_X25519_ML_KEM_768, "X25519_ML_KEM_768" },
+ { WOLFSSL_SECP256R1MLKEM512, "SecP256r1MLKEM512" },
+ { WOLFSSL_SECP384R1MLKEM768, "SecP384r1MLKEM768" },
+ { WOLFSSL_SECP521R1MLKEM1024, "SecP521r1MLKEM1024" },
+ { WOLFSSL_SECP256R1MLKEM768, "SecP256r1MLKEM768" },
+ { WOLFSSL_SECP384R1MLKEM1024, "SecP384r1MLKEM1024" },
+ { WOLFSSL_X25519MLKEM768, "X25519MLKEM768" },
{ 0, NULL }
};
#endif
diff --git a/src/tool_cb_hdr.c b/src/tool_cb_hdr.c
index e988224ac..d8cd117e3 100644
--- a/src/tool_cb_hdr.c
+++ b/src/tool_cb_hdr.c
@@ -34,6 +34,7 @@
#include "tool_cb_wrt.h"
#include "tool_operate.h"
#include "tool_libinfo.h"
+#include "tool_strdup.h"
#include "memdebug.h" /* keep this as LAST include */
@@ -285,11 +286,11 @@ size_t tool_header_cb(char *ptr, size_t size, size_t nmemb, void *userdata)
if(!outs->stream && !tool_create_output_file(outs, per->config))
return CURL_WRITEFUNC_ERROR;
- if(hdrcbdata->global->isatty &&
+ if(hdrcbdata->config->global->isatty &&
#ifdef _WIN32
tool_term_has_bold &&
#endif
- hdrcbdata->global->styled_output)
+ hdrcbdata->config->global->styled_output)
value = memchr(ptr, ':', cb);
if(value) {
size_t namelen = value - ptr;
@@ -322,12 +323,9 @@ static char *parse_filename(const char *ptr, size_t len)
char *q;
char stop = '\0';
- /* simple implementation of strndup() */
- copy = malloc(len + 1);
+ copy = memdup0(ptr, len);
if(!copy)
return NULL;
- memcpy(copy, ptr, len);
- copy[len] = '\0';
p = copy;
if(*p == '\'' || *p == '"') {
@@ -438,11 +436,9 @@ static void write_linked_location(CURL *curl, const char *location,
goto locout;
/* Create a null-terminated and whitespace-stripped copy of Location: */
- copyloc = malloc(llen + 1);
+ copyloc = memdup0(loc, llen);
if(!copyloc)
goto locout;
- memcpy(copyloc, loc, llen);
- copyloc[llen] = 0;
/* The original URL to use as a base for a relative redirect URL */
if(curl_easy_getinfo(curl, CURLINFO_EFFECTIVE_URL, &locurl))
diff --git a/src/tool_cb_hdr.h b/src/tool_cb_hdr.h
index 7402c12a9..37be591e7 100644
--- a/src/tool_cb_hdr.h
+++ b/src/tool_cb_hdr.h
@@ -41,7 +41,6 @@
*/
struct HdrCbData {
- struct GlobalConfig *global;
struct OperationConfig *config;
struct OutStruct *outs;
struct OutStruct *heads;
diff --git a/src/tool_cb_wrt.c b/src/tool_cb_wrt.c
index d34c1fa2e..3ac14cd01 100644
--- a/src/tool_cb_wrt.c
+++ b/src/tool_cb_wrt.c
@@ -68,35 +68,24 @@ bool tool_create_output_file(struct OutStruct *outs,
} while(fd == -1 && errno == EINTR);
if(config->file_clobber_mode == CLOBBER_NEVER && fd == -1) {
int next_num = 1;
- size_t len = strlen(fname);
- size_t newlen = len + 13; /* nul + 1-11 digits + dot */
- char *newname;
- /* Guard against wraparound in new filename */
- if(newlen < len) {
- errorf(global, "overflow in filename generation");
- return FALSE;
- }
- newname = malloc(newlen);
- if(!newname) {
- errorf(global, "out of memory");
- return FALSE;
- }
- memcpy(newname, fname, len);
- newname[len] = '.';
+ struct dynbuf fbuffer;
+ curlx_dyn_init(&fbuffer, 1025);
/* !checksrc! disable ERRNOVAR 1 */
while(fd == -1 && /* have not successfully opened a file */
(errno == EEXIST || errno == EISDIR) &&
/* because we keep having files that already exist */
next_num < 100 /* and we have not reached the retry limit */ ) {
- msnprintf(newname + len + 1, 12, "%d", next_num);
+ curlx_dyn_reset(&fbuffer);
+ if(curlx_dyn_addf(&fbuffer, "%s.%d", fname, next_num))
+ return FALSE;
next_num++;
do {
- fd = open(newname, O_CREAT | O_WRONLY | O_EXCL | CURL_O_BINARY,
- OPENMODE);
+ fd = open(curlx_dyn_ptr(&fbuffer),
+ O_CREAT | O_WRONLY | O_EXCL | CURL_O_BINARY, OPENMODE);
/* Keep retrying in the hope that it is not interrupted sometime */
} while(fd == -1 && errno == EINTR);
}
- outs->filename = newname; /* remember the new one */
+ outs->filename = curlx_dyn_ptr(&fbuffer); /* remember the new one */
outs->alloc_filename = TRUE;
}
/* An else statement to not overwrite existing files and not retry with
@@ -124,6 +113,130 @@ bool tool_create_output_file(struct OutStruct *outs,
return TRUE;
}
+#if defined(_WIN32) && !defined(UNDER_CE)
+static size_t win_console(intptr_t fhnd, struct OutStruct *outs,
+ char *buffer, size_t bytes,
+ size_t *retp)
+{
+ wchar_t *wc_buf;
+ DWORD wc_len, chars_written;
+ unsigned char *rbuf = (unsigned char *)buffer;
+ DWORD rlen = (DWORD)bytes;
+
+#define IS_TRAILING_BYTE(x) (0x80 <= (x) && (x) < 0xC0)
+
+ /* attempt to complete an incomplete UTF-8 sequence from previous call. the
+ sequence does not have to be well-formed. */
+ if(outs->utf8seq[0] && rlen) {
+ bool complete = false;
+ /* two byte sequence (lead byte 110yyyyy) */
+ if(0xC0 <= outs->utf8seq[0] && outs->utf8seq[0] < 0xE0) {
+ outs->utf8seq[1] = *rbuf++;
+ --rlen;
+ complete = true;
+ }
+ /* three byte sequence (lead byte 1110zzzz) */
+ else if(0xE0 <= outs->utf8seq[0] && outs->utf8seq[0] < 0xF0) {
+ if(!outs->utf8seq[1]) {
+ outs->utf8seq[1] = *rbuf++;
+ --rlen;
+ }
+ if(rlen && !outs->utf8seq[2]) {
+ outs->utf8seq[2] = *rbuf++;
+ --rlen;
+ complete = true;
+ }
+ }
+ /* four byte sequence (lead byte 11110uuu) */
+ else if(0xF0 <= outs->utf8seq[0] && outs->utf8seq[0] < 0xF8) {
+ if(!outs->utf8seq[1]) {
+ outs->utf8seq[1] = *rbuf++;
+ --rlen;
+ }
+ if(rlen && !outs->utf8seq[2]) {
+ outs->utf8seq[2] = *rbuf++;
+ --rlen;
+ }
+ if(rlen && !outs->utf8seq[3]) {
+ outs->utf8seq[3] = *rbuf++;
+ --rlen;
+ complete = true;
+ }
+ }
+
+ if(complete) {
+ WCHAR prefix[3] = {0}; /* UTF-16 (1-2 WCHARs) + NUL */
+
+ if(MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)outs->utf8seq, -1,
+ prefix, CURL_ARRAYSIZE(prefix))) {
+ DEBUGASSERT(prefix[2] == L'\0');
+ if(!WriteConsoleW((HANDLE) fhnd, prefix, prefix[1] ? 2 : 1,
+ &chars_written, NULL)) {
+ return CURL_WRITEFUNC_ERROR;
+ }
+ }
+ /* else: UTF-8 input was not well formed and OS is pre-Vista which drops
+ invalid characters instead of writing U+FFFD to output. */
+ memset(outs->utf8seq, 0, sizeof(outs->utf8seq));
+ }
+ }
+
+ /* suppress an incomplete utf-8 sequence at end of rbuf */
+ if(!outs->utf8seq[0] && rlen && (rbuf[rlen - 1] & 0x80)) {
+ /* check for lead byte from a two, three or four byte sequence */
+ if(0xC0 <= rbuf[rlen - 1] && rbuf[rlen - 1] < 0xF8) {
+ outs->utf8seq[0] = rbuf[rlen - 1];
+ rlen -= 1;
+ }
+ else if(rlen >= 2 && IS_TRAILING_BYTE(rbuf[rlen - 1])) {
+ /* check for lead byte from a three or four byte sequence */
+ if(0xE0 <= rbuf[rlen - 2] && rbuf[rlen - 2] < 0xF8) {
+ outs->utf8seq[0] = rbuf[rlen - 2];
+ outs->utf8seq[1] = rbuf[rlen - 1];
+ rlen -= 2;
+ }
+ else if(rlen >= 3 && IS_TRAILING_BYTE(rbuf[rlen - 2])) {
+ /* check for lead byte from a four byte sequence */
+ if(0xF0 <= rbuf[rlen - 3] && rbuf[rlen - 3] < 0xF8) {
+ outs->utf8seq[0] = rbuf[rlen - 3];
+ outs->utf8seq[1] = rbuf[rlen - 2];
+ outs->utf8seq[2] = rbuf[rlen - 1];
+ rlen -= 3;
+ }
+ }
+ }
+ }
+
+ if(rlen) {
+ /* calculate buffer size for wide characters */
+ wc_len = (DWORD)MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)rbuf, (int)rlen,
+ NULL, 0);
+ if(!wc_len)
+ return CURL_WRITEFUNC_ERROR;
+
+ wc_buf = (wchar_t*) malloc(wc_len * sizeof(wchar_t));
+ if(!wc_buf)
+ return CURL_WRITEFUNC_ERROR;
+
+ wc_len = (DWORD)MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)rbuf, (int)rlen,
+ wc_buf, (int)wc_len);
+ if(!wc_len) {
+ free(wc_buf);
+ return CURL_WRITEFUNC_ERROR;
+ }
+
+ if(!WriteConsoleW((HANDLE) fhnd, wc_buf, wc_len, &chars_written, NULL)) {
+ free(wc_buf);
+ return CURL_WRITEFUNC_ERROR;
+ }
+ free(wc_buf);
+ }
+
+ *retp = bytes;
+ return 0;
+}
+#endif
+
/*
** callback for CURLOPT_WRITEFUNCTION
*/
@@ -215,131 +328,9 @@ size_t tool_write_cb(char *buffer, size_t sz, size_t nmemb, void *userdata)
/* if Windows console then UTF-8 must be converted to UTF-16 */
if(isatty(fileno(outs->stream)) &&
GetConsoleScreenBufferInfo((HANDLE)fhnd, &console_info)) {
- wchar_t *wc_buf;
- DWORD wc_len, chars_written;
- unsigned char *rbuf = (unsigned char *)buffer;
- DWORD rlen = (DWORD)bytes;
-
-#define IS_TRAILING_BYTE(x) (0x80 <= (x) && (x) < 0xC0)
-
- /* attempt to complete an incomplete UTF-8 sequence from previous call.
- the sequence does not have to be well-formed. */
- if(outs->utf8seq[0] && rlen) {
- bool complete = false;
- /* two byte sequence (lead byte 110yyyyy) */
- if(0xC0 <= outs->utf8seq[0] && outs->utf8seq[0] < 0xE0) {
- outs->utf8seq[1] = *rbuf++;
- --rlen;
- complete = true;
- }
- /* three byte sequence (lead byte 1110zzzz) */
- else if(0xE0 <= outs->utf8seq[0] && outs->utf8seq[0] < 0xF0) {
- if(!outs->utf8seq[1]) {
- outs->utf8seq[1] = *rbuf++;
- --rlen;
- }
- if(rlen && !outs->utf8seq[2]) {
- outs->utf8seq[2] = *rbuf++;
- --rlen;
- complete = true;
- }
- }
- /* four byte sequence (lead byte 11110uuu) */
- else if(0xF0 <= outs->utf8seq[0] && outs->utf8seq[0] < 0xF8) {
- if(!outs->utf8seq[1]) {
- outs->utf8seq[1] = *rbuf++;
- --rlen;
- }
- if(rlen && !outs->utf8seq[2]) {
- outs->utf8seq[2] = *rbuf++;
- --rlen;
- }
- if(rlen && !outs->utf8seq[3]) {
- outs->utf8seq[3] = *rbuf++;
- --rlen;
- complete = true;
- }
- }
-
- if(complete) {
- WCHAR prefix[3] = {0}; /* UTF-16 (1-2 WCHARs) + NUL */
-
- if(MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)outs->utf8seq, -1,
- prefix, CURL_ARRAYSIZE(prefix))) {
- DEBUGASSERT(prefix[2] == L'\0');
- if(!WriteConsoleW(
- (HANDLE) fhnd,
- prefix,
- prefix[1] ? 2 : 1,
- &chars_written,
- NULL)) {
- return CURL_WRITEFUNC_ERROR;
- }
- }
- /* else: UTF-8 input was not well formed and OS is pre-Vista which
- drops invalid characters instead of writing U+FFFD to output. */
-
- memset(outs->utf8seq, 0, sizeof(outs->utf8seq));
- }
- }
-
- /* suppress an incomplete utf-8 sequence at end of rbuf */
- if(!outs->utf8seq[0] && rlen && (rbuf[rlen - 1] & 0x80)) {
- /* check for lead byte from a two, three or four byte sequence */
- if(0xC0 <= rbuf[rlen - 1] && rbuf[rlen - 1] < 0xF8) {
- outs->utf8seq[0] = rbuf[rlen - 1];
- rlen -= 1;
- }
- else if(rlen >= 2 && IS_TRAILING_BYTE(rbuf[rlen - 1])) {
- /* check for lead byte from a three or four byte sequence */
- if(0xE0 <= rbuf[rlen - 2] && rbuf[rlen - 2] < 0xF8) {
- outs->utf8seq[0] = rbuf[rlen - 2];
- outs->utf8seq[1] = rbuf[rlen - 1];
- rlen -= 2;
- }
- else if(rlen >= 3 && IS_TRAILING_BYTE(rbuf[rlen - 2])) {
- /* check for lead byte from a four byte sequence */
- if(0xF0 <= rbuf[rlen - 3] && rbuf[rlen - 3] < 0xF8) {
- outs->utf8seq[0] = rbuf[rlen - 3];
- outs->utf8seq[1] = rbuf[rlen - 2];
- outs->utf8seq[2] = rbuf[rlen - 1];
- rlen -= 3;
- }
- }
- }
- }
-
- if(rlen) {
- /* calculate buffer size for wide characters */
- wc_len = (DWORD)MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)rbuf, (int)rlen,
- NULL, 0);
- if(!wc_len)
- return CURL_WRITEFUNC_ERROR;
-
- wc_buf = (wchar_t*) malloc(wc_len * sizeof(wchar_t));
- if(!wc_buf)
- return CURL_WRITEFUNC_ERROR;
-
- wc_len = (DWORD)MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)rbuf, (int)rlen,
- wc_buf, (int)wc_len);
- if(!wc_len) {
- free(wc_buf);
- return CURL_WRITEFUNC_ERROR;
- }
-
- if(!WriteConsoleW(
- (HANDLE) fhnd,
- wc_buf,
- wc_len,
- &chars_written,
- NULL)) {
- free(wc_buf);
- return CURL_WRITEFUNC_ERROR;
- }
- free(wc_buf);
- }
-
- rc = bytes;
+ size_t retval = win_console(fhnd, outs, buffer, bytes, &rc);
+ if(retval)
+ return retval;
}
else
#endif
diff --git a/src/tool_operate.c b/src/tool_operate.c
index 11abc1f9d..e785bc321 100644
--- a/src/tool_operate.c
+++ b/src/tool_operate.c
@@ -1353,7 +1353,6 @@ static CURLcode single_transfer(struct OperationConfig *config,
hdrcbdata->outs = outs;
hdrcbdata->heads = heads;
hdrcbdata->etag_save = etag_save;
- hdrcbdata->global = global;
hdrcbdata->config = config;
result = config2setopts(config, per, curl, share);
diff --git a/src/tool_strdup.c b/src/tool_strdup.c
index a5725d6d4..ff80b56b9 100644
--- a/src/tool_strdup.c
+++ b/src/tool_strdup.c
@@ -22,6 +22,7 @@
*
***************************************************************************/
#include "tool_strdup.h"
+#include "memdebug.h" /* keep this as LAST include */
#ifndef HAVE_STRDUP
char *strdup(const char *str)
@@ -42,3 +43,14 @@ char *strdup(const char *str)
return newstr;
}
#endif
+
+char *memdup0(const char *data, size_t len)
+{
+ char *p = malloc(len + 1);
+ if(!p)
+ return NULL;
+ if(len)
+ memcpy(p, data, len);
+ p[len] = 0;
+ return p;
+}
diff --git a/src/tool_strdup.h b/src/tool_strdup.h
index 9b2161896..275be7c5d 100644
--- a/src/tool_strdup.h
+++ b/src/tool_strdup.h
@@ -28,5 +28,6 @@
#ifndef HAVE_STRDUP
extern char *strdup(const char *str);
#endif
+char *memdup0(const char *data, size_t len);
#endif /* HEADER_TOOL_STRDUP_H */
diff --git a/src/tool_urlglob.c b/src/tool_urlglob.c
index c20bbd4ea..d79aa2990 100644
--- a/src/tool_urlglob.c
+++ b/src/tool_urlglob.c
@@ -27,6 +27,7 @@
#include "tool_doswin.h"
#include "tool_urlglob.h"
#include "tool_vms.h"
+#include "tool_strdup.h"
#include "memdebug.h" /* keep this as LAST include */
#define GLOBERROR(string, column, code) \
@@ -45,13 +46,10 @@ static CURLcode glob_fixed(struct URLGlob *glob, char *fixed, size_t len)
if(!pat->content.Set.elements)
return GLOBERROR("out of memory", 0, CURLE_OUT_OF_MEMORY);
- pat->content.Set.elements[0] = malloc(len + 1);
+ pat->content.Set.elements[0] = memdup0(fixed, len);
if(!pat->content.Set.elements[0])
return GLOBERROR("out of memory", 0, CURLE_OUT_OF_MEMORY);
- memcpy(pat->content.Set.elements[0], fixed, len);
- pat->content.Set.elements[0][len] = 0;
-
return CURLE_OK;
}
diff --git a/src/var.c b/src/var.c
index b2fc835fb..85d03f3ce 100644
--- a/src/var.c
+++ b/src/var.c
@@ -31,23 +31,13 @@
#include "tool_parsecfg.h"
#include "tool_paramhlp.h"
#include "tool_writeout_json.h"
+#include "tool_strdup.h"
#include "var.h"
#include "memdebug.h" /* keep this as LAST include */
#define MAX_EXPAND_CONTENT 10000000
#define MAX_VAR_LEN 128 /* max length of a name */
-static char *Memdup(const char *data, size_t len)
-{
- char *p = malloc(len + 1);
- if(!p)
- return NULL;
- if(len)
- memcpy(p, data, len);
- p[len] = 0;
- return p;
-}
-
/* free everything */
void varcleanup(struct GlobalConfig *global)
{
@@ -208,7 +198,7 @@ static ParameterError varfunc(struct GlobalConfig *global,
free(c);
clen = curlx_dyn_len(out);
- c = Memdup(curlx_dyn_ptr(out), clen);
+ c = memdup0(curlx_dyn_ptr(out), clen);
if(!c) {
err = PARAM_NO_MEM;
break;
@@ -379,7 +369,7 @@ static ParameterError addvariable(struct GlobalConfig *global,
if(p) {
memcpy(p->name, name, nlen);
- p->content = contalloc ? content : Memdup(content, clen);
+ p->content = contalloc ? content : memdup0(content, clen);
if(p->content) {
p->clen = clen;
diff --git a/tests/data/Makefile.am b/tests/data/Makefile.am
index 379ede24a..c01d93eb8 100644
--- a/tests/data/Makefile.am
+++ b/tests/data/Makefile.am
@@ -252,7 +252,7 @@ test2064 test2065 test2066 test2067 test2068 test2069 test2070 test2071 \
test2072 test2073 test2074 test2075 test2076 test2077 test2078 test2079 \
test2080 test2081 test2082 test2083 test2084 test2085 test2086 test2087 \
test2088 test2089 \
-test2100 test2101 test2102 test2103 \
+test2100 test2101 test2102 test2103 test2104 \
\
test2200 test2201 test2202 test2203 test2204 test2205 \
\
diff --git a/tests/data/test2104 b/tests/data/test2104
new file mode 100644
index 000000000..12ed0ff85
--- /dev/null
+++ b/tests/data/test2104
@@ -0,0 +1,49 @@
+<testcase>
+<info>
+<keywords>
+DNS cache
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+<dns>
+</dns>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+dns
+</server>
+<features>
+override-dns
+</features>
+<name>
+Get three URLs with bad host name - cache
+</name>
+<setenv>
+CURL_DNS_SERVER=127.0.0.1:%DNSPORT
+</setenv>
+<command>
+http://examplehost.example/%TESTNUMBER http://examplehost.example/%TESTNUMBER http://examplehost.example/%TESTNUMBER
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+# curl: (6) Could not resolve host: examplehost.example
+<errorcode>
+6
+</errorcode>
+
+# Ignore HTTPS requests here
+<dns host="examplehost.example QTYPE A">
+QNAME examplehost.example QTYPE A
+QNAME examplehost.example QTYPE AAAA
+</dns>
+</verify>
+</testcase>
diff --git a/tests/data/test655 b/tests/data/test655
index 583e7c0a0..3cf5bd885 100644
--- a/tests/data/test655
+++ b/tests/data/test655
@@ -36,7 +36,7 @@ lib%TESTNUMBER
resolver start callback
</name>
<command>
-http://%HOSTIP:%HTTPPORT/%TESTNUMBER
+http://failthis/%TESTNUMBER http://%HOSTIP:%HTTPPORT/%TESTNUMBER
</command>
</client>
diff --git a/tests/libtest/lib3033.c b/tests/libtest/lib3033.c
index 692541329..1c0b9856f 100644
--- a/tests/libtest/lib3033.c
+++ b/tests/libtest/lib3033.c
@@ -36,7 +36,7 @@ static CURLcode t3033_req_test(CURLM *multi, CURL *easy,
if(index == 1) {
curl_multi_setopt(multi, CURLMOPT_NETWORK_CHANGED,
- CURLM_NWCOPT_CLEAR_CONNS);
+ CURLMNWC_CLEAR_CONNS);
curl_mprintf("[1] signal network change\n");
}
else {
diff --git a/tests/libtest/lib655.c b/tests/libtest/lib655.c
index d1bf80473..07392cbd8 100644
--- a/tests/libtest/lib655.c
+++ b/tests/libtest/lib655.c
@@ -74,7 +74,7 @@ static CURLcode test_lib655(const char *URL)
goto test_cleanup;
}
- /* First set the URL that is about to receive our request. */
+ /* Set the URL that is about to receive our first request. */
test_setopt(curl, CURLOPT_URL, URL);
test_setopt(curl, CURLOPT_RESOLVER_START_DATA, TEST_DATA_STRING);
@@ -91,6 +91,9 @@ static CURLcode test_lib655(const char *URL)
goto test_cleanup;
}
+ /* Set the URL that receives our second request. */
+ test_setopt(curl, CURLOPT_URL, libtest_arg2);
+
test_setopt(curl, CURLOPT_RESOLVER_START_FUNCTION, resolver_alloc_cb_pass);
/* this should succeed */
diff --git a/tests/runtests.pl b/tests/runtests.pl
index f2e2a6fdb..407a37946 100755
--- a/tests/runtests.pl
+++ b/tests/runtests.pl
@@ -1674,6 +1674,29 @@ sub singletest_check {
}
}
+ my @dnsd = getpart("verify", "dns");
+ if(@dnsd) {
+ # we're supposed to verify a dynamically generated file!
+ my %hash = getpartattr("verify", "dns");
+ my $hostname=$hash{'host'};
+
+ # Verify the sent DNS requests
+ my @out = loadarray("$logdir/dnsd.input");
+ my @sverify = sort @dnsd;
+ my @sout = sort @out;
+
+ if($hostname) {
+ # when a hostname is set, we filter out requests to just this
+ # pattern
+ @sout = grep {/$hostname/} @sout;
+ }
+
+ $res = compare($runnerid, $testnum, $testname, "DNS", \@sout, \@sverify);
+ if($res) {
+ return -1;
+ }
+ }
+
# accept multiple comma-separated error codes
my @splerr = split(/ *, */, $errorcode);
my $errok;
diff --git a/tests/server/dnsd.c b/tests/server/dnsd.c
index 745fbeb59..dc49723da 100644
--- a/tests/server/dnsd.c
+++ b/tests/server/dnsd.c
@@ -64,6 +64,19 @@ static int qname(const unsigned char **pkt, size_t *size)
#define QTYPE_AAAA 28
#define QTYPE_HTTPS 0x41
+static const char *type2string(unsigned short qtype)
+{
+ switch(qtype) {
+ case QTYPE_A:
+ return "A";
+ case QTYPE_AAAA:
+ return "AAAA";
+ case QTYPE_HTTPS:
+ return "HTTPS";
+ }
+ return "<unknown>";
+}
+
/*
* Handle initial connection protocol.
*
@@ -125,8 +138,7 @@ static int store_incoming(const unsigned char *data, size_t size,
fprintf(server, "Z: %x\n", (id & 0x70) >> 4);
fprintf(server, "RCODE: %x\n", (id & 0x0f));
#endif
- qd = get16bit(&data, &size);
- fprintf(server, "QDCOUNT: %04x\n", qd);
+ (void) get16bit(&data, &size);
data += 6; /* skip ANCOUNT, NSCOUNT and ARCOUNT */
size -= 6;
@@ -136,14 +148,13 @@ static int store_incoming(const unsigned char *data, size_t size,
qptr = data;
if(!qname(&data, &size)) {
- fprintf(server, "QNAME: %s\n", name);
qd = get16bit(&data, &size);
- fprintf(server, "QTYPE: %04x\n", qd);
+ fprintf(server, "QNAME %s QTYPE %s\n", name, type2string(qd));
*qtype = qd;
- logmsg("Question for '%s' type %x", name, qd);
+ logmsg("Question for '%s' type %x / %s", name, qd,
+ type2string(qd));
- qd = get16bit(&data, &size);
- logmsg("QCLASS: %04x\n", qd);
+ (void) get16bit(&data, &size);
*qlen = qsize - size; /* total size of the query */
memcpy(qbuf, qptr, *qlen);
@@ -618,7 +629,7 @@ static int test_dnsd(int argc, char **argv)
clear_advisor_read_lock(loglockfile);
}
- logmsg("end of one transfer");
+ /* logmsg("end of one transfer"); */
}
dnsd_cleanup:
diff --git a/tests/server/rtspd.c b/tests/server/rtspd.c
index d046fdf42..67829922d 100644
--- a/tests/server/rtspd.c
+++ b/tests/server/rtspd.c
@@ -1224,7 +1224,7 @@ static int test_rtspd(int argc, char *argv[])
logmsg("====> Client connect");
-#ifdef TCP_NODELAY
+#if defined(TCP_NODELAY) && !defined(__EMSCRIPTEN__)
/*
* Disable the Nagle algorithm to make it easier to send out a large
* response in many small segments to torture the clients more.
diff --git a/tests/server/sws.c b/tests/server/sws.c
index 2ae4727ad..2b94e5293 100644
--- a/tests/server/sws.c
+++ b/tests/server/sws.c
@@ -158,7 +158,7 @@ static const char *doc404 = "HTTP/1.1 404 Not Found\r\n"
/* work around for handling trailing headers */
static int already_recv_zeroed_chunk = FALSE;
-#ifdef TCP_NODELAY
+#if defined(TCP_NODELAY) && defined(CURL_TCP_NODELAY_SUPPORTED)
/* returns true if the current socket is an IP one */
static bool socket_domain_is_ip(void)
{
@@ -1239,7 +1239,7 @@ static curl_socket_t connect_to(const char *ipaddr, unsigned short port)
return CURL_SOCKET_BAD;
}
-#ifdef TCP_NODELAY
+#if defined(TCP_NODELAY) && defined(CURL_TCP_NODELAY_SUPPORTED)
if(socket_domain_is_ip()) {
/* Disable the Nagle algorithm */
curl_socklen_t flag = 1;
@@ -1545,7 +1545,7 @@ static void http_connect(curl_socket_t *infdp,
}
memset(req2, 0, sizeof(*req2));
logmsg("====> Client connect DATA");
-#ifdef TCP_NODELAY
+#if defined(TCP_NODELAY) && defined(CURL_TCP_NODELAY_SUPPORTED)
if(socket_domain_is_ip()) {
/* Disable the Nagle algorithm */
curl_socklen_t flag = 1;
@@ -1871,7 +1871,7 @@ static curl_socket_t accept_connection(curl_socket_t sock)
all_sockets[num_sockets] = msgsock;
num_sockets += 1;
-#ifdef TCP_NODELAY
+#if defined(TCP_NODELAY) && defined(CURL_TCP_NODELAY_SUPPORTED)
if(socket_domain_is_ip()) {
/*
* Disable the Nagle algorithm to make it easier to send out a large