Compare commits
1 Commits
master
...
renovate/a
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
52e8c0af99 |
142
.github/scripts/cleancmd.pl
vendored
142
.github/scripts/cleancmd.pl
vendored
@ -3,117 +3,55 @@
|
||||
#
|
||||
# SPDX-License-Identifier: curl
|
||||
#
|
||||
# Input: cmdline docs markdown files, they get modified *in place*
|
||||
#
|
||||
# Strip off the leading meta-data/header part, remove all known curl symbols
|
||||
# and long command line options. Also clean up whatever else the spell checker
|
||||
# might have a problem with that we still deem is fine.
|
||||
# Input: a cmdline docs markdown, it gets modified *in place*
|
||||
#
|
||||
# The main purpose is to strip off the leading meta-data part, but also to
|
||||
# clean up whatever else the spell checker might have a problem with that we
|
||||
# still deem is fine.
|
||||
|
||||
open(S, "<./docs/libcurl/symbols-in-versions")
|
||||
|| die "can't find symbols-in-versions";
|
||||
while(<S>) {
|
||||
if(/^([^ ]*) /) {
|
||||
push @asyms, $1;
|
||||
my $header = 1;
|
||||
while(1) {
|
||||
# set this if the markdown has no meta-data header to skip
|
||||
if($ARGV[0] eq "--no-header") {
|
||||
shift @ARGV;
|
||||
$header = 0;
|
||||
}
|
||||
else {
|
||||
last;
|
||||
}
|
||||
}
|
||||
close(S);
|
||||
|
||||
# init the opts table with "special" options not easy to figure out
|
||||
my @aopts = (
|
||||
'--ftp-ssl-reqd', # old alias
|
||||
);
|
||||
my $f = $ARGV[0];
|
||||
|
||||
open(O, "<./docs/options-in-versions")
|
||||
|| die "can't find options-in-versions";
|
||||
while(<O>) {
|
||||
chomp;
|
||||
if(/^([^ ]+)/) {
|
||||
my $o = $1;
|
||||
push @aopts, $o;
|
||||
if($o =~ /^--no-(.*)/) {
|
||||
# for the --no options, also make one without it
|
||||
push @aopts, "--$1";
|
||||
open(F, "<$f") or die;
|
||||
|
||||
my $ignore = $header;
|
||||
my $sepcount = 0;
|
||||
my @out;
|
||||
while(<F>) {
|
||||
if(/^---/ && $header) {
|
||||
if(++$sepcount == 2) {
|
||||
$ignore = 0;
|
||||
}
|
||||
elsif($o =~ /^--disable-(.*)/) {
|
||||
# for the --disable options, also make the special ones
|
||||
push @aopts, "--$1";
|
||||
push @aopts, "--no-$1";
|
||||
}
|
||||
}
|
||||
}
|
||||
close(O);
|
||||
|
||||
open(C, "<./.github/scripts/spellcheck.curl")
|
||||
|| die "can't find spellcheck.curl";
|
||||
while(<C>) {
|
||||
if(/^\#/) {
|
||||
next;
|
||||
}
|
||||
chomp;
|
||||
if(/^([^ ]+)/) {
|
||||
push @asyms, $1;
|
||||
}
|
||||
next if($ignore);
|
||||
|
||||
# strip out backticked words
|
||||
$_ =~ s/`[^`]+`//g;
|
||||
|
||||
# strip out all long command line options
|
||||
$_ =~ s/--[a-z0-9-]+//g;
|
||||
|
||||
# strip out https URLs, we don't want them spellchecked
|
||||
$_ =~ s!https://[a-z0-9\#_/.-]+!!gi;
|
||||
|
||||
push @out, $_;
|
||||
}
|
||||
close(C);
|
||||
close(F);
|
||||
|
||||
# longest symbols first
|
||||
my @syms = sort { length($b) <=> length($a) } @asyms;
|
||||
|
||||
# longest cmdline options first
|
||||
my @opts = sort { length($b) <=> length($a) } @aopts;
|
||||
|
||||
sub process {
|
||||
my ($f) = @_;
|
||||
|
||||
my $ignore = 0;
|
||||
my $sepcount = 0;
|
||||
my $out;
|
||||
my $line = 0;
|
||||
open(F, "<$f") or die;
|
||||
|
||||
while(<F>) {
|
||||
$line++;
|
||||
if(/^---/ && ($line == 1)) {
|
||||
$ignore = 1;
|
||||
next;
|
||||
}
|
||||
elsif(/^---/ && $ignore) {
|
||||
$ignore = 0;
|
||||
next;
|
||||
}
|
||||
next if($ignore);
|
||||
|
||||
my $l = $_;
|
||||
|
||||
# strip out backticked words
|
||||
$l =~ s/`[^`]+`//g;
|
||||
|
||||
# **bold**
|
||||
$l =~ s/\*\*(\S.*?)\*\*//g;
|
||||
# *italics*
|
||||
$l =~ s/\*(\S.*?)\*//g;
|
||||
|
||||
# strip out https URLs, we don't want them spellchecked
|
||||
$l =~ s!https://[a-z0-9\#_/.-]+!!gi;
|
||||
|
||||
$out .= $l;
|
||||
}
|
||||
close(F);
|
||||
|
||||
# cut out all known curl cmdline options
|
||||
map { $out =~ s/$_//g; } (@opts);
|
||||
|
||||
# cut out all known curl symbols
|
||||
map { $out =~ s/\b$_\b//g; } (@syms);
|
||||
|
||||
if(!$ignore) {
|
||||
open(O, ">$f") or die;
|
||||
print O $out;
|
||||
close(O);
|
||||
}
|
||||
}
|
||||
|
||||
for my $f (@ARGV) {
|
||||
process($f);
|
||||
if(!$ignore) {
|
||||
open(O, ">$f") or die;
|
||||
print O @out;
|
||||
close(O);
|
||||
}
|
||||
|
||||
86
.github/scripts/cleanspell.pl
vendored
Executable file
86
.github/scripts/cleanspell.pl
vendored
Executable file
@ -0,0 +1,86 @@
|
||||
#!/usr/bin/env perl
|
||||
# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
#
|
||||
# SPDX-License-Identifier: curl
|
||||
#
|
||||
# Given: a libcurl curldown man page
|
||||
# Outputs: the same file, minus the SYNOPSIS and the EXAMPLE sections
|
||||
#
|
||||
|
||||
my $f = $ARGV[0];
|
||||
|
||||
open(F, "<$f") or die;
|
||||
|
||||
my @out;
|
||||
my $ignore = 0;
|
||||
while(<F>) {
|
||||
if($_ =~ /^# (SYNOPSIS|EXAMPLE)/) {
|
||||
$ignore = 1;
|
||||
}
|
||||
elsif($ignore && ($_ =~ /^# [A-Z]/)) {
|
||||
$ignore = 0;
|
||||
}
|
||||
elsif(!$ignore) {
|
||||
# **bold**
|
||||
$_ =~ s/\*\*(\S.*?)\*\*//g;
|
||||
# *italics*
|
||||
$_ =~ s/\*(\S.*?)\*//g;
|
||||
|
||||
$_ =~ s/CURL(M|SH|U|H)code//g;
|
||||
$_ =~ s/CURL_[A-Z0-9_]*//g;
|
||||
$_ =~ s/CURLALTSVC_[A-Z0-9_]*//g;
|
||||
$_ =~ s/CURLAUTH_[A-Z0-9_]*//g;
|
||||
$_ =~ s/CURLE_[A-Z0-9_]*//g;
|
||||
$_ =~ s/CURLFORM_[A-Z0-9_]*//g;
|
||||
$_ =~ s/CURLFTP_[A-Z0-9_]*//g;
|
||||
$_ =~ s/CURLFTPAUTH_[A-Z0-9_]*//g;
|
||||
$_ =~ s/CURLFTPMETHOD_[A-Z0-9_]*//g;
|
||||
$_ =~ s/CURLFTPSSL_[A-Z0-9_]*//g;
|
||||
$_ =~ s/CURLGSSAPI_[A-Z0-9_]*//g;
|
||||
$_ =~ s/CURLHEADER_[A-Z0-9_]*//g;
|
||||
$_ =~ s/CURLINFO_[A-Z0-9_]*//g;
|
||||
$_ =~ s/CURLM_[A-Z0-9_]*//g;
|
||||
$_ =~ s/CURLMIMEOPT_[A-Z0-9_]*//g;
|
||||
$_ =~ s/CURLMOPT_[A-Z0-9_]*//g;
|
||||
$_ =~ s/CURLOPT_[A-Z0-9_]*//g;
|
||||
$_ =~ s/CURLPIPE_[A-Z0-9_]*//g;
|
||||
$_ =~ s/CURLPROTO_[A-Z0-9_]*//g;
|
||||
$_ =~ s/CURLPROXY_[A-Z0-9_]*//g;
|
||||
$_ =~ s/CURLPX_[A-Z0-9_]*//g;
|
||||
$_ =~ s/CURLSHE_[A-Z0-9_]*//g;
|
||||
$_ =~ s/CURLSHOPT_[A-Z0-9_]*//g;
|
||||
$_ =~ s/CURLSSLOPT_[A-Z0-9_]*//g;
|
||||
$_ =~ s/CURLSSH_[A-Z0-9_]*//g;
|
||||
$_ =~ s/CURLSSLBACKEND_[A-Z0-9_]*//g;
|
||||
$_ =~ s/CURLU_[A-Z0-9_]*//g;
|
||||
$_ =~ s/CURLUPART_[A-Z0-9_]*//g;
|
||||
#$_ =~ s/\bCURLU\b//g; # stand-alone CURLU
|
||||
$_ =~ s/CURLUE_[A-Z0-9_]*//g;
|
||||
$_ =~ s/CURLHE_[A-Z0-9_]*//g;
|
||||
$_ =~ s/CURLWS_[A-Z0-9_]*//g;
|
||||
$_ =~ s/CURLKH[A-Z0-9_]*//g;
|
||||
$_ =~ s/CURLUPART_[A-Z0-9_]*//g;
|
||||
$_ =~ s/CURLUSESSL_[A-Z0-9_]*//g;
|
||||
$_ =~ s/CURLPAUSE_[A-Z0-9_]*//g;
|
||||
$_ =~ s/CURLHSTS_[A-Z0-9_]*//g;
|
||||
$_ =~ s/curl_global_([a-z_]*)//g;
|
||||
$_ =~ s/curl_(strequal|strnequal|formadd|waitfd|formget|getdate|formfree)//g;
|
||||
$_ =~ s/curl_easy_([a-z]*)//g;
|
||||
$_ =~ s/curl_multi_([a-z_]*)//g;
|
||||
$_ =~ s/curl_mime_(subparts|addpart|filedata|data_cb)//g;
|
||||
$_ =~ s/curl_ws_(send|recv|meta)//g;
|
||||
$_ =~ s/curl_url_(dup)//g;
|
||||
$_ =~ s/curl_pushheader_by(name|num)//g;
|
||||
$_ =~ s/libcurl-(env|ws)//g;
|
||||
$_ =~ s/libcurl\\-(env|ws)//g;
|
||||
$_ =~ s/(^|\W)((tftp|https|http|ftp):\/\/[a-z0-9\-._~%:\/?\#\[\]\@!\$&'()*+,;=\\]+)//gi;
|
||||
push @out, $_;
|
||||
}
|
||||
}
|
||||
close(F);
|
||||
|
||||
open(O, ">$f") or die;
|
||||
for my $l (@out) {
|
||||
print O $l;
|
||||
}
|
||||
close(O);
|
||||
151
.github/scripts/spellcheck.curl
vendored
151
.github/scripts/spellcheck.curl
vendored
@ -1,151 +0,0 @@
|
||||
# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
#
|
||||
# SPDX-License-Identifier: curl
|
||||
#
|
||||
# common variable types + structs
|
||||
# callback typedefs
|
||||
# public functions names
|
||||
# some man page names
|
||||
curl_fileinfo
|
||||
curl_forms
|
||||
curl_hstsentry
|
||||
curl_httppost
|
||||
curl_index
|
||||
curl_khkey
|
||||
curl_pushheaders
|
||||
curl_waitfd
|
||||
CURLcode
|
||||
CURLformoption
|
||||
CURLHcode
|
||||
CURLMcode
|
||||
CURLMsg
|
||||
CURLSHcode
|
||||
CURLUcode
|
||||
curl_calloc_callback
|
||||
curl_chunk_bgn_callback
|
||||
curl_chunk_end_callback
|
||||
curl_conv_callback
|
||||
curl_debug_callback
|
||||
curl_fnmatch_callback
|
||||
curl_formget_callback
|
||||
curl_free_callback
|
||||
curl_hstsread_callback
|
||||
curl_hstswrite_callback
|
||||
curl_ioctl_callback
|
||||
curl_malloc_callback
|
||||
curl_multi_timer_callback
|
||||
curl_opensocket_callback
|
||||
curl_prereq_callback
|
||||
curl_progress_callback
|
||||
curl_push_callback
|
||||
curl_read_callback
|
||||
curl_realloc_callback
|
||||
curl_resolver_start_callback
|
||||
curl_seek_callback
|
||||
curl_socket_callback
|
||||
curl_sockopt_callback
|
||||
curl_ssl_ctx_callback
|
||||
curl_strdup_callback
|
||||
curl_trailer_callback
|
||||
curl_write_callback
|
||||
curl_xferinfo_callback
|
||||
curl_strequal
|
||||
curl_strnequal
|
||||
curl_mime_init
|
||||
curl_mime_free
|
||||
curl_mime_addpart
|
||||
curl_mime_name
|
||||
curl_mime_filename
|
||||
curl_mime_type
|
||||
curl_mime_encoder
|
||||
curl_mime_data
|
||||
curl_mime_filedata
|
||||
curl_mime_data_cb
|
||||
curl_mime_subparts
|
||||
curl_mime_headers
|
||||
curl_formadd
|
||||
curl_formget
|
||||
curl_formfree
|
||||
curl_getdate
|
||||
curl_getenv
|
||||
curl_version
|
||||
curl_easy_escape
|
||||
curl_escape
|
||||
curl_easy_unescape
|
||||
curl_unescape
|
||||
curl_free
|
||||
curl_global_init
|
||||
curl_global_init_mem
|
||||
curl_global_cleanup
|
||||
curl_global_trace
|
||||
curl_global_sslset
|
||||
curl_slist_append
|
||||
curl_slist_free_all
|
||||
curl_getdate
|
||||
curl_share_init
|
||||
curl_share_setopt
|
||||
curl_share_cleanup
|
||||
curl_version_info
|
||||
curl_easy_strerror
|
||||
curl_share_strerror
|
||||
curl_easy_pause
|
||||
curl_easy_ssls_import
|
||||
curl_easy_ssls_export
|
||||
curl_easy_init
|
||||
curl_easy_setopt
|
||||
curl_easy_perform
|
||||
curl_easy_cleanup
|
||||
curl_easy_getinfo
|
||||
curl_easy_duphandle
|
||||
curl_easy_reset
|
||||
curl_easy_recv
|
||||
curl_easy_send
|
||||
curl_easy_upkeep
|
||||
curl_easy_header
|
||||
curl_easy_nextheader
|
||||
curl_mprintf
|
||||
curl_mfprintf
|
||||
curl_msprintf
|
||||
curl_msnprintf
|
||||
curl_mvprintf
|
||||
curl_mvfprintf
|
||||
curl_mvsprintf
|
||||
curl_mvsnprintf
|
||||
curl_maprintf
|
||||
curl_mvaprintf
|
||||
curl_multi_init
|
||||
curl_multi_add_handle
|
||||
curl_multi_remove_handle
|
||||
curl_multi_fdset
|
||||
curl_multi_waitfds
|
||||
curl_multi_wait
|
||||
curl_multi_poll
|
||||
curl_multi_wakeup
|
||||
curl_multi_perform
|
||||
curl_multi_cleanup
|
||||
curl_multi_info_read
|
||||
curl_multi_strerror
|
||||
curl_multi_socket
|
||||
curl_multi_socket_action
|
||||
curl_multi_socket_all
|
||||
curl_multi_timeout
|
||||
curl_multi_setopt
|
||||
curl_multi_assign
|
||||
curl_multi_get_handles
|
||||
curl_pushheader_bynum
|
||||
curl_pushheader_byname
|
||||
curl_multi_waitfds
|
||||
curl_easy_option_by_name
|
||||
curl_easy_option_by_id
|
||||
curl_easy_option_next
|
||||
curl_url
|
||||
curl_url_cleanup
|
||||
curl_url_dup
|
||||
curl_url_get
|
||||
curl_url_set
|
||||
curl_url_strerror
|
||||
curl_ws_recv
|
||||
curl_ws_send
|
||||
curl_ws_meta
|
||||
libcurl-env
|
||||
libcurl-ws
|
||||
2
.github/scripts/spellcheck.words
vendored
2
.github/scripts/spellcheck.words
vendored
@ -251,7 +251,6 @@ Feltzing
|
||||
ffi
|
||||
filesize
|
||||
filesystem
|
||||
FindCURL
|
||||
FLOSS
|
||||
fnmatch
|
||||
footguns
|
||||
@ -951,6 +950,7 @@ winbuild
|
||||
WinIDN
|
||||
WinLDAP
|
||||
winsock
|
||||
winssl
|
||||
Wireshark
|
||||
wolfSSH
|
||||
wolfSSL
|
||||
|
||||
16
.github/workflows/checkdocs.yml
vendored
16
.github/workflows/checkdocs.yml
vendored
@ -107,8 +107,20 @@ jobs:
|
||||
persist-credentials: false
|
||||
name: checkout
|
||||
|
||||
- name: trim all *.md files in docs/
|
||||
run: .github/scripts/cleancmd.pl $(find docs -name "*.md")
|
||||
- name: trim all man page *.md files
|
||||
run: find docs -name "*.md" ! -name "_*" -print0 | xargs -0 -n1 .github/scripts/cleancmd.pl
|
||||
|
||||
- name: trim libcurl man page *.md files
|
||||
run: find docs/libcurl \( -name "curl_*.md" -o -name "libcurl*.md" \) -print0 | xargs -0 -n1 .github/scripts/cleanspell.pl
|
||||
|
||||
- name: trim libcurl option man page *.md files
|
||||
run: find docs/libcurl/opts -name "CURL*.md" -print0 | xargs -0 -n1 .github/scripts/cleanspell.pl
|
||||
|
||||
- name: trim cmdline docs markdown _*.md files
|
||||
run: find docs/cmdline-opts -name "_*.md" -print0 | xargs -0 -n1 .github/scripts/cleancmd.pl --no-header
|
||||
|
||||
- name: trim docs/ markdown _*.md files
|
||||
run: git ls-files docs/*.md docs/internals/*.md | xargs -n1 .github/scripts/cleancmd.pl --no-header
|
||||
|
||||
- name: setup the custom wordlist
|
||||
run: grep -v '^#' .github/scripts/spellcheck.words > wordlist.txt
|
||||
|
||||
23
.github/workflows/distcheck.yml
vendored
23
.github/workflows/distcheck.yml
vendored
@ -19,9 +19,6 @@ concurrency:
|
||||
|
||||
permissions: {}
|
||||
|
||||
env:
|
||||
MAKEFLAGS: -j 5
|
||||
|
||||
jobs:
|
||||
maketgz-and-verify-in-tree:
|
||||
runs-on: ubuntu-latest
|
||||
@ -46,7 +43,7 @@ jobs:
|
||||
- name: 'maketgz'
|
||||
run: SOURCE_DATE_EPOCH=1711526400 ./scripts/maketgz 99.98.97
|
||||
|
||||
- uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4
|
||||
- uses: actions/upload-artifact@4cec3d8aa04e39d1a68397de0c4cd6fb9dce8ec1 # v4
|
||||
with:
|
||||
name: 'release-tgz'
|
||||
path: 'curl-99.98.97.tar.gz'
|
||||
@ -58,9 +55,9 @@ jobs:
|
||||
tar xvf curl-99.98.97.tar.gz
|
||||
pushd curl-99.98.97
|
||||
./configure --prefix=$HOME/temp --without-ssl --without-libpsl
|
||||
make
|
||||
make test-ci
|
||||
make install
|
||||
make -j5
|
||||
make -j5 test-ci
|
||||
make -j5 install
|
||||
popd
|
||||
# basic check of the installed files
|
||||
bash scripts/installcheck.sh $HOME/temp
|
||||
@ -83,8 +80,8 @@ jobs:
|
||||
mkdir build
|
||||
pushd build
|
||||
../curl-99.98.97/configure --without-ssl --without-libpsl
|
||||
make
|
||||
make test-ci
|
||||
make -j5
|
||||
make -j5 test-ci
|
||||
popd
|
||||
rm -rf build
|
||||
rm -rf curl-99.98.97
|
||||
@ -106,9 +103,9 @@ jobs:
|
||||
mkdir build
|
||||
pushd build
|
||||
../configure --without-ssl --enable-debug "--prefix=${PWD}/pkg" --without-libpsl
|
||||
make
|
||||
make test-ci
|
||||
make install
|
||||
make -j5
|
||||
make -j5 test-ci
|
||||
make -j5 install
|
||||
|
||||
verify-out-of-tree-cmake:
|
||||
runs-on: ubuntu-latest
|
||||
@ -125,7 +122,7 @@ jobs:
|
||||
tar xvf curl-99.98.97.tar.gz
|
||||
pushd curl-99.98.97
|
||||
cmake -B build -DCURL_WERROR=ON -DCURL_USE_LIBPSL=OFF
|
||||
make -C build
|
||||
make -C build -j5
|
||||
|
||||
missing-files:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
50
.github/workflows/http3-linux.yml
vendored
50
.github/workflows/http3-linux.yml
vendored
@ -232,7 +232,6 @@ jobs:
|
||||
--with-ngtcp2=$HOME/ngtcp2/build --enable-warnings --enable-werror --enable-debug --disable-ntlm
|
||||
--with-test-nghttpx="$HOME/nghttp2/build/bin/nghttpx"
|
||||
--with-openssl=$HOME/quictls/build --enable-ssls-export
|
||||
--with-libuv
|
||||
|
||||
- name: gnutls
|
||||
PKG_CONFIG_PATH: '$HOME/gnutls/build/lib/pkgconfig:$HOME/nghttp3/build/lib/pkgconfig:$HOME/ngtcp2/build/lib/pkgconfig:$HOME/nghttp2/build/lib/pkgconfig'
|
||||
@ -241,7 +240,6 @@ jobs:
|
||||
--with-ngtcp2=$HOME/ngtcp2/build --enable-warnings --enable-werror --enable-debug
|
||||
--with-test-nghttpx="$HOME/nghttp2/build/bin/nghttpx"
|
||||
--with-gnutls=$HOME/gnutls/build --enable-ssls-export
|
||||
--with-libuv
|
||||
|
||||
- name: wolfssl
|
||||
PKG_CONFIG_PATH: '$HOME/wolfssl/build/lib/pkgconfig:$HOME/nghttp3/build/lib/pkgconfig:$HOME/ngtcp2/build/lib/pkgconfig:$HOME/nghttp2/build/lib/pkgconfig'
|
||||
@ -251,7 +249,6 @@ jobs:
|
||||
--with-test-nghttpx="$HOME/nghttp2/build/bin/nghttpx"
|
||||
--with-wolfssl=$HOME/wolfssl/build
|
||||
--enable-ech --enable-ssls-export
|
||||
--with-libuv
|
||||
|
||||
- name: wolfssl
|
||||
PKG_CONFIG_PATH: '$HOME/wolfssl/build/lib/pkgconfig:$HOME/nghttp3/build/lib/pkgconfig:$HOME/ngtcp2/build/lib/pkgconfig:$HOME/nghttp2/build/lib/pkgconfig'
|
||||
@ -260,7 +257,6 @@ jobs:
|
||||
-DTEST_NGHTTPX="$HOME/nghttp2/build/bin/nghttpx"
|
||||
-DHTTPD_NGHTTPX="$HOME/nghttp2/build/bin/nghttpx"
|
||||
-DUSE_ECH=ON
|
||||
-DCURL_USE_LIBUV=ON
|
||||
|
||||
- name: openssl-quic
|
||||
PKG_CONFIG_PATH: '$HOME/openssl/build/lib64/pkgconfig'
|
||||
@ -270,7 +266,6 @@ jobs:
|
||||
--with-test-nghttpx="$HOME/nghttp2/build/bin/nghttpx"
|
||||
--with-openssl=$HOME/openssl/build --with-openssl-quic
|
||||
--with-nghttp3=$HOME/nghttp3/build
|
||||
--with-libuv
|
||||
|
||||
- name: quiche
|
||||
configure: >-
|
||||
@ -280,7 +275,6 @@ jobs:
|
||||
--with-quiche=$HOME/quiche/target/release
|
||||
--with-test-nghttpx="$HOME/nghttp2/build/bin/nghttpx"
|
||||
--with-ca-fallback
|
||||
--with-libuv
|
||||
|
||||
- name: quiche
|
||||
PKG_CONFIG_PATH: '$HOME/quiche/target/release'
|
||||
@ -290,7 +284,6 @@ jobs:
|
||||
-DTEST_NGHTTPX="$HOME/nghttp2/build/bin/nghttpx"
|
||||
-DHTTPD_NGHTTPX="$HOME/nghttp2/build/bin/nghttpx"
|
||||
-DCURL_CA_FALLBACK=ON
|
||||
-DCURL_USE_LIBUV=ON
|
||||
|
||||
steps:
|
||||
- name: 'install prereqs'
|
||||
@ -302,7 +295,7 @@ jobs:
|
||||
libpsl-dev libbrotli-dev libzstd-dev zlib1g-dev libev-dev libc-ares-dev \
|
||||
nettle-dev libp11-kit-dev libtspi-dev libunistring-dev guile-2.2-dev libtasn1-bin \
|
||||
libtasn1-6-dev libidn2-0-dev gawk gperf libtss2-dev dns-root-data bison gtk-doc-tools \
|
||||
texinfo texlive texlive-extra-utils autopoint libev-dev libuv1-dev \
|
||||
texinfo texlive texlive-extra-utils autopoint libev-dev \
|
||||
apache2 apache2-dev libnghttp2-dev vsftpd
|
||||
python3 -m venv $HOME/venv
|
||||
echo 'CC=gcc-12' >> $GITHUB_ENV
|
||||
@ -434,45 +427,46 @@ jobs:
|
||||
export PKG_CONFIG_PATH="${{ matrix.build.PKG_CONFIG_PATH }}"
|
||||
fi
|
||||
if [ -n '${{ matrix.build.generate }}' ]; then
|
||||
cmake -B bld -G Ninja \
|
||||
cmake -B . -G Ninja \
|
||||
-DCMAKE_C_COMPILER_TARGET=$(uname -m)-pc-linux-gnu -DBUILD_STATIC_LIBS=ON \
|
||||
-DCMAKE_UNITY_BUILD=ON -DCURL_TEST_BUNDLES=ON -DCURL_WERROR=ON \
|
||||
${{ matrix.build.generate }}
|
||||
else
|
||||
mkdir bld && cd bld && ../configure --enable-unity --enable-test-bundles --enable-warnings --enable-werror \
|
||||
--disable-dependency-tracking \
|
||||
./configure --disable-dependency-tracking --enable-unity --enable-test-bundles --enable-warnings --enable-werror \
|
||||
${{ matrix.build.configure }}
|
||||
fi
|
||||
|
||||
- name: 'configure log'
|
||||
if: ${{ !cancelled() }}
|
||||
run: cat bld/config.log bld/CMakeFiles/CMakeConfigureLog.yaml 2>/dev/null || true
|
||||
run: cat config.log CMakeFiles/CMakeConfigureLog.yaml 2>/dev/null || true
|
||||
|
||||
- name: 'curl_config.h'
|
||||
run: |
|
||||
echo '::group::raw'; cat bld/lib/curl_config.h || true; echo '::endgroup::'
|
||||
grep -F '#define' bld/lib/curl_config.h | sort || true
|
||||
echo '::group::raw'; cat lib/curl_config.h || true; echo '::endgroup::'
|
||||
grep -F '#define' lib/curl_config.h | sort || true
|
||||
|
||||
- name: 'test configs'
|
||||
run: grep -H -v '^#' bld/tests/config bld/tests/http/config.ini || true
|
||||
run: |
|
||||
cat tests/config || true
|
||||
cat tests/http/config.ini || true
|
||||
|
||||
- name: 'build'
|
||||
run: |
|
||||
if [ -n '${{ matrix.build.generate }}' ]; then
|
||||
cmake --build bld --verbose
|
||||
cmake --build . --verbose
|
||||
else
|
||||
make -C bld V=1
|
||||
make V=1
|
||||
fi
|
||||
|
||||
- name: 'check curl -V output'
|
||||
run: bld/src/curl -V
|
||||
run: ./src/curl -V
|
||||
|
||||
- name: 'build tests'
|
||||
run: |
|
||||
if [ -n '${{ matrix.build.generate }}' ]; then
|
||||
cmake --build bld --verbose --target testdeps
|
||||
cmake --build . --verbose --target testdeps
|
||||
else
|
||||
make -C bld V=1 -C tests
|
||||
make V=1 -C tests
|
||||
fi
|
||||
|
||||
- name: 'install test prereqs'
|
||||
@ -486,9 +480,9 @@ jobs:
|
||||
run: |
|
||||
source $HOME/venv/bin/activate
|
||||
if [ -n '${{ matrix.build.generate }}' ]; then
|
||||
cmake --build bld --verbose --target test-ci
|
||||
cmake --build . --verbose --target test-ci
|
||||
else
|
||||
make -C bld V=1 test-ci
|
||||
make V=1 test-ci
|
||||
fi
|
||||
|
||||
- name: 'install pytest prereqs'
|
||||
@ -496,23 +490,23 @@ jobs:
|
||||
source $HOME/venv/bin/activate
|
||||
python3 -m pip install -r tests/http/requirements.txt
|
||||
|
||||
- name: 'run pytest event based'
|
||||
- name: 'run pytest'
|
||||
env:
|
||||
CURL_TEST_EVENT: 1
|
||||
TFLAGS: '${{ matrix.build.tflags }}'
|
||||
CURL_CI: github
|
||||
PYTEST_ADDOPTS: '--color=yes'
|
||||
run: |
|
||||
source $HOME/venv/bin/activate
|
||||
if [ -n '${{ matrix.build.generate }}' ]; then
|
||||
cmake --build bld --verbose --target curl-pytest-ci
|
||||
cmake --build . --verbose --target curl-pytest-ci
|
||||
else
|
||||
make -C bld V=1 pytest-ci
|
||||
make V=1 pytest-ci
|
||||
fi
|
||||
|
||||
- name: 'build examples'
|
||||
run: |
|
||||
if [ -n '${{ matrix.build.generate }}' ]; then
|
||||
cmake --build bld --verbose --target curl-examples
|
||||
cmake --build . --verbose --target curl-examples
|
||||
else
|
||||
make -C bld V=1 examples
|
||||
make V=1 examples
|
||||
fi
|
||||
|
||||
55
.github/workflows/linux.yml
vendored
55
.github/workflows/linux.yml
vendored
@ -304,8 +304,7 @@ jobs:
|
||||
libtool autoconf automake pkgconf ninja-build \
|
||||
${{ matrix.build.install_steps != 'skipall' && matrix.build.install_steps != 'skiprun' && 'stunnel4' || '' }} \
|
||||
libpsl-dev libbrotli-dev libzstd-dev \
|
||||
${{ matrix.build.install_packages }} \
|
||||
${{ contains(matrix.build.install_steps, 'pytest') && 'apache2 apache2-dev libnghttp2-dev vsftpd' || '' }}
|
||||
${{ matrix.build.install_packages }}
|
||||
python3 -m venv $HOME/venv
|
||||
|
||||
- name: 'install prereqs'
|
||||
@ -320,6 +319,11 @@ jobs:
|
||||
${{ matrix.build.install_packages }}
|
||||
python3 -m venv $HOME/venv
|
||||
|
||||
- name: 'install prereqs for pytest'
|
||||
if: contains(matrix.build.install_steps, 'pytest')
|
||||
run: |
|
||||
sudo apt-get -o Dpkg::Use-Pty=0 install apache2 apache2-dev libnghttp2-dev vsftpd
|
||||
|
||||
- name: 'install dependencies'
|
||||
if: startsWith(matrix.build.container, 'alpine')
|
||||
run: |
|
||||
@ -556,7 +560,7 @@ jobs:
|
||||
cd $HOME
|
||||
curl -sSf --compressed https://sh.rustup.rs/ | sh -s -- -y
|
||||
source $HOME/.cargo/env
|
||||
rustup toolchain install stable --profile minimal
|
||||
rustup toolchain install nightly
|
||||
|
||||
- name: 'build rustls'
|
||||
if: contains(matrix.build.install_steps, 'rustls') && steps.cache-rustls.outputs.cache-hit != 'true'
|
||||
@ -589,37 +593,37 @@ jobs:
|
||||
export PKG_CONFIG_PATH="${{ matrix.build.PKG_CONFIG_PATH }}"
|
||||
fi
|
||||
if [ -n '${{ matrix.build.generate }}' ]; then
|
||||
cmake -B bld -G Ninja \
|
||||
cmake -B . -G Ninja \
|
||||
-DCMAKE_INSTALL_PREFIX="$HOME/curl" \
|
||||
-DCMAKE_C_COMPILER_TARGET=$(uname -m)-pc-linux-gnu -DBUILD_STATIC_LIBS=ON \
|
||||
-DCMAKE_UNITY_BUILD=ON -DCURL_TEST_BUNDLES=ON -DCURL_WERROR=ON \
|
||||
${{ matrix.build.generate }}
|
||||
else
|
||||
mkdir bld && cd bld && \
|
||||
${{ matrix.build.configure-prefix }} \
|
||||
../configure --enable-unity --enable-test-bundles --enable-warnings --enable-werror \
|
||||
--disable-dependency-tracking \
|
||||
./configure --disable-dependency-tracking --enable-unity --enable-test-bundles --enable-warnings --enable-werror \
|
||||
${{ matrix.build.configure }}
|
||||
fi
|
||||
|
||||
- name: 'configure log'
|
||||
if: ${{ !cancelled() }}
|
||||
run: cat bld/config.log bld/CMakeFiles/CMakeConfigureLog.yaml 2>/dev/null || true
|
||||
run: cat config.log CMakeFiles/CMakeConfigureLog.yaml 2>/dev/null || true
|
||||
|
||||
- name: 'curl_config.h'
|
||||
run: |
|
||||
echo '::group::raw'; cat bld/lib/curl_config.h || true; echo '::endgroup::'
|
||||
grep -F '#define' bld/lib/curl_config.h | sort || true
|
||||
echo '::group::raw'; cat lib/curl_config.h || true; echo '::endgroup::'
|
||||
grep -F '#define' lib/curl_config.h | sort || true
|
||||
|
||||
- name: 'test configs'
|
||||
run: grep -H -v '^#' bld/tests/config bld/tests/http/config.ini || true
|
||||
run: |
|
||||
cat tests/config || true
|
||||
cat tests/http/config.ini || true
|
||||
|
||||
- name: 'build'
|
||||
run: |
|
||||
if [ -n '${{ matrix.build.generate }}' ]; then
|
||||
${{ matrix.build.make-prefix }} cmake --build bld --verbose
|
||||
${{ matrix.build.make-prefix }} cmake --build . --verbose
|
||||
else
|
||||
${{ matrix.build.make-prefix }} make -C bld V=1 ${{ matrix.build.make-custom-target }}
|
||||
${{ matrix.build.make-prefix }} make V=1 ${{ matrix.build.make-custom-target }}
|
||||
fi
|
||||
|
||||
- name: 'single-use function check'
|
||||
@ -627,27 +631,27 @@ jobs:
|
||||
run: |
|
||||
git config --global --add safe.directory "*"
|
||||
if [ -n '${{ matrix.build.generate }}' ]; then
|
||||
libcurla=bld/lib/libcurl.a
|
||||
libcurla=lib/libcurl.a
|
||||
else
|
||||
libcurla=bld/lib/.libs/libcurl.a
|
||||
libcurla=lib/.libs/libcurl.a
|
||||
fi
|
||||
./scripts/singleuse.pl --unit ${libcurla}
|
||||
|
||||
- name: 'check curl -V output'
|
||||
if: ${{ matrix.build.make-custom-target != 'tidy' }}
|
||||
run: bld/src/curl -V
|
||||
run: ./src/curl -V
|
||||
|
||||
- name: 'cmake install'
|
||||
if: ${{ matrix.build.generate }}
|
||||
run: cmake --install bld --strip
|
||||
run: cmake --install . --strip
|
||||
|
||||
- name: 'build tests'
|
||||
if: ${{ matrix.build.install_steps != 'skipall' }}
|
||||
run: |
|
||||
if [ -n '${{ matrix.build.generate }}' ]; then
|
||||
cmake --build bld --verbose --target testdeps
|
||||
cmake --build . --verbose --target testdeps
|
||||
else
|
||||
make -C bld V=1 -C tests
|
||||
make V=1 -C tests
|
||||
fi
|
||||
|
||||
- name: 'install test prereqs'
|
||||
@ -674,9 +678,9 @@ jobs:
|
||||
fi
|
||||
[ -x "$HOME/venv/bin/activate" ] && source $HOME/venv/bin/activate
|
||||
if [ -n '${{ matrix.build.generate }}' ]; then
|
||||
cmake --build bld --verbose --target ${{ matrix.build.torture && 'test-torture' || 'test-ci' }}
|
||||
cmake --build . --verbose --target ${{ matrix.build.torture && 'test-torture' || 'test-ci' }}
|
||||
else
|
||||
make -C bld V=1 ${{ matrix.build.torture && 'test-torture' || 'test-ci' }}
|
||||
make V=1 ${{ matrix.build.torture && 'test-torture' || 'test-ci' }}
|
||||
fi
|
||||
|
||||
- name: 'install pytest prereqs'
|
||||
@ -688,21 +692,22 @@ jobs:
|
||||
- name: 'run pytest'
|
||||
if: contains(matrix.build.install_steps, 'pytest')
|
||||
env:
|
||||
TFLAGS: '${{ matrix.build.tflags }}'
|
||||
CURL_CI: github
|
||||
PYTEST_ADDOPTS: '--color=yes'
|
||||
run: |
|
||||
[ -x "$HOME/venv/bin/activate" ] && source $HOME/venv/bin/activate
|
||||
if [ -n '${{ matrix.build.generate }}' ]; then
|
||||
cmake --build bld --verbose --target curl-pytest-ci
|
||||
cmake --build . --verbose --target curl-pytest-ci
|
||||
else
|
||||
make -C bld V=1 pytest-ci
|
||||
make V=1 pytest-ci
|
||||
fi
|
||||
|
||||
- name: 'build examples'
|
||||
if: ${{ matrix.build.make-custom-target != 'tidy' }}
|
||||
run: |
|
||||
if [ -n '${{ matrix.build.generate }}' ]; then
|
||||
${{ matrix.build.make-prefix }} cmake --build bld --verbose --target curl-examples
|
||||
${{ matrix.build.make-prefix }} cmake --build . --verbose --target curl-examples
|
||||
else
|
||||
${{ matrix.build.make-prefix }} make -C bld V=1 examples
|
||||
${{ matrix.build.make-prefix }} make V=1 examples
|
||||
fi
|
||||
|
||||
19
.github/workflows/macos.yml
vendored
19
.github/workflows/macos.yml
vendored
@ -47,8 +47,8 @@ permissions: {}
|
||||
# newer than the 10.8 required by `CFURLCreateDataAndPropertiesFromResource`.
|
||||
|
||||
env:
|
||||
MAKEFLAGS: -j 4
|
||||
LDFLAGS: -w # suppress 'object file was built for newer macOS version than being linked' warnings
|
||||
MAKEFLAGS: -j 4
|
||||
|
||||
jobs:
|
||||
macos:
|
||||
@ -123,10 +123,9 @@ jobs:
|
||||
compiler: clang
|
||||
configure: --enable-debug --with-openssl=$(brew --prefix openssl)
|
||||
tflags: --test-event
|
||||
- name: 'quictls libssh2 !ldap 10.15'
|
||||
- name: 'OpenSSL libssh2 !ldap 10.15'
|
||||
compiler: clang
|
||||
install: quictls
|
||||
configure: --enable-debug --disable-ldap --with-openssl=$(brew --prefix quictls) LDFLAGS="${LDFLAGS} -L$(brew --prefix quictls)/lib"
|
||||
configure: --enable-debug --disable-ldap --with-openssl=$(brew --prefix openssl)
|
||||
macos-version-min: '10.15'
|
||||
# cmake
|
||||
- name: 'OpenSSL gsasl rtmp AppleIDN'
|
||||
@ -137,9 +136,9 @@ jobs:
|
||||
generate: -DOPENSSL_ROOT_DIR=$(brew --prefix openssl) -DUSE_APPLE_IDN=ON -DCURL_CLANG_TIDY=ON -DCLANG_TIDY=$(brew --prefix llvm)/bin/clang-tidy
|
||||
clang-tidy: true
|
||||
chkprefill: _chkprefill
|
||||
- name: 'quictls +static libssh +examples'
|
||||
install: quictls libssh
|
||||
generate: -DOPENSSL_ROOT_DIR=$(brew --prefix quictls) -DBUILD_STATIC_LIBS=ON -DCURL_USE_LIBSSH2=OFF -DCURL_USE_LIBSSH=ON
|
||||
- name: 'OpenSSL +static libssh +examples'
|
||||
install: libssh
|
||||
generate: -DOPENSSL_ROOT_DIR=$(brew --prefix openssl) -DBUILD_STATIC_LIBS=ON -DCURL_USE_LIBSSH2=OFF -DCURL_USE_LIBSSH=ON
|
||||
- name: 'SecureTransport debug'
|
||||
generate: -DCURL_USE_SECTRANSP=ON -DENABLE_DEBUG=ON
|
||||
macos-version-min: '10.8'
|
||||
@ -185,12 +184,11 @@ jobs:
|
||||
run: |
|
||||
echo ${{ matrix.build.generate && 'ninja' || 'automake libtool' }} \
|
||||
pkgconf libpsl libssh2 \
|
||||
${{ !matrix.build.clang-tidy && 'libnghttp2 stunnel' || '' }} \
|
||||
${{ !matrix.build.clang-tidy && 'nghttp2 stunnel' || '' }} \
|
||||
${{ matrix.build.install }} | xargs -Ix -n1 echo brew '"x"' > /tmp/Brewfile
|
||||
while [[ $? == 0 ]]; do for i in 1 2 3; do brew update && brew bundle install --no-lock --file /tmp/Brewfile && break 2 || { echo Error: wait to try again; sleep 10; } done; false Too many retries; done
|
||||
|
||||
- name: 'brew unlink openssl'
|
||||
if: ${{ contains(matrix.build.install, 'libressl') || contains(matrix.build.install, 'quictls') }}
|
||||
run: |
|
||||
if test -d $(brew --prefix)/include/openssl; then
|
||||
brew unlink openssl
|
||||
@ -315,6 +313,7 @@ jobs:
|
||||
if [ -z '${{ matrix.build.torture }}' ]; then
|
||||
TFLAGS+=' ~2037 ~2041' # flaky
|
||||
if [[ '${{ matrix.compiler }}' = 'gcc'* ]]; then
|
||||
TFLAGS+=' ~RTSP' # 567 568 569 570 571 572 577 689 3100
|
||||
TFLAGS+=' ~1156 ~1539' # HTTP Content-Range, Content-Length
|
||||
if [[ -n '${{ matrix.build.configure }}' || \
|
||||
'${{ matrix.build.generate }}' = *'-DCURL_USE_SECTRANSP=ON'* ]]; then
|
||||
@ -345,7 +344,7 @@ jobs:
|
||||
if: ${{ contains(matrix.build.name, '+examples') }}
|
||||
run: |
|
||||
if [ -n '${{ matrix.build.generate }}' ]; then
|
||||
cmake --build bld --verbose --target curl-examples
|
||||
cmake --build bld --target curl-examples --verbose
|
||||
else
|
||||
make -C bld examples V=1
|
||||
fi
|
||||
|
||||
82
.github/workflows/non-native.yml
vendored
82
.github/workflows/non-native.yml
vendored
@ -59,21 +59,21 @@ jobs:
|
||||
time cmake -B bld -G Ninja \
|
||||
-DCMAKE_UNITY_BUILD=ON -DCURL_TEST_BUNDLES=ON \
|
||||
-DCURL_WERROR=ON \
|
||||
-DENABLE_DEBUG=ON -DCMAKE_BUILD_TYPE=Debug \
|
||||
-DENABLE_DEBUG=ON -DCMAKE_BUILD_TYPE=Debug -DCMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG= \
|
||||
-DCURL_USE_OPENSSL=ON \
|
||||
-DCURL_USE_GSSAPI=ON \
|
||||
|| { cat bld/CMakeFiles/CMake*.yaml; false; }
|
||||
echo '::group::curl_config.h (raw)'; cat bld/lib/curl_config.h || true; echo '::endgroup::'
|
||||
echo '::group::curl_config.h'; grep -F '#define' bld/lib/curl_config.h | sort || true; echo '::endgroup::'
|
||||
time cmake --build bld
|
||||
time cmake --build bld --config Debug
|
||||
bld/src/curl --disable --version
|
||||
if [ '${{ matrix.arch }}' = 'x86_64' ]; then # Slow on emulated CPU
|
||||
time cmake --build bld --target testdeps
|
||||
time cmake --build bld --config Debug --target testdeps
|
||||
export TFLAGS='-j4'
|
||||
time cmake --build bld --target test-ci
|
||||
time cmake --build bld --config Debug --target test-ci
|
||||
fi
|
||||
echo '::group::build examples'
|
||||
time cmake --build bld --target curl-examples
|
||||
time cmake --build bld --config Debug --target curl-examples
|
||||
echo '::endgroup::'
|
||||
|
||||
openbsd:
|
||||
@ -100,20 +100,20 @@ jobs:
|
||||
time cmake -B bld -G Ninja \
|
||||
-DCMAKE_UNITY_BUILD=ON -DCURL_TEST_BUNDLES=ON \
|
||||
-DCURL_WERROR=ON \
|
||||
-DENABLE_DEBUG=ON -DCMAKE_BUILD_TYPE=Debug \
|
||||
-DENABLE_DEBUG=ON -DCMAKE_BUILD_TYPE=Debug -DCMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG= \
|
||||
-DCURL_USE_OPENSSL=ON \
|
||||
|| { cat bld/CMakeFiles/CMake*.yaml; false; }
|
||||
echo '::group::curl_config.h (raw)'; cat bld/lib/curl_config.h || true; echo '::endgroup::'
|
||||
echo '::group::curl_config.h'; grep -F '#define' bld/lib/curl_config.h | sort || true; echo '::endgroup::'
|
||||
time cmake --build bld
|
||||
time cmake --build bld --config Debug
|
||||
bld/src/curl --disable --version
|
||||
if [ '${{ matrix.arch }}' = 'x86_64' ]; then # Slow on emulated CPU
|
||||
time cmake --build bld --target testdeps
|
||||
time cmake --build bld --config Debug --target testdeps
|
||||
export TFLAGS='-j8 ~3017 ~TFTP ~FTP' # FIXME: TFTP requests executed twice? Related: `curl: (69) TFTP: Access Violation`?
|
||||
time cmake --build bld --target test-ci
|
||||
time cmake --build bld --config Debug --target test-ci
|
||||
fi
|
||||
echo '::group::build examples'
|
||||
time cmake --build bld --target curl-examples
|
||||
time cmake --build bld --config Debug --target curl-examples
|
||||
echo '::endgroup::'
|
||||
|
||||
freebsd:
|
||||
@ -140,7 +140,6 @@ jobs:
|
||||
version: '14.1'
|
||||
architecture: ${{ matrix.arch }}
|
||||
run: |
|
||||
export MAKEFLAGS=-j3
|
||||
# https://ports.freebsd.org/
|
||||
time sudo pkg install -y autoconf automake libtool \
|
||||
pkgconf brotli openldap26-client libidn2 libnghttp2 stunnel py311-impacket
|
||||
@ -155,18 +154,18 @@ jobs:
|
||||
|| { tail -n 1000 config.log; false; }
|
||||
echo '::group::curl_config.h (raw)'; cat lib/curl_config.h || true; echo '::endgroup::'
|
||||
echo '::group::curl_config.h'; grep -F '#define' lib/curl_config.h | sort || true; echo '::endgroup::'
|
||||
time make install
|
||||
time make -j3 install
|
||||
src/curl --disable --version
|
||||
desc='${{ matrix.desc }}'
|
||||
if [ '${{ matrix.arch }}' = 'x86_64' ]; then # Slow on emulated CPU
|
||||
time make -C tests
|
||||
time make -j3 -C tests
|
||||
if [ "${desc#*!runtests*}" = "${desc}" ]; then
|
||||
time make test-ci V=1 TFLAGS='-j4'
|
||||
fi
|
||||
fi
|
||||
if [ "${desc#*!examples*}" = "${desc}" ]; then
|
||||
echo '::group::build examples'
|
||||
time make examples
|
||||
time make -j3 examples
|
||||
echo '::endgroup::'
|
||||
fi
|
||||
|
||||
@ -185,25 +184,25 @@ jobs:
|
||||
-DCMAKE_C_COMPILER='${{ matrix.compiler }}' \
|
||||
-DCMAKE_UNITY_BUILD=ON -DCURL_TEST_BUNDLES=ON \
|
||||
-DCURL_WERROR=ON \
|
||||
-DENABLE_DEBUG=ON -DCMAKE_BUILD_TYPE=Debug \
|
||||
-DENABLE_DEBUG=ON -DCMAKE_BUILD_TYPE=Debug -DCMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG= \
|
||||
-DCURL_USE_OPENSSL=ON \
|
||||
-DCURL_USE_GSSAPI=ON \
|
||||
${{ matrix.options }} \
|
||||
|| { cat bld/CMakeFiles/CMake*.yaml; false; }
|
||||
echo '::group::curl_config.h (raw)'; cat bld/lib/curl_config.h || true; echo '::endgroup::'
|
||||
echo '::group::curl_config.h'; grep -F '#define' bld/lib/curl_config.h | sort || true; echo '::endgroup::'
|
||||
time cmake --build bld
|
||||
time cmake --build bld --config Debug
|
||||
bld/src/curl --disable --version
|
||||
desc='${{ matrix.desc }}'
|
||||
if [ '${{ matrix.arch }}' = 'x86_64' ]; then # Slow on emulated CPU
|
||||
time cmake --build bld --target testdeps
|
||||
time cmake --build bld --config Debug --target testdeps
|
||||
if [ "${desc#*!runtests*}" = "${desc}" ]; then
|
||||
time cmake --build bld --target test-ci
|
||||
time cmake --build bld --config Debug --target test-ci
|
||||
fi
|
||||
fi
|
||||
if [ "${desc#*!examples*}" = "${desc}" ]; then
|
||||
echo '::group::build examples'
|
||||
time cmake --build bld --target curl-examples
|
||||
time cmake --build bld --config Debug --target curl-examples
|
||||
echo '::endgroup::'
|
||||
fi
|
||||
|
||||
@ -224,7 +223,6 @@ jobs:
|
||||
run: |
|
||||
set -e
|
||||
ln -s /usr/bin/gcpp /usr/bin/cpp # Some tests expect `cpp`, which is named `gcpp` in this env.
|
||||
export MAKEFLAGS=-j3
|
||||
time autoreconf -fi
|
||||
mkdir bld && cd bld && time ../configure --enable-unity --enable-test-bundles --enable-debug --enable-warnings --enable-werror \
|
||||
--prefix="${HOME}"/install \
|
||||
@ -233,12 +231,12 @@ jobs:
|
||||
|| { tail -n 1000 config.log; false; }
|
||||
echo '::group::curl_config.h (raw)'; cat lib/curl_config.h || true; echo '::endgroup::'
|
||||
echo '::group::curl_config.h'; grep -F '#define' lib/curl_config.h | sort || true; echo '::endgroup::'
|
||||
time gmake install
|
||||
time gmake -j3 install
|
||||
src/curl --disable --version
|
||||
time gmake -C tests
|
||||
time gmake -j3 -C tests
|
||||
time gmake test-ci V=1
|
||||
echo '::group::build examples'
|
||||
time gmake examples
|
||||
time gmake -j3 examples
|
||||
echo '::endgroup::'
|
||||
|
||||
ios:
|
||||
@ -246,9 +244,9 @@ jobs:
|
||||
runs-on: 'macos-latest'
|
||||
timeout-minutes: 10
|
||||
env:
|
||||
MAKEFLAGS: -j 4
|
||||
DEVELOPER_DIR: "/Applications/Xcode${{ matrix.build.xcode && format('_{0}', matrix.build.xcode) || '' }}.app/Contents/Developer"
|
||||
CC: ${{ matrix.build.compiler || 'clang' }}
|
||||
MAKEFLAGS: -j 4
|
||||
# renovate: datasource=github-tags depName=libressl-portable/portable versioning=semver registryUrl=https://github.com
|
||||
libressl-version: 4.0.0
|
||||
strategy:
|
||||
@ -263,7 +261,6 @@ jobs:
|
||||
install_steps: libressl
|
||||
# FIXME: Could not make OPENSSL_ROOT_DIR work. CMake seems to prepend sysroot to it.
|
||||
generate: >-
|
||||
-DCMAKE_BUILD_TYPE=Release -DCMAKE_UNITY_BUILD_BATCH_SIZE=50
|
||||
-DOPENSSL_INCLUDE_DIR="$HOME/libressl/include"
|
||||
-DOPENSSL_SSL_LIBRARY="$HOME/libressl/lib/libssl.a"
|
||||
-DOPENSSL_CRYPTO_LIBRARY="$HOME/libressl/lib/libcrypto.a"
|
||||
@ -272,7 +269,6 @@ jobs:
|
||||
- name: 'libressl'
|
||||
install_steps: libressl
|
||||
generator: Xcode
|
||||
options: --config Debug
|
||||
generate: >-
|
||||
-DCMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_ALLOWED=OFF
|
||||
-DMACOSX_BUNDLE_GUI_IDENTIFIER=se.curl
|
||||
@ -365,7 +361,7 @@ jobs:
|
||||
- name: 'build'
|
||||
run: |
|
||||
if [ -n '${{ matrix.build.generate }}' ]; then
|
||||
cmake --build bld ${{ matrix.build.options }} --parallel 4 --verbose
|
||||
cmake --build bld --verbose
|
||||
else
|
||||
make -C bld V=1
|
||||
fi
|
||||
@ -376,7 +372,7 @@ jobs:
|
||||
- name: 'build tests'
|
||||
run: |
|
||||
if [ -n '${{ matrix.build.generate }}' ]; then
|
||||
cmake --build bld ${{ matrix.build.options }} --parallel 4 --target testdeps --verbose
|
||||
cmake --build bld --target testdeps --verbose
|
||||
else
|
||||
make -C bld V=1 -C tests
|
||||
fi
|
||||
@ -384,7 +380,7 @@ jobs:
|
||||
- name: 'build examples'
|
||||
run: |
|
||||
if [ -n '${{ matrix.build.generate }}' ]; then
|
||||
cmake --build bld ${{ matrix.build.options }} --parallel 4 --target curl-examples --verbose
|
||||
cmake --build bld --target curl-examples --verbose
|
||||
else
|
||||
make -C bld examples V=1
|
||||
fi
|
||||
@ -394,9 +390,9 @@ jobs:
|
||||
runs-on: 'ubuntu-latest'
|
||||
timeout-minutes: 25
|
||||
env:
|
||||
MAKEFLAGS: -j 5
|
||||
VCPKG_BINARY_SOURCES: 'clear;x-gha,readwrite'
|
||||
VCPKG_DISABLE_METRICS: '1'
|
||||
MAKEFLAGS: -j 5
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
@ -494,7 +490,7 @@ jobs:
|
||||
if [ '${{ matrix.build }}' = 'cmake' ]; then
|
||||
cmake --build bld --verbose
|
||||
else
|
||||
make -C bld V=1
|
||||
make -j5 -C bld V=1
|
||||
fi
|
||||
|
||||
- name: 'curl info'
|
||||
@ -505,7 +501,7 @@ jobs:
|
||||
if [ '${{ matrix.build }}' = 'cmake' ]; then
|
||||
cmake --build bld --target testdeps
|
||||
else
|
||||
make -C bld -C tests
|
||||
make -j5 -C bld -C tests
|
||||
fi
|
||||
|
||||
- name: 'build examples'
|
||||
@ -513,7 +509,7 @@ jobs:
|
||||
if [ '${{ matrix.build }}' = 'cmake' ]; then
|
||||
cmake --build bld --target curl-examples
|
||||
else
|
||||
make -C bld examples
|
||||
make -j5 -C bld examples
|
||||
fi
|
||||
|
||||
amiga:
|
||||
@ -521,7 +517,6 @@ jobs:
|
||||
runs-on: 'ubuntu-latest'
|
||||
timeout-minutes: 5
|
||||
env:
|
||||
MAKEFLAGS: -j 5
|
||||
amissl-version: 5.18
|
||||
strategy:
|
||||
matrix:
|
||||
@ -589,9 +584,9 @@ jobs:
|
||||
- name: 'build'
|
||||
run: |
|
||||
if [ '${{ matrix.build }}' = 'cmake' ]; then
|
||||
cmake --build bld
|
||||
cmake --build bld --parallel 5
|
||||
else
|
||||
make -C bld
|
||||
make -j5 -C bld
|
||||
fi
|
||||
|
||||
- name: 'curl info'
|
||||
@ -601,18 +596,18 @@ jobs:
|
||||
if: ${{ matrix.build == 'cmake' }} # skip for autotools to save time
|
||||
run: |
|
||||
if [ '${{ matrix.build }}' = 'cmake' ]; then
|
||||
cmake --build bld --target testdeps
|
||||
cmake --build bld --parallel 5 --target testdeps
|
||||
else
|
||||
make -C bld -C tests
|
||||
make -j5 -C bld -C tests
|
||||
fi
|
||||
|
||||
- name: 'build examples'
|
||||
if: ${{ matrix.build == 'cmake' }} # skip for autotools to save time
|
||||
run: |
|
||||
if [ '${{ matrix.build }}' = 'cmake' ]; then
|
||||
cmake --build bld --target curl-examples
|
||||
cmake --build bld --parallel 5 --target curl-examples
|
||||
else
|
||||
make -C bld examples
|
||||
make -j5 -C bld examples
|
||||
fi
|
||||
|
||||
msdos:
|
||||
@ -620,7 +615,6 @@ jobs:
|
||||
runs-on: 'ubuntu-latest'
|
||||
timeout-minutes: 5
|
||||
env:
|
||||
MAKEFLAGS: -j 5
|
||||
toolchain-version: '3.4'
|
||||
strategy:
|
||||
matrix:
|
||||
@ -700,7 +694,7 @@ jobs:
|
||||
if [ '${{ matrix.build }}' = 'cmake' ]; then
|
||||
cmake --build bld
|
||||
else
|
||||
make -C bld
|
||||
make -j5 -C bld
|
||||
fi
|
||||
|
||||
- name: 'curl info'
|
||||
@ -712,7 +706,7 @@ jobs:
|
||||
if [ '${{ matrix.build }}' = 'cmake' ]; then
|
||||
cmake --build bld --target testdeps
|
||||
else
|
||||
make -C bld -C tests
|
||||
make -j5 -C bld -C tests
|
||||
fi
|
||||
|
||||
- name: 'build examples'
|
||||
@ -721,5 +715,5 @@ jobs:
|
||||
if [ '${{ matrix.build }}' = 'cmake' ]; then
|
||||
cmake --build bld --target curl-examples
|
||||
else
|
||||
make -C bld examples
|
||||
make -j5 -C bld examples
|
||||
fi
|
||||
|
||||
154
.github/workflows/windows.yml
vendored
154
.github/workflows/windows.yml
vendored
@ -44,7 +44,6 @@ jobs:
|
||||
run:
|
||||
shell: C:\cygwin\bin\bash.exe '{0}'
|
||||
env:
|
||||
MAKEFLAGS: -j 5
|
||||
SHELLOPTS: 'igncr'
|
||||
strategy:
|
||||
matrix:
|
||||
@ -84,13 +83,14 @@ jobs:
|
||||
- name: 'configure'
|
||||
timeout-minutes: 5
|
||||
run: |
|
||||
PATH=/usr/bin
|
||||
if [ '${{ matrix.build }}' = 'cmake' ]; then
|
||||
PATH="/usr/bin:$(cygpath "${SYSTEMROOT}")/System32"
|
||||
cmake -B bld -G Ninja -D_CURL_PREFILL=ON ${options} \
|
||||
-DCMAKE_UNITY_BUILD=ON -DCMAKE_UNITY_BUILD_BATCH_SIZE=30 -DCURL_TEST_BUNDLES=ON \
|
||||
-DCURL_WERROR=ON \
|
||||
${{ matrix.config }}
|
||||
else
|
||||
PATH="/usr/bin:$(cygpath "${SYSTEMROOT}")/System32"
|
||||
mkdir bld && cd bld && ../configure --enable-unity --enable-test-bundles --enable-warnings --enable-werror \
|
||||
--prefix="${HOME}"/install \
|
||||
--with-openssl \
|
||||
@ -112,9 +112,9 @@ jobs:
|
||||
timeout-minutes: 10
|
||||
run: |
|
||||
if [ '${{ matrix.build }}' = 'cmake' ]; then
|
||||
cmake --build bld
|
||||
cmake --build bld --config '${{ matrix.type }}'
|
||||
else
|
||||
make -C bld V=1 install
|
||||
make -C bld -j5 V=1 install
|
||||
fi
|
||||
|
||||
- name: 'curl version'
|
||||
@ -131,9 +131,9 @@ jobs:
|
||||
timeout-minutes: 15
|
||||
run: |
|
||||
if [ '${{ matrix.build }}' = 'cmake' ]; then
|
||||
cmake --build bld --target testdeps
|
||||
cmake --build bld --config '${{ matrix.type }}' --target testdeps
|
||||
else
|
||||
make -C bld V=1 -C tests
|
||||
make -C bld -j5 V=1 -C tests
|
||||
fi
|
||||
|
||||
- name: 'run tests'
|
||||
@ -146,9 +146,9 @@ jobs:
|
||||
fi
|
||||
if [ '${{ matrix.build }}' = 'cmake' ]; then
|
||||
PATH="$PWD/bld/lib:$PATH"
|
||||
cmake --build bld --target test-ci
|
||||
cmake --build bld --config '${{ matrix.type }}' --target test-ci
|
||||
else
|
||||
make -C bld V=1 test-ci
|
||||
make -C bld -j5 V=1 test-ci
|
||||
fi
|
||||
|
||||
- name: 'build examples'
|
||||
@ -156,9 +156,9 @@ jobs:
|
||||
timeout-minutes: 5
|
||||
run: |
|
||||
if [ '${{ matrix.build }}' = 'cmake' ]; then
|
||||
cmake --build bld --target curl-examples
|
||||
cmake --build bld --config '${{ matrix.type }}' --target curl-examples
|
||||
else
|
||||
make -C bld V=1 examples
|
||||
make -C bld -j5 V=1 examples
|
||||
fi
|
||||
|
||||
msys2: # both msys and mingw-w64
|
||||
@ -168,8 +168,6 @@ jobs:
|
||||
defaults:
|
||||
run:
|
||||
shell: msys2 {0}
|
||||
env:
|
||||
MAKEFLAGS: -j 5
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
@ -207,7 +205,6 @@ jobs:
|
||||
libnghttp2-devel
|
||||
libpsl-devel
|
||||
libssh2-devel
|
||||
${{ matrix.chkprefill == '_chkprefill' && 'diffutils' || '' }}
|
||||
|
||||
- uses: msys2/setup-msys2@d44ca8e88d8b43d56cf5670f91747359d5537f97 # v2
|
||||
if: ${{ matrix.sys != 'msys' }}
|
||||
@ -253,6 +250,8 @@ jobs:
|
||||
fi
|
||||
[ '${{ matrix.sys }}' = 'msys' ] && options+=' -D_CURL_PREFILL=ON'
|
||||
[ '${{ matrix.test }}' = 'uwp' ] && options+=' -DCMAKE_SYSTEM_NAME=WindowsStore -DCMAKE_SYSTEM_VERSION=10.0'
|
||||
[ '${{ matrix.type }}' = 'Debug' ] && options+=' -DCMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG='
|
||||
[ '${{ matrix.type }}' = 'Release' ] && options+=' -DCMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE='
|
||||
[ "${_chkprefill}" = '_chkprefill' ] && options+=' -D_CURL_PREFILL=OFF'
|
||||
cmake -B "bld${_chkprefill}" -G Ninja ${options} \
|
||||
-DCMAKE_C_FLAGS="${{ matrix.cflags }} ${CFLAGS_CMAKE} ${CPPFLAGS}" \
|
||||
@ -287,9 +286,9 @@ jobs:
|
||||
timeout-minutes: 10
|
||||
run: |
|
||||
if [ '${{ matrix.build }}' = 'cmake' ]; then
|
||||
cmake --build bld
|
||||
cmake --build bld --config '${{ matrix.type }}'
|
||||
else
|
||||
make -C bld V=1 install
|
||||
make -C bld -j5 V=1 install
|
||||
fi
|
||||
|
||||
- name: 'curl version'
|
||||
@ -312,9 +311,9 @@ jobs:
|
||||
timeout-minutes: 10
|
||||
run: |
|
||||
if [ '${{ matrix.build }}' = 'cmake' ]; then
|
||||
cmake --build bld --target testdeps
|
||||
cmake --build bld --config '${{ matrix.type }}' --target testdeps
|
||||
else
|
||||
make -C bld V=1 -C tests
|
||||
make -C bld -j5 V=1 -C tests
|
||||
fi
|
||||
if [ '${{ matrix.build }}' != 'cmake' ]; then
|
||||
# avoid libtool's .exe wrappers
|
||||
@ -348,10 +347,10 @@ jobs:
|
||||
PATH="$PATH:/c/Program Files (x86)/stunnel/bin"
|
||||
if [ '${{ matrix.build }}' = 'cmake' ]; then
|
||||
PATH="$PWD/bld/lib:$PATH"
|
||||
cmake --build bld --target test-ci
|
||||
cmake --build bld --config '${{ matrix.type }}' --target test-ci
|
||||
else
|
||||
PATH="$PWD/bld/lib/.libs:$PATH"
|
||||
make -C bld V=1 test-ci
|
||||
make -C bld -j5 V=1 test-ci
|
||||
fi
|
||||
|
||||
- name: 'build examples'
|
||||
@ -359,9 +358,9 @@ jobs:
|
||||
timeout-minutes: 5
|
||||
run: |
|
||||
if [ '${{ matrix.build }}' = 'cmake' ]; then
|
||||
cmake --build bld --target curl-examples
|
||||
cmake --build bld --config '${{ matrix.type }}' --target curl-examples
|
||||
else
|
||||
make -C bld V=1 examples
|
||||
make -C bld -j5 V=1 examples
|
||||
fi
|
||||
|
||||
mingw-w64-standalone-downloads:
|
||||
@ -371,8 +370,6 @@ jobs:
|
||||
defaults:
|
||||
run:
|
||||
shell: C:\msys64\usr\bin\bash.exe {0}
|
||||
env:
|
||||
MAKEFLAGS: -j 5
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
@ -429,21 +426,15 @@ jobs:
|
||||
timeout-minutes: 5
|
||||
run: |
|
||||
PATH="$(cygpath "${USERPROFILE}")/my-cache/${{ matrix.dir }}/bin:/c/msys64/usr/bin:$PATH"
|
||||
for _chkprefill in '' ${{ matrix.chkprefill }}; do
|
||||
options=''
|
||||
[ "${_chkprefill}" = '_chkprefill' ] && options+=' -D_CURL_PREFILL=OFF'
|
||||
cmake -B "bld${_chkprefill}" -G 'MSYS Makefiles' ${options} \
|
||||
-DCMAKE_C_COMPILER=gcc \
|
||||
-DCMAKE_BUILD_TYPE='${{ matrix.type }}' \
|
||||
-DCMAKE_UNITY_BUILD=ON -DCMAKE_UNITY_BUILD_BATCH_SIZE=30 -DCURL_TEST_BUNDLES=ON \
|
||||
-DCURL_WERROR=ON \
|
||||
-DCURL_USE_LIBPSL=OFF \
|
||||
${{ matrix.config }}
|
||||
done
|
||||
if [ -d bld_chkprefill ] && ! diff -u bld/lib/curl_config.h bld_chkprefill/lib/curl_config.h; then
|
||||
echo '::group::reference configure log'; cat bld_chkprefill/CMakeFiles/CMake*.yaml 2>/dev/null || true; echo '::endgroup::'
|
||||
false
|
||||
fi
|
||||
[ '${{ matrix.type }}' = 'Debug' ] && options+=' -DCMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG='
|
||||
[ '${{ matrix.type }}' = 'Release' ] && options+=' -DCMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE='
|
||||
cmake -B bld -G 'MSYS Makefiles' ${options} \
|
||||
-DCMAKE_C_COMPILER=gcc \
|
||||
-DCMAKE_BUILD_TYPE='${{ matrix.type }}' \
|
||||
-DCMAKE_UNITY_BUILD=ON -DCMAKE_UNITY_BUILD_BATCH_SIZE=30 -DCURL_TEST_BUNDLES=ON \
|
||||
-DCURL_WERROR=ON \
|
||||
-DCURL_USE_LIBPSL=OFF \
|
||||
${{ matrix.config }}
|
||||
|
||||
- name: 'configure log'
|
||||
if: ${{ !cancelled() }}
|
||||
@ -458,7 +449,7 @@ jobs:
|
||||
timeout-minutes: 5
|
||||
run: |
|
||||
PATH="$(cygpath "${USERPROFILE}")/my-cache/${{ matrix.dir }}/bin:/c/msys64/usr/bin:$PATH"
|
||||
cmake --build bld
|
||||
cmake --build bld --config '${{ matrix.type }}' --parallel 5
|
||||
|
||||
- name: 'curl version'
|
||||
timeout-minutes: 1
|
||||
@ -472,7 +463,7 @@ jobs:
|
||||
timeout-minutes: 10
|
||||
run: |
|
||||
PATH="$(cygpath "${USERPROFILE}")/my-cache/${{ matrix.dir }}/bin:/c/msys64/usr/bin:$PATH"
|
||||
cmake --build bld --target testdeps
|
||||
cmake --build bld --config '${{ matrix.type }}' --parallel 5 --target testdeps
|
||||
|
||||
- name: 'install test prereqs'
|
||||
if: ${{ matrix.tflags != 'skipall' && matrix.tflags != 'skiprun' }}
|
||||
@ -501,29 +492,27 @@ jobs:
|
||||
TFLAGS+=" -ac $(cygpath "${SYSTEMROOT}/System32/curl.exe")"
|
||||
fi
|
||||
PATH="$PWD/bld/lib:$PATH:/c/Program Files (x86)/stunnel/bin"
|
||||
cmake --build bld --target test-ci
|
||||
cmake --build bld --config '${{ matrix.type }}' --target test-ci
|
||||
|
||||
- name: 'build examples'
|
||||
timeout-minutes: 5
|
||||
run: |
|
||||
PATH="$(cygpath "${USERPROFILE}")/my-cache/${{ matrix.dir }}/bin:/c/msys64/usr/bin:$PATH"
|
||||
cmake --build bld --target curl-examples
|
||||
cmake --build bld --config '${{ matrix.type }}' --parallel 5 --target curl-examples
|
||||
|
||||
linux-cross-mingw-w64:
|
||||
name: "linux-mingw, ${{ matrix.build == 'cmake' && 'CM' || 'AM' }} ${{ matrix.compiler }}"
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 15
|
||||
env:
|
||||
MAKEFLAGS: -j 5
|
||||
TRIPLET: 'x86_64-w64-mingw32'
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
build: [autotools, cmake]
|
||||
compiler: [gcc]
|
||||
env:
|
||||
TRIPLET: 'x86_64-w64-mingw32'
|
||||
steps:
|
||||
- name: 'install packages'
|
||||
timeout-minutes: 5
|
||||
run: sudo apt-get -o Dpkg::Use-Pty=0 install mingw-w64 ${{ matrix.build == 'cmake' && 'ninja-build' || '' }}
|
||||
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
||||
@ -567,7 +556,7 @@ jobs:
|
||||
if [ '${{ matrix.build }}' = 'cmake' ]; then
|
||||
cmake --build bld
|
||||
else
|
||||
make -C bld
|
||||
make -C bld -j5
|
||||
fi
|
||||
|
||||
- name: 'curl info'
|
||||
@ -579,7 +568,7 @@ jobs:
|
||||
if [ '${{ matrix.build }}' = 'cmake' ]; then
|
||||
cmake --build bld --target testdeps
|
||||
else
|
||||
make -C bld -C tests
|
||||
make -C bld -j5 -C tests
|
||||
fi
|
||||
|
||||
- name: 'build examples'
|
||||
@ -587,7 +576,7 @@ jobs:
|
||||
if [ '${{ matrix.build }}' = 'cmake' ]; then
|
||||
cmake --build bld --target curl-examples
|
||||
else
|
||||
make -C bld examples
|
||||
make -C bld -j5 examples
|
||||
fi
|
||||
|
||||
wince:
|
||||
@ -595,7 +584,6 @@ jobs:
|
||||
runs-on: 'macos-latest'
|
||||
timeout-minutes: 10
|
||||
env:
|
||||
MAKEFLAGS: -j 4
|
||||
toolchain-version: '0.59.1'
|
||||
strategy:
|
||||
matrix:
|
||||
@ -604,7 +592,6 @@ jobs:
|
||||
steps:
|
||||
- name: 'install packages'
|
||||
if: ${{ matrix.build == 'autotools' }}
|
||||
timeout-minutes: 5
|
||||
run: |
|
||||
echo automake libtool | xargs -Ix -n1 echo brew '"x"' > /tmp/Brewfile
|
||||
while [[ $? == 0 ]]; do for i in 1 2 3; do brew update && brew bundle install --no-lock --file /tmp/Brewfile && break 2 || { echo Error: wait to try again; sleep 10; } done; false Too many retries; done
|
||||
@ -618,7 +605,6 @@ jobs:
|
||||
|
||||
- name: 'install compiler (mingw32ce)'
|
||||
if: ${{ steps.cache-compiler.outputs.cache-hit != 'true' }}
|
||||
timeout-minutes: 5
|
||||
run: |
|
||||
cd "${HOME}" || exit 1
|
||||
curl --disable --fail --silent --show-error --connect-timeout 15 --max-time 120 --retry 3 --retry-connrefused --proto-redir =https \
|
||||
@ -629,19 +615,18 @@ jobs:
|
||||
|
||||
- name: 'configure'
|
||||
run: |
|
||||
PATH="$HOME/opt/mingw32ce/bin:$PATH"
|
||||
MINGW32CE_ROOT="${HOME}/opt/mingw32ce"
|
||||
if [ '${{ matrix.build }}' = 'cmake' ]; then
|
||||
cmake -B bld \
|
||||
-DCMAKE_SYSTEM_NAME=WindowsCE \
|
||||
-DCMAKE_SYSTEM_VERSION=8.0 \
|
||||
-DCMAKE_SYSTEM_PROCESSOR=arm \
|
||||
-DCMAKE_C_FLAGS='-O3 -DNDEBUG' \
|
||||
-DCMAKE_C_COMPILER_TARGET=arm-mingw32ce \
|
||||
-DCMAKE_C_COMPILER=arm-mingw32ce-gcc \
|
||||
-DCMAKE_RC_COMPILER=arm-mingw32ce-windres \
|
||||
-DMINGW32CE_LIBRARY_DIR="$HOME/opt/mingw32ce/arm-mingw32ce/lib" \
|
||||
-DCMAKE_C_COMPILER_TARGET=arm-wince-mingw32ce \
|
||||
-DCMAKE_C_COMPILER="${MINGW32CE_ROOT}/bin/arm-mingw32ce-gcc" \
|
||||
-DCMAKE_RC_COMPILER="${MINGW32CE_ROOT}/bin/arm-mingw32ce-windres" \
|
||||
-DMINGW32CE_LIBRARY_DIR="${MINGW32CE_ROOT}/arm-mingw32ce/lib" \
|
||||
-DCMAKE_IGNORE_PREFIX_PATH="$(brew --prefix)" \
|
||||
-DCMAKE_UNITY_BUILD=ON -DCMAKE_UNITY_BUILD_BATCH_SIZE=50 -DCURL_TEST_BUNDLES=ON \
|
||||
-DCMAKE_UNITY_BUILD=ON -DCURL_TEST_BUNDLES=ON \
|
||||
-DBUILD_SHARED_LIBS=ON -DBUILD_STATIC_LIBS=ON -DBUILD_STATIC_CURL=OFF \
|
||||
-DCURL_WERROR=ON \
|
||||
-DCURL_USE_SCHANNEL=ON \
|
||||
@ -649,7 +634,12 @@ jobs:
|
||||
else
|
||||
autoreconf -fi
|
||||
mkdir bld && cd bld && ../configure --disable-dependency-tracking --enable-unity --enable-test-bundles --enable-warnings --enable-werror \
|
||||
--host=arm-mingw32ce \
|
||||
ac_cv_prog_cc_c99=no \
|
||||
CC="${MINGW32CE_ROOT}/bin/arm-mingw32ce-gcc" \
|
||||
AR="${MINGW32CE_ROOT}/bin/arm-mingw32ce-ar" \
|
||||
RANLIB="${MINGW32CE_ROOT}/bin/arm-mingw32ce-ranlib" \
|
||||
RC="${MINGW32CE_ROOT}/bin/arm-mingw32ce-windres" \
|
||||
--host=arm-wince-mingw32ce \
|
||||
--with-schannel \
|
||||
--without-libpsl \
|
||||
--disable-shared
|
||||
@ -666,11 +656,10 @@ jobs:
|
||||
|
||||
- name: 'build'
|
||||
run: |
|
||||
PATH="$HOME/opt/mingw32ce/bin:$PATH"
|
||||
if [ '${{ matrix.build }}' = 'cmake' ]; then
|
||||
cmake --build bld
|
||||
else
|
||||
make -C bld
|
||||
make -j5 -C bld
|
||||
fi
|
||||
|
||||
- name: 'curl info'
|
||||
@ -680,21 +669,19 @@ jobs:
|
||||
- name: 'build tests'
|
||||
if: ${{ matrix.build == 'cmake' }} # skip for autotools to save time
|
||||
run: |
|
||||
PATH="$HOME/opt/mingw32ce/bin:$PATH"
|
||||
if [ '${{ matrix.build }}' = 'cmake' ]; then
|
||||
cmake --build bld --target testdeps
|
||||
else
|
||||
make -C bld -C tests
|
||||
make -j5 -C bld -C tests
|
||||
fi
|
||||
|
||||
- name: 'build examples'
|
||||
if: ${{ matrix.build == 'cmake' }} # skip for autotools to save time
|
||||
run: |
|
||||
PATH="$HOME/opt/mingw32ce/bin:$PATH"
|
||||
if [ '${{ matrix.build }}' = 'cmake' ]; then
|
||||
cmake --build bld --target curl-examples
|
||||
else
|
||||
make -C bld examples
|
||||
make -j5 -C bld examples
|
||||
fi
|
||||
|
||||
msvc:
|
||||
@ -710,16 +697,16 @@ jobs:
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- name: 'openssl'
|
||||
install: 'brotli zlib zstd nghttp2 nghttp3 openssl libssh2'
|
||||
- name: 'schannel MultiSSL U'
|
||||
install: 'brotli zlib zstd libpsl nghttp2 libssh2[core,zlib] pkgconf gsasl openssl mbedtls wolfssl'
|
||||
arch: 'x64'
|
||||
plat: 'uwp'
|
||||
plat: 'windows'
|
||||
type: 'Debug'
|
||||
tflags: 'skiprun'
|
||||
tflags: '~1516 ~2301 ~2302 ~2303 ~2307 ~2310'
|
||||
config: >-
|
||||
-DCURL_USE_LIBSSH2=ON
|
||||
-DCURL_USE_SCHANNEL=OFF -DCURL_USE_OPENSSL=ON -DUSE_OPENSSL_QUIC=ON
|
||||
-DCURL_USE_LIBPSL=OFF
|
||||
-DCURL_USE_SCHANNEL=ON -DCURL_USE_OPENSSL=ON -DCURL_USE_MBEDTLS=ON -DCURL_USE_WOLFSSL=ON -DCURL_DEFAULT_SSL_BACKEND=schannel
|
||||
-DCURL_USE_GSASL=ON -DUSE_WIN32_IDN=ON -DENABLE_UNICODE=ON -DUSE_SSLS_EXPORT=ON
|
||||
|
||||
- name: 'openssl'
|
||||
install: 'brotli zlib zstd libpsl nghttp2 nghttp3 openssl libssh2 pkgconf gsasl c-ares libuv krb5'
|
||||
@ -732,16 +719,16 @@ jobs:
|
||||
-DCURL_USE_SCHANNEL=OFF -DCURL_USE_OPENSSL=ON -DUSE_OPENSSL_QUIC=ON
|
||||
-DCURL_USE_GSASL=ON -DENABLE_ARES=ON -DCURL_USE_LIBUV=ON -DCURL_USE_GSSAPI=ON
|
||||
|
||||
- name: 'schannel MultiSSL U'
|
||||
install: 'brotli zlib zstd libpsl nghttp2 libssh2[core,zlib] pkgconf gsasl openssl mbedtls wolfssl'
|
||||
- name: 'openssl'
|
||||
install: 'brotli zlib zstd nghttp2 nghttp3 openssl libssh2'
|
||||
arch: 'x64'
|
||||
plat: 'windows'
|
||||
plat: 'uwp'
|
||||
type: 'Debug'
|
||||
tflags: '~1516 ~2301 ~2302 ~2303 ~2307 ~2310'
|
||||
tflags: 'skiprun'
|
||||
config: >-
|
||||
-DCURL_USE_LIBSSH2=ON
|
||||
-DCURL_USE_SCHANNEL=ON -DCURL_USE_OPENSSL=ON -DCURL_USE_MBEDTLS=ON -DCURL_USE_WOLFSSL=ON -DCURL_DEFAULT_SSL_BACKEND=schannel
|
||||
-DCURL_USE_GSASL=ON -DUSE_WIN32_IDN=ON -DENABLE_UNICODE=ON -DUSE_SSLS_EXPORT=ON
|
||||
-DCURL_USE_SCHANNEL=OFF -DCURL_USE_OPENSSL=ON -DUSE_OPENSSL_QUIC=ON
|
||||
-DCURL_USE_LIBPSL=OFF
|
||||
|
||||
- name: 'libressl'
|
||||
install: 'brotli zlib zstd libpsl nghttp2 libressl libssh2[core,zlib] pkgconf ngtcp2[libressl] nghttp3'
|
||||
@ -840,6 +827,8 @@ jobs:
|
||||
-DCMAKE_EXE_LINKER_FLAGS="-INCREMENTAL:NO ${ldflags}" \
|
||||
-DCMAKE_SHARED_LINKER_FLAGS="-INCREMENTAL:NO ${ldflags}" \
|
||||
-DCMAKE_VS_GLOBALS="TrackFileAccess=false${vsglobals}" \
|
||||
-DCMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG= \
|
||||
-DCMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE= \
|
||||
-DCMAKE_UNITY_BUILD=ON -DCURL_TEST_BUNDLES=ON \
|
||||
-DCURL_WERROR=ON \
|
||||
-DBUILD_SHARED_LIBS=OFF \
|
||||
@ -869,10 +858,10 @@ jobs:
|
||||
- name: 'curl version'
|
||||
timeout-minutes: 1
|
||||
run: |
|
||||
PATH=/usr/bin find . \( -name '*.exe' -o -name '*.dll' -o -name '*.lib' -o -name '*.pdb' \) -exec file '{}' \;
|
||||
PATH=/usr/bin find . \( -name '*.exe' -o -name '*.dll' -o -name '*.lib' \) -exec file '{}' \;
|
||||
if [ '${{ matrix.plat }}' != 'uwp' ]; then # Missing: ucrtbased.dll, VCRUNTIME140D.dll, VCRUNTIME140D_APP.dll
|
||||
PATH="$PWD/bld/lib/${{ matrix.type }}:$PATH"
|
||||
'bld/src/${{ matrix.type }}/curl.exe' --disable --version
|
||||
PATH="$PWD/bld/lib:$PATH"
|
||||
bld/src/curl.exe --disable --version
|
||||
fi
|
||||
|
||||
- name: 'build tests'
|
||||
@ -907,14 +896,13 @@ jobs:
|
||||
if: ${{ matrix.tflags != 'skipall' && matrix.tflags != 'skiprun' }}
|
||||
timeout-minutes: 10
|
||||
run: |
|
||||
export CURL_DIRSUFFIX='${{ matrix.type }}'
|
||||
export TFLAGS='-j8 ~WebSockets ~SCP ~612 ${{ matrix.tflags }}'
|
||||
if [[ '${{ matrix.install }}' = *'libssh2[core,zlib]'* ]]; then
|
||||
TFLAGS+=' ~SFTP'
|
||||
elif [[ '${{ matrix.install }}' = *'libssh '* ]]; then
|
||||
TFLAGS+=' ~614' # 'SFTP pre-quote chmod' SFTP, pre-quote, directory
|
||||
fi
|
||||
PATH="$PWD/bld/lib/${{ matrix.type }}:$PATH:/c/Program Files (x86)/stunnel/bin:/c/Program Files/OpenSSH-Win64"
|
||||
PATH="$PWD/bld/lib:$PATH:/c/Program Files (x86)/stunnel/bin:/c/Program Files/OpenSSH-Win64"
|
||||
PATH="/c/msys64/usr/bin:$PATH"
|
||||
cmake --build bld --config '${{ matrix.type }}' --target test-ci
|
||||
|
||||
|
||||
@ -87,10 +87,3 @@ macro(curl_required_libpaths _libpaths_arg)
|
||||
list(APPEND CMAKE_REQUIRED_LINK_DIRECTORIES "${_libpaths_arg}")
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
# Pre-fill variables set by a check_type_size() call.
|
||||
macro(curl_prefill_type_size _type _size)
|
||||
set(HAVE_SIZEOF_${_type} TRUE)
|
||||
set(SIZEOF_${_type} ${_size})
|
||||
set(SIZEOF_${_type}_CODE "#define SIZEOF_${_type} ${_size}")
|
||||
endmacro()
|
||||
|
||||
@ -182,7 +182,6 @@ if(PICKY_COMPILER)
|
||||
-Wold-style-declaration # gcc 4.3
|
||||
-Wpragmas # clang 3.5 gcc 4.1 appleclang 6.0
|
||||
-Wstrict-aliasing=3 # gcc 4.0
|
||||
-ftree-vrp # gcc 4.3 (required for -Warray-bounds, included in -Wall)
|
||||
)
|
||||
endif()
|
||||
if(NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 4.5)
|
||||
@ -205,7 +204,7 @@ if(PICKY_COMPILER)
|
||||
endif()
|
||||
if(NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 5.0)
|
||||
list(APPEND _picky_enable
|
||||
-Warray-bounds=2 # clang 3.0 gcc 5.0 (clang default: -Warray-bounds)
|
||||
-Warray-bounds=2 -ftree-vrp # clang 3.0 gcc 5.0 (clang default: -Warray-bounds)
|
||||
)
|
||||
endif()
|
||||
if(NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 6.0)
|
||||
|
||||
@ -44,6 +44,10 @@ if(MINGW)
|
||||
set(HAVE_UTIME_H 1) # wrapper to sys/utime.h
|
||||
set(HAVE_DIRENT_H 1)
|
||||
set(HAVE_OPENDIR 1)
|
||||
if(MINGW32CE)
|
||||
set(HAVE_STRTOK_R 0)
|
||||
set(HAVE_FILE_OFFSET_BITS 0)
|
||||
endif()
|
||||
else()
|
||||
set(HAVE_LIBGEN_H 0)
|
||||
set(HAVE_FTRUNCATE 0)
|
||||
@ -74,6 +78,7 @@ else()
|
||||
set(HAVE_SNPRINTF 0)
|
||||
endif()
|
||||
set(HAVE_BASENAME 0)
|
||||
set(HAVE_FILE_OFFSET_BITS 0)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
@ -191,37 +196,6 @@ set(STDC_HEADERS 1)
|
||||
set(HAVE_SIZEOF_SUSECONDS_T 0)
|
||||
set(HAVE_SIZEOF_SA_FAMILY_T 0)
|
||||
|
||||
if(MINGW OR MSVC)
|
||||
curl_prefill_type_size("INT" 4)
|
||||
curl_prefill_type_size("LONG" 4)
|
||||
curl_prefill_type_size("LONG_LONG" 8)
|
||||
curl_prefill_type_size("__INT64" 8)
|
||||
curl_prefill_type_size("CURL_OFF_T" 8)
|
||||
# CURL_SOCKET_T, SIZE_T: 8 for _WIN64, 4 otherwise
|
||||
# TIME_T: 8 for _WIN64 or UCRT or MSVC and not Windows CE, 4 otherwise
|
||||
# Also 4 for non-UCRT 32-bit when _USE_32BIT_TIME_T is set.
|
||||
# mingw-w64 sets _USE_32BIT_TIME_T unless __MINGW_USE_VC2005_COMPAT is explicit defined.
|
||||
if(MSVC)
|
||||
set(HAVE_SIZEOF_SSIZE_T 0)
|
||||
set(HAVE_FILE_OFFSET_BITS 0)
|
||||
curl_prefill_type_size("OFF_T" 4)
|
||||
curl_prefill_type_size("ADDRESS_FAMILY" 2)
|
||||
else()
|
||||
# SSIZE_T: 8 for _WIN64, 4 otherwise
|
||||
if(MINGW64_VERSION)
|
||||
if(NOT MINGW64_VERSION VERSION_LESS 3.0)
|
||||
set(HAVE_FILE_OFFSET_BITS 1)
|
||||
curl_prefill_type_size("OFF_T" 8)
|
||||
endif()
|
||||
if(NOT MINGW64_VERSION VERSION_LESS 2.0)
|
||||
curl_prefill_type_size("ADDRESS_FAMILY" 2)
|
||||
else()
|
||||
set(HAVE_SIZEOF_ADDRESS_FAMILY 0)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(WINCE) # Windows CE exceptions
|
||||
set(HAVE_LOCALE_H 0)
|
||||
set(HAVE_GETADDRINFO 0)
|
||||
@ -230,15 +204,7 @@ if(WINCE) # Windows CE exceptions
|
||||
set(HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID 0)
|
||||
set(HAVE_SIGNAL 0)
|
||||
set(HAVE_SETMODE 0)
|
||||
curl_prefill_type_size("CURL_SOCKET_T" 4)
|
||||
curl_prefill_type_size("TIME_T" 4)
|
||||
curl_prefill_type_size("SIZE_T" 4)
|
||||
if(MINGW32CE)
|
||||
set(HAVE_STRTOK_R 0)
|
||||
set(HAVE__SETMODE 0)
|
||||
set(HAVE_FILE_OFFSET_BITS 0)
|
||||
set(HAVE_SIZEOF_ADDRESS_FAMILY 0)
|
||||
curl_prefill_type_size("SSIZE_T" 4)
|
||||
curl_prefill_type_size("OFF_T" 4)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
@ -217,6 +217,13 @@ option(ENABLE_ARES "Enable c-ares support" OFF)
|
||||
option(CURL_DISABLE_INSTALL "Disable installation targets" OFF)
|
||||
|
||||
if(WIN32)
|
||||
option(CURL_STATIC_CRT "Build libcurl with static CRT with MSVC (/MT)" OFF)
|
||||
if(CURL_STATIC_CRT AND MSVC)
|
||||
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
|
||||
string(APPEND CMAKE_C_FLAGS_RELEASE " -MT")
|
||||
string(APPEND CMAKE_C_FLAGS_DEBUG " -MTd")
|
||||
endif()
|
||||
|
||||
option(ENABLE_UNICODE "Use the Unicode version of the Windows API functions" OFF)
|
||||
if(WINDOWS_STORE OR WINCE)
|
||||
set(ENABLE_UNICODE ON)
|
||||
@ -257,9 +264,7 @@ if(WIN32)
|
||||
if(MINGW64_VERSION)
|
||||
string(REGEX MATCH "MINGW64_VERSION=[0-9]+\.[0-9]+" CURL_TEST_OUTPUT "${CURL_TEST_OUTPUT}")
|
||||
string(REGEX REPLACE "MINGW64_VERSION=" "" MINGW64_VERSION "${CURL_TEST_OUTPUT}")
|
||||
if(MINGW64_VERSION)
|
||||
message(STATUS "Found MINGW64_VERSION=${MINGW64_VERSION}")
|
||||
endif()
|
||||
message(STATUS "Found MINGW64_VERSION=${MINGW64_VERSION}")
|
||||
endif()
|
||||
unset(MINGW64_VERSION CACHE) # Avoid storing in CMake cache
|
||||
endif()
|
||||
@ -349,19 +354,6 @@ else()
|
||||
set(LIB_SELECTED ${LIB_STATIC})
|
||||
endif()
|
||||
|
||||
if(WIN32)
|
||||
option(CURL_STATIC_CRT "Build libcurl with static CRT with MSVC (/MT)" OFF)
|
||||
if(CURL_STATIC_CRT AND MSVC)
|
||||
if(BUILD_STATIC_CURL OR NOT BUILD_CURL_EXE)
|
||||
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
|
||||
string(APPEND CMAKE_C_FLAGS_RELEASE " -MT")
|
||||
string(APPEND CMAKE_C_FLAGS_DEBUG " -MTd")
|
||||
else()
|
||||
message(WARNING "Static CRT requires static or no curl executable.")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Override to force-disable or force-enable the use of pkg-config.
|
||||
if((UNIX AND NOT ANDROID AND (NOT APPLE OR CMAKE_SYSTEM_NAME MATCHES "Darwin")) OR
|
||||
VCPKG_TOOLCHAIN OR
|
||||
@ -827,6 +819,9 @@ if(CURL_USE_OPENSSL)
|
||||
set(_openssl "AmiSSL")
|
||||
else()
|
||||
set(_openssl "OpenSSL")
|
||||
if(OPENSSL_VERSION VERSION_LESS 1.1.1)
|
||||
message(WARNING "OpenSSL ${OPENSSL_VERSION} does not support TLS 1.3.")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
@ -1953,6 +1948,22 @@ endif()
|
||||
|
||||
# Some other minor tests
|
||||
|
||||
if(CMAKE_COMPILER_IS_GNUCC AND APPLE)
|
||||
include(CheckCCompilerFlag)
|
||||
check_c_compiler_flag("-Wno-long-double" HAVE_C_FLAG_Wno_long_double)
|
||||
if(HAVE_C_FLAG_Wno_long_double)
|
||||
# The Mac version of GCC warns about use of long double. Disable it.
|
||||
get_source_file_property(_mprintf_compile_flags "mprintf.c" COMPILE_FLAGS)
|
||||
if(_mprintf_compile_flags)
|
||||
string(APPEND _mprintf_compile_flags " -Wno-long-double")
|
||||
else()
|
||||
set(_mprintf_compile_flags "-Wno-long-double")
|
||||
endif()
|
||||
set_source_files_properties("mprintf.c" PROPERTIES
|
||||
COMPILE_FLAGS ${_mprintf_compile_flags})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(_cmake_try_compile_target_type_save)
|
||||
set(CMAKE_TRY_COMPILE_TARGET_TYPE ${_cmake_try_compile_target_type_save})
|
||||
unset(_cmake_try_compile_target_type_save)
|
||||
@ -1972,6 +1983,9 @@ if(WIN32)
|
||||
set(USE_WIN32_LARGE_FILES ON)
|
||||
endif()
|
||||
|
||||
# Use the manifest embedded in the Windows Resource
|
||||
string(APPEND CMAKE_RC_FLAGS " -DCURL_EMBED_MANIFEST")
|
||||
|
||||
# We use crypto functions that are not available for UWP apps
|
||||
if(NOT WINDOWS_STORE)
|
||||
set(USE_WIN32_CRYPTO ON)
|
||||
@ -1987,6 +2001,9 @@ if(WIN32)
|
||||
endif()
|
||||
|
||||
if(MSVC)
|
||||
# Disable default manifest added by CMake
|
||||
string(APPEND CMAKE_EXE_LINKER_FLAGS " -MANIFEST:NO")
|
||||
|
||||
string(APPEND CMAKE_C_FLAGS " -MP") # Parallel compilation
|
||||
endif()
|
||||
|
||||
@ -2166,7 +2183,7 @@ curl_add_if("TLS-SRP" USE_TLS_SRP)
|
||||
curl_add_if("HTTP2" USE_NGHTTP2)
|
||||
curl_add_if("HTTP3" USE_NGTCP2 OR USE_QUICHE OR USE_MSH3 OR USE_OPENSSL_QUIC)
|
||||
curl_add_if("MultiSSL" CURL_WITH_MULTI_SSL)
|
||||
curl_add_if("HTTPS-proxy" NOT CURL_DISABLE_PROXY AND _ssl_enabled AND (USE_OPENSSL OR USE_GNUTLS
|
||||
curl_add_if("HTTPS-proxy" _ssl_enabled AND (USE_OPENSSL OR USE_GNUTLS
|
||||
OR USE_SCHANNEL OR USE_RUSTLS OR USE_BEARSSL OR
|
||||
USE_MBEDTLS OR USE_SECTRANSP OR
|
||||
(USE_WOLFSSL AND HAVE_WOLFSSL_BIO)))
|
||||
|
||||
116
RELEASE-NOTES
116
RELEASE-NOTES
@ -4,15 +4,10 @@ curl and libcurl 8.13.0
|
||||
Command line options: 267
|
||||
curl_easy_setopt() options: 306
|
||||
Public functions in libcurl: 96
|
||||
Contributors: 3354
|
||||
Contributors: 3349
|
||||
|
||||
This release includes the following changes:
|
||||
|
||||
o curl: add write-out variable 'tls_earlydata' [79]
|
||||
o rustls: add support for CERTINFO [106]
|
||||
o tool_getparam: make --url support a file with URLs [104]
|
||||
o var: add a '64dec' function that can base64 decode a string [78]
|
||||
o wolfssl: tls early data support [50]
|
||||
|
||||
This release includes the following bugfixes:
|
||||
|
||||
@ -21,111 +16,67 @@ This release includes the following bugfixes:
|
||||
o asyn-thread: avoid the separate curl_mutex_t alloc [6]
|
||||
o asyn-thread: do not allocate thread_data separately [21]
|
||||
o asyn-thread: remove 'status' from struct Curl_async [36]
|
||||
o build: add Windows CE / CeGCC support, with CI jobs [87]
|
||||
o build: drop unused `getpart` tool [107]
|
||||
o build: enable -Wjump-misses-init for GCC 4.5+ [62]
|
||||
o build: fix compiler warnings in feature detections [39]
|
||||
o build: set `HAVE_WRITABLE_ARGV` for Apple cross-builds [8]
|
||||
o build: silence bogus `-Wconversion` warnings with gcc 5.1-5.4 [68]
|
||||
o c-ares: error out for unsupported versions, drop unused macros [85]
|
||||
o ca-native.md: sync with CURLSSLOPT_NATIVE_CA [72]
|
||||
o cf-socket: deduplicate Windows Vista detection [11]
|
||||
o client writer: handle pause before deocding [61]
|
||||
o cmake: `SHARE_LIB_OBJECT=ON` requires CMake 3.12 or newer [46]
|
||||
o cmake: add pre-fill for Unix, enable in GHA/macos, verify pre-fills [42]
|
||||
o cmake: allow empty `IMPORT_LIB_SUFFIX`, add suffix collision detection [41]
|
||||
o cmake: avoid `-Wnonnull` warning in `HAVE_FSETXATTR_5` detection [81]
|
||||
o cmake: disable HTTPS-proxy as a feature if proxy is disabled [77]
|
||||
o cmake: drop `CURL_DISABLE_TESTS` option [94]
|
||||
o cmake: allow empty custom `IMPORT_LIB_SUFFIX`, add suffix collision detection [41]
|
||||
o cmake: drop `HAVE_IN_ADDR_T` from pre-fill too
|
||||
o cmake: drop two stray TLS feature checks for wolfSSL [9]
|
||||
o cmake: fix `HAVE_ATOMIC`/`HAVE_STDATOMIC` pre-fill for clang-cl [28]
|
||||
o cmake: fix ECH detection in custom-patched OpenSSL [32]
|
||||
o cmake: hide empty `MINGW64_VERSION` output for mingw32ce [114]
|
||||
o cmake: mention 'insecure' in the debug build warning [15]
|
||||
o cmake: misc tidy-ups [38]
|
||||
o cmake: pre-fill known type sizes for Windows OSes [100]
|
||||
o cmake: restrict static CRT builds to static curl exe, test in CI [113]
|
||||
o cmake: sync cutoff version with autotools for picky option `-ftree-vrp` [99]
|
||||
o cmake: sync OpenSSL(-fork) feature checks with `./configure` [49]
|
||||
o CODE_STYLE: readability and banned functions [35]
|
||||
o configure: silence compiler warnings in feature checks, drop duplicates [86]
|
||||
o configure: use `curl_cv_apple` variable [40]
|
||||
o conn: fix connection reuse when SSL is optional [54]
|
||||
o contributors.sh: lowercase 'github' for consistency [52]
|
||||
o contrithanks.sh: update docs/THANKS in place [119]
|
||||
o cookie: do prefix matching case-sensitively [82]
|
||||
o cookie: minor parser simplification [58]
|
||||
o cookie: simplify invalid_octets() [24]
|
||||
o curl.h: change some enums to defines with L suffix [84]
|
||||
o curl_msh3: remove verify bypass from DEBUGBUILDs [43]
|
||||
o curl_trc: fix build with CURL_DISABLE_VERBOSE_STRINGS [109]
|
||||
o CURLMOPT_SOCKETFUNCTION.md: add advice for socket callback invocation[69]
|
||||
o CURLOPT_HTTPHEADER.md: add comments to the example [90]
|
||||
o CURLOPT_HTTPHEADER.md: rephrases [108]
|
||||
o docs: add FD_ZERO to curl_multi_fdset example [19]
|
||||
o docs: bump `rustls` to 0.14.1 [111]
|
||||
o docs: correct argument names & URL redirection [4]
|
||||
o eventfd: allow use on all CPUs [93]
|
||||
o gnutls: fix connection state check on handshake [80]
|
||||
o hash: use single linked list for entries [57]
|
||||
o hostip: make CURLOPT_RESOLVE support replacing IPv6 addresses [47]
|
||||
o HTTP3.md: only speak about minimal versions [18]
|
||||
o http: convert parsers to strparse [48]
|
||||
o http: fix NTLM info message typo [22]
|
||||
o http: fix the auth check [88]
|
||||
o http: make the RTSP version check stricter [73]
|
||||
o http: negotiation and room for alt-svc/https rr to navigate [64]
|
||||
o http: version negotiation [45]
|
||||
o http_aws_sigv4: use strparse more for parsing [55]
|
||||
o https-rr: implementation improvements [44]
|
||||
o httpsrr: fix port detection [51]
|
||||
o httpsrr: fix the HTTPS-RR threaded-resolver build combo [67]
|
||||
o INSTALL-CMAKE.md: CMake usage updates [101]
|
||||
o INSTALL-CMAKE.md: mention `ZLIB_USE_STATIC_LIBS` [112]
|
||||
o lib: better optimized casecompare() and ncasecompare() [3]
|
||||
o lib: simplify more white space loops [60]
|
||||
o lib: strtoofft.h header cleanup [17]
|
||||
o lib: use Curl_str_* instead of strtok_r() [59]
|
||||
o lib: use Curl_str_number() for parsing decimal numbers [13]
|
||||
o libtest/libprereq.c: set CURLOPT_FOLLOWLOCATION with a long [89]
|
||||
o managen: correct the warning for un-escaped '<' and '>' [1]
|
||||
o msvc: drop support for VS2005 and older [96]
|
||||
o multi: event based rework [74]
|
||||
o openssl: check return value of X509_get0_pubkey [105]
|
||||
o openssl: drop support for old OpenSSL/LibreSSL versions [95]
|
||||
o openssl: remove bad `goto`s into other scope [63]
|
||||
o runtests: drop recognizing 'winssl' as Schannel [102]
|
||||
o runtests: drop ref to unused external function
|
||||
o runtests: recognize AWS-LC as OpenSSL [103]
|
||||
o runtests: support multi-target cmake, drop workarounds from CI [116]
|
||||
o schannel: deduplicate Windows Vista detection [98]
|
||||
o schannel: enable ALPN support under WINE 6.0+ [92]
|
||||
o schannel: enable ALPN with MinGW, fix ALPN for UWP builds [71]
|
||||
o schannel: guard ALPN init code to ALPN builds [91]
|
||||
o scripts/managen: fix option 'single' [31]
|
||||
o scripts/managen: fix parsing of markdown code sections [30]
|
||||
o setopt: remove unnecesary void pointer typecasts [76]
|
||||
o ssh: consider sftp quote commands case sensitive [33]
|
||||
o ssl session cache: add exportable flag [56]
|
||||
o strparse: make Curl_str_number() return error for no digits [14]
|
||||
o strparse: switch the API to work on 'const char *' [2]
|
||||
o strparse: switch to curl_off_t as base data type [7]
|
||||
o tests: fix enum/int confusion, fix autotools `CFLAGS` for `servers` [27]
|
||||
o tidy-up: align MSYS2/Cygwin codepaths, follow Cygwin `MAX_PID` bump [97]
|
||||
o tests: fix enum/int confusion (Intel C), fix autotools `CFLAGS` for `servers` [27]
|
||||
o tidy-up: delete, comment or scope C macros reported unused [16]
|
||||
o tidy-up: drop unused `CURL_INADDR_NONE` macro and `in_addr_t` type [26]
|
||||
o tidy-up: use `CURL_ARRAYSIZE()` [37]
|
||||
o timediff: fix comment for curlx_mstotv() [25]
|
||||
o timediff: remove unnecessary double typecast [53]
|
||||
o tool_getparam: clear sensitive arguments better [66]
|
||||
o tool_operate: fail SSH transfers without server auth [70]
|
||||
o urlapi: simplify junkscan [23]
|
||||
o variable.md: clarify 'trim' example [12]
|
||||
o windows: drop code and curl manifest targeting W2K and older [115]
|
||||
o wolfssh: retrieve the error using wolfSSH_get_error [5]
|
||||
o wolfssl: fix CA certificate multiple location import [34]
|
||||
o wolfssl: warn if CA native import option is ignored [65]
|
||||
o wolfssl: when using PQ KEM, use ML-KEM, not Kyber [10]
|
||||
|
||||
This release includes the following known bugs:
|
||||
@ -147,13 +98,12 @@ Planned upcoming removals include:
|
||||
This release would not have looked like this without help, code, reports and
|
||||
advice from friends like these:
|
||||
|
||||
Anthony Hu, Dan Fandrich, Daniel Stenberg, dependabot[bot], Derek Huang,
|
||||
Dexter Gerig, Harry Sintonen, Jeremy Drake, John Bampton, Joseph Chen,
|
||||
kayrus on github, kriztalz, Laurențiu Nicola, lf- on github, Marcel Raad,
|
||||
Mark Phillips, qhill on github, Ray Satiro, renovate[bot], rmg-x on github,
|
||||
RubisetCie on github, Sergey, Stefan Eissing, Tianyi Song, Timo Tijhof,
|
||||
Viktor Szakats, Yedaya Katsman, Zenju on github
|
||||
(28 contributors)
|
||||
Anthony Hu, Daniel Stenberg, dependabot[bot], Dexter Gerig, Harry Sintonen,
|
||||
John Bampton, Joseph Chen, kayrus on github, kriztalz, lf- on github,
|
||||
Marcel Raad, Mark Phillips, Ray Satiro, rmg-x on github,
|
||||
RubisetCie on Github, Sergey, Stefan Eissing, Viktor Szakats,
|
||||
Zenju on github
|
||||
(19 contributors)
|
||||
|
||||
References to bug reports and discussions on issues:
|
||||
|
||||
@ -204,11 +154,8 @@ References to bug reports and discussions on issues:
|
||||
[45] = https://curl.se/bug/?i=16100
|
||||
[46] = https://curl.se/bug/?i=16375
|
||||
[47] = https://curl.se/bug/?i=16357
|
||||
[48] = https://curl.se/bug/?i=16436
|
||||
[49] = https://curl.se/bug/?i=16352
|
||||
[50] = https://curl.se/bug/?i=16167
|
||||
[51] = https://curl.se/bug/?i=16409
|
||||
[52] = https://curl.se/bug/?i=16443
|
||||
[53] = https://curl.se/bug/?i=16367
|
||||
[54] = https://curl.se/bug/?i=16384
|
||||
[55] = https://curl.se/bug/?i=16366
|
||||
@ -221,53 +168,8 @@ References to bug reports and discussions on issues:
|
||||
[62] = https://curl.se/bug/?i=16252
|
||||
[63] = https://curl.se/bug/?i=16356
|
||||
[64] = https://curl.se/bug/?i=16117
|
||||
[65] = https://curl.se/bug/?i=16417
|
||||
[66] = https://curl.se/bug/?i=16396
|
||||
[67] = https://curl.se/bug/?i=16399
|
||||
[68] = https://curl.se/bug/?i=16398
|
||||
[69] = https://curl.se/bug/?i=16441
|
||||
[70] = https://curl.se/bug/?i=16205
|
||||
[71] = https://curl.se/bug/?i=16385
|
||||
[72] = https://curl.se/bug/?i=16373
|
||||
[73] = https://curl.se/bug/?i=16435
|
||||
[74] = https://curl.se/bug/?i=16308
|
||||
[76] = https://curl.se/bug/?i=16426
|
||||
[77] = https://curl.se/bug/?i=16434
|
||||
[78] = https://curl.se/bug/?i=16330
|
||||
[79] = https://curl.se/bug/?i=15956
|
||||
[80] = https://curl.se/bug/?i=16423
|
||||
[81] = https://curl.se/bug/?i=16427
|
||||
[82] = https://curl.se/bug/?i=16494
|
||||
[84] = https://curl.se/bug/?i=16482
|
||||
[85] = https://curl.se/bug/?i=16407
|
||||
[86] = https://curl.se/bug/?i=16377
|
||||
[87] = https://curl.se/bug/?i=15975
|
||||
[88] = https://curl.se/bug/?i=16419
|
||||
[89] = https://curl.se/bug/?i=16487
|
||||
[90] = https://curl.se/bug/?i=16488
|
||||
[91] = https://curl.se/bug/?i=16420
|
||||
[92] = https://curl.se/bug/?i=16393
|
||||
[93] = https://curl.se/bug/?i=16277
|
||||
[94] = https://curl.se/bug/?i=16134
|
||||
[95] = https://curl.se/bug/?i=16104
|
||||
[96] = https://curl.se/bug/?i=16004
|
||||
[97] = https://curl.se/bug/?i=16217
|
||||
[98] = https://curl.se/bug/?i=16408
|
||||
[99] = https://curl.se/bug/?i=16478
|
||||
[100] = https://curl.se/bug/?i=16464
|
||||
[101] = https://curl.se/bug/?i=16329
|
||||
[102] = https://curl.se/bug/?i=16467
|
||||
[103] = https://curl.se/bug/?i=16466
|
||||
[104] = https://curl.se/bug/?i=16099
|
||||
[105] = https://curl.se/bug/?i=16468
|
||||
[106] = https://curl.se/bug/?i=16459
|
||||
[107] = https://curl.se/bug/?i=16460
|
||||
[108] = https://curl.se/bug/?i=16461
|
||||
[109] = https://curl.se/bug/?i=16462
|
||||
[111] = https://curl.se/bug/?i=16446
|
||||
[112] = https://curl.se/bug/?i=16457
|
||||
[113] = https://curl.se/bug/?i=16456
|
||||
[114] = https://curl.se/bug/?i=16455
|
||||
[115] = https://curl.se/bug/?i=16453
|
||||
[116] = https://curl.se/bug/?i=16452
|
||||
[119] = https://curl.se/bug/?i=16448
|
||||
|
||||
55
appveyor.sh
55
appveyor.sh
@ -36,8 +36,6 @@ esac
|
||||
if [ "${APPVEYOR_BUILD_WORKER_IMAGE}" = 'Visual Studio 2022' ]; then
|
||||
openssl_root_win="C:/OpenSSL-v34${openssl_suffix}"
|
||||
elif [ "${APPVEYOR_BUILD_WORKER_IMAGE}" = 'Visual Studio 2019' ]; then
|
||||
openssl_root_win="C:/OpenSSL-v11${openssl_suffix}"
|
||||
elif [ "${APPVEYOR_BUILD_WORKER_IMAGE}" = 'Visual Studio 2013' ]; then
|
||||
openssl_root_win="C:/OpenSSL${openssl_suffix}"
|
||||
else
|
||||
openssl_root_win="C:/OpenSSL-v111${openssl_suffix}"
|
||||
@ -54,49 +52,35 @@ if [ "${BUILD_SYSTEM}" = 'CMake' ]; then
|
||||
[ -n "${TOOLSET:-}" ] && options+=" -T ${TOOLSET}"
|
||||
[ "${OPENSSL}" = 'ON' ] && options+=" -DOPENSSL_ROOT_DIR=${openssl_root_win}"
|
||||
[ -n "${CURLDEBUG:-}" ] && options+=" -DENABLE_CURLDEBUG=${CURLDEBUG}"
|
||||
if [ "${APPVEYOR_BUILD_WORKER_IMAGE}" = 'Visual Studio 2013' ]; then
|
||||
mkdir "_bld${_chkprefill}"
|
||||
cd "_bld${_chkprefill}"
|
||||
options+=' ..'
|
||||
root='..'
|
||||
else
|
||||
options+=" -B _bld${_chkprefill}"
|
||||
options+=' -DCMAKE_VS_GLOBALS=TrackFileAccess=false'
|
||||
options+=" -DCMAKE_UNITY_BUILD=${UNITY}"
|
||||
root='.'
|
||||
fi
|
||||
# shellcheck disable=SC2086
|
||||
time cmake -G "${PRJ_GEN}" ${TARGET} \
|
||||
-DCURL_TEST_BUNDLES=ON \
|
||||
cmake -B "_bld${_chkprefill}" -G "${PRJ_GEN}" ${TARGET} \
|
||||
-DCMAKE_VS_GLOBALS=TrackFileAccess=false \
|
||||
-DCMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG= \
|
||||
-DCMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE= \
|
||||
-DCMAKE_UNITY_BUILD="${UNITY}" -DCURL_TEST_BUNDLES=ON \
|
||||
-DCURL_WERROR=ON \
|
||||
-DBUILD_SHARED_LIBS="${SHARED}" \
|
||||
-DCURL_STATIC_CRT=ON \
|
||||
-DENABLE_DEBUG="${DEBUG}" \
|
||||
-DENABLE_UNICODE="${ENABLE_UNICODE}" \
|
||||
-DHTTP_ONLY="${HTTP_ONLY}" \
|
||||
-DCURL_USE_SCHANNEL="${SCHANNEL}" \
|
||||
-DCURL_USE_OPENSSL="${OPENSSL}" \
|
||||
-DCURL_USE_LIBPSL=OFF \
|
||||
${options} \
|
||||
|| { cat ${root}/_bld/CMakeFiles/CMake* 2>/dev/null; false; }
|
||||
[ "${APPVEYOR_BUILD_WORKER_IMAGE}" = 'Visual Studio 2013' ] && cd ..
|
||||
${options}
|
||||
done
|
||||
if [ -d _bld_chkprefill ] && ! diff -u _bld/lib/curl_config.h _bld_chkprefill/lib/curl_config.h; then
|
||||
cat _bld_chkprefill/CMakeFiles/CMake* 2>/dev/null || true
|
||||
cat _bld_chkprefill/CMakeFiles/CMakeConfigureLog.yaml 2>/dev/null || true
|
||||
false
|
||||
fi
|
||||
if false; then
|
||||
cat _bld/CMakeFiles/CMakeConfigureLog.yaml 2>/dev/null || true
|
||||
fi
|
||||
echo 'curl_config.h'; grep -F '#define' _bld/lib/curl_config.h | sort || true
|
||||
# shellcheck disable=SC2086
|
||||
if ! time cmake --build _bld --config "${PRJ_CFG}" --parallel 2 -- ${BUILD_OPT:-}; then
|
||||
if [ "${PRJ_GEN}" = 'Visual Studio 9 2008' ]; then
|
||||
find . -name BuildLog.htm -exec dos2unix '{}' +
|
||||
find . -name BuildLog.htm -exec cat '{}' +
|
||||
fi
|
||||
false
|
||||
fi
|
||||
[ "${SHARED}" = 'ON' ] && PATH="$PWD/_bld/lib/${PRJ_CFG}:$PATH"
|
||||
[ "${OPENSSL}" = 'ON' ] && { PATH="${openssl_root}:$PATH"; cp "${openssl_root}"/*.dll "_bld/src/${PRJ_CFG}"; }
|
||||
curl="_bld/src/${PRJ_CFG}/curl.exe"
|
||||
cmake --build _bld --config "${PRJ_CFG}" --parallel 2 -- ${BUILD_OPT:-}
|
||||
[ "${SHARED}" = 'ON' ] && PATH="$PWD/_bld/lib:$PATH"
|
||||
[ "${OPENSSL}" = 'ON' ] && PATH="${openssl_root}:$PATH"
|
||||
curl='_bld/src/curl.exe'
|
||||
elif [ "${BUILD_SYSTEM}" = 'VisualStudioSolution' ]; then
|
||||
(
|
||||
cd projects
|
||||
@ -129,7 +113,7 @@ EOF
|
||||
curl="builds/libcurl-vc14.10-x64-${PATHPART}-dll-ssl-dll-ipv6-sspi/bin/curl.exe"
|
||||
fi
|
||||
|
||||
find . \( -name '*.exe' -o -name '*.dll' -o -name '*.lib' -o -name '*.pdb' \) -exec file '{}' \;
|
||||
find . \( -name '*.exe' -o -name '*.dll' -o -name '*.lib' \) -exec file '{}' \;
|
||||
if [ -z "${SKIP_RUN:-}" ]; then
|
||||
"${curl}" --disable --version
|
||||
else
|
||||
@ -140,14 +124,13 @@ fi
|
||||
|
||||
if [ "${TFLAGS}" != 'skipall' ] && \
|
||||
[ "${BUILD_SYSTEM}" = 'CMake' ]; then
|
||||
time cmake --build _bld --config "${PRJ_CFG}" --parallel 2 --target testdeps
|
||||
cmake --build _bld --config "${PRJ_CFG}" --parallel 2 --target testdeps
|
||||
fi
|
||||
|
||||
# run tests
|
||||
|
||||
if [ "${TFLAGS}" != 'skipall' ] && \
|
||||
[ "${TFLAGS}" != 'skiprun' ]; then
|
||||
export CURL_DIRSUFFIX="${PRJ_CFG}"
|
||||
if [ -x "$(cygpath "${SYSTEMROOT}/System32/curl.exe")" ]; then
|
||||
TFLAGS+=" -ac $(cygpath "${SYSTEMROOT}/System32/curl.exe")"
|
||||
elif [ -x "$(cygpath 'C:/msys64/usr/bin/curl.exe')" ]; then
|
||||
@ -155,12 +138,12 @@ if [ "${TFLAGS}" != 'skipall' ] && \
|
||||
fi
|
||||
TFLAGS+=' -j0'
|
||||
if [ "${BUILD_SYSTEM}" = 'CMake' ]; then
|
||||
time cmake --build _bld --config "${PRJ_CFG}" --target test-ci
|
||||
cmake --build _bld --config "${PRJ_CFG}" --target test-ci
|
||||
else
|
||||
(
|
||||
TFLAGS="-a -p !flaky -r -rm ${TFLAGS}"
|
||||
cd _bld/tests
|
||||
time ./runtests.pl
|
||||
./runtests.pl
|
||||
)
|
||||
fi
|
||||
fi
|
||||
@ -169,5 +152,5 @@ fi
|
||||
|
||||
if [ "${EXAMPLES}" = 'ON' ] && \
|
||||
[ "${BUILD_SYSTEM}" = 'CMake' ]; then
|
||||
time cmake --build _bld --config "${PRJ_CFG}" --parallel 2 --target curl-examples
|
||||
cmake --build _bld --config "${PRJ_CFG}" --parallel 2 --target curl-examples
|
||||
fi
|
||||
|
||||
45
appveyor.yml
45
appveyor.yml
@ -31,11 +31,8 @@
|
||||
version: 7.50.0.{build}
|
||||
|
||||
environment:
|
||||
BUILD_SYSTEM: CMake
|
||||
UNITY: 'ON'
|
||||
OPENSSL: 'OFF'
|
||||
SCHANNEL: 'OFF'
|
||||
ENABLE_UNICODE: 'OFF'
|
||||
DEBUG: 'ON'
|
||||
SHARED: 'OFF'
|
||||
HTTP_ONLY: 'OFF'
|
||||
@ -48,77 +45,89 @@ environment:
|
||||
|
||||
- job_name: 'CMake, VS2022, Release, x64, OpenSSL 3.4, Shared, Build-tests'
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: 'Visual Studio 2022'
|
||||
BUILD_SYSTEM: CMake
|
||||
PRJ_GEN: 'Visual Studio 17 2022'
|
||||
TARGET: '-A x64'
|
||||
PRJ_CFG: Release
|
||||
OPENSSL: 'ON'
|
||||
SCHANNEL: 'OFF'
|
||||
ENABLE_UNICODE: 'OFF'
|
||||
SHARED: 'ON'
|
||||
- job_name: 'CMake, VS2022, Release, arm64, Schannel, Static, Build-tests'
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: 'Visual Studio 2022'
|
||||
BUILD_SYSTEM: CMake
|
||||
PRJ_GEN: 'Visual Studio 17 2022'
|
||||
TARGET: '-A ARM64'
|
||||
PRJ_CFG: Release
|
||||
SCHANNEL: 'ON'
|
||||
ENABLE_UNICODE: 'OFF'
|
||||
DEBUG: 'OFF'
|
||||
CURLDEBUG: 'ON'
|
||||
- job_name: 'CMake, VS2008, Debug, x86, OpenSSL 1.0.2 + Schannel, Shared, Build-tests & examples'
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: 'Visual Studio 2013'
|
||||
PRJ_GEN: 'Visual Studio 9 2008'
|
||||
TARGET: '-A Win32'
|
||||
PRJ_CFG: Debug
|
||||
OPENSSL: 'ON'
|
||||
SCHANNEL: 'ON'
|
||||
SHARED: 'ON'
|
||||
EXAMPLES: 'ON'
|
||||
- job_name: 'CMake, VS2010, Debug, x64, Schannel, Shared, Build-tests & examples'
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: 'Visual Studio 2015'
|
||||
BUILD_SYSTEM: CMake
|
||||
PRJ_GEN: 'Visual Studio 10 2010'
|
||||
TARGET: '-A x64'
|
||||
PRJ_CFG: Debug
|
||||
SCHANNEL: 'ON'
|
||||
ENABLE_UNICODE: 'OFF'
|
||||
SHARED: 'ON'
|
||||
EXAMPLES: 'ON'
|
||||
- job_name: 'CMake, VS2012, Release, x86, OpenSSL 1.1.1 + Schannel, Shared, Build-tests'
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: 'Visual Studio 2015'
|
||||
BUILD_SYSTEM: CMake
|
||||
PRJ_GEN: 'Visual Studio 11 2012'
|
||||
TARGET: '-A Win32'
|
||||
PRJ_CFG: Release
|
||||
OPENSSL: 'ON'
|
||||
SCHANNEL: 'ON'
|
||||
ENABLE_UNICODE: 'OFF'
|
||||
SHARED: 'ON'
|
||||
- job_name: 'CMake, VS2013, Debug, x64, OpenSSL 1.1.1, Shared, Build-only'
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: 'Visual Studio 2015'
|
||||
BUILD_SYSTEM: CMake
|
||||
PRJ_GEN: 'Visual Studio 12 2013'
|
||||
TARGET: '-A x64'
|
||||
PRJ_CFG: Debug
|
||||
OPENSSL: 'ON'
|
||||
SCHANNEL: 'OFF'
|
||||
ENABLE_UNICODE: 'OFF'
|
||||
SHARED: 'ON'
|
||||
TFLAGS: 'skipall'
|
||||
- job_name: 'CMake, VS2015, Debug, x64, OpenSSL 1.1.1, Static, Build-only'
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: 'Visual Studio 2015'
|
||||
BUILD_SYSTEM: CMake
|
||||
PRJ_GEN: 'Visual Studio 14 2015'
|
||||
TARGET: '-A x64'
|
||||
PRJ_CFG: Debug
|
||||
OPENSSL: 'ON'
|
||||
SCHANNEL: 'OFF'
|
||||
ENABLE_UNICODE: 'OFF'
|
||||
TFLAGS: 'skipall'
|
||||
- job_name: 'CMake, VS2017, Debug, x64, OpenSSL 1.1.1, Shared, Build-only'
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: 'Visual Studio 2017'
|
||||
BUILD_SYSTEM: CMake
|
||||
PRJ_GEN: 'Visual Studio 15 2017'
|
||||
TARGET: '-A x64'
|
||||
PRJ_CFG: Debug
|
||||
OPENSSL: 'ON'
|
||||
SCHANNEL: 'OFF'
|
||||
ENABLE_UNICODE: 'OFF'
|
||||
SHARED: 'ON'
|
||||
TFLAGS: 'skipall'
|
||||
- job_name: 'CMake, VS2019, Debug, x64, OpenSSL 1.1.0 + Schannel, Shared, Build-tests'
|
||||
- job_name: 'CMake, VS2019, Debug, x64, OpenSSL 1.0.2 + Schannel, Shared, Build-tests'
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: 'Visual Studio 2019'
|
||||
BUILD_SYSTEM: CMake
|
||||
PRJ_GEN: 'Visual Studio 16 2019'
|
||||
TARGET: '-A x64'
|
||||
PRJ_CFG: Debug
|
||||
OPENSSL: 'ON'
|
||||
SCHANNEL: 'ON'
|
||||
ENABLE_UNICODE: 'OFF'
|
||||
SHARED: 'ON'
|
||||
- job_name: 'CMake, VS2022, Debug, x64, Schannel, Static, Unicode, Build-tests & examples, clang-cl'
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: 'Visual Studio 2022'
|
||||
BUILD_SYSTEM: CMake
|
||||
PRJ_GEN: 'Visual Studio 17 2022'
|
||||
TARGET: '-A x64'
|
||||
PRJ_CFG: Debug
|
||||
@ -128,6 +137,7 @@ environment:
|
||||
TOOLSET: 'ClangCl'
|
||||
- job_name: 'CMake, VS2022, Debug, x64, Schannel, Static, Unicode, Build-tests'
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: 'Visual Studio 2022'
|
||||
BUILD_SYSTEM: CMake
|
||||
PRJ_GEN: 'Visual Studio 17 2022'
|
||||
TARGET: '-A x64'
|
||||
PRJ_CFG: Debug
|
||||
@ -135,6 +145,7 @@ environment:
|
||||
ENABLE_UNICODE: 'ON'
|
||||
- job_name: 'CMake, VS2022, Release, x64, Schannel, Shared, Unicode, DEBUGBUILD, no-CURLDEBUG, Build-tests'
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: 'Visual Studio 2022'
|
||||
BUILD_SYSTEM: CMake
|
||||
PRJ_GEN: 'Visual Studio 17 2022'
|
||||
TARGET: '-A x64'
|
||||
PRJ_CFG: Release
|
||||
@ -144,14 +155,20 @@ environment:
|
||||
CURLDEBUG: 'OFF'
|
||||
- job_name: 'CMake, VS2022, Debug, x64, no SSL, Static, Build-tests'
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: 'Visual Studio 2022'
|
||||
BUILD_SYSTEM: CMake
|
||||
PRJ_GEN: 'Visual Studio 17 2022'
|
||||
TARGET: '-A x64'
|
||||
PRJ_CFG: Debug
|
||||
SCHANNEL: 'OFF'
|
||||
ENABLE_UNICODE: 'OFF'
|
||||
- job_name: 'CMake, VS2022, Debug, x64, no SSL, Static, HTTP only, Build-tests'
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: 'Visual Studio 2022'
|
||||
BUILD_SYSTEM: CMake
|
||||
PRJ_GEN: 'Visual Studio 17 2022'
|
||||
TARGET: '-A x64'
|
||||
PRJ_CFG: Debug
|
||||
SCHANNEL: 'OFF'
|
||||
ENABLE_UNICODE: 'OFF'
|
||||
HTTP_ONLY: 'ON'
|
||||
|
||||
# winbuild-based builds
|
||||
@ -237,5 +254,5 @@ skip_commits:
|
||||
#artifacts:
|
||||
# - path: '**/curl.exe'
|
||||
# name: curl
|
||||
# - path: '**/*.dll'
|
||||
# - path: '**/*curl*.dll'
|
||||
# name: libcurl dll
|
||||
|
||||
@ -21,12 +21,6 @@ CMake's GUIs.
|
||||
A CMake configuration of curl is similar to the autotools build of curl.
|
||||
It consists of the following steps after you have unpacked the source.
|
||||
|
||||
We recommend building with CMake on Windows. For instructions on migrating
|
||||
from the `projects/Windows` Visual Studio solution files, see
|
||||
[this section](#migrating-from-visual-studio-ide-project-files). For
|
||||
instructions on migrating from the winbuild builds, see
|
||||
[the following section](#migrating-from-winbuild-builds).
|
||||
|
||||
## Using `cmake`
|
||||
|
||||
You can configure for in source tree builds or for a build tree
|
||||
@ -37,14 +31,10 @@ that is apart from the source tree.
|
||||
$ cmake -B .
|
||||
|
||||
- Build in a separate directory (parallel to the curl source tree in this
|
||||
example). The build directory is created for you. This is recommended over
|
||||
building in the source tree to separate source and build artifacts.
|
||||
example). The build directory is created for you.
|
||||
|
||||
$ cmake -B ../curl-build
|
||||
|
||||
For the full list of CMake build configuration variables see
|
||||
[the corresponding section](#cmake-build-options).
|
||||
|
||||
### Fallback for CMake before version 3.13
|
||||
|
||||
CMake before version 3.13 does not support the `-B` option. In that case,
|
||||
@ -139,12 +129,6 @@ Install to default location (you have to specify the build directory).
|
||||
|
||||
$ cmake --install ../curl-build
|
||||
|
||||
Do not use `--prefix` to change the installation prefix as the output produced
|
||||
by the `curl-config` script is determined at CMake configure time. If you want
|
||||
to set a custom install prefix for curl, set
|
||||
[`CMAKE_INSTALL_PREFIX`](https://cmake.org/cmake/help/latest/variable/CMAKE_INSTALL_PREFIX.html)
|
||||
when configuring the CMake build.
|
||||
|
||||
### Fallback for CMake before version 3.15
|
||||
|
||||
CMake before version 3.15 does not support the `--install` option. In that
|
||||
@ -155,68 +139,6 @@ assumes that CMake generates `Makefile`:
|
||||
$ cd ../curl-build
|
||||
$ make install
|
||||
|
||||
# CMake usage
|
||||
|
||||
Just as curl can be built and installed using CMake, it can also be used from
|
||||
CMake.
|
||||
|
||||
## Using `find_package`
|
||||
|
||||
To locate libcurl from CMake, one can use the standard
|
||||
[`find_package`](https://cmake.org/cmake/help/latest/command/find_package.html)
|
||||
command in the typical fashion:
|
||||
|
||||
```cmake
|
||||
find_package(CURL 8.12.0 REQUIRED) # FATAL_ERROR if CURL is not found
|
||||
```
|
||||
|
||||
This invokes the CMake-provided
|
||||
[FindCURL](https://cmake.org/cmake/help/latest/module/FindCURL.html) find module,
|
||||
which first performs a search using the `find_package`
|
||||
[config mode](https://cmake.org/cmake/help/latest/command/find_package.html#config-mode-search-procedure).
|
||||
This is supported by the `CURLConfig.cmake` CMake config script which is
|
||||
available if the given CURL was built and installed using CMake.
|
||||
|
||||
### Detecting CURL features/protocols
|
||||
|
||||
Since version 8.12.0, `CURLConfig.cmake` publishes the supported CURL features
|
||||
and protocols (see [release notes](https://curl.se/ch/8.12.0.html)). These can
|
||||
be specified using the `find_package` keywords `COMPONENTS` and
|
||||
`OPTIONAL_COMPONENTS`, with protocols in all caps, e.g. `HTTPS`, `LDAP`, while
|
||||
features should be in their original sentence case, e.g. `AsynchDNS`,
|
||||
`UnixSockets`. If any of the `COMPONENTS` are missing, then CURL is considered
|
||||
as *not* found.
|
||||
|
||||
Here is an example of using `COMPONENTS` and `OPTIONAL_COMPONENTS` in
|
||||
`find_package` with CURL:
|
||||
|
||||
```cmake
|
||||
# CURL_FOUND is FALSE if no HTTPS but brotli and zstd can be missing
|
||||
find_package(CURL 8.12.0 COMPONENTS HTTPS OPTIONAL_COMPONENTS brotli zstd)
|
||||
```
|
||||
|
||||
One can also check the defined `CURL_SUPPORTS_<feature-or-protocol>` variables
|
||||
if a particular feature/protocol is supported. For example:
|
||||
|
||||
```cmake
|
||||
# check HTTPS
|
||||
if(CURL_SUPPORTS_HTTPS)
|
||||
message(STATUS "CURL supports HTTPS")
|
||||
else()
|
||||
message(STATUS "CURL does NOT support HTTPS")
|
||||
endif()
|
||||
```
|
||||
|
||||
### Linking against libcurl
|
||||
|
||||
To link a CMake target against libcurl one can use
|
||||
[`target_link_libraries`](https://cmake.org/cmake/help/latest/command/target_link_libraries.html)
|
||||
as usual:
|
||||
|
||||
```cmake
|
||||
target_link_libraries(my_target PRIVATE CURL::libcurl)
|
||||
```
|
||||
|
||||
# CMake build options
|
||||
|
||||
- `BUILD_CURL_EXE`: Build curl executable. Default: `ON`
|
||||
@ -238,7 +160,7 @@ target_link_libraries(my_target PRIVATE CURL::libcurl)
|
||||
- `CURL_LIBCURL_VERSIONED_SYMBOLS`: Enable libcurl versioned symbols. Default: `OFF`
|
||||
- `CURL_LIBCURL_VERSIONED_SYMBOLS_PREFIX`: Override default versioned symbol prefix. Default: `<TLS-BACKEND>_` or `MULTISSL_`
|
||||
- `CURL_LTO`: Enable compiler Link Time Optimizations. Default: `OFF`
|
||||
- `CURL_STATIC_CRT`: Build libcurl with static CRT with MSVC (`/MT`) (requires static or no curl executable). Default: `OFF`
|
||||
- `CURL_STATIC_CRT`: Build libcurl with static CRT with MSVC (`/MT`). Default: `OFF`
|
||||
- `CURL_TARGET_WINDOWS_VERSION`: Minimum target Windows version as hex string.
|
||||
- `CURL_TEST_BUNDLES`: Bundle `libtest` and `unittest` tests into single binaries. Default: `OFF`
|
||||
- `CURL_WERROR`: Turn compiler warnings into errors. Default: `OFF`
|
||||
@ -384,7 +306,6 @@ Details via CMake
|
||||
- `OPENSSL_USE_STATIC_LIBS`: Look for static OpenSSL libraries.
|
||||
- `ZLIB_INCLUDE_DIR`: The zlib include directory.
|
||||
- `ZLIB_LIBRARY`: Path to `zlib` library.
|
||||
- `ZLIB_USE_STATIC_LIBS`: Look for static ZLIB library (requires CMake v3.24).
|
||||
|
||||
## Dependency options
|
||||
|
||||
@ -458,7 +379,7 @@ Details via CMake
|
||||
|
||||
# Migrating from Visual Studio IDE Project Files
|
||||
|
||||
We recommend using CMake to build curl with MSVC.
|
||||
We recommend CMake to build curl with MSVC.
|
||||
|
||||
The project build files reside in project/Windows/VC\* for VS2010, VS2010 and
|
||||
VS2013 respectively.
|
||||
@ -478,8 +399,8 @@ Configuration element | Equivalent CMake options
|
||||
`Win32` | `-A Win32`
|
||||
`DLL` | `BUILD_SHARED_LIBS=ON`, `BUILD_STATIC_LIBS=OFF`, (default)
|
||||
`LIB` | `BUILD_SHARED_LIBS=OFF`, `BUILD_STATIC_LIBS=ON`
|
||||
`Debug` | `CMAKE_BUILD_TYPE=Debug` (`-G "NMake Makefiles"` only)
|
||||
`Release` | `CMAKE_BUILD_TYPE=Release` (`-G "NMake Makefiles"` only)
|
||||
`Debug` | `CMAKE_BUILD_TYPE=Debug`
|
||||
`Release` | `CMAKE_BUILD_TYPE=Release`
|
||||
`DLL Windows SSPI` | `CURL_USE_SCHANNEL=ON` (with SSPI enabled by default)
|
||||
`DLL OpenSSL` | `CURL_USE_OPENSSL=ON`, optional: `OPENSSL_ROOT_DIR`, `OPENSSL_USE_STATIC_LIBS=ON`
|
||||
`DLL libssh2` | `CURL_USE_LIBSSH2=ON`, optional: `LIBSSH2_INCLUDE_DIR`, `LIBSSH2_LIBRARY`
|
||||
@ -493,13 +414,7 @@ For example these commands:
|
||||
|
||||
translate to:
|
||||
|
||||
> cmake . -G "Visual Studio 12 2013" -A x64 -DCURL_USE_SCHANNEL=ON -DUSE_WIN32_IDN=ON -DCURL_USE_LIBPSL=OFF
|
||||
> cmake --build . --config Debug --parallel
|
||||
|
||||
We do *not* specify `-DCMAKE_BUILD_TYPE=Debug` here as we might do for the
|
||||
`"NMake Makefiles"` generator because the Visual Studio generators are
|
||||
[multi-config generators](https://cmake.org/cmake/help/latest/prop_gbl/GENERATOR_IS_MULTI_CONFIG.html)
|
||||
and therefore ignore the value of `CMAKE_BUILD_TYPE`.
|
||||
> cmake . -G "Visual Studio 12 2013" -A x64 -DCMAKE_BUILD_TYPE=Debug -DCURL_USE_SCHANNEL=ON -DUSE_WIN32_IDN=ON -DCURL_USE_LIBPSL=OFF
|
||||
|
||||
# Migrating from winbuild builds
|
||||
|
||||
@ -522,7 +437,7 @@ winbuild options | Equivalent CMake options
|
||||
`DEBUG` | `CMAKE_BUILD_TYPE=Debug`
|
||||
`GEN_PDB` | `CMAKE_EXE_LINKER_FLAGS=/Fd<path>`, `CMAKE_SHARED_LINKER_FLAGS=/Fd<path>`
|
||||
`LIB_NAME_DLL`, `LIB_NAME_STATIC` | `IMPORT_LIB_SUFFIX`, `LIBCURL_OUTPUT_NAME`, `STATIC_LIB_SUFFIX`
|
||||
`VC`: `<N>` | see the CMake [Visual Studio generators](https://cmake.org/cmake/help/latest/manual/cmake-generators.7.html#visual-studio-generators)
|
||||
`VC` | see CMake `-G` [options](https://cmake.org/cmake/help/latest/manual/cmake-generators.7.html)
|
||||
`MACHINE`: `x64`, `x86` | `-A x64`, `-A Win32`
|
||||
`MODE`: `dll`, `static` | `BUILD_SHARED_LIBS=ON/OFF`, `BUILD_STATIC_LIBS=ON/OFF`, `BUILD_STATIC_CURL=ON/OFF` (default: dll)
|
||||
`RTLIBCFG`: `static` | `CURL_STATIC_CRT=ON`
|
||||
@ -552,8 +467,4 @@ For example this command-line:
|
||||
|
||||
translates to:
|
||||
|
||||
> cmake . -G "Visual Studio 17 2022" -A x64 -DBUILD_SHARED_LIBS=ON -DOPENSSL_ROOT_DIR=C:\OpenSSL -DCURL_USE_OPENSSL=ON -DENABLE_UNICODE=ON -DCURL_USE_LIBPSL=OFF
|
||||
> cmake --build . --config Debug
|
||||
|
||||
We use `--config` with `cmake --build` because the Visual Studio CMake
|
||||
generators are multi-config and therefore ignore `CMAKE_BUILD_TYPE`.
|
||||
> cmake . -G "Visual Studio 17 2022" -A x64 -DCMAKE_BUILD_TYPE=Debug -DBUILD_SHARED_LIBS=ON -DOPENSSL_ROOT_DIR=C:\OpenSSL -DCURL_USE_OPENSSL=ON -DENABLE_UNICODE=ON -DCURL_USE_LIBPSL=OFF
|
||||
|
||||
@ -52,7 +52,6 @@ INTERNALDOCS = \
|
||||
internals/HASH.md \
|
||||
internals/LLIST.md \
|
||||
internals/MQTT.md \
|
||||
internals/MULTI-EV.md \
|
||||
internals/NEW-PROTOCOL.md \
|
||||
internals/README.md \
|
||||
internals/SPLAY.md \
|
||||
|
||||
@ -9,7 +9,7 @@ SPDX-License-Identifier: curl
|
||||
[Rustls is a TLS backend written in Rust](https://docs.rs/rustls/). curl can
|
||||
be built to use it as an alternative to OpenSSL or other TLS backends. We use
|
||||
the [rustls-ffi C bindings](https://github.com/rustls/rustls-ffi/). This
|
||||
version of curl is compatible with `rustls-ffi` v0.14.x.
|
||||
version of curl depends on version v0.14.0 of rustls-ffi.
|
||||
|
||||
# Building with Rustls
|
||||
|
||||
@ -17,7 +17,7 @@ First, [install Rust](https://rustup.rs/).
|
||||
|
||||
Next, check out, build, and install the appropriate version of rustls-ffi:
|
||||
|
||||
% git clone https://github.com/rustls/rustls-ffi -b v0.14.1
|
||||
% git clone https://github.com/rustls/rustls-ffi -b v0.14.0
|
||||
% cd rustls-ffi
|
||||
% make
|
||||
% make DESTDIR=${HOME}/rustls-ffi-built/ install
|
||||
|
||||
@ -157,4 +157,3 @@ s/edmcln\z/edmcln on github/
|
||||
s/andrewkirillov-ibm/Andrew Kirillov/
|
||||
s/\(.*\) via #[0-9]*//
|
||||
s/jethrogb$/jethrogb on github/
|
||||
s/on github/on github/i
|
||||
|
||||
@ -247,11 +247,11 @@ local system or network, the bar is raised. If a local user wrongfully has
|
||||
elevated rights on your system enough to attack curl, they can probably
|
||||
already do much worse harm and the problem is not really in curl.
|
||||
|
||||
## Debug & Experiments
|
||||
## Experiments
|
||||
|
||||
Vulnerabilities in features which are off by default (in the build) and
|
||||
documented as experimental, or exist only in debug mode, are not eligible for a
|
||||
reward and we do not consider them security problems.
|
||||
documented as experimental, are not eligible for a reward and we do not
|
||||
consider them security problems.
|
||||
|
||||
## URL inconsistencies
|
||||
|
||||
|
||||
@ -27,10 +27,10 @@ set:
|
||||
When expanding variables, curl supports a set of functions that can make the
|
||||
variable contents more convenient to use. It can trim leading and trailing
|
||||
white space with `trim`, it can output the contents as a JSON quoted string
|
||||
with `json`, URL encode the string with `url`, base64 encode it with `b64` and
|
||||
base64 decode it with `64dec`. To apply functions to a variable expansion, add
|
||||
them colon separated to the right side of the variable. Variable content
|
||||
holding null bytes that are not encoded when expanded cause error.
|
||||
with `json`, URL encode the string with `url` or base64 encode it with `b64`.
|
||||
To apply functions to a variable expansion, add them colon separated to the
|
||||
right side of the variable. Variable content holding null bytes that are not
|
||||
encoded when expanded cause error.
|
||||
|
||||
Example: get the contents of a file called $HOME/.secret into a variable
|
||||
called "fix". Make sure that the content is trimmed and percent-encoded when
|
||||
|
||||
@ -59,4 +59,4 @@ used.
|
||||
|
||||
Doing FTP over an HTTP proxy without --proxytunnel makes curl do HTTP with an
|
||||
FTP URL over the proxy. For such transfers, common FTP specific options do not
|
||||
work, including --ssl-reqd and --ftp-ssl-control.
|
||||
work, including --ftp-ssl-reqd and --ftp-ssl-control.
|
||||
|
||||
@ -38,8 +38,5 @@ for you, it is probably not a good idea to use early data for it. curl
|
||||
cannot deduce what the security implications of your requests actually
|
||||
are and make this decision for you.
|
||||
|
||||
The amount of early data sent can be inspected by using the `--write-out`
|
||||
variable `tls_earlydata`.
|
||||
|
||||
**WARNING**: this option has security implications. See above for more
|
||||
details.
|
||||
|
||||
@ -2,19 +2,16 @@
|
||||
c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
SPDX-License-Identifier: curl
|
||||
Long: url
|
||||
Arg: <url/file>
|
||||
Help: URL(s) to work with
|
||||
Arg: <url>
|
||||
Help: URL to work with
|
||||
Category: curl
|
||||
Added: 7.5
|
||||
Multi: append
|
||||
See-also:
|
||||
- next
|
||||
- config
|
||||
- path-as-is
|
||||
- disallow-username-in-url
|
||||
Example:
|
||||
- --url $URL
|
||||
- --url @file
|
||||
---
|
||||
|
||||
# `--url`
|
||||
@ -35,15 +32,3 @@ destination option unless --remote-name-all is used.
|
||||
|
||||
On Windows, `file://` accesses can be converted to network accesses by the
|
||||
operating system.
|
||||
|
||||
Starting in curl 8.13.0, curl can be told to download URLs provided in a text
|
||||
file, one URL per line. It is done by with `--url @filename`: so instead of a
|
||||
URL, you specify a filename prefixed with the `@` symbol. It can be told to
|
||||
load the list of URLs from stdin by providing an argument like `@-`.
|
||||
|
||||
When downloading URLs given in a file, it implies using --remote-name for each
|
||||
provided URL. The URLs are full, there is no globbing applied or done on
|
||||
these. Features such as --skip-existing work fine in combination with this.
|
||||
|
||||
Lines in the URL file that start with `#` are treated as comments and are
|
||||
skipped.
|
||||
|
||||
@ -66,45 +66,30 @@ error.
|
||||
|
||||
Available functions:
|
||||
|
||||
## `trim`
|
||||
|
||||
## trim
|
||||
removes all leading and trailing white space.
|
||||
|
||||
Example:
|
||||
|
||||
curl --expand-url https://example.com/{{var:trim}}
|
||||
|
||||
## `json`
|
||||
|
||||
## json
|
||||
outputs the content using JSON string quoting rules.
|
||||
|
||||
Example:
|
||||
|
||||
curl --expand-data {{data:json}} https://example.com
|
||||
|
||||
## `url`
|
||||
|
||||
## url
|
||||
shows the content URL (percent) encoded.
|
||||
|
||||
Example:
|
||||
|
||||
curl --expand-url https://example.com/{{path:url}}
|
||||
|
||||
## `b64`
|
||||
|
||||
## b64
|
||||
expands the variable base64 encoded
|
||||
|
||||
Example:
|
||||
|
||||
curl --expand-url https://example.com/{{var:b64}}
|
||||
|
||||
## `64dec`
|
||||
|
||||
decodes a base64 encoded character sequence. If the sequence is not possible
|
||||
to decode, it instead outputs `[64dec-fail]`
|
||||
|
||||
Example:
|
||||
|
||||
curl --expand-url https://example.com/{{var:64dec}}
|
||||
|
||||
(Added in 8.13.0)
|
||||
|
||||
@ -62,7 +62,7 @@ The variables available are:
|
||||
|
||||
## `certs`
|
||||
Output the certificate chain with details. Supported only by the OpenSSL,
|
||||
GnuTLS, Schannel, Rustls, and Secure Transport backends. (Added in 7.88.0)
|
||||
GnuTLS, Schannel and Secure Transport backends. (Added in 7.88.0)
|
||||
|
||||
## `conn_id`
|
||||
The connection identifier last used by the transfer. The connection id is
|
||||
@ -128,7 +128,7 @@ The http method used in the most recent HTTP request. (Added in 7.72.0)
|
||||
|
||||
## `num_certs`
|
||||
Number of server certificates received in the TLS handshake. Supported only by
|
||||
the OpenSSL, GnuTLS, Schannel, Rustls and Secure Transport backends.
|
||||
the OpenSSL, GnuTLS, Schannel and Secure Transport backends.
|
||||
(Added in 7.88.0)
|
||||
|
||||
## `num_connects`
|
||||
@ -262,12 +262,6 @@ the result.
|
||||
## `time_total`
|
||||
The total time, in seconds, that the full operation lasted.
|
||||
|
||||
## `tls_earlydata`
|
||||
The amount of bytes that were sent as TLSv1.3 early data. This is 0
|
||||
if this TLS feature was not used and negative if the data sent had
|
||||
been rejected by the server. The use of early data is enabled via
|
||||
the command line option `--tls-earlydata`. (Added in 8.12.0)
|
||||
|
||||
## `url`
|
||||
The URL that was fetched. (Added in 7.75.0)
|
||||
|
||||
|
||||
@ -24,53 +24,53 @@ displays information about the curl and libcurl installation.
|
||||
|
||||
# OPTIONS
|
||||
|
||||
## `--ca`
|
||||
## --ca
|
||||
|
||||
Displays the built-in path to the CA cert bundle this libcurl uses.
|
||||
|
||||
## `--cc`
|
||||
## --cc
|
||||
|
||||
Displays the compiler used to build libcurl.
|
||||
|
||||
## `--cflags`
|
||||
## --cflags
|
||||
|
||||
Set of compiler options (CFLAGS) to use when compiling files that use
|
||||
libcurl. Currently that is only the include path to the curl include files.
|
||||
|
||||
## `--checkfor [version]`
|
||||
## --checkfor [version]
|
||||
|
||||
Specify the oldest possible libcurl version string you want, and this script
|
||||
returns 0 if the current installation is new enough or it returns 1 and
|
||||
outputs a text saying that the current version is not new enough. (Added in
|
||||
7.15.4)
|
||||
|
||||
## `--configure`
|
||||
## --configure
|
||||
|
||||
Displays the arguments given to configure when building curl.
|
||||
|
||||
## `--feature`
|
||||
## --feature
|
||||
|
||||
Lists what particular main features the installed libcurl was built with. At
|
||||
the time of writing, this list may include SSL, KRB4 or IPv6. Do not assume
|
||||
any particular order. The keywords are separated by newlines. There may be
|
||||
none, one, or several keywords in the list.
|
||||
|
||||
## `--help`
|
||||
## --help
|
||||
|
||||
Displays the available options.
|
||||
|
||||
## `--libs`
|
||||
## --libs
|
||||
|
||||
Shows the complete set of libs and other linker options you need in order to
|
||||
link your application with libcurl.
|
||||
|
||||
## `--prefix`
|
||||
## --prefix
|
||||
|
||||
This is the prefix used when libcurl was installed. libcurl is then installed
|
||||
in $prefix/lib and its header files are installed in $prefix/include and so
|
||||
on. The prefix is set with `configure --prefix`.
|
||||
on. The prefix is set with "configure --prefix".
|
||||
|
||||
## `--protocols`
|
||||
## --protocols
|
||||
|
||||
Lists what particular protocols the installed libcurl was built to support. At
|
||||
the time of writing, this list may include HTTP, HTTPS, FTP, FTPS, FILE,
|
||||
@ -78,22 +78,22 @@ TELNET, LDAP, DICT and many more. Do not assume any particular order. The
|
||||
protocols are listed using uppercase and are separated by newlines. There may
|
||||
be none, one, or several protocols in the list. (Added in 7.13.0)
|
||||
|
||||
## `--ssl-backends`
|
||||
## --ssl-backends
|
||||
|
||||
Lists the SSL backends that were enabled when libcurl was built. It might be
|
||||
no, one or several names. If more than one name, they appear comma-separated.
|
||||
(Added in 7.58.0)
|
||||
|
||||
## `--static-libs`
|
||||
## --static-libs
|
||||
|
||||
Shows the complete set of libs and other linker options you need in order to
|
||||
link your application with libcurl statically. (Added in 7.17.1)
|
||||
|
||||
## `--version`
|
||||
## --version
|
||||
|
||||
Outputs version information about the installed libcurl.
|
||||
|
||||
## `--vernum`
|
||||
## --vernum
|
||||
|
||||
Outputs version information about the installed libcurl, in numerical mode.
|
||||
This shows the version number, in hexadecimal, using 8 bits for each part:
|
||||
@ -104,21 +104,22 @@ omitted. (This option was broken in the 7.15.0 release.)
|
||||
# EXAMPLES
|
||||
|
||||
What linker options do I need when I link with libcurl?
|
||||
|
||||
$ curl-config --libs
|
||||
|
||||
~~~
|
||||
$ curl-config --libs
|
||||
~~~
|
||||
What compiler options do I need when I compile using libcurl functions?
|
||||
|
||||
$ curl-config --cflags
|
||||
|
||||
~~~
|
||||
$ curl-config --cflags
|
||||
~~~
|
||||
How do I know if libcurl was built with SSL support?
|
||||
|
||||
$ curl-config --feature | grep SSL
|
||||
|
||||
~~~
|
||||
$ curl-config --feature | grep SSL
|
||||
~~~
|
||||
What's the installed libcurl version?
|
||||
|
||||
$ curl-config --version
|
||||
|
||||
~~~
|
||||
$ curl-config --version
|
||||
~~~
|
||||
How do I build a single file with a one-line command?
|
||||
|
||||
$ `curl-config --cc --cflags` -o example source.c `curl-config --libs`
|
||||
~~~
|
||||
$ `curl-config --cc --cflags` -o example source.c `curl-config --libs`
|
||||
~~~
|
||||
|
||||
@ -298,19 +298,14 @@ int main(void)
|
||||
|
||||
filter = (struct connection_filter *)calloc(1, sizeof(*filter));
|
||||
if(!filter)
|
||||
return 1;
|
||||
exit(1);
|
||||
|
||||
if(curl_global_init(CURL_GLOBAL_DEFAULT)) {
|
||||
free(filter);
|
||||
return 1;
|
||||
}
|
||||
if(curl_global_init(CURL_GLOBAL_DEFAULT))
|
||||
exit(1);
|
||||
|
||||
curl = curl_easy_init();
|
||||
if(!curl) {
|
||||
curl_global_cleanup();
|
||||
free(filter);
|
||||
return 1;
|
||||
}
|
||||
if(!curl)
|
||||
exit(1);
|
||||
|
||||
/* Set the target URL */
|
||||
curl_easy_setopt(curl, CURLOPT_URL, "http://localhost");
|
||||
|
||||
@ -79,12 +79,12 @@ int main(int argc, char *argv[])
|
||||
fprintf(stderr,
|
||||
"\rUsage: %s [-m=1|2|5|10|20|50|100] [-t] [-x] [url]\n",
|
||||
appname);
|
||||
return 1;
|
||||
exit(1);
|
||||
case 'v':
|
||||
case 'V':
|
||||
fprintf(stderr, "\r%s %s - %s\n",
|
||||
appname, CHKSPEED_VERSION, curl_version());
|
||||
return 1;
|
||||
exit(1);
|
||||
case 'a':
|
||||
case 'A':
|
||||
prtall = 1;
|
||||
|
||||
@ -34,7 +34,8 @@
|
||||
#include <curl/curl.h>
|
||||
#include <curl/mprintf.h>
|
||||
|
||||
static int print_cookies(CURL *curl)
|
||||
static void
|
||||
print_cookies(CURL *curl)
|
||||
{
|
||||
CURLcode res;
|
||||
struct curl_slist *cookies;
|
||||
@ -46,7 +47,7 @@ static int print_cookies(CURL *curl)
|
||||
if(res != CURLE_OK) {
|
||||
fprintf(stderr, "Curl curl_easy_getinfo failed: %s\n",
|
||||
curl_easy_strerror(res));
|
||||
return 1;
|
||||
exit(1);
|
||||
}
|
||||
nc = cookies;
|
||||
i = 1;
|
||||
@ -59,8 +60,6 @@ static int print_cookies(CURL *curl)
|
||||
printf("(none)\n");
|
||||
}
|
||||
curl_slist_free_all(cookies);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
|
||||
@ -418,22 +418,22 @@ static int init_fifo(GlobalInfo *g)
|
||||
struct epoll_event epev;
|
||||
|
||||
fprintf(MSG_OUT, "Creating named pipe \"%s\"\n", fifo);
|
||||
if(lstat(fifo, &st) == 0) {
|
||||
if(lstat (fifo, &st) == 0) {
|
||||
if((st.st_mode & S_IFMT) == S_IFREG) {
|
||||
errno = EEXIST;
|
||||
perror("lstat");
|
||||
return 1;
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
unlink(fifo);
|
||||
if(mkfifo(fifo, 0600) == -1) {
|
||||
if(mkfifo (fifo, 0600) == -1) {
|
||||
perror("mkfifo");
|
||||
return 1;
|
||||
exit(1);
|
||||
}
|
||||
sockfd = open(fifo, O_RDWR | O_NONBLOCK, 0);
|
||||
if(sockfd == -1) {
|
||||
perror("open");
|
||||
return 1;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
g->fifofd = sockfd;
|
||||
@ -449,9 +449,9 @@ static int init_fifo(GlobalInfo *g)
|
||||
|
||||
static void clean_fifo(GlobalInfo *g)
|
||||
{
|
||||
epoll_ctl(g->epfd, EPOLL_CTL_DEL, g->fifofd, NULL);
|
||||
fclose(g->input);
|
||||
unlink(fifo);
|
||||
epoll_ctl(g->epfd, EPOLL_CTL_DEL, g->fifofd, NULL);
|
||||
fclose(g->input);
|
||||
unlink(fifo);
|
||||
}
|
||||
|
||||
|
||||
@ -478,13 +478,13 @@ int main(int argc, char **argv)
|
||||
g.epfd = epoll_create1(EPOLL_CLOEXEC);
|
||||
if(g.epfd == -1) {
|
||||
perror("epoll_create1 failed");
|
||||
return 1;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
g.tfd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC);
|
||||
if(g.tfd == -1) {
|
||||
perror("timerfd_create failed");
|
||||
return 1;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
memset(&its, 0, sizeof(struct itimerspec));
|
||||
@ -496,8 +496,7 @@ int main(int argc, char **argv)
|
||||
ev.data.fd = g.tfd;
|
||||
epoll_ctl(g.epfd, EPOLL_CTL_ADD, g.tfd, &ev);
|
||||
|
||||
if(init_fifo(&g))
|
||||
return 1;
|
||||
init_fifo(&g);
|
||||
g.multi = curl_multi_init();
|
||||
|
||||
/* setup the generic multi interface options we want */
|
||||
@ -522,7 +521,7 @@ int main(int argc, char **argv)
|
||||
}
|
||||
else {
|
||||
perror("epoll_wait");
|
||||
return 1;
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -402,22 +402,22 @@ static int init_fifo(GlobalInfo *g)
|
||||
curl_socket_t sockfd;
|
||||
|
||||
fprintf(MSG_OUT, "Creating named pipe \"%s\"\n", fifo);
|
||||
if(lstat(fifo, &st) == 0) {
|
||||
if(lstat (fifo, &st) == 0) {
|
||||
if((st.st_mode & S_IFMT) == S_IFREG) {
|
||||
errno = EEXIST;
|
||||
perror("lstat");
|
||||
return 1;
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
unlink(fifo);
|
||||
if(mkfifo(fifo, 0600) == -1) {
|
||||
if(mkfifo (fifo, 0600) == -1) {
|
||||
perror("mkfifo");
|
||||
return 1;
|
||||
exit(1);
|
||||
}
|
||||
sockfd = open(fifo, O_RDWR | O_NONBLOCK, 0);
|
||||
if(sockfd == -1) {
|
||||
perror("open");
|
||||
return 1;
|
||||
exit(1);
|
||||
}
|
||||
g->input = fdopen(sockfd, "r");
|
||||
|
||||
@ -436,8 +436,7 @@ int main(int argc, char **argv)
|
||||
memset(&g, 0, sizeof(GlobalInfo));
|
||||
g.loop = ev_default_loop(0);
|
||||
|
||||
if(init_fifo(&g))
|
||||
return 1;
|
||||
init_fifo(&g);
|
||||
g.multi = curl_multi_init();
|
||||
|
||||
ev_timer_init(&g.timer_event, timer_cb, 0., 0.);
|
||||
|
||||
@ -392,21 +392,21 @@ int init_fifo(void)
|
||||
if((st.st_mode & S_IFMT) == S_IFREG) {
|
||||
errno = EEXIST;
|
||||
perror("lstat");
|
||||
return CURL_SOCKET_BAD;
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
unlink(fifo);
|
||||
if(mkfifo(fifo, 0600) == -1) {
|
||||
if(mkfifo (fifo, 0600) == -1) {
|
||||
perror("mkfifo");
|
||||
return CURL_SOCKET_BAD;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
socket = open(fifo, O_RDWR | O_NONBLOCK, 0);
|
||||
|
||||
if(socket == CURL_SOCKET_BAD) {
|
||||
if(socket == -1) {
|
||||
perror("open");
|
||||
return socket;
|
||||
exit(1);
|
||||
}
|
||||
MSG_OUT("Now, pipe some URL's into > %s\n", fifo);
|
||||
|
||||
@ -421,8 +421,6 @@ int main(void)
|
||||
GIOChannel* ch;
|
||||
|
||||
fd = init_fifo();
|
||||
if(fd == CURL_SOCKET_BAD)
|
||||
return 1;
|
||||
ch = g_io_channel_unix_new(fd);
|
||||
g_io_add_watch(ch, G_IO_IN, fifo_cb, g);
|
||||
gmain = g_main_loop_new(NULL, FALSE);
|
||||
|
||||
@ -399,22 +399,22 @@ static int init_fifo(GlobalInfo *g)
|
||||
curl_socket_t sockfd;
|
||||
|
||||
fprintf(MSG_OUT, "Creating named pipe \"%s\"\n", fifo);
|
||||
if(lstat(fifo, &st) == 0) {
|
||||
if(lstat (fifo, &st) == 0) {
|
||||
if((st.st_mode & S_IFMT) == S_IFREG) {
|
||||
errno = EEXIST;
|
||||
perror("lstat");
|
||||
return 1;
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
unlink(fifo);
|
||||
if(mkfifo (fifo, 0600) == -1) {
|
||||
perror("mkfifo");
|
||||
return 1;
|
||||
exit(1);
|
||||
}
|
||||
sockfd = open(fifo, O_RDWR | O_NONBLOCK, 0);
|
||||
if(sockfd == -1) {
|
||||
perror("open");
|
||||
return 1;
|
||||
exit(1);
|
||||
}
|
||||
g->input = fdopen(sockfd, "r");
|
||||
|
||||
@ -440,8 +440,7 @@ int main(int argc, char **argv)
|
||||
|
||||
memset(&g, 0, sizeof(GlobalInfo));
|
||||
g.evbase = event_base_new();
|
||||
if(init_fifo(&g))
|
||||
return 1;
|
||||
init_fifo(&g);
|
||||
g.multi = curl_multi_init();
|
||||
evtimer_assign(&g.timer_event, g.evbase, timer_cb, &g);
|
||||
|
||||
|
||||
@ -94,7 +94,7 @@ static bool init(CURL *&conn, const char *url)
|
||||
|
||||
if(conn == NULL) {
|
||||
fprintf(stderr, "Failed to create CURL connection\n");
|
||||
return false;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
code = curl_easy_setopt(conn, CURLOPT_ERRORBUFFER, errorBuffer);
|
||||
@ -270,7 +270,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
if(argc != 2) {
|
||||
fprintf(stderr, "Usage: %s <url>\n", argv[0]);
|
||||
return EXIT_FAILURE;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
curl_global_init(CURL_GLOBAL_DEFAULT);
|
||||
@ -279,7 +279,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
if(!init(conn, argv[1])) {
|
||||
fprintf(stderr, "Connection initialization failed\n");
|
||||
return EXIT_FAILURE;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
// Retrieve content for the URL
|
||||
@ -289,7 +289,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
if(code != CURLE_OK) {
|
||||
fprintf(stderr, "Failed to get '%s' [%s]\n", argv[1], errorBuffer);
|
||||
return EXIT_FAILURE;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
// Parse the (assumed) HTML code
|
||||
|
||||
@ -142,7 +142,7 @@ int my_trace(CURL *handle, curl_infotype type,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int setup(struct transfer *t, int num)
|
||||
static void setup(struct transfer *t, int num)
|
||||
{
|
||||
char filename[128];
|
||||
CURL *hnd;
|
||||
@ -155,7 +155,7 @@ static int setup(struct transfer *t, int num)
|
||||
if(!t->out) {
|
||||
fprintf(stderr, "error: could not open file %s for writing: %s\n",
|
||||
filename, strerror(errno));
|
||||
return 1;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* write to this file */
|
||||
@ -179,7 +179,6 @@ static int setup(struct transfer *t, int num)
|
||||
/* wait for pipe connection to confirm */
|
||||
curl_easy_setopt(hnd, CURLOPT_PIPEWAIT, 1L);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -205,8 +204,7 @@ int main(int argc, char **argv)
|
||||
multi_handle = curl_multi_init();
|
||||
|
||||
for(i = 0; i < num_transfers; i++) {
|
||||
if(setup(&trans[i], i))
|
||||
return 1;
|
||||
setup(&trans[i], i);
|
||||
|
||||
/* add the individual transfer */
|
||||
curl_multi_add_handle(multi_handle, trans[i].easy);
|
||||
|
||||
@ -200,7 +200,7 @@ static size_t read_callback(char *ptr, size_t size, size_t nmemb, void *userp)
|
||||
return retcode;
|
||||
}
|
||||
|
||||
static int setup(struct input *i, int num, const char *upload)
|
||||
static void setup(struct input *i, int num, const char *upload)
|
||||
{
|
||||
FILE *out;
|
||||
char url[256];
|
||||
@ -209,15 +209,14 @@ static int setup(struct input *i, int num, const char *upload)
|
||||
curl_off_t uploadsize;
|
||||
CURL *hnd;
|
||||
|
||||
hnd = i->hnd = NULL;
|
||||
|
||||
hnd = i->hnd = curl_easy_init();
|
||||
i->num = num;
|
||||
curl_msnprintf(filename, 128, "dl-%d", num);
|
||||
out = fopen(filename, "wb");
|
||||
if(!out) {
|
||||
fprintf(stderr, "error: could not open file %s for writing: %s\n", upload,
|
||||
strerror(errno));
|
||||
return 1;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
curl_msnprintf(url, 256, "https://localhost:8443/upload-%d", num);
|
||||
@ -226,8 +225,7 @@ static int setup(struct input *i, int num, const char *upload)
|
||||
if(stat(upload, &file_info)) {
|
||||
fprintf(stderr, "error: could not stat file %s: %s\n", upload,
|
||||
strerror(errno));
|
||||
fclose(out);
|
||||
return 1;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
uploadsize = file_info.st_size;
|
||||
@ -236,12 +234,9 @@ static int setup(struct input *i, int num, const char *upload)
|
||||
if(!i->in) {
|
||||
fprintf(stderr, "error: could not open file %s for reading: %s\n", upload,
|
||||
strerror(errno));
|
||||
fclose(out);
|
||||
return 1;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
hnd = i->hnd = curl_easy_init();
|
||||
|
||||
/* write to this file */
|
||||
curl_easy_setopt(hnd, CURLOPT_WRITEDATA, out);
|
||||
|
||||
@ -274,7 +269,6 @@ static int setup(struct input *i, int num, const char *upload)
|
||||
/* wait for pipe connection to confirm */
|
||||
curl_easy_setopt(hnd, CURLOPT_PIPEWAIT, 1L);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -307,8 +301,7 @@ int main(int argc, char **argv)
|
||||
multi_handle = curl_multi_init();
|
||||
|
||||
for(i = 0; i < num_transfers; i++) {
|
||||
if(setup(&trans[i], i, filename))
|
||||
return 1;
|
||||
setup(&trans[i], i, filename);
|
||||
|
||||
/* add the individual transfer */
|
||||
curl_multi_add_handle(multi_handle, trans[i].hnd);
|
||||
|
||||
@ -1,127 +0,0 @@
|
||||
<!--
|
||||
Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
|
||||
SPDX-License-Identifier: curl
|
||||
-->
|
||||
|
||||
# Multi Event Based
|
||||
|
||||
A libcurl multi is operating "event based" when the application uses
|
||||
and event library like `libuv` to monitor the sockets and file descriptors
|
||||
libcurl uses to trigger transfer operations. How that works from the
|
||||
applications point of view is described in libcurl-multi(3).
|
||||
|
||||
This documents is about the internal handling.
|
||||
|
||||
## Source Locations
|
||||
|
||||
All code related to event based handling is found in `lib/multi_ev.c`
|
||||
and `lib/multi_ev.h`. The header defines a set of internal functions
|
||||
and `struct curl_multi_ev` that is embedded in each multi handle.
|
||||
|
||||
There is `Curl_multi_ev_init()` and `Curl_multi_ev_cleanup()` to manage
|
||||
the overall life cycle, call on creation and destruction of the multi
|
||||
handle.
|
||||
|
||||
## Tracking Events
|
||||
|
||||
First, the various functions in `lib/multi_ev.h` only ever really do
|
||||
something when the libcurl application has registered its callback
|
||||
in `multi->socket_cb`.
|
||||
|
||||
This is important as this callback gets informed about *changes* to sockets.
|
||||
When a new socket is added, an existing is removed, or the `POLLIN/OUT`
|
||||
flags change, `multi->socket_cb` needs to be invoked. `multi_ev` has to
|
||||
track what it already reported to detect changes.
|
||||
|
||||
Most applications are expected to go "event based" right from the start,
|
||||
but the libcurl API does not prohibit an application to start another
|
||||
way and then go for events later on, even in the middle of a transfer.
|
||||
|
||||
### Transfer Events
|
||||
|
||||
Most event that happen are in connection with a transfer. A transfer
|
||||
opens a connection, which opens a socket, and waits for this socket
|
||||
to become writable (`POLLOUT`) when using TCP, for example.
|
||||
|
||||
The multi then calls `Curl_multi_ev_assess_xfer(multi, data)` to
|
||||
let the multi event code detect what sockets the transfer is interested in.
|
||||
If indeed a `multi->socket_cb` is set, the *current* transfer pollset is
|
||||
retrieved via `Curl_multi_getsock()`. This current pollset is then
|
||||
compared to the *previous* pollset. If relevant changes are detected,
|
||||
`multi->socket_cb` gets informed about those. These can be:
|
||||
|
||||
* a socket is in the current set, but not the previous one
|
||||
* a socket was also in the previous one, but IN/OUT flags changed
|
||||
* a socket in the previous one is no longer part of the current
|
||||
|
||||
`multi_ev.c` keeps a `struct mev_sh_entry` for each sockets in a hash
|
||||
with the socket as key. It tracks in each entry which transfers are
|
||||
interested in this particular socket. How many transfer want to read
|
||||
and/or write and what the summarized `POLLIN/POLLOUT` action, that
|
||||
had been reported to `multi->socket_cb` was.
|
||||
|
||||
This is necessary as a socket may be in use by several transfers
|
||||
at the same time (think HTTP/2 on the same connection). When a transfer
|
||||
is done and gets removed from the socket entry, it decrements
|
||||
the reader and/or writer count (depending on what it was last
|
||||
interested in). This *may* result in the entry's summarized action
|
||||
to change, or not.
|
||||
|
||||
### Connection Events
|
||||
|
||||
There are also events not connected to any transfer that need to be tracked.
|
||||
The multi connection cache, concerned with clean shutdowns of connections,
|
||||
is interested in socket events during the shutdown.
|
||||
|
||||
To allow use of the libcurl infrastructure, the connection cache operates
|
||||
using an *internal* easy handle that is not a transfer as such. The
|
||||
internal handle is used for all connection shutdown operations, being tied
|
||||
to a particular connection only for a short time. This means tracking
|
||||
the last pollset for an internal handle is useless.
|
||||
|
||||
Instead, the connection cache uses `Curl_multi_ev_assess_conn()` to have
|
||||
multi event handling check the connection and track a "last pollset"
|
||||
for the connection alone.
|
||||
|
||||
## Event Processing
|
||||
|
||||
When the libcurl application is informed by the event library that
|
||||
a particular socket has an event, it calls `curl_multi_socket_action()`
|
||||
to make libcurl react to it. This internally invokes
|
||||
`Curl_multi_ev_expire_xfers()` which expires all transfers that
|
||||
are interested in the given socket, so the multi handle runs them.
|
||||
|
||||
In addition `Curl_multi_ev_expire_xfers()` returns a `bool` to let
|
||||
the multi know that connections are also interested in the socket, so
|
||||
the connection pool should be informed as well.
|
||||
|
||||
## All Things Pass
|
||||
|
||||
When a transfer is done, e.g. removed from its multi handle, the
|
||||
multi calls `Curl_multi_ev_xfer_done()`. This cleans up the pollset
|
||||
tracking for the transfer.
|
||||
|
||||
When a connection is done, and before it is destroyed,
|
||||
`Curl_multi_ev_conn_done()` is called. This cleans up the pollset
|
||||
tracking for this connection.
|
||||
|
||||
When a socket is about to be closed, `Curl_multi_ev_socket_done()`
|
||||
is called to cleanup the socket entry and all information kept there.
|
||||
|
||||
These calls do not have to happen in any particular order. A transfer's
|
||||
socket may be around while the transfer is ongoing. Or it might disappear
|
||||
in the middle of things. Also, a transfer might be interested in several
|
||||
sockets at the same time (resolving, eye balling, ftp are all examples of
|
||||
those).
|
||||
|
||||
### And Come Again
|
||||
|
||||
While transfer and connection identifier are practically unique in a
|
||||
libcurl application, sockets are not. Operating systems are keen on reusing
|
||||
their resources, and the next socket may get the same identifier as
|
||||
one just having been closed with high likelihood.
|
||||
|
||||
This means that multi event handling needs to be informed *before* a close,
|
||||
clean up all its tracking and be ready to see that same socket identifier
|
||||
again right after.
|
||||
@ -151,15 +151,6 @@ int Curl_str_casecompare(struct Curl_str *str, const char *check);
|
||||
Returns true if the provided string in the `str` argument matches the `check`
|
||||
string case insensitively.
|
||||
|
||||
## `Curl_str_cmp`
|
||||
|
||||
~~~c
|
||||
int Curl_str_cmp(struct Curl_str *str, const char *check);
|
||||
~~~
|
||||
|
||||
Returns true if the provided string in the `str` argument matches the `check`
|
||||
string case sensitively. This is *not* the same return code as `strcmp`.
|
||||
|
||||
## `Curl_str_nudge`
|
||||
|
||||
~~~c
|
||||
|
||||
@ -28,10 +28,11 @@ const struct curl_easyoption *curl_easy_option_by_id(CURLoption id);
|
||||
# DESCRIPTION
|
||||
|
||||
Given a *CURLoption* **id**, this function returns a pointer to the
|
||||
*curl_easyoption* struct, holding information about the curl_easy_setopt(3)
|
||||
option using that id. The option id is the `CURLOPT_` prefixed ones provided
|
||||
in the standard curl/curl.h header file. This function returns the non-alias
|
||||
version of the cases where there is an alias function as well.
|
||||
*curl_easyoption* struct, holding information about the
|
||||
curl_easy_setopt(3) option using that id. The option id is the CURLOPT_
|
||||
prefix ones provided in the standard curl/curl.h header file. This function
|
||||
returns the non-alias version of the cases where there is an alias function as
|
||||
well.
|
||||
|
||||
If libcurl has no option with the given id, this function returns NULL.
|
||||
|
||||
|
||||
@ -27,10 +27,11 @@ const struct curl_easyoption *curl_easy_option_by_name(const char *name);
|
||||
|
||||
# DESCRIPTION
|
||||
|
||||
Given a **name**, this function returns a pointer to the *curl_easyoption*
|
||||
struct, holding information about the curl_easy_setopt(3) option using that
|
||||
name. The name should be specified without the `CURLOPT_` prefix and the name
|
||||
comparison is made case insensitive.
|
||||
Given a **name**, this function returns a pointer to the
|
||||
*curl_easyoption* struct, holding information about the
|
||||
curl_easy_setopt(3) option using that name. The name should be specified
|
||||
without the "CURLOPT_" prefix and the name comparison is made case
|
||||
insensitive.
|
||||
|
||||
If libcurl has no option with the given name, this function returns NULL.
|
||||
|
||||
|
||||
@ -316,4 +316,4 @@ filenames are now escaped before transmission.
|
||||
# RETURN VALUE
|
||||
|
||||
0 means everything was OK, non-zero means an error occurred corresponding to a
|
||||
`CURL_FORMADD_*` constant defined in *\<curl/curl.h\>*.
|
||||
CURL_FORMADD_* constant defined in *\<curl/curl.h\>*.
|
||||
|
||||
@ -38,9 +38,9 @@ first argument to the curl_formget_callback function.
|
||||
size_t len);"
|
||||
~~~
|
||||
|
||||
The *curl_formget_callback* is invoked for each part of the HTTP POST chain.
|
||||
The character buffer passed to the callback must not be freed. The callback
|
||||
should return the buffer length passed to it on success.
|
||||
The curl_formget_callback is invoked for each part of the HTTP POST chain. The
|
||||
character buffer passed to the callback must not be freed. The callback should
|
||||
return the buffer length passed to it on success.
|
||||
|
||||
If the **CURLFORM_STREAM** option is used in the formpost, it prevents
|
||||
curl_formget(3) from working until you have performed the actual HTTP request.
|
||||
|
||||
@ -101,34 +101,13 @@ trace.
|
||||
|
||||
Tracing of DNS operations to resolve hostnames and HTTPS records.
|
||||
|
||||
## `lib-ids`
|
||||
|
||||
Adds transfer and connection identifiers as prefix to every call to
|
||||
CURLOPT_DEBUGFUNCTION(3). The format is `[n-m]` where `n` is the identifier
|
||||
of the transfer and `m` is the identifier of the connection. A literal `x`
|
||||
is used for internal transfers or when no connection is assigned.
|
||||
|
||||
For example, `[5-x]` is the prefix for transfer 5 that has no
|
||||
connection. The command line tool `curl`uses the same format for its
|
||||
`--trace-ids` option.
|
||||
|
||||
`lib-ids` is intended for libcurl applications that handle multiple
|
||||
transfers but have no own way to identify in trace output which transfer
|
||||
a trace event is connected to.
|
||||
|
||||
## `doh`
|
||||
|
||||
Former name for DNS-over-HTTP operations. Now an alias for `dns`.
|
||||
|
||||
## `multi`
|
||||
|
||||
Traces multi operations managing transfers' state changes and sockets poll
|
||||
states.
|
||||
|
||||
## `read`
|
||||
|
||||
Traces reading of upload data from the application in order to send it to the
|
||||
server.
|
||||
Traces reading of upload data from the application in order to send it to the server.
|
||||
|
||||
## `ssls`
|
||||
|
||||
|
||||
@ -376,8 +376,9 @@ supports HTTP zstd content encoding using zstd library (Added in 7.72.0)
|
||||
|
||||
*features* mask bit: CURL_VERSION_CONV
|
||||
|
||||
libcurl was built with support for character conversions provided by
|
||||
callbacks. Always 0 since 7.82.0. (Added in 7.15.4, deprecated.)
|
||||
libcurl was built with support for character conversions, as provided by the
|
||||
CURLOPT_CONV_* callbacks. Always 0 since 7.82.0. (Added in 7.15.4,
|
||||
deprecated.)
|
||||
|
||||
## no name
|
||||
|
||||
|
||||
@ -23,16 +23,16 @@ These variables are intended for internal use only, subject to change and have
|
||||
many effects on the behavior of libcurl. Refer to the source code to determine
|
||||
how exactly they are being used.
|
||||
|
||||
## `CURL_ALTSVC_HTTP`
|
||||
## CURL_ALTSVC_HTTP
|
||||
|
||||
Bypass the AltSvc HTTPS protocol restriction if this variable exists.
|
||||
|
||||
## `CURL_DBG_SOCK_RBLOCK`
|
||||
## CURL_DBG_SOCK_RBLOCK
|
||||
|
||||
The percentage of recv() calls that should be answered with a EAGAIN at random.
|
||||
For TCP/UNIX sockets.
|
||||
|
||||
## `CURL_DBG_SOCK_RMAX`
|
||||
## CURL_DBG_SOCK_RMAX
|
||||
|
||||
The maximum data that shall be received from the network in one recv() call.
|
||||
For TCP/UNIX sockets. This is applied to every recv.
|
||||
@ -40,12 +40,12 @@ For TCP/UNIX sockets. This is applied to every recv.
|
||||
Example: **CURL_DBG_SOCK_RMAX=400** means recv buffer size is limited to a
|
||||
maximum of 400 bytes.
|
||||
|
||||
## `CURL_DBG_SOCK_WBLOCK`
|
||||
## CURL_DBG_SOCK_WBLOCK
|
||||
|
||||
The percentage of send() calls that should be answered with a EAGAIN at random.
|
||||
For TCP/UNIX sockets.
|
||||
|
||||
## `CURL_DBG_SOCK_WPARTIAL`
|
||||
## CURL_DBG_SOCK_WPARTIAL
|
||||
|
||||
The percentage of data that shall be written to the network. For TCP/UNIX
|
||||
sockets. This is applied to every send.
|
||||
@ -53,12 +53,12 @@ sockets. This is applied to every send.
|
||||
Example: **CURL_DBG_SOCK_WPARTIAL=80** means a send with 1000 bytes would
|
||||
only send 800.
|
||||
|
||||
## `CURL_DBG_QUIC_WBLOCK`
|
||||
## CURL_DBG_QUIC_WBLOCK
|
||||
|
||||
The percentage of send() calls that should be answered with EAGAIN at random.
|
||||
QUIC only.
|
||||
|
||||
## `CURL_DEBUG`
|
||||
## CURL_DEBUG
|
||||
|
||||
Trace logging behavior as an alternative to calling curl_global_trace(3).
|
||||
|
||||
@ -73,39 +73,39 @@ Example: **CURL_DEBUG=tcp,-http/2 curl -vv url** means trace protocol details,
|
||||
triggered by `-vv`, add tracing of TCP in addition and remove tracing of
|
||||
HTTP/2.
|
||||
|
||||
## `CURL_DEBUG_SIZE`
|
||||
## CURL_DEBUG_SIZE
|
||||
|
||||
Fake the size returned by CURLINFO_HEADER_SIZE and CURLINFO_REQUEST_SIZE.
|
||||
|
||||
## `CURL_GETHOSTNAME`
|
||||
## CURL_GETHOSTNAME
|
||||
|
||||
Fake the local machine's unqualified hostname for NTLM and SMTP.
|
||||
|
||||
## `CURL_HSTS_HTTP`
|
||||
## CURL_HSTS_HTTP
|
||||
|
||||
Bypass the HSTS HTTPS protocol restriction if this variable exists.
|
||||
|
||||
## `CURL_FORCETIME`
|
||||
## CURL_FORCETIME
|
||||
|
||||
A time of 0 is used for AWS signatures and NTLM if this variable exists.
|
||||
|
||||
## `CURL_ENTROPY`
|
||||
## CURL_ENTROPY
|
||||
|
||||
A fixed faked value to use instead of a proper random number so that functions
|
||||
in libcurl that are otherwise getting random outputs can be tested for what
|
||||
they generate.
|
||||
|
||||
## `CURL_SMALLREQSEND`
|
||||
## CURL_SMALLREQSEND
|
||||
|
||||
An alternative size of HTTP data to be sent at a time only if smaller than the
|
||||
current.
|
||||
|
||||
## `CURL_SMALLSENDS`
|
||||
## CURL_SMALLSENDS
|
||||
|
||||
An alternative size of socket data to be sent at a time only if smaller than
|
||||
the current.
|
||||
|
||||
## `CURL_TIME`
|
||||
## CURL_TIME
|
||||
|
||||
Fake Unix timestamp to use for AltSvc, HSTS and CURLINFO variables that are
|
||||
time related.
|
||||
@ -114,34 +114,34 @@ This variable can also be used to fake the data returned by some CURLINFO
|
||||
variables that are not time-related (such as CURLINFO_LOCAL_PORT), and in that
|
||||
case the value is not a timestamp.
|
||||
|
||||
## `CURL_TRACE`
|
||||
## CURL_TRACE
|
||||
|
||||
LDAP tracing is enabled if this variable exists and its value is 1 or greater.
|
||||
|
||||
OpenLDAP tracing is separate. Refer to CURL_OPENLDAP_TRACE.
|
||||
|
||||
## `CURL_OPENLDAP_TRACE`
|
||||
## CURL_OPENLDAP_TRACE
|
||||
|
||||
OpenLDAP tracing is enabled if this variable exists and its value is 1 or
|
||||
greater. There is a number of debug levels, refer to *openldap.c* comments.
|
||||
|
||||
## `CURL_WS_CHUNK_SIZE`
|
||||
## CURL_WS_CHUNK_SIZE
|
||||
|
||||
Used to influence the buffer chunk size used for WebSocket encoding and
|
||||
decoding.
|
||||
|
||||
## `CURL_WS_CHUNK_EAGAIN`
|
||||
## CURL_WS_CHUNK_EAGAIN
|
||||
|
||||
Used to simulate blocking sends after this chunk size for WebSocket
|
||||
connections.
|
||||
|
||||
## `CURL_FORBID_REUSE`
|
||||
## CURL_FORBID_REUSE
|
||||
|
||||
Used to set the CURLOPT_FORBID_REUSE flag on each transfer initiated
|
||||
by the curl command line tool. The value of the environment variable
|
||||
does not matter.
|
||||
|
||||
## `CURL_GRACEFUL_SHUTDOWN`
|
||||
## CURL_GRACEFUL_SHUTDOWN
|
||||
|
||||
Make a blocking, graceful shutdown of all remaining connections when
|
||||
a multi handle is destroyed. This implicitly triggers for easy handles
|
||||
|
||||
@ -15,7 +15,6 @@ TLS-backend:
|
||||
- GnuTLS
|
||||
- Schannel
|
||||
- Secure Transport
|
||||
- rustls
|
||||
Added-in: 7.19.1
|
||||
---
|
||||
|
||||
|
||||
@ -32,7 +32,7 @@ CURLINFO_SCHEME(3) instead, because this option cannot return all
|
||||
possible protocols.
|
||||
|
||||
Pass a pointer to a long to receive the version used in the last http
|
||||
connection. The returned value is set to one of these values:
|
||||
connection. The returned value is set to one of the CURLPROTO_* values:
|
||||
|
||||
~~~c
|
||||
CURLPROTO_DICT, CURLPROTO_FILE, CURLPROTO_FTP, CURLPROTO_FTPS,
|
||||
|
||||
@ -58,11 +58,12 @@ struct curl_tlssessioninfo {
|
||||
};
|
||||
~~~
|
||||
|
||||
The *backend* struct member is one of these defines: CURLSSLBACKEND_NONE (when
|
||||
built without TLS support), CURLSSLBACKEND_WOLFSSL,
|
||||
CURLSSLBACKEND_SECURETRANSPORT, CURLSSLBACKEND_GNUTLS, CURLSSLBACKEND_MBEDTLS,
|
||||
CURLSSLBACKEND_NSS, CURLSSLBACKEND_OPENSSL or CURLSSLBACKEND_SCHANNEL. (Note
|
||||
that the OpenSSL forks are all reported as just OpenSSL here.)
|
||||
The *backend* struct member is one of the defines in the CURLSSLBACKEND_*
|
||||
series: CURLSSLBACKEND_NONE (when built without TLS support),
|
||||
CURLSSLBACKEND_WOLFSSL, CURLSSLBACKEND_SECURETRANSPORT, CURLSSLBACKEND_GNUTLS,
|
||||
CURLSSLBACKEND_MBEDTLS, CURLSSLBACKEND_NSS, CURLSSLBACKEND_OPENSSL or
|
||||
CURLSSLBACKEND_SCHANNEL. (Note that the OpenSSL
|
||||
forks are all reported as just OpenSSL here.)
|
||||
|
||||
The *internals* struct member points to a TLS library specific pointer for
|
||||
the active ("in use") SSL connection, with the following underlying types:
|
||||
|
||||
@ -47,11 +47,6 @@ libcurl then expects the application to monitor the sockets for the specific
|
||||
activities and tell libcurl again when something happens on one of them. Tell
|
||||
libcurl by calling curl_multi_socket_action(3).
|
||||
|
||||
This callback may get invoked at any time when interacting with libcurl.
|
||||
This may even happen after all transfers are done and is *likely* to
|
||||
happen *during* a call to curl_multi_cleanup(3) when cached connections
|
||||
are shut down.
|
||||
|
||||
# CALLBACK ARGUMENTS
|
||||
|
||||
*easy* identifies the specific transfer for which this update is related.
|
||||
|
||||
@ -17,7 +17,6 @@ TLS-backend:
|
||||
- GnuTLS
|
||||
- Schannel
|
||||
- Secure Transport
|
||||
- rustls
|
||||
Added-in: 7.19.1
|
||||
---
|
||||
|
||||
|
||||
@ -42,24 +42,21 @@ header list establishes the document-level MIME headers to prepend to the
|
||||
uploaded document described by CURLOPT_MIMEPOST(3). This does not affect raw
|
||||
mail uploads.
|
||||
|
||||
When used with HTTP, this option can add new headers, replace internal headers
|
||||
and remove internal headers.
|
||||
|
||||
The linked list should be a valid list of **struct curl_slist** entries
|
||||
The linked list should be a fully valid list of **struct curl_slist** structs
|
||||
properly filled in. Use curl_slist_append(3) to create the list and
|
||||
curl_slist_free_all(3) to free it again after use.
|
||||
curl_slist_free_all(3) to clean up an entire list. If you add a header that is
|
||||
otherwise generated and used by libcurl internally, your added header is used
|
||||
instead. If you add a header with no content as in 'Accept:' (no data on the
|
||||
right side of the colon), the internally used header is disabled/removed. With
|
||||
this option you can add new headers, replace internal headers and remove
|
||||
internal headers. To add a header with no content (nothing to the right side
|
||||
of the colon), use the form 'name;' (note the ending semicolon).
|
||||
|
||||
If you provide a header that is otherwise generated and used by libcurl
|
||||
internally, your header alternative is used instead. If you provide a header
|
||||
without content (no data on the right side of the colon) as in `Accept:`, the
|
||||
internally used header is removed. To forcibly add a header without content
|
||||
(nothing after the colon), use the form `name;` (using a trailing semicolon).
|
||||
|
||||
The headers included in the linked list **must not** be CRLF-terminated, since
|
||||
libcurl adds CRLF after each header item itself. Failure to comply with this
|
||||
might result in strange behavior. libcurl passes on the verbatim strings you
|
||||
give it, without any filter or other safe guards. That includes white space
|
||||
and control characters.
|
||||
The headers included in the linked list **must not** be CRLF-terminated,
|
||||
because libcurl adds CRLF after each header item itself. Failure to comply
|
||||
with this might result in strange behavior. libcurl passes on the verbatim
|
||||
strings you give it, without any filter or other safe guards. That includes
|
||||
white space and control characters.
|
||||
|
||||
The first line in an HTTP request (containing the method, usually a GET or
|
||||
POST) is not a header and cannot be replaced using this option. Only the lines
|
||||
@ -167,15 +164,9 @@ int main(void)
|
||||
if(curl) {
|
||||
curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
|
||||
|
||||
/* add this header */
|
||||
list = curl_slist_append(list, "Shoesize: 10");
|
||||
|
||||
/* remove this header */
|
||||
list = curl_slist_append(list, "Accept:");
|
||||
|
||||
/* change this header */
|
||||
list = curl_slist_append(list, "Host: example.net");
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, list);
|
||||
|
||||
curl_easy_perform(curl);
|
||||
|
||||
@ -28,8 +28,8 @@ CURLcode curl_easy_setopt(CURL *handle, CURLOPT_MIME_OPTIONS, long options);
|
||||
|
||||
# DESCRIPTION
|
||||
|
||||
Pass a long that holds a bitmask of options. Each bit is a boolean flag used
|
||||
while encoding a MIME tree or multipart form data.
|
||||
Pass a long that holds a bitmask of CURLMIMEOPT_* defines. Each bit is a
|
||||
Boolean flag used while encoding a MIME tree or multipart form data.
|
||||
|
||||
Available bits are:
|
||||
|
||||
|
||||
@ -31,7 +31,7 @@ This option is deprecated. We strongly recommend using
|
||||
CURLOPT_PROTOCOLS_STR(3) instead because this option cannot control all
|
||||
available protocols.
|
||||
|
||||
Pass a long that holds a bitmask of protocol bits. If used, this bitmask
|
||||
Pass a long that holds a bitmask of CURLPROTO_* defines. If used, this bitmask
|
||||
limits what protocols libcurl may use in the transfer. This allows you to have
|
||||
a libcurl built to support a wide range of protocols but still limit specific
|
||||
transfers to only be allowed to use a subset of them. By default libcurl
|
||||
|
||||
@ -32,10 +32,10 @@ This option is deprecated. We strongly recommend using
|
||||
CURLOPT_REDIR_PROTOCOLS_STR(3) instead because this option cannot
|
||||
control all available protocols.
|
||||
|
||||
Pass a long that holds a bitmask of protocol bits. If used, this bitmask
|
||||
Pass a long that holds a bitmask of CURLPROTO_* defines. If used, this bitmask
|
||||
limits what protocols libcurl may use in a transfer that it follows to in a
|
||||
redirect when CURLOPT_FOLLOWLOCATION(3) is enabled. This allows you to limit
|
||||
specific transfers to only be allowed to use a subset of protocols in
|
||||
redirect when CURLOPT_FOLLOWLOCATION(3) is enabled. This allows you to
|
||||
limit specific transfers to only be allowed to use a subset of protocols in
|
||||
redirections.
|
||||
|
||||
Protocols denied by CURLOPT_PROTOCOLS(3) are not overridden by this
|
||||
|
||||
@ -89,11 +89,11 @@ could be a privacy violation and unexpected.
|
||||
## CURLSSLOPT_EARLYDATA
|
||||
|
||||
Tell libcurl to try sending application data as TLS1.3 early data. This option
|
||||
is supported for GnuTLS and wolfSSL. This option works on a best effort basis,
|
||||
is only supported for GnuTLS. This option works on a best effort basis,
|
||||
in cases when it wasn't possible to send early data the request is resent
|
||||
normally post-handshake.
|
||||
This option does not work when using QUIC.
|
||||
(Added in 8.11.0 for GnuTLS and 8.13.0 for wolfSSL)
|
||||
(Added in 8.11.0)
|
||||
|
||||
# DEFAULT
|
||||
|
||||
|
||||
@ -71,7 +71,7 @@ int main(void)
|
||||
~~~
|
||||
|
||||
If you are on Linux and somehow have a need for paths larger than 107 bytes,
|
||||
you can use the *proc* filesystem to bypass the limitation:
|
||||
you can use the proc filesystem to bypass the limitation:
|
||||
|
||||
~~~c
|
||||
int dirfd = open(long_directory_path_to_socket, O_DIRECTORY | O_RDONLY);
|
||||
|
||||
@ -81,8 +81,9 @@ int main(void)
|
||||
|
||||
# HISTORY
|
||||
|
||||
This option was known as CURLOPT_FTP_SSL up to 7.16.4. Supported by LDAP since
|
||||
7.81.0. Fully supported by the OpenLDAP backend only.
|
||||
This option was known as CURLOPT_FTP_SSL up to 7.16.4, and the constants were
|
||||
known as CURLFTPSSL_* Handled by LDAP since 7.81.0. Fully supported by the
|
||||
OpenLDAP backend only.
|
||||
|
||||
# %AVAILABILITY%
|
||||
|
||||
|
||||
@ -51,7 +51,7 @@ stdout
|
||||
A common technique is to use the write callback to store the incoming data
|
||||
into a dynamically growing allocated buffer, and then this
|
||||
CURLOPT_WRITEDATA(3) is used to point to a struct or the buffer to store data
|
||||
in. Like in the *getinmemory* example:
|
||||
in. Like in the getinmemory example:
|
||||
https://curl.se/libcurl/c/getinmemory.html
|
||||
|
||||
# HISTORY
|
||||
|
||||
@ -45,7 +45,6 @@ CURL_GLOBAL_DEFAULT 7.8
|
||||
CURL_GLOBAL_NOTHING 7.8
|
||||
CURL_GLOBAL_SSL 7.8
|
||||
CURL_GLOBAL_WIN32 7.8.1
|
||||
CURL_HAS_DECLSPEC_ATTRIBUTE 8.13.0
|
||||
CURL_HET_DEFAULT 7.59.0
|
||||
CURL_HTTP_VERSION_1_0 7.9.1
|
||||
CURL_HTTP_VERSION_1_1 7.9.1
|
||||
|
||||
@ -102,6 +102,11 @@
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
/* Compatibility for non-Clang compilers */
|
||||
#ifndef __has_declspec_attribute
|
||||
# define __has_declspec_attribute(x) 0
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
@ -113,17 +118,11 @@ typedef void CURLSH;
|
||||
* libcurl external API function linkage decorations.
|
||||
*/
|
||||
|
||||
#ifdef __has_declspec_attribute
|
||||
#define CURL_HAS_DECLSPEC_ATTRIBUTE(x) __has_declspec_attribute(x)
|
||||
#else
|
||||
#define CURL_HAS_DECLSPEC_ATTRIBUTE(x) 0
|
||||
#endif
|
||||
|
||||
#ifdef CURL_STATICLIB
|
||||
# define CURL_EXTERN
|
||||
#elif defined(_WIN32) || \
|
||||
(CURL_HAS_DECLSPEC_ATTRIBUTE(dllexport) && \
|
||||
CURL_HAS_DECLSPEC_ATTRIBUTE(dllimport))
|
||||
(__has_declspec_attribute(dllexport) && \
|
||||
__has_declspec_attribute(dllimport))
|
||||
# if defined(BUILDING_LIBCURL)
|
||||
# define CURL_EXTERN __declspec(dllexport)
|
||||
# else
|
||||
@ -2303,33 +2302,32 @@ enum {
|
||||
/*
|
||||
* Public API enums for RTSP requests
|
||||
*/
|
||||
|
||||
#define CURL_RTSPREQ_NONE 0L
|
||||
#define CURL_RTSPREQ_OPTIONS 1L
|
||||
#define CURL_RTSPREQ_DESCRIBE 2L
|
||||
#define CURL_RTSPREQ_ANNOUNCE 3L
|
||||
#define CURL_RTSPREQ_SETUP 4L
|
||||
#define CURL_RTSPREQ_PLAY 5L
|
||||
#define CURL_RTSPREQ_PAUSE 6L
|
||||
#define CURL_RTSPREQ_TEARDOWN 7L
|
||||
#define CURL_RTSPREQ_GET_PARAMETER 8L
|
||||
#define CURL_RTSPREQ_SET_PARAMETER 9L
|
||||
#define CURL_RTSPREQ_RECORD 10L
|
||||
#define CURL_RTSPREQ_RECEIVE 11L
|
||||
#define CURL_RTSPREQ_LAST 12L /* not used */
|
||||
enum {
|
||||
CURL_RTSPREQ_NONE, /* first in list */
|
||||
CURL_RTSPREQ_OPTIONS,
|
||||
CURL_RTSPREQ_DESCRIBE,
|
||||
CURL_RTSPREQ_ANNOUNCE,
|
||||
CURL_RTSPREQ_SETUP,
|
||||
CURL_RTSPREQ_PLAY,
|
||||
CURL_RTSPREQ_PAUSE,
|
||||
CURL_RTSPREQ_TEARDOWN,
|
||||
CURL_RTSPREQ_GET_PARAMETER,
|
||||
CURL_RTSPREQ_SET_PARAMETER,
|
||||
CURL_RTSPREQ_RECORD,
|
||||
CURL_RTSPREQ_RECEIVE,
|
||||
CURL_RTSPREQ_LAST /* last in list */
|
||||
};
|
||||
|
||||
/* These enums are for use with the CURLOPT_NETRC option. */
|
||||
#define CURL_NETRC_IGNORED 0L /* The .netrc will never be read.
|
||||
This is the default. */
|
||||
#define CURL_NETRC_OPTIONAL 1L /* A user:password in the URL will be preferred
|
||||
to one in the .netrc. */
|
||||
#define CURL_NETRC_REQUIRED 2L /* A user:password in the URL will be ignored.
|
||||
Unless one is set programmatically, the
|
||||
.netrc will be queried. */
|
||||
enum CURL_NETRC_OPTION {
|
||||
/* we set a single member here, just to make sure we still provide the enum,
|
||||
but the values to use are defined above with L suffixes */
|
||||
CURL_NETRC_LAST = 3
|
||||
CURL_NETRC_IGNORED, /* The .netrc will never be read.
|
||||
* This is the default. */
|
||||
CURL_NETRC_OPTIONAL, /* A user:password in the URL will be preferred
|
||||
* to one in the .netrc. */
|
||||
CURL_NETRC_REQUIRED, /* A user:password in the URL will be ignored.
|
||||
* Unless one is set programmatically, the .netrc
|
||||
* will be queried. */
|
||||
CURL_NETRC_LAST
|
||||
};
|
||||
|
||||
#define CURL_SSLVERSION_DEFAULT 0
|
||||
@ -2353,13 +2351,10 @@ enum CURL_NETRC_OPTION {
|
||||
/* never use, keep last */
|
||||
#define CURL_SSLVERSION_MAX_LAST (CURL_SSLVERSION_LAST << 16)
|
||||
|
||||
#define CURL_TLSAUTH_NONE 0L
|
||||
#define CURL_TLSAUTH_SRP 1L
|
||||
|
||||
enum CURL_TLSAUTH {
|
||||
/* we set a single member here, just to make sure we still provide the enum,
|
||||
but the values to use are defined above with L suffixes */
|
||||
CURL_TLSAUTH_LAST = 2
|
||||
CURL_TLSAUTH_NONE,
|
||||
CURL_TLSAUTH_SRP,
|
||||
CURL_TLSAUTH_LAST /* never use, keep last */
|
||||
};
|
||||
|
||||
/* symbols to use with CURLOPT_POSTREDIR.
|
||||
@ -2374,16 +2369,14 @@ enum CURL_TLSAUTH {
|
||||
#define CURL_REDIR_POST_ALL \
|
||||
(CURL_REDIR_POST_301|CURL_REDIR_POST_302|CURL_REDIR_POST_303)
|
||||
|
||||
#define CURL_TIMECOND_NONE 0L
|
||||
#define CURL_TIMECOND_IFMODSINCE 1L
|
||||
#define CURL_TIMECOND_IFUNMODSINCE 2L
|
||||
#define CURL_TIMECOND_LASTMOD 3L
|
||||
|
||||
typedef enum {
|
||||
/* we set a single member here, just to make sure we still provide
|
||||
the enum typedef, but the values to use are defined above with L
|
||||
suffixes */
|
||||
CURL_TIMECOND_LAST = 4
|
||||
CURL_TIMECOND_NONE,
|
||||
|
||||
CURL_TIMECOND_IFMODSINCE,
|
||||
CURL_TIMECOND_IFUNMODSINCE,
|
||||
CURL_TIMECOND_LASTMOD,
|
||||
|
||||
CURL_TIMECOND_LAST
|
||||
} curl_TimeCond;
|
||||
|
||||
/* Special size_t value signaling a null-terminated string. */
|
||||
|
||||
@ -162,8 +162,7 @@ endif
|
||||
TIDY := clang-tidy
|
||||
|
||||
tidy:
|
||||
(_csources=`echo ' $(CSOURCES)' | sed -e 's/ +/ /g' -e 's| | $(srcdir)/|g'`; \
|
||||
$(TIDY) $$_csources $(TIDYFLAGS) $(CURL_CLANG_TIDYFLAGS) -- $(AM_CPPFLAGS) $(CPPFLAGS) -DHAVE_CONFIG_H)
|
||||
$(TIDY) $(CSOURCES) $(TIDYFLAGS) $(CURL_CLANG_TIDYFLAGS) -- $(AM_CPPFLAGS) $(CPPFLAGS) -DHAVE_CONFIG_H
|
||||
|
||||
optiontable:
|
||||
perl optiontable.pl < $(top_srcdir)/include/curl/curl.h > easyoptions.c
|
||||
|
||||
@ -198,7 +198,6 @@ LIB_CFILES = \
|
||||
mprintf.c \
|
||||
mqtt.c \
|
||||
multi.c \
|
||||
multi_ev.c \
|
||||
netrc.c \
|
||||
nonblock.c \
|
||||
noproxy.c \
|
||||
@ -336,7 +335,6 @@ LIB_HFILES = \
|
||||
mime.h \
|
||||
mqtt.h \
|
||||
multihandle.h \
|
||||
multi_ev.h \
|
||||
multiif.h \
|
||||
netrc.h \
|
||||
nonblock.h \
|
||||
|
||||
246
lib/altsvc.c
246
lib/altsvc.c
@ -407,6 +407,26 @@ CURLcode Curl_altsvc_save(struct Curl_easy *data,
|
||||
return result;
|
||||
}
|
||||
|
||||
static CURLcode getalnum(const char **ptr, char *alpnbuf, size_t buflen)
|
||||
{
|
||||
size_t len;
|
||||
const char *protop;
|
||||
const char *p = *ptr;
|
||||
while(ISBLANK(*p))
|
||||
p++;
|
||||
protop = p;
|
||||
while(*p && !ISBLANK(*p) && (*p != ';') && (*p != '='))
|
||||
p++;
|
||||
len = p - protop;
|
||||
*ptr = p;
|
||||
|
||||
if(!len || (len >= buflen))
|
||||
return CURLE_BAD_FUNCTION_ARGUMENT;
|
||||
memcpy(alpnbuf, protop, len);
|
||||
alpnbuf[len] = 0;
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
/* hostcompare() returns true if 'host' matches 'check'. The first host
|
||||
* argument may have a trailing dot present that will be ignored.
|
||||
*/
|
||||
@ -477,124 +497,144 @@ CURLcode Curl_altsvc_parse(struct Curl_easy *data,
|
||||
unsigned short srcport)
|
||||
{
|
||||
const char *p = value;
|
||||
char alpnbuf[MAX_ALTSVC_ALPNLEN] = "";
|
||||
struct altsvc *as;
|
||||
unsigned short dstport = srcport; /* the same by default */
|
||||
CURLcode result = getalnum(&p, alpnbuf, sizeof(alpnbuf));
|
||||
size_t entries = 0;
|
||||
struct Curl_str alpn;
|
||||
const char *sp;
|
||||
time_t maxage = 24 * 3600; /* default is 24 hours */
|
||||
bool persist = FALSE;
|
||||
size_t alpnlen = strlen(alpnbuf);
|
||||
size_t srchostlen = strlen(srchost);
|
||||
#ifdef CURL_DISABLE_VERBOSE_STRINGS
|
||||
(void)data;
|
||||
#endif
|
||||
if(result) {
|
||||
infof(data, "Excessive alt-svc header, ignoring.");
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
DEBUGASSERT(asi);
|
||||
|
||||
/* initial check for "clear" */
|
||||
if(!Curl_str_until(&p, &alpn, MAX_ALTSVC_LINE, ';') &&
|
||||
!Curl_str_single(&p, ';')) {
|
||||
Curl_str_trimblanks(&alpn);
|
||||
/* "clear" is a magic keyword */
|
||||
if(Curl_str_casecompare(&alpn, "clear")) {
|
||||
/* Flush cached alternatives for this source origin */
|
||||
altsvc_flush(asi, srcalpnid, srchost, srcport);
|
||||
return CURLE_OK;
|
||||
}
|
||||
}
|
||||
|
||||
p = value;
|
||||
|
||||
if(Curl_str_until(&p, &alpn, MAX_ALTSVC_LINE, '='))
|
||||
return CURLE_OK; /* strange line */
|
||||
|
||||
Curl_str_trimblanks(&alpn);
|
||||
|
||||
/* Handle the optional 'ma' and 'persist' flags once first, as they need to
|
||||
be known for each alternative service. Unknown flags are skipped. */
|
||||
sp = strchr(p, ';');
|
||||
if(sp) {
|
||||
sp++; /* pass the semicolon */
|
||||
for(;;) {
|
||||
struct Curl_str name;
|
||||
struct Curl_str val;
|
||||
const char *vp;
|
||||
curl_off_t num;
|
||||
bool quoted;
|
||||
/* allow some extra whitespaces around name and value */
|
||||
if(Curl_str_until(&sp, &name, 20, '=') ||
|
||||
Curl_str_single(&sp, '=') ||
|
||||
Curl_str_until(&sp, &val, 80, ';'))
|
||||
break;
|
||||
Curl_str_trimblanks(&name);
|
||||
Curl_str_trimblanks(&val);
|
||||
/* the value might be quoted */
|
||||
vp = Curl_str(&val);
|
||||
quoted = (*vp == '\"');
|
||||
if(quoted)
|
||||
vp++;
|
||||
if(!Curl_str_number(&vp, &num, TIME_T_MAX)) {
|
||||
if(Curl_str_casecompare(&name, "ma"))
|
||||
maxage = (time_t)num;
|
||||
else if(Curl_str_casecompare(&name, "persist") && (num == 1))
|
||||
persist = TRUE;
|
||||
}
|
||||
if(quoted && Curl_str_single(&sp, '\"'))
|
||||
break;
|
||||
if(Curl_str_single(&sp, ';'))
|
||||
break;
|
||||
}
|
||||
/* "clear" is a magic keyword */
|
||||
if(strcasecompare(alpnbuf, "clear")) {
|
||||
/* Flush cached alternatives for this source origin */
|
||||
altsvc_flush(asi, srcalpnid, srchost, srcport);
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
do {
|
||||
if(!Curl_str_single(&p, '=')) {
|
||||
/* [protocol]="[host][:port], [protocol]="[host][:port]" */
|
||||
enum alpnid dstalpnid =
|
||||
Curl_alpn2alpnid(Curl_str(&alpn), Curl_strlen(&alpn));
|
||||
if(!Curl_str_single(&p, '\"')) {
|
||||
struct Curl_str dsthost;
|
||||
curl_off_t port = 0;
|
||||
if(Curl_str_single(&p, ':')) {
|
||||
if(*p == '=') {
|
||||
/* [protocol]="[host][:port]" */
|
||||
enum alpnid dstalpnid = Curl_alpn2alpnid(alpnbuf, alpnlen);
|
||||
p++;
|
||||
if(*p == '\"') {
|
||||
const char *dsthost = "";
|
||||
size_t dstlen = 0; /* destination hostname length */
|
||||
const char *value_ptr;
|
||||
char option[32];
|
||||
curl_off_t num;
|
||||
bool quoted = FALSE;
|
||||
time_t maxage = 24 * 3600; /* default is 24 hours */
|
||||
bool persist = FALSE;
|
||||
bool valid = TRUE;
|
||||
p++;
|
||||
if(*p != ':') {
|
||||
/* hostname starts here */
|
||||
if(Curl_str_single(&p, '[')) {
|
||||
if(Curl_str_until(&p, &dsthost, MAX_ALTSVC_HOSTLEN, ':')) {
|
||||
infof(data, "Bad alt-svc hostname, ignoring.");
|
||||
const char *hostp = p;
|
||||
if(*p == '[') {
|
||||
/* pass all valid IPv6 letters - does not handle zone id */
|
||||
dstlen = strspn(++p, "0123456789abcdefABCDEF:.");
|
||||
if(p[dstlen] != ']')
|
||||
/* invalid host syntax, bail out */
|
||||
break;
|
||||
}
|
||||
/* we store the IPv6 numerical address *with* brackets */
|
||||
dstlen += 2;
|
||||
p = &p[dstlen-1];
|
||||
}
|
||||
else {
|
||||
/* IPv6 host name */
|
||||
if(Curl_str_until(&p, &dsthost, MAX_IPADR_LEN, ']') ||
|
||||
Curl_str_single(&p, ']')) {
|
||||
infof(data, "Bad alt-svc IPv6 hostname, ignoring.");
|
||||
break;
|
||||
}
|
||||
while(*p && (ISALNUM(*p) || (*p == '.') || (*p == '-')))
|
||||
p++;
|
||||
dstlen = p - hostp;
|
||||
}
|
||||
if(!dstlen || (dstlen >= MAX_ALTSVC_HOSTLEN)) {
|
||||
infof(data, "Excessive alt-svc hostname, ignoring.");
|
||||
valid = FALSE;
|
||||
}
|
||||
else {
|
||||
dsthost = hostp;
|
||||
}
|
||||
if(Curl_str_single(&p, ':'))
|
||||
break;
|
||||
}
|
||||
else
|
||||
else {
|
||||
/* no destination name, use source host */
|
||||
Curl_str_assign(&dsthost, srchost, strlen(srchost));
|
||||
|
||||
if(Curl_str_number(&p, &port, 0xffff)) {
|
||||
infof(data, "Unknown alt-svc port number, ignoring.");
|
||||
break;
|
||||
dsthost = srchost;
|
||||
dstlen = strlen(srchost);
|
||||
}
|
||||
|
||||
dstport = (unsigned short)port;
|
||||
|
||||
if(Curl_str_single(&p, '\"'))
|
||||
if(*p == ':') {
|
||||
curl_off_t port = 0;
|
||||
p++;
|
||||
if(Curl_str_number(&p, &port, 0xffff) || (*p != '\"')) {
|
||||
infof(data, "Unknown alt-svc port number, ignoring.");
|
||||
valid = FALSE;
|
||||
}
|
||||
else
|
||||
dstport = (unsigned short)port;
|
||||
}
|
||||
if(*p++ != '\"')
|
||||
break;
|
||||
|
||||
if(dstalpnid) {
|
||||
/* Handle the optional 'ma' and 'persist' flags. Unknown flags
|
||||
are skipped. */
|
||||
for(;;) {
|
||||
while(ISBLANK(*p))
|
||||
p++;
|
||||
if(*p != ';')
|
||||
break;
|
||||
p++; /* pass the semicolon */
|
||||
if(!*p || ISNEWLINE(*p))
|
||||
break;
|
||||
result = getalnum(&p, option, sizeof(option));
|
||||
if(result) {
|
||||
/* skip option if name is too long */
|
||||
option[0] = '\0';
|
||||
}
|
||||
while(ISBLANK(*p))
|
||||
p++;
|
||||
if(*p != '=')
|
||||
return CURLE_OK;
|
||||
p++;
|
||||
while(ISBLANK(*p))
|
||||
p++;
|
||||
if(!*p)
|
||||
return CURLE_OK;
|
||||
if(*p == '\"') {
|
||||
/* quoted value */
|
||||
p++;
|
||||
quoted = TRUE;
|
||||
}
|
||||
value_ptr = p;
|
||||
if(quoted) {
|
||||
while(*p && *p != '\"')
|
||||
p++;
|
||||
if(!*p++)
|
||||
return CURLE_OK;
|
||||
}
|
||||
else {
|
||||
while(*p && !ISBLANK(*p) && *p!= ';' && *p != ',')
|
||||
p++;
|
||||
}
|
||||
if(!Curl_str_number(&value_ptr, &num, TIME_T_MAX)) {
|
||||
if(strcasecompare("ma", option))
|
||||
maxage = (time_t)num;
|
||||
else if(strcasecompare("persist", option) && (num == 1))
|
||||
persist = TRUE;
|
||||
}
|
||||
}
|
||||
if(dstalpnid && valid) {
|
||||
if(!entries++)
|
||||
/* Flush cached alternatives for this source origin, if any - when
|
||||
this is the first entry of the line. */
|
||||
altsvc_flush(asi, srcalpnid, srchost, srcport);
|
||||
|
||||
as = altsvc_createid(srchost, strlen(srchost),
|
||||
Curl_str(&dsthost),
|
||||
Curl_strlen(&dsthost),
|
||||
as = altsvc_createid(srchost, srchostlen,
|
||||
dsthost, dstlen,
|
||||
srcalpnid, dstalpnid,
|
||||
srcport, dstport);
|
||||
if(as) {
|
||||
@ -607,28 +647,26 @@ CURLcode Curl_altsvc_parse(struct Curl_easy *data,
|
||||
as->expires = maxage + secs;
|
||||
as->persist = persist;
|
||||
Curl_llist_append(&asi->list, as, &as->node);
|
||||
infof(data, "Added alt-svc: %.*s:%d over %s",
|
||||
(int)Curl_strlen(&dsthost), Curl_str(&dsthost),
|
||||
dstport, Curl_alpnid2str(dstalpnid));
|
||||
infof(data, "Added alt-svc: %s:%d over %s", dsthost, dstport,
|
||||
Curl_alpnid2str(dstalpnid));
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
break;
|
||||
|
||||
/* after the double quote there can be a comma if there is another
|
||||
string or a semicolon if no more */
|
||||
if(Curl_str_single(&p, ','))
|
||||
break;
|
||||
|
||||
/* comma means another alternative is present */
|
||||
if(Curl_str_until(&p, &alpn, MAX_ALTSVC_LINE, '='))
|
||||
break;
|
||||
Curl_str_trimblanks(&alpn);
|
||||
if(*p == ',') {
|
||||
/* comma means another alternative is presented */
|
||||
p++;
|
||||
result = getalnum(&p, alpnbuf, sizeof(alpnbuf));
|
||||
if(result)
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
break;
|
||||
} while(1);
|
||||
} while(*p && (*p != ';') && (*p != '\n') && (*p != '\r'));
|
||||
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
@ -245,7 +245,7 @@ static void sock_state_cb(void *data, ares_socket_t socket_fd,
|
||||
struct Curl_easy *easy = data;
|
||||
if(!readable && !writable) {
|
||||
DEBUGASSERT(easy);
|
||||
Curl_multi_will_close(easy, socket_fd);
|
||||
Curl_multi_closed(easy, socket_fd);
|
||||
}
|
||||
}
|
||||
|
||||
@ -592,7 +592,7 @@ static void query_completed_cb(void *arg, /* (struct connectdata *) */
|
||||
res->num_pending--;
|
||||
|
||||
if(CURL_ASYNC_SUCCESS == status) {
|
||||
struct Curl_addrinfo *ai = Curl_he2ai(hostent, data->conn->remote_port);
|
||||
struct Curl_addrinfo *ai = Curl_he2ai(hostent, data->state.async.port);
|
||||
if(ai) {
|
||||
compound_results(res, ai);
|
||||
}
|
||||
@ -774,6 +774,8 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data,
|
||||
if(!res->hostname)
|
||||
return NULL;
|
||||
|
||||
data->state.async.hostname = res->hostname;
|
||||
data->state.async.port = port;
|
||||
data->state.async.done = FALSE; /* not done */
|
||||
data->state.async.dns = NULL; /* clear */
|
||||
|
||||
@ -809,7 +811,6 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data,
|
||||
service, &hints, addrinfo_cb, data);
|
||||
}
|
||||
#else
|
||||
(void)port;
|
||||
|
||||
#ifdef HAVE_CARES_IPV6
|
||||
if((data->conn->ip_version != CURL_IPRESOLVE_V4) && Curl_ipv6works(data)) {
|
||||
|
||||
@ -394,13 +394,13 @@ static void destroy_async_data(struct Curl_easy *data)
|
||||
* ensure CURLMOPT_SOCKETFUNCTION fires CURL_POLL_REMOVE
|
||||
* before the FD is invalidated to avoid EBADF on EPOLL_CTL_DEL
|
||||
*/
|
||||
Curl_multi_will_close(data, sock_rd);
|
||||
Curl_multi_closed(data, sock_rd);
|
||||
wakeup_close(sock_rd);
|
||||
#endif
|
||||
|
||||
td->init = FALSE;
|
||||
}
|
||||
|
||||
Curl_safefree(async->hostname);
|
||||
}
|
||||
|
||||
#ifdef USE_HTTPSRR_ARES
|
||||
@ -414,7 +414,7 @@ static CURLcode resolve_httpsrr(struct Curl_easy *data,
|
||||
memset(&async->thdata.hinfo, 0, sizeof(struct Curl_https_rrinfo));
|
||||
async->thdata.hinfo.port = -1;
|
||||
ares_query_dnsrec(async->thdata.channel,
|
||||
data->conn->host.name, ARES_CLASS_IN,
|
||||
async->hostname, ARES_CLASS_IN,
|
||||
ARES_REC_TYPE_HTTPS,
|
||||
Curl_dnsrec_done_cb, data, NULL);
|
||||
|
||||
@ -436,6 +436,7 @@ static bool init_resolve_thread(struct Curl_easy *data,
|
||||
int err = ENOMEM;
|
||||
struct Curl_async *async = &data->state.async;
|
||||
|
||||
async->port = port;
|
||||
async->done = FALSE;
|
||||
async->dns = NULL;
|
||||
td->thread_hnd = curl_thread_t_null;
|
||||
@ -446,6 +447,11 @@ static bool init_resolve_thread(struct Curl_easy *data,
|
||||
goto errno_exit;
|
||||
}
|
||||
|
||||
free(async->hostname);
|
||||
async->hostname = strdup(hostname);
|
||||
if(!async->hostname)
|
||||
goto err_exit;
|
||||
|
||||
/* The thread will set this TRUE when complete. */
|
||||
td->tsd.done = FALSE;
|
||||
|
||||
|
||||
@ -177,7 +177,7 @@ void Curl_resolver_kill(struct Curl_easy *data);
|
||||
|
||||
/* Curl_resolver_getsock()
|
||||
*
|
||||
* This function is called from the Curl_multi_getsock() function. 'sock' is a
|
||||
* This function is called from the multi_getsock() function. 'sock' is a
|
||||
* pointer to an array to hold the file descriptors, with 'numsock' being the
|
||||
* size of that array (in number of entries). This function is supposed to
|
||||
* return bitmask indicating what file descriptors (referring to array indexes
|
||||
|
||||
@ -422,7 +422,7 @@ static int socket_close(struct Curl_easy *data, struct connectdata *conn,
|
||||
|
||||
if(use_callback && conn && conn->fclosesocket) {
|
||||
int rc;
|
||||
Curl_multi_will_close(data, sock);
|
||||
Curl_multi_closed(data, sock);
|
||||
Curl_set_in_callback(data, TRUE);
|
||||
rc = conn->fclosesocket(conn->closesocket_client, sock);
|
||||
Curl_set_in_callback(data, FALSE);
|
||||
@ -431,7 +431,7 @@ static int socket_close(struct Curl_easy *data, struct connectdata *conn,
|
||||
|
||||
if(conn)
|
||||
/* tell the multi-socket code about this */
|
||||
Curl_multi_will_close(data, sock);
|
||||
Curl_multi_closed(data, sock);
|
||||
|
||||
sclose(sock);
|
||||
|
||||
@ -997,7 +997,7 @@ 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) {
|
||||
CURL_TRC_CF(data, cf, "cf_socket_close, fd=%" FMT_SOCKET_T, ctx->sock);
|
||||
CURL_TRC_CF(data, cf, "cf_socket_close(%" FMT_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);
|
||||
@ -1019,7 +1019,7 @@ static CURLcode cf_socket_shutdown(struct Curl_cfilter *cf,
|
||||
if(cf->connected) {
|
||||
struct cf_socket_ctx *ctx = cf->ctx;
|
||||
|
||||
CURL_TRC_CF(data, cf, "cf_socket_shutdown, fd=%" FMT_SOCKET_T, ctx->sock);
|
||||
CURL_TRC_CF(data, cf, "cf_socket_shutdown(%" FMT_SOCKET_T ")", ctx->sock);
|
||||
/* On TCP, and when the socket looks well and non-blocking mode
|
||||
* can be enabled, receive dangling bytes before close to avoid
|
||||
* entering RST states unnecessarily. */
|
||||
|
||||
@ -200,8 +200,8 @@ CURLcode Curl_conn_shutdown(struct Curl_easy *data, int sockindex, bool *done)
|
||||
*done = FALSE;
|
||||
now = Curl_now();
|
||||
if(!Curl_shutdown_started(data, sockindex)) {
|
||||
CURL_TRC_M(data, "shutdown start on%s connection",
|
||||
sockindex ? " secondary" : "");
|
||||
DEBUGF(infof(data, "shutdown start on%s connection",
|
||||
sockindex ? " secondary" : ""));
|
||||
Curl_shutdown_start(data, sockindex, &now);
|
||||
}
|
||||
else {
|
||||
@ -476,7 +476,7 @@ CURLcode Curl_conn_connect(struct Curl_easy *data,
|
||||
/* In general, we want to send after connect, wait on that. */
|
||||
if(sockfd != CURL_SOCKET_BAD)
|
||||
Curl_pollset_set_out_only(data, &ps, sockfd);
|
||||
Curl_conn_adjust_pollset(data, data->conn, &ps);
|
||||
Curl_conn_adjust_pollset(data, &ps);
|
||||
result = Curl_pollfds_add_ps(&cpfds, &ps);
|
||||
if(result)
|
||||
goto out;
|
||||
@ -626,15 +626,14 @@ void Curl_conn_cf_adjust_pollset(struct Curl_cfilter *cf,
|
||||
}
|
||||
|
||||
void Curl_conn_adjust_pollset(struct Curl_easy *data,
|
||||
struct connectdata *conn,
|
||||
struct easy_pollset *ps)
|
||||
struct easy_pollset *ps)
|
||||
{
|
||||
int i;
|
||||
|
||||
DEBUGASSERT(data);
|
||||
DEBUGASSERT(conn);
|
||||
DEBUGASSERT(data->conn);
|
||||
for(i = 0; i < 2; ++i) {
|
||||
Curl_conn_cf_adjust_pollset(conn->cfilter[i], data, ps);
|
||||
Curl_conn_cf_adjust_pollset(data->conn->cfilter[i], data, ps);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -455,8 +455,7 @@ void Curl_conn_cf_adjust_pollset(struct Curl_cfilter *cf,
|
||||
* Adjust pollset from filters installed at transfer's connection.
|
||||
*/
|
||||
void Curl_conn_adjust_pollset(struct Curl_easy *data,
|
||||
struct connectdata *conn,
|
||||
struct easy_pollset *ps);
|
||||
struct easy_pollset *ps);
|
||||
|
||||
/**
|
||||
* Curl_poll() the filter chain at `cf` with timeout `timeout_ms`.
|
||||
|
||||
148
lib/conncache.c
148
lib/conncache.c
@ -32,7 +32,6 @@
|
||||
#include "cfilters.h"
|
||||
#include "progress.h"
|
||||
#include "multiif.h"
|
||||
#include "multi_ev.h"
|
||||
#include "sendf.h"
|
||||
#include "conncache.h"
|
||||
#include "http_negotiate.h"
|
||||
@ -95,8 +94,8 @@ static void cpool_run_conn_shutdown(struct Curl_easy *data,
|
||||
bool *done);
|
||||
static void cpool_run_conn_shutdown_handler(struct Curl_easy *data,
|
||||
struct connectdata *conn);
|
||||
static CURLMcode cpool_update_shutdown_ev(struct cpool *cpool,
|
||||
struct Curl_multi *multi,
|
||||
static CURLMcode cpool_update_shutdown_ev(struct Curl_multi *multi,
|
||||
struct Curl_easy *data,
|
||||
struct connectdata *conn);
|
||||
static void cpool_shutdown_all(struct cpool *cpool,
|
||||
struct Curl_easy *data, int timeout_ms);
|
||||
@ -149,10 +148,10 @@ static void cpool_bundle_free_entry(void *freethis)
|
||||
}
|
||||
|
||||
int Curl_cpool_init(struct cpool *cpool,
|
||||
Curl_cpool_disconnect_cb *disconnect_cb,
|
||||
struct Curl_multi *multi,
|
||||
struct Curl_share *share,
|
||||
size_t size)
|
||||
Curl_cpool_disconnect_cb *disconnect_cb,
|
||||
struct Curl_multi *multi,
|
||||
struct Curl_share *share,
|
||||
size_t size)
|
||||
{
|
||||
DEBUGASSERT(!!multi != !!share); /* either one */
|
||||
Curl_hash_init(&cpool->dest2bundle, size, Curl_hash_str,
|
||||
@ -318,10 +317,10 @@ int Curl_cpool_check_limits(struct Curl_easy *data,
|
||||
if(!oldest_idle)
|
||||
break;
|
||||
/* disconnect the old conn and continue */
|
||||
CURL_TRC_M(data, "Discarding connection #%"
|
||||
DEBUGF(infof(data, "Discarding connection #%"
|
||||
FMT_OFF_T " from %zu to reach destination "
|
||||
"limit of %zu", oldest_idle->connection_id,
|
||||
Curl_llist_count(&bundle->conns), dest_limit);
|
||||
Curl_llist_count(&bundle->conns), dest_limit));
|
||||
Curl_cpool_disconnect(data, oldest_idle, FALSE);
|
||||
|
||||
/* in case the bundle was destroyed in disconnect, look it up again */
|
||||
@ -342,10 +341,10 @@ int Curl_cpool_check_limits(struct Curl_easy *data,
|
||||
if(!oldest_idle)
|
||||
break;
|
||||
/* disconnect the old conn and continue */
|
||||
CURL_TRC_M(data, "Discarding connection #%"
|
||||
FMT_OFF_T " from %zu to reach total "
|
||||
"limit of %zu",
|
||||
oldest_idle->connection_id, cpool->num_conn, total_limit);
|
||||
DEBUGF(infof(data, "Discarding connection #%"
|
||||
FMT_OFF_T " from %zu to reach total "
|
||||
"limit of %zu",
|
||||
oldest_idle->connection_id, cpool->num_conn, total_limit));
|
||||
Curl_cpool_disconnect(data, oldest_idle, FALSE);
|
||||
shutdowns = Curl_llist_count(&cpool->shutdowns);
|
||||
}
|
||||
@ -653,6 +652,8 @@ static void cpool_shutdown_discard_all(struct cpool *cpool)
|
||||
while(e) {
|
||||
conn = Curl_node_elem(e);
|
||||
Curl_node_remove(e);
|
||||
DEBUGF(infof(cpool->idata, "discard connection #%" FMT_OFF_T,
|
||||
conn->connection_id));
|
||||
cpool_close_and_destroy(cpool, conn, NULL, FALSE);
|
||||
e = Curl_llist_head(&cpool->shutdowns);
|
||||
}
|
||||
@ -734,9 +735,9 @@ static void cpool_discard_conn(struct cpool *cpool,
|
||||
* are other users of it
|
||||
*/
|
||||
if(CONN_INUSE(conn) && !aborted) {
|
||||
CURL_TRC_M(data, "[CPOOL] not discarding #%" FMT_OFF_T
|
||||
" still in use by %zu transfers", conn->connection_id,
|
||||
CONN_INUSE(conn));
|
||||
DEBUGF(infof(data, "[CCACHE] not discarding #%" FMT_OFF_T
|
||||
" still in use by %zu transfers", conn->connection_id,
|
||||
CONN_INUSE(conn)));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -757,7 +758,8 @@ static void cpool_discard_conn(struct cpool *cpool,
|
||||
/* Attempt to shutdown the connection right away. */
|
||||
Curl_attach_connection(data, conn);
|
||||
cpool_run_conn_shutdown(data, conn, &done);
|
||||
CURL_TRC_M(data, "[CPOOL] shutdown, done=%d", done);
|
||||
DEBUGF(infof(data, "[CCACHE] shutdown #%" FMT_OFF_T ", done=%d",
|
||||
conn->connection_id, done));
|
||||
Curl_detach_connection(data);
|
||||
}
|
||||
|
||||
@ -771,26 +773,30 @@ static void cpool_discard_conn(struct cpool *cpool,
|
||||
if(data->multi && data->multi->max_total_connections > 0 &&
|
||||
(data->multi->max_total_connections <=
|
||||
(long)(cpool->num_conn + Curl_llist_count(&cpool->shutdowns)))) {
|
||||
CURL_TRC_M(data, "[CPOOL] discarding oldest shutdown connection "
|
||||
"due to connection limit of %ld",
|
||||
data->multi->max_total_connections);
|
||||
DEBUGF(infof(data, "[CCACHE] discarding oldest shutdown connection "
|
||||
"due to connection limit of %ld",
|
||||
data->multi->max_total_connections));
|
||||
cpool_shutdown_destroy_oldest(cpool);
|
||||
}
|
||||
|
||||
if(data->multi && data->multi->socket_cb) {
|
||||
DEBUGASSERT(cpool == &data->multi->cpool);
|
||||
if(cpool_update_shutdown_ev(cpool, data->multi, conn)) {
|
||||
CURL_TRC_M(data, "[CPOOL] update events failed, discarding #%"
|
||||
FMT_OFF_T, conn->connection_id);
|
||||
/* Start with an empty shutdown pollset, so out internal closure handle
|
||||
* is added to the sockets. */
|
||||
memset(&conn->shutdown_poll, 0, sizeof(conn->shutdown_poll));
|
||||
if(cpool_update_shutdown_ev(data->multi, cpool->idata, conn)) {
|
||||
DEBUGF(infof(data, "[CCACHE] update events for shutdown failed, "
|
||||
"discarding #%" FMT_OFF_T,
|
||||
conn->connection_id));
|
||||
cpool_close_and_destroy(cpool, conn, data, FALSE);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Curl_llist_append(&cpool->shutdowns, conn, &conn->cpool_node);
|
||||
CURL_TRC_M(data, "[CPOOL] added #%" FMT_OFF_T
|
||||
" to shutdowns, now %zu conns in shutdown",
|
||||
conn->connection_id, Curl_llist_count(&cpool->shutdowns));
|
||||
DEBUGF(infof(data, "[CCACHE] added #%" FMT_OFF_T
|
||||
" to shutdowns, now %zu conns in shutdown",
|
||||
conn->connection_id, Curl_llist_count(&cpool->shutdowns)));
|
||||
}
|
||||
|
||||
void Curl_cpool_disconnect(struct Curl_easy *data,
|
||||
@ -924,7 +930,7 @@ static CURLcode cpool_add_pollfds(struct cpool *cpool,
|
||||
conn = Curl_node_elem(e);
|
||||
memset(&ps, 0, sizeof(ps));
|
||||
Curl_attach_connection(cpool->idata, conn);
|
||||
Curl_conn_adjust_pollset(cpool->idata, conn, &ps);
|
||||
Curl_conn_adjust_pollset(cpool->idata, &ps);
|
||||
Curl_detach_connection(cpool->idata);
|
||||
|
||||
result = Curl_pollfds_add_ps(cpfds, &ps);
|
||||
@ -965,7 +971,7 @@ unsigned int Curl_cpool_add_waitfds(struct cpool *cpool,
|
||||
conn = Curl_node_elem(e);
|
||||
memset(&ps, 0, sizeof(ps));
|
||||
Curl_attach_connection(cpool->idata, conn);
|
||||
Curl_conn_adjust_pollset(cpool->idata, conn, &ps);
|
||||
Curl_conn_adjust_pollset(cpool->idata, &ps);
|
||||
Curl_detach_connection(cpool->idata);
|
||||
|
||||
need += Curl_waitfds_add_ps(cwfds, &ps);
|
||||
@ -991,7 +997,7 @@ void Curl_cpool_setfds(struct cpool *cpool,
|
||||
struct connectdata *conn = Curl_node_elem(e);
|
||||
memset(&ps, 0, sizeof(ps));
|
||||
Curl_attach_connection(cpool->idata, conn);
|
||||
Curl_conn_adjust_pollset(cpool->idata, conn, &ps);
|
||||
Curl_conn_adjust_pollset(cpool->idata, &ps);
|
||||
Curl_detach_connection(cpool->idata);
|
||||
|
||||
for(i = 0; i < ps.num; i++) {
|
||||
@ -1030,14 +1036,15 @@ static void cpool_perform(struct cpool *cpool)
|
||||
return;
|
||||
|
||||
DEBUGASSERT(data);
|
||||
CURL_TRC_M(data, "[CPOOL] perform, %zu connections being shutdown",
|
||||
Curl_llist_count(&cpool->shutdowns));
|
||||
DEBUGF(infof(data, "[CCACHE] perform, %zu connections being shutdown",
|
||||
Curl_llist_count(&cpool->shutdowns)));
|
||||
while(e) {
|
||||
enext = Curl_node_next(e);
|
||||
conn = Curl_node_elem(e);
|
||||
Curl_attach_connection(data, conn);
|
||||
cpool_run_conn_shutdown(data, conn, &done);
|
||||
CURL_TRC_M(data, "[CPOOL] shutdown, done=%d", done);
|
||||
DEBUGF(infof(data, "[CCACHE] shutdown #%" FMT_OFF_T ", done=%d",
|
||||
conn->connection_id, done));
|
||||
Curl_detach_connection(data);
|
||||
if(done) {
|
||||
Curl_node_remove(e);
|
||||
@ -1060,6 +1067,14 @@ static void cpool_perform(struct cpool *cpool)
|
||||
Curl_expire(data, next_from_now_ms, EXPIRE_RUN_NOW);
|
||||
}
|
||||
|
||||
void Curl_cpool_multi_perform(struct Curl_multi *multi)
|
||||
{
|
||||
CPOOL_LOCK(&multi->cpool);
|
||||
cpool_perform(&multi->cpool);
|
||||
CPOOL_UNLOCK(&multi->cpool);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Close and destroy the connection. Run the shutdown sequence once,
|
||||
* of so requested.
|
||||
@ -1093,7 +1108,8 @@ static void cpool_close_and_destroy(struct cpool *cpool,
|
||||
}
|
||||
|
||||
if(cpool)
|
||||
CURL_TRC_M(data, "[CPOOL] closing connection");
|
||||
DEBUGF(infof(data, "[CCACHE] closing #%" FMT_OFF_T,
|
||||
conn->connection_id));
|
||||
else
|
||||
DEBUGF(infof(data, "closing connection #%" FMT_OFF_T,
|
||||
conn->connection_id));
|
||||
@ -1101,54 +1117,60 @@ static void cpool_close_and_destroy(struct cpool *cpool,
|
||||
Curl_conn_close(data, FIRSTSOCKET);
|
||||
Curl_detach_connection(data);
|
||||
|
||||
if(cpool && cpool->multi)
|
||||
Curl_multi_ev_conn_done(cpool->multi, data, conn);
|
||||
else if(data->multi)
|
||||
Curl_multi_ev_conn_done(data->multi, data, conn);
|
||||
|
||||
Curl_conn_free(data, conn);
|
||||
|
||||
if(cpool && cpool->multi) {
|
||||
CURL_TRC_M(data, "[CPOOL] trigger multi connchanged");
|
||||
DEBUGF(infof(data, "[CCACHE] trigger multi connchanged"));
|
||||
Curl_multi_connchanged(cpool->multi);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static CURLMcode cpool_update_shutdown_ev(struct cpool *cpool,
|
||||
struct Curl_multi *multi,
|
||||
static CURLMcode cpool_update_shutdown_ev(struct Curl_multi *multi,
|
||||
struct Curl_easy *data,
|
||||
struct connectdata *conn)
|
||||
{
|
||||
struct easy_pollset ps;
|
||||
CURLMcode mresult;
|
||||
|
||||
DEBUGASSERT(cpool);
|
||||
DEBUGASSERT(data);
|
||||
DEBUGASSERT(multi);
|
||||
DEBUGASSERT(multi->socket_cb);
|
||||
|
||||
Curl_attach_connection(cpool->idata, conn);
|
||||
mresult = Curl_multi_ev_assess_conn(multi, cpool->idata, conn);
|
||||
Curl_detach_connection(cpool->idata);
|
||||
memset(&ps, 0, sizeof(ps));
|
||||
Curl_attach_connection(data, conn);
|
||||
Curl_conn_adjust_pollset(data, &ps);
|
||||
Curl_detach_connection(data);
|
||||
|
||||
mresult = Curl_multi_pollset_ev(multi, data, &ps, &conn->shutdown_poll);
|
||||
|
||||
if(!mresult) /* Remember for next time */
|
||||
memcpy(&conn->shutdown_poll, &ps, sizeof(ps));
|
||||
return mresult;
|
||||
}
|
||||
|
||||
static void cpool_multi_socket(struct Curl_multi *multi, curl_socket_t s)
|
||||
void Curl_cpool_multi_socket(struct Curl_multi *multi,
|
||||
curl_socket_t s, int ev_bitmask)
|
||||
{
|
||||
struct cpool *cpool = &multi->cpool;
|
||||
struct Curl_easy *data = cpool->idata;
|
||||
struct Curl_llist_node *e;
|
||||
struct connectdata *conn;
|
||||
bool done;
|
||||
|
||||
(void)ev_bitmask;
|
||||
DEBUGASSERT(multi->socket_cb);
|
||||
CPOOL_LOCK(cpool);
|
||||
e = Curl_llist_head(&cpool->shutdowns);
|
||||
while(e) {
|
||||
conn = Curl_node_elem(e);
|
||||
if(s == conn->sock[FIRSTSOCKET] || s == conn->sock[SECONDARYSOCKET]) {
|
||||
Curl_attach_connection(cpool->idata, conn);
|
||||
cpool_run_conn_shutdown(cpool->idata, conn, &done);
|
||||
CURL_TRC_M(cpool->idata, "[CPOOL] shutdown, done=%d", done);
|
||||
Curl_detach_connection(cpool->idata);
|
||||
if(done || cpool_update_shutdown_ev(cpool, multi, conn)) {
|
||||
Curl_attach_connection(data, conn);
|
||||
cpool_run_conn_shutdown(data, conn, &done);
|
||||
DEBUGF(infof(data, "[CCACHE] shutdown #%" FMT_OFF_T ", done=%d",
|
||||
conn->connection_id, done));
|
||||
Curl_detach_connection(data);
|
||||
if(done || cpool_update_shutdown_ev(multi, data, conn)) {
|
||||
Curl_node_remove(e);
|
||||
cpool_close_and_destroy(cpool, conn, NULL, FALSE);
|
||||
}
|
||||
@ -1159,17 +1181,6 @@ static void cpool_multi_socket(struct Curl_multi *multi, curl_socket_t s)
|
||||
CPOOL_UNLOCK(cpool);
|
||||
}
|
||||
|
||||
void Curl_cpool_multi_perform(struct Curl_multi *multi, curl_socket_t s)
|
||||
{
|
||||
CPOOL_LOCK(&multi->cpool);
|
||||
if((s == CURL_SOCKET_TIMEOUT) || (!multi->socket_cb))
|
||||
cpool_perform(&multi->cpool);
|
||||
else
|
||||
cpool_multi_socket(multi, s);
|
||||
CPOOL_UNLOCK(&multi->cpool);
|
||||
}
|
||||
|
||||
|
||||
#define NUM_POLLS_ON_STACK 10
|
||||
|
||||
static CURLcode cpool_shutdown_wait(struct cpool *cpool, int timeout_ms)
|
||||
@ -1201,13 +1212,14 @@ static void cpool_shutdown_all(struct cpool *cpool,
|
||||
return;
|
||||
(void)data;
|
||||
|
||||
CURL_TRC_M(data, "[CPOOL] shutdown all");
|
||||
DEBUGF(infof(data, "cpool shutdown all"));
|
||||
|
||||
/* Move all connections into the shutdown queue */
|
||||
for(conn = cpool_get_live_conn(cpool); conn;
|
||||
conn = cpool_get_live_conn(cpool)) {
|
||||
/* Move conn from live set to shutdown or destroy right away */
|
||||
CURL_TRC_M(data, "[CPOOL] moving connection to shutdown queue");
|
||||
DEBUGF(infof(data, "moving connection #%" FMT_OFF_T
|
||||
" to shutdown queue", conn->connection_id));
|
||||
cpool_remove_conn(cpool, conn);
|
||||
cpool_discard_conn(cpool, data, conn, FALSE);
|
||||
}
|
||||
@ -1219,21 +1231,21 @@ static void cpool_shutdown_all(struct cpool *cpool,
|
||||
cpool_perform(cpool);
|
||||
|
||||
if(!Curl_llist_head(&cpool->shutdowns)) {
|
||||
CURL_TRC_M(data, "[CPOOL] shutdown finished cleanly");
|
||||
DEBUGF(infof(data, "cpool shutdown ok"));
|
||||
break;
|
||||
}
|
||||
|
||||
/* wait for activity, timeout or "nothing" */
|
||||
timespent = Curl_timediff(Curl_now(), started);
|
||||
if(timespent >= (timediff_t)timeout_ms) {
|
||||
CURL_TRC_M(data, "[CPOOL] shutdown finished, %s",
|
||||
(timeout_ms > 0) ? "timeout" : "best effort done");
|
||||
DEBUGF(infof(data, "cpool shutdown %s",
|
||||
(timeout_ms > 0) ? "timeout" : "best effort done"));
|
||||
break;
|
||||
}
|
||||
|
||||
remain_ms = timeout_ms - (int)timespent;
|
||||
if(cpool_shutdown_wait(cpool, remain_ms)) {
|
||||
CURL_TRC_M(data, "[CPOOL] shutdown finished, aborted");
|
||||
DEBUGF(infof(data, "cpool shutdown all, abort"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -191,9 +191,13 @@ void Curl_cpool_setfds(struct cpool *cpool,
|
||||
int *maxfd);
|
||||
|
||||
/**
|
||||
* Run connections on socket. If socket is CURL_SOCKET_TIMEOUT, run
|
||||
* maintenance on all connections.
|
||||
* Perform maintenance on connections in the pool. Specifically,
|
||||
* progress the shutdown of connections in the queue.
|
||||
*/
|
||||
void Curl_cpool_multi_perform(struct Curl_multi *multi, curl_socket_t s);
|
||||
void Curl_cpool_multi_perform(struct Curl_multi *multi);
|
||||
|
||||
void Curl_cpool_multi_socket(struct Curl_multi *multi,
|
||||
curl_socket_t s, int ev_bitmask);
|
||||
|
||||
|
||||
#endif /* HEADER_CURL_CONNCACHE_H */
|
||||
|
||||
@ -536,9 +536,9 @@ parse_cookie_header(struct Curl_easy *data,
|
||||
* "the rest". Prefixes must start with '__' and end with a '-', so
|
||||
* only test for names where that can possibly be true.
|
||||
*/
|
||||
if(!strncmp("__Secure-", Curl_str(&name), 9))
|
||||
if(strncasecompare("__Secure-", Curl_str(&name), 9))
|
||||
co->prefix_secure = TRUE;
|
||||
else if(!strncmp("__Host-", Curl_str(&name), 7))
|
||||
else if(strncasecompare("__Host-", Curl_str(&name), 7))
|
||||
co->prefix_host = TRUE;
|
||||
|
||||
/*
|
||||
|
||||
@ -34,9 +34,15 @@
|
||||
#endif
|
||||
|
||||
#else /* HAVE_MEMRCHR */
|
||||
#if (!defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)) || \
|
||||
defined(USE_OPENSSL) || \
|
||||
defined(USE_SCHANNEL)
|
||||
|
||||
void *Curl_memrchr(const void *s, int c, size_t n);
|
||||
|
||||
#define memrchr(x,y,z) Curl_memrchr((x),(y),(z))
|
||||
|
||||
#endif
|
||||
#endif /* HAVE_MEMRCHR */
|
||||
|
||||
#endif /* HEADER_CURL_MEMRCHR_H */
|
||||
|
||||
@ -120,14 +120,6 @@
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Avoid bogus format check warnings with mingw32ce gcc 4.4.0 in
|
||||
C99 (-std=gnu99) mode */
|
||||
#if defined(__MINGW32CE__) && !defined(CURL_NO_FMT_CHECKS) && \
|
||||
(defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) && \
|
||||
(defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ == 4))
|
||||
#define CURL_NO_FMT_CHECKS
|
||||
#endif
|
||||
|
||||
/* Compatibility */
|
||||
#ifdef ENABLE_IPV6
|
||||
#define USE_IPV6 1
|
||||
|
||||
229
lib/curl_trc.c
229
lib/curl_trc.c
@ -53,10 +53,12 @@
|
||||
#include "curl_memory.h"
|
||||
#include "memdebug.h"
|
||||
|
||||
static void trc_write(struct Curl_easy *data, curl_infotype type,
|
||||
char *ptr, size_t size)
|
||||
void Curl_debug(struct Curl_easy *data, curl_infotype type,
|
||||
char *ptr, size_t size)
|
||||
{
|
||||
if(data->set.verbose) {
|
||||
static const char s_infotype[CURLINFO_END][3] = {
|
||||
"* ", "< ", "> ", "{ ", "} ", "{ ", "} " };
|
||||
if(data->set.fdebug) {
|
||||
bool inCallback = Curl_is_in_callback(data);
|
||||
Curl_set_in_callback(data, TRUE);
|
||||
@ -64,8 +66,6 @@ static void trc_write(struct Curl_easy *data, curl_infotype type,
|
||||
Curl_set_in_callback(data, inCallback);
|
||||
}
|
||||
else {
|
||||
static const char s_infotype[CURLINFO_END][3] = {
|
||||
"* ", "< ", "> ", "{ ", "} ", "{ ", "} " };
|
||||
switch(type) {
|
||||
case CURLINFO_TEXT:
|
||||
case CURLINFO_HEADER_OUT:
|
||||
@ -80,100 +80,6 @@ static void trc_write(struct Curl_easy *data, curl_infotype type,
|
||||
}
|
||||
}
|
||||
|
||||
/* max length we trace before ending in '...' */
|
||||
#define TRC_LINE_MAX 2048
|
||||
|
||||
#define CURL_TRC_FMT_IDSC "[x-%" CURL_FORMAT_CURL_OFF_T "] "
|
||||
#define CURL_TRC_FMT_IDSD "[%" CURL_FORMAT_CURL_OFF_T "-x] "
|
||||
#define CURL_TRC_FMT_IDSDC "[%" CURL_FORMAT_CURL_OFF_T "-%" \
|
||||
CURL_FORMAT_CURL_OFF_T "] "
|
||||
|
||||
static struct curl_trc_feat Curl_trc_feat_ids = {
|
||||
"LIB-IDS",
|
||||
CURL_LOG_LVL_NONE,
|
||||
};
|
||||
#define CURL_TRC_IDS(data) \
|
||||
(Curl_trc_is_verbose(data) && \
|
||||
Curl_trc_feat_ids.log_level >= CURL_LOG_LVL_INFO)
|
||||
|
||||
static size_t trc_print_ids(struct Curl_easy *data, char *buf, size_t maxlen)
|
||||
{
|
||||
curl_off_t cid = data->conn ?
|
||||
data->conn->connection_id : data->state.recent_conn_id;
|
||||
if(data->id >= 0) {
|
||||
if(cid >= 0)
|
||||
return msnprintf(buf, maxlen, CURL_TRC_FMT_IDSDC, data->id, cid);
|
||||
else
|
||||
return msnprintf(buf, maxlen, CURL_TRC_FMT_IDSD, data->id);
|
||||
}
|
||||
else if(cid >= 0)
|
||||
return msnprintf(buf, maxlen, CURL_TRC_FMT_IDSC, cid);
|
||||
else {
|
||||
return msnprintf(buf, maxlen, "[x-x] ");
|
||||
}
|
||||
}
|
||||
|
||||
static size_t trc_end_buf(char *buf, size_t len, size_t maxlen, bool addnl)
|
||||
{
|
||||
/* make sure we end the trace line in `buf` properly. It needs
|
||||
* to end with a terminating '\0' or '\n\0' */
|
||||
if(len >= (maxlen - (addnl ? 2 : 1))) {
|
||||
len = maxlen - 5;
|
||||
buf[len++] = '.';
|
||||
buf[len++] = '.';
|
||||
buf[len++] = '.';
|
||||
buf[len++] = '\n';
|
||||
}
|
||||
else if(addnl)
|
||||
buf[len++] = '\n';
|
||||
buf[len] = '\0';
|
||||
return len;
|
||||
}
|
||||
|
||||
void Curl_debug(struct Curl_easy *data, curl_infotype type,
|
||||
char *ptr, size_t size)
|
||||
{
|
||||
if(data->set.verbose) {
|
||||
static const char s_infotype[CURLINFO_END][3] = {
|
||||
"* ", "< ", "> ", "{ ", "} ", "{ ", "} " };
|
||||
char buf[TRC_LINE_MAX];
|
||||
size_t len;
|
||||
if(data->set.fdebug) {
|
||||
bool inCallback = Curl_is_in_callback(data);
|
||||
|
||||
if(CURL_TRC_IDS(data) && (size < TRC_LINE_MAX)) {
|
||||
len = trc_print_ids(data, buf, TRC_LINE_MAX);
|
||||
len += msnprintf(buf + len, TRC_LINE_MAX - len, "%.*s",
|
||||
(int)size, ptr);
|
||||
len = trc_end_buf(buf, len, TRC_LINE_MAX, FALSE);
|
||||
Curl_set_in_callback(data, TRUE);
|
||||
(void)(*data->set.fdebug)(data, type, buf, len, data->set.debugdata);
|
||||
Curl_set_in_callback(data, inCallback);
|
||||
}
|
||||
else {
|
||||
Curl_set_in_callback(data, TRUE);
|
||||
(void)(*data->set.fdebug)(data, type, ptr, size, data->set.debugdata);
|
||||
Curl_set_in_callback(data, inCallback);
|
||||
}
|
||||
}
|
||||
else {
|
||||
switch(type) {
|
||||
case CURLINFO_TEXT:
|
||||
case CURLINFO_HEADER_OUT:
|
||||
case CURLINFO_HEADER_IN:
|
||||
if(CURL_TRC_IDS(data)) {
|
||||
len = trc_print_ids(data, buf, TRC_LINE_MAX);
|
||||
fwrite(buf, len, 1, data->set.err);
|
||||
}
|
||||
fwrite(s_infotype[type], 2, 1, data->set.err);
|
||||
fwrite(ptr, size, 1, data->set.err);
|
||||
break;
|
||||
default: /* nada */
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Curl_failf() is for messages stating why we failed.
|
||||
* The message SHALL NOT include any LF or CR.
|
||||
@ -183,7 +89,7 @@ void Curl_failf(struct Curl_easy *data, const char *fmt, ...)
|
||||
DEBUGASSERT(!strchr(fmt, '\n'));
|
||||
if(data->set.verbose || data->set.errorbuffer) {
|
||||
va_list ap;
|
||||
size_t len;
|
||||
int len;
|
||||
char error[CURL_ERROR_SIZE + 2];
|
||||
va_start(ap, fmt);
|
||||
len = mvsnprintf(error, CURL_ERROR_SIZE, fmt, ap);
|
||||
@ -194,41 +100,36 @@ void Curl_failf(struct Curl_easy *data, const char *fmt, ...)
|
||||
}
|
||||
error[len++] = '\n';
|
||||
error[len] = '\0';
|
||||
trc_write(data, CURLINFO_TEXT, error, len);
|
||||
Curl_debug(data, CURLINFO_TEXT, error, len);
|
||||
va_end(ap);
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined(CURL_DISABLE_VERBOSE_STRINGS)
|
||||
|
||||
/* Curl_infof() is for info message along the way */
|
||||
#define MAXINFO 2048
|
||||
|
||||
static void trc_infof(struct Curl_easy *data,
|
||||
struct curl_trc_feat *feat,
|
||||
const char *opt_id, int opt_id_idx,
|
||||
const char * const fmt, va_list ap) CURL_PRINTF(5, 0);
|
||||
static void trc_infof(struct Curl_easy *data, struct curl_trc_feat *feat,
|
||||
const char * const fmt, va_list ap) CURL_PRINTF(3, 0);
|
||||
|
||||
static void trc_infof(struct Curl_easy *data,
|
||||
struct curl_trc_feat *feat,
|
||||
const char *opt_id, int opt_id_idx,
|
||||
static void trc_infof(struct Curl_easy *data, struct curl_trc_feat *feat,
|
||||
const char * const fmt, va_list ap)
|
||||
{
|
||||
size_t len = 0;
|
||||
char buf[TRC_LINE_MAX];
|
||||
|
||||
if(CURL_TRC_IDS(data))
|
||||
len += trc_print_ids(data, buf + len, TRC_LINE_MAX - len);
|
||||
int len = 0;
|
||||
char buffer[MAXINFO + 5];
|
||||
if(feat)
|
||||
len += msnprintf(buf + len, TRC_LINE_MAX - len, "[%s] ", feat->name);
|
||||
if(opt_id) {
|
||||
if(opt_id_idx > 0)
|
||||
len += msnprintf(buf + len, TRC_LINE_MAX - len, "[%s-%d] ",
|
||||
opt_id, opt_id_idx);
|
||||
else
|
||||
len += msnprintf(buf + len, TRC_LINE_MAX - len, "[%s] ", opt_id);
|
||||
len = msnprintf(buffer, (MAXINFO + 1), "[%s] ", feat->name);
|
||||
len += mvsnprintf(buffer + len, (MAXINFO + 1) - len, fmt, ap);
|
||||
if(len >= MAXINFO) { /* too long, shorten with '...' */
|
||||
--len;
|
||||
buffer[len++] = '.';
|
||||
buffer[len++] = '.';
|
||||
buffer[len++] = '.';
|
||||
}
|
||||
len += mvsnprintf(buf + len, TRC_LINE_MAX - len, fmt, ap);
|
||||
len = trc_end_buf(buf, len, TRC_LINE_MAX, TRUE);
|
||||
trc_write(data, CURLINFO_TEXT, buf, len);
|
||||
buffer[len++] = '\n';
|
||||
buffer[len] = '\0';
|
||||
Curl_debug(data, CURLINFO_TEXT, buffer, len);
|
||||
}
|
||||
|
||||
void Curl_infof(struct Curl_easy *data, const char *fmt, ...)
|
||||
@ -237,7 +138,7 @@ void Curl_infof(struct Curl_easy *data, const char *fmt, ...)
|
||||
if(Curl_trc_is_verbose(data)) {
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
trc_infof(data, data->state.feat, NULL, 0, fmt, ap);
|
||||
trc_infof(data, data->state.feat, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
}
|
||||
@ -248,16 +149,25 @@ void Curl_trc_cf_infof(struct Curl_easy *data, struct Curl_cfilter *cf,
|
||||
DEBUGASSERT(cf);
|
||||
if(Curl_trc_cf_is_verbose(cf, data)) {
|
||||
va_list ap;
|
||||
int len = 0;
|
||||
char buffer[MAXINFO + 2];
|
||||
if(data->state.feat)
|
||||
len += msnprintf(buffer + len, MAXINFO - len, "[%s] ",
|
||||
data->state.feat->name);
|
||||
if(cf->sockindex)
|
||||
len += msnprintf(buffer + len, MAXINFO - len, "[%s-%d] ",
|
||||
cf->cft->name, cf->sockindex);
|
||||
else
|
||||
len += msnprintf(buffer + len, MAXINFO - len, "[%s] ", cf->cft->name);
|
||||
va_start(ap, fmt);
|
||||
trc_infof(data, data->state.feat, cf->cft->name, cf->sockindex, fmt, ap);
|
||||
len += mvsnprintf(buffer + len, MAXINFO - len, fmt, ap);
|
||||
va_end(ap);
|
||||
buffer[len++] = '\n';
|
||||
buffer[len] = '\0';
|
||||
Curl_debug(data, CURLINFO_TEXT, buffer, len);
|
||||
}
|
||||
}
|
||||
|
||||
struct curl_trc_feat Curl_trc_feat_multi = {
|
||||
"MULTI",
|
||||
CURL_LOG_LVL_NONE,
|
||||
};
|
||||
struct curl_trc_feat Curl_trc_feat_read = {
|
||||
"READ",
|
||||
CURL_LOG_LVL_NONE,
|
||||
@ -272,54 +182,13 @@ struct curl_trc_feat Curl_trc_feat_dns = {
|
||||
};
|
||||
|
||||
|
||||
static const char * const Curl_trc_mstate_names[]={
|
||||
"INIT",
|
||||
"PENDING",
|
||||
"SETUP",
|
||||
"CONNECT",
|
||||
"RESOLVING",
|
||||
"CONNECTING",
|
||||
"TUNNELING",
|
||||
"PROTOCONNECT",
|
||||
"PROTOCONNECTING",
|
||||
"DO",
|
||||
"DOING",
|
||||
"DOING_MORE",
|
||||
"DID",
|
||||
"PERFORMING",
|
||||
"RATELIMITING",
|
||||
"DONE",
|
||||
"COMPLETED",
|
||||
"MSGSENT",
|
||||
};
|
||||
|
||||
const char *Curl_trc_mstate_name(int state)
|
||||
{
|
||||
if((state >= 0) && ((size_t)state < CURL_ARRAYSIZE(Curl_trc_mstate_names)))
|
||||
return Curl_trc_mstate_names[(size_t)state];
|
||||
return "?";
|
||||
}
|
||||
|
||||
void Curl_trc_multi(struct Curl_easy *data, const char *fmt, ...)
|
||||
{
|
||||
DEBUGASSERT(!strchr(fmt, '\n'));
|
||||
if(Curl_trc_ft_is_verbose(data, &Curl_trc_feat_multi)) {
|
||||
const char *sname = (data->id >= 0) ?
|
||||
Curl_trc_mstate_name(data->mstate) : NULL;
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
trc_infof(data, &Curl_trc_feat_multi, sname, 0, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
}
|
||||
|
||||
void Curl_trc_read(struct Curl_easy *data, const char *fmt, ...)
|
||||
{
|
||||
DEBUGASSERT(!strchr(fmt, '\n'));
|
||||
if(Curl_trc_ft_is_verbose(data, &Curl_trc_feat_read)) {
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
trc_infof(data, &Curl_trc_feat_read, NULL, 0, fmt, ap);
|
||||
trc_infof(data, &Curl_trc_feat_read, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
}
|
||||
@ -330,7 +199,7 @@ void Curl_trc_write(struct Curl_easy *data, const char *fmt, ...)
|
||||
if(Curl_trc_ft_is_verbose(data, &Curl_trc_feat_write)) {
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
trc_infof(data, &Curl_trc_feat_write, NULL, 0, fmt, ap);
|
||||
trc_infof(data, &Curl_trc_feat_write, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
}
|
||||
@ -341,7 +210,7 @@ void Curl_trc_dns(struct Curl_easy *data, const char *fmt, ...)
|
||||
if(Curl_trc_ft_is_verbose(data, &Curl_trc_feat_dns)) {
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
trc_infof(data, &Curl_trc_feat_dns, NULL, 0, fmt, ap);
|
||||
trc_infof(data, &Curl_trc_feat_dns, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
}
|
||||
@ -358,7 +227,7 @@ void Curl_trc_ftp(struct Curl_easy *data, const char *fmt, ...)
|
||||
if(Curl_trc_ft_is_verbose(data, &Curl_trc_feat_ftp)) {
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
trc_infof(data, &Curl_trc_feat_ftp, NULL, 0, fmt, ap);
|
||||
trc_infof(data, &Curl_trc_feat_ftp, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
}
|
||||
@ -376,7 +245,7 @@ void Curl_trc_smtp(struct Curl_easy *data, const char *fmt, ...)
|
||||
if(Curl_trc_ft_is_verbose(data, &Curl_trc_feat_smtp)) {
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
trc_infof(data, &Curl_trc_feat_smtp, NULL, 0, fmt, ap);
|
||||
trc_infof(data, &Curl_trc_feat_smtp, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
}
|
||||
@ -394,7 +263,7 @@ void Curl_trc_ssls(struct Curl_easy *data, const char *fmt, ...)
|
||||
if(Curl_trc_ft_is_verbose(data, &Curl_trc_feat_ssls)) {
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
trc_infof(data, &Curl_trc_feat_ssls, NULL, 0, fmt, ap);
|
||||
trc_infof(data, &Curl_trc_feat_ssls, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
}
|
||||
@ -412,7 +281,7 @@ void Curl_trc_ws(struct Curl_easy *data, const char *fmt, ...)
|
||||
if(Curl_trc_ft_is_verbose(data, &Curl_trc_feat_ws)) {
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
trc_infof(data, &Curl_trc_feat_ws, NULL, 0, fmt, ap);
|
||||
trc_infof(data, &Curl_trc_feat_ws, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
}
|
||||
@ -422,7 +291,6 @@ void Curl_trc_ws(struct Curl_easy *data, const char *fmt, ...)
|
||||
#define TRC_CT_PROTOCOL (1<<(0))
|
||||
#define TRC_CT_NETWORK (1<<(1))
|
||||
#define TRC_CT_PROXY (1<<(2))
|
||||
#define TRC_CT_INTERNALS (1<<(3))
|
||||
|
||||
struct trc_feat_def {
|
||||
struct curl_trc_feat *feat;
|
||||
@ -430,8 +298,6 @@ struct trc_feat_def {
|
||||
};
|
||||
|
||||
static struct trc_feat_def trc_feats[] = {
|
||||
{ &Curl_trc_feat_ids, TRC_CT_INTERNALS },
|
||||
{ &Curl_trc_feat_multi, TRC_CT_NETWORK },
|
||||
{ &Curl_trc_feat_read, TRC_CT_NONE },
|
||||
{ &Curl_trc_feat_write, TRC_CT_NONE },
|
||||
{ &Curl_trc_feat_dns, TRC_CT_NETWORK },
|
||||
@ -602,11 +468,6 @@ void Curl_trc_cf_infof(struct Curl_easy *data,
|
||||
|
||||
struct curl_trc_feat;
|
||||
|
||||
void Curl_trc_multi(struct Curl_easy *data, const char *fmt, ...)
|
||||
{
|
||||
(void)data; (void)fmt;
|
||||
}
|
||||
|
||||
void Curl_trc_write(struct Curl_easy *data, const char *fmt, ...)
|
||||
{
|
||||
(void)data; (void)fmt;
|
||||
|
||||
@ -82,9 +82,6 @@ void Curl_infof(struct Curl_easy *data,
|
||||
*/
|
||||
void Curl_trc_cf_infof(struct Curl_easy *data, struct Curl_cfilter *cf,
|
||||
const char *fmt, ...) CURL_PRINTF(3, 4);
|
||||
void Curl_trc_multi(struct Curl_easy *data,
|
||||
const char *fmt, ...) CURL_PRINTF(2, 3);
|
||||
const char *Curl_trc_mstate_name(int state);
|
||||
void Curl_trc_write(struct Curl_easy *data,
|
||||
const char *fmt, ...) CURL_PRINTF(2, 3);
|
||||
void Curl_trc_read(struct Curl_easy *data,
|
||||
@ -117,9 +114,6 @@ void Curl_trc_ws(struct Curl_easy *data,
|
||||
#define infof(data, ...) \
|
||||
do { if(Curl_trc_is_verbose(data)) \
|
||||
Curl_infof(data, __VA_ARGS__); } while(0)
|
||||
#define CURL_TRC_M(data, ...) \
|
||||
do { if(Curl_trc_ft_is_verbose(data, &Curl_trc_feat_multi)) \
|
||||
Curl_trc_multi(data, __VA_ARGS__); } while(0)
|
||||
#define CURL_TRC_CF(data, cf, ...) \
|
||||
do { if(Curl_trc_cf_is_verbose(cf, data)) \
|
||||
Curl_trc_cf_infof(data, cf, __VA_ARGS__); } while(0)
|
||||
@ -157,7 +151,6 @@ void Curl_trc_ws(struct Curl_easy *data,
|
||||
#else /* CURL_HAVE_C99 */
|
||||
|
||||
#define infof Curl_infof
|
||||
#define CURL_TRC_M Curl_trc_multi
|
||||
#define CURL_TRC_CF Curl_trc_cf_infof
|
||||
#define CURL_TRC_WRITE Curl_trc_write
|
||||
#define CURL_TRC_READ Curl_trc_read
|
||||
@ -178,15 +171,13 @@ void Curl_trc_ws(struct Curl_easy *data,
|
||||
|
||||
#endif /* !CURL_HAVE_C99 */
|
||||
|
||||
#ifndef CURL_DISABLE_VERBOSE_STRINGS
|
||||
/* informational messages enabled */
|
||||
|
||||
struct curl_trc_feat {
|
||||
const char *name;
|
||||
int log_level;
|
||||
};
|
||||
|
||||
#ifndef CURL_DISABLE_VERBOSE_STRINGS
|
||||
/* informational messages enabled */
|
||||
|
||||
extern struct curl_trc_feat Curl_trc_feat_multi;
|
||||
extern struct curl_trc_feat Curl_trc_feat_read;
|
||||
extern struct curl_trc_feat Curl_trc_feat_write;
|
||||
extern struct curl_trc_feat Curl_trc_feat_dns;
|
||||
@ -201,7 +192,6 @@ extern struct curl_trc_feat Curl_trc_feat_dns;
|
||||
#define Curl_trc_ft_is_verbose(data, ft) \
|
||||
(Curl_trc_is_verbose(data) && \
|
||||
(ft)->log_level >= CURL_LOG_LVL_INFO)
|
||||
#define CURL_MSTATE_NAME(s) Curl_trc_mstate_name((int)(s))
|
||||
|
||||
#else /* defined(CURL_DISABLE_VERBOSE_STRINGS) */
|
||||
/* All informational messages are not compiled in for size savings */
|
||||
@ -209,7 +199,6 @@ extern struct curl_trc_feat Curl_trc_feat_dns;
|
||||
#define Curl_trc_is_verbose(d) (FALSE)
|
||||
#define Curl_trc_cf_is_verbose(x,y) (FALSE)
|
||||
#define Curl_trc_ft_is_verbose(x,y) (FALSE)
|
||||
#define CURL_MSTATE_NAME(x) ((void)(x), "-")
|
||||
|
||||
#endif /* !defined(CURL_DISABLE_VERBOSE_STRINGS) */
|
||||
|
||||
|
||||
@ -1181,7 +1181,7 @@ CURLcode Curl_doh_is_resolved(struct Curl_easy *data,
|
||||
|
||||
if(dohp->probe[DOH_SLOT_IPV4].easy_mid < 0 &&
|
||||
dohp->probe[DOH_SLOT_IPV6].easy_mid < 0) {
|
||||
failf(data, "Could not DoH-resolve: %s", dohp->host);
|
||||
failf(data, "Could not DoH-resolve: %s", data->state.async.hostname);
|
||||
return CONN_IS_PROXIED(data->conn) ? CURLE_COULDNT_RESOLVE_PROXY :
|
||||
CURLE_COULDNT_RESOLVE_HOST;
|
||||
}
|
||||
|
||||
@ -1195,10 +1195,10 @@ CURLcode curl_easy_pause(CURL *d, int action)
|
||||
}
|
||||
|
||||
out:
|
||||
if(!result && !data->state.done && keep_changed && data->multi)
|
||||
/* pause/unpausing may result in multi event changes */
|
||||
if(Curl_multi_ev_assess_xfer(data->multi, data))
|
||||
result = CURLE_ABORTED_BY_CALLBACK;
|
||||
if(!result && !data->state.done && keep_changed)
|
||||
/* This transfer may have been moved in or out of the bundle, update the
|
||||
corresponding socket callback, if used */
|
||||
result = Curl_updatesocket(data);
|
||||
|
||||
if(recursive)
|
||||
/* this might have called a callback recursively which might have set this
|
||||
|
||||
@ -76,8 +76,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->conn->host.dispname, 0,
|
||||
data->conn->localport, FALSE);
|
||||
data->state.async.hostname, 0,
|
||||
data->state.async.port, FALSE);
|
||||
if(data->share)
|
||||
Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
|
||||
|
||||
|
||||
@ -1480,7 +1480,7 @@ CURLcode Curl_resolver_error(struct Curl_easy *data)
|
||||
}
|
||||
|
||||
failf(data, "Could not resolve %s: %s", host_or_proxy,
|
||||
data->conn->host.dispname);
|
||||
data->state.async.hostname);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
283
lib/http.c
283
lib/http.c
@ -273,28 +273,46 @@ char *Curl_checkProxyheaders(struct Curl_easy *data,
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Strip off leading and trailing whitespace from the value in the given HTTP
|
||||
* header line and return a strdup()ed copy. Returns NULL in case of
|
||||
* allocation failure or bad input. Returns an empty string if the header
|
||||
* value consists entirely of whitespace.
|
||||
*
|
||||
* If the header is provided as "name;", ending with a semicolon, it must
|
||||
* return a blank string.
|
||||
* Strip off leading and trailing whitespace from the value in the
|
||||
* given HTTP header line and return a strdupped copy. Returns NULL in
|
||||
* case of allocation failure. Returns an empty string if the header value
|
||||
* consists entirely of whitespace.
|
||||
*/
|
||||
char *Curl_copy_header_value(const char *header)
|
||||
{
|
||||
struct Curl_str out;
|
||||
const char *start;
|
||||
const char *end;
|
||||
size_t len;
|
||||
|
||||
/* find the end of the header name */
|
||||
if(!Curl_str_cspn(&header, &out, ";:") &&
|
||||
(!Curl_str_single(&header, ':') || !Curl_str_single(&header, ';'))) {
|
||||
Curl_str_untilnl(&header, &out, MAX_HTTP_RESP_HEADER_SIZE);
|
||||
Curl_str_trimblanks(&out);
|
||||
/* Find the end of the header name */
|
||||
while(*header && (*header != ':'))
|
||||
++header;
|
||||
|
||||
return Curl_memdup0(Curl_str(&out), Curl_strlen(&out));
|
||||
}
|
||||
/* bad input */
|
||||
return NULL;
|
||||
if(*header)
|
||||
/* Skip over colon */
|
||||
++header;
|
||||
|
||||
/* Find the first non-space letter */
|
||||
start = header;
|
||||
while(ISSPACE(*start))
|
||||
start++;
|
||||
|
||||
end = strchr(start, '\r');
|
||||
if(!end)
|
||||
end = strchr(start, '\n');
|
||||
if(!end)
|
||||
end = strchr(start, '\0');
|
||||
if(!end)
|
||||
return NULL;
|
||||
|
||||
/* skip all trailing space letters */
|
||||
while((end > start) && ISSPACE(*end))
|
||||
end--;
|
||||
|
||||
/* get length of the type */
|
||||
len = end - start + 1;
|
||||
|
||||
return Curl_memdup0(start, len);
|
||||
}
|
||||
|
||||
#ifndef CURL_DISABLE_HTTP_AUTH
|
||||
@ -996,8 +1014,6 @@ static CURLcode auth_bearer(struct Curl_easy *data,
|
||||
* 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.
|
||||
*
|
||||
* The 'auth' line ends with a null byte without CR or LF present.
|
||||
*/
|
||||
CURLcode Curl_http_input_auth(struct Curl_easy *data, bool proxy,
|
||||
const char *auth) /* the first non-space */
|
||||
@ -1450,8 +1466,9 @@ Curl_compareheader(const char *headerline, /* line to check */
|
||||
* The field value MAY be preceded by any amount of LWS, though a single SP
|
||||
* is preferred." */
|
||||
|
||||
const char *p;
|
||||
struct Curl_str val;
|
||||
size_t len;
|
||||
const char *start;
|
||||
const char *end;
|
||||
DEBUGASSERT(hlen);
|
||||
DEBUGASSERT(clen);
|
||||
DEBUGASSERT(header);
|
||||
@ -1461,21 +1478,31 @@ Curl_compareheader(const char *headerline, /* line to check */
|
||||
return FALSE; /* does not start with header */
|
||||
|
||||
/* pass the header */
|
||||
p = &headerline[hlen];
|
||||
start = &headerline[hlen];
|
||||
|
||||
if(Curl_str_untilnl(&p, &val, MAX_HTTP_RESP_HEADER_SIZE))
|
||||
return FALSE;
|
||||
Curl_str_trimblanks(&val);
|
||||
/* pass all whitespace */
|
||||
while(ISSPACE(*start))
|
||||
start++;
|
||||
|
||||
/* find the end of the header line */
|
||||
end = strchr(start, '\r'); /* lines end with CRLF */
|
||||
if(!end) {
|
||||
/* in case there is a non-standard compliant line here */
|
||||
end = strchr(start, '\n');
|
||||
|
||||
if(!end)
|
||||
/* hm, there is no line ending here, use the zero byte! */
|
||||
end = strchr(start, '\0');
|
||||
}
|
||||
|
||||
len = end-start; /* length of the content part of the input line */
|
||||
|
||||
/* find the content string in the rest of the line */
|
||||
if(Curl_strlen(&val) >= clen) {
|
||||
size_t len;
|
||||
p = Curl_str(&val);
|
||||
for(len = Curl_strlen(&val); len >= Curl_strlen(&val); len--, p++) {
|
||||
if(strncasecompare(p, content, clen))
|
||||
return TRUE; /* match! */
|
||||
}
|
||||
for(; len >= clen; len--, start++) {
|
||||
if(strncasecompare(start, content, clen))
|
||||
return TRUE; /* match! */
|
||||
}
|
||||
|
||||
return FALSE; /* no match */
|
||||
}
|
||||
|
||||
@ -1594,6 +1621,7 @@ CURLcode Curl_add_custom_headers(struct Curl_easy *data,
|
||||
bool is_connect, int httpversion,
|
||||
struct dynbuf *req)
|
||||
{
|
||||
char *ptr;
|
||||
struct curl_slist *h[2];
|
||||
struct curl_slist *headers;
|
||||
int numlists = 1; /* by default */
|
||||
@ -1633,81 +1661,98 @@ CURLcode Curl_add_custom_headers(struct Curl_easy *data,
|
||||
|
||||
/* loop through one or two lists */
|
||||
for(i = 0; i < numlists; i++) {
|
||||
for(headers = h[i]; headers; headers = headers->next) {
|
||||
CURLcode result = CURLE_OK;
|
||||
bool blankheader = FALSE;
|
||||
struct Curl_str name;
|
||||
const char *p = headers->data;
|
||||
const char *origp = p;
|
||||
headers = h[i];
|
||||
|
||||
/* explicitly asked to send header without content is done by a header
|
||||
that ends with a semicolon, but there must be no colon present in the
|
||||
name */
|
||||
if(!Curl_str_until(&p, &name, MAX_HTTP_RESP_HEADER_SIZE, ';') &&
|
||||
!Curl_str_single(&p, ';') &&
|
||||
!Curl_str_single(&p, '\0') &&
|
||||
!memchr(Curl_str(&name), ':', Curl_strlen(&name)))
|
||||
blankheader = TRUE;
|
||||
else {
|
||||
p = origp;
|
||||
if(!Curl_str_until(&p, &name, MAX_HTTP_RESP_HEADER_SIZE, ':') &&
|
||||
!Curl_str_single(&p, ':')) {
|
||||
struct Curl_str val;
|
||||
Curl_str_untilnl(&p, &val, MAX_HTTP_RESP_HEADER_SIZE);
|
||||
Curl_str_trimblanks(&val);
|
||||
if(!Curl_strlen(&val))
|
||||
/* no content, don't send this */
|
||||
continue;
|
||||
while(headers) {
|
||||
char *semicolonp = NULL;
|
||||
ptr = strchr(headers->data, ':');
|
||||
if(!ptr) {
|
||||
char *optr;
|
||||
/* no colon, semicolon? */
|
||||
ptr = strchr(headers->data, ';');
|
||||
if(ptr) {
|
||||
optr = ptr;
|
||||
ptr++; /* pass the semicolon */
|
||||
while(ISSPACE(*ptr))
|
||||
ptr++;
|
||||
|
||||
if(*ptr) {
|
||||
/* this may be used for something else in the future */
|
||||
optr = NULL;
|
||||
}
|
||||
else {
|
||||
if(*(--ptr) == ';') {
|
||||
/* copy the source */
|
||||
semicolonp = strdup(headers->data);
|
||||
if(!semicolonp) {
|
||||
Curl_dyn_free(req);
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
/* put a colon where the semicolon is */
|
||||
semicolonp[ptr - headers->data] = ':';
|
||||
/* point at the colon */
|
||||
optr = &semicolonp [ptr - headers->data];
|
||||
}
|
||||
}
|
||||
ptr = optr;
|
||||
}
|
||||
else
|
||||
/* no colon */
|
||||
continue;
|
||||
}
|
||||
if(ptr && (ptr != headers->data)) {
|
||||
/* we require a colon for this to be a true header */
|
||||
|
||||
/* only send this if the contents was non-blank or done special */
|
||||
ptr++; /* pass the colon */
|
||||
while(ISSPACE(*ptr))
|
||||
ptr++;
|
||||
|
||||
if(data->state.aptr.host &&
|
||||
/* a Host: header was sent already, do not pass on any custom
|
||||
Host: header as that will produce *two* in the same
|
||||
request! */
|
||||
Curl_str_casecompare(&name, "Host"))
|
||||
;
|
||||
else if(data->state.httpreq == HTTPREQ_POST_FORM &&
|
||||
/* this header (extended by formdata.c) is sent later */
|
||||
Curl_str_casecompare(&name, "Content-Type"))
|
||||
;
|
||||
else if(data->state.httpreq == HTTPREQ_POST_MIME &&
|
||||
/* this header is sent later */
|
||||
Curl_str_casecompare(&name, "Content-Type"))
|
||||
;
|
||||
else if(data->req.authneg &&
|
||||
/* while doing auth neg, do not allow the custom length since
|
||||
we will force length zero then */
|
||||
Curl_str_casecompare(&name, "Content-Length"))
|
||||
;
|
||||
else if(data->state.aptr.te &&
|
||||
/* when asking for Transfer-Encoding, do not pass on a custom
|
||||
Connection: */
|
||||
Curl_str_casecompare(&name, "Connection"))
|
||||
;
|
||||
else if((httpversion >= 20) &&
|
||||
Curl_str_casecompare(&name, "Transfer-Encoding"))
|
||||
/* HTTP/2 does not support chunked requests */
|
||||
;
|
||||
else if((Curl_str_casecompare(&name, "Authorization") ||
|
||||
Curl_str_casecompare(&name, "Cookie")) &&
|
||||
/* be careful of sending this potentially sensitive header to
|
||||
other hosts */
|
||||
!Curl_auth_allowed_to_host(data))
|
||||
;
|
||||
else if(blankheader)
|
||||
result = Curl_dyn_addf(req, "%.*s:\r\n", (int)Curl_strlen(&name),
|
||||
Curl_str(&name));
|
||||
else
|
||||
result = Curl_dyn_addf(req, "%s\r\n", origp);
|
||||
if(*ptr || semicolonp) {
|
||||
/* only send this if the contents was non-blank or done special */
|
||||
CURLcode result = CURLE_OK;
|
||||
char *compare = semicolonp ? semicolonp : headers->data;
|
||||
|
||||
if(result)
|
||||
return result;
|
||||
if(data->state.aptr.host &&
|
||||
/* a Host: header was sent already, do not pass on any custom
|
||||
Host: header as that will produce *two* in the same
|
||||
request! */
|
||||
checkprefix("Host:", compare))
|
||||
;
|
||||
else if(data->state.httpreq == HTTPREQ_POST_FORM &&
|
||||
/* this header (extended by formdata.c) is sent later */
|
||||
checkprefix("Content-Type:", compare))
|
||||
;
|
||||
else if(data->state.httpreq == HTTPREQ_POST_MIME &&
|
||||
/* this header is sent later */
|
||||
checkprefix("Content-Type:", compare))
|
||||
;
|
||||
else if(data->req.authneg &&
|
||||
/* while doing auth neg, do not allow the custom length since
|
||||
we will force length zero then */
|
||||
checkprefix("Content-Length:", compare))
|
||||
;
|
||||
else if(data->state.aptr.te &&
|
||||
/* when asking for Transfer-Encoding, do not pass on a custom
|
||||
Connection: */
|
||||
checkprefix("Connection:", compare))
|
||||
;
|
||||
else if((httpversion >= 20) &&
|
||||
checkprefix("Transfer-Encoding:", compare))
|
||||
/* HTTP/2 does not support chunked requests */
|
||||
;
|
||||
else if((checkprefix("Authorization:", compare) ||
|
||||
checkprefix("Cookie:", compare)) &&
|
||||
/* be careful of sending this potentially sensitive header to
|
||||
other hosts */
|
||||
!Curl_auth_allowed_to_host(data))
|
||||
;
|
||||
else {
|
||||
result = Curl_dyn_addf(req, "%s\r\n", compare);
|
||||
}
|
||||
if(semicolonp)
|
||||
free(semicolonp);
|
||||
if(result)
|
||||
return result;
|
||||
}
|
||||
}
|
||||
headers = headers->next;
|
||||
}
|
||||
}
|
||||
|
||||
@ -3940,22 +3985,30 @@ static CURLcode http_rw_hd(struct Curl_easy *data,
|
||||
}
|
||||
else if(data->conn->handler->protocol & CURLPROTO_RTSP) {
|
||||
const char *p = hd;
|
||||
struct Curl_str ver;
|
||||
curl_off_t status;
|
||||
/* we set the max string a little excessive to forgive some leading
|
||||
spaces */
|
||||
if(!Curl_str_until(&p, &ver, 32, ' ') &&
|
||||
!Curl_str_single(&p, ' ') &&
|
||||
!Curl_str_number(&p, &status, 999)) {
|
||||
Curl_str_trimblanks(&ver);
|
||||
if(Curl_str_cmp(&ver, "RTSP/1.0")) {
|
||||
k->httpcode = (int)status;
|
||||
fine_statusline = TRUE;
|
||||
k->httpversion = 11; /* RTSP acts like HTTP 1.1 */
|
||||
while(ISBLANK(*p))
|
||||
p++;
|
||||
if(!strncmp(p, "RTSP/", 5)) {
|
||||
p += 5;
|
||||
if(ISDIGIT(*p)) {
|
||||
p++;
|
||||
if((p[0] == '.') && ISDIGIT(p[1])) {
|
||||
if(ISBLANK(p[2])) {
|
||||
p += 3;
|
||||
if(ISDIGIT(p[0]) && ISDIGIT(p[1]) && ISDIGIT(p[2])) {
|
||||
k->httpcode = (p[0] - '0') * 100 + (p[1] - '0') * 10 +
|
||||
(p[2] - '0');
|
||||
p += 3;
|
||||
if(ISSPACE(*p)) {
|
||||
fine_statusline = TRUE;
|
||||
k->httpversion = 11; /* RTSP acts like HTTP 1.1 */
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!fine_statusline)
|
||||
return CURLE_WEIRD_SERVER_REPLY;
|
||||
}
|
||||
if(!fine_statusline)
|
||||
return CURLE_WEIRD_SERVER_REPLY;
|
||||
}
|
||||
|
||||
if(fine_statusline) {
|
||||
|
||||
668
lib/multi.c
668
lib/multi.c
@ -36,7 +36,6 @@
|
||||
#include "share.h"
|
||||
#include "psl.h"
|
||||
#include "multiif.h"
|
||||
#include "multi_ev.h"
|
||||
#include "sendf.h"
|
||||
#include "timeval.h"
|
||||
#include "http.h"
|
||||
@ -95,6 +94,8 @@
|
||||
|
||||
static void move_pending_to_connect(struct Curl_multi *multi,
|
||||
struct Curl_easy *data);
|
||||
static CURLMcode singlesocket(struct Curl_multi *multi,
|
||||
struct Curl_easy *data);
|
||||
static CURLMcode add_next_timeout(struct curltime now,
|
||||
struct Curl_multi *multi,
|
||||
struct Curl_easy *d);
|
||||
@ -103,6 +104,31 @@ static CURLMcode multi_timeout(struct Curl_multi *multi,
|
||||
long *timeout_ms);
|
||||
static void process_pending_handles(struct Curl_multi *multi);
|
||||
static void multi_xfer_bufs_free(struct Curl_multi *multi);
|
||||
static void expire_ex(struct Curl_easy *data, const struct curltime *nowp,
|
||||
timediff_t milli, expire_id id);
|
||||
|
||||
#if defined( DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
|
||||
static const char * const multi_statename[]={
|
||||
"INIT",
|
||||
"PENDING",
|
||||
"SETUP",
|
||||
"CONNECT",
|
||||
"RESOLVING",
|
||||
"CONNECTING",
|
||||
"TUNNELING",
|
||||
"PROTOCONNECT",
|
||||
"PROTOCONNECTING",
|
||||
"DO",
|
||||
"DOING",
|
||||
"DOING_MORE",
|
||||
"DID",
|
||||
"PERFORMING",
|
||||
"RATELIMITING",
|
||||
"DONE",
|
||||
"COMPLETED",
|
||||
"MSGSENT",
|
||||
};
|
||||
#endif
|
||||
|
||||
/* function pointer called once when switching TO a state */
|
||||
typedef void (*init_multistate_func)(struct Curl_easy *data);
|
||||
@ -153,18 +179,26 @@ static void mstate(struct Curl_easy *data, CURLMstate state
|
||||
NULL /* MSGSENT */
|
||||
};
|
||||
|
||||
#if defined(DEBUGBUILD) && defined(CURL_DISABLE_VERBOSE_STRINGS)
|
||||
(void) lineno;
|
||||
#endif
|
||||
|
||||
if(oldstate == state)
|
||||
/* do not bother when the new state is the same as the old state */
|
||||
return;
|
||||
|
||||
#ifdef DEBUGBUILD
|
||||
CURL_TRC_M(data, "-> [%s] (line %d)", CURL_MSTATE_NAME(state), lineno);
|
||||
#else
|
||||
CURL_TRC_M(data, "-> [%s]", CURL_MSTATE_NAME(state));
|
||||
#endif
|
||||
|
||||
data->mstate = state;
|
||||
|
||||
#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
|
||||
if(data->mstate >= MSTATE_PENDING &&
|
||||
data->mstate < MSTATE_COMPLETED) {
|
||||
infof(data,
|
||||
"STATE: %s => %s handle %p; line %d",
|
||||
multi_statename[oldstate], multi_statename[data->mstate],
|
||||
(void *)data, lineno);
|
||||
}
|
||||
#endif
|
||||
|
||||
if(state == MSTATE_COMPLETED) {
|
||||
/* changing to COMPLETED means there is one less easy handle 'alive' */
|
||||
DEBUGASSERT(data->multi->num_alive > 0);
|
||||
@ -186,6 +220,163 @@ static void mstate(struct Curl_easy *data, CURLMstate state
|
||||
#define multistate(x,y) mstate(x,y, __LINE__)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* We add one of these structs to the sockhash for each socket
|
||||
*/
|
||||
|
||||
struct Curl_sh_entry {
|
||||
struct Curl_hash transfers; /* hash of transfers using this socket */
|
||||
unsigned int action; /* what combined action READ/WRITE this socket waits
|
||||
for */
|
||||
unsigned int users; /* number of transfers using this */
|
||||
void *socketp; /* settable by users with curl_multi_assign() */
|
||||
unsigned int readers; /* this many transfers want to read */
|
||||
unsigned int writers; /* this many transfers want to write */
|
||||
};
|
||||
|
||||
/* look up a given socket in the socket hash, skip invalid sockets */
|
||||
static struct Curl_sh_entry *sh_getentry(struct Curl_hash *sh,
|
||||
curl_socket_t s)
|
||||
{
|
||||
if(s != CURL_SOCKET_BAD) {
|
||||
/* only look for proper sockets */
|
||||
return Curl_hash_pick(sh, (char *)&s, sizeof(curl_socket_t));
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#define TRHASH_SIZE 13
|
||||
|
||||
/* the given key here is a struct Curl_easy pointer */
|
||||
static size_t trhash(void *key, size_t key_length, size_t slots_num)
|
||||
{
|
||||
unsigned char bytes = ((unsigned char *)key)[key_length - 1] ^
|
||||
((unsigned char *)key)[0];
|
||||
return (bytes % slots_num);
|
||||
}
|
||||
|
||||
static size_t trhash_compare(void *k1, size_t k1_len, void *k2, size_t k2_len)
|
||||
{
|
||||
(void)k2_len;
|
||||
return !memcmp(k1, k2, k1_len);
|
||||
}
|
||||
|
||||
static void trhash_dtor(void *nada)
|
||||
{
|
||||
(void)nada;
|
||||
}
|
||||
|
||||
/*
|
||||
* The sockhash has its own separate subhash in each entry that need to be
|
||||
* safely destroyed first.
|
||||
*/
|
||||
static void sockhash_destroy(struct Curl_hash *h)
|
||||
{
|
||||
struct Curl_hash_iterator iter;
|
||||
struct Curl_hash_element *he;
|
||||
|
||||
DEBUGASSERT(h);
|
||||
Curl_hash_start_iterate(h, &iter);
|
||||
he = Curl_hash_next_element(&iter);
|
||||
while(he) {
|
||||
struct Curl_sh_entry *sh = (struct Curl_sh_entry *)he->ptr;
|
||||
Curl_hash_destroy(&sh->transfers);
|
||||
he = Curl_hash_next_element(&iter);
|
||||
}
|
||||
Curl_hash_destroy(h);
|
||||
}
|
||||
|
||||
|
||||
/* make sure this socket is present in the hash for this handle */
|
||||
static struct Curl_sh_entry *sh_addentry(struct Curl_hash *sh,
|
||||
curl_socket_t s)
|
||||
{
|
||||
struct Curl_sh_entry *there = sh_getentry(sh, s);
|
||||
struct Curl_sh_entry *check;
|
||||
|
||||
if(there) {
|
||||
/* it is present, return fine */
|
||||
return there;
|
||||
}
|
||||
|
||||
/* not present, add it */
|
||||
check = calloc(1, sizeof(struct Curl_sh_entry));
|
||||
if(!check)
|
||||
return NULL; /* major failure */
|
||||
|
||||
Curl_hash_init(&check->transfers, TRHASH_SIZE, trhash, trhash_compare,
|
||||
trhash_dtor);
|
||||
|
||||
/* make/add new hash entry */
|
||||
if(!Curl_hash_add(sh, (char *)&s, sizeof(curl_socket_t), check)) {
|
||||
Curl_hash_destroy(&check->transfers);
|
||||
free(check);
|
||||
return NULL; /* major failure */
|
||||
}
|
||||
|
||||
return check; /* things are good in sockhash land */
|
||||
}
|
||||
|
||||
|
||||
/* delete the given socket + handle from the hash */
|
||||
static void sh_delentry(struct Curl_sh_entry *entry,
|
||||
struct Curl_hash *sh, curl_socket_t s)
|
||||
{
|
||||
Curl_hash_destroy(&entry->transfers);
|
||||
|
||||
/* We remove the hash entry. This will end up in a call to
|
||||
sh_freeentry(). */
|
||||
Curl_hash_delete(sh, (char *)&s, sizeof(curl_socket_t));
|
||||
}
|
||||
|
||||
/*
|
||||
* free a sockhash entry
|
||||
*/
|
||||
static void sh_freeentry(void *freethis)
|
||||
{
|
||||
struct Curl_sh_entry *p = (struct Curl_sh_entry *) freethis;
|
||||
|
||||
free(p);
|
||||
}
|
||||
|
||||
static size_t fd_key_compare(void *k1, size_t k1_len, void *k2, size_t k2_len)
|
||||
{
|
||||
(void) k1_len; (void) k2_len;
|
||||
|
||||
return (*((curl_socket_t *) k1)) == (*((curl_socket_t *) k2));
|
||||
}
|
||||
|
||||
static size_t hash_fd(void *key, size_t key_length, size_t slots_num)
|
||||
{
|
||||
curl_socket_t fd = *((curl_socket_t *) key);
|
||||
(void) key_length;
|
||||
|
||||
return (fd % (curl_socket_t)slots_num);
|
||||
}
|
||||
|
||||
/*
|
||||
* sh_init() creates a new socket hash and returns the handle for it.
|
||||
*
|
||||
* Quote from README.multi_socket:
|
||||
*
|
||||
* "Some tests at 7000 and 9000 connections showed that the socket hash lookup
|
||||
* is somewhat of a bottle neck. Its current implementation may be a bit too
|
||||
* limiting. It simply has a fixed-size array, and on each entry in the array
|
||||
* it has a linked list with entries. The hash only checks which list to scan
|
||||
* through. The code I had used so for used a list with merely 7 slots (as
|
||||
* that is what the DNS hash uses) but with 7000 connections that would make
|
||||
* an average of 1000 nodes in each list to run through. I upped that to 97
|
||||
* slots (I believe a prime is suitable) and noticed a significant speed
|
||||
* increase. I need to reconsider the hash implementation or use a rather
|
||||
* large default value like this. At 9000 connections I was still below 10us
|
||||
* per call."
|
||||
*
|
||||
*/
|
||||
static void sh_init(struct Curl_hash *hash, size_t hashsize)
|
||||
{
|
||||
Curl_hash_init(hash, hashsize, hash_fd, fd_key_compare,
|
||||
sh_freeentry);
|
||||
}
|
||||
|
||||
/* multi->proto_hash destructor. Should never be called as elements
|
||||
* MUST be added with their own destructor */
|
||||
@ -209,7 +400,7 @@ static void multi_addmsg(struct Curl_multi *multi, struct Curl_message *msg)
|
||||
Curl_llist_append(&multi->msglist, msg, &msg->list);
|
||||
}
|
||||
|
||||
struct Curl_multi *Curl_multi_handle(size_t ev_hashsize, /* event hash */
|
||||
struct Curl_multi *Curl_multi_handle(size_t hashsize, /* socket hash */
|
||||
size_t chashsize, /* connection hash */
|
||||
size_t dnssize, /* dns hash */
|
||||
size_t sesssize) /* TLS session cache */
|
||||
@ -222,7 +413,8 @@ struct Curl_multi *Curl_multi_handle(size_t ev_hashsize, /* event hash */
|
||||
multi->magic = CURL_MULTI_HANDLE;
|
||||
|
||||
Curl_init_dnscache(&multi->hostcache, dnssize);
|
||||
Curl_multi_ev_init(multi, ev_hashsize);
|
||||
|
||||
sh_init(&multi->sockhash, hashsize);
|
||||
|
||||
Curl_hash_init(&multi->proto_hash, 23,
|
||||
Curl_hash_str, Curl_str_key_compare, ph_freeentry);
|
||||
@ -260,7 +452,7 @@ struct Curl_multi *Curl_multi_handle(size_t ev_hashsize, /* event hash */
|
||||
|
||||
error:
|
||||
|
||||
Curl_multi_ev_cleanup(multi);
|
||||
sockhash_destroy(&multi->sockhash);
|
||||
Curl_hash_destroy(&multi->proto_hash);
|
||||
Curl_hash_destroy(&multi->hostcache);
|
||||
Curl_cpool_destroy(&multi->cpool);
|
||||
@ -396,7 +588,6 @@ CURLMcode curl_multi_add_handle(CURLM *m, CURL *d)
|
||||
Curl_cpool_xfer_init(data);
|
||||
multi_warn_debug(multi, data);
|
||||
|
||||
CURL_TRC_M(data, "added, transfers=%u", multi->num_easy);
|
||||
return CURLM_OK;
|
||||
}
|
||||
|
||||
@ -430,8 +621,9 @@ static void multi_done_locked(struct connectdata *conn,
|
||||
|
||||
if(CONN_INUSE(conn)) {
|
||||
/* Stop if still used. */
|
||||
CURL_TRC_M(data, "Connection still in use %zu, no more multi_done now!",
|
||||
Curl_llist_count(&conn->easyq));
|
||||
DEBUGF(infof(data, "Connection still in use %zu, "
|
||||
"no more multi_done now!",
|
||||
Curl_llist_count(&conn->easyq)));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -468,12 +660,12 @@ static void multi_done_locked(struct connectdata *conn,
|
||||
#endif
|
||||
) || conn->bits.close
|
||||
|| (mdctx->premature && !Curl_conn_is_multiplex(conn, FIRSTSOCKET))) {
|
||||
CURL_TRC_M(data, "multi_done, not reusing connection=%"
|
||||
FMT_OFF_T ", forbid=%d"
|
||||
", close=%d, premature=%d, conn_multiplex=%d",
|
||||
conn->connection_id, data->set.reuse_forbid,
|
||||
conn->bits.close, mdctx->premature,
|
||||
Curl_conn_is_multiplex(conn, FIRSTSOCKET));
|
||||
DEBUGF(infof(data, "multi_done, not reusing connection=%"
|
||||
FMT_OFF_T ", forbid=%d"
|
||||
", close=%d, premature=%d, conn_multiplex=%d",
|
||||
conn->connection_id, data->set.reuse_forbid,
|
||||
conn->bits.close, mdctx->premature,
|
||||
Curl_conn_is_multiplex(conn, FIRSTSOCKET)));
|
||||
connclose(conn, "disconnecting");
|
||||
Curl_cpool_disconnect(data, conn, mdctx->premature);
|
||||
}
|
||||
@ -511,8 +703,14 @@ static CURLcode multi_done(struct Curl_easy *data,
|
||||
|
||||
memset(&mdctx, 0, sizeof(mdctx));
|
||||
|
||||
CURL_TRC_M(data, "multi_done: status: %d prem: %d done: %d",
|
||||
(int)status, (int)premature, data->state.done);
|
||||
#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
|
||||
DEBUGF(infof(data, "multi_done[%s]: status: %d prem: %d done: %d",
|
||||
multi_statename[data->mstate],
|
||||
(int)status, (int)premature, data->state.done));
|
||||
#else
|
||||
DEBUGF(infof(data, "multi_done: status: %d prem: %d done: %d",
|
||||
(int)status, (int)premature, data->state.done));
|
||||
#endif
|
||||
|
||||
if(data->state.done)
|
||||
/* Stop if multi_done() has already been called */
|
||||
@ -663,14 +861,18 @@ CURLMcode curl_multi_remove_handle(CURLM *m, CURL *d)
|
||||
|
||||
Curl_wildcard_dtor(&data->wildcard);
|
||||
|
||||
/* change state without using multistate(), only to make singlesocket() do
|
||||
what we want */
|
||||
data->mstate = MSTATE_COMPLETED;
|
||||
|
||||
/* This ignores the return code even in case of problems because there is
|
||||
nothing more to do about that, here */
|
||||
(void)singlesocket(multi, data); /* to let the application know what sockets
|
||||
that vanish with this handle */
|
||||
|
||||
/* Remove the association between the connection and the handle */
|
||||
Curl_detach_connection(data);
|
||||
|
||||
/* Tell event handling that this transfer is definitely going away */
|
||||
Curl_multi_ev_xfer_done(multi, data);
|
||||
|
||||
if(data->set.connect_only && !data->multi_easy) {
|
||||
/* This removes a handle that was part the multi interface that used
|
||||
CONNECT_ONLY, that connection is now left alive but since this handle
|
||||
@ -725,8 +927,6 @@ CURLMcode curl_multi_remove_handle(CURLM *m, CURL *d)
|
||||
if(rc)
|
||||
return rc;
|
||||
}
|
||||
|
||||
CURL_TRC_M(data, "removed, transfers=%u", multi->num_easy);
|
||||
return CURLM_OK;
|
||||
}
|
||||
|
||||
@ -868,15 +1068,13 @@ static int perform_getsock(struct Curl_easy *data, curl_socket_t *sock)
|
||||
|
||||
/* Initializes `poll_set` with the current socket poll actions needed
|
||||
* for transfer `data`. */
|
||||
void Curl_multi_getsock(struct Curl_easy *data,
|
||||
struct easy_pollset *ps,
|
||||
const char *caller)
|
||||
static void multi_getsock(struct Curl_easy *data,
|
||||
struct easy_pollset *ps)
|
||||
{
|
||||
bool expect_sockets = TRUE;
|
||||
|
||||
/* If the transfer has no connection, this is fine. Happens when
|
||||
called via curl_multi_remove_handle() => Curl_multi_ev_assess() =>
|
||||
Curl_multi_getsock(). */
|
||||
/* The no connection case can happen when this is called from
|
||||
curl_multi_remove_handle() => singlesocket() => multi_getsock().
|
||||
*/
|
||||
Curl_pollset_reset(data, ps);
|
||||
if(!data->conn)
|
||||
return;
|
||||
@ -900,30 +1098,30 @@ void Curl_multi_getsock(struct Curl_easy *data,
|
||||
case MSTATE_CONNECTING:
|
||||
case MSTATE_TUNNELING:
|
||||
Curl_pollset_add_socks(data, ps, connecting_getsock);
|
||||
Curl_conn_adjust_pollset(data, data->conn, ps);
|
||||
Curl_conn_adjust_pollset(data, ps);
|
||||
break;
|
||||
|
||||
case MSTATE_PROTOCONNECT:
|
||||
case MSTATE_PROTOCONNECTING:
|
||||
Curl_pollset_add_socks(data, ps, protocol_getsock);
|
||||
Curl_conn_adjust_pollset(data, data->conn, ps);
|
||||
Curl_conn_adjust_pollset(data, ps);
|
||||
break;
|
||||
|
||||
case MSTATE_DO:
|
||||
case MSTATE_DOING:
|
||||
Curl_pollset_add_socks(data, ps, doing_getsock);
|
||||
Curl_conn_adjust_pollset(data, data->conn, ps);
|
||||
Curl_conn_adjust_pollset(data, ps);
|
||||
break;
|
||||
|
||||
case MSTATE_DOING_MORE:
|
||||
Curl_pollset_add_socks(data, ps, domore_getsock);
|
||||
Curl_conn_adjust_pollset(data, data->conn, ps);
|
||||
Curl_conn_adjust_pollset(data, ps);
|
||||
break;
|
||||
|
||||
case MSTATE_DID: /* same as PERFORMING in regard to polling */
|
||||
case MSTATE_PERFORMING:
|
||||
Curl_pollset_add_socks(data, ps, perform_getsock);
|
||||
Curl_conn_adjust_pollset(data, data->conn, ps);
|
||||
Curl_conn_adjust_pollset(data, ps);
|
||||
break;
|
||||
|
||||
case MSTATE_RATELIMITING:
|
||||
@ -945,35 +1143,6 @@ void Curl_multi_getsock(struct Curl_easy *data,
|
||||
break;
|
||||
}
|
||||
|
||||
switch(ps->num) {
|
||||
case 0:
|
||||
CURL_TRC_M(data, "%s pollset[], timeouts=%zu, paused %d/%d (r/w)",
|
||||
caller, Curl_llist_count(&data->state.timeoutlist),
|
||||
Curl_creader_is_paused(data), Curl_cwriter_is_paused(data));
|
||||
break;
|
||||
case 1:
|
||||
CURL_TRC_M(data, "%s pollset[fd=%" FMT_SOCKET_T " %s%s], timeouts=%zu",
|
||||
caller, ps->sockets[0],
|
||||
(ps->actions[0] & CURL_POLL_IN) ? "IN" : "",
|
||||
(ps->actions[0] & CURL_POLL_OUT) ? "OUT" : "",
|
||||
Curl_llist_count(&data->state.timeoutlist));
|
||||
break;
|
||||
case 2:
|
||||
CURL_TRC_M(data, "%s pollset[fd=%" FMT_SOCKET_T " %s%s, "
|
||||
"fd=%" FMT_SOCKET_T " %s%s], timeouts=%zu",
|
||||
caller, ps->sockets[0],
|
||||
(ps->actions[0] & CURL_POLL_IN) ? "IN" : "",
|
||||
(ps->actions[0] & CURL_POLL_OUT) ? "OUT" : "",
|
||||
ps->sockets[1],
|
||||
(ps->actions[1] & CURL_POLL_IN) ? "IN" : "",
|
||||
(ps->actions[1] & CURL_POLL_OUT) ? "OUT" : "",
|
||||
Curl_llist_count(&data->state.timeoutlist));
|
||||
break;
|
||||
default:
|
||||
CURL_TRC_M(data, "%s pollset[fds=%u], timeouts=%zu",
|
||||
caller, ps->num, Curl_llist_count(&data->state.timeoutlist));
|
||||
break;
|
||||
}
|
||||
if(expect_sockets && !ps->num &&
|
||||
!Curl_llist_count(&data->state.timeoutlist) &&
|
||||
!Curl_cwriter_is_paused(data) && !Curl_creader_is_paused(data) &&
|
||||
@ -1008,27 +1177,26 @@ CURLMcode curl_multi_fdset(CURLM *m,
|
||||
|
||||
for(e = Curl_llist_head(&multi->process); e; e = Curl_node_next(e)) {
|
||||
struct Curl_easy *data = Curl_node_elem(e);
|
||||
struct easy_pollset ps;
|
||||
|
||||
Curl_multi_getsock(data, &ps, "curl_multi_fdset");
|
||||
multi_getsock(data, &data->last_poll);
|
||||
|
||||
for(i = 0; i < ps.num; i++) {
|
||||
if(!FDSET_SOCK(ps.sockets[i]))
|
||||
for(i = 0; i < data->last_poll.num; i++) {
|
||||
if(!FDSET_SOCK(data->last_poll.sockets[i]))
|
||||
/* pretend it does not exist */
|
||||
continue;
|
||||
#if defined(__DJGPP__)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Warith-conversion"
|
||||
#endif
|
||||
if(ps.actions[i] & CURL_POLL_IN)
|
||||
FD_SET(ps.sockets[i], read_fd_set);
|
||||
if(ps.actions[i] & CURL_POLL_OUT)
|
||||
FD_SET(ps.sockets[i], write_fd_set);
|
||||
if(data->last_poll.actions[i] & CURL_POLL_IN)
|
||||
FD_SET(data->last_poll.sockets[i], read_fd_set);
|
||||
if(data->last_poll.actions[i] & CURL_POLL_OUT)
|
||||
FD_SET(data->last_poll.sockets[i], write_fd_set);
|
||||
#if defined(__DJGPP__)
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
if((int)ps.sockets[i] > this_max_fd)
|
||||
this_max_fd = (int)ps.sockets[i];
|
||||
if((int)data->last_poll.sockets[i] > this_max_fd)
|
||||
this_max_fd = (int)data->last_poll.sockets[i];
|
||||
}
|
||||
}
|
||||
|
||||
@ -1062,10 +1230,8 @@ CURLMcode curl_multi_waitfds(CURLM *m,
|
||||
Curl_waitfds_init(&cwfds, ufds, size);
|
||||
for(e = Curl_llist_head(&multi->process); e; e = Curl_node_next(e)) {
|
||||
struct Curl_easy *data = Curl_node_elem(e);
|
||||
struct easy_pollset ps;
|
||||
|
||||
Curl_multi_getsock(data, &ps, "curl_multi_waitfds");
|
||||
need += Curl_waitfds_add_ps(&cwfds, &ps);
|
||||
multi_getsock(data, &data->last_poll);
|
||||
need += Curl_waitfds_add_ps(&cwfds, &data->last_poll);
|
||||
}
|
||||
|
||||
need += Curl_cpool_add_waitfds(&multi->cpool, &cwfds);
|
||||
@ -1137,10 +1303,9 @@ static CURLMcode multi_wait(struct Curl_multi *multi,
|
||||
/* Add the curl handles to our pollfds first */
|
||||
for(e = Curl_llist_head(&multi->process); e; e = Curl_node_next(e)) {
|
||||
struct Curl_easy *data = Curl_node_elem(e);
|
||||
struct easy_pollset ps;
|
||||
|
||||
Curl_multi_getsock(data, &ps, "multi_wait");
|
||||
if(Curl_pollfds_add_ps(&cpfds, &ps)) {
|
||||
multi_getsock(data, &data->last_poll);
|
||||
if(Curl_pollfds_add_ps(&cpfds, &data->last_poll)) {
|
||||
result = CURLM_OUT_OF_MEMORY;
|
||||
goto out;
|
||||
}
|
||||
@ -1275,14 +1440,23 @@ static CURLMcode multi_wait(struct Curl_multi *multi,
|
||||
#ifdef USE_WINSOCK
|
||||
/* Count up all our own sockets that had activity,
|
||||
and remove them from the event. */
|
||||
for(i = 0; i < curl_nfds; ++i) {
|
||||
wsa_events.lNetworkEvents = 0;
|
||||
if(WSAEnumNetworkEvents(cpfds.pfds[i].fd, NULL, &wsa_events) == 0) {
|
||||
if(ret && !pollrc && wsa_events.lNetworkEvents)
|
||||
retcode++;
|
||||
if(curl_nfds) {
|
||||
for(e = Curl_llist_head(&multi->process); e && !result;
|
||||
e = Curl_node_next(e)) {
|
||||
struct Curl_easy *data = Curl_node_elem(e);
|
||||
|
||||
for(i = 0; i < data->last_poll.num; i++) {
|
||||
wsa_events.lNetworkEvents = 0;
|
||||
if(WSAEnumNetworkEvents(data->last_poll.sockets[i], NULL,
|
||||
&wsa_events) == 0) {
|
||||
if(ret && !pollrc && wsa_events.lNetworkEvents)
|
||||
retcode++;
|
||||
}
|
||||
WSAEventSelect(data->last_poll.sockets[i], multi->wsa_event, 0);
|
||||
}
|
||||
}
|
||||
WSAEventSelect(cpfds.pfds[i].fd, multi->wsa_event, 0);
|
||||
}
|
||||
|
||||
WSAResetEvent(multi->wsa_event);
|
||||
#else
|
||||
#ifdef ENABLE_WAKEUP
|
||||
@ -2072,7 +2246,7 @@ static CURLMcode state_resolving(struct Curl_multi *multi,
|
||||
socket(s) will again be used further down. If the name has not yet been
|
||||
resolved, it is likely that new sockets have been opened in an attempt to
|
||||
contact another resolver. */
|
||||
rc = Curl_multi_ev_assess_xfer(multi, data);
|
||||
rc = singlesocket(multi, data);
|
||||
if(rc)
|
||||
return rc;
|
||||
|
||||
@ -2191,7 +2365,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
||||
rc = CURLM_OK;
|
||||
|
||||
if(multi_ischanged(multi, TRUE)) {
|
||||
CURL_TRC_M(data, "multi changed, check CONNECT_PEND queue");
|
||||
DEBUGF(infof(data, "multi changed, check CONNECT_PEND queue"));
|
||||
process_pending_handles(multi); /* multiplexed */
|
||||
}
|
||||
|
||||
@ -2557,7 +2731,6 @@ CURLMcode curl_multi_perform(CURLM *m, int *running_handles)
|
||||
struct Curl_llist_node *e;
|
||||
struct Curl_llist_node *n = NULL;
|
||||
struct Curl_multi *multi = m;
|
||||
bool first = TRUE;
|
||||
SIGPIPE_VARIABLE(pipe_st);
|
||||
|
||||
if(!GOOD_MULTI_HANDLE(multi))
|
||||
@ -2572,16 +2745,12 @@ CURLMcode curl_multi_perform(CURLM *m, int *running_handles)
|
||||
CURLMcode result;
|
||||
/* Do the loop and only alter the signal ignore state if the next handle
|
||||
has a different NO_SIGNAL state than the previous */
|
||||
if(first) {
|
||||
CURL_TRC_M(data, "multi_perform(running=%u)", multi->num_alive);
|
||||
first = FALSE;
|
||||
}
|
||||
|
||||
/* the current node might be unlinked in multi_runsingle(), get the next
|
||||
pointer now */
|
||||
n = Curl_node_next(e);
|
||||
|
||||
if(data && data != multi->cpool.idata) {
|
||||
if(data != multi->cpool.idata) {
|
||||
/* connection pool handle is processed below */
|
||||
sigpipe_apply(data, &pipe_st);
|
||||
result = multi_runsingle(multi, &now, data);
|
||||
@ -2591,7 +2760,7 @@ CURLMcode curl_multi_perform(CURLM *m, int *running_handles)
|
||||
}
|
||||
|
||||
sigpipe_apply(multi->cpool.idata, &pipe_st);
|
||||
Curl_cpool_multi_perform(multi, CURL_SOCKET_TIMEOUT);
|
||||
Curl_cpool_multi_perform(multi);
|
||||
sigpipe_restore(&pipe_st);
|
||||
|
||||
if(multi_ischanged(m, TRUE))
|
||||
@ -2693,7 +2862,7 @@ CURLMcode curl_multi_cleanup(CURLM *m)
|
||||
|
||||
multi->magic = 0; /* not good anymore */
|
||||
|
||||
Curl_multi_ev_cleanup(multi);
|
||||
sockhash_destroy(&multi->sockhash);
|
||||
Curl_hash_destroy(&multi->proto_hash);
|
||||
Curl_hash_destroy(&multi->hostcache);
|
||||
Curl_psl_destroy(&multi->psl);
|
||||
@ -2756,14 +2925,233 @@ CURLMsg *curl_multi_info_read(CURLM *m, int *msgs_in_queue)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* singlesocket() checks what sockets we deal with and their "action state"
|
||||
* and if we have a different state in any of those sockets from last time we
|
||||
* call the callback accordingly.
|
||||
*/
|
||||
static CURLMcode singlesocket(struct Curl_multi *multi,
|
||||
struct Curl_easy *data)
|
||||
{
|
||||
struct easy_pollset cur_poll;
|
||||
CURLMcode mresult;
|
||||
|
||||
void Curl_multi_will_close(struct Curl_easy *data, curl_socket_t s)
|
||||
/* Fill in the 'current' struct with the state as it is now: what sockets to
|
||||
supervise and for what actions */
|
||||
multi_getsock(data, &cur_poll);
|
||||
mresult = Curl_multi_pollset_ev(multi, data, &cur_poll, &data->last_poll);
|
||||
|
||||
if(!mresult) /* Remember for next time */
|
||||
memcpy(&data->last_poll, &cur_poll, sizeof(cur_poll));
|
||||
return mresult;
|
||||
}
|
||||
|
||||
CURLMcode Curl_multi_pollset_ev(struct Curl_multi *multi,
|
||||
struct Curl_easy *data,
|
||||
struct easy_pollset *ps,
|
||||
struct easy_pollset *last_ps)
|
||||
{
|
||||
unsigned int i;
|
||||
struct Curl_sh_entry *entry;
|
||||
curl_socket_t s;
|
||||
int rc;
|
||||
|
||||
/* 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 < ps->num; i++) {
|
||||
unsigned char cur_action = ps->actions[i];
|
||||
unsigned char last_action = 0;
|
||||
int comboaction;
|
||||
|
||||
s = ps->sockets[i];
|
||||
|
||||
/* get it from the hash */
|
||||
entry = sh_getentry(&multi->sockhash, s);
|
||||
if(entry) {
|
||||
/* check if new for this transfer */
|
||||
unsigned int j;
|
||||
for(j = 0; j < last_ps->num; j++) {
|
||||
if(s == last_ps->sockets[j]) {
|
||||
last_action = last_ps->actions[j];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* this is a socket we did not have before, add it to the hash! */
|
||||
entry = sh_addentry(&multi->sockhash, s);
|
||||
if(!entry)
|
||||
/* fatal */
|
||||
return CURLM_OUT_OF_MEMORY;
|
||||
}
|
||||
if(last_action && (last_action != cur_action)) {
|
||||
/* Socket was used already, but different action now */
|
||||
if(last_action & CURL_POLL_IN) {
|
||||
DEBUGASSERT(entry->readers);
|
||||
entry->readers--;
|
||||
}
|
||||
if(last_action & CURL_POLL_OUT) {
|
||||
DEBUGASSERT(entry->writers);
|
||||
entry->writers--;
|
||||
}
|
||||
if(cur_action & CURL_POLL_IN) {
|
||||
entry->readers++;
|
||||
}
|
||||
if(cur_action & CURL_POLL_OUT)
|
||||
entry->writers++;
|
||||
}
|
||||
else if(!last_action &&
|
||||
!Curl_hash_pick(&entry->transfers, (char *)&data, /* hash key */
|
||||
sizeof(struct Curl_easy *))) {
|
||||
DEBUGASSERT(entry->users < 100000); /* detect weird values */
|
||||
/* a new transfer using this socket */
|
||||
entry->users++;
|
||||
if(cur_action & CURL_POLL_IN)
|
||||
entry->readers++;
|
||||
if(cur_action & CURL_POLL_OUT)
|
||||
entry->writers++;
|
||||
/* add 'data' to the transfer hash on this socket! */
|
||||
if(!Curl_hash_add(&entry->transfers, (char *)&data, /* hash key */
|
||||
sizeof(struct Curl_easy *), data)) {
|
||||
Curl_hash_destroy(&entry->transfers);
|
||||
return CURLM_OUT_OF_MEMORY;
|
||||
}
|
||||
}
|
||||
|
||||
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(last_action && ((int)entry->action == comboaction))
|
||||
/* same, continue */
|
||||
continue;
|
||||
|
||||
if(multi->socket_cb) {
|
||||
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;
|
||||
return CURLM_ABORTED_BY_CALLBACK;
|
||||
}
|
||||
}
|
||||
|
||||
/* store the current action state */
|
||||
entry->action = (unsigned int)comboaction;
|
||||
}
|
||||
|
||||
/* Check for last_poll.sockets that no longer appear in ps->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 < last_ps->num; i++) {
|
||||
unsigned int j;
|
||||
bool stillused = FALSE;
|
||||
s = last_ps->sockets[i];
|
||||
for(j = 0; j < ps->num; j++) {
|
||||
if(s == ps->sockets[j]) {
|
||||
/* this is still supervised */
|
||||
stillused = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(stillused)
|
||||
continue;
|
||||
|
||||
entry = sh_getentry(&multi->sockhash, s);
|
||||
/* if this is NULL here, the socket has been closed and notified so
|
||||
already by Curl_multi_closed() */
|
||||
if(entry) {
|
||||
unsigned char oldactions = last_ps->actions[i];
|
||||
/* this socket has been removed. Decrease user count */
|
||||
DEBUGASSERT(entry->users);
|
||||
entry->users--;
|
||||
if(oldactions & CURL_POLL_OUT)
|
||||
entry->writers--;
|
||||
if(oldactions & CURL_POLL_IN)
|
||||
entry->readers--;
|
||||
if(!entry->users) {
|
||||
bool dead = FALSE;
|
||||
if(multi->socket_cb) {
|
||||
set_in_callback(multi, TRUE);
|
||||
rc = multi->socket_cb(data, s, CURL_POLL_REMOVE,
|
||||
multi->socket_userp, entry->socketp);
|
||||
set_in_callback(multi, FALSE);
|
||||
if(rc == -1)
|
||||
dead = TRUE;
|
||||
}
|
||||
sh_delentry(entry, &multi->sockhash, s);
|
||||
if(dead) {
|
||||
multi->dead = TRUE;
|
||||
return CURLM_ABORTED_BY_CALLBACK;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* still users, but remove this handle as a user of this socket */
|
||||
if(Curl_hash_delete(&entry->transfers, (char *)&data,
|
||||
sizeof(struct Curl_easy *))) {
|
||||
DEBUGASSERT(NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
} /* for loop over num */
|
||||
|
||||
return CURLM_OK;
|
||||
}
|
||||
|
||||
CURLcode Curl_updatesocket(struct Curl_easy *data)
|
||||
{
|
||||
if(singlesocket(data->multi, data))
|
||||
return CURLE_ABORTED_BY_CALLBACK;
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Curl_multi_closed()
|
||||
*
|
||||
* Used by the connect code to tell the multi_socket code that one of the
|
||||
* sockets we were using is about to be closed. This function will then
|
||||
* remove it from the sockethash for this handle to make the multi_socket API
|
||||
* behave properly, especially for the case when libcurl will create another
|
||||
* socket again and it gets the same file descriptor number.
|
||||
*/
|
||||
|
||||
void Curl_multi_closed(struct Curl_easy *data, curl_socket_t s)
|
||||
{
|
||||
if(data) {
|
||||
/* if there is still an easy handle associated with this connection */
|
||||
struct Curl_multi *multi = data->multi;
|
||||
DEBUGF(infof(data, "Curl_multi_closed, fd=%" FMT_SOCKET_T
|
||||
" multi is %p", s, (void *)multi));
|
||||
if(multi) {
|
||||
CURL_TRC_M(data, "Curl_multi_will_close fd=%" FMT_SOCKET_T, s);
|
||||
Curl_multi_ev_socket_done(multi, data, s);
|
||||
/* this is set if this connection is part of a handle that is added to
|
||||
a multi handle, and only then this is necessary */
|
||||
struct Curl_sh_entry *entry = sh_getentry(&multi->sockhash, s);
|
||||
|
||||
DEBUGF(infof(data, "Curl_multi_closed, fd=%" FMT_SOCKET_T
|
||||
" entry is %p", s, (void *)entry));
|
||||
if(entry) {
|
||||
int rc = 0;
|
||||
if(multi->socket_cb) {
|
||||
set_in_callback(multi, TRUE);
|
||||
rc = multi->socket_cb(data, s, CURL_POLL_REMOVE,
|
||||
multi->socket_userp, entry->socketp);
|
||||
set_in_callback(multi, FALSE);
|
||||
}
|
||||
|
||||
/* now remove it from the socket hash */
|
||||
sh_delentry(entry, &multi->sockhash, s);
|
||||
if(rc == -1)
|
||||
/* This just marks the multi handle as "dead" without returning an
|
||||
error code primarily because this function is used from many
|
||||
places where propagating an error back is tricky. */
|
||||
multi->dead = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2865,8 +3253,9 @@ static CURLMcode multi_run_expired(struct multi_run_ctx *mrc)
|
||||
result = multi_runsingle(multi, &mrc->now, data);
|
||||
|
||||
if(CURLM_OK >= result) {
|
||||
/* reassess event handling of data */
|
||||
result = Curl_multi_ev_assess_xfer(multi, data);
|
||||
/* get the socket(s) and check if the state has been changed since
|
||||
last */
|
||||
result = singlesocket(multi, data);
|
||||
if(result)
|
||||
goto out;
|
||||
}
|
||||
@ -2882,6 +3271,7 @@ static CURLMcode multi_socket(struct Curl_multi *multi,
|
||||
int *running_handles)
|
||||
{
|
||||
CURLMcode result = CURLM_OK;
|
||||
struct Curl_easy *data = NULL;
|
||||
struct multi_run_ctx mrc;
|
||||
|
||||
(void)ev_bitmask;
|
||||
@ -2891,19 +3281,56 @@ static CURLMcode multi_socket(struct Curl_multi *multi,
|
||||
sigpipe_init(&mrc.pipe_st);
|
||||
|
||||
if(checkall) {
|
||||
struct Curl_llist_node *e;
|
||||
/* *perform() deals with running_handles on its own */
|
||||
result = curl_multi_perform(multi, running_handles);
|
||||
|
||||
/* walk through each easy handle and do the socket state change magic
|
||||
and callbacks */
|
||||
if(result != CURLM_BAD_HANDLE) {
|
||||
/* Reassess event status of all active transfers */
|
||||
result = Curl_multi_ev_assess_xfer_list(multi, &multi->process);
|
||||
for(e = Curl_llist_head(&multi->process); e && !result;
|
||||
e = Curl_node_next(e)) {
|
||||
result = singlesocket(multi, Curl_node_elem(e));
|
||||
}
|
||||
}
|
||||
mrc.run_cpool = TRUE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if(s != CURL_SOCKET_TIMEOUT) {
|
||||
Curl_multi_ev_expire_xfers(multi, s, &mrc.now, &mrc.run_cpool);
|
||||
struct Curl_sh_entry *entry = sh_getentry(&multi->sockhash, s);
|
||||
|
||||
if(!entry) {
|
||||
/* Unmatched socket, we cannot act on it but we ignore this fact. In
|
||||
real-world tests it has been proved that libevent can in fact give
|
||||
the application actions even though the socket was just previously
|
||||
asked to get removed, so thus we better survive stray socket actions
|
||||
and just move on. */
|
||||
/* The socket might come from a connection that is being shut down
|
||||
* by the multi's connection pool. */
|
||||
Curl_cpool_multi_socket(multi, s, ev_bitmask);
|
||||
}
|
||||
else {
|
||||
struct Curl_hash_iterator iter;
|
||||
struct Curl_hash_element *he;
|
||||
|
||||
/* the socket can be shared by many transfers, iterate */
|
||||
Curl_hash_start_iterate(&entry->transfers, &iter);
|
||||
for(he = Curl_hash_next_element(&iter); he;
|
||||
he = Curl_hash_next_element(&iter)) {
|
||||
data = (struct Curl_easy *)he->ptr;
|
||||
DEBUGASSERT(data);
|
||||
DEBUGASSERT(data->magic == CURLEASY_MAGIC_NUMBER);
|
||||
|
||||
if(data == multi->cpool.idata)
|
||||
mrc.run_cpool = TRUE;
|
||||
else {
|
||||
/* Expire with out current now, so we will get it below when
|
||||
* asking the splaytree for expired transfers. */
|
||||
expire_ex(data, &mrc.now, 0, EXPIRE_RUN_NOW);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* Asked to run due to time-out. Clear the 'last_expire_ts' variable to
|
||||
@ -2912,7 +3339,6 @@ static CURLMcode multi_socket(struct Curl_multi *multi,
|
||||
handles the case when the application asks libcurl to run the timeout
|
||||
prematurely. */
|
||||
memset(&multi->last_expire_ts, 0, sizeof(multi->last_expire_ts));
|
||||
mrc.run_cpool = TRUE;
|
||||
}
|
||||
|
||||
result = multi_run_expired(&mrc);
|
||||
@ -2932,7 +3358,7 @@ static CURLMcode multi_socket(struct Curl_multi *multi,
|
||||
out:
|
||||
if(mrc.run_cpool) {
|
||||
sigpipe_apply(multi->cpool.idata, &mrc.pipe_st);
|
||||
Curl_cpool_multi_perform(multi, s);
|
||||
Curl_cpool_multi_perform(multi);
|
||||
}
|
||||
sigpipe_restore(&mrc.pipe_st);
|
||||
|
||||
@ -3249,9 +3675,9 @@ multi_addtimeout(struct Curl_easy *data,
|
||||
return CURLM_OK;
|
||||
}
|
||||
|
||||
void Curl_expire_ex(struct Curl_easy *data,
|
||||
const struct curltime *nowp,
|
||||
timediff_t milli, expire_id id)
|
||||
static void expire_ex(struct Curl_easy *data,
|
||||
const struct curltime *nowp,
|
||||
timediff_t milli, expire_id id)
|
||||
{
|
||||
struct Curl_multi *multi = data->multi;
|
||||
struct curltime *curr_expire = &data->state.expiretime;
|
||||
@ -3323,7 +3749,7 @@ void Curl_expire_ex(struct Curl_easy *data,
|
||||
void Curl_expire(struct Curl_easy *data, timediff_t milli, expire_id id)
|
||||
{
|
||||
struct curltime now = Curl_now();
|
||||
Curl_expire_ex(data, &now, milli, id);
|
||||
expire_ex(data, &now, milli, id);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -3367,7 +3793,9 @@ bool Curl_expire_clear(struct Curl_easy *data)
|
||||
/* clear the timeout list too */
|
||||
Curl_llist_destroy(list, NULL);
|
||||
|
||||
CURL_TRC_M(data, "Expire cleared");
|
||||
#ifdef DEBUGBUILD
|
||||
infof(data, "Expire cleared");
|
||||
#endif
|
||||
nowp->tv_sec = 0;
|
||||
nowp->tv_usec = 0;
|
||||
return TRUE;
|
||||
@ -3378,11 +3806,19 @@ bool Curl_expire_clear(struct Curl_easy *data)
|
||||
CURLMcode curl_multi_assign(CURLM *m, curl_socket_t s,
|
||||
void *hashp)
|
||||
{
|
||||
struct Curl_sh_entry *there = NULL;
|
||||
struct Curl_multi *multi = m;
|
||||
if(!GOOD_MULTI_HANDLE(multi))
|
||||
return CURLM_BAD_HANDLE;
|
||||
|
||||
return Curl_multi_ev_assign(multi, s, hashp);
|
||||
there = sh_getentry(&multi->sockhash, s);
|
||||
|
||||
if(!there)
|
||||
return CURLM_BAD_SOCKET;
|
||||
|
||||
there->socketp = hashp;
|
||||
|
||||
return CURLM_OK;
|
||||
}
|
||||
|
||||
static void move_pending_to_connect(struct Curl_multi *multi,
|
||||
|
||||
610
lib/multi_ev.c
610
lib/multi_ev.c
@ -1,610 +0,0 @@
|
||||
/***************************************************************************
|
||||
* _ _ ____ _
|
||||
* Project ___| | | | _ \| |
|
||||
* / __| | | | |_) | |
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
* are also available at https://curl.se/docs/copyright.html.
|
||||
*
|
||||
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||
* copies of the Software, and permit persons to whom the Software is
|
||||
* furnished to do so, under the terms of the COPYING file.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
* SPDX-License-Identifier: curl
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
#include "curl_setup.h"
|
||||
|
||||
#include <curl/curl.h>
|
||||
|
||||
#include "urldata.h"
|
||||
#include "cfilters.h"
|
||||
#include "curl_trc.h"
|
||||
#include "multiif.h"
|
||||
#include "timeval.h"
|
||||
#include "multi_ev.h"
|
||||
#include "select.h"
|
||||
#include "warnless.h"
|
||||
#include "multihandle.h"
|
||||
#include "socks.h"
|
||||
/* The last 3 #include files should be in this order */
|
||||
#include "curl_printf.h"
|
||||
#include "curl_memory.h"
|
||||
#include "memdebug.h"
|
||||
|
||||
|
||||
static void mev_in_callback(struct Curl_multi *multi, bool value)
|
||||
{
|
||||
multi->in_callback = value;
|
||||
}
|
||||
|
||||
#define CURL_MEV_XFER_HASH_SIZE 13
|
||||
#define CURL_MEV_CONN_HASH_SIZE 3
|
||||
|
||||
/* Information about a socket for which we inform the libcurl application
|
||||
* what to supervise (CURL_POLL_IN/CURL_POLL_OUT/CURL_POLL_REMOVE)
|
||||
*/
|
||||
struct mev_sh_entry {
|
||||
struct Curl_hash xfers; /* hash of transfers using this socket */
|
||||
struct Curl_hash conns; /* hash of connections using this socket */
|
||||
void *user_data; /* libcurl app data via curl_multi_assign() */
|
||||
unsigned int action; /* CURL_POLL_IN/CURL_POLL_OUT we last told the
|
||||
* libcurl application to watch out for */
|
||||
unsigned int readers; /* this many transfers want to read */
|
||||
unsigned int writers; /* this many transfers want to write */
|
||||
};
|
||||
|
||||
static size_t mev_sh_entry_hash(void *key, size_t key_length, size_t slots_num)
|
||||
{
|
||||
curl_socket_t fd = *((curl_socket_t *) key);
|
||||
(void) key_length;
|
||||
return (fd % (curl_socket_t)slots_num);
|
||||
}
|
||||
|
||||
static size_t mev_sh_entry_compare(void *k1, size_t k1_len,
|
||||
void *k2, size_t k2_len)
|
||||
{
|
||||
(void) k1_len; (void) k2_len;
|
||||
return (*((curl_socket_t *) k1)) == (*((curl_socket_t *) k2));
|
||||
}
|
||||
|
||||
/* sockhash entry destructor callback */
|
||||
static void mev_sh_entry_dtor(void *freethis)
|
||||
{
|
||||
struct mev_sh_entry *entry = (struct mev_sh_entry *)freethis;
|
||||
Curl_hash_destroy(&entry->xfers);
|
||||
Curl_hash_destroy(&entry->conns);
|
||||
free(entry);
|
||||
}
|
||||
|
||||
/* look up a given socket in the socket hash, skip invalid sockets */
|
||||
static struct mev_sh_entry *
|
||||
mev_sh_entry_get(struct Curl_hash *sh, curl_socket_t s)
|
||||
{
|
||||
if(s != CURL_SOCKET_BAD) {
|
||||
/* only look for proper sockets */
|
||||
return Curl_hash_pick(sh, (char *)&s, sizeof(curl_socket_t));
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void mev_nop_dtor(void *e)
|
||||
{
|
||||
(void)e; /* does nothing */
|
||||
}
|
||||
|
||||
/* make sure this socket is present in the hash for this handle */
|
||||
static struct mev_sh_entry *
|
||||
mev_sh_entry_add(struct Curl_hash *sh, curl_socket_t s)
|
||||
{
|
||||
struct mev_sh_entry *there = mev_sh_entry_get(sh, s);
|
||||
struct mev_sh_entry *check;
|
||||
|
||||
if(there) {
|
||||
/* it is present, return fine */
|
||||
return there;
|
||||
}
|
||||
|
||||
/* not present, add it */
|
||||
check = calloc(1, sizeof(struct mev_sh_entry));
|
||||
if(!check)
|
||||
return NULL; /* major failure */
|
||||
|
||||
Curl_hash_offt_init(&check->xfers, CURL_MEV_XFER_HASH_SIZE, mev_nop_dtor);
|
||||
Curl_hash_offt_init(&check->conns, CURL_MEV_CONN_HASH_SIZE, mev_nop_dtor);
|
||||
|
||||
/* make/add new hash entry */
|
||||
if(!Curl_hash_add(sh, (char *)&s, sizeof(curl_socket_t), check)) {
|
||||
mev_sh_entry_dtor(check);
|
||||
return NULL; /* major failure */
|
||||
}
|
||||
|
||||
return check; /* things are good in sockhash land */
|
||||
}
|
||||
|
||||
/* delete the given socket entry from the hash */
|
||||
static void mev_sh_entry_kill(struct Curl_multi *multi, curl_socket_t s)
|
||||
{
|
||||
Curl_hash_delete(&multi->ev.sh_entries, (char *)&s, sizeof(curl_socket_t));
|
||||
}
|
||||
|
||||
static size_t mev_sh_entry_user_count(struct mev_sh_entry *e)
|
||||
{
|
||||
return Curl_hash_count(&e->xfers) + Curl_hash_count(&e->conns);
|
||||
}
|
||||
|
||||
static bool mev_sh_entry_xfer_known(struct mev_sh_entry *e,
|
||||
struct Curl_easy *data)
|
||||
{
|
||||
return !!Curl_hash_offt_get(&e->xfers, data->id);
|
||||
}
|
||||
|
||||
static bool mev_sh_entry_conn_known(struct mev_sh_entry *e,
|
||||
struct connectdata *conn)
|
||||
{
|
||||
return !!Curl_hash_offt_get(&e->conns, conn->connection_id);
|
||||
}
|
||||
|
||||
static bool mev_sh_entry_xfer_add(struct mev_sh_entry *e,
|
||||
struct Curl_easy *data)
|
||||
{
|
||||
/* detect weird values */
|
||||
DEBUGASSERT(mev_sh_entry_user_count(e) < 100000);
|
||||
return !!Curl_hash_offt_set(&e->xfers, data->id, data);
|
||||
}
|
||||
|
||||
static bool mev_sh_entry_conn_add(struct mev_sh_entry *e,
|
||||
struct connectdata *conn)
|
||||
{
|
||||
/* detect weird values */
|
||||
DEBUGASSERT(mev_sh_entry_user_count(e) < 100000);
|
||||
return !!Curl_hash_offt_set(&e->conns, conn->connection_id, conn);
|
||||
}
|
||||
|
||||
|
||||
static bool mev_sh_entry_xfer_remove(struct mev_sh_entry *e,
|
||||
struct Curl_easy *data)
|
||||
{
|
||||
return !Curl_hash_offt_remove(&e->xfers, data->id);
|
||||
}
|
||||
|
||||
/* Purge any information about socket `s`.
|
||||
* Let the socket callback know as well when necessary */
|
||||
static CURLMcode mev_forget_socket(struct Curl_multi *multi,
|
||||
struct Curl_easy *data,
|
||||
curl_socket_t s,
|
||||
const char *cause)
|
||||
{
|
||||
struct mev_sh_entry *entry = mev_sh_entry_get(&multi->ev.sh_entries, s);
|
||||
int rc = 0;
|
||||
|
||||
if(!entry) /* we never knew or already forgot about this socket */
|
||||
return CURLM_OK;
|
||||
|
||||
/* We managed this socket before, tell the socket callback to forget it. */
|
||||
if(multi->socket_cb) {
|
||||
CURL_TRC_M(data, "ev %s, call(fd=%" FMT_SOCKET_T ", ev=REMOVE)",
|
||||
cause, s);
|
||||
mev_in_callback(multi, TRUE);
|
||||
rc = multi->socket_cb(data, s, CURL_POLL_REMOVE,
|
||||
multi->socket_userp, entry->user_data);
|
||||
mev_in_callback(multi, FALSE);
|
||||
}
|
||||
|
||||
mev_sh_entry_kill(multi, s);
|
||||
if(rc == -1) {
|
||||
multi->dead = TRUE;
|
||||
return CURLM_ABORTED_BY_CALLBACK;
|
||||
}
|
||||
return CURLM_OK;
|
||||
}
|
||||
|
||||
static CURLMcode mev_sh_entry_update(struct Curl_multi *multi,
|
||||
struct Curl_easy *data,
|
||||
struct mev_sh_entry *entry,
|
||||
curl_socket_t s,
|
||||
unsigned char last_action,
|
||||
unsigned char cur_action)
|
||||
{
|
||||
int rc, comboaction;
|
||||
|
||||
/* we should only be called when the callback exists */
|
||||
DEBUGASSERT(multi->socket_cb);
|
||||
if(!multi->socket_cb)
|
||||
return CURLM_OK;
|
||||
|
||||
/* Transfer `data` goes from `last_action` to `cur_action` on socket `s`
|
||||
* with `multi->ev.sh_entries` entry `entry`. Update `entry` and trigger
|
||||
* `multi->socket_cb` on change, if the callback is set. */
|
||||
if(last_action == cur_action) /* nothing from `data` changed */
|
||||
return CURLM_OK;
|
||||
|
||||
if(last_action & CURL_POLL_IN) {
|
||||
DEBUGASSERT(entry->readers);
|
||||
if(!(cur_action & CURL_POLL_IN))
|
||||
entry->readers--;
|
||||
}
|
||||
else if(cur_action & CURL_POLL_IN)
|
||||
entry->readers++;
|
||||
|
||||
if(last_action & CURL_POLL_OUT) {
|
||||
DEBUGASSERT(entry->writers);
|
||||
if(!(cur_action & CURL_POLL_OUT))
|
||||
entry->writers--;
|
||||
}
|
||||
else if(cur_action & CURL_POLL_OUT)
|
||||
entry->writers++;
|
||||
|
||||
DEBUGASSERT(entry->readers <= mev_sh_entry_user_count(entry));
|
||||
DEBUGASSERT(entry->writers <= mev_sh_entry_user_count(entry));
|
||||
DEBUGASSERT(entry->writers + entry->readers);
|
||||
|
||||
CURL_TRC_M(data, "ev update fd=%" FMT_SOCKET_T ", action '%s%s' -> '%s%s'"
|
||||
" (%d/%d r/w)", s,
|
||||
(last_action & CURL_POLL_IN) ? "IN" : "",
|
||||
(last_action & CURL_POLL_OUT) ? "OUT" : "",
|
||||
(cur_action & CURL_POLL_IN) ? "IN" : "",
|
||||
(cur_action & CURL_POLL_OUT) ? "OUT" : "",
|
||||
entry->readers, entry->writers);
|
||||
|
||||
comboaction = (entry->writers ? CURL_POLL_OUT : 0) |
|
||||
(entry->readers ? CURL_POLL_IN : 0);
|
||||
if(((int)entry->action == comboaction)) /* nothing for socket changed */
|
||||
return CURLM_OK;
|
||||
|
||||
CURL_TRC_M(data, "ev update call(fd=%" FMT_SOCKET_T ", ev=%s%s)",
|
||||
s, (comboaction & CURL_POLL_IN) ? "IN" : "",
|
||||
(comboaction & CURL_POLL_OUT) ? "OUT" : "");
|
||||
mev_in_callback(multi, TRUE);
|
||||
rc = multi->socket_cb(data, s, comboaction, multi->socket_userp,
|
||||
entry->user_data);
|
||||
|
||||
mev_in_callback(multi, FALSE);
|
||||
if(rc == -1) {
|
||||
multi->dead = TRUE;
|
||||
return CURLM_ABORTED_BY_CALLBACK;
|
||||
}
|
||||
entry->action = (unsigned int)comboaction;
|
||||
return CURLM_OK;
|
||||
}
|
||||
|
||||
static CURLMcode mev_pollset_diff(struct Curl_multi *multi,
|
||||
struct Curl_easy *data,
|
||||
struct connectdata *conn,
|
||||
struct easy_pollset *ps,
|
||||
struct easy_pollset *prev_ps)
|
||||
{
|
||||
struct mev_sh_entry *entry;
|
||||
curl_socket_t s;
|
||||
unsigned int i, j;
|
||||
CURLMcode mresult;
|
||||
|
||||
/* The transfer `data` reports in `ps` the sockets it is interested
|
||||
* in and which combinatino of CURL_POLL_IN/CURL_POLL_OUT it wants
|
||||
* to have monitored for events.
|
||||
* There can be more than 1 transfer interested in the same socket
|
||||
* and 1 transfer might be interested in more than 1 socket.
|
||||
* `prev_ps` is the pollset copy from the previous call here. On
|
||||
* the 1st call it will be empty.
|
||||
*/
|
||||
DEBUGASSERT(ps);
|
||||
DEBUGASSERT(prev_ps);
|
||||
|
||||
/* Handle changes to sockets the transfer is interested in. */
|
||||
for(i = 0; i < ps->num; i++) {
|
||||
unsigned char last_action;
|
||||
bool first_time = FALSE; /* data/conn appears first time on socket */
|
||||
|
||||
s = ps->sockets[i];
|
||||
/* Have we handled this socket before? */
|
||||
entry = mev_sh_entry_get(&multi->ev.sh_entries, s);
|
||||
if(!entry) {
|
||||
/* new socket, add new entry */
|
||||
first_time = TRUE;
|
||||
entry = mev_sh_entry_add(&multi->ev.sh_entries, s);
|
||||
if(!entry) /* fatal */
|
||||
return CURLM_OUT_OF_MEMORY;
|
||||
CURL_TRC_M(data, "ev new entry fd=%" FMT_SOCKET_T, s);
|
||||
}
|
||||
else if(conn) {
|
||||
first_time = !mev_sh_entry_conn_known(entry, data->conn);
|
||||
}
|
||||
else {
|
||||
first_time = !mev_sh_entry_xfer_known(entry, data);
|
||||
}
|
||||
|
||||
/* What was the previous action the transfer had regarding this socket?
|
||||
* If the transfer is new to the socket, disregard the information
|
||||
* in `last_poll`, because the socket might have been destroyed and
|
||||
* reopened. We'd have cleared the sh_entry for that, but the socket
|
||||
* might still be mentioned in the hashed pollsets. */
|
||||
last_action = 0;
|
||||
if(first_time) {
|
||||
if(conn) {
|
||||
if(!mev_sh_entry_conn_add(entry, data->conn))
|
||||
return CURLM_OUT_OF_MEMORY;
|
||||
}
|
||||
else {
|
||||
if(!mev_sh_entry_xfer_add(entry, data))
|
||||
return CURLM_OUT_OF_MEMORY;
|
||||
}
|
||||
CURL_TRC_M(data, "ev entry fd=%" FMT_SOCKET_T ", added %s #%" FMT_OFF_T
|
||||
", total=%zu/%zu (xfer/conn)", s,
|
||||
conn ? "connection" : "transfer",
|
||||
conn ? conn->connection_id : data->id,
|
||||
Curl_hash_count(&entry->xfers),
|
||||
Curl_hash_count(&entry->conns));
|
||||
}
|
||||
else {
|
||||
for(j = 0; j < prev_ps->num; j++) {
|
||||
if(s == prev_ps->sockets[j]) {
|
||||
last_action = prev_ps->actions[j];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* track readers/writers changes and report to socket callback */
|
||||
mresult = mev_sh_entry_update(multi, data, entry, s,
|
||||
last_action, ps->actions[i]);
|
||||
if(mresult)
|
||||
return mresult;
|
||||
}
|
||||
|
||||
/* Handle changes to sockets the transfer is NO LONGER interested in. */
|
||||
for(i = 0; i < prev_ps->num; i++) {
|
||||
bool stillused = FALSE;
|
||||
|
||||
s = prev_ps->sockets[i];
|
||||
for(j = 0; j < ps->num; j++) {
|
||||
if(s == ps->sockets[j]) {
|
||||
/* socket is still supervised */
|
||||
stillused = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(stillused)
|
||||
continue;
|
||||
|
||||
entry = mev_sh_entry_get(&multi->ev.sh_entries, s);
|
||||
/* if entry does not exist, we were either never told about it or
|
||||
* have already cleaned up this socket via Curl_multi_ev_socket_done().
|
||||
* In other words: this is perfectly normal */
|
||||
if(!entry)
|
||||
continue;
|
||||
|
||||
if(!mev_sh_entry_xfer_remove(entry, data)) {
|
||||
/* `data` says in `prev_ps` that it had been using a socket,
|
||||
* but `data` has not been registered for it.
|
||||
* This should not happen if our book-keeping is correct? */
|
||||
CURL_TRC_M(data, "ev entry fd=%" FMT_SOCKET_T ", transfer lost "
|
||||
"interest but is not registered", s);
|
||||
DEBUGASSERT(NULL);
|
||||
continue;
|
||||
}
|
||||
|
||||
if(mev_sh_entry_user_count(entry)) {
|
||||
/* track readers/writers changes and report to socket callback */
|
||||
mresult = mev_sh_entry_update(multi, data, entry, s,
|
||||
prev_ps->actions[i], 0);
|
||||
if(mresult)
|
||||
return mresult;
|
||||
CURL_TRC_M(data, "ev entry fd=%" FMT_SOCKET_T ", removed transfer, "
|
||||
"total=%zu/%zu (xfer/conn)", s,
|
||||
Curl_hash_count(&entry->xfers),
|
||||
Curl_hash_count(&entry->conns));
|
||||
}
|
||||
else {
|
||||
mresult = mev_forget_socket(multi, data, s, "last user gone");
|
||||
if(mresult)
|
||||
return mresult;
|
||||
}
|
||||
} /* for loop over num */
|
||||
|
||||
/* Remember for next time */
|
||||
memcpy(prev_ps, ps, sizeof(*prev_ps));
|
||||
return CURLM_OK;
|
||||
}
|
||||
|
||||
static struct easy_pollset*
|
||||
mev_add_new_pollset(struct Curl_hash *h, curl_off_t id)
|
||||
{
|
||||
struct easy_pollset *ps;
|
||||
|
||||
ps = calloc(1, sizeof(*ps));
|
||||
if(!ps)
|
||||
return NULL;
|
||||
if(!Curl_hash_offt_set(h, id, ps)) {
|
||||
free(ps);
|
||||
return NULL;
|
||||
}
|
||||
return ps;
|
||||
}
|
||||
|
||||
static struct easy_pollset *
|
||||
mev_get_last_pollset(struct Curl_multi *multi,
|
||||
struct Curl_easy *data,
|
||||
struct connectdata *conn)
|
||||
{
|
||||
if(data) {
|
||||
if(conn)
|
||||
return Curl_hash_offt_get(&multi->ev.conn_pollsets,
|
||||
conn->connection_id);
|
||||
else if(data)
|
||||
return Curl_hash_offt_get(&multi->ev.xfer_pollsets, data->id);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void mev_init_cur_pollset(struct easy_pollset *ps,
|
||||
struct Curl_easy *data,
|
||||
struct connectdata *conn)
|
||||
{
|
||||
memset(ps, 0, sizeof(*ps));
|
||||
if(conn)
|
||||
Curl_conn_adjust_pollset(data, conn, ps);
|
||||
else if(data)
|
||||
Curl_multi_getsock(data, ps, "ev assess");
|
||||
}
|
||||
|
||||
static CURLMcode mev_assess(struct Curl_multi *multi,
|
||||
struct Curl_easy *data,
|
||||
struct connectdata *conn)
|
||||
{
|
||||
if(multi && multi->socket_cb) {
|
||||
struct easy_pollset ps, *last_ps;
|
||||
|
||||
mev_init_cur_pollset(&ps, data, conn);
|
||||
last_ps = mev_get_last_pollset(multi, data, conn);
|
||||
|
||||
if(!last_ps && ps.num) {
|
||||
if(conn)
|
||||
last_ps = mev_add_new_pollset(&multi->ev.conn_pollsets,
|
||||
data->conn->connection_id);
|
||||
else
|
||||
last_ps = mev_add_new_pollset(&multi->ev.xfer_pollsets, data->id);
|
||||
if(!last_ps)
|
||||
return CURLM_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
if(last_ps)
|
||||
return mev_pollset_diff(multi, data, conn, &ps, last_ps);
|
||||
else
|
||||
DEBUGASSERT(!ps.num);
|
||||
}
|
||||
return CURLM_OK;
|
||||
}
|
||||
|
||||
CURLMcode Curl_multi_ev_assess_xfer(struct Curl_multi *multi,
|
||||
struct Curl_easy *data)
|
||||
{
|
||||
return mev_assess(multi, data, NULL);
|
||||
}
|
||||
|
||||
CURLMcode Curl_multi_ev_assess_conn(struct Curl_multi *multi,
|
||||
struct Curl_easy *data,
|
||||
struct connectdata *conn)
|
||||
{
|
||||
return mev_assess(multi, data, conn);
|
||||
}
|
||||
|
||||
CURLMcode Curl_multi_ev_assess_xfer_list(struct Curl_multi *multi,
|
||||
struct Curl_llist *list)
|
||||
{
|
||||
struct Curl_llist_node *e;
|
||||
CURLMcode result = CURLM_OK;
|
||||
|
||||
if(multi && multi->socket_cb) {
|
||||
for(e = Curl_llist_head(list); e && !result; e = Curl_node_next(e)) {
|
||||
result = Curl_multi_ev_assess_xfer(multi, Curl_node_elem(e));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
CURLMcode Curl_multi_ev_assign(struct Curl_multi *multi,
|
||||
curl_socket_t s,
|
||||
void *user_data)
|
||||
{
|
||||
struct mev_sh_entry *e = mev_sh_entry_get(&multi->ev.sh_entries, s);
|
||||
if(!e)
|
||||
return CURLM_BAD_SOCKET;
|
||||
e->user_data = user_data;
|
||||
return CURLM_OK;
|
||||
}
|
||||
|
||||
|
||||
void Curl_multi_ev_expire_xfers(struct Curl_multi *multi,
|
||||
curl_socket_t s,
|
||||
const struct curltime *nowp,
|
||||
bool *run_cpool)
|
||||
{
|
||||
struct mev_sh_entry *entry;
|
||||
|
||||
DEBUGASSERT(s != CURL_SOCKET_TIMEOUT);
|
||||
entry = mev_sh_entry_get(&multi->ev.sh_entries, s);
|
||||
|
||||
/* Unmatched socket, we cannot act on it but we ignore this fact. In
|
||||
real-world tests it has been proved that libevent can in fact give
|
||||
the application actions even though the socket was just previously
|
||||
asked to get removed, so thus we better survive stray socket actions
|
||||
and just move on. */
|
||||
if(entry) {
|
||||
struct Curl_hash_iterator iter;
|
||||
struct Curl_hash_element *he;
|
||||
|
||||
/* the socket can be shared by many transfers, iterate */
|
||||
Curl_hash_start_iterate(&entry->xfers, &iter);
|
||||
for(he = Curl_hash_next_element(&iter); he;
|
||||
he = Curl_hash_next_element(&iter)) {
|
||||
struct Curl_easy *data = (struct Curl_easy *)he->ptr;
|
||||
DEBUGASSERT(data);
|
||||
DEBUGASSERT(data->magic == CURLEASY_MAGIC_NUMBER);
|
||||
DEBUGASSERT(data->id >= 0); /* we should not track internal handles */
|
||||
|
||||
/* Expire with out current now, so we will get it below when
|
||||
* asking the splaytree for expired transfers. */
|
||||
Curl_expire_ex(data, nowp, 0, EXPIRE_RUN_NOW);
|
||||
}
|
||||
|
||||
if(Curl_hash_count(&entry->conns))
|
||||
*run_cpool = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
void Curl_multi_ev_socket_done(struct Curl_multi *multi,
|
||||
struct Curl_easy *data, curl_socket_t s)
|
||||
{
|
||||
mev_forget_socket(multi, data, s, "socket done");
|
||||
}
|
||||
|
||||
void Curl_multi_ev_xfer_done(struct Curl_multi *multi,
|
||||
struct Curl_easy *data)
|
||||
{
|
||||
DEBUGASSERT(!data->conn); /* transfer should have been detached */
|
||||
if(data->id >= 0) {
|
||||
(void)mev_assess(multi, data, NULL);
|
||||
Curl_hash_offt_remove(&multi->ev.xfer_pollsets, data->id);
|
||||
}
|
||||
}
|
||||
|
||||
void Curl_multi_ev_conn_done(struct Curl_multi *multi,
|
||||
struct Curl_easy *data,
|
||||
struct connectdata *conn)
|
||||
{
|
||||
(void)mev_assess(multi, data, conn);
|
||||
Curl_hash_offt_remove(&multi->ev.conn_pollsets, conn->connection_id);
|
||||
}
|
||||
|
||||
#define CURL_MEV_PS_HASH_SLOTS (991) /* nice prime */
|
||||
|
||||
static void mev_hash_pollset_free(void *entry)
|
||||
{
|
||||
free(entry);
|
||||
}
|
||||
|
||||
void Curl_multi_ev_init(struct Curl_multi *multi, size_t hashsize)
|
||||
{
|
||||
Curl_hash_init(&multi->ev.sh_entries, hashsize, mev_sh_entry_hash,
|
||||
mev_sh_entry_compare, mev_sh_entry_dtor);
|
||||
Curl_hash_offt_init(&multi->ev.xfer_pollsets,
|
||||
CURL_MEV_PS_HASH_SLOTS, mev_hash_pollset_free);
|
||||
Curl_hash_offt_init(&multi->ev.conn_pollsets,
|
||||
CURL_MEV_PS_HASH_SLOTS, mev_hash_pollset_free);
|
||||
}
|
||||
|
||||
void Curl_multi_ev_cleanup(struct Curl_multi *multi)
|
||||
{
|
||||
Curl_hash_destroy(&multi->ev.sh_entries);
|
||||
Curl_hash_destroy(&multi->ev.xfer_pollsets);
|
||||
Curl_hash_destroy(&multi->ev.conn_pollsets);
|
||||
}
|
||||
@ -1,79 +0,0 @@
|
||||
#ifndef HEADER_CURL_MULTI_EV_H
|
||||
#define HEADER_CURL_MULTI_EV_H
|
||||
/***************************************************************************
|
||||
* _ _ ____ _
|
||||
* Project ___| | | | _ \| |
|
||||
* / __| | | | |_) | |
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
* are also available at https://curl.se/docs/copyright.html.
|
||||
*
|
||||
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||
* copies of the Software, and permit persons to whom the Software is
|
||||
* furnished to do so, under the terms of the COPYING file.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
* SPDX-License-Identifier: curl
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
struct Curl_easy;
|
||||
struct Curl_multi;
|
||||
struct easy_pollset;
|
||||
|
||||
struct curl_multi_ev {
|
||||
struct Curl_hash sh_entries;
|
||||
struct Curl_hash xfer_pollsets;
|
||||
struct Curl_hash conn_pollsets;
|
||||
};
|
||||
|
||||
/* Setup/teardown of multi event book-keeping. */
|
||||
void Curl_multi_ev_init(struct Curl_multi *multi, size_t hashsize);
|
||||
void Curl_multi_ev_cleanup(struct Curl_multi *multi);
|
||||
|
||||
/* Assign a 'user_data' to be passed to the socket callback when
|
||||
* invoked with the given socket. This will fail if this socket
|
||||
* is not active, e.g. the application has not been told to monitor it. */
|
||||
CURLMcode Curl_multi_ev_assign(struct Curl_multi *multi, curl_socket_t s,
|
||||
void *user_data);
|
||||
|
||||
/* Assess the transfer by getting its current pollset, compute
|
||||
* any changes to the last one and inform the application's socket
|
||||
* callback if things have changed. */
|
||||
CURLMcode Curl_multi_ev_assess_xfer(struct Curl_multi *multi,
|
||||
struct Curl_easy *data);
|
||||
/* Assess all easy handles on the list */
|
||||
CURLMcode Curl_multi_ev_assess_xfer_list(struct Curl_multi *multi,
|
||||
struct Curl_llist *list);
|
||||
/* Assess the connection by getting its current pollset */
|
||||
CURLMcode Curl_multi_ev_assess_conn(struct Curl_multi *multi,
|
||||
struct Curl_easy *data,
|
||||
struct connectdata *conn);
|
||||
|
||||
/* Expire all transfers tied to the given socket */
|
||||
void Curl_multi_ev_expire_xfers(struct Curl_multi *multi,
|
||||
curl_socket_t s,
|
||||
const struct curltime *nowp,
|
||||
bool *run_cpool);
|
||||
|
||||
/* Socket will be closed, forget anything we know about it. */
|
||||
void Curl_multi_ev_socket_done(struct Curl_multi *multi,
|
||||
struct Curl_easy *data, curl_socket_t s);
|
||||
|
||||
/* Transfer is removed from the multi */
|
||||
void Curl_multi_ev_xfer_done(struct Curl_multi *multi,
|
||||
struct Curl_easy *data);
|
||||
|
||||
/* Connection is being destroyed */
|
||||
void Curl_multi_ev_conn_done(struct Curl_multi *multi,
|
||||
struct Curl_easy *data,
|
||||
struct connectdata *conn);
|
||||
|
||||
#endif /* HEADER_CURL_MULTI_EV_H */
|
||||
@ -27,7 +27,6 @@
|
||||
#include "llist.h"
|
||||
#include "hash.h"
|
||||
#include "conncache.h"
|
||||
#include "multi_ev.h"
|
||||
#include "psl.h"
|
||||
#include "socketpair.h"
|
||||
|
||||
@ -39,9 +38,9 @@ struct Curl_message {
|
||||
struct CURLMsg extmsg;
|
||||
};
|
||||
|
||||
/* NOTE: if you add a state here, add the name to the statenames[] array
|
||||
* in curl_trc.c as well!
|
||||
*/
|
||||
/* NOTE: if you add a state here, add the name to the statename[] array as
|
||||
well!
|
||||
*/
|
||||
typedef enum {
|
||||
MSTATE_INIT, /* 0 - start in this state */
|
||||
MSTATE_PENDING, /* 1 - no connections, waiting for one */
|
||||
@ -129,9 +128,10 @@ struct Curl_multi {
|
||||
char *xfer_sockbuf; /* the actual buffer */
|
||||
size_t xfer_sockbuf_len; /* the allocated length */
|
||||
|
||||
/* multi event related things */
|
||||
struct curl_multi_ev ev;
|
||||
|
||||
/* 'sockhash' is the lookup hash for socket descriptor => easy handles (note
|
||||
the pluralis form, there can be more than one easy handle waiting on the
|
||||
same actual socket) */
|
||||
struct Curl_hash sockhash;
|
||||
/* `proto_hash` is a general key-value store for protocol implementations
|
||||
* with the lifetime of the multi handle. The number of elements kept here
|
||||
* should be in the order of supported protocols (and sub-protocols like
|
||||
|
||||
@ -28,10 +28,8 @@
|
||||
* Prototypes for library-wide functions provided by multi.c
|
||||
*/
|
||||
|
||||
CURLcode Curl_updatesocket(struct Curl_easy *data);
|
||||
void Curl_expire(struct Curl_easy *data, timediff_t milli, expire_id);
|
||||
void Curl_expire_ex(struct Curl_easy *data,
|
||||
const struct curltime *nowp,
|
||||
timediff_t milli, expire_id id);
|
||||
bool Curl_expire_clear(struct Curl_easy *data);
|
||||
void Curl_expire_done(struct Curl_easy *data, expire_id id);
|
||||
CURLMcode Curl_update_timer(struct Curl_multi *multi) WARN_UNUSED_RESULT;
|
||||
@ -66,13 +64,26 @@ struct Curl_multi *Curl_multi_handle(size_t hashsize,
|
||||
/* mask for checking if read and/or write is set for index x */
|
||||
#define GETSOCK_MASK_RW(x) (GETSOCK_READSOCK(x)|GETSOCK_WRITESOCK(x))
|
||||
|
||||
/**
|
||||
* Let the multi handle know that the socket is about to be closed.
|
||||
* The multi will then remove anything it knows about the socket, so
|
||||
* when the OS is using this socket (number) again subsequently,
|
||||
* the internal book keeping will not get confused.
|
||||
/*
|
||||
* Curl_multi_closed()
|
||||
*
|
||||
* Used by the connect code to tell the multi_socket code that one of the
|
||||
* sockets we were using is about to be closed. This function will then
|
||||
* remove it from the sockethash for this handle to make the multi_socket API
|
||||
* behave properly, especially for the case when libcurl will create another
|
||||
* socket again and it gets the same file descriptor number.
|
||||
*/
|
||||
void Curl_multi_will_close(struct Curl_easy *data, curl_socket_t s);
|
||||
|
||||
void Curl_multi_closed(struct Curl_easy *data, curl_socket_t s);
|
||||
|
||||
/* Compare the two pollsets to notify the multi_socket API of changes
|
||||
* in socket polling, e.g calling multi->socket_cb() with the changes if
|
||||
* differences are seen.
|
||||
*/
|
||||
CURLMcode Curl_multi_pollset_ev(struct Curl_multi *multi,
|
||||
struct Curl_easy *data,
|
||||
struct easy_pollset *ps,
|
||||
struct easy_pollset *last_ps);
|
||||
|
||||
/*
|
||||
* Add a handle and move it into PERFORM state at once. For pushed streams.
|
||||
@ -85,10 +96,6 @@ CURLMcode Curl_multi_add_perform(struct Curl_multi *multi,
|
||||
/* Return the value of the CURLMOPT_MAX_CONCURRENT_STREAMS option */
|
||||
unsigned int Curl_multi_max_concurrent_streams(struct Curl_multi *multi);
|
||||
|
||||
void Curl_multi_getsock(struct Curl_easy *data,
|
||||
struct easy_pollset *ps,
|
||||
const char *caller);
|
||||
|
||||
/**
|
||||
* Borrow the transfer buffer from the multi, suitable
|
||||
* for the given transfer `data`. The buffer may only be used in one
|
||||
|
||||
46
lib/setopt.c
46
lib/setopt.c
@ -438,7 +438,7 @@ static CURLcode setopt_long(struct Curl_easy *data, CURLoption option,
|
||||
*/
|
||||
if((arg < CURL_TIMECOND_NONE) || (arg >= CURL_TIMECOND_LAST))
|
||||
return CURLE_BAD_FUNCTION_ARGUMENT;
|
||||
data->set.timecondition = (unsigned char)arg;
|
||||
data->set.timecondition = (unsigned char)(curl_TimeCond)arg;
|
||||
break;
|
||||
case CURLOPT_TIMEVALUE:
|
||||
/*
|
||||
@ -1970,46 +1970,46 @@ static CURLcode setopt_cptr(struct Curl_easy *data, CURLoption option,
|
||||
/*
|
||||
* Custom pointer to pass the header write callback function
|
||||
*/
|
||||
data->set.writeheader = ptr;
|
||||
data->set.writeheader = (void *)ptr;
|
||||
break;
|
||||
case CURLOPT_READDATA:
|
||||
/*
|
||||
* FILE pointer to read the file to be uploaded from. Or possibly used as
|
||||
* argument to the read callback.
|
||||
*/
|
||||
data->set.in_set = ptr;
|
||||
data->set.in_set = (void *)ptr;
|
||||
break;
|
||||
case CURLOPT_WRITEDATA:
|
||||
/*
|
||||
* FILE pointer to write to. Or possibly used as argument to the write
|
||||
* callback.
|
||||
*/
|
||||
data->set.out = ptr;
|
||||
data->set.out = (void *)ptr;
|
||||
break;
|
||||
case CURLOPT_DEBUGDATA:
|
||||
/*
|
||||
* Set to a void * that should receive all error writes. This
|
||||
* defaults to CURLOPT_STDERR for normal operations.
|
||||
*/
|
||||
data->set.debugdata = ptr;
|
||||
data->set.debugdata = (void *)ptr;
|
||||
break;
|
||||
case CURLOPT_PROGRESSDATA:
|
||||
/*
|
||||
* Custom client data to pass to the progress callback
|
||||
*/
|
||||
data->set.progress_client = ptr;
|
||||
data->set.progress_client = (void *)ptr;
|
||||
break;
|
||||
case CURLOPT_SEEKDATA:
|
||||
/*
|
||||
* Seek control callback. Might be NULL.
|
||||
*/
|
||||
data->set.seek_client = ptr;
|
||||
data->set.seek_client = (void *)ptr;
|
||||
break;
|
||||
case CURLOPT_IOCTLDATA:
|
||||
/*
|
||||
* I/O control data pointer. Might be NULL.
|
||||
*/
|
||||
data->set.ioctl_client = ptr;
|
||||
data->set.ioctl_client = (void *)ptr;
|
||||
break;
|
||||
case CURLOPT_SSL_CTX_DATA:
|
||||
/*
|
||||
@ -2017,7 +2017,7 @@ static CURLcode setopt_cptr(struct Curl_easy *data, CURLoption option,
|
||||
*/
|
||||
#ifdef USE_SSL
|
||||
if(Curl_ssl_supports(data, SSLSUPP_SSL_CTX))
|
||||
data->set.ssl.fsslctxp = ptr;
|
||||
data->set.ssl.fsslctxp = (void *)ptr;
|
||||
else
|
||||
#endif
|
||||
return CURLE_NOT_BUILT_IN;
|
||||
@ -2026,33 +2026,33 @@ static CURLcode setopt_cptr(struct Curl_easy *data, CURLoption option,
|
||||
/*
|
||||
* socket callback data pointer. Might be NULL.
|
||||
*/
|
||||
data->set.sockopt_client = ptr;
|
||||
data->set.sockopt_client = (void *)ptr;
|
||||
break;
|
||||
case CURLOPT_OPENSOCKETDATA:
|
||||
/*
|
||||
* socket callback data pointer. Might be NULL.
|
||||
*/
|
||||
data->set.opensocket_client = ptr;
|
||||
data->set.opensocket_client = (void *)ptr;
|
||||
break;
|
||||
case CURLOPT_RESOLVER_START_DATA:
|
||||
/*
|
||||
* resolver start callback data pointer. Might be NULL.
|
||||
*/
|
||||
data->set.resolver_start_client = ptr;
|
||||
data->set.resolver_start_client = (void *)ptr;
|
||||
break;
|
||||
case CURLOPT_CLOSESOCKETDATA:
|
||||
/*
|
||||
* socket callback data pointer. Might be NULL.
|
||||
*/
|
||||
data->set.closesocket_client = ptr;
|
||||
data->set.closesocket_client = (void *)ptr;
|
||||
break;
|
||||
case CURLOPT_TRAILERDATA:
|
||||
#ifndef CURL_DISABLE_HTTP
|
||||
data->set.trailer_data = ptr;
|
||||
data->set.trailer_data = (void *)ptr;
|
||||
#endif
|
||||
break;
|
||||
case CURLOPT_PREREQDATA:
|
||||
data->set.prereq_userp = ptr;
|
||||
data->set.prereq_userp = (void *)ptr;
|
||||
break;
|
||||
|
||||
case CURLOPT_ERRORBUFFER:
|
||||
@ -2388,7 +2388,7 @@ static CURLcode setopt_cptr(struct Curl_easy *data, CURLoption option,
|
||||
/*
|
||||
* Set private data pointer.
|
||||
*/
|
||||
data->set.private_data = ptr;
|
||||
data->set.private_data = (void *)ptr;
|
||||
break;
|
||||
|
||||
#ifdef USE_SSL
|
||||
@ -2430,7 +2430,7 @@ static CURLcode setopt_cptr(struct Curl_easy *data, CURLoption option,
|
||||
/*
|
||||
* Custom client data to pass to the SSH keyfunc callback
|
||||
*/
|
||||
data->set.ssh_keyfunc_userp = ptr;
|
||||
data->set.ssh_keyfunc_userp = (void *)ptr;
|
||||
break;
|
||||
#ifdef USE_LIBSSH2
|
||||
case CURLOPT_SSH_HOST_PUBLIC_KEY_SHA256:
|
||||
@ -2445,7 +2445,7 @@ static CURLcode setopt_cptr(struct Curl_easy *data, CURLoption option,
|
||||
/*
|
||||
* Custom client data to pass to the SSH keyfunc callback
|
||||
*/
|
||||
data->set.ssh_hostkeyfunc_userp = ptr;
|
||||
data->set.ssh_hostkeyfunc_userp = (void *)ptr;
|
||||
break;
|
||||
#endif /* USE_LIBSSH2 */
|
||||
#endif /* USE_SSH */
|
||||
@ -2504,15 +2504,15 @@ static CURLcode setopt_cptr(struct Curl_easy *data, CURLoption option,
|
||||
return Curl_setstropt(&data->set.str[STRING_RTSP_TRANSPORT], ptr);
|
||||
|
||||
case CURLOPT_INTERLEAVEDATA:
|
||||
data->set.rtp_out = ptr;
|
||||
data->set.rtp_out = (void *)ptr;
|
||||
break;
|
||||
#endif /* ! CURL_DISABLE_RTSP */
|
||||
#ifndef CURL_DISABLE_FTP
|
||||
case CURLOPT_CHUNK_DATA:
|
||||
data->set.wildcardptr = ptr;
|
||||
data->set.wildcardptr = (void *)ptr;
|
||||
break;
|
||||
case CURLOPT_FNMATCH_DATA:
|
||||
data->set.fnmatch_data = ptr;
|
||||
data->set.fnmatch_data = (void *)ptr;
|
||||
break;
|
||||
#endif
|
||||
#ifdef USE_TLS_SRP
|
||||
@ -2587,10 +2587,10 @@ static CURLcode setopt_cptr(struct Curl_easy *data, CURLoption option,
|
||||
#endif
|
||||
#ifndef CURL_DISABLE_HSTS
|
||||
case CURLOPT_HSTSREADDATA:
|
||||
data->set.hsts_read_userp = ptr;
|
||||
data->set.hsts_read_userp = (void *)ptr;
|
||||
break;
|
||||
case CURLOPT_HSTSWRITEDATA:
|
||||
data->set.hsts_write_userp = ptr;
|
||||
data->set.hsts_write_userp = (void *)ptr;
|
||||
break;
|
||||
case CURLOPT_HSTS: {
|
||||
struct curl_slist *h;
|
||||
|
||||
@ -93,6 +93,12 @@
|
||||
* newer symbols.
|
||||
*/
|
||||
|
||||
#ifndef _WIN32_WINNT_NT4
|
||||
#define _WIN32_WINNT_NT4 0x0400 /* Windows NT 4.0 */
|
||||
#endif
|
||||
#ifndef _WIN32_WINNT_WIN2K
|
||||
#define _WIN32_WINNT_WIN2K 0x0500 /* Windows 2000 */
|
||||
#endif
|
||||
#ifndef _WIN32_WINNT_WINXP
|
||||
#define _WIN32_WINNT_WINXP 0x0501 /* Windows XP */
|
||||
#endif
|
||||
|
||||
@ -114,10 +114,7 @@ void *Curl_memdup0(const char *src, size_t length)
|
||||
char *buf = malloc(length + 1);
|
||||
if(!buf)
|
||||
return NULL;
|
||||
if(length) {
|
||||
DEBUGASSERT(src); /* must never be NULL */
|
||||
memcpy(buf, src, length);
|
||||
}
|
||||
memcpy(buf, src, length);
|
||||
buf[length] = 0;
|
||||
return buf;
|
||||
}
|
||||
|
||||
@ -31,12 +31,6 @@ void Curl_str_init(struct Curl_str *out)
|
||||
out->len = 0;
|
||||
}
|
||||
|
||||
void Curl_str_assign(struct Curl_str *out, const char *str, size_t len)
|
||||
{
|
||||
out->str = str;
|
||||
out->len = len;
|
||||
}
|
||||
|
||||
/* Get a word until the first DELIM or end of string. At least one byte long.
|
||||
return non-zero on error */
|
||||
int Curl_str_until(const char **linep, struct Curl_str *out,
|
||||
@ -69,29 +63,6 @@ int Curl_str_word(const char **linep, struct Curl_str *out,
|
||||
return Curl_str_until(linep, out, max, ' ');
|
||||
}
|
||||
|
||||
/* Get a word until a newline byte or end of string. At least one byte long.
|
||||
return non-zero on error */
|
||||
int Curl_str_untilnl(const char **linep, struct Curl_str *out,
|
||||
const size_t max)
|
||||
{
|
||||
const char *s = *linep;
|
||||
size_t len = 0;
|
||||
DEBUGASSERT(linep && *linep && out && max);
|
||||
|
||||
Curl_str_init(out);
|
||||
while(*s && !ISNEWLINE(*s)) {
|
||||
s++;
|
||||
if(++len > max)
|
||||
return STRE_BIG;
|
||||
}
|
||||
if(!len)
|
||||
return STRE_SHORT;
|
||||
out->str = *linep;
|
||||
out->len = len;
|
||||
*linep = s; /* point to the first byte after the word */
|
||||
return STRE_OK;
|
||||
}
|
||||
|
||||
|
||||
/* Get a "quoted" word. No escaping possible.
|
||||
return non-zero on error */
|
||||
@ -232,16 +203,6 @@ int Curl_str_casecompare(struct Curl_str *str, const char *check)
|
||||
return ((str->len == clen) && strncasecompare(str->str, check, clen));
|
||||
}
|
||||
|
||||
/* case sensitive string compare. Returns non-zero on match. */
|
||||
int Curl_str_cmp(struct Curl_str *str, const char *check)
|
||||
{
|
||||
if(check) {
|
||||
size_t clen = strlen(check);
|
||||
return ((str->len == clen) && !strncmp(str->str, check, clen));
|
||||
}
|
||||
return !!(str->len);
|
||||
}
|
||||
|
||||
/* Trim off 'num' number of bytes from the beginning (left side) of the
|
||||
string. If 'num' is larger than the string, return error. */
|
||||
int Curl_str_nudge(struct Curl_str *str, size_t num)
|
||||
|
||||
@ -43,7 +43,6 @@ struct Curl_str {
|
||||
};
|
||||
|
||||
void Curl_str_init(struct Curl_str *out);
|
||||
void Curl_str_assign(struct Curl_str *out, const char *str, size_t len);
|
||||
|
||||
#define Curl_str(x) ((x)->str)
|
||||
#define Curl_strlen(x) ((x)->len)
|
||||
@ -57,11 +56,6 @@ int Curl_str_word(const char **linep, struct Curl_str *out, const size_t max);
|
||||
int Curl_str_until(const char **linep, struct Curl_str *out, const size_t max,
|
||||
char delim);
|
||||
|
||||
/* Get a word until a newline byte or end of string. At least one byte long.
|
||||
return non-zero on error */
|
||||
int Curl_str_untilnl(const char **linep, struct Curl_str *out,
|
||||
const size_t max);
|
||||
|
||||
/* Get a "quoted" word. No escaping possible.
|
||||
return non-zero on error */
|
||||
int Curl_str_quotedword(const char **linep, struct Curl_str *out,
|
||||
@ -91,7 +85,6 @@ int Curl_str_newline(const char **linep);
|
||||
/* case insensitive compare that the parsed string matches the
|
||||
given string. */
|
||||
int Curl_str_casecompare(struct Curl_str *str, const char *check);
|
||||
int Curl_str_cmp(struct Curl_str *str, const char *check);
|
||||
|
||||
int Curl_str_nudge(struct Curl_str *str, size_t num);
|
||||
|
||||
|
||||
178
lib/urlapi.c
178
lib/urlapi.c
@ -35,7 +35,6 @@
|
||||
#include "strdup.h"
|
||||
#include "idn.h"
|
||||
#include "strparse.h"
|
||||
#include "curl_memrchr.h"
|
||||
|
||||
/* The last 3 #include files should be in this order */
|
||||
#include "curl_printf.h"
|
||||
@ -111,18 +110,26 @@ static void free_urlhandle(struct Curl_URL *u)
|
||||
*/
|
||||
static const char *find_host_sep(const char *url)
|
||||
{
|
||||
const char *sep;
|
||||
const char *query;
|
||||
|
||||
/* Find the start of the hostname */
|
||||
const char *sep = strstr(url, "//");
|
||||
sep = strstr(url, "//");
|
||||
if(!sep)
|
||||
sep = url;
|
||||
else
|
||||
sep += 2;
|
||||
|
||||
/* Find first / or ? */
|
||||
while(*sep && *sep != '/' && *sep != '?')
|
||||
sep++;
|
||||
query = strchr(sep, '?');
|
||||
sep = strchr(sep, '/');
|
||||
|
||||
return sep;
|
||||
if(!sep)
|
||||
sep = url + strlen(url);
|
||||
|
||||
if(!query)
|
||||
query = url + strlen(url);
|
||||
|
||||
return sep < query ? sep : query;
|
||||
}
|
||||
|
||||
/* convert CURLcode to CURLUcode */
|
||||
@ -148,40 +155,46 @@ static CURLUcode urlencode_str(struct dynbuf *o, const char *url,
|
||||
bool left = !query;
|
||||
const unsigned char *iptr;
|
||||
const unsigned char *host_sep = (const unsigned char *) url;
|
||||
CURLcode result = CURLE_OK;
|
||||
CURLcode result;
|
||||
|
||||
if(!relative) {
|
||||
size_t n;
|
||||
if(!relative)
|
||||
host_sep = (const unsigned char *) find_host_sep(url);
|
||||
|
||||
/* output the first piece as-is */
|
||||
n = (const char *)host_sep - url;
|
||||
result = Curl_dyn_addn(o, url, n);
|
||||
len -= n;
|
||||
}
|
||||
for(iptr = (unsigned char *)url; /* read from here */
|
||||
len; iptr++, len--) {
|
||||
|
||||
if(iptr < host_sep) {
|
||||
result = Curl_dyn_addn(o, iptr, 1);
|
||||
if(result)
|
||||
return cc2cu(result);
|
||||
continue;
|
||||
}
|
||||
|
||||
for(iptr = host_sep; len && !result; iptr++, len--) {
|
||||
if(*iptr == ' ') {
|
||||
if(left)
|
||||
result = Curl_dyn_addn(o, "%20", 3);
|
||||
else
|
||||
result = Curl_dyn_addn(o, "+", 1);
|
||||
if(result)
|
||||
return cc2cu(result);
|
||||
continue;
|
||||
}
|
||||
else if(urlchar_needs_escaping(*iptr)) {
|
||||
|
||||
if(*iptr == '?')
|
||||
left = FALSE;
|
||||
|
||||
if(urlchar_needs_escaping(*iptr)) {
|
||||
char out[3]={'%'};
|
||||
out[1] = hexdigits[*iptr >> 4];
|
||||
out[2] = hexdigits[*iptr & 0xf];
|
||||
result = Curl_dyn_addn(o, out, 3);
|
||||
}
|
||||
else {
|
||||
else
|
||||
result = Curl_dyn_addn(o, iptr, 1);
|
||||
if(*iptr == '?')
|
||||
left = FALSE;
|
||||
}
|
||||
if(result)
|
||||
return cc2cu(result);
|
||||
}
|
||||
|
||||
if(result)
|
||||
return cc2cu(result);
|
||||
return CURLUE_OK;
|
||||
}
|
||||
|
||||
@ -234,76 +247,87 @@ size_t Curl_is_absolute_url(const char *url, char *buf, size_t buflen,
|
||||
}
|
||||
|
||||
/*
|
||||
* Concatenate a relative URL onto a base URL making it absolute.
|
||||
* Concatenate a relative URL to a base URL making it absolute.
|
||||
*
|
||||
* Note that this function destroys the 'base' string.
|
||||
*/
|
||||
static CURLUcode redirect_url(const char *base, const char *relurl,
|
||||
static CURLUcode redirect_url(char *base, const char *relurl,
|
||||
CURLU *u, unsigned int flags)
|
||||
{
|
||||
struct dynbuf urlbuf;
|
||||
bool host_changed = FALSE;
|
||||
const char *useurl = relurl;
|
||||
const char *cutoff = NULL;
|
||||
size_t prelen;
|
||||
CURLcode result = CURLE_OK;
|
||||
CURLUcode uc;
|
||||
/* protsep points to the start of the hostname */
|
||||
char *protsep = strstr(base, "//");
|
||||
DEBUGASSERT(protsep);
|
||||
if(!protsep)
|
||||
protsep = base;
|
||||
else
|
||||
protsep += 2; /* pass the slashes */
|
||||
|
||||
/* protsep points to the start of the hostname, after [scheme]:// */
|
||||
const char *protsep = base + strlen(u->scheme) + 3;
|
||||
DEBUGASSERT(base && relurl && u); /* all set here */
|
||||
if(!base)
|
||||
return CURLUE_MALFORMED_INPUT; /* should never happen */
|
||||
if(('/' != relurl[0]) && ('#' != relurl[0])) {
|
||||
/* First we need to find out if there is a ?-letter in the original URL,
|
||||
and cut it and the right-side of that off */
|
||||
char *pathsep = strchr(protsep, '?');
|
||||
if(pathsep)
|
||||
*pathsep = 0;
|
||||
else {
|
||||
/* if not, cut off the potential fragment */
|
||||
pathsep = strchr(protsep, '#');
|
||||
if(pathsep)
|
||||
*pathsep = 0;
|
||||
}
|
||||
|
||||
/* if the redirect-to piece is not just a query, cut the path after the
|
||||
last slash */
|
||||
if(useurl[0] != '?') {
|
||||
pathsep = strrchr(protsep, '/');
|
||||
if(pathsep)
|
||||
pathsep[1] = 0; /* leave the slash */
|
||||
}
|
||||
}
|
||||
else if('/' == relurl[0]) {
|
||||
/* We got a new absolute path for this server */
|
||||
|
||||
/* handle different relative URL types */
|
||||
switch(relurl[0]) {
|
||||
case '/':
|
||||
if(relurl[1] == '/') {
|
||||
/* protocol-relative URL: //example.com/path */
|
||||
cutoff = protsep;
|
||||
useurl = &relurl[2];
|
||||
/* the new URL starts with //, just keep the protocol part from the
|
||||
original one */
|
||||
*protsep = 0;
|
||||
useurl = &relurl[2]; /* we keep the slashes from the original, so we
|
||||
skip the new ones */
|
||||
host_changed = TRUE;
|
||||
}
|
||||
else
|
||||
/* absolute /path */
|
||||
cutoff = strchr(protsep, '/');
|
||||
break;
|
||||
|
||||
case '#':
|
||||
/* fragment-only change */
|
||||
if(u->fragment)
|
||||
cutoff = strchr(protsep, '#');
|
||||
break;
|
||||
|
||||
default:
|
||||
/* path or query-only change */
|
||||
if(u->query && u->query[0])
|
||||
/* remove existing query */
|
||||
cutoff = strchr(protsep, '?');
|
||||
else if(u->fragment && u->fragment[0])
|
||||
/* Remove existing fragment */
|
||||
cutoff = strchr(protsep, '#');
|
||||
|
||||
if(relurl[0] != '?') {
|
||||
/* append a relative path after the last slash */
|
||||
cutoff = memrchr(protsep, '/',
|
||||
cutoff ? (size_t)(cutoff - protsep) : strlen(protsep));
|
||||
if(cutoff)
|
||||
cutoff++; /* truncate after last slash */
|
||||
else {
|
||||
/* cut the original URL at first slash */
|
||||
char *pathsep = strchr(protsep, '/');
|
||||
if(pathsep)
|
||||
*pathsep = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
else {
|
||||
/* the relative piece starts with '#' */
|
||||
|
||||
/* If there is a fragment in the original URL, cut it off */
|
||||
char *pathsep = strchr(protsep, '#');
|
||||
if(pathsep)
|
||||
*pathsep = 0;
|
||||
}
|
||||
|
||||
prelen = cutoff ? (size_t)(cutoff - base) : strlen(base);
|
||||
|
||||
/* build new URL */
|
||||
Curl_dyn_init(&urlbuf, CURL_MAX_INPUT_LENGTH);
|
||||
|
||||
if(!Curl_dyn_addn(&urlbuf, base, prelen) &&
|
||||
!urlencode_str(&urlbuf, useurl, strlen(useurl), !host_changed, FALSE)) {
|
||||
uc = parseurl_and_replace(Curl_dyn_ptr(&urlbuf), u,
|
||||
flags & ~CURLU_PATH_AS_IS);
|
||||
}
|
||||
else
|
||||
uc = CURLUE_OUT_OF_MEMORY;
|
||||
/* copy over the root URL part */
|
||||
result = Curl_dyn_add(&urlbuf, base);
|
||||
if(result)
|
||||
return cc2cu(result);
|
||||
|
||||
/* then append the new piece on the right side */
|
||||
uc = urlencode_str(&urlbuf, useurl, strlen(useurl), !host_changed,
|
||||
FALSE);
|
||||
if(!uc)
|
||||
uc = parseurl_and_replace(Curl_dyn_ptr(&urlbuf), u,
|
||||
flags&~CURLU_PATH_AS_IS);
|
||||
Curl_dyn_free(&urlbuf);
|
||||
return uc;
|
||||
}
|
||||
@ -1416,10 +1440,8 @@ CURLUcode curl_url_get(const CURLU *u, CURLUPart what,
|
||||
punycode = (flags & CURLU_PUNYCODE) ? 1 : 0;
|
||||
depunyfy = (flags & CURLU_PUNY2IDN) ? 1 : 0;
|
||||
if(u->scheme && strcasecompare("file", u->scheme)) {
|
||||
url = aprintf("file://%s%s%s%s%s",
|
||||
url = aprintf("file://%s%s%s",
|
||||
u->path,
|
||||
show_query ? "?": "",
|
||||
u->query ? u->query : "",
|
||||
show_fragment ? "#": "",
|
||||
u->fragment ? u->fragment : "");
|
||||
}
|
||||
@ -1773,7 +1795,7 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what,
|
||||
|| curl_url_get(u, CURLUPART_URL, &oldurl, flags)) {
|
||||
return parseurl_and_replace(part, u, flags);
|
||||
}
|
||||
DEBUGASSERT(oldurl); /* it is set here */
|
||||
|
||||
/* apply the relative part to create a new URL */
|
||||
uc = redirect_url(oldurl, part, u, flags);
|
||||
free(oldurl);
|
||||
|
||||
@ -565,12 +565,14 @@ struct hostname {
|
||||
#if defined(CURLRES_ASYNCH) || !defined(CURL_DISABLE_DOH)
|
||||
#define USE_CURL_ASYNC
|
||||
struct Curl_async {
|
||||
char *hostname;
|
||||
struct Curl_dns_entry *dns;
|
||||
#ifdef CURLRES_ASYNCH
|
||||
struct thread_data thdata;
|
||||
#endif
|
||||
void *resolver; /* resolver state, if it is used in the URL state -
|
||||
ares_channel e.g. */
|
||||
int port;
|
||||
BIT(done); /* set TRUE when the lookup is complete */
|
||||
};
|
||||
|
||||
@ -813,6 +815,9 @@ struct connectdata {
|
||||
struct curltime start[2]; /* when filter shutdown started */
|
||||
unsigned int timeout_ms; /* 0 means no timeout */
|
||||
} shutdown;
|
||||
/* Last pollset used in connection shutdown. Used to detect changes
|
||||
* for multi_socket API. */
|
||||
struct easy_pollset shutdown_poll;
|
||||
|
||||
struct ssl_primary_config ssl_config;
|
||||
#ifndef CURL_DISABLE_PROXY
|
||||
@ -1688,9 +1693,6 @@ struct UserDefined {
|
||||
struct curl_slist *mail_rcpt; /* linked list of mail recipients */
|
||||
#endif
|
||||
unsigned int maxconnects; /* Max idle connections in the connection cache */
|
||||
#ifdef USE_ECH
|
||||
int tls_ech; /* TLS ECH configuration */
|
||||
#endif
|
||||
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 */
|
||||
@ -1828,6 +1830,9 @@ struct UserDefined {
|
||||
#ifndef CURL_DISABLE_WEBSOCKETS
|
||||
BIT(ws_raw_mode);
|
||||
#endif
|
||||
#ifdef USE_ECH
|
||||
int tls_ech; /* TLS ECH configuration */
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifndef CURL_DISABLE_MIME
|
||||
@ -1880,6 +1885,12 @@ struct Curl_easy {
|
||||
|
||||
struct Curl_message msg; /* A single posted message. */
|
||||
|
||||
/* Array with the plain socket numbers this handle takes care of, in no
|
||||
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(). */
|
||||
struct easy_pollset last_poll;
|
||||
|
||||
struct Names dns;
|
||||
struct Curl_multi *multi; /* if non-NULL, points to the multi handle
|
||||
struct to which this "belongs" when used by
|
||||
|
||||
@ -113,12 +113,88 @@ bool curlx_verify_windows_version(const unsigned int majorVersion,
|
||||
/* we are always running on PLATFORM_WINNT */
|
||||
matched = FALSE;
|
||||
}
|
||||
#elif defined(UNDER_CE)
|
||||
(void)majorVersion;
|
||||
(void)minorVersion;
|
||||
(void)buildVersion;
|
||||
(void)platform;
|
||||
(void)condition;
|
||||
#elif !defined(_WIN32_WINNT) || !defined(_WIN32_WINNT_WIN2K) || \
|
||||
(_WIN32_WINNT < _WIN32_WINNT_WIN2K)
|
||||
OSVERSIONINFO osver;
|
||||
|
||||
memset(&osver, 0, sizeof(osver));
|
||||
osver.dwOSVersionInfoSize = sizeof(osver);
|
||||
|
||||
/* Find out Windows version */
|
||||
if(GetVersionEx(&osver)) {
|
||||
/* Verify the Operating System version number */
|
||||
switch(condition) {
|
||||
case VERSION_LESS_THAN:
|
||||
if(osver.dwMajorVersion < majorVersion ||
|
||||
(osver.dwMajorVersion == majorVersion &&
|
||||
osver.dwMinorVersion < minorVersion) ||
|
||||
(buildVersion != 0 &&
|
||||
(osver.dwMajorVersion == majorVersion &&
|
||||
osver.dwMinorVersion == minorVersion &&
|
||||
osver.dwBuildNumber < buildVersion)))
|
||||
matched = TRUE;
|
||||
break;
|
||||
|
||||
case VERSION_LESS_THAN_EQUAL:
|
||||
if(osver.dwMajorVersion < majorVersion ||
|
||||
(osver.dwMajorVersion == majorVersion &&
|
||||
osver.dwMinorVersion < minorVersion) ||
|
||||
(osver.dwMajorVersion == majorVersion &&
|
||||
osver.dwMinorVersion == minorVersion &&
|
||||
(buildVersion == 0 ||
|
||||
osver.dwBuildNumber <= buildVersion)))
|
||||
matched = TRUE;
|
||||
break;
|
||||
|
||||
case VERSION_EQUAL:
|
||||
if(osver.dwMajorVersion == majorVersion &&
|
||||
osver.dwMinorVersion == minorVersion &&
|
||||
(buildVersion == 0 ||
|
||||
osver.dwBuildNumber == buildVersion))
|
||||
matched = TRUE;
|
||||
break;
|
||||
|
||||
case VERSION_GREATER_THAN_EQUAL:
|
||||
if(osver.dwMajorVersion > majorVersion ||
|
||||
(osver.dwMajorVersion == majorVersion &&
|
||||
osver.dwMinorVersion > minorVersion) ||
|
||||
(osver.dwMajorVersion == majorVersion &&
|
||||
osver.dwMinorVersion == minorVersion &&
|
||||
(buildVersion == 0 ||
|
||||
osver.dwBuildNumber >= buildVersion)))
|
||||
matched = TRUE;
|
||||
break;
|
||||
|
||||
case VERSION_GREATER_THAN:
|
||||
if(osver.dwMajorVersion > majorVersion ||
|
||||
(osver.dwMajorVersion == majorVersion &&
|
||||
osver.dwMinorVersion > minorVersion) ||
|
||||
(buildVersion != 0 &&
|
||||
(osver.dwMajorVersion == majorVersion &&
|
||||
osver.dwMinorVersion == minorVersion &&
|
||||
osver.dwBuildNumber > buildVersion)))
|
||||
matched = TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Verify the platform identifier (if necessary) */
|
||||
if(matched) {
|
||||
switch(platform) {
|
||||
case PLATFORM_WINDOWS:
|
||||
if(osver.dwPlatformId != VER_PLATFORM_WIN32_WINDOWS)
|
||||
matched = FALSE;
|
||||
break;
|
||||
|
||||
case PLATFORM_WINNT:
|
||||
if(osver.dwPlatformId != VER_PLATFORM_WIN32_NT)
|
||||
matched = FALSE;
|
||||
break;
|
||||
|
||||
default: /* like platform == PLATFORM_DONT_CARE */
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
ULONGLONG cm = 0;
|
||||
struct OUR_OSVERSIONINFOEXW osver;
|
||||
|
||||
@ -481,27 +481,17 @@ static int cf_ngtcp2_handshake_completed(ngtcp2_conn *tconn, void *user_data)
|
||||
* the handshake time when we really did connect */
|
||||
if(ctx->use_earlydata)
|
||||
Curl_pgrsTimeWas(data, TIMER_APPCONNECT, ctx->handshake_at);
|
||||
if(ctx->use_earlydata) {
|
||||
#ifdef USE_GNUTLS
|
||||
if(ctx->use_earlydata) {
|
||||
int flags = gnutls_session_get_flags(ctx->tls.gtls.session);
|
||||
ctx->earlydata_accepted = !!(flags & GNUTLS_SFLAGS_EARLY_DATA);
|
||||
#endif
|
||||
#ifdef USE_WOLFSSL
|
||||
#ifdef WOLFSSL_EARLY_DATA
|
||||
ctx->earlydata_accepted =
|
||||
(wolfSSL_get_early_data_status(ctx->tls.wssl.ssl) !=
|
||||
WOLFSSL_EARLY_DATA_REJECTED);
|
||||
#else
|
||||
DEBUGASSERT(0); /* should not come here if ED is disabled. */
|
||||
ctx->earlydata_accepted = FALSE;
|
||||
#endif /* WOLFSSL_EARLY_DATA */
|
||||
#endif
|
||||
CURL_TRC_CF(data, cf, "server did%s accept %zu bytes of early data",
|
||||
ctx->earlydata_accepted ? "" : " not", ctx->earlydata_skip);
|
||||
Curl_pgrsEarlyData(data, ctx->earlydata_accepted ?
|
||||
(curl_off_t)ctx->earlydata_skip :
|
||||
-(curl_off_t)ctx->earlydata_skip);
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -2267,23 +2257,8 @@ static int wssl_quic_new_session_cb(WOLFSSL *ssl, WOLFSSL_SESSION *session)
|
||||
struct Curl_easy *data = CF_DATA_CURRENT(cf);
|
||||
DEBUGASSERT(data);
|
||||
if(data && ctx) {
|
||||
ngtcp2_ssize tplen;
|
||||
uint8_t tpbuf[256];
|
||||
unsigned char *quic_tp = NULL;
|
||||
size_t quic_tp_len = 0;
|
||||
|
||||
tplen = ngtcp2_conn_encode_0rtt_transport_params(ctx->qconn, tpbuf,
|
||||
sizeof(tpbuf));
|
||||
if(tplen < 0)
|
||||
CURL_TRC_CF(data, cf, "error encoding 0RTT transport data: %s",
|
||||
ngtcp2_strerror((int)tplen));
|
||||
else {
|
||||
quic_tp = (unsigned char *)tpbuf;
|
||||
quic_tp_len = (size_t)tplen;
|
||||
}
|
||||
(void)Curl_wssl_cache_session(cf, data, ctx->peer.scache_key,
|
||||
session, wolfSSL_version(ssl),
|
||||
"h3", quic_tp, quic_tp_len);
|
||||
session, wolfSSL_version(ssl), "h3");
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
@ -2333,13 +2308,13 @@ static CURLcode cf_ngtcp2_tls_ctx_setup(struct Curl_cfilter *cf,
|
||||
}
|
||||
|
||||
#elif defined(USE_WOLFSSL)
|
||||
if(ngtcp2_crypto_wolfssl_configure_client_context(ctx->wssl.ssl_ctx) != 0) {
|
||||
if(ngtcp2_crypto_wolfssl_configure_client_context(ctx->wssl.ctx) != 0) {
|
||||
failf(data, "ngtcp2_crypto_wolfssl_configure_client_context failed");
|
||||
return CURLE_FAILED_INIT;
|
||||
}
|
||||
if(ssl_config->primary.cache_session) {
|
||||
/* Register to get notified when a new session is received */
|
||||
wolfSSL_CTX_sess_set_new_cb(ctx->wssl.ssl_ctx, wssl_quic_new_session_cb);
|
||||
wolfSSL_CTX_sess_set_new_cb(ctx->wssl.ctx, wssl_quic_new_session_cb);
|
||||
}
|
||||
#endif
|
||||
return CURLE_OK;
|
||||
@ -2347,7 +2322,6 @@ static CURLcode cf_ngtcp2_tls_ctx_setup(struct Curl_cfilter *cf,
|
||||
|
||||
static CURLcode cf_ngtcp2_on_session_reuse(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data,
|
||||
struct alpn_spec *alpns,
|
||||
struct Curl_ssl_session *scs,
|
||||
bool *do_early_data)
|
||||
{
|
||||
@ -2358,19 +2332,10 @@ static CURLcode cf_ngtcp2_on_session_reuse(struct Curl_cfilter *cf,
|
||||
#ifdef USE_GNUTLS
|
||||
ctx->earlydata_max =
|
||||
gnutls_record_get_max_early_data_size(ctx->tls.gtls.session);
|
||||
#endif
|
||||
#ifdef USE_WOLFSSL
|
||||
#ifdef WOLFSSL_EARLY_DATA
|
||||
ctx->earlydata_max = scs->earlydata_max;
|
||||
#else
|
||||
ctx->earlydata_max = 0;
|
||||
#endif /* WOLFSSL_EARLY_DATA */
|
||||
#endif
|
||||
#if defined(USE_GNUTLS) || defined(USE_WOLFSSL)
|
||||
if((!ctx->earlydata_max)) {
|
||||
CURL_TRC_CF(data, cf, "SSL session does not allow earlydata");
|
||||
}
|
||||
else if(!Curl_alpn_contains_proto(alpns, scs->alpn)) {
|
||||
else if(strcmp("h3", scs->alpn)) {
|
||||
CURL_TRC_CF(data, cf, "SSL session from different ALPN, no early data");
|
||||
}
|
||||
else if(!scs->quic_tp || !scs->quic_tp_len) {
|
||||
@ -2398,7 +2363,6 @@ static CURLcode cf_ngtcp2_on_session_reuse(struct Curl_cfilter *cf,
|
||||
(void)data;
|
||||
(void)ctx;
|
||||
(void)scs;
|
||||
(void)alpns;
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
@ -2416,9 +2380,6 @@ static CURLcode cf_connect_start(struct Curl_cfilter *cf,
|
||||
CURLcode result;
|
||||
const struct Curl_sockaddr_ex *sockaddr = NULL;
|
||||
int qfd;
|
||||
static const struct alpn_spec ALPN_SPEC_H3 = {
|
||||
{ "h3", "h3-29" }, 2
|
||||
};
|
||||
|
||||
DEBUGASSERT(ctx->initialized);
|
||||
ctx->dcid.datalen = NGTCP2_MAX_CIDLEN;
|
||||
@ -2462,7 +2423,9 @@ static const struct alpn_spec ALPN_SPEC_H3 = {
|
||||
if(rc)
|
||||
return CURLE_QUIC_CONNECT_ERROR;
|
||||
|
||||
result = Curl_vquic_tls_init(&ctx->tls, cf, data, &ctx->peer, &ALPN_SPEC_H3,
|
||||
#define H3_ALPN "\x2h3\x5h3-29"
|
||||
result = Curl_vquic_tls_init(&ctx->tls, cf, data, &ctx->peer,
|
||||
H3_ALPN, sizeof(H3_ALPN) - 1,
|
||||
cf_ngtcp2_tls_ctx_setup, &ctx->tls,
|
||||
&ctx->conn_ref,
|
||||
cf_ngtcp2_on_session_reuse);
|
||||
@ -2475,7 +2438,7 @@ static const struct alpn_spec ALPN_SPEC_H3 = {
|
||||
#elif defined(USE_GNUTLS)
|
||||
ngtcp2_conn_set_tls_native_handle(ctx->qconn, ctx->tls.gtls.session);
|
||||
#elif defined(USE_WOLFSSL)
|
||||
ngtcp2_conn_set_tls_native_handle(ctx->qconn, ctx->tls.wssl.ssl);
|
||||
ngtcp2_conn_set_tls_native_handle(ctx->qconn, ctx->tls.wssl.handle);
|
||||
#else
|
||||
#error "ngtcp2 TLS backend not defined"
|
||||
#endif
|
||||
|
||||
@ -1163,15 +1163,13 @@ static CURLcode cf_osslq_ctx_start(struct Curl_cfilter *cf,
|
||||
const struct Curl_sockaddr_ex *peer_addr = NULL;
|
||||
BIO *bio = NULL;
|
||||
BIO_ADDR *baddr = NULL;
|
||||
static const struct alpn_spec ALPN_SPEC_H3 = {
|
||||
{ "h3" }, 1
|
||||
};
|
||||
|
||||
DEBUGASSERT(ctx->initialized);
|
||||
|
||||
#define H3_ALPN "\x2h3"
|
||||
result = Curl_vquic_tls_init(&ctx->tls, cf, data, &ctx->peer,
|
||||
&ALPN_SPEC_H3, NULL, NULL, NULL, NULL);
|
||||
H3_ALPN, sizeof(H3_ALPN) - 1,
|
||||
NULL, NULL, NULL, NULL);
|
||||
if(result)
|
||||
goto out;
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user