un-nest curl

This commit is contained in:
2025-08-16 11:22:44 -04:00
parent 77186c88dd
commit 58cabadc44
5586 changed files with 310 additions and 310 deletions

View File

@@ -0,0 +1 @@
# dummy

View File

@@ -0,0 +1,52 @@
#***************************************************************************
# _ _ ____ _
# 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
#
###########################################################################
# Get BUNDLE, FIRST_C, FIRST_H, CURLX_C, TESTS_C variables
curl_transform_makefile_inc("Makefile.inc" "${CMAKE_CURRENT_BINARY_DIR}/Makefile.inc.cmake")
include("${CMAKE_CURRENT_BINARY_DIR}/Makefile.inc.cmake")
if(LIB_SELECTED STREQUAL LIB_STATIC)
set(CURLX_C "") # Already exported from the libcurl static build. Skip them.
endif()
add_custom_command(OUTPUT "${BUNDLE}.c"
COMMAND ${PERL_EXECUTABLE} "${PROJECT_SOURCE_DIR}/scripts/mk-unity.pl"
--include ${CURLX_C} --test ${TESTS_C} > "${BUNDLE}.c"
DEPENDS
"${PROJECT_SOURCE_DIR}/scripts/mk-unity.pl" "${CMAKE_CURRENT_SOURCE_DIR}/Makefile.inc"
${FIRST_C} ${CURLX_C} ${TESTS_C}
VERBATIM)
add_executable(${BUNDLE} EXCLUDE_FROM_ALL "${BUNDLE}.c")
add_dependencies(testdeps ${BUNDLE})
target_link_libraries(${BUNDLE} ${LIB_SELECTED} ${CURL_LIBS})
target_include_directories(${BUNDLE} PRIVATE
"${PROJECT_BINARY_DIR}/lib" # for "curl_config.h"
"${PROJECT_SOURCE_DIR}/lib" # for "curl_setup.h", curlx
"${CMAKE_CURRENT_SOURCE_DIR}" # for the generated bundle source to find included test sources
)
set_property(TARGET ${BUNDLE} APPEND PROPERTY COMPILE_DEFINITIONS "CURL_NO_OLDIES")
set_target_properties(${BUNDLE} PROPERTIES OUTPUT_NAME "${BUNDLE}" PROJECT_LABEL "Test ${BUNDLE}" UNITY_BUILD OFF C_CLANG_TIDY "")
curl_add_clang_tidy_test_target("${BUNDLE}-clang-tidy" ${BUNDLE} ${FIRST_C} ${TESTS_C})

View File

@@ -0,0 +1,777 @@
# Makefile.in generated by automake 1.16.5 from Makefile.am.
# tests/client/Makefile. Generated from Makefile.in by configure.
# Copyright (C) 1994-2021 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
#***************************************************************************
# _ _ ____ _
# 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
#
###########################################################################
# Shared between CMakeLists.txt and Makefile.am
am__is_gnu_make = { \
if test -z '$(MAKELEVEL)'; then \
false; \
elif test -n '$(MAKE_HOST)'; then \
true; \
elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
true; \
else \
false; \
fi; \
}
am__make_running_with_option = \
case $${target_option-} in \
?) ;; \
*) echo "am__make_running_with_option: internal error: invalid" \
"target option '$${target_option-}' specified" >&2; \
exit 1;; \
esac; \
has_opt=no; \
sane_makeflags=$$MAKEFLAGS; \
if $(am__is_gnu_make); then \
sane_makeflags=$$MFLAGS; \
else \
case $$MAKEFLAGS in \
*\\[\ \ ]*) \
bs=\\; \
sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
| sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
esac; \
fi; \
skip_next=no; \
strip_trailopt () \
{ \
flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
}; \
for flg in $$sane_makeflags; do \
test $$skip_next = yes && { skip_next=no; continue; }; \
case $$flg in \
*=*|--*) continue;; \
-*I) strip_trailopt 'I'; skip_next=yes;; \
-*I?*) strip_trailopt 'I';; \
-*O) strip_trailopt 'O'; skip_next=yes;; \
-*O?*) strip_trailopt 'O';; \
-*l) strip_trailopt 'l'; skip_next=yes;; \
-*l?*) strip_trailopt 'l';; \
-[dEDm]) skip_next=yes;; \
-[JT]) skip_next=yes;; \
esac; \
case $$flg in \
*$$target_option*) has_opt=yes; break;; \
esac; \
done; \
test $$has_opt = yes
am__make_dryrun = (target_option=n; $(am__make_running_with_option))
am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
pkgdatadir = $(datadir)/curl
pkgincludedir = $(includedir)/curl
pkglibdir = $(libdir)/curl
pkglibexecdir = $(libexecdir)/curl
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
install_sh_DATA = $(install_sh) -c -m 644
install_sh_PROGRAM = $(install_sh) -c
install_sh_SCRIPT = $(install_sh) -c
INSTALL_HEADER = $(INSTALL_DATA)
transform = $(program_transform_name)
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
build_triplet = x86_64-pc-linux-gnu
host_triplet = x86_64-pc-linux-gnu
am__append_1 = -DCURL_STATICLIB
noinst_PROGRAMS = $(am__EXEEXT_1)
subdir = tests/client
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/curl-amissl.m4 \
$(top_srcdir)/m4/curl-compilers.m4 \
$(top_srcdir)/m4/curl-confopts.m4 \
$(top_srcdir)/m4/curl-functions.m4 \
$(top_srcdir)/m4/curl-gnutls.m4 \
$(top_srcdir)/m4/curl-mbedtls.m4 \
$(top_srcdir)/m4/curl-openssl.m4 \
$(top_srcdir)/m4/curl-override.m4 \
$(top_srcdir)/m4/curl-reentrant.m4 \
$(top_srcdir)/m4/curl-rustls.m4 \
$(top_srcdir)/m4/curl-schannel.m4 \
$(top_srcdir)/m4/curl-sysconfig.m4 \
$(top_srcdir)/m4/curl-wolfssl.m4 $(top_srcdir)/m4/libtool.m4 \
$(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
$(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
$(top_srcdir)/m4/xc-am-iface.m4 \
$(top_srcdir)/m4/xc-cc-check.m4 \
$(top_srcdir)/m4/xc-lt-iface.m4 \
$(top_srcdir)/m4/xc-val-flgs.m4 \
$(top_srcdir)/m4/zz40-xc-ovr.m4 \
$(top_srcdir)/m4/zz50-xc-ovr.m4 \
$(top_srcdir)/m4/zz60-xc-ovr.m4 $(top_srcdir)/acinclude.m4 \
$(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
mkinstalldirs = $(install_sh) -d
CONFIG_HEADER = $(top_builddir)/lib/curl_config.h
CONFIG_CLEAN_FILES =
CONFIG_CLEAN_VPATH_FILES =
am__EXEEXT_1 = clients$(EXEEXT)
PROGRAMS = $(noinst_PROGRAMS)
clients_SOURCES = clients.c
clients_OBJECTS = clients.$(OBJEXT)
clients_LDADD = $(LDADD)
clients_DEPENDENCIES = $(top_builddir)/lib/libcurl.la
AM_V_lt = $(am__v_lt_$(V))
am__v_lt_ = $(am__v_lt_$(AM_DEFAULT_VERBOSITY))
am__v_lt_0 = --silent
am__v_lt_1 =
AM_V_P = $(am__v_P_$(V))
am__v_P_ = $(am__v_P_$(AM_DEFAULT_VERBOSITY))
am__v_P_0 = false
am__v_P_1 = :
AM_V_GEN = $(am__v_GEN_$(V))
am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY))
am__v_GEN_0 = @echo " GEN " $@;
am__v_GEN_1 =
AM_V_at = $(am__v_at_$(V))
am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY))
am__v_at_0 = @
am__v_at_1 =
DEFAULT_INCLUDES =
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__maybe_remake_depfiles = depfiles
am__depfiles_remade = ./$(DEPDIR)/clients.Po
am__mv = mv -f
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
$(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
$(AM_CFLAGS) $(CFLAGS)
AM_V_CC = $(am__v_CC_$(V))
am__v_CC_ = $(am__v_CC_$(AM_DEFAULT_VERBOSITY))
am__v_CC_0 = @echo " CC " $@;
am__v_CC_1 =
CCLD = $(CC)
LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
$(AM_LDFLAGS) $(LDFLAGS) -o $@
AM_V_CCLD = $(am__v_CCLD_$(V))
am__v_CCLD_ = $(am__v_CCLD_$(AM_DEFAULT_VERBOSITY))
am__v_CCLD_0 = @echo " CCLD " $@;
am__v_CCLD_1 =
SOURCES = clients.c
DIST_SOURCES = clients.c
am__can_run_installinfo = \
case $$AM_UPDATE_INFO_DIR in \
n|no|NO) false;; \
*) (install-info --version) >/dev/null 2>&1;; \
esac
am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
# Read a list of newline-separated strings from the standard input,
# and print each of them once, without duplicates. Input order is
# *not* preserved.
am__uniquify_input = $(AWK) '\
BEGIN { nonempty = 0; } \
{ items[$$0] = 1; nonempty = 1; } \
END { if (nonempty) { for (i in items) print i; }; } \
'
# Make sure the list of sources is unique. This is necessary because,
# e.g., the same source file might be shared among _SOURCES variables
# for different programs/libraries.
am__define_uniq_tagged_files = \
list='$(am__tagged_files)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | $(am__uniquify_input)`
am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.inc \
$(top_srcdir)/depcomp
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
ACLOCAL = ${SHELL} '/home/teknari/Sync/Programming/VibeCoding/nostr_core_lib/curl-8.15.0/missing' aclocal-1.16
AMTAR = $${TAR-tar}
AM_DEFAULT_VERBOSITY = 0
APXS =
AR = /usr/bin/ar
AR_FLAGS = cr
AS = as
AUTOCONF = ${SHELL} '/home/teknari/Sync/Programming/VibeCoding/nostr_core_lib/curl-8.15.0/missing' autoconf
AUTOHEADER = ${SHELL} '/home/teknari/Sync/Programming/VibeCoding/nostr_core_lib/curl-8.15.0/missing' autoheader
AUTOMAKE = ${SHELL} '/home/teknari/Sync/Programming/VibeCoding/nostr_core_lib/curl-8.15.0/missing' automake-1.16
AWK = mawk
BLANK_AT_MAKETIME =
CADDY =
CC = gcc
CCDEPMODE = depmode=gcc3
CFLAGS = -Werror-implicit-function-declaration -O2 -Wno-system-headers
CFLAG_CURL_SYMBOL_HIDING = -fvisibility=hidden
CONFIGURE_OPTIONS = " '--disable-shared' '--enable-static' '--with-openssl=/home/teknari/Sync/Programming/VibeCoding/nostr_core_lib/curl-8.15.0/../openssl-install' '--without-libpsl' '--without-brotli' '--disable-ldap' '--disable-ldaps' '--disable-rtsp' '--disable-proxy' '--disable-dict' '--disable-telnet' '--disable-tftp' '--disable-pop3' '--disable-imap' '--disable-smb' '--disable-smtp' '--disable-gopher' '--disable-manual' '--prefix=/home/teknari/Sync/Programming/VibeCoding/nostr_core_lib/curl-8.15.0/../curl-install'"
CPP = gcc -E
CPPFLAGS = -D_GNU_SOURCE -isystem /home/teknari/Sync/Programming/VibeCoding/nostr_core_lib/openssl-install/include
CSCOPE = cscope
CTAGS = ctags
CURLVERSION = 8.15.0
CURL_CA_BUNDLE = /etc/ssl/certs/ca-certificates.crt
CURL_CA_EMBED =
CURL_CFLAG_EXTRAS =
CURL_CPP = gcc -E -D_GNU_SOURCE -isystem /home/teknari/Sync/Programming/VibeCoding/nostr_core_lib/openssl-install/include
CURL_LIBCURL_VERSIONED_SYMBOLS_PREFIX =
CURL_LIBCURL_VERSIONED_SYMBOLS_SONAME = 4
CURL_NETWORK_AND_TIME_LIBS =
CYGPATH_W = echo
DEFS = -DHAVE_CONFIG_H
DEPDIR = .deps
DLLTOOL = false
DSYMUTIL =
DUMPBIN =
ECHO_C =
ECHO_N = -n
ECHO_T =
EGREP = /usr/bin/grep -E
ENABLE_SHARED = no
ENABLE_STATIC = yes
ETAGS = etags
EXEEXT =
FGREP = /usr/bin/grep -F
FILECMD = file
FISH_FUNCTIONS_DIR =
GCOV =
GREP = /usr/bin/grep
HAVE_LIBZ = 1
HTTPD =
HTTPD_NGHTTPX =
INSTALL = /usr/bin/install -c
INSTALL_DATA = ${INSTALL} -m 644
INSTALL_PROGRAM = ${INSTALL}
INSTALL_SCRIPT = ${INSTALL}
INSTALL_STRIP_PROGRAM = $(install_sh) -c -s
LCOV =
LD = /usr/bin/ld -m elf_x86_64
LDFLAGS = -L/home/teknari/Sync/Programming/VibeCoding/nostr_core_lib/openssl-install/lib64
LIBCURL_PC_CFLAGS = -DCURL_STATICLIB
LIBCURL_PC_CFLAGS_PRIVATE = -DCURL_STATICLIB
LIBCURL_PC_LDFLAGS_PRIVATE = -L/home/teknari/Sync/Programming/VibeCoding/nostr_core_lib/openssl-install/lib64
LIBCURL_PC_LIBS = -lssl -lcrypto -lssl -lcrypto -lz
LIBCURL_PC_LIBS_PRIVATE = -lssl -lcrypto -lssl -lcrypto -lz
LIBCURL_PC_REQUIRES = zlib,openssl
LIBCURL_PC_REQUIRES_PRIVATE = zlib,openssl
LIBOBJS =
# Prevent LIBS from being used for all link targets
LIBS = $(BLANK_AT_MAKETIME)
LIBTOOL = $(SHELL) $(top_builddir)/libtool
LIPO =
LN_S = ln -s
LTLIBOBJS =
LT_SYS_LIBRARY_PATH =
MAINT = #
MAKEINFO = ${SHELL} '/home/teknari/Sync/Programming/VibeCoding/nostr_core_lib/curl-8.15.0/missing' makeinfo
MANIFEST_TOOL = :
MKDIR_P = /usr/bin/mkdir -p
NM = /usr/bin/nm -B
NMEDIT =
OBJDUMP = objdump
OBJEXT = o
OTOOL =
OTOOL64 =
PACKAGE = curl
PACKAGE_BUGREPORT = a suitable curl mailing list: https://curl.se/mail/
PACKAGE_NAME = curl
PACKAGE_STRING = curl -
PACKAGE_TARNAME = curl
PACKAGE_URL =
PACKAGE_VERSION = -
PATH_SEPARATOR = :
PERL = /usr/bin/perl
PKGCONFIG = no
RANLIB = ranlib
RC =
SED = /usr/bin/sed
SET_MAKE =
SHELL = /bin/bash
SSL_BACKENDS = OpenSSL v3+
STRIP = strip
SUPPORT_FEATURES = alt-svc AsynchDNS HSTS IPv6 Largefile libz NTLM SSL threadsafe TLS-SRP UnixSockets
SUPPORT_PROTOCOLS = FILE FTP FTPS HTTP HTTPS IPFS IPNS MQTT WS WSS
TEST_NGHTTPX = nghttpx
VERSION = -
VERSIONNUM = 080f00
VSFTPD =
ZLIB_LIBS = -lz
ZSH_FUNCTIONS_DIR =
abs_builddir = /home/teknari/Sync/Programming/VibeCoding/nostr_core_lib/curl-8.15.0/tests/client
abs_srcdir = /home/teknari/Sync/Programming/VibeCoding/nostr_core_lib/curl-8.15.0/tests/client
abs_top_builddir = /home/teknari/Sync/Programming/VibeCoding/nostr_core_lib/curl-8.15.0
abs_top_srcdir = /home/teknari/Sync/Programming/VibeCoding/nostr_core_lib/curl-8.15.0
ac_ct_AR =
ac_ct_CC = gcc
ac_ct_DUMPBIN =
am__include = include
am__leading_dot = .
am__quote =
am__tar = $${TAR-tar} chof - "$$tardir"
am__untar = $${TAR-tar} xf -
bindir = ${exec_prefix}/bin
build = x86_64-pc-linux-gnu
build_alias =
build_cpu = x86_64
build_os = linux-gnu
build_vendor = pc
builddir = .
datadir = ${datarootdir}
datarootdir = ${prefix}/share
docdir = ${datarootdir}/doc/${PACKAGE_TARNAME}
dvidir = ${docdir}
exec_prefix = ${prefix}
host = x86_64-pc-linux-gnu
host_alias =
host_cpu = x86_64
host_os = linux-gnu
host_vendor = pc
htmldir = ${docdir}
includedir = ${prefix}/include
infodir = ${datarootdir}/info
install_sh = ${SHELL} /home/teknari/Sync/Programming/VibeCoding/nostr_core_lib/curl-8.15.0/install-sh
libdir = ${exec_prefix}/lib
libexecdir = ${exec_prefix}/libexec
libext = a
localedir = ${datarootdir}/locale
localstatedir = ${prefix}/var
mandir = ${datarootdir}/man
mkdir_p = $(MKDIR_P)
oldincludedir = /usr/include
pdfdir = ${docdir}
prefix = /home/teknari/Sync/Programming/VibeCoding/nostr_core_lib/curl-8.15.0/../curl-install
program_transform_name = s,x,x,
psdir = ${docdir}
runstatedir = ${localstatedir}/run
sbindir = ${exec_prefix}/sbin
sharedstatedir = ${prefix}/com
srcdir = .
sysconfdir = ${prefix}/etc
target_alias =
top_build_prefix = ../../
top_builddir = ../..
top_srcdir = ../..
#***************************************************************************
# _ _ ____ _
# 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
#
###########################################################################
AUTOMAKE_OPTIONS = foreign nostdinc
# Specify our include paths here, and do it relative to $(top_srcdir) and
# $(top_builddir), to ensure that these paths which belong to the library
# being currently built and tested are searched before the library which
# might possibly already be installed in the system.
#
# $(top_srcdir)/include is for libcurl's external include files
# $(top_builddir)/lib is for libcurl's generated lib/curl_config.h file
# $(top_srcdir)/lib for libcurl's lib/curl_setup.h and other "borrowed" files
# $(srcdir) for the generated bundle source to find included test sources
AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_builddir)/lib \
-I$(top_srcdir)/lib -I$(srcdir) $(am__append_1) \
-DCURL_NO_OLDIES
BUNDLE = clients
# Files referenced from the bundle source
FIRST_C = first.c
FIRST_H = first.h
CURLX_C = \
../../lib/curlx/multibyte.c \
../../lib/curlx/timediff.c \
../../lib/curlx/wait.c
# All test clients
TESTS_C = \
h2_pausing.c \
h2_serverpush.c \
h2_upgrade_extreme.c \
hx_download.c \
hx_upload.c \
tls_session_reuse.c \
upload_pausing.c \
ws_data.c \
ws_pingpong.c
# Get BUNDLE, FIRST_C, FIRST_H, CURLX_C, TESTS_C variables
EXTRA_DIST = CMakeLists.txt $(FIRST_C) $(FIRST_H) $(TESTS_C)
# These are part of the libcurl static lib. Add them here when linking shared.
#curlx_c_lib = $(CURLX_C)
curlx_c_lib =
LDADD = $(top_builddir)/lib/libcurl.la
CLEANFILES = $(BUNDLE).c
CHECKSRC = $(CS_$(V))
CS_0 = @echo " RUN " $@;
CS_1 =
CS_ = $(CS_0)
all: all-am
.SUFFIXES:
.SUFFIXES: .c .lo .o .obj
$(srcdir)/Makefile.in: # $(srcdir)/Makefile.am $(srcdir)/Makefile.inc $(am__configure_deps)
@for dep in $?; do \
case '$(am__configure_deps)' in \
*$$dep*) \
( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
&& { if test -f $@; then exit 0; else break; fi; }; \
exit 1;; \
esac; \
done; \
echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign tests/client/Makefile'; \
$(am__cd) $(top_srcdir) && \
$(AUTOMAKE) --foreign tests/client/Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
*config.status*) \
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
*) \
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
esac;
$(srcdir)/Makefile.inc $(am__empty):
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(top_srcdir)/configure: # $(am__configure_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(ACLOCAL_M4): # $(am__aclocal_m4_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(am__aclocal_m4_deps):
clean-noinstPROGRAMS:
@list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \
echo " rm -f" $$list; \
rm -f $$list || exit $$?; \
test -n "$(EXEEXT)" || exit 0; \
list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
echo " rm -f" $$list; \
rm -f $$list
clients$(EXEEXT): $(clients_OBJECTS) $(clients_DEPENDENCIES) $(EXTRA_clients_DEPENDENCIES)
@rm -f clients$(EXEEXT)
$(AM_V_CCLD)$(LINK) $(clients_OBJECTS) $(clients_LDADD) $(LIBS)
mostlyclean-compile:
-rm -f *.$(OBJEXT)
distclean-compile:
-rm -f *.tab.c
include ./$(DEPDIR)/clients.Po # am--include-marker
$(am__depfiles_remade):
@$(MKDIR_P) $(@D)
@echo '# dummy' >$@-t && $(am__mv) $@-t $@
am--depfiles: $(am__depfiles_remade)
.c.o:
$(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
$(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
$(am__mv) $$depbase.Tpo $$depbase.Po
# $(AM_V_CC)source='$<' object='$@' libtool=no \
# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
# $(AM_V_CC_no)$(COMPILE) -c -o $@ $<
.c.obj:
$(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\
$(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\
$(am__mv) $$depbase.Tpo $$depbase.Po
# $(AM_V_CC)source='$<' object='$@' libtool=no \
# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
# $(AM_V_CC_no)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
.c.lo:
$(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
$(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
$(am__mv) $$depbase.Tpo $$depbase.Plo
# $(AM_V_CC)source='$<' object='$@' libtool=yes \
# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
# $(AM_V_CC_no)$(LTCOMPILE) -c -o $@ $<
mostlyclean-libtool:
-rm -f *.lo
clean-libtool:
-rm -rf .libs _libs
ID: $(am__tagged_files)
$(am__define_uniq_tagged_files); mkid -fID $$unique
tags: tags-am
TAGS: tags
tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
set x; \
here=`pwd`; \
$(am__define_uniq_tagged_files); \
shift; \
if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
test -n "$$unique" || unique=$$empty_fix; \
if test $$# -gt 0; then \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
"$$@" $$unique; \
else \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
$$unique; \
fi; \
fi
ctags: ctags-am
CTAGS: ctags
ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
$(am__define_uniq_tagged_files); \
test -z "$(CTAGS_ARGS)$$unique" \
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
$$unique
GTAGS:
here=`$(am__cd) $(top_builddir) && pwd` \
&& $(am__cd) $(top_srcdir) \
&& gtags -i $(GTAGS_ARGS) "$$here"
cscopelist: cscopelist-am
cscopelist-am: $(am__tagged_files)
list='$(am__tagged_files)'; \
case "$(srcdir)" in \
[\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
*) sdir=$(subdir)/$(srcdir) ;; \
esac; \
for i in $$list; do \
if test -f "$$i"; then \
echo "$(subdir)/$$i"; \
else \
echo "$$sdir/$$i"; \
fi; \
done >> $(top_builddir)/cscope.files
distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
distdir: $(BUILT_SOURCES)
$(MAKE) $(AM_MAKEFLAGS) distdir-am
distdir-am: $(DISTFILES)
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
list='$(DISTFILES)'; \
dist_files=`for file in $$list; do echo $$file; done | \
sed -e "s|^$$srcdirstrip/||;t" \
-e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
case $$dist_files in \
*/*) $(MKDIR_P) `echo "$$dist_files" | \
sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
sort -u` ;; \
esac; \
for file in $$dist_files; do \
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
if test -d $$d/$$file; then \
dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
if test -d "$(distdir)/$$file"; then \
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
fi; \
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
fi; \
cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
else \
test -f "$(distdir)/$$file" \
|| cp -p $$d/$$file "$(distdir)/$$file" \
|| exit 1; \
fi; \
done
check-am: all-am
check: check-am
#all-local:
all-am: Makefile $(PROGRAMS) all-local
installdirs:
install: install-am
install-exec: install-exec-am
install-data: install-data-am
uninstall: uninstall-am
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
installcheck: installcheck-am
install-strip:
if test -z '$(STRIP)'; then \
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
install; \
else \
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
"INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
fi
mostlyclean-generic:
clean-generic:
-test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
distclean-generic:
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
clean: clean-am
clean-am: clean-generic clean-libtool clean-local clean-noinstPROGRAMS \
mostlyclean-am
distclean: distclean-am
-rm -f ./$(DEPDIR)/clients.Po
-rm -f Makefile
distclean-am: clean-am distclean-compile distclean-generic \
distclean-tags
dvi: dvi-am
dvi-am:
html: html-am
html-am:
info: info-am
info-am:
install-data-am:
install-dvi: install-dvi-am
install-dvi-am:
install-exec-am:
install-html: install-html-am
install-html-am:
install-info: install-info-am
install-info-am:
install-man:
install-pdf: install-pdf-am
install-pdf-am:
install-ps: install-ps-am
install-ps-am:
installcheck-am:
maintainer-clean: maintainer-clean-am
-rm -f ./$(DEPDIR)/clients.Po
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
mostlyclean: mostlyclean-am
mostlyclean-am: mostlyclean-compile mostlyclean-generic \
mostlyclean-libtool
pdf: pdf-am
pdf-am:
ps: ps-am
ps-am:
uninstall-am:
.MAKE: install-am install-strip
.PHONY: CTAGS GTAGS TAGS all all-am all-local am--depfiles check \
check-am clean clean-generic clean-libtool clean-local \
clean-noinstPROGRAMS cscopelist-am ctags ctags-am distclean \
distclean-compile distclean-generic distclean-libtool \
distclean-tags distdir dvi dvi-am html html-am info info-am \
install install-am install-data install-data-am install-dvi \
install-dvi-am install-exec install-exec-am install-html \
install-html-am install-info install-info-am install-man \
install-pdf install-pdf-am install-ps install-ps-am \
install-strip installcheck installcheck-am installdirs \
maintainer-clean maintainer-clean-generic mostlyclean \
mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
pdf pdf-am ps ps-am tags tags-am uninstall uninstall-am
.PRECIOUS: Makefile
$(BUNDLE).c: $(top_srcdir)/scripts/mk-unity.pl Makefile.inc $(FIRST_C) $(curlx_c_lib) $(TESTS_C)
/usr/bin/perl $(top_srcdir)/scripts/mk-unity.pl --include $(curlx_c_lib) --test $(TESTS_C) > $(BUNDLE).c
# ignore generated C files since they play by slightly different rules!
checksrc:
$(CHECKSRC)(/usr/bin/perl $(top_srcdir)/scripts/checksrc.pl -D$(srcdir) \
-W$(srcdir)/$(BUNDLE).c \
$(srcdir)/*.[ch])
all-local: checksrc
clean-local:
rm -f $(BUNDLE)
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:

View File

@@ -0,0 +1,85 @@
#***************************************************************************
# _ _ ____ _
# 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
#
###########################################################################
AUTOMAKE_OPTIONS = foreign nostdinc
# Specify our include paths here, and do it relative to $(top_srcdir) and
# $(top_builddir), to ensure that these paths which belong to the library
# being currently built and tested are searched before the library which
# might possibly already be installed in the system.
#
# $(top_srcdir)/include is for libcurl's external include files
# $(top_builddir)/lib is for libcurl's generated lib/curl_config.h file
# $(top_srcdir)/lib for libcurl's lib/curl_setup.h and other "borrowed" files
# $(srcdir) for the generated bundle source to find included test sources
AM_CPPFLAGS = -I$(top_srcdir)/include \
-I$(top_builddir)/lib \
-I$(top_srcdir)/lib \
-I$(srcdir)
# Get BUNDLE, FIRST_C, FIRST_H, CURLX_C, TESTS_C variables
include Makefile.inc
EXTRA_DIST = CMakeLists.txt $(FIRST_C) $(FIRST_H) $(TESTS_C)
CFLAGS += @CURL_CFLAG_EXTRAS@
# Prevent LIBS from being used for all link targets
LIBS = $(BLANK_AT_MAKETIME)
if USE_CPPFLAG_CURL_STATICLIB
AM_CPPFLAGS += -DCURL_STATICLIB
endif
AM_CPPFLAGS += -DCURL_NO_OLDIES
if USE_CPPFLAG_CURL_STATICLIB
curlx_c_lib =
else
# These are part of the libcurl static lib. Add them here when linking shared.
curlx_c_lib = $(CURLX_C)
endif
$(BUNDLE).c: $(top_srcdir)/scripts/mk-unity.pl Makefile.inc $(FIRST_C) $(curlx_c_lib) $(TESTS_C)
@PERL@ $(top_srcdir)/scripts/mk-unity.pl --include $(curlx_c_lib) --test $(TESTS_C) > $(BUNDLE).c
noinst_PROGRAMS = $(BUNDLE)
LDADD = $(top_builddir)/lib/libcurl.la
CLEANFILES = $(BUNDLE).c
CHECKSRC = $(CS_$(V))
CS_0 = @echo " RUN " $@;
CS_1 =
CS_ = $(CS_0)
# ignore generated C files since they play by slightly different rules!
checksrc:
$(CHECKSRC)(@PERL@ $(top_srcdir)/scripts/checksrc.pl -D$(srcdir) \
-W$(srcdir)/$(BUNDLE).c \
$(srcdir)/*.[ch])
if NOT_CURL_CI
all-local: checksrc
endif
clean-local:
rm -f $(BUNDLE)

View File

@@ -0,0 +1,777 @@
# Makefile.in generated by automake 1.16.5 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2021 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
@SET_MAKE@
#***************************************************************************
# _ _ ____ _
# 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
#
###########################################################################
# Shared between CMakeLists.txt and Makefile.am
VPATH = @srcdir@
am__is_gnu_make = { \
if test -z '$(MAKELEVEL)'; then \
false; \
elif test -n '$(MAKE_HOST)'; then \
true; \
elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
true; \
else \
false; \
fi; \
}
am__make_running_with_option = \
case $${target_option-} in \
?) ;; \
*) echo "am__make_running_with_option: internal error: invalid" \
"target option '$${target_option-}' specified" >&2; \
exit 1;; \
esac; \
has_opt=no; \
sane_makeflags=$$MAKEFLAGS; \
if $(am__is_gnu_make); then \
sane_makeflags=$$MFLAGS; \
else \
case $$MAKEFLAGS in \
*\\[\ \ ]*) \
bs=\\; \
sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
| sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
esac; \
fi; \
skip_next=no; \
strip_trailopt () \
{ \
flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
}; \
for flg in $$sane_makeflags; do \
test $$skip_next = yes && { skip_next=no; continue; }; \
case $$flg in \
*=*|--*) continue;; \
-*I) strip_trailopt 'I'; skip_next=yes;; \
-*I?*) strip_trailopt 'I';; \
-*O) strip_trailopt 'O'; skip_next=yes;; \
-*O?*) strip_trailopt 'O';; \
-*l) strip_trailopt 'l'; skip_next=yes;; \
-*l?*) strip_trailopt 'l';; \
-[dEDm]) skip_next=yes;; \
-[JT]) skip_next=yes;; \
esac; \
case $$flg in \
*$$target_option*) has_opt=yes; break;; \
esac; \
done; \
test $$has_opt = yes
am__make_dryrun = (target_option=n; $(am__make_running_with_option))
am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
pkgdatadir = $(datadir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkglibexecdir = $(libexecdir)/@PACKAGE@
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
install_sh_DATA = $(install_sh) -c -m 644
install_sh_PROGRAM = $(install_sh) -c
install_sh_SCRIPT = $(install_sh) -c
INSTALL_HEADER = $(INSTALL_DATA)
transform = $(program_transform_name)
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
@USE_CPPFLAG_CURL_STATICLIB_TRUE@am__append_1 = -DCURL_STATICLIB
noinst_PROGRAMS = $(am__EXEEXT_1)
subdir = tests/client
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/curl-amissl.m4 \
$(top_srcdir)/m4/curl-compilers.m4 \
$(top_srcdir)/m4/curl-confopts.m4 \
$(top_srcdir)/m4/curl-functions.m4 \
$(top_srcdir)/m4/curl-gnutls.m4 \
$(top_srcdir)/m4/curl-mbedtls.m4 \
$(top_srcdir)/m4/curl-openssl.m4 \
$(top_srcdir)/m4/curl-override.m4 \
$(top_srcdir)/m4/curl-reentrant.m4 \
$(top_srcdir)/m4/curl-rustls.m4 \
$(top_srcdir)/m4/curl-schannel.m4 \
$(top_srcdir)/m4/curl-sysconfig.m4 \
$(top_srcdir)/m4/curl-wolfssl.m4 $(top_srcdir)/m4/libtool.m4 \
$(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
$(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
$(top_srcdir)/m4/xc-am-iface.m4 \
$(top_srcdir)/m4/xc-cc-check.m4 \
$(top_srcdir)/m4/xc-lt-iface.m4 \
$(top_srcdir)/m4/xc-val-flgs.m4 \
$(top_srcdir)/m4/zz40-xc-ovr.m4 \
$(top_srcdir)/m4/zz50-xc-ovr.m4 \
$(top_srcdir)/m4/zz60-xc-ovr.m4 $(top_srcdir)/acinclude.m4 \
$(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
mkinstalldirs = $(install_sh) -d
CONFIG_HEADER = $(top_builddir)/lib/curl_config.h
CONFIG_CLEAN_FILES =
CONFIG_CLEAN_VPATH_FILES =
am__EXEEXT_1 = clients$(EXEEXT)
PROGRAMS = $(noinst_PROGRAMS)
clients_SOURCES = clients.c
clients_OBJECTS = clients.$(OBJEXT)
clients_LDADD = $(LDADD)
clients_DEPENDENCIES = $(top_builddir)/lib/libcurl.la
AM_V_lt = $(am__v_lt_@AM_V@)
am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
am__v_lt_0 = --silent
am__v_lt_1 =
AM_V_P = $(am__v_P_@AM_V@)
am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
am__v_P_0 = false
am__v_P_1 = :
AM_V_GEN = $(am__v_GEN_@AM_V@)
am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
am__v_GEN_0 = @echo " GEN " $@;
am__v_GEN_1 =
AM_V_at = $(am__v_at_@AM_V@)
am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
am__v_at_0 = @
am__v_at_1 =
DEFAULT_INCLUDES =
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__maybe_remake_depfiles = depfiles
am__depfiles_remade = ./$(DEPDIR)/clients.Po
am__mv = mv -f
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
$(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
$(AM_CFLAGS) $(CFLAGS)
AM_V_CC = $(am__v_CC_@AM_V@)
am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
am__v_CC_0 = @echo " CC " $@;
am__v_CC_1 =
CCLD = $(CC)
LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
$(AM_LDFLAGS) $(LDFLAGS) -o $@
AM_V_CCLD = $(am__v_CCLD_@AM_V@)
am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
am__v_CCLD_0 = @echo " CCLD " $@;
am__v_CCLD_1 =
SOURCES = clients.c
DIST_SOURCES = clients.c
am__can_run_installinfo = \
case $$AM_UPDATE_INFO_DIR in \
n|no|NO) false;; \
*) (install-info --version) >/dev/null 2>&1;; \
esac
am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
# Read a list of newline-separated strings from the standard input,
# and print each of them once, without duplicates. Input order is
# *not* preserved.
am__uniquify_input = $(AWK) '\
BEGIN { nonempty = 0; } \
{ items[$$0] = 1; nonempty = 1; } \
END { if (nonempty) { for (i in items) print i; }; } \
'
# Make sure the list of sources is unique. This is necessary because,
# e.g., the same source file might be shared among _SOURCES variables
# for different programs/libraries.
am__define_uniq_tagged_files = \
list='$(am__tagged_files)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | $(am__uniquify_input)`
am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.inc \
$(top_srcdir)/depcomp
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
ACLOCAL = @ACLOCAL@
AMTAR = @AMTAR@
AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
APXS = @APXS@
AR = @AR@
AR_FLAGS = @AR_FLAGS@
AS = @AS@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
BLANK_AT_MAKETIME = @BLANK_AT_MAKETIME@
CADDY = @CADDY@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@ @CURL_CFLAG_EXTRAS@
CFLAG_CURL_SYMBOL_HIDING = @CFLAG_CURL_SYMBOL_HIDING@
CONFIGURE_OPTIONS = @CONFIGURE_OPTIONS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CSCOPE = @CSCOPE@
CTAGS = @CTAGS@
CURLVERSION = @CURLVERSION@
CURL_CA_BUNDLE = @CURL_CA_BUNDLE@
CURL_CA_EMBED = @CURL_CA_EMBED@
CURL_CFLAG_EXTRAS = @CURL_CFLAG_EXTRAS@
CURL_CPP = @CURL_CPP@
CURL_LIBCURL_VERSIONED_SYMBOLS_PREFIX = @CURL_LIBCURL_VERSIONED_SYMBOLS_PREFIX@
CURL_LIBCURL_VERSIONED_SYMBOLS_SONAME = @CURL_LIBCURL_VERSIONED_SYMBOLS_SONAME@
CURL_NETWORK_AND_TIME_LIBS = @CURL_NETWORK_AND_TIME_LIBS@
CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
DLLTOOL = @DLLTOOL@
DSYMUTIL = @DSYMUTIL@
DUMPBIN = @DUMPBIN@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
ENABLE_SHARED = @ENABLE_SHARED@
ENABLE_STATIC = @ENABLE_STATIC@
ETAGS = @ETAGS@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
FILECMD = @FILECMD@
FISH_FUNCTIONS_DIR = @FISH_FUNCTIONS_DIR@
GCOV = @GCOV@
GREP = @GREP@
HAVE_LIBZ = @HAVE_LIBZ@
HTTPD = @HTTPD@
HTTPD_NGHTTPX = @HTTPD_NGHTTPX@
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
LCOV = @LCOV@
LD = @LD@
LDFLAGS = @LDFLAGS@
LIBCURL_PC_CFLAGS = @LIBCURL_PC_CFLAGS@
LIBCURL_PC_CFLAGS_PRIVATE = @LIBCURL_PC_CFLAGS_PRIVATE@
LIBCURL_PC_LDFLAGS_PRIVATE = @LIBCURL_PC_LDFLAGS_PRIVATE@
LIBCURL_PC_LIBS = @LIBCURL_PC_LIBS@
LIBCURL_PC_LIBS_PRIVATE = @LIBCURL_PC_LIBS_PRIVATE@
LIBCURL_PC_REQUIRES = @LIBCURL_PC_REQUIRES@
LIBCURL_PC_REQUIRES_PRIVATE = @LIBCURL_PC_REQUIRES_PRIVATE@
LIBOBJS = @LIBOBJS@
# Prevent LIBS from being used for all link targets
LIBS = $(BLANK_AT_MAKETIME)
LIBTOOL = @LIBTOOL@
LIPO = @LIPO@
LN_S = @LN_S@
LTLIBOBJS = @LTLIBOBJS@
LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
MAINT = @MAINT@
MAKEINFO = @MAKEINFO@
MANIFEST_TOOL = @MANIFEST_TOOL@
MKDIR_P = @MKDIR_P@
NM = @NM@
NMEDIT = @NMEDIT@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
PACKAGE_NAME = @PACKAGE_NAME@
PACKAGE_STRING = @PACKAGE_STRING@
PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
PERL = @PERL@
PKGCONFIG = @PKGCONFIG@
RANLIB = @RANLIB@
RC = @RC@
SED = @SED@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
SSL_BACKENDS = @SSL_BACKENDS@
STRIP = @STRIP@
SUPPORT_FEATURES = @SUPPORT_FEATURES@
SUPPORT_PROTOCOLS = @SUPPORT_PROTOCOLS@
TEST_NGHTTPX = @TEST_NGHTTPX@
VERSION = @VERSION@
VERSIONNUM = @VERSIONNUM@
VSFTPD = @VSFTPD@
ZLIB_LIBS = @ZLIB_LIBS@
ZSH_FUNCTIONS_DIR = @ZSH_FUNCTIONS_DIR@
abs_builddir = @abs_builddir@
abs_srcdir = @abs_srcdir@
abs_top_builddir = @abs_top_builddir@
abs_top_srcdir = @abs_top_srcdir@
ac_ct_AR = @ac_ct_AR@
ac_ct_CC = @ac_ct_CC@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
am__tar = @am__tar@
am__untar = @am__untar@
bindir = @bindir@
build = @build@
build_alias = @build_alias@
build_cpu = @build_cpu@
build_os = @build_os@
build_vendor = @build_vendor@
builddir = @builddir@
datadir = @datadir@
datarootdir = @datarootdir@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
host = @host@
host_alias = @host_alias@
host_cpu = @host_cpu@
host_os = @host_os@
host_vendor = @host_vendor@
htmldir = @htmldir@
includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
libdir = @libdir@
libexecdir = @libexecdir@
libext = @libext@
localedir = @localedir@
localstatedir = @localstatedir@
mandir = @mandir@
mkdir_p = @mkdir_p@
oldincludedir = @oldincludedir@
pdfdir = @pdfdir@
prefix = @prefix@
program_transform_name = @program_transform_name@
psdir = @psdir@
runstatedir = @runstatedir@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
sysconfdir = @sysconfdir@
target_alias = @target_alias@
top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
#***************************************************************************
# _ _ ____ _
# 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
#
###########################################################################
AUTOMAKE_OPTIONS = foreign nostdinc
# Specify our include paths here, and do it relative to $(top_srcdir) and
# $(top_builddir), to ensure that these paths which belong to the library
# being currently built and tested are searched before the library which
# might possibly already be installed in the system.
#
# $(top_srcdir)/include is for libcurl's external include files
# $(top_builddir)/lib is for libcurl's generated lib/curl_config.h file
# $(top_srcdir)/lib for libcurl's lib/curl_setup.h and other "borrowed" files
# $(srcdir) for the generated bundle source to find included test sources
AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_builddir)/lib \
-I$(top_srcdir)/lib -I$(srcdir) $(am__append_1) \
-DCURL_NO_OLDIES
BUNDLE = clients
# Files referenced from the bundle source
FIRST_C = first.c
FIRST_H = first.h
CURLX_C = \
../../lib/curlx/multibyte.c \
../../lib/curlx/timediff.c \
../../lib/curlx/wait.c
# All test clients
TESTS_C = \
h2_pausing.c \
h2_serverpush.c \
h2_upgrade_extreme.c \
hx_download.c \
hx_upload.c \
tls_session_reuse.c \
upload_pausing.c \
ws_data.c \
ws_pingpong.c
# Get BUNDLE, FIRST_C, FIRST_H, CURLX_C, TESTS_C variables
EXTRA_DIST = CMakeLists.txt $(FIRST_C) $(FIRST_H) $(TESTS_C)
# These are part of the libcurl static lib. Add them here when linking shared.
@USE_CPPFLAG_CURL_STATICLIB_FALSE@curlx_c_lib = $(CURLX_C)
@USE_CPPFLAG_CURL_STATICLIB_TRUE@curlx_c_lib =
LDADD = $(top_builddir)/lib/libcurl.la
CLEANFILES = $(BUNDLE).c
CHECKSRC = $(CS_$(V))
CS_0 = @echo " RUN " $@;
CS_1 =
CS_ = $(CS_0)
all: all-am
.SUFFIXES:
.SUFFIXES: .c .lo .o .obj
$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(srcdir)/Makefile.inc $(am__configure_deps)
@for dep in $?; do \
case '$(am__configure_deps)' in \
*$$dep*) \
( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
&& { if test -f $@; then exit 0; else break; fi; }; \
exit 1;; \
esac; \
done; \
echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign tests/client/Makefile'; \
$(am__cd) $(top_srcdir) && \
$(AUTOMAKE) --foreign tests/client/Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
*config.status*) \
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
*) \
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
esac;
$(srcdir)/Makefile.inc $(am__empty):
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(am__aclocal_m4_deps):
clean-noinstPROGRAMS:
@list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \
echo " rm -f" $$list; \
rm -f $$list || exit $$?; \
test -n "$(EXEEXT)" || exit 0; \
list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
echo " rm -f" $$list; \
rm -f $$list
clients$(EXEEXT): $(clients_OBJECTS) $(clients_DEPENDENCIES) $(EXTRA_clients_DEPENDENCIES)
@rm -f clients$(EXEEXT)
$(AM_V_CCLD)$(LINK) $(clients_OBJECTS) $(clients_LDADD) $(LIBS)
mostlyclean-compile:
-rm -f *.$(OBJEXT)
distclean-compile:
-rm -f *.tab.c
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clients.Po@am__quote@ # am--include-marker
$(am__depfiles_remade):
@$(MKDIR_P) $(@D)
@echo '# dummy' >$@-t && $(am__mv) $@-t $@
am--depfiles: $(am__depfiles_remade)
.c.o:
@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
.c.obj:
@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\
@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\
@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
.c.lo:
@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
mostlyclean-libtool:
-rm -f *.lo
clean-libtool:
-rm -rf .libs _libs
ID: $(am__tagged_files)
$(am__define_uniq_tagged_files); mkid -fID $$unique
tags: tags-am
TAGS: tags
tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
set x; \
here=`pwd`; \
$(am__define_uniq_tagged_files); \
shift; \
if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
test -n "$$unique" || unique=$$empty_fix; \
if test $$# -gt 0; then \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
"$$@" $$unique; \
else \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
$$unique; \
fi; \
fi
ctags: ctags-am
CTAGS: ctags
ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
$(am__define_uniq_tagged_files); \
test -z "$(CTAGS_ARGS)$$unique" \
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
$$unique
GTAGS:
here=`$(am__cd) $(top_builddir) && pwd` \
&& $(am__cd) $(top_srcdir) \
&& gtags -i $(GTAGS_ARGS) "$$here"
cscopelist: cscopelist-am
cscopelist-am: $(am__tagged_files)
list='$(am__tagged_files)'; \
case "$(srcdir)" in \
[\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
*) sdir=$(subdir)/$(srcdir) ;; \
esac; \
for i in $$list; do \
if test -f "$$i"; then \
echo "$(subdir)/$$i"; \
else \
echo "$$sdir/$$i"; \
fi; \
done >> $(top_builddir)/cscope.files
distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
distdir: $(BUILT_SOURCES)
$(MAKE) $(AM_MAKEFLAGS) distdir-am
distdir-am: $(DISTFILES)
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
list='$(DISTFILES)'; \
dist_files=`for file in $$list; do echo $$file; done | \
sed -e "s|^$$srcdirstrip/||;t" \
-e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
case $$dist_files in \
*/*) $(MKDIR_P) `echo "$$dist_files" | \
sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
sort -u` ;; \
esac; \
for file in $$dist_files; do \
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
if test -d $$d/$$file; then \
dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
if test -d "$(distdir)/$$file"; then \
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
fi; \
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
fi; \
cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
else \
test -f "$(distdir)/$$file" \
|| cp -p $$d/$$file "$(distdir)/$$file" \
|| exit 1; \
fi; \
done
check-am: all-am
check: check-am
@NOT_CURL_CI_FALSE@all-local:
all-am: Makefile $(PROGRAMS) all-local
installdirs:
install: install-am
install-exec: install-exec-am
install-data: install-data-am
uninstall: uninstall-am
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
installcheck: installcheck-am
install-strip:
if test -z '$(STRIP)'; then \
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
install; \
else \
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
"INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
fi
mostlyclean-generic:
clean-generic:
-test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
distclean-generic:
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
clean: clean-am
clean-am: clean-generic clean-libtool clean-local clean-noinstPROGRAMS \
mostlyclean-am
distclean: distclean-am
-rm -f ./$(DEPDIR)/clients.Po
-rm -f Makefile
distclean-am: clean-am distclean-compile distclean-generic \
distclean-tags
dvi: dvi-am
dvi-am:
html: html-am
html-am:
info: info-am
info-am:
install-data-am:
install-dvi: install-dvi-am
install-dvi-am:
install-exec-am:
install-html: install-html-am
install-html-am:
install-info: install-info-am
install-info-am:
install-man:
install-pdf: install-pdf-am
install-pdf-am:
install-ps: install-ps-am
install-ps-am:
installcheck-am:
maintainer-clean: maintainer-clean-am
-rm -f ./$(DEPDIR)/clients.Po
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
mostlyclean: mostlyclean-am
mostlyclean-am: mostlyclean-compile mostlyclean-generic \
mostlyclean-libtool
pdf: pdf-am
pdf-am:
ps: ps-am
ps-am:
uninstall-am:
.MAKE: install-am install-strip
.PHONY: CTAGS GTAGS TAGS all all-am all-local am--depfiles check \
check-am clean clean-generic clean-libtool clean-local \
clean-noinstPROGRAMS cscopelist-am ctags ctags-am distclean \
distclean-compile distclean-generic distclean-libtool \
distclean-tags distdir dvi dvi-am html html-am info info-am \
install install-am install-data install-data-am install-dvi \
install-dvi-am install-exec install-exec-am install-html \
install-html-am install-info install-info-am install-man \
install-pdf install-pdf-am install-ps install-ps-am \
install-strip installcheck installcheck-am installdirs \
maintainer-clean maintainer-clean-generic mostlyclean \
mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
pdf pdf-am ps ps-am tags tags-am uninstall uninstall-am
.PRECIOUS: Makefile
$(BUNDLE).c: $(top_srcdir)/scripts/mk-unity.pl Makefile.inc $(FIRST_C) $(curlx_c_lib) $(TESTS_C)
@PERL@ $(top_srcdir)/scripts/mk-unity.pl --include $(curlx_c_lib) --test $(TESTS_C) > $(BUNDLE).c
# ignore generated C files since they play by slightly different rules!
checksrc:
$(CHECKSRC)(@PERL@ $(top_srcdir)/scripts/checksrc.pl -D$(srcdir) \
-W$(srcdir)/$(BUNDLE).c \
$(srcdir)/*.[ch])
@NOT_CURL_CI_TRUE@all-local: checksrc
clean-local:
rm -f $(BUNDLE)
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:

View File

@@ -0,0 +1,47 @@
#***************************************************************************
# _ _ ____ _
# 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
#
###########################################################################
# Shared between CMakeLists.txt and Makefile.am
BUNDLE = clients
# Files referenced from the bundle source
FIRST_C = first.c
FIRST_H = first.h
CURLX_C = \
../../lib/curlx/multibyte.c \
../../lib/curlx/timediff.c \
../../lib/curlx/wait.c
# All test clients
TESTS_C = \
h2_pausing.c \
h2_serverpush.c \
h2_upgrade_extreme.c \
hx_download.c \
hx_upload.c \
tls_session_reuse.c \
upload_pausing.c \
ws_data.c \
ws_pingpong.c

View File

@@ -0,0 +1,52 @@
/***************************************************************************
* _ _ ____ _
* 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 "first.h"
int main(int argc, char **argv)
{
entry_func_t entry_func;
char *entry_name;
size_t tmp;
if(argc < 2) {
curl_mfprintf(stderr, "Pass clientname as first argument\n");
return 1;
}
entry_name = argv[1];
entry_func = NULL;
for(tmp = 0; s_entries[tmp].ptr; ++tmp) {
if(strcmp(entry_name, s_entries[tmp].name) == 0) {
entry_func = s_entries[tmp].ptr;
break;
}
}
if(!entry_func) {
curl_mfprintf(stderr, "Test '%s' not found.\n", entry_name);
return 99;
}
return entry_func(argc - 1, argv + 1);
}

View File

@@ -0,0 +1,266 @@
#ifndef HEADER_CLIENT_FIRST_H
#define HEADER_CLIENT_FIRST_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
#include "curl_setup.h"
typedef int (*entry_func_t)(int, char **);
struct entry_s {
const char *name;
entry_func_t ptr;
};
extern const struct entry_s s_entries[];
#include <curl/curl.h>
#include <curlx/curlx.h>
#define ERR() \
do { \
curl_mfprintf(stderr, "something unexpected went wrong - bailing out!\n");\
return 2; \
} while(0)
static void log_line_start(FILE *log, const char *idsbuf, curl_infotype type)
{
/*
* This is the trace look that is similar to what libcurl makes on its
* own.
*/
static const char * const s_infotype[] = {
"* ", "< ", "> ", "{ ", "} ", "{ ", "} "
};
if(idsbuf && *idsbuf)
curl_mfprintf(log, "%s%s", idsbuf, s_infotype[type]);
else
fputs(s_infotype[type], log);
}
#define TRC_IDS_FORMAT_IDS_1 "[%" CURL_FORMAT_CURL_OFF_T "-x] "
#define TRC_IDS_FORMAT_IDS_2 "[%" CURL_FORMAT_CURL_OFF_T "-%" \
CURL_FORMAT_CURL_OFF_T "] "
/*
** callback for CURLOPT_DEBUGFUNCTION
*/
static int debug_cb(CURL *handle, curl_infotype type,
char *data, size_t size, void *userdata)
{
FILE *output = stderr;
static int newl = 0;
static int traced_data = 0;
char idsbuf[60];
curl_off_t xfer_id, conn_id;
(void)handle; /* not used */
(void)userdata;
if(!curl_easy_getinfo(handle, CURLINFO_XFER_ID, &xfer_id) && xfer_id >= 0) {
if(!curl_easy_getinfo(handle, CURLINFO_CONN_ID, &conn_id) &&
conn_id >= 0) {
curl_msnprintf(idsbuf, sizeof(idsbuf), TRC_IDS_FORMAT_IDS_2, xfer_id,
conn_id);
}
else {
curl_msnprintf(idsbuf, sizeof(idsbuf), TRC_IDS_FORMAT_IDS_1, xfer_id);
}
}
else
idsbuf[0] = 0;
switch(type) {
case CURLINFO_HEADER_OUT:
if(size > 0) {
size_t st = 0;
size_t i;
for(i = 0; i < size - 1; i++) {
if(data[i] == '\n') { /* LF */
if(!newl) {
log_line_start(output, idsbuf, type);
}
(void)fwrite(data + st, i - st + 1, 1, output);
st = i + 1;
newl = 0;
}
}
if(!newl)
log_line_start(output, idsbuf, type);
(void)fwrite(data + st, i - st + 1, 1, output);
}
newl = (size && (data[size - 1] != '\n')) ? 1 : 0;
traced_data = 0;
break;
case CURLINFO_TEXT:
case CURLINFO_HEADER_IN:
if(!newl)
log_line_start(output, idsbuf, type);
(void)fwrite(data, size, 1, output);
newl = (size && (data[size - 1] != '\n')) ? 1 : 0;
traced_data = 0;
break;
case CURLINFO_DATA_OUT:
case CURLINFO_DATA_IN:
case CURLINFO_SSL_DATA_IN:
case CURLINFO_SSL_DATA_OUT:
if(!traced_data) {
if(!newl)
log_line_start(output, idsbuf, type);
curl_mfprintf(output, "[%ld bytes data]\n", (long)size);
newl = 0;
traced_data = 1;
}
break;
default: /* nada */
newl = 0;
traced_data = 1;
break;
}
return 0;
}
static void dump(const char *text, unsigned char *ptr, size_t size, char nohex)
{
size_t i;
size_t c;
unsigned int width = 0x10;
if(nohex)
/* without the hex output, we can fit more on screen */
width = 0x40;
curl_mfprintf(stderr, "%s, %lu bytes (0x%lx)\n",
text, (unsigned long)size, (unsigned long)size);
for(i = 0; i < size; i += width) {
curl_mfprintf(stderr, "%4.4lx: ", (unsigned long)i);
if(!nohex) {
/* hex not disabled, show it */
for(c = 0; c < width; c++)
if(i + c < size)
curl_mfprintf(stderr, "%02x ", ptr[i + c]);
else
fputs(" ", stderr);
}
for(c = 0; (c < width) && (i + c < size); c++) {
/* check for 0D0A; if found, skip past and start a new line of output */
if(nohex && (i + c + 1 < size) && ptr[i + c] == 0x0D &&
ptr[i + c + 1] == 0x0A) {
i += (c + 2 - width);
break;
}
curl_mfprintf(stderr, "%c",
(ptr[i + c] >= 0x20) && (ptr[i + c] < 0x80) ? ptr[i + c] : '.');
/* check again for 0D0A, to avoid an extra \n if it's at width */
if(nohex && (i + c + 2 < size) && ptr[i + c + 1] == 0x0D &&
ptr[i + c + 2] == 0x0A) {
i += (c + 3 - width);
break;
}
}
fputc('\n', stderr); /* newline */
}
}
#ifndef CURL_DISABLE_WEBSOCKETS
/* just close the connection */
static void websocket_close(CURL *curl)
{
size_t sent;
CURLcode result =
curl_ws_send(curl, "", 0, &sent, 0, CURLWS_CLOSE);
curl_mfprintf(stderr, "ws: curl_ws_send returned %u, sent %u\n",
(int)result, (int)sent);
}
#endif /* CURL_DISABLE_WEBSOCKETS */
static int coptind;
static char *coptarg;
static int cgetopt(int argc, char * const argv[], const char *optstring)
{
static int optpos = 1;
int coptopt;
char *arg;
if(coptind == 0) { /* Reset? */
coptind = !!argc;
optpos = 1;
}
arg = argv[coptind];
if(arg && strcmp(arg, "--") == 0) {
coptind++;
return -1;
}
else if(!arg || arg[0] != '-') {
return -1;
}
else {
const char *opt = strchr(optstring, arg[optpos]);
coptopt = arg[optpos];
if(!opt) {
if(!arg[++optpos]) {
coptind++;
optpos = 1;
}
return '?';
}
else if(opt[1] == ':') {
if(arg[optpos + 1]) {
coptarg = arg + optpos + 1;
coptind++;
optpos = 1;
return coptopt;
}
else if(argv[coptind + 1]) {
coptarg = argv[coptind + 1];
coptind += 2;
optpos = 1;
return coptopt;
}
else {
if(!arg[++optpos]) {
coptind++;
optpos = 1;
}
return *optstring == ':' ? ':' : '?';
}
}
else {
if(!arg[++optpos]) {
coptind++;
optpos = 1;
}
return coptopt;
}
}
}
#endif /* HEADER_CLIENT_FIRST_H */

View File

@@ -0,0 +1,282 @@
/***************************************************************************
* _ _ ____ _
* 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
*
***************************************************************************/
/* This is based on the PoC client of issue #11982
*/
#include "first.h"
static void usage_h2_pausing(const char *msg)
{
if(msg)
curl_mfprintf(stderr, "%s\n", msg);
curl_mfprintf(stderr,
"usage: [options] url\n"
" pause downloads with following options:\n"
" -V http_version (http/1.1, h2, h3) http version to use\n"
);
}
struct handle
{
size_t idx;
int paused;
int resumed;
int errored;
int fail_write;
CURL *h;
};
static size_t cb(char *data, size_t size, size_t nmemb, void *clientp)
{
size_t realsize = size * nmemb;
struct handle *handle = (struct handle *) clientp;
curl_off_t totalsize;
(void)data;
if(curl_easy_getinfo(handle->h, CURLINFO_CONTENT_LENGTH_DOWNLOAD_T,
&totalsize) == CURLE_OK)
curl_mfprintf(stderr, "INFO: [%d] write, "
"Content-Length %" CURL_FORMAT_CURL_OFF_T "\n",
(int)handle->idx, totalsize);
if(!handle->resumed) {
++handle->paused;
curl_mfprintf(stderr, "INFO: [%d] write, PAUSING %d time on %lu bytes\n",
(int)handle->idx, handle->paused, (long)realsize);
assert(handle->paused == 1);
return CURL_WRITEFUNC_PAUSE;
}
if(handle->fail_write) {
++handle->errored;
curl_mfprintf(stderr, "INFO: [%d] FAIL write of %lu bytes, %d time\n",
(int)handle->idx, (long)realsize, handle->errored);
return CURL_WRITEFUNC_ERROR;
}
curl_mfprintf(stderr, "INFO: [%d] write, accepting %lu bytes\n",
(int)handle->idx, (long)realsize);
return realsize;
}
static int test_h2_pausing(int argc, char *argv[])
{
struct handle handles[2];
CURLM *multi_handle;
int still_running = 1, msgs_left, numfds;
size_t i;
CURLMsg *msg;
int rounds = 0;
int rc = 0;
CURLU *cu;
struct curl_slist *resolve = NULL;
char resolve_buf[1024];
char *url, *host = NULL, *port = NULL;
int all_paused = 0;
int resume_round = -1;
int http_version = CURL_HTTP_VERSION_2_0;
int ch;
while((ch = cgetopt(argc, argv, "hV:")) != -1) {
switch(ch) {
case 'h':
usage_h2_pausing(NULL);
return 2;
case 'V': {
if(!strcmp("http/1.1", coptarg))
http_version = CURL_HTTP_VERSION_1_1;
else if(!strcmp("h2", coptarg))
http_version = CURL_HTTP_VERSION_2_0;
else if(!strcmp("h3", coptarg))
http_version = CURL_HTTP_VERSION_3ONLY;
else {
usage_h2_pausing("invalid http version");
return 1;
}
break;
}
default:
usage_h2_pausing("invalid option");
return 1;
}
}
argc -= coptind;
argv += coptind;
if(argc != 1) {
curl_mfprintf(stderr, "ERROR: need URL as argument\n");
return 2;
}
url = argv[0];
curl_global_init(CURL_GLOBAL_DEFAULT);
curl_global_trace("ids,time,http/2,http/3");
cu = curl_url();
if(!cu) {
curl_mfprintf(stderr, "out of memory\n");
return 1;
}
if(curl_url_set(cu, CURLUPART_URL, url, 0)) {
curl_mfprintf(stderr, "not a URL: '%s'\n", url);
return 1;
}
if(curl_url_get(cu, CURLUPART_HOST, &host, 0)) {
curl_mfprintf(stderr, "could not get host of '%s'\n", url);
return 1;
}
if(curl_url_get(cu, CURLUPART_PORT, &port, 0)) {
curl_mfprintf(stderr, "could not get port of '%s'\n", url);
return 1;
}
memset(&resolve, 0, sizeof(resolve));
curl_msnprintf(resolve_buf, sizeof(resolve_buf)-1, "%s:%s:127.0.0.1",
host, port);
resolve = curl_slist_append(resolve, resolve_buf);
for(i = 0; i < CURL_ARRAYSIZE(handles); i++) {
handles[i].idx = i;
handles[i].paused = 0;
handles[i].resumed = 0;
handles[i].errored = 0;
handles[i].fail_write = 1;
handles[i].h = curl_easy_init();
if(!handles[i].h ||
curl_easy_setopt(handles[i].h, CURLOPT_WRITEFUNCTION, cb) != CURLE_OK ||
curl_easy_setopt(handles[i].h, CURLOPT_WRITEDATA, &handles[i])
!= CURLE_OK ||
curl_easy_setopt(handles[i].h, CURLOPT_FOLLOWLOCATION, 1L) != CURLE_OK ||
curl_easy_setopt(handles[i].h, CURLOPT_VERBOSE, 1L) != CURLE_OK ||
curl_easy_setopt(handles[i].h, CURLOPT_DEBUGFUNCTION, debug_cb)
!= CURLE_OK ||
curl_easy_setopt(handles[i].h, CURLOPT_SSL_VERIFYPEER, 0L) != CURLE_OK ||
curl_easy_setopt(handles[i].h, CURLOPT_RESOLVE, resolve) != CURLE_OK ||
curl_easy_setopt(handles[i].h, CURLOPT_PIPEWAIT, 1L) ||
curl_easy_setopt(handles[i].h, CURLOPT_URL, url) != CURLE_OK) {
ERR();
}
curl_easy_setopt(handles[i].h, CURLOPT_HTTP_VERSION, (long)http_version);
}
multi_handle = curl_multi_init();
if(!multi_handle)
ERR();
for(i = 0; i < CURL_ARRAYSIZE(handles); i++) {
if(curl_multi_add_handle(multi_handle, handles[i].h) != CURLM_OK)
ERR();
}
for(rounds = 0;; rounds++) {
curl_mfprintf(stderr, "INFO: multi_perform round %d\n", rounds);
if(curl_multi_perform(multi_handle, &still_running) != CURLM_OK)
ERR();
if(!still_running) {
int as_expected = 1;
curl_mfprintf(stderr, "INFO: no more handles running\n");
for(i = 0; i < CURL_ARRAYSIZE(handles); i++) {
if(!handles[i].paused) {
curl_mfprintf(stderr, "ERROR: [%d] NOT PAUSED\n", (int)i);
as_expected = 0;
}
else if(handles[i].paused != 1) {
curl_mfprintf(stderr, "ERROR: [%d] PAUSED %d times!\n",
(int)i, handles[i].paused);
as_expected = 0;
}
else if(!handles[i].resumed) {
curl_mfprintf(stderr, "ERROR: [%d] NOT resumed!\n", (int)i);
as_expected = 0;
}
else if(handles[i].errored != 1) {
curl_mfprintf(stderr, "ERROR: [%d] NOT errored once, %d instead!\n",
(int)i, handles[i].errored);
as_expected = 0;
}
}
if(!as_expected) {
curl_mfprintf(stderr, "ERROR: handles not in expected state "
"after %d rounds\n", rounds);
rc = 1;
}
break;
}
if(curl_multi_poll(multi_handle, NULL, 0, 100, &numfds) != CURLM_OK)
ERR();
/* !checksrc! disable EQUALSNULL 1 */
while((msg = curl_multi_info_read(multi_handle, &msgs_left)) != NULL) {
if(msg->msg == CURLMSG_DONE) {
for(i = 0; i < CURL_ARRAYSIZE(handles); i++) {
if(msg->easy_handle == handles[i].h) {
if(handles[i].paused != 1 || !handles[i].resumed) {
curl_mfprintf(stderr, "ERROR: [%d] done, pauses=%d, resumed=%d, "
"result %d - wtf?\n", (int)i, handles[i].paused,
handles[i].resumed, msg->data.result);
rc = 1;
goto out;
}
}
}
}
}
/* Successfully paused? */
if(!all_paused) {
for(i = 0; i < CURL_ARRAYSIZE(handles); i++) {
if(!handles[i].paused) {
break;
}
}
all_paused = (i == CURL_ARRAYSIZE(handles));
if(all_paused) {
curl_mfprintf(stderr, "INFO: all transfers paused\n");
/* give transfer some rounds to mess things up */
resume_round = rounds + 2;
}
}
if(resume_round > 0 && rounds == resume_round) {
/* time to resume */
for(i = 0; i < CURL_ARRAYSIZE(handles); i++) {
curl_mfprintf(stderr, "INFO: [%d] resumed\n", (int)i);
handles[i].resumed = 1;
curl_easy_pause(handles[i].h, CURLPAUSE_CONT);
}
}
}
out:
for(i = 0; i < CURL_ARRAYSIZE(handles); i++) {
curl_multi_remove_handle(multi_handle, handles[i].h);
curl_easy_cleanup(handles[i].h);
}
curl_slist_free_all(resolve);
curl_free(host);
curl_free(port);
curl_url_cleanup(cu);
curl_multi_cleanup(multi_handle);
curl_global_cleanup();
return rc;
}

View File

@@ -0,0 +1,205 @@
/***************************************************************************
* _ _ ____ _
* 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 "first.h"
static int my_trace(CURL *handle, curl_infotype type,
char *data, size_t size, void *userp)
{
const char *text;
(void)handle; /* prevent compiler warning */
(void)userp;
switch(type) {
case CURLINFO_TEXT:
curl_mfprintf(stderr, "== Info: %s", data);
return 0;
case CURLINFO_HEADER_OUT:
text = "=> Send header";
break;
case CURLINFO_DATA_OUT:
text = "=> Send data";
break;
case CURLINFO_SSL_DATA_OUT:
text = "=> Send SSL data";
break;
case CURLINFO_HEADER_IN:
text = "<= Recv header";
break;
case CURLINFO_DATA_IN:
text = "<= Recv data";
break;
case CURLINFO_SSL_DATA_IN:
text = "<= Recv SSL data";
break;
default: /* in case a new one is introduced to shock us */
return 0;
}
dump(text, (unsigned char *)data, size, 1);
return 0;
}
static FILE *out_download;
static int setup_h2_serverpush(CURL *hnd, const char *url)
{
out_download = fopen("download_0.data", "wb");
if(!out_download)
return 1; /* failed */
curl_easy_setopt(hnd, CURLOPT_URL, url);
curl_easy_setopt(hnd, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2_0);
curl_easy_setopt(hnd, CURLOPT_SSL_VERIFYPEER, 0L);
curl_easy_setopt(hnd, CURLOPT_SSL_VERIFYHOST, 0L);
curl_easy_setopt(hnd, CURLOPT_WRITEDATA, out_download);
/* please be verbose */
curl_easy_setopt(hnd, CURLOPT_VERBOSE, 1L);
curl_easy_setopt(hnd, CURLOPT_DEBUGFUNCTION, my_trace);
/* wait for pipe connection to confirm */
curl_easy_setopt(hnd, CURLOPT_PIPEWAIT, 1L);
return 0; /* all is good */
}
static FILE *out_push;
/* called when there's an incoming push */
static int server_push_callback(CURL *parent,
CURL *easy,
size_t num_headers,
struct curl_pushheaders *headers,
void *userp)
{
char *headp;
size_t i;
int *transfers = (int *)userp;
char filename[128];
static unsigned int count = 0;
int rv;
(void)parent; /* we have no use for this */
curl_msnprintf(filename, sizeof(filename) - 1, "push%u", count++);
/* here's a new stream, save it in a new file for each new push */
out_push = fopen(filename, "wb");
if(!out_push) {
/* if we cannot save it, deny it */
curl_mfprintf(stderr, "Failed to create output file for push\n");
rv = CURL_PUSH_DENY;
goto out;
}
/* write to this file */
curl_easy_setopt(easy, CURLOPT_WRITEDATA, out_push);
curl_mfprintf(stderr, "**** push callback approves stream %u, "
"got %lu headers!\n", count, (unsigned long)num_headers);
for(i = 0; i < num_headers; i++) {
headp = curl_pushheader_bynum(headers, i);
curl_mfprintf(stderr, "**** header %lu: %s\n", (unsigned long)i, headp);
}
headp = curl_pushheader_byname(headers, ":path");
if(headp) {
curl_mfprintf(stderr, "**** The PATH is %s\n",
headp /* skip :path + colon */);
}
(*transfers)++; /* one more */
rv = CURL_PUSH_OK;
out:
return rv;
}
/*
* Download a file over HTTP/2, take care of server push.
*/
static int test_h2_serverpush(int argc, char *argv[])
{
CURL *easy;
CURLM *multi_handle;
int transfers = 1; /* we start with one */
struct CURLMsg *m;
const char *url;
if(argc != 2) {
curl_mfprintf(stderr, "need URL as argument\n");
return 2;
}
url = argv[1];
multi_handle = curl_multi_init();
curl_multi_setopt(multi_handle, CURLMOPT_PIPELINING, CURLPIPE_MULTIPLEX);
curl_multi_setopt(multi_handle, CURLMOPT_PUSHFUNCTION, server_push_callback);
curl_multi_setopt(multi_handle, CURLMOPT_PUSHDATA, &transfers);
easy = curl_easy_init();
if(setup_h2_serverpush(easy, url)) {
fclose(out_download);
curl_mfprintf(stderr, "failed\n");
return 1;
}
curl_multi_add_handle(multi_handle, easy);
do {
int still_running; /* keep number of running handles */
CURLMcode mc = curl_multi_perform(multi_handle, &still_running);
if(still_running)
/* wait for activity, timeout or "nothing" */
mc = curl_multi_poll(multi_handle, NULL, 0, 1000, NULL);
if(mc)
break;
/*
* A little caution when doing server push is that libcurl itself has
* created and added one or more easy handles but we need to clean them up
* when we are done.
*/
do {
int msgq = 0;
m = curl_multi_info_read(multi_handle, &msgq);
if(m && (m->msg == CURLMSG_DONE)) {
CURL *e = m->easy_handle;
transfers--;
curl_multi_remove_handle(multi_handle, e);
curl_easy_cleanup(e);
}
} while(m);
} while(transfers); /* as long as we have transfers going */
curl_multi_cleanup(multi_handle);
fclose(out_download);
if(out_push)
fclose(out_push);
return 0;
}

View File

@@ -0,0 +1,163 @@
/***************************************************************************
* _ _ ____ _
* 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 "first.h"
static size_t write_h2ue_cb(char *ptr, size_t size, size_t nmemb, void *opaque)
{
(void)ptr;
(void)opaque;
return size * nmemb;
}
static int test_h2_upgrade_extreme(int argc, char *argv[])
{
const char *url;
CURLM *multi = NULL;
CURL *easy;
CURLMcode mc;
int running_handles = 0, start_count, numfds;
CURLMsg *msg;
int msgs_in_queue;
char range[128];
int exitcode = 1;
if(argc != 2) {
curl_mfprintf(stderr, "%s URL\n", argv[0]);
return 2;
}
url = argv[1];
multi = curl_multi_init();
if(!multi) {
curl_mfprintf(stderr, "curl_multi_init failed\n");
goto cleanup;
}
start_count = 200;
do {
if(start_count) {
easy = curl_easy_init();
if(!easy) {
curl_mfprintf(stderr, "curl_easy_init failed\n");
goto cleanup;
}
curl_easy_setopt(easy, CURLOPT_VERBOSE, 1L);
curl_easy_setopt(easy, CURLOPT_DEBUGFUNCTION, debug_cb);
curl_easy_setopt(easy, CURLOPT_URL, url);
curl_easy_setopt(easy, CURLOPT_NOSIGNAL, 1L);
curl_easy_setopt(easy, CURLOPT_AUTOREFERER, 1L);
curl_easy_setopt(easy, CURLOPT_FAILONERROR, 1L);
curl_easy_setopt(easy, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2_0);
curl_easy_setopt(easy, CURLOPT_WRITEFUNCTION, write_h2ue_cb);
curl_easy_setopt(easy, CURLOPT_WRITEDATA, NULL);
curl_easy_setopt(easy, CURLOPT_HTTPGET, 1L);
curl_msnprintf(range, sizeof(range),
"%" CURL_FORMAT_CURL_OFF_TU "-"
"%" CURL_FORMAT_CURL_OFF_TU,
(curl_off_t)0,
(curl_off_t)16384);
curl_easy_setopt(easy, CURLOPT_RANGE, range);
mc = curl_multi_add_handle(multi, easy);
if(mc != CURLM_OK) {
curl_mfprintf(stderr, "curl_multi_add_handle: %s\n",
curl_multi_strerror(mc));
curl_easy_cleanup(easy);
goto cleanup;
}
--start_count;
}
mc = curl_multi_perform(multi, &running_handles);
if(mc != CURLM_OK) {
curl_mfprintf(stderr, "curl_multi_perform: %s\n",
curl_multi_strerror(mc));
goto cleanup;
}
if(running_handles) {
mc = curl_multi_poll(multi, NULL, 0, 1000000, &numfds);
if(mc != CURLM_OK) {
curl_mfprintf(stderr, "curl_multi_poll: %s\n",
curl_multi_strerror(mc));
goto cleanup;
}
}
/* Check for finished handles and remove. */
/* !checksrc! disable EQUALSNULL 1 */
while((msg = curl_multi_info_read(multi, &msgs_in_queue)) != NULL) {
if(msg->msg == CURLMSG_DONE) {
long status = 0;
curl_off_t xfer_id;
curl_easy_getinfo(msg->easy_handle, CURLINFO_XFER_ID, &xfer_id);
curl_easy_getinfo(msg->easy_handle, CURLINFO_RESPONSE_CODE, &status);
if(msg->data.result == CURLE_SEND_ERROR ||
msg->data.result == CURLE_RECV_ERROR) {
/* We get these if the server had a GOAWAY in transit on
* re-using a connection */
}
else if(msg->data.result) {
curl_mfprintf(stderr, "transfer #%" CURL_FORMAT_CURL_OFF_T
": failed with %d\n", xfer_id, msg->data.result);
goto cleanup;
}
else if(status != 206) {
curl_mfprintf(stderr, "transfer #%" CURL_FORMAT_CURL_OFF_T
": wrong http status %ld (expected 206)\n", xfer_id,
status);
goto cleanup;
}
curl_multi_remove_handle(multi, msg->easy_handle);
curl_easy_cleanup(msg->easy_handle);
curl_mfprintf(stderr, "transfer #%" CURL_FORMAT_CURL_OFF_T" retiring "
"(%d now running)\n", xfer_id, running_handles);
}
}
curl_mfprintf(stderr, "running_handles=%d, yet_to_start=%d\n",
running_handles, start_count);
} while(running_handles > 0 || start_count);
curl_mfprintf(stderr, "exiting\n");
exitcode = 0;
cleanup:
if(multi) {
CURL **list = curl_multi_get_handles(multi);
if(list) {
int i;
for(i = 0; list[i]; i++) {
curl_multi_remove_handle(multi, list[i]);
curl_easy_cleanup(list[i]);
}
curl_free(list);
}
curl_multi_cleanup(multi);
}
return exitcode;
}

View File

@@ -0,0 +1,447 @@
/***************************************************************************
* _ _ ____ _
* 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 "first.h"
static int verbose_d = 1;
struct transfer_d {
int idx;
CURL *easy;
char filename[128];
FILE *out;
curl_off_t recv_size;
curl_off_t fail_at;
curl_off_t pause_at;
curl_off_t abort_at;
int started;
int paused;
int resumed;
int done;
CURLcode result;
};
static size_t transfer_count_d = 1;
static struct transfer_d *transfer_d;
static int forbid_reuse_d = 0;
static struct transfer_d *get_transfer_for_easy_d(CURL *easy)
{
size_t i;
for(i = 0; i < transfer_count_d; ++i) {
if(easy == transfer_d[i].easy)
return &transfer_d[i];
}
return NULL;
}
static size_t my_write_d_cb(char *buf, size_t nitems, size_t buflen,
void *userdata)
{
struct transfer_d *t = userdata;
size_t blen = (nitems * buflen);
size_t nwritten;
curl_mfprintf(stderr, "[t-%d] RECV %ld bytes, total=%ld, pause_at=%ld\n",
t->idx, (long)blen, (long)t->recv_size, (long)t->pause_at);
if(!t->out) {
curl_msnprintf(t->filename, sizeof(t->filename)-1, "download_%u.data",
t->idx);
t->out = fopen(t->filename, "wb");
if(!t->out)
return 0;
}
if(!t->resumed &&
t->recv_size < t->pause_at &&
((t->recv_size + (curl_off_t)blen) >= t->pause_at)) {
curl_mfprintf(stderr, "[t-%d] PAUSE\n", t->idx);
t->paused = 1;
return CURL_WRITEFUNC_PAUSE;
}
nwritten = fwrite(buf, nitems, buflen, t->out);
if(nwritten < blen) {
curl_mfprintf(stderr, "[t-%d] write failure\n", t->idx);
return 0;
}
t->recv_size += (curl_off_t)nwritten;
if(t->fail_at > 0 && t->recv_size >= t->fail_at) {
curl_mfprintf(stderr, "[t-%d] FAIL by write callback at %ld bytes\n",
t->idx, (long)t->recv_size);
return CURL_WRITEFUNC_ERROR;
}
return (size_t)nwritten;
}
static int my_progress_d_cb(void *userdata,
curl_off_t dltotal, curl_off_t dlnow,
curl_off_t ultotal, curl_off_t ulnow)
{
struct transfer_d *t = userdata;
(void)ultotal;
(void)ulnow;
(void)dltotal;
if(t->abort_at > 0 && dlnow >= t->abort_at) {
curl_mfprintf(stderr, "[t-%d] ABORT by progress_cb at %ld bytes\n",
t->idx, (long)dlnow);
return 1;
}
return 0;
}
static int setup_hx_download(CURL *hnd, const char *url, struct transfer_d *t,
long http_version, struct curl_slist *host,
CURLSH *share, int use_earlydata,
int fresh_connect)
{
curl_easy_setopt(hnd, CURLOPT_SHARE, share);
curl_easy_setopt(hnd, CURLOPT_URL, url);
curl_easy_setopt(hnd, CURLOPT_HTTP_VERSION, http_version);
curl_easy_setopt(hnd, CURLOPT_SSL_VERIFYPEER, 0L);
curl_easy_setopt(hnd, CURLOPT_SSL_VERIFYHOST, 0L);
curl_easy_setopt(hnd, CURLOPT_ACCEPT_ENCODING, "");
curl_easy_setopt(hnd, CURLOPT_BUFFERSIZE, (long)(128 * 1024));
curl_easy_setopt(hnd, CURLOPT_WRITEFUNCTION, my_write_d_cb);
curl_easy_setopt(hnd, CURLOPT_WRITEDATA, t);
curl_easy_setopt(hnd, CURLOPT_NOPROGRESS, 0L);
curl_easy_setopt(hnd, CURLOPT_XFERINFOFUNCTION, my_progress_d_cb);
curl_easy_setopt(hnd, CURLOPT_XFERINFODATA, t);
if(use_earlydata)
curl_easy_setopt(hnd, CURLOPT_SSL_OPTIONS, (long)CURLSSLOPT_EARLYDATA);
if(forbid_reuse_d)
curl_easy_setopt(hnd, CURLOPT_FORBID_REUSE, 1L);
if(host)
curl_easy_setopt(hnd, CURLOPT_RESOLVE, host);
if(fresh_connect)
curl_easy_setopt(hnd, CURLOPT_FRESH_CONNECT, 1L);
/* please be verbose */
if(verbose_d) {
curl_easy_setopt(hnd, CURLOPT_VERBOSE, 1L);
curl_easy_setopt(hnd, CURLOPT_DEBUGFUNCTION, debug_cb);
}
/* wait for pipe connection to confirm */
curl_easy_setopt(hnd, CURLOPT_PIPEWAIT, 1L);
return 0; /* all is good */
}
static void usage_hx_download(const char *msg)
{
if(msg)
curl_mfprintf(stderr, "%s\n", msg);
curl_mfprintf(stderr,
"usage: [options] url\n"
" download a url with following options:\n"
" -a abort paused transfer\n"
" -m number max parallel downloads\n"
" -e use TLS early data when possible\n"
" -f forbid connection reuse\n"
" -n number total downloads\n");
curl_mfprintf(stderr,
" -A number abort transfer after `number` response bytes\n"
" -F number fail writing response after `number` response bytes\n"
" -M number max concurrent connections to a host\n"
" -P number pause transfer after `number` response bytes\n"
" -r <host>:<port>:<addr> resolve information\n"
" -T number max concurrent connections total\n"
" -V http_version (http/1.1, h2, h3) http version to use\n"
);
}
/*
* Download a file over HTTP/2, take care of server push.
*/
static int test_hx_download(int argc, char *argv[])
{
CURLM *multi_handle;
struct CURLMsg *m;
CURLSH *share;
const char *url;
size_t i, n, max_parallel = 1;
size_t active_transfers;
size_t pause_offset = 0;
size_t abort_offset = 0;
size_t fail_offset = 0;
int abort_paused = 0, use_earlydata = 0;
struct transfer_d *t;
int http_version = CURL_HTTP_VERSION_2_0;
int ch;
struct curl_slist *host = NULL;
char *resolve = NULL;
size_t max_host_conns = 0;
size_t max_total_conns = 0;
int fresh_connect = 0;
int result = 0;
while((ch = cgetopt(argc, argv, "aefhm:n:xA:F:M:P:r:T:V:")) != -1) {
switch(ch) {
case 'h':
usage_hx_download(NULL);
result = 2;
goto cleanup;
case 'a':
abort_paused = 1;
break;
case 'e':
use_earlydata = 1;
break;
case 'f':
forbid_reuse_d = 1;
break;
case 'm':
max_parallel = (size_t)strtol(coptarg, NULL, 10);
break;
case 'n':
transfer_count_d = (size_t)strtol(coptarg, NULL, 10);
break;
case 'x':
fresh_connect = 1;
break;
case 'A':
abort_offset = (size_t)strtol(coptarg, NULL, 10);
break;
case 'F':
fail_offset = (size_t)strtol(coptarg, NULL, 10);
break;
case 'M':
max_host_conns = (size_t)strtol(coptarg, NULL, 10);
break;
case 'P':
pause_offset = (size_t)strtol(coptarg, NULL, 10);
break;
case 'r':
free(resolve);
resolve = strdup(coptarg);
break;
case 'T':
max_total_conns = (size_t)strtol(coptarg, NULL, 10);
break;
case 'V': {
if(!strcmp("http/1.1", coptarg))
http_version = CURL_HTTP_VERSION_1_1;
else if(!strcmp("h2", coptarg))
http_version = CURL_HTTP_VERSION_2_0;
else if(!strcmp("h3", coptarg))
http_version = CURL_HTTP_VERSION_3ONLY;
else {
usage_hx_download("invalid http version");
result = 1;
goto cleanup;
}
break;
}
default:
usage_hx_download("invalid option");
result = 1;
goto cleanup;
}
}
argc -= coptind;
argv += coptind;
curl_global_init(CURL_GLOBAL_DEFAULT);
curl_global_trace("ids,time,http/2,http/3");
if(argc != 1) {
usage_hx_download("not enough arguments");
result = 2;
goto cleanup;
}
url = argv[0];
if(resolve)
host = curl_slist_append(NULL, resolve);
share = curl_share_init();
if(!share) {
curl_mfprintf(stderr, "error allocating share\n");
result = 1;
goto cleanup;
}
curl_share_setopt(share, CURLSHOPT_SHARE, CURL_LOCK_DATA_COOKIE);
curl_share_setopt(share, CURLSHOPT_SHARE, CURL_LOCK_DATA_DNS);
curl_share_setopt(share, CURLSHOPT_SHARE, CURL_LOCK_DATA_SSL_SESSION);
/* curl_share_setopt(share, CURLSHOPT_SHARE, CURL_LOCK_DATA_CONNECT); */
curl_share_setopt(share, CURLSHOPT_SHARE, CURL_LOCK_DATA_PSL);
curl_share_setopt(share, CURLSHOPT_SHARE, CURL_LOCK_DATA_HSTS);
transfer_d = calloc(transfer_count_d, sizeof(*transfer_d));
if(!transfer_d) {
curl_mfprintf(stderr, "error allocating transfer structs\n");
result = 1;
goto cleanup;
}
multi_handle = curl_multi_init();
curl_multi_setopt(multi_handle, CURLMOPT_PIPELINING, CURLPIPE_MULTIPLEX);
curl_multi_setopt(multi_handle, CURLMOPT_MAX_TOTAL_CONNECTIONS,
(long)max_total_conns);
curl_multi_setopt(multi_handle, CURLMOPT_MAX_HOST_CONNECTIONS,
(long)max_host_conns);
active_transfers = 0;
for(i = 0; i < transfer_count_d; ++i) {
t = &transfer_d[i];
t->idx = (int)i;
t->abort_at = (curl_off_t)abort_offset;
t->fail_at = (curl_off_t)fail_offset;
t->pause_at = (curl_off_t)pause_offset;
}
n = (max_parallel < transfer_count_d) ? max_parallel : transfer_count_d;
for(i = 0; i < n; ++i) {
t = &transfer_d[i];
t->easy = curl_easy_init();
if(!t->easy ||
setup_hx_download(t->easy, url, t, http_version, host, share,
use_earlydata, fresh_connect)) {
curl_mfprintf(stderr, "[t-%d] FAILED setup\n", (int)i);
result = 1;
goto cleanup;
}
curl_multi_add_handle(multi_handle, t->easy);
t->started = 1;
++active_transfers;
curl_mfprintf(stderr, "[t-%d] STARTED\n", t->idx);
}
do {
int still_running; /* keep number of running handles */
CURLMcode mc = curl_multi_perform(multi_handle, &still_running);
if(still_running) {
/* wait for activity, timeout or "nothing" */
mc = curl_multi_poll(multi_handle, NULL, 0, 1000, NULL);
}
if(mc)
break;
do {
int msgq = 0;
m = curl_multi_info_read(multi_handle, &msgq);
if(m && (m->msg == CURLMSG_DONE)) {
CURL *e = m->easy_handle;
--active_transfers;
curl_multi_remove_handle(multi_handle, e);
t = get_transfer_for_easy_d(e);
if(t) {
t->done = 1;
t->result = m->data.result;
curl_mfprintf(stderr, "[t-%d] FINISHED with result %d\n",
t->idx, t->result);
if(use_earlydata) {
curl_off_t sent;
curl_easy_getinfo(e, CURLINFO_EARLYDATA_SENT_T, &sent);
curl_mfprintf(stderr, "[t-%d] EarlyData: %ld\n", t->idx,
(long)sent);
}
}
else {
curl_easy_cleanup(e);
curl_mfprintf(stderr, "unknown FINISHED???\n");
}
}
/* nothing happening, maintenance */
if(abort_paused) {
/* abort paused transfers */
for(i = 0; i < transfer_count_d; ++i) {
t = &transfer_d[i];
if(!t->done && t->paused && t->easy) {
curl_multi_remove_handle(multi_handle, t->easy);
t->done = 1;
active_transfers--;
curl_mfprintf(stderr, "[t-%d] ABORTED\n", t->idx);
}
}
}
else {
/* resume one paused transfer */
for(i = 0; i < transfer_count_d; ++i) {
t = &transfer_d[i];
if(!t->done && t->paused) {
t->resumed = 1;
t->paused = 0;
curl_easy_pause(t->easy, CURLPAUSE_CONT);
curl_mfprintf(stderr, "[t-%d] RESUMED\n", t->idx);
break;
}
}
}
while(active_transfers < max_parallel) {
for(i = 0; i < transfer_count_d; ++i) {
t = &transfer_d[i];
if(!t->started) {
t->easy = curl_easy_init();
if(!t->easy ||
setup_hx_download(t->easy, url, t, http_version, host, share,
use_earlydata, fresh_connect)) {
curl_mfprintf(stderr, "[t-%d] FAILED setup\n", (int)i);
result = 1;
goto cleanup;
}
curl_multi_add_handle(multi_handle, t->easy);
t->started = 1;
++active_transfers;
curl_mfprintf(stderr, "[t-%d] STARTED\n", t->idx);
break;
}
}
/* all started */
if(i == transfer_count_d)
break;
}
} while(m);
} while(active_transfers); /* as long as we have transfers going */
curl_multi_cleanup(multi_handle);
for(i = 0; i < transfer_count_d; ++i) {
t = &transfer_d[i];
if(t->out) {
fclose(t->out);
t->out = NULL;
}
if(t->easy) {
curl_easy_cleanup(t->easy);
t->easy = NULL;
}
if(t->result)
result = t->result;
}
free(transfer_d);
curl_share_cleanup(share);
curl_slist_free_all(host);
cleanup:
free(resolve);
return result;
}

View File

@@ -0,0 +1,498 @@
/***************************************************************************
* _ _ ____ _
* 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 "first.h"
static int verbose_u = 1;
struct transfer_u {
int idx;
CURL *easy;
const char *method;
char filename[128];
FILE *out;
curl_off_t send_total;
curl_off_t recv_size;
curl_off_t send_size;
curl_off_t fail_at;
curl_off_t pause_at;
curl_off_t abort_at;
int started;
int paused;
int resumed;
int done;
};
static size_t transfer_count_u = 1;
static struct transfer_u *transfer_u;
static int forbid_reuse_u = 0;
static struct transfer_u *get_transfer_for_easy_u(CURL *easy)
{
size_t i;
for(i = 0; i < transfer_count_u; ++i) {
if(easy == transfer_u[i].easy)
return &transfer_u[i];
}
return NULL;
}
static size_t my_write_u_cb(char *buf, size_t nitems, size_t buflen,
void *userdata)
{
struct transfer_u *t = userdata;
size_t blen = (nitems * buflen);
size_t nwritten;
curl_mfprintf(stderr, "[t-%d] RECV %ld bytes, total=%ld, pause_at=%ld\n",
t->idx, (long)blen, (long)t->recv_size, (long)t->pause_at);
if(!t->out) {
curl_msnprintf(t->filename, sizeof(t->filename)-1, "download_%u.data",
t->idx);
t->out = fopen(t->filename, "wb");
if(!t->out)
return 0;
}
nwritten = fwrite(buf, nitems, buflen, t->out);
if(nwritten < blen) {
curl_mfprintf(stderr, "[t-%d] write failure\n", t->idx);
return 0;
}
t->recv_size += (curl_off_t)nwritten;
return (size_t)nwritten;
}
static size_t my_read_cb(char *buf, size_t nitems, size_t buflen,
void *userdata)
{
struct transfer_u *t = userdata;
size_t blen = (nitems * buflen);
size_t nread;
if(t->send_total <= t->send_size)
nread = 0;
else if((t->send_total - t->send_size) < (curl_off_t)blen)
nread = (size_t)(t->send_total - t->send_size);
else
nread = blen;
curl_mfprintf(stderr, "[t-%d] SEND %ld bytes, total=%ld, pause_at=%ld\n",
t->idx, (long)nread, (long)t->send_total, (long)t->pause_at);
if(!t->resumed &&
t->send_size < t->pause_at &&
((t->send_size + (curl_off_t)blen) >= t->pause_at)) {
curl_mfprintf(stderr, "[t-%d] PAUSE\n", t->idx);
t->paused = 1;
return CURL_READFUNC_PAUSE;
}
memset(buf, 'x', nread);
t->send_size += (curl_off_t)nread;
if(t->fail_at > 0 && t->send_size >= t->fail_at) {
curl_mfprintf(stderr, "[t-%d] ABORT by read callback at %ld bytes\n",
t->idx, (long)t->send_size);
return CURL_READFUNC_ABORT;
}
return (size_t)nread;
}
static int my_progress_u_cb(void *userdata,
curl_off_t dltotal, curl_off_t dlnow,
curl_off_t ultotal, curl_off_t ulnow)
{
struct transfer_u *t = userdata;
(void)ultotal;
(void)dlnow;
(void)dltotal;
if(t->abort_at > 0 && ulnow >= t->abort_at) {
curl_mfprintf(stderr, "[t-%d] ABORT by progress_cb at %ld bytes sent\n",
t->idx, (long)ulnow);
return 1;
}
return 0;
}
static int setup_hx_upload(CURL *hnd, const char *url, struct transfer_u *t,
long http_version, struct curl_slist *host,
CURLSH *share, int use_earlydata,
int announce_length)
{
curl_easy_setopt(hnd, CURLOPT_SHARE, share);
curl_easy_setopt(hnd, CURLOPT_URL, url);
curl_easy_setopt(hnd, CURLOPT_HTTP_VERSION, http_version);
curl_easy_setopt(hnd, CURLOPT_SSL_VERIFYPEER, 0L);
curl_easy_setopt(hnd, CURLOPT_SSL_VERIFYHOST, 0L);
curl_easy_setopt(hnd, CURLOPT_BUFFERSIZE, (long)(128 * 1024));
curl_easy_setopt(hnd, CURLOPT_FOLLOWLOCATION, CURLFOLLOW_OBEYCODE);
curl_easy_setopt(hnd, CURLOPT_WRITEFUNCTION, my_write_u_cb);
curl_easy_setopt(hnd, CURLOPT_WRITEDATA, t);
if(use_earlydata)
curl_easy_setopt(hnd, CURLOPT_SSL_OPTIONS, (long)CURLSSLOPT_EARLYDATA);
if(!t->method || !strcmp("PUT", t->method))
curl_easy_setopt(hnd, CURLOPT_UPLOAD, 1L);
else if(!strcmp("POST", t->method))
curl_easy_setopt(hnd, CURLOPT_POST, 1L);
else {
curl_mfprintf(stderr, "unsupported method '%s'\n", t->method);
return 1;
}
curl_easy_setopt(hnd, CURLOPT_READFUNCTION, my_read_cb);
curl_easy_setopt(hnd, CURLOPT_READDATA, t);
if(announce_length)
curl_easy_setopt(hnd, CURLOPT_INFILESIZE_LARGE, t->send_total);
curl_easy_setopt(hnd, CURLOPT_NOPROGRESS, 0L);
curl_easy_setopt(hnd, CURLOPT_XFERINFOFUNCTION, my_progress_u_cb);
curl_easy_setopt(hnd, CURLOPT_XFERINFODATA, t);
if(forbid_reuse_u)
curl_easy_setopt(hnd, CURLOPT_FORBID_REUSE, 1L);
if(host)
curl_easy_setopt(hnd, CURLOPT_RESOLVE, host);
/* please be verbose */
if(verbose_u) {
curl_easy_setopt(hnd, CURLOPT_VERBOSE, 1L);
curl_easy_setopt(hnd, CURLOPT_DEBUGFUNCTION, debug_cb);
}
/* wait for pipe connection to confirm */
curl_easy_setopt(hnd, CURLOPT_PIPEWAIT, 1L);
return 0; /* all is good */
}
static void usage_hx_upload(const char *msg)
{
if(msg)
curl_mfprintf(stderr, "%s\n", msg);
curl_mfprintf(stderr,
"usage: [options] url\n"
" upload to a url with following options:\n"
" -a abort paused transfer\n"
" -e use TLS earlydata\n"
" -m number max parallel uploads\n"
" -n number total uploads\n"
" -A number abort transfer after `number` request body bytes\n"
" -F number fail reading request body after `number` of bytes\n"
" -P number pause transfer after `number` request body bytes\n"
" -r <host>:<port>:<addr> resolve information\n"
" -S number size to upload\n"
" -V http_version (http/1.1, h2, h3) http version to use\n"
);
}
/*
* Download a file over HTTP/2, take care of server push.
*/
static int test_hx_upload(int argc, char *argv[])
{
CURLM *multi_handle;
CURLSH *share;
const char *url;
const char *method = "PUT";
size_t i, n, max_parallel = 1;
size_t active_transfers;
size_t pause_offset = 0;
size_t abort_offset = 0;
size_t fail_offset = 0;
size_t send_total = (128 * 1024);
int abort_paused = 0;
int reuse_easy = 0;
int use_earlydata = 0;
int announce_length = 0;
struct transfer_u *t;
int http_version = CURL_HTTP_VERSION_2_0;
struct curl_slist *host = NULL;
const char *resolve = NULL;
int ch;
while((ch = cgetopt(argc, argv, "aefhlm:n:A:F:M:P:r:RS:V:")) != -1) {
switch(ch) {
case 'h':
usage_hx_upload(NULL);
return 2;
case 'a':
abort_paused = 1;
break;
case 'e':
use_earlydata = 1;
break;
case 'f':
forbid_reuse_u = 1;
break;
case 'l':
announce_length = 1;
break;
case 'm':
max_parallel = (size_t)strtol(coptarg, NULL, 10);
break;
case 'n':
transfer_count_u = (size_t)strtol(coptarg, NULL, 10);
break;
case 'A':
abort_offset = (size_t)strtol(coptarg, NULL, 10);
break;
case 'F':
fail_offset = (size_t)strtol(coptarg, NULL, 10);
break;
case 'M':
method = coptarg;
break;
case 'P':
pause_offset = (size_t)strtol(coptarg, NULL, 10);
break;
case 'r':
resolve = coptarg;
break;
case 'R':
reuse_easy = 1;
break;
case 'S':
send_total = (size_t)strtol(coptarg, NULL, 10);
break;
case 'V': {
if(!strcmp("http/1.1", coptarg))
http_version = CURL_HTTP_VERSION_1_1;
else if(!strcmp("h2", coptarg))
http_version = CURL_HTTP_VERSION_2_0;
else if(!strcmp("h3", coptarg))
http_version = CURL_HTTP_VERSION_3ONLY;
else {
usage_hx_upload("invalid http version");
return 1;
}
break;
}
default:
usage_hx_upload("invalid option");
return 1;
}
}
argc -= coptind;
argv += coptind;
if(max_parallel > 1 && reuse_easy) {
usage_hx_upload("cannot mix -R and -P");
return 2;
}
curl_global_init(CURL_GLOBAL_DEFAULT);
curl_global_trace("ids,time,http/2,http/3");
if(argc != 1) {
usage_hx_upload("not enough arguments");
return 2;
}
url = argv[0];
if(resolve)
host = curl_slist_append(NULL, resolve);
share = curl_share_init();
if(!share) {
curl_mfprintf(stderr, "error allocating share\n");
return 1;
}
curl_share_setopt(share, CURLSHOPT_SHARE, CURL_LOCK_DATA_COOKIE);
curl_share_setopt(share, CURLSHOPT_SHARE, CURL_LOCK_DATA_DNS);
curl_share_setopt(share, CURLSHOPT_SHARE, CURL_LOCK_DATA_SSL_SESSION);
curl_share_setopt(share, CURLSHOPT_SHARE, CURL_LOCK_DATA_CONNECT);
curl_share_setopt(share, CURLSHOPT_SHARE, CURL_LOCK_DATA_PSL);
curl_share_setopt(share, CURLSHOPT_SHARE, CURL_LOCK_DATA_HSTS);
transfer_u = calloc(transfer_count_u, sizeof(*transfer_u));
if(!transfer_u) {
curl_mfprintf(stderr, "error allocating transfer structs\n");
return 1;
}
active_transfers = 0;
for(i = 0; i < transfer_count_u; ++i) {
t = &transfer_u[i];
t->idx = (int)i;
t->method = method;
t->send_total = (curl_off_t)send_total;
t->abort_at = (curl_off_t)abort_offset;
t->fail_at = (curl_off_t)fail_offset;
t->pause_at = (curl_off_t)pause_offset;
}
if(reuse_easy) {
CURL *easy = curl_easy_init();
CURLcode rc = CURLE_OK;
if(!easy) {
curl_mfprintf(stderr, "failed to init easy handle\n");
return 1;
}
for(i = 0; i < transfer_count_u; ++i) {
t = &transfer_u[i];
t->easy = easy;
if(setup_hx_upload(t->easy, url, t, http_version, host, share,
use_earlydata, announce_length)) {
curl_mfprintf(stderr, "[t-%d] FAILED setup\n", (int)i);
return 1;
}
curl_mfprintf(stderr, "[t-%d] STARTING\n", t->idx);
rc = curl_easy_perform(easy);
curl_mfprintf(stderr, "[t-%d] DONE -> %d\n", t->idx, rc);
t->easy = NULL;
curl_easy_reset(easy);
}
curl_easy_cleanup(easy);
}
else {
multi_handle = curl_multi_init();
curl_multi_setopt(multi_handle, CURLMOPT_PIPELINING, CURLPIPE_MULTIPLEX);
n = (max_parallel < transfer_count_u) ? max_parallel : transfer_count_u;
for(i = 0; i < n; ++i) {
t = &transfer_u[i];
t->easy = curl_easy_init();
if(!t->easy || setup_hx_upload(t->easy, url, t, http_version, host,
share, use_earlydata, announce_length)) {
curl_mfprintf(stderr, "[t-%d] FAILED setup\n", (int)i);
return 1;
}
curl_multi_add_handle(multi_handle, t->easy);
t->started = 1;
++active_transfers;
curl_mfprintf(stderr, "[t-%d] STARTED\n", t->idx);
}
do {
int still_running; /* keep number of running handles */
CURLMcode mc = curl_multi_perform(multi_handle, &still_running);
struct CURLMsg *m;
if(still_running) {
/* wait for activity, timeout or "nothing" */
mc = curl_multi_poll(multi_handle, NULL, 0, 1000, NULL);
}
if(mc)
break;
do {
int msgq = 0;
m = curl_multi_info_read(multi_handle, &msgq);
if(m && (m->msg == CURLMSG_DONE)) {
CURL *e = m->easy_handle;
--active_transfers;
curl_multi_remove_handle(multi_handle, e);
t = get_transfer_for_easy_u(e);
if(t) {
long res_status;
curl_easy_getinfo(e, CURLINFO_RESPONSE_CODE, &res_status);
t->done = 1;
curl_mfprintf(stderr, "[t-%d] FINISHED, result=%d, response=%ld\n",
t->idx, m->data.result, res_status);
if(use_earlydata) {
curl_off_t sent;
curl_easy_getinfo(e, CURLINFO_EARLYDATA_SENT_T, &sent);
curl_mfprintf(stderr, "[t-%d] EarlyData: %ld\n", t->idx,
(long)sent);
}
}
else {
curl_easy_cleanup(e);
curl_mfprintf(stderr, "unknown FINISHED???\n");
}
}
/* nothing happening, maintenance */
if(abort_paused) {
/* abort paused transfers */
for(i = 0; i < transfer_count_u; ++i) {
t = &transfer_u[i];
if(!t->done && t->paused && t->easy) {
curl_multi_remove_handle(multi_handle, t->easy);
t->done = 1;
active_transfers--;
curl_mfprintf(stderr, "[t-%d] ABORTED\n", t->idx);
}
}
}
else {
/* resume one paused transfer */
for(i = 0; i < transfer_count_u; ++i) {
t = &transfer_u[i];
if(!t->done && t->paused) {
t->resumed = 1;
t->paused = 0;
curl_easy_pause(t->easy, CURLPAUSE_CONT);
curl_mfprintf(stderr, "[t-%d] RESUMED\n", t->idx);
break;
}
}
}
while(active_transfers < max_parallel) {
for(i = 0; i < transfer_count_u; ++i) {
t = &transfer_u[i];
if(!t->started) {
t->easy = curl_easy_init();
if(!t->easy || setup_hx_upload(t->easy, url, t, http_version,
host, share, use_earlydata,
announce_length)) {
curl_mfprintf(stderr, "[t-%d] FAILED setup\n", (int)i);
return 1;
}
curl_multi_add_handle(multi_handle, t->easy);
t->started = 1;
++active_transfers;
curl_mfprintf(stderr, "[t-%d] STARTED\n", t->idx);
break;
}
}
/* all started */
if(i == transfer_count_u)
break;
}
} while(m);
} while(active_transfers); /* as long as we have transfers going */
curl_multi_cleanup(multi_handle);
}
for(i = 0; i < transfer_count_u; ++i) {
t = &transfer_u[i];
if(t->out) {
fclose(t->out);
t->out = NULL;
}
if(t->easy) {
curl_easy_cleanup(t->easy);
t->easy = NULL;
}
}
free(transfer_u);
curl_share_cleanup(share);
return 0;
}

View File

@@ -0,0 +1,260 @@
/***************************************************************************
* _ _ ____ _
* 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 "first.h"
static int tse_found_tls_session = FALSE;
static size_t write_tse_cb(char *ptr, size_t size, size_t nmemb, void *opaque)
{
CURL *easy = opaque;
(void)ptr;
if(!tse_found_tls_session) {
struct curl_tlssessioninfo *tlssession;
CURLcode rc;
rc = curl_easy_getinfo(easy, CURLINFO_TLS_SSL_PTR, &tlssession);
if(rc) {
curl_mfprintf(stderr, "curl_easy_getinfo(CURLINFO_TLS_SSL_PTR) "
"failed: %s\n", curl_easy_strerror(rc));
return rc;
}
if(tlssession->backend == CURLSSLBACKEND_NONE) {
curl_mfprintf(stderr, "curl_easy_getinfo(CURLINFO_TLS_SSL_PTR) "
"gave no backend\n");
return CURLE_FAILED_INIT;
}
if(!tlssession->internals) {
curl_mfprintf(stderr, "curl_easy_getinfo(CURLINFO_TLS_SSL_PTR) "
"missing\n");
return CURLE_FAILED_INIT;
}
tse_found_tls_session = TRUE;
}
return size * nmemb;
}
static CURL *tse_add_transfer(CURLM *multi, CURLSH *share,
struct curl_slist *resolve,
const char *url, long http_version)
{
CURL *easy;
CURLMcode mc;
easy = curl_easy_init();
if(!easy) {
curl_mfprintf(stderr, "curl_easy_init failed\n");
return NULL;
}
curl_easy_setopt(easy, CURLOPT_VERBOSE, 1L);
curl_easy_setopt(easy, CURLOPT_DEBUGFUNCTION, debug_cb);
curl_easy_setopt(easy, CURLOPT_URL, url);
curl_easy_setopt(easy, CURLOPT_SHARE, share);
curl_easy_setopt(easy, CURLOPT_NOSIGNAL, 1L);
curl_easy_setopt(easy, CURLOPT_AUTOREFERER, 1L);
curl_easy_setopt(easy, CURLOPT_FAILONERROR, 1L);
curl_easy_setopt(easy, CURLOPT_HTTP_VERSION, http_version);
curl_easy_setopt(easy, CURLOPT_WRITEFUNCTION, write_tse_cb);
curl_easy_setopt(easy, CURLOPT_WRITEDATA, easy);
curl_easy_setopt(easy, CURLOPT_HTTPGET, 1L);
curl_easy_setopt(easy, CURLOPT_SSL_VERIFYPEER, 0L);
if(resolve)
curl_easy_setopt(easy, CURLOPT_RESOLVE, resolve);
mc = curl_multi_add_handle(multi, easy);
if(mc != CURLM_OK) {
curl_mfprintf(stderr, "curl_multi_add_handle: %s\n",
curl_multi_strerror(mc));
curl_easy_cleanup(easy);
return NULL;
}
return easy;
}
static int test_tls_session_reuse(int argc, char *argv[])
{
const char *url;
CURLM *multi = NULL;
CURLMcode mc;
int running_handles = 0, numfds;
CURLMsg *msg;
CURLSH *share = NULL;
CURLU *cu;
struct curl_slist *resolve = NULL;
char resolve_buf[1024];
int msgs_in_queue;
int add_more, waits, ongoing = 0;
char *host = NULL, *port = NULL;
int http_version = CURL_HTTP_VERSION_1_1;
int exitcode = 1;
if(argc != 3) {
curl_mfprintf(stderr, "%s proto URL\n", argv[0]);
return 2;
}
if(!strcmp("h2", argv[1]))
http_version = CURL_HTTP_VERSION_2;
else if(!strcmp("h3", argv[1]))
http_version = CURL_HTTP_VERSION_3ONLY;
url = argv[2];
cu = curl_url();
if(!cu) {
curl_mfprintf(stderr, "out of memory\n");
return 1;
}
if(curl_url_set(cu, CURLUPART_URL, url, 0)) {
curl_mfprintf(stderr, "not a URL: '%s'\n", url);
goto cleanup;
}
if(curl_url_get(cu, CURLUPART_HOST, &host, 0)) {
curl_mfprintf(stderr, "could not get host of '%s'\n", url);
goto cleanup;
}
if(curl_url_get(cu, CURLUPART_PORT, &port, 0)) {
curl_mfprintf(stderr, "could not get port of '%s'\n", url);
goto cleanup;
}
curl_msnprintf(resolve_buf, sizeof(resolve_buf)-1, "%s:%s:127.0.0.1",
host, port);
resolve = curl_slist_append(resolve, resolve_buf);
multi = curl_multi_init();
if(!multi) {
curl_mfprintf(stderr, "curl_multi_init failed\n");
goto cleanup;
}
share = curl_share_init();
if(!share) {
curl_mfprintf(stderr, "curl_share_init failed\n");
goto cleanup;
}
curl_share_setopt(share, CURLSHOPT_SHARE, CURL_LOCK_DATA_SSL_SESSION);
if(!tse_add_transfer(multi, share, resolve, url, http_version))
goto cleanup;
++ongoing;
add_more = 6;
waits = 3;
do {
mc = curl_multi_perform(multi, &running_handles);
if(mc != CURLM_OK) {
curl_mfprintf(stderr, "curl_multi_perform: %s\n",
curl_multi_strerror(mc));
goto cleanup;
}
if(running_handles) {
mc = curl_multi_poll(multi, NULL, 0, 1000000, &numfds);
if(mc != CURLM_OK) {
curl_mfprintf(stderr, "curl_multi_poll: %s\n",
curl_multi_strerror(mc));
goto cleanup;
}
}
if(waits) {
--waits;
}
else {
while(add_more) {
if(!tse_add_transfer(multi, share, resolve, url, http_version))
goto cleanup;
++ongoing;
--add_more;
}
}
/* Check for finished handles and remove. */
/* !checksrc! disable EQUALSNULL 1 */
while((msg = curl_multi_info_read(multi, &msgs_in_queue)) != NULL) {
if(msg->msg == CURLMSG_DONE) {
long status = 0;
curl_off_t xfer_id;
curl_easy_getinfo(msg->easy_handle, CURLINFO_XFER_ID, &xfer_id);
curl_easy_getinfo(msg->easy_handle, CURLINFO_RESPONSE_CODE, &status);
if(msg->data.result == CURLE_SEND_ERROR ||
msg->data.result == CURLE_RECV_ERROR) {
/* We get these if the server had a GOAWAY in transit on
* re-using a connection */
}
else if(msg->data.result) {
curl_mfprintf(stderr, "transfer #%" CURL_FORMAT_CURL_OFF_T
": failed with %d\n", xfer_id, msg->data.result);
goto cleanup;
}
else if(status != 200) {
curl_mfprintf(stderr, "transfer #%" CURL_FORMAT_CURL_OFF_T
": wrong http status %ld (expected 200)\n", xfer_id,
status);
goto cleanup;
}
curl_multi_remove_handle(multi, msg->easy_handle);
curl_easy_cleanup(msg->easy_handle);
--ongoing;
curl_mfprintf(stderr, "transfer #%" CURL_FORMAT_CURL_OFF_T" retiring "
"(%d now running)\n", xfer_id, running_handles);
}
}
curl_mfprintf(stderr, "running_handles=%d, yet_to_start=%d\n",
running_handles, add_more);
} while(ongoing || add_more);
if(!tse_found_tls_session) {
curl_mfprintf(stderr, "CURLINFO_TLS_SSL_PTR not found during run\n");
exitcode = CURLE_FAILED_INIT;
goto cleanup;
}
curl_mfprintf(stderr, "exiting\n");
exitcode = 0;
cleanup:
if(multi) {
CURL **list = curl_multi_get_handles(multi);
if(list) {
int i;
for(i = 0; list[i]; i++) {
curl_multi_remove_handle(multi, list[i]);
curl_easy_cleanup(list[i]);
}
curl_free(list);
}
curl_multi_cleanup(multi);
}
curl_share_cleanup(share);
curl_slist_free_all(resolve);
curl_free(host);
curl_free(port);
curl_url_cleanup(cu);
return exitcode;
}

View File

@@ -0,0 +1,196 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
/* This is based on the PoC client of issue #11769
*/
#include "first.h"
static size_t total_read = 0;
static size_t read_callback(char *ptr, size_t size, size_t nmemb,
void *userdata)
{
static const size_t PAUSE_READ_AFTER = 1;
(void)size;
(void)nmemb;
(void)userdata;
if(total_read >= PAUSE_READ_AFTER) {
curl_mfprintf(stderr, "read_callback, return PAUSE\n");
return CURL_READFUNC_PAUSE;
}
else {
ptr[0] = '\n';
++total_read;
curl_mfprintf(stderr, "read_callback, return 1 byte\n");
return 1;
}
}
static int progress_callback(void *clientp,
curl_off_t dltotal,
curl_off_t dlnow,
curl_off_t ultotal,
curl_off_t ulnow)
{
(void)dltotal;
(void)dlnow;
(void)ultotal;
(void)ulnow;
(void)clientp;
#if 0
/* Used to unpause on progress, but keeping for now. */
{
CURL *curl = (CURL *)clientp;
curl_easy_pause(curl, CURLPAUSE_CONT);
/* curl_easy_pause(curl, CURLPAUSE_RECV_CONT); */
}
#endif
return 0;
}
static void usage_upload_pausing(const char *msg)
{
if(msg)
curl_mfprintf(stderr, "%s\n", msg);
curl_mfprintf(stderr,
"usage: [options] url\n"
" upload and pause, options:\n"
" -V http_version (http/1.1, h2, h3) http version to use\n"
);
}
static int test_upload_pausing(int argc, char *argv[])
{
CURL *curl;
CURLcode rc = CURLE_OK;
CURLU *cu;
struct curl_slist *resolve = NULL;
char resolve_buf[1024];
char *url, *host = NULL, *port = NULL;
long http_version = CURL_HTTP_VERSION_1_1;
int ch;
while((ch = cgetopt(argc, argv, "V:")) != -1) {
switch(ch) {
case 'V': {
if(!strcmp("http/1.1", coptarg))
http_version = CURL_HTTP_VERSION_1_1;
else if(!strcmp("h2", coptarg))
http_version = CURL_HTTP_VERSION_2_0;
else if(!strcmp("h3", coptarg))
http_version = CURL_HTTP_VERSION_3ONLY;
else {
usage_upload_pausing("invalid http version");
return 1;
}
break;
}
default:
usage_upload_pausing("invalid option");
return 1;
}
}
argc -= coptind;
argv += coptind;
if(argc != 1) {
usage_upload_pausing("not enough arguments");
return 2;
}
url = argv[0];
curl_global_init(CURL_GLOBAL_DEFAULT);
curl_global_trace("ids,time");
cu = curl_url();
if(!cu) {
curl_mfprintf(stderr, "out of memory\n");
return 1;
}
if(curl_url_set(cu, CURLUPART_URL, url, 0)) {
curl_mfprintf(stderr, "not a URL: '%s'\n", url);
return 1;
}
if(curl_url_get(cu, CURLUPART_HOST, &host, 0)) {
curl_mfprintf(stderr, "could not get host of '%s'\n", url);
return 1;
}
if(curl_url_get(cu, CURLUPART_PORT, &port, 0)) {
curl_mfprintf(stderr, "could not get port of '%s'\n", url);
return 1;
}
memset(&resolve, 0, sizeof(resolve));
curl_msnprintf(resolve_buf, sizeof(resolve_buf)-1, "%s:%s:127.0.0.1",
host, port);
resolve = curl_slist_append(resolve, resolve_buf);
curl = curl_easy_init();
if(!curl) {
curl_mfprintf(stderr, "out of memory\n");
return 1;
}
/* We want to use our own read function. */
curl_easy_setopt(curl, CURLOPT_READFUNCTION, read_callback);
/* It will help us to continue the read function. */
curl_easy_setopt(curl, CURLOPT_XFERINFOFUNCTION, progress_callback);
curl_easy_setopt(curl, CURLOPT_XFERINFODATA, curl);
curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0L);
/* It will help us to ensure that keepalive does not help. */
curl_easy_setopt(curl, CURLOPT_TCP_KEEPALIVE, 1L);
curl_easy_setopt(curl, CURLOPT_TCP_KEEPIDLE, 1L);
curl_easy_setopt(curl, CURLOPT_TCP_KEEPINTVL, 1L);
curl_easy_setopt(curl, CURLOPT_TCP_KEEPCNT, 1L);
/* Enable uploading. */
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "POST");
curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
if(curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L) != CURLE_OK ||
curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, debug_cb)
!= CURLE_OK ||
curl_easy_setopt(curl, CURLOPT_RESOLVE, resolve) != CURLE_OK)
ERR();
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_HTTP_VERSION, http_version);
rc = curl_easy_perform(curl);
if(curl) {
curl_easy_cleanup(curl);
}
curl_slist_free_all(resolve);
curl_free(host);
curl_free(port);
curl_url_cleanup(cu);
curl_global_cleanup();
return (int)rc;
}

View File

@@ -0,0 +1,254 @@
/***************************************************************************
* _ _ ____ _
* 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 "first.h"
#ifndef CURL_DISABLE_WEBSOCKETS
static CURLcode check_recv(const struct curl_ws_frame *frame,
size_t r_offset, size_t nread, size_t exp_len)
{
if(!frame)
return CURLE_OK;
if(frame->flags & CURLWS_CLOSE) {
curl_mfprintf(stderr, "recv_data: unexpected CLOSE frame from server, "
"got %ld bytes, offset=%ld, rflags %x\n",
(long)nread, (long)r_offset, frame->flags);
return CURLE_RECV_ERROR;
}
if(!r_offset && !(frame->flags & CURLWS_BINARY)) {
curl_mfprintf(stderr, "recv_data: wrong frame, got %ld bytes, offset=%ld, "
"rflags %x\n",
(long)nread, (long)r_offset, frame->flags);
return CURLE_RECV_ERROR;
}
if(frame->offset != (curl_off_t)r_offset) {
curl_mfprintf(stderr, "recv_data: frame offset, expected %ld, got %ld\n",
(long)r_offset, (long)frame->offset);
return CURLE_RECV_ERROR;
}
if(frame->bytesleft != (curl_off_t)(exp_len - r_offset - nread)) {
curl_mfprintf(stderr, "recv_data: frame bytesleft, "
"expected %ld, got %ld\n",
(long)(exp_len - r_offset - nread), (long)frame->bytesleft);
return CURLE_RECV_ERROR;
}
if(r_offset + nread > exp_len) {
curl_mfprintf(stderr, "recv_data: data length, expected %ld, now at %ld\n",
(long)exp_len, (long)(r_offset + nread));
return CURLE_RECV_ERROR;
}
return CURLE_OK;
}
static CURLcode data_echo(CURL *curl, size_t count,
size_t plen_min, size_t plen_max)
{
CURLcode r = CURLE_OK;
const struct curl_ws_frame *frame;
size_t len;
char *send_buf = NULL, *recv_buf = NULL;
size_t i, scount = count, rcount = count;
int rblock, sblock;
send_buf = calloc(1, plen_max + 1);
recv_buf = calloc(1, plen_max + 1);
if(!send_buf || !recv_buf) {
r = CURLE_OUT_OF_MEMORY;
goto out;
}
for(i = 0; i < plen_max; ++i) {
send_buf[i] = (char)('0' + ((int)i % 10));
}
for(len = plen_min; len <= plen_max; ++len) {
size_t nwritten, nread, slen = len, rlen = len;
char *sbuf = send_buf, *rbuf = recv_buf;
memset(recv_buf, 0, plen_max);
while(slen || rlen || scount || rcount) {
sblock = rblock = 1;
if(slen) {
r = curl_ws_send(curl, sbuf, slen, &nwritten, 0, CURLWS_BINARY);
sblock = (r == CURLE_AGAIN);
if(!r || (r == CURLE_AGAIN)) {
curl_mfprintf(stderr, "curl_ws_send(len=%ld) -> %d, %ld (%ld/%ld)\n",
(long)slen, r, (long)nwritten,
(long)(len - slen), (long)len);
sbuf += nwritten;
slen -= nwritten;
}
else
goto out;
}
if(!slen && scount) { /* go again? */
scount--;
sbuf = send_buf;
slen = len;
}
if(rlen) {
size_t max_recv = (64 * 1024);
r = curl_ws_recv(curl, rbuf, (rlen > max_recv) ? max_recv : rlen,
&nread, &frame);
if(!r || (r == CURLE_AGAIN)) {
rblock = (r == CURLE_AGAIN);
curl_mfprintf(stderr, "curl_ws_recv(len=%ld) -> %d, %ld (%ld/%ld) "
"\n",
(long)rlen, r, (long)nread, (long)(len - rlen),
(long)len);
if(!r) {
r = check_recv(frame, len - rlen, nread, len);
if(r)
goto out;
}
rbuf += nread;
rlen -= nread;
}
else
goto out;
}
if(!rlen && rcount) { /* go again? */
rcount--;
rbuf = recv_buf;
rlen = len;
}
if(rblock && sblock) {
curl_mfprintf(stderr, "EAGAIN, sleep, try again\n");
curlx_wait_ms(100);
}
}
if(memcmp(send_buf, recv_buf, len)) {
curl_mfprintf(stderr, "recv_data: data differs\n");
dump("expected:", (unsigned char *)send_buf, len, 0);
dump("received:", (unsigned char *)recv_buf, len, 0);
r = CURLE_RECV_ERROR;
goto out;
}
}
out:
if(!r)
websocket_close(curl);
free(send_buf);
free(recv_buf);
return r;
}
static void usage_ws_data(const char *msg)
{
if(msg)
curl_mfprintf(stderr, "%s\n", msg);
curl_mfprintf(stderr,
"usage: [options] url\n"
" -m number minimum frame size\n"
" -M number maximum frame size\n"
);
}
#endif
static int test_ws_data(int argc, char *argv[])
{
#ifndef CURL_DISABLE_WEBSOCKETS
CURL *curl;
CURLcode res = CURLE_OK;
const char *url;
size_t plen_min = 0, plen_max = 0, count = 1;
int ch;
while((ch = cgetopt(argc, argv, "c:hm:M:")) != -1) {
switch(ch) {
case 'h':
usage_ws_data(NULL);
res = CURLE_BAD_FUNCTION_ARGUMENT;
goto cleanup;
case 'c':
count = (size_t)strtol(coptarg, NULL, 10);
break;
case 'm':
plen_min = (size_t)strtol(coptarg, NULL, 10);
break;
case 'M':
plen_max = (size_t)strtol(coptarg, NULL, 10);
break;
default:
usage_ws_data("invalid option");
res = CURLE_BAD_FUNCTION_ARGUMENT;
goto cleanup;
}
}
argc -= coptind;
argv += coptind;
if(!plen_max)
plen_max = plen_min;
if(plen_max < plen_min) {
curl_mfprintf(stderr, "maxlen must be >= minlen, got %ld-%ld\n",
(long)plen_min, (long)plen_max);
res = CURLE_BAD_FUNCTION_ARGUMENT;
goto cleanup;
}
if(argc != 1) {
usage_ws_data(NULL);
res = CURLE_BAD_FUNCTION_ARGUMENT;
goto cleanup;
}
url = argv[0];
curl_global_init(CURL_GLOBAL_ALL);
curl = curl_easy_init();
if(curl) {
curl_easy_setopt(curl, CURLOPT_URL, url);
/* use the callback style */
curl_easy_setopt(curl, CURLOPT_USERAGENT, "ws-data");
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
curl_easy_setopt(curl, CURLOPT_CONNECT_ONLY, 2L); /* websocket style */
res = curl_easy_perform(curl);
curl_mfprintf(stderr, "curl_easy_perform() returned %u\n", (int)res);
if(res == CURLE_OK)
res = data_echo(curl, count, plen_min, plen_max);
/* always cleanup */
curl_easy_cleanup(curl);
}
cleanup:
curl_global_cleanup();
return (int)res;
#else /* !CURL_DISABLE_WEBSOCKETS */
(void)argc;
(void)argv;
curl_mfprintf(stderr, "WebSockets not enabled in libcurl\n");
return 1;
#endif /* CURL_DISABLE_WEBSOCKETS */
}

View File

@@ -0,0 +1,133 @@
/***************************************************************************
* _ _ ____ _
* 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 "first.h"
#ifndef CURL_DISABLE_WEBSOCKETS
static CURLcode ping(CURL *curl, const char *send_payload)
{
size_t sent;
CURLcode result =
curl_ws_send(curl, send_payload, strlen(send_payload), &sent, 0,
CURLWS_PING);
curl_mfprintf(stderr, "ws: curl_ws_send returned %u, sent %u\n",
(int)result, (int)sent);
return result;
}
static CURLcode recv_pong(CURL *curl, const char *expected_payload)
{
size_t rlen;
const struct curl_ws_frame *meta;
char buffer[256];
CURLcode result = curl_ws_recv(curl, buffer, sizeof(buffer), &rlen, &meta);
if(result) {
curl_mfprintf(stderr, "ws: curl_ws_recv returned %u, received %ld\n",
(int)result, (long)rlen);
return result;
}
if(!(meta->flags & CURLWS_PONG)) {
curl_mfprintf(stderr, "recv_pong: wrong frame, got %d bytes rflags %x\n",
(int)rlen, meta->flags);
return CURLE_RECV_ERROR;
}
curl_mfprintf(stderr, "ws: got PONG back\n");
if(rlen == strlen(expected_payload) &&
!memcmp(expected_payload, buffer, rlen)) {
curl_mfprintf(stderr, "ws: got the same payload back\n");
return CURLE_OK;
}
curl_mfprintf(stderr, "ws: did NOT get the same payload back\n");
return CURLE_RECV_ERROR;
}
static CURLcode pingpong(CURL *curl, const char *payload)
{
CURLcode res;
int i;
res = ping(curl, payload);
if(res)
return res;
for(i = 0; i < 10; ++i) {
curl_mfprintf(stderr, "Receive pong\n");
res = recv_pong(curl, payload);
if(res == CURLE_AGAIN) {
curlx_wait_ms(100);
continue;
}
websocket_close(curl);
return res;
}
websocket_close(curl);
return CURLE_RECV_ERROR;
}
#endif
static int test_ws_pingpong(int argc, char *argv[])
{
#ifndef CURL_DISABLE_WEBSOCKETS
CURL *curl;
CURLcode res = CURLE_OK;
const char *url, *payload;
if(argc != 3) {
curl_mfprintf(stderr, "usage: ws-pingpong url payload\n");
return 2;
}
url = argv[1];
payload = argv[2];
curl_global_init(CURL_GLOBAL_ALL);
curl = curl_easy_init();
if(curl) {
curl_easy_setopt(curl, CURLOPT_URL, url);
/* use the callback style */
curl_easy_setopt(curl, CURLOPT_USERAGENT, "ws-pingpong");
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
curl_easy_setopt(curl, CURLOPT_CONNECT_ONLY, 2L); /* websocket style */
res = curl_easy_perform(curl);
curl_mfprintf(stderr, "curl_easy_perform() returned %u\n", (int)res);
if(res == CURLE_OK)
res = pingpong(curl, payload);
/* always cleanup */
curl_easy_cleanup(curl);
}
curl_global_cleanup();
return (int)res;
#else /* !CURL_DISABLE_WEBSOCKETS */
(void)argc;
(void)argv;
curl_mfprintf(stderr, "WebSockets not enabled in libcurl\n");
return 1;
#endif /* CURL_DISABLE_WEBSOCKETS */
}