Merge topic 'update-curl'

fe2fe52c86 curl: Set build options the way we need for CMake
548f0cfd1d Merge branch 'upstream-curl' into update-curl
fe5ffe06a9 curl 2023-12-06 (7161cb17)
38f85b8390 curl: Update script to get curl 8.5.0

Acked-by: Kitware Robot <kwrobot@kitware.com>
Acked-by: buildbot <buildbot@kitware.com>
Merge-request: !9069
This commit is contained in:
Brad King
2023-12-15 14:33:20 +00:00
committed by Kitware Robot
151 changed files with 5596 additions and 4615 deletions
+1 -1
View File
@@ -8,7 +8,7 @@ readonly name="curl"
readonly ownership="Curl Upstream <curl-library@lists.haxx.se>"
readonly subtree="Utilities/cmcurl"
readonly repo="https://github.com/curl/curl.git"
readonly tag="curl-8_4_0"
readonly tag="curl-8_5_0"
readonly shortlog=false
readonly paths="
CMake/*
+88 -158
View File
@@ -23,7 +23,6 @@
***************************************************************************/
#ifdef HAVE_FCNTL_O_NONBLOCK
/* headers for FCNTL_O_NONBLOCK test */
#include <sys/types.h>
#include <unistd.h>
@@ -45,14 +44,13 @@
#error "O_NONBLOCK does not work on this platform"
#endif
int
main ()
int main(void)
{
/* O_NONBLOCK source test */
int flags = 0;
if(0 != fcntl(0, F_SETFL, flags | O_NONBLOCK))
return 1;
return 0;
/* O_NONBLOCK source test */
int flags = 0;
if(0 != fcntl(0, F_SETFL, flags | O_NONBLOCK))
return 1;
return 0;
}
#endif
@@ -108,36 +106,16 @@ int main(void)
}
#endif
#ifdef HAVE_SOCKLEN_T
#ifdef _WIN32
#include <ws2tcpip.h>
#else
#include <sys/types.h>
#include <sys/socket.h>
#endif
int
main ()
{
if ((socklen_t *) 0)
return 0;
if (sizeof (socklen_t))
return 0;
;
return 0;
}
#endif
#ifdef HAVE_IN_ADDR_T
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
int
main ()
int main(void)
{
if ((in_addr_t *) 0)
return 0;
if (sizeof (in_addr_t))
return 0;
if((in_addr_t *) 0)
return 0;
if(sizeof(in_addr_t))
return 0;
;
return 0;
}
@@ -150,11 +128,10 @@ if (sizeof (in_addr_t))
#ifdef HAVE_STDBOOL_H
#include <stdbool.h>
#endif
int
main ()
int main(void)
{
if (sizeof (bool *) )
return 0;
if(sizeof(bool *))
return 0;
;
return 0;
}
@@ -165,8 +142,9 @@ if (sizeof (bool *) )
#include <stdarg.h>
#include <string.h>
#include <float.h>
int main() { return 0; }
int main(void) { return 0; }
#endif
#ifdef HAVE_FILE_OFFSET_BITS
#ifdef _FILE_OFFSET_BITS
#undef _FILE_OFFSET_BITS
@@ -181,104 +159,95 @@ int main() { return 0; }
int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
&& LARGE_OFF_T % 2147483647 == 1)
? 1 : -1];
int main () { ; return 0; }
int main(void) { ; return 0; }
#endif
#ifdef HAVE_IOCTLSOCKET
/* includes start */
#ifdef HAVE_WINDOWS_H
# ifndef WIN32_LEAN_AND_MEAN
# define WIN32_LEAN_AND_MEAN
# endif
# include <windows.h>
# ifdef HAVE_WINSOCK2_H
# include <winsock2.h>
# endif
# include <windows.h>
#endif
int
main ()
int main(void)
{
/* ioctlsocket source code */
int socket;
unsigned long flags = ioctlsocket(socket, FIONBIO, &flags);
/* ioctlsocket source code */
int socket;
unsigned long flags = ioctlsocket(socket, FIONBIO, &flags);
;
return 0;
}
#endif
#ifdef HAVE_IOCTLSOCKET_CAMEL
/* includes start */
#ifdef HAVE_WINDOWS_H
# ifndef WIN32_LEAN_AND_MEAN
# define WIN32_LEAN_AND_MEAN
# endif
# include <windows.h>
# ifdef HAVE_WINSOCK2_H
# include <winsock2.h>
# endif
# include <windows.h>
#endif
int
main ()
int main(void)
{
/* IoctlSocket source code */
if(0 != IoctlSocket(0, 0, 0))
return 1;
/* IoctlSocket source code */
if(0 != IoctlSocket(0, 0, 0))
return 1;
;
return 0;
}
#endif
#ifdef HAVE_IOCTLSOCKET_CAMEL_FIONBIO
/* includes start */
#ifdef HAVE_WINDOWS_H
# ifndef WIN32_LEAN_AND_MEAN
# define WIN32_LEAN_AND_MEAN
# endif
# include <windows.h>
# ifdef HAVE_WINSOCK2_H
# include <winsock2.h>
# endif
# include <windows.h>
#endif
int
main ()
int main(void)
{
/* IoctlSocket source code */
long flags = 0;
if(0 != IoctlSocket(0, FIONBIO, &flags))
return 1;
/* IoctlSocket source code */
long flags = 0;
if(0 != IoctlSocket(0, FIONBIO, &flags))
return 1;
;
return 0;
}
#endif
#ifdef HAVE_IOCTLSOCKET_FIONBIO
/* includes start */
#ifdef HAVE_WINDOWS_H
# ifndef WIN32_LEAN_AND_MEAN
# define WIN32_LEAN_AND_MEAN
# endif
# include <windows.h>
# ifdef HAVE_WINSOCK2_H
# include <winsock2.h>
# endif
# include <windows.h>
#endif
int
main ()
int main(void)
{
int flags = 0;
if(0 != ioctlsocket(0, FIONBIO, &flags))
return 1;
int flags = 0;
if(0 != ioctlsocket(0, FIONBIO, &flags))
return 1;
;
return 0;
}
#endif
#ifdef HAVE_IOCTL_FIONBIO
/* headers for FIONBIO test */
/* includes start */
@@ -297,19 +266,16 @@ main ()
#ifdef HAVE_STROPTS_H
# include <stropts.h>
#endif
int
main ()
int main(void)
{
int flags = 0;
if(0 != ioctl(0, FIONBIO, &flags))
return 1;
int flags = 0;
if(0 != ioctl(0, FIONBIO, &flags))
return 1;
;
return 0;
}
#endif
#ifdef HAVE_IOCTL_SIOCGIFADDR
/* headers for FIONBIO test */
/* includes start */
@@ -329,28 +295,26 @@ main ()
# include <stropts.h>
#endif
#include <net/if.h>
int
main ()
int main(void)
{
struct ifreq ifr;
if(0 != ioctl(0, SIOCGIFADDR, &ifr))
return 1;
struct ifreq ifr;
if(0 != ioctl(0, SIOCGIFADDR, &ifr))
return 1;
;
return 0;
}
#endif
#ifdef HAVE_SETSOCKOPT_SO_NONBLOCK
/* includes start */
#ifdef HAVE_WINDOWS_H
# ifndef WIN32_LEAN_AND_MEAN
# define WIN32_LEAN_AND_MEAN
# endif
# include <windows.h>
# ifdef HAVE_WINSOCK2_H
# include <winsock2.h>
# endif
# include <windows.h>
#endif
/* includes start */
#ifdef HAVE_SYS_TYPES_H
@@ -360,30 +324,30 @@ main ()
# include <sys/socket.h>
#endif
/* includes end */
int
main ()
int main(void)
{
if(0 != setsockopt(0, SOL_SOCKET, SO_NONBLOCK, 0, 0))
return 1;
if(0 != setsockopt(0, SOL_SOCKET, SO_NONBLOCK, 0, 0))
return 1;
;
return 0;
}
#endif
#ifdef HAVE_GLIBC_STRERROR_R
#include <string.h>
#include <errno.h>
void check(char c) {}
int
main () {
int main(void)
{
char buffer[1024];
/* This will not compile if strerror_r does not return a char* */
check(strerror_r(EACCES, buffer, sizeof(buffer))[0]);
return 0;
}
#endif
#ifdef HAVE_POSIX_STRERROR_R
#include <string.h>
#include <errno.h>
@@ -391,92 +355,51 @@ main () {
/* float, because a pointer can't be implicitly cast to float */
void check(float f) {}
int
main () {
int main(void)
{
char buffer[1024];
/* This will not compile if strerror_r does not return an int */
check(strerror_r(EACCES, buffer, sizeof(buffer)));
return 0;
}
#endif
#ifdef HAVE_FSETXATTR_6
#include <sys/xattr.h> /* header from libc, not from libattr */
int
main() {
int main(void)
{
fsetxattr(0, 0, 0, 0, 0, 0);
return 0;
}
#endif
#ifdef HAVE_FSETXATTR_5
#include <sys/xattr.h> /* header from libc, not from libattr */
int
main() {
int main(void)
{
fsetxattr(0, 0, 0, 0, 0);
return 0;
}
#endif
#ifdef HAVE_CLOCK_GETTIME_MONOTONIC
#include <time.h>
int
main() {
int main(void)
{
struct timespec ts = {0, 0};
clock_gettime(CLOCK_MONOTONIC, &ts);
return 0;
}
#endif
#ifdef HAVE_BUILTIN_AVAILABLE
int
main() {
int main(void)
{
if(__builtin_available(macOS 10.12, *)) {}
return 0;
}
#endif
#ifdef HAVE_VARIADIC_MACROS_C99
#define c99_vmacro3(first, ...) fun3(first, __VA_ARGS__)
#define c99_vmacro2(first, ...) fun2(first, __VA_ARGS__)
int fun3(int arg1, int arg2, int arg3);
int fun2(int arg1, int arg2);
int fun3(int arg1, int arg2, int arg3) {
return arg1 + arg2 + arg3;
}
int fun2(int arg1, int arg2) {
return arg1 + arg2;
}
int
main() {
int res3 = c99_vmacro3(1, 2, 3);
int res2 = c99_vmacro2(1, 2);
(void)res3;
(void)res2;
return 0;
}
#endif
#ifdef HAVE_VARIADIC_MACROS_GCC
#define gcc_vmacro3(first, args...) fun3(first, args)
#define gcc_vmacro2(first, args...) fun2(first, args)
int fun3(int arg1, int arg2, int arg3);
int fun2(int arg1, int arg2);
int fun3(int arg1, int arg2, int arg3) {
return arg1 + arg2 + arg3;
}
int fun2(int arg1, int arg2) {
return arg1 + arg2;
}
int
main() {
int res3 = gcc_vmacro3(1, 2, 3);
int res2 = gcc_vmacro2(1, 2);
(void)res3;
(void)res2;
return 0;
}
#endif
#ifdef HAVE_ATOMIC
/* includes start */
#ifdef HAVE_SYS_TYPES_H
@@ -490,17 +413,24 @@ main() {
#endif
/* includes end */
int
main() {
int main(void)
{
_Atomic int i = 1;
i = 0; /* Force an atomic-write operation. */
return i;
}
#endif
#ifdef HAVE_WIN32_WINNT
/* includes start */
#ifdef WIN32
# include "../lib/setup-win32.h"
#ifdef _WIN32
# ifndef WIN32_LEAN_AND_MEAN
# define WIN32_LEAN_AND_MEAN
# endif
# ifndef NOGDI
# define NOGDI
# endif
# include <windows.h>
#endif
/* includes end */
@@ -508,8 +438,8 @@ main() {
#define expand(x) enquote(x)
#pragma message("_WIN32_WINNT=" expand(_WIN32_WINNT))
int
main() {
int main(void)
{
return 0;
}
#endif
+7
View File
@@ -56,11 +56,18 @@ find_library(Zstd_LIBRARY NAMES zstd
${PC_Zstd_LIBRARY_DIRS}
)
if(Zstd_INCLUDE_DIR)
file(READ "${Zstd_INCLUDE_DIR}/zstd.h" _zstd_header)
string(REGEX MATCH ".*define ZSTD_VERSION_MAJOR *([0-9]+).*define ZSTD_VERSION_MINOR *([0-9]+).*define ZSTD_VERSION_RELEASE *([0-9]+)" _zstd_ver "${_zstd_header}")
set(Zstd_VERSION "${CMAKE_MATCH_1}.${CMAKE_MATCH_2}.${CMAKE_MATCH_3}")
endif()
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(Zstd
REQUIRED_VARS
Zstd_LIBRARY
Zstd_INCLUDE_DIR
VERSION_VAR Zstd_VERSION
)
if(Zstd_FOUND)
-13
View File
@@ -23,19 +23,6 @@
###########################################################################
#File defines convenience macros for available feature testing
# This macro checks if the symbol exists in the library and if it
# does, it prepends library to the list. It is intended to be called
# multiple times with a sequence of possibly dependent libraries in
# order of least-to-most-dependent. Some libraries depend on others
# to link correctly.
macro(check_library_exists_concat LIBRARY SYMBOL VARIABLE)
check_library_exists("${LIBRARY};${CURL_LIBS}" ${SYMBOL} "${CMAKE_LIBRARY_PATH}"
${VARIABLE})
if(${VARIABLE})
set(CURL_LIBS ${LIBRARY} ${CURL_LIBS})
endif()
endmacro()
# Check if header file exists and add it to the list.
# This macro is intended to be called multiple times with a sequence of
# possibly dependent header files. Some headers depend on others to be
+7 -7
View File
@@ -35,13 +35,13 @@ endmacro()
set(signature_call_conv)
if(HAVE_WINDOWS_H)
add_header_include(HAVE_WINSOCK2_H "winsock2.h")
add_header_include(HAVE_WINDOWS_H "windows.h")
set(_source_epilogue
"${_source_epilogue}\n#ifndef WIN32_LEAN_AND_MEAN\n#define WIN32_LEAN_AND_MEAN\n#endif")
add_header_include(HAVE_WINSOCK2_H "winsock2.h")
add_header_include(HAVE_WINDOWS_H "windows.h")
set(signature_call_conv "PASCAL")
if(WIN32)
set(CMAKE_REQUIRED_LIBRARIES ws2_32)
set(CMAKE_REQUIRED_LIBRARIES "ws2_32")
endif()
else()
add_header_include(HAVE_SYS_TYPES_H "sys/types.h")
@@ -71,11 +71,11 @@ int main(void) {
}" HAVE_STRUCT_TIMEVAL)
if(HAVE_WINDOWS_H)
set(CMAKE_EXTRA_INCLUDE_FILES winsock2.h)
set(CMAKE_EXTRA_INCLUDE_FILES "winsock2.h")
else()
set(CMAKE_EXTRA_INCLUDE_FILES)
if(HAVE_SYS_SOCKET_H)
set(CMAKE_EXTRA_INCLUDE_FILES sys/socket.h)
set(CMAKE_EXTRA_INCLUDE_FILES "sys/socket.h")
endif()
endif()
@@ -172,7 +172,7 @@ if(NOT DEFINED HAVE_GETADDRINFO_THREADSAFE)
}" HAVE_H_ERRNO)
if(NOT HAVE_H_ERRNO)
check_c_source_runs("${_source_epilogue}
check_c_source_compiles("${_source_epilogue}
int main(void)
{
h_errno = 2;
@@ -201,7 +201,7 @@ if(NOT DEFINED HAVE_GETADDRINFO_THREADSAFE)
set(_source_epilogue "${_save_epilogue}")
endif()
if(NOT DEFINED HAVE_CLOCK_GETTIME_MONOTONIC_RAW)
if(NOT WIN32 AND NOT DEFINED HAVE_CLOCK_GETTIME_MONOTONIC_RAW)
set(_save_epilogue "${_source_epilogue}")
set(_source_epilogue "#undef inline")
+28 -9
View File
@@ -52,8 +52,8 @@ if(PICKY_COMPILER)
# Assume these options always exist with both clang and gcc.
# Require clang 3.0 / gcc 2.95 or later.
list(APPEND WPICKY_ENABLE
-Wbad-function-cast # clang 3.0 gcc 2.95
-Wconversion # clang 3.0 gcc 2.95
-Wbad-function-cast # clang 2.7 gcc 2.95
-Wconversion # clang 2.7 gcc 2.95
-Winline # clang 1.0 gcc 1.0
-Wmissing-declarations # clang 1.0 gcc 2.7
-Wmissing-prototypes # clang 1.0 gcc 1.0
@@ -70,23 +70,37 @@ if(PICKY_COMPILER)
# Always enable with clang, version dependent with gcc
set(WPICKY_COMMON_OLD
-Waddress # clang 2.7 gcc 4.3
-Wattributes # clang 2.7 gcc 4.1
-Wcast-align # clang 1.0 gcc 4.2
-Wdeclaration-after-statement # clang 1.0 gcc 3.4
-Wempty-body # clang 3.0 gcc 4.3
-Wdiv-by-zero # clang 2.7 gcc 4.1
-Wempty-body # clang 2.7 gcc 4.3
-Wendif-labels # clang 1.0 gcc 3.3
-Wfloat-equal # clang 1.0 gcc 2.96 (3.0)
-Wignored-qualifiers # clang 3.0 gcc 4.3
-Wformat-security # clang 2.7 gcc 4.1
-Wignored-qualifiers # clang 2.8 gcc 4.3
-Wmissing-field-initializers # clang 2.7 gcc 4.1
-Wmissing-noreturn # clang 2.7 gcc 4.1
-Wno-format-nonliteral # clang 1.0 gcc 2.96 (3.0)
-Wno-sign-conversion # clang 3.0 gcc 4.3
-Wno-sign-conversion # clang 2.9 gcc 4.3
-Wno-system-headers # clang 1.0 gcc 3.0
# -Wpadded # clang 2.9 gcc 4.1 # Not used because we cannot change public structs
-Wredundant-decls # clang 2.7 gcc 4.1
-Wold-style-definition # clang 2.7 gcc 3.4
-Wstrict-prototypes # clang 1.0 gcc 3.3
-Wtype-limits # clang 3.0 gcc 4.3
# -Wswitch-enum # clang 2.7 gcc 4.1 # Not used because this basically disallows default case
-Wtype-limits # clang 2.7 gcc 4.3
-Wunreachable-code # clang 2.7 gcc 4.1
# -Wunused-macros # clang 2.7 gcc 4.1 # Not practical
-Wunused-parameter # clang 2.7 gcc 4.1
-Wvla # clang 2.8 gcc 4.3
)
set(WPICKY_COMMON
-Wdouble-promotion # clang 3.6 gcc 4.6 appleclang 6.3
-Wenum-conversion # clang 3.2 gcc 10.0 appleclang 4.6 g++ 11.0
-Wpragmas # clang 3.5 gcc 4.1 appleclang 6.0
-Wunused-const-variable # clang 3.4 gcc 6.0 appleclang 5.1
)
@@ -95,12 +109,16 @@ if(PICKY_COMPILER)
${WPICKY_COMMON_OLD}
-Wshift-sign-overflow # clang 2.9
-Wshorten-64-to-32 # clang 1.0
-Wlanguage-extension-token # clang 3.0
)
# Enable based on compiler version
if((CMAKE_C_COMPILER_ID STREQUAL "Clang" AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 3.6) OR
(CMAKE_C_COMPILER_ID STREQUAL "AppleClang" AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 6.3))
list(APPEND WPICKY_ENABLE
${WPICKY_COMMON}
-Wunreachable-code-break # clang 3.5 appleclang 6.0
-Wheader-guard # clang 3.4 appleclang 5.1
-Wsometimes-uninitialized # clang 3.2 appleclang 4.6
)
endif()
if((CMAKE_C_COMPILER_ID STREQUAL "Clang" AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 3.9) OR
@@ -125,6 +143,7 @@ if(PICKY_COMPILER)
if(NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 4.3)
list(APPEND WPICKY_ENABLE
${WPICKY_COMMON_OLD}
-Wclobbered # gcc 4.3
-Wmissing-parameter-type # gcc 4.3
-Wold-style-declaration # gcc 4.3
-Wstrict-aliasing=3 # gcc 4.0
@@ -159,7 +178,7 @@ if(PICKY_COMPILER)
-Walloc-zero # gcc 7.0
-Wduplicated-branches # gcc 7.0
-Wformat-overflow=2 # gcc 7.0
-Wformat-truncation=1 # gcc 7.0
-Wformat-truncation=2 # gcc 7.0
-Wrestrict # gcc 7.0
)
endif()
@@ -174,11 +193,11 @@ if(PICKY_COMPILER)
unset(WPICKY)
foreach(_CCOPT ${WPICKY_ENABLE})
foreach(_CCOPT IN LISTS WPICKY_ENABLE)
set(WPICKY "${WPICKY} ${_CCOPT}")
endforeach()
foreach(_CCOPT ${WPICKY_DETECT})
foreach(_CCOPT IN LISTS WPICKY_DETECT)
# surprisingly, CHECK_C_COMPILER_FLAG needs a new variable to store each new
# test result in.
string(MAKE_C_IDENTIFIER "OPT${_CCOPT}" _optvarname)
@@ -21,113 +21,167 @@
# SPDX-License-Identifier: curl
#
###########################################################################
if(NOT UNIX)
if(WIN32)
if(NOT WIN32)
message(FATAL_ERROR "This file should be included on Windows platform only")
endif()
set(HAVE_WINDOWS_H 1)
set(HAVE_WS2TCPIP_H 1)
set(HAVE_WINSOCK2_H 1)
set(HAVE_LOCALE_H 1)
if(MINGW)
set(HAVE_SNPRINTF 1)
set(HAVE_UNISTD_H 1)
set(HAVE_INTTYPES_H 1)
if(MINGW)
set(HAVE_SNPRINTF 1)
set(HAVE_UNISTD_H 1)
set(HAVE_LIBGEN_H 1)
set(HAVE_STDDEF_H 1) # detected by CMake internally in check_type_size()
set(HAVE_STDBOOL_H 1)
set(HAVE_BOOL_T "${HAVE_STDBOOL_H}")
set(HAVE_STRTOLL 1)
set(HAVE_BASENAME 1)
set(HAVE_STRCASECMP 1)
set(HAVE_FTRUNCATE 1)
set(HAVE_SYS_PARAM_H 1)
set(HAVE_SYS_TIME_H 1)
set(HAVE_GETTIMEOFDAY 1)
else()
set(HAVE_LIBGEN_H 0)
set(HAVE_STRCASECMP 0)
set(HAVE_FTRUNCATE 0)
set(HAVE_SYS_PARAM_H 0)
set(HAVE_SYS_TIME_H 0)
set(HAVE_GETTIMEOFDAY 0)
if(MSVC)
set(HAVE_UNISTD_H 0)
set(HAVE_LOCALE_H 1)
set(HAVE_STDDEF_H 1) # detected by CMake internally in check_type_size()
set(HAVE_STDATOMIC_H 0)
if(NOT MSVC_VERSION LESS 1800)
set(HAVE_STDBOOL_H 1)
set(HAVE_STRTOLL 1)
set(HAVE_BASENAME 1)
elseif(MSVC)
if(NOT MSVC_VERSION LESS 1800)
set(HAVE_INTTYPES_H 1)
set(HAVE_STRTOLL 1)
else()
set(HAVE_INTTYPES_H 0)
set(HAVE_STRTOLL 0)
endif()
if(NOT MSVC_VERSION LESS 1900)
set(HAVE_SNPRINTF 1)
else()
set(HAVE_SNPRINTF 0)
endif()
set(HAVE_BASENAME 0)
else()
set(HAVE_STDBOOL_H 0)
set(HAVE_STRTOLL 0)
endif()
set(HAVE_LIBSOCKET 0)
set(HAVE_GETHOSTNAME 1)
set(HAVE_LIBZ 0)
set(HAVE_ARC4RANDOM 0)
set(HAVE_FNMATCH 0)
set(HAVE_SCHED_YIELD 0)
set(HAVE_ARPA_INET_H 0)
set(HAVE_FCNTL_H 1)
set(HAVE_IFADDRS_H 0)
set(HAVE_IO_H 1)
set(HAVE_NETDB_H 0)
set(HAVE_NETINET_IN_H 0)
set(HAVE_NETINET_TCP_H 0)
set(HAVE_NETINET_UDP_H 0)
set(HAVE_NET_IF_H 0)
set(HAVE_IOCTL_SIOCGIFADDR 0)
set(HAVE_POLL_H 0)
set(HAVE_POLL_FINE 0)
set(HAVE_PWD_H 0)
set(HAVE_STRINGS_H 0)
set(HAVE_SYS_FILIO_H 0)
set(HAVE_SYS_WAIT_H 0)
set(HAVE_SYS_IOCTL_H 0)
set(HAVE_SYS_PARAM_H 0)
set(HAVE_SYS_POLL_H 0)
set(HAVE_SYS_RESOURCE_H 0)
set(HAVE_SYS_SELECT_H 0)
set(HAVE_SYS_SOCKET_H 0)
set(HAVE_SYS_SOCKIO_H 0)
set(HAVE_SYS_STAT_H 1)
set(HAVE_SYS_TIME_H 0)
set(HAVE_SYS_TYPES_H 1)
set(HAVE_SYS_UN_H 0)
set(HAVE_SYS_UTIME_H 1)
set(HAVE_TERMIOS_H 0)
set(HAVE_TERMIO_H 0)
set(HAVE_UTIME_H 0)
set(HAVE_FSEEKO 0)
set(HAVE__FSEEKI64 1)
set(HAVE_SOCKET 1)
set(HAVE_SELECT 1)
set(HAVE_STRDUP 1)
set(HAVE_STRICMP 1)
set(HAVE_STRCMPI 1)
set(HAVE_MEMRCHR 0)
set(HAVE_GETTIMEOFDAY 0)
set(HAVE_CLOSESOCKET 1)
set(HAVE_SIGSETJMP 0)
set(HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID 1)
set(HAVE_GETPASS_R 0)
set(HAVE_GETPWUID 0)
set(HAVE_GETEUID 0)
set(HAVE_UTIME 1)
set(HAVE_GMTIME_R 0)
set(HAVE_CLOCK_GETTIME_MONOTONIC_RAW 0)
set(HAVE_GETHOSTBYNAME_R 0)
set(HAVE_SIGNAL 1)
set(HAVE_LINUX_TCP_H 0)
set(HAVE_GLIBC_STRERROR_R 0)
set(HAVE_MACH_ABSOLUTE_TIME 0)
set(HAVE_GETIFADDRS 0)
set(HAVE_GETHOSTBYNAME_R_3 0)
set(HAVE_GETHOSTBYNAME_R_3_REENTRANT 0)
set(HAVE_GETHOSTBYNAME_R_5 0)
set(HAVE_GETHOSTBYNAME_R_5_REENTRANT 0)
set(HAVE_GETHOSTBYNAME_R_6 0)
set(HAVE_GETHOSTBYNAME_R_6_REENTRANT 0)
set(HAVE_O_NONBLOCK 0)
set(HAVE_IN_ADDR_T 0)
set(STDC_HEADERS 1)
set(HAVE_SIGACTION 0)
set(HAVE_MACRO_SIGSETJMP 0)
else()
message("This file should be included on Windows platform only")
set(HAVE_BOOL_T "${HAVE_STDBOOL_H}")
if(NOT MSVC_VERSION LESS 1900)
set(HAVE_SNPRINTF 1)
else()
set(HAVE_SNPRINTF 0)
endif()
set(HAVE_BASENAME 0)
set(HAVE_STRTOK_R 0)
set(HAVE_FILE_OFFSET_BITS 0)
set(HAVE_ATOMIC 0)
endif()
endif()
# Available in Windows XP and newer
set(HAVE_GETADDRINFO 1)
set(HAVE_FREEADDRINFO 1)
set(HAVE_FCHMOD 0)
set(HAVE_SOCKETPAIR 0)
set(HAVE_SENDMSG 0)
set(HAVE_ALARM 0)
set(HAVE_FCNTL 0)
set(HAVE_GETPPID 0)
set(HAVE_UTIMES 0)
set(HAVE_GETPWUID_R 0)
set(HAVE_STRERROR_R 0)
set(HAVE_SIGINTERRUPT 0)
set(HAVE_PIPE 0)
set(HAVE_IF_NAMETOINDEX 0)
set(HAVE_GETRLIMIT 0)
set(HAVE_SETRLIMIT 0)
set(HAVE_FSETXATTR 0)
set(HAVE_LIBSOCKET 0)
set(HAVE_SETLOCALE 1)
set(HAVE_SETMODE 1)
set(HAVE_GETPEERNAME 1)
set(HAVE_GETSOCKNAME 1)
set(HAVE_GETHOSTNAME 1)
set(HAVE_LIBZ 0)
set(HAVE_RECV 1)
set(HAVE_SEND 1)
set(HAVE_STROPTS_H 0)
set(HAVE_SYS_XATTR_H 0)
set(HAVE_ARC4RANDOM 0)
set(HAVE_FNMATCH 0)
set(HAVE_SCHED_YIELD 0)
set(HAVE_ARPA_INET_H 0)
set(HAVE_FCNTL_H 1)
set(HAVE_IFADDRS_H 0)
set(HAVE_IO_H 1)
set(HAVE_NETDB_H 0)
set(HAVE_NETINET_IN_H 0)
set(HAVE_NETINET_TCP_H 0)
set(HAVE_NETINET_UDP_H 0)
set(HAVE_NET_IF_H 0)
set(HAVE_IOCTL_SIOCGIFADDR 0)
set(HAVE_POLL_H 0)
set(HAVE_POLL_FINE 0)
set(HAVE_PWD_H 0)
set(HAVE_STRINGS_H 0) # mingw-w64 has it (wrapper to string.h)
set(HAVE_SYS_FILIO_H 0)
set(HAVE_SYS_WAIT_H 0)
set(HAVE_SYS_IOCTL_H 0)
set(HAVE_SYS_POLL_H 0)
set(HAVE_SYS_RESOURCE_H 0)
set(HAVE_SYS_SELECT_H 0)
set(HAVE_SYS_SOCKET_H 0)
set(HAVE_SYS_SOCKIO_H 0)
set(HAVE_SYS_STAT_H 1)
set(HAVE_SYS_TYPES_H 1)
set(HAVE_SYS_UN_H 0)
set(HAVE_SYS_UTIME_H 1)
set(HAVE_TERMIOS_H 0)
set(HAVE_TERMIO_H 0)
set(HAVE_UTIME_H 0) # mingw-w64 has it (wrapper to sys/utime.h)
set(HAVE_FSEEKO 0)
set(HAVE__FSEEKI64 1)
set(HAVE_SOCKET 1)
set(HAVE_SELECT 1)
set(HAVE_STRDUP 1)
set(HAVE_STRICMP 1)
set(HAVE_STRCMPI 1)
set(HAVE_MEMRCHR 0)
set(HAVE_CLOSESOCKET 1)
set(HAVE_SIGSETJMP 0)
set(HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID 1)
set(HAVE_GETPASS_R 0)
set(HAVE_GETPWUID 0)
set(HAVE_GETEUID 0)
set(HAVE_UTIME 1)
set(HAVE_GMTIME_R 0)
set(HAVE_GETHOSTBYNAME_R 0)
set(HAVE_SIGNAL 1)
set(HAVE_SIGACTION 0)
set(HAVE_LINUX_TCP_H 0)
set(HAVE_GLIBC_STRERROR_R 0)
set(HAVE_MACH_ABSOLUTE_TIME 0)
set(HAVE_GETIFADDRS 0)
set(HAVE_FCNTL_O_NONBLOCK 0)
set(HAVE_IOCTLSOCKET 1)
set(HAVE_IOCTLSOCKET_CAMEL 0)
set(HAVE_IOCTLSOCKET_CAMEL_FIONBIO 0)
set(HAVE_IOCTLSOCKET_FIONBIO 1)
set(HAVE_IOCTL_FIONBIO 0)
set(HAVE_SETSOCKOPT_SO_NONBLOCK 0)
set(HAVE_POSIX_STRERROR_R 0)
set(HAVE_BUILTIN_AVAILABLE 0)
set(HAVE_MSG_NOSIGNAL 0)
set(HAVE_STRUCT_TIMEVAL 1)
set(HAVE_GETHOSTBYNAME_R_3 0)
set(HAVE_GETHOSTBYNAME_R_3_REENTRANT 0)
set(HAVE_GETHOSTBYNAME_R_5 0)
set(HAVE_GETHOSTBYNAME_R_5_REENTRANT 0)
set(HAVE_GETHOSTBYNAME_R_6 0)
set(HAVE_GETHOSTBYNAME_R_6_REENTRANT 0)
set(HAVE_O_NONBLOCK 0)
set(HAVE_IN_ADDR_T 0)
set(STDC_HEADERS 1)
set(HAVE_SIZEOF_SUSECONDS_T 0)
set(HAVE_SIZEOF_SA_FAMILY_T 0)
+3 -1
View File
@@ -35,4 +35,6 @@ include("${CMAKE_CURRENT_LIST_DIR}/@TARGETS_EXPORT_NAME@.cmake")
check_required_components("@PROJECT_NAME@")
# Alias for either shared or static library
add_library(@PROJECT_NAME@::libcurl ALIAS @PROJECT_NAME@::@LIB_SELECTED@)
if(NOT TARGET @PROJECT_NAME@::libcurl)
add_library(@PROJECT_NAME@::libcurl ALIAS @PROJECT_NAME@::@LIB_SELECTED@)
endif()
+349 -314
View File
@@ -22,6 +22,7 @@ set(CURL_DISABLE_ALTSVC ON)
set(CURL_DISABLE_AWS OFF)
set(CURL_DISABLE_BASIC_AUTH OFF)
set(CURL_DISABLE_BEARER_AUTH OFF)
set(CURL_DISABLE_BINDLOCAL OFF)
set(CURL_DISABLE_COOKIES OFF CACHE INTERNAL "Do not disable curl cookie support")
set(CURL_DISABLE_DICT ON CACHE INTERNAL "Disable curl dict protocol?")
set(CURL_DISABLE_DIGEST_AUTH OFF)
@@ -31,10 +32,12 @@ set(CURL_DISABLE_FORM_API OFF)
set(CURL_DISABLE_FTP OFF CACHE INTERNAL "Disable curl ftp protocol?")
set(CURL_DISABLE_GETOPTIONS OFF)
set(CURL_DISABLE_GOPHER ON CACHE INTERNAL "Disable curl gopher protocol?")
set(CURL_DISABLE_HEADERS_API OFF)
set(CURL_DISABLE_HSTS OFF)
set(CURL_DISABLE_HTTP_AUTH OFF)
set(CURL_DISABLE_HTTP OFF CACHE INTERNAL "Disable curl http protocol?")
set(CURL_DISABLE_IMAP ON CACHE INTERNAL "Disable curl imap protocol?")
set(CURL_DISABLE_INSTALL ON)
set(CURL_DISABLE_KERBEROS_AUTH OFF)
set(CURL_DISABLE_LDAP ON CACHE INTERNAL "Disable curl ldap protocol?")
set(CURL_DISABLE_LDAPS ON CACHE INTERNAL "Disable curl ldaps protocol?")
@@ -209,7 +212,6 @@ endif()
# HAVE_GNUTLS_SRP: `gnutls_srp_verifier` present in GnuTLS
# HAVE_SSL_CTX_SET_QUIC_METHOD: `SSL_CTX_set_quic_method` present in OpenSSL/wolfSSL
# HAVE_QUICHE_CONN_SET_QLOG_FD: `quiche_conn_set_qlog_fd` present in QUICHE
# HAVE_ZSTD_CREATEDSTREAM: `ZSTD_createDStream` present in Zstd
#
# For each of the above variables, if the variable is DEFINED (either
# to ON or OFF), the symbol detection will be skipped. If the
@@ -260,6 +262,8 @@ option(BUILD_SHARED_LIBS "Build shared libraries" ON)
option(BUILD_STATIC_LIBS "Build static libraries" OFF)
option(BUILD_STATIC_CURL "Build curl executable with static libcurl" OFF)
option(ENABLE_ARES "Set to ON to enable c-ares support" OFF)
option(CURL_DISABLE_INSTALL "Set to ON to disable instalation targets" OFF)
if(WIN32)
option(CURL_STATIC_CRT "Set to ON to build libcurl with static CRT on Windows (/MT)." OFF)
option(ENABLE_UNICODE "Set to ON to use the Unicode version of the Windows API functions" OFF)
@@ -385,6 +389,8 @@ option(CURL_DISABLE_GETOPTIONS "disables curl_easy_options API for existing opti
mark_as_advanced(CURL_DISABLE_GETOPTIONS)
option(CURL_DISABLE_GOPHER "disables Gopher" OFF)
mark_as_advanced(CURL_DISABLE_GOPHER)
option(CURL_DISABLE_HEADERS_API "disables headers-api support" OFF)
mark_as_advanced(CURL_DISABLE_HEADERS_API)
option(CURL_DISABLE_HSTS "disables HSTS support" OFF)
mark_as_advanced(CURL_DISABLE_HSTS)
option(CURL_DISABLE_HTTP "disables HTTP" OFF)
@@ -402,6 +408,8 @@ mark_as_advanced(CURL_DISABLE_LIBCURL_OPTION)
option(CURL_DISABLE_MIME "disables MIME support" OFF)
mark_as_advanced(CURL_DISABLE_MIME)
option(CURL_DISABLE_MQTT "disables MQTT" OFF)
mark_as_advanced(CURL_DISABLE_BINDLOCAL)
option(CURL_DISABLE_BINDLOCAL "disables local binding support" OFF)
mark_as_advanced(CURL_DISABLE_MQTT)
option(CURL_DISABLE_NETRC "disables netrc parser" OFF)
mark_as_advanced(CURL_DISABLE_NETRC)
@@ -529,28 +537,33 @@ include(CheckCSourceCompiles)
# On windows preload settings
if(WIN32)
list(APPEND CMAKE_REQUIRED_DEFINITIONS -D_WINSOCKAPI_=)
set(HAVE_WINDOWS_H 1)
set(HAVE_WS2TCPIP_H 1)
set(HAVE_WINSOCK2_H 1)
include(${CMAKE_CURRENT_SOURCE_DIR}/CMake/Platforms/WindowsCache.cmake)
endif()
if(ENABLE_THREADED_RESOLVER)
find_package(Threads REQUIRED)
if(WIN32)
set(USE_THREADS_WIN32 ON)
else()
find_package(Threads REQUIRED)
set(USE_THREADS_POSIX ${CMAKE_USE_PTHREADS_INIT})
set(HAVE_PTHREAD_H ${CMAKE_USE_PTHREADS_INIT})
set(CURL_LIBS ${CURL_LIBS} ${CMAKE_THREAD_LIBS_INIT})
endif()
set(CURL_LIBS ${CURL_LIBS} ${CMAKE_THREAD_LIBS_INIT})
endif()
# Check for all needed libraries
check_library_exists_concat("socket" connect HAVE_LIBSOCKET)
check_library_exists("socket" "connect" "" HAVE_LIBSOCKET)
if(HAVE_LIBSOCKET)
set(CURL_LIBS "socket;${CURL_LIBS}")
endif()
check_function_exists(gethostname HAVE_GETHOSTNAME)
if(WIN32)
list(APPEND CURL_LIBS "ws2_32")
list(APPEND CURL_LIBS "ws2_32" "bcrypt")
if(USE_LIBRTMP)
list(APPEND CURL_LIBS "winmm")
endif()
@@ -581,7 +594,7 @@ set(openssl_default ON)
if(WIN32 OR CURL_USE_SECTRANSP OR CURL_USE_SCHANNEL OR CURL_USE_MBEDTLS OR CURL_USE_WOLFSSL)
set(openssl_default OFF)
endif()
cmake_dependent_option(CURL_USE_OPENSSL "Use OpenSSL code. Experimental" ${openssl_default} CURL_ENABLE_SSL OFF)
cmake_dependent_option(CURL_USE_OPENSSL "Enable OpenSSL for SSL/TLS" ${openssl_default} CURL_ENABLE_SSL OFF)
option(CURL_DISABLE_OPENSSL_AUTO_LOAD_CONFIG "Disable automatic loading of OpenSSL configuration" OFF)
endif()
@@ -653,11 +666,6 @@ if(CURL_USE_OPENSSL)
list(APPEND CURL_LIBS ${OPENSSL_LIBRARIES})
include_directories(${OPENSSL_INCLUDE_DIR})
if(WIN32)
list(APPEND CURL_LIBS "ws2_32")
list(APPEND CURL_LIBS "bcrypt") # for OpenSSL/LibreSSL
endif()
if(CURL_DEFAULT_SSL_BACKEND AND CURL_DEFAULT_SSL_BACKEND STREQUAL "openssl")
set(valid_default_ssl_backend TRUE)
endif()
@@ -783,17 +791,12 @@ option(CURL_ZSTD "Set to ON to enable building curl with zstd support." OFF)
set(HAVE_ZSTD OFF)
if(CURL_ZSTD)
find_package(Zstd REQUIRED)
if(NOT DEFINED HAVE_ZSTD_CREATEDSTREAM)
cmake_push_check_state()
set(CMAKE_REQUIRED_INCLUDES ${Zstd_INCLUDE_DIRS})
set(CMAKE_REQUIRED_LIBRARIES ${Zstd_LIBRARIES})
check_symbol_exists(ZSTD_createDStream "zstd.h" HAVE_ZSTD_CREATEDSTREAM)
cmake_pop_check_state()
endif()
if(Zstd_FOUND AND HAVE_ZSTD_CREATEDSTREAM)
if(Zstd_FOUND AND NOT Zstd_VERSION VERSION_LESS "1.0.0")
set(HAVE_ZSTD ON)
list(APPEND CURL_LIBS ${Zstd_LIBRARIES})
include_directories(${Zstd_INCLUDE_DIRS})
else()
message(WARNING "zstd v1.0.0 or newer is required, disabling zstd support.")
endif()
endif()
@@ -826,6 +829,20 @@ macro(openssl_check_symbol_exists SYMBOL FILES VARIABLE)
cmake_pop_check_state()
endmacro()
# Ensure that the OpenSSL fork actually supports QUIC.
macro(openssl_check_quic)
if(NOT DEFINED HAVE_SSL_CTX_SET_QUIC_METHOD)
if(USE_OPENSSL)
openssl_check_symbol_exists(SSL_CTX_set_quic_method "openssl/ssl.h" HAVE_SSL_CTX_SET_QUIC_METHOD)
elseif(USE_WOLFSSL)
openssl_check_symbol_exists(wolfSSL_set_quic_method "wolfssl/options.h;wolfssl/openssl/ssl.h" HAVE_SSL_CTX_SET_QUIC_METHOD)
endif()
endif()
if(NOT HAVE_SSL_CTX_SET_QUIC_METHOD)
message(FATAL_ERROR "QUIC support is missing in OpenSSL fork. Try setting -DOPENSSL_ROOT_DIR")
endif()
endmacro()
if(USE_OPENSSL OR USE_WOLFSSL)
if(NOT DEFINED HAVE_SSL_SET0_WBIO)
openssl_check_symbol_exists(SSL_set0_wbio "openssl/ssl.h" HAVE_SSL_SET0_WBIO)
@@ -852,18 +869,7 @@ if(USE_NGTCP2)
else()
find_package(NGTCP2 REQUIRED quictls)
endif()
# Be sure that the OpenSSL/wolfSSL library actually supports QUIC.
if(NOT DEFINED HAVE_SSL_CTX_SET_QUIC_METHOD)
if(USE_OPENSSL)
openssl_check_symbol_exists(SSL_CTX_set_quic_method "openssl/ssl.h" HAVE_SSL_CTX_SET_QUIC_METHOD)
elseif(USE_WOLFSSL)
openssl_check_symbol_exists(wolfSSL_set_quic_method "wolfssl/options.h;wolfssl/openssl/ssl.h" HAVE_SSL_CTX_SET_QUIC_METHOD)
endif()
endif()
if(NOT HAVE_SSL_CTX_SET_QUIC_METHOD)
message(FATAL_ERROR "QUIC support is missing in OpenSSL/LibreSSL/BoringSSL/wolfSSL. Try setting -DOPENSSL_ROOT_DIR")
endif()
openssl_check_quic()
elseif(USE_GNUTLS)
find_package(NGTCP2 REQUIRED GnuTLS)
else()
@@ -885,7 +891,10 @@ if(USE_QUICHE)
message(FATAL_ERROR "Only one HTTP/3 backend can be selected!")
endif()
find_package(QUICHE REQUIRED)
CheckQuicSupportInOpenSSL()
if(NOT HAVE_BORINGSSL)
message(FATAL_ERROR "quiche requires BoringSSL")
endif()
openssl_check_quic()
set(USE_QUICHE ON)
include_directories(${QUICHE_INCLUDE_DIRS})
list(APPEND CURL_LIBS ${QUICHE_LIBRARIES})
@@ -930,8 +939,12 @@ if(NOT CURL_DISABLE_LDAP)
if(NOT USE_WIN32_LDAP)
# Check for LDAP
set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_LIBRARIES})
check_library_exists_concat(${CMAKE_LDAP_LIB} ldap_init HAVE_LIBLDAP)
check_library_exists_concat(${CMAKE_LBER_LIB} ber_init HAVE_LIBLBER)
check_library_exists("${CMAKE_LDAP_LIB}" "ldap_init" "" HAVE_LIBLDAP)
if(HAVE_LIBLDAP)
check_library_exists("${CMAKE_LDAP_LIB};${CMAKE_LBER_LIB}" "ber_init" "" HAVE_LIBLBER)
else()
check_library_exists("${CMAKE_LBER_LIB}" "ber_init" "" HAVE_LIBLBER)
endif()
set(CMAKE_REQUIRED_INCLUDES_BAK ${CMAKE_REQUIRED_INCLUDES})
set(CMAKE_LDAP_INCLUDE_DIR "" CACHE STRING "Path to LDAP include directory")
@@ -970,8 +983,10 @@ if(NOT CURL_DISABLE_LDAP)
list(APPEND CMAKE_REQUIRED_DEFINITIONS -DLDAP_DEPRECATED=1)
list(APPEND CMAKE_REQUIRED_LIBRARIES ${CMAKE_LDAP_LIB})
set(CURL_LIBS "${CMAKE_LDAP_LIB};${CURL_LIBS}")
if(HAVE_LIBLBER)
list(APPEND CMAKE_REQUIRED_LIBRARIES ${CMAKE_LBER_LIB})
set(CURL_LIBS "${CMAKE_LBER_LIB};${CURL_LIBS}")
endif()
check_c_source_compiles("
@@ -1018,7 +1033,11 @@ endif()
# Check for idn2
option(USE_LIBIDN2 "Use libidn2 for IDN support" ON)
if(USE_LIBIDN2)
check_library_exists_concat("idn2" idn2_lookup_ul HAVE_LIBIDN2)
check_library_exists("idn2" "idn2_lookup_ul" "" HAVE_LIBIDN2)
if(HAVE_LIBIDN2)
set(CURL_LIBS "idn2;${CURL_LIBS}")
check_include_file_concat("idn2.h" HAVE_IDN2_H)
endif()
else()
set(HAVE_LIBIDN2 OFF)
endif()
@@ -1233,17 +1252,50 @@ endif()
endif()
# Check for header files
if(NOT UNIX)
check_include_file_concat("windows.h" HAVE_WINDOWS_H)
check_include_file_concat("ws2tcpip.h" HAVE_WS2TCPIP_H)
if(WIN32)
check_include_file_concat("winsock2.h" HAVE_WINSOCK2_H)
check_include_file_concat("ws2tcpip.h" HAVE_WS2TCPIP_H)
check_include_file_concat("windows.h" HAVE_WINDOWS_H)
else()
set(HAVE_WINDOWS_H 0)
set(HAVE_WS2TCPIP_H 0)
set(HAVE_WINSOCK2_H 0)
set(HAVE_WS2TCPIP_H 0)
set(HAVE_WINDOWS_H 0)
endif()
if(WIN32)
# detect actual value of _WIN32_WINNT and store as HAVE_WIN32_WINNT
curl_internal_test(HAVE_WIN32_WINNT)
if(HAVE_WIN32_WINNT)
string(REGEX MATCH ".*_WIN32_WINNT=0x[0-9a-fA-F]+" OUTPUT "${OUTPUT}")
string(REGEX REPLACE ".*_WIN32_WINNT=" "" OUTPUT "${OUTPUT}")
string(REGEX REPLACE "0x([0-9a-f][0-9a-f][0-9a-f])$" "0x0\\1" OUTPUT "${OUTPUT}") # pad to 4 digits
string(TOLOWER "${OUTPUT}" HAVE_WIN32_WINNT)
message(STATUS "Found _WIN32_WINNT=${HAVE_WIN32_WINNT}")
endif()
# avoid storing HAVE_WIN32_WINNT in CMake cache
unset(HAVE_WIN32_WINNT CACHE)
if(HAVE_WIN32_WINNT)
if(HAVE_WIN32_WINNT STRLESS "0x0501")
# Windows XP is required for freeaddrinfo, getaddrinfo
message(FATAL_ERROR "Building for Windows XP or newer is required.")
endif()
# pre-fill detection results based on target OS version
if(MINGW OR MSVC)
if(HAVE_WIN32_WINNT STRLESS "0x0600")
set(HAVE_INET_NTOP 0)
set(HAVE_INET_PTON 0)
else() # Windows Vista or newer
set(HAVE_INET_NTOP 1)
set(HAVE_INET_PTON 1)
endif()
unset(HAVE_INET_NTOP CACHE)
unset(HAVE_INET_PTON CACHE)
endif()
endif()
endif()
check_include_file_concat("inttypes.h" HAVE_INTTYPES_H)
check_include_file_concat("sys/filio.h" HAVE_SYS_FILIO_H)
check_include_file_concat("sys/wait.h" HAVE_SYS_WAIT_H)
check_include_file_concat("sys/ioctl.h" HAVE_SYS_IOCTL_H)
@@ -1261,7 +1313,6 @@ check_include_file_concat("sys/utime.h" HAVE_SYS_UTIME_H)
check_include_file_concat("sys/xattr.h" HAVE_SYS_XATTR_H)
check_include_file_concat("arpa/inet.h" HAVE_ARPA_INET_H)
check_include_file_concat("fcntl.h" HAVE_FCNTL_H)
check_include_file_concat("idn2.h" HAVE_IDN2_H)
check_include_file_concat("ifaddrs.h" HAVE_IFADDRS_H)
check_include_file_concat("io.h" HAVE_IO_H)
check_include_file_concat("libgen.h" HAVE_LIBGEN_H)
@@ -1277,7 +1328,6 @@ check_include_file_concat("poll.h" HAVE_POLL_H)
check_include_file_concat("pwd.h" HAVE_PWD_H)
check_include_file_concat("stdatomic.h" HAVE_STDATOMIC_H)
check_include_file_concat("stdbool.h" HAVE_STDBOOL_H)
check_include_file_concat("stdint.h" HAVE_STDINT_H)
check_include_file_concat("strings.h" HAVE_STRINGS_H)
check_include_file_concat("stropts.h" HAVE_STROPTS_H)
check_include_file_concat("termio.h" HAVE_TERMIO_H)
@@ -1308,7 +1358,6 @@ elseif(HAVE_LIBNETWORK)
set(CMAKE_REQUIRED_LIBRARIES network)
endif()
check_symbol_exists(fchmod "${CURL_INCLUDES}" HAVE_FCHMOD)
check_symbol_exists(fnmatch "${CURL_INCLUDES};fnmatch.h" HAVE_FNMATCH)
check_symbol_exists(basename "${CURL_INCLUDES};string.h" HAVE_BASENAME)
check_symbol_exists(socket "${CURL_INCLUDES}" HAVE_SOCKET)
@@ -1345,6 +1394,7 @@ check_symbol_exists(gethostbyname_r "${CURL_INCLUDES}" HAVE_GETHOSTBYNAME_R)
check_symbol_exists(signal "${CURL_INCLUDES};signal.h" HAVE_SIGNAL)
check_symbol_exists(strtoll "${CURL_INCLUDES};stdlib.h" HAVE_STRTOLL)
check_symbol_exists(strerror_r "${CURL_INCLUDES};stdlib.h;string.h" HAVE_STRERROR_R)
check_symbol_exists(sigaction "signal.h" HAVE_SIGACTION)
check_symbol_exists(siginterrupt "${CURL_INCLUDES};signal.h" HAVE_SIGINTERRUPT)
check_symbol_exists(getaddrinfo "${CURL_INCLUDES};stdlib.h;string.h" HAVE_GETADDRINFO)
check_symbol_exists(getifaddrs "${CURL_INCLUDES};stdlib.h" HAVE_GETIFADDRS)
@@ -1361,6 +1411,10 @@ check_symbol_exists(setlocale "${CURL_INCLUDES}" HAVE_SETLOCALE)
check_symbol_exists(setmode "${CURL_INCLUDES}" HAVE_SETMODE)
check_symbol_exists(setrlimit "${CURL_INCLUDES}" HAVE_SETRLIMIT)
if(HAVE_FSEEKO)
set(HAVE_DECL_FSEEKO 1)
endif()
if(NOT MSVC OR (MSVC_VERSION GREATER_EQUAL 1900))
# earlier MSVC compilers had faulty snprintf implementations
check_symbol_exists(snprintf "stdio.h" HAVE_SNPRINTF)
@@ -1384,20 +1438,11 @@ check_type_size("sa_family_t" SIZEOF_SA_FAMILY_T)
set(HAVE_SA_FAMILY_T ${HAVE_SIZEOF_SA_FAMILY_T})
set(CMAKE_EXTRA_INCLUDE_FILES "")
set(CMAKE_EXTRA_INCLUDE_FILES "ws2def.h")
check_type_size("ADDRESS_FAMILY" SIZEOF_ADDRESS_FAMILY)
set(HAVE_ADDRESS_FAMILY ${HAVE_SIZEOF_ADDRESS_FAMILY})
set(CMAKE_EXTRA_INCLUDE_FILES "")
# sigaction and sigsetjmp are special. Use special mechanism for
# detecting those, but only if previous attempt failed.
check_symbol_exists(sigaction "signal.h" HAVE_SIGACTION)
if(NOT HAVE_SIGSETJMP)
check_symbol_exists(sigsetjmp "setjmp.h" HAVE_MACRO_SIGSETJMP)
if(HAVE_MACRO_SIGSETJMP)
set(HAVE_SIGSETJMP 1)
endif()
if(WIN32)
set(CMAKE_EXTRA_INCLUDE_FILES "ws2def.h")
check_type_size("ADDRESS_FAMILY" SIZEOF_ADDRESS_FAMILY)
set(HAVE_ADDRESS_FAMILY ${HAVE_SIZEOF_ADDRESS_FAMILY})
set(CMAKE_EXTRA_INCLUDE_FILES "")
endif()
# Do curl specific tests
@@ -1421,8 +1466,6 @@ foreach(CURL_TEST
HAVE_BOOL_T
STDC_HEADERS
HAVE_FILE_OFFSET_BITS
HAVE_VARIADIC_MACROS_C99
HAVE_VARIADIC_MACROS_GCC
HAVE_ATOMIC
)
curl_internal_test(${CURL_TEST})
@@ -1442,18 +1485,6 @@ set(CMAKE_EXTRA_INCLUDE_FILES "curl/curl.h")
check_type_size("curl_socket_t" SIZEOF_CURL_SOCKET_T)
set(CMAKE_EXTRA_INCLUDE_FILES "")
if(WIN32)
# detect actual value of _WIN32_WINNT and store as HAVE_WIN32_WINNT
curl_internal_test(HAVE_WIN32_WINNT)
if(HAVE_WIN32_WINNT)
string(REGEX MATCH ".*_WIN32_WINNT=0x[0-9a-fA-F]+" OUTPUT "${OUTPUT}")
string(REGEX REPLACE ".*_WIN32_WINNT=" "" HAVE_WIN32_WINNT "${OUTPUT}")
message(STATUS "Found _WIN32_WINNT=${HAVE_WIN32_WINNT}")
endif()
# avoid storing HAVE_WIN32_WINNT in CMake cache
unset(HAVE_WIN32_WINNT CACHE)
endif()
if(0) # This code not needed for building within CMake.
if(NOT WIN32 AND NOT CMAKE_CROSSCOMPILING)
# on not-Windows and not-crosscompiling, check for writable argv[]
@@ -1511,8 +1542,10 @@ if(NEED_REENTRANT)
endforeach()
endif()
# Check clock_gettime(CLOCK_MONOTONIC, x) support
curl_internal_test(HAVE_CLOCK_GETTIME_MONOTONIC)
if(NOT WIN32)
# Check clock_gettime(CLOCK_MONOTONIC, x) support
curl_internal_test(HAVE_CLOCK_GETTIME_MONOTONIC)
endif()
# Check compiler support of __builtin_available()
curl_internal_test(HAVE_BUILTIN_AVAILABLE)
@@ -1577,8 +1610,6 @@ if(WIN32)
if(USE_WIN32_CRYPTO OR USE_SCHANNEL)
list(APPEND CURL_LIBS "advapi32" "crypt32")
endif()
list(APPEND CURL_LIBS "bcrypt")
endif()
if(MSVC)
@@ -1683,258 +1714,262 @@ if(BUILD_TESTING)
add_subdirectory(tests)
endif()
# Helper to populate a list (_items) with a label when conditions (the remaining
# args) are satisfied
macro(_add_if label)
# needs to be a macro to allow this indirection
if(${ARGN})
set(_items ${_items} "${label}")
endif()
endmacro()
if(NOT CURL_DISABLE_INSTALL)
# NTLM support requires crypto function adaptions from various SSL libs
# TODO alternative SSL libs tests for SSP1, GnuTLS, NSS
if(NOT (CURL_DISABLE_NTLM) AND
(USE_OPENSSL OR USE_MBEDTLS OR USE_DARWINSSL OR USE_WIN32_CRYPTO OR USE_GNUTLS))
set(use_curl_ntlm_core ON)
endif()
# Clear list and try to detect available features
set(_items)
_add_if("SSL" SSL_ENABLED)
_add_if("IPv6" ENABLE_IPV6)
_add_if("unixsockets" USE_UNIX_SOCKETS)
_add_if("libz" HAVE_LIBZ)
_add_if("brotli" HAVE_BROTLI)
_add_if("zstd" HAVE_ZSTD)
_add_if("AsynchDNS" USE_ARES OR USE_THREADS_POSIX OR USE_THREADS_WIN32)
_add_if("IDN" HAVE_LIBIDN2 OR USE_WIN32_IDN)
_add_if("Largefile" (SIZEOF_CURL_OFF_T GREATER 4) AND
((SIZEOF_OFF_T GREATER 4) OR USE_WIN32_LARGE_FILES))
# TODO SSP1 (Schannel) check is missing
_add_if("SSPI" USE_WINDOWS_SSPI)
_add_if("GSS-API" HAVE_GSSAPI)
_add_if("alt-svc" NOT CURL_DISABLE_ALTSVC)
_add_if("HSTS" NOT CURL_DISABLE_HSTS)
# TODO SSP1 missing for SPNEGO
_add_if("SPNEGO" NOT CURL_DISABLE_NEGOTIATE_AUTH AND
(HAVE_GSSAPI OR USE_WINDOWS_SSPI))
_add_if("Kerberos" NOT CURL_DISABLE_KERBEROS_AUTH AND
(HAVE_GSSAPI OR USE_WINDOWS_SSPI))
# NTLM support requires crypto function adaptions from various SSL libs
# TODO alternative SSL libs tests for SSP1, GnuTLS, NSS
_add_if("NTLM" NOT (CURL_DISABLE_NTLM) AND
(use_curl_ntlm_core OR USE_WINDOWS_SSPI))
# TODO missing option (autoconf: --enable-ntlm-wb)
_add_if("NTLM_WB" NOT (CURL_DISABLE_NTLM) AND
(use_curl_ntlm_core OR USE_WINDOWS_SSPI) AND
NOT CURL_DISABLE_HTTP AND NTLM_WB_ENABLED)
_add_if("TLS-SRP" USE_TLS_SRP)
# TODO option --with-nghttp2 tests for nghttp2 lib and nghttp2/nghttp2.h header
_add_if("HTTP2" USE_NGHTTP2)
_add_if("HTTP3" USE_NGTCP2 OR USE_QUICHE)
_add_if("MultiSSL" CURL_WITH_MULTI_SSL)
# TODO wolfSSL only support this from v5.0.0 onwards
_add_if("HTTPS-proxy" SSL_ENABLED AND (USE_OPENSSL OR USE_GNUTLS
OR USE_SCHANNEL OR USE_RUSTLS OR USE_BEARSSL OR
USE_MBEDTLS OR USE_SECTRANSP))
_add_if("unicode" ENABLE_UNICODE)
_add_if("threadsafe" HAVE_ATOMIC OR (WIN32 AND
HAVE_WIN32_WINNT GREATER_EQUAL 0x600))
_add_if("PSL" USE_LIBPSL)
string(REPLACE ";" " " SUPPORT_FEATURES "${_items}")
message(STATUS "Enabled features: ${SUPPORT_FEATURES}")
# Clear list and try to detect available protocols
set(_items)
_add_if("HTTP" NOT CURL_DISABLE_HTTP)
_add_if("HTTPS" NOT CURL_DISABLE_HTTP AND SSL_ENABLED)
_add_if("FTP" NOT CURL_DISABLE_FTP)
_add_if("FTPS" NOT CURL_DISABLE_FTP AND SSL_ENABLED)
_add_if("FILE" NOT CURL_DISABLE_FILE)
_add_if("TELNET" NOT CURL_DISABLE_TELNET)
_add_if("LDAP" NOT CURL_DISABLE_LDAP)
# CURL_DISABLE_LDAP implies CURL_DISABLE_LDAPS
_add_if("LDAPS" NOT CURL_DISABLE_LDAPS AND
((USE_OPENLDAP AND SSL_ENABLED) OR
(NOT USE_OPENLDAP AND HAVE_LDAP_SSL)))
_add_if("DICT" NOT CURL_DISABLE_DICT)
_add_if("TFTP" NOT CURL_DISABLE_TFTP)
_add_if("GOPHER" NOT CURL_DISABLE_GOPHER)
_add_if("GOPHERS" NOT CURL_DISABLE_GOPHER AND SSL_ENABLED)
_add_if("POP3" NOT CURL_DISABLE_POP3)
_add_if("POP3S" NOT CURL_DISABLE_POP3 AND SSL_ENABLED)
_add_if("IMAP" NOT CURL_DISABLE_IMAP)
_add_if("IMAPS" NOT CURL_DISABLE_IMAP AND SSL_ENABLED)
_add_if("SMB" NOT CURL_DISABLE_SMB AND
use_curl_ntlm_core AND (SIZEOF_CURL_OFF_T GREATER 4))
_add_if("SMBS" NOT CURL_DISABLE_SMB AND SSL_ENABLED AND
use_curl_ntlm_core AND (SIZEOF_CURL_OFF_T GREATER 4))
_add_if("SMTP" NOT CURL_DISABLE_SMTP)
_add_if("SMTPS" NOT CURL_DISABLE_SMTP AND SSL_ENABLED)
_add_if("SCP" USE_LIBSSH2 OR USE_LIBSSH)
_add_if("SFTP" USE_LIBSSH2 OR USE_LIBSSH)
_add_if("RTSP" NOT CURL_DISABLE_RTSP)
_add_if("RTMP" USE_LIBRTMP)
_add_if("MQTT" NOT CURL_DISABLE_MQTT)
_add_if("WS" USE_WEBSOCKETS)
_add_if("WSS" USE_WEBSOCKETS)
if(_items)
list(SORT _items)
endif()
string(REPLACE ";" " " SUPPORT_PROTOCOLS "${_items}")
message(STATUS "Enabled protocols: ${SUPPORT_PROTOCOLS}")
# Clear list and collect SSL backends
set(_items)
_add_if("Schannel" SSL_ENABLED AND USE_SCHANNEL)
_add_if("OpenSSL" SSL_ENABLED AND USE_OPENSSL)
_add_if("Secure Transport" SSL_ENABLED AND USE_SECTRANSP)
_add_if("mbedTLS" SSL_ENABLED AND USE_MBEDTLS)
_add_if("BearSSL" SSL_ENABLED AND USE_BEARSSL)
_add_if("wolfSSL" SSL_ENABLED AND USE_WOLFSSL)
_add_if("GnuTLS" SSL_ENABLED AND USE_GNUTLS)
if(_items)
list(SORT _items)
endif()
string(REPLACE ";" " " SSL_BACKENDS "${_items}")
message(STATUS "Enabled SSL backends: ${SSL_BACKENDS}")
if(CURL_DEFAULT_SSL_BACKEND)
message(STATUS "Default SSL backend: ${CURL_DEFAULT_SSL_BACKEND}")
endif()
# curl-config needs the following options to be set.
set(CC "${CMAKE_C_COMPILER}")
# TODO probably put a -D... options here?
set(CONFIGURE_OPTIONS "")
set(CURLVERSION "${CURL_VERSION}")
set(exec_prefix "\${prefix}")
set(includedir "\${prefix}/include")
set(LDFLAGS "${CMAKE_SHARED_LINKER_FLAGS}")
set(LIBCURL_LIBS "")
set(libdir "${CMAKE_INSTALL_PREFIX}/lib")
foreach(_lib ${CMAKE_C_IMPLICIT_LINK_LIBRARIES} ${CURL_LIBS})
if(TARGET "${_lib}")
set(_libname "${_lib}")
get_target_property(_imported "${_libname}" IMPORTED)
if(NOT _imported)
# Reading the LOCATION property on non-imported target will error out.
# Assume the user won't need this information in the .pc file.
continue()
endif()
get_target_property(_lib "${_libname}" LOCATION)
if(NOT _lib)
message(WARNING "Bad lib in library list: ${_libname}")
continue()
# Helper to populate a list (_items) with a label when conditions (the remaining
# args) are satisfied
macro(_add_if label)
# needs to be a macro to allow this indirection
if(${ARGN})
set(_items ${_items} "${label}")
endif()
endmacro()
# NTLM support requires crypto function adaptions from various SSL libs
# TODO alternative SSL libs tests for SSP1, GnuTLS, NSS
if(NOT (CURL_DISABLE_NTLM) AND
(USE_OPENSSL OR USE_MBEDTLS OR USE_DARWINSSL OR USE_WIN32_CRYPTO OR USE_GNUTLS))
set(use_curl_ntlm_core ON)
endif()
if(_lib MATCHES ".*/.*" OR _lib MATCHES "^-")
set(LIBCURL_LIBS "${LIBCURL_LIBS} ${_lib}")
# Clear list and try to detect available features
set(_items)
_add_if("SSL" SSL_ENABLED)
_add_if("IPv6" ENABLE_IPV6)
_add_if("UnixSockets" USE_UNIX_SOCKETS)
_add_if("libz" HAVE_LIBZ)
_add_if("brotli" HAVE_BROTLI)
_add_if("zstd" HAVE_ZSTD)
_add_if("AsynchDNS" USE_ARES OR USE_THREADS_POSIX OR USE_THREADS_WIN32)
_add_if("IDN" HAVE_LIBIDN2 OR USE_WIN32_IDN)
_add_if("Largefile" (SIZEOF_CURL_OFF_T GREATER 4) AND
((SIZEOF_OFF_T GREATER 4) OR USE_WIN32_LARGE_FILES))
# TODO SSP1 (Schannel) check is missing
_add_if("SSPI" USE_WINDOWS_SSPI)
_add_if("GSS-API" HAVE_GSSAPI)
_add_if("alt-svc" NOT CURL_DISABLE_ALTSVC)
_add_if("HSTS" NOT CURL_DISABLE_HSTS)
# TODO SSP1 missing for SPNEGO
_add_if("SPNEGO" NOT CURL_DISABLE_NEGOTIATE_AUTH AND
(HAVE_GSSAPI OR USE_WINDOWS_SSPI))
_add_if("Kerberos" NOT CURL_DISABLE_KERBEROS_AUTH AND
(HAVE_GSSAPI OR USE_WINDOWS_SSPI))
# NTLM support requires crypto function adaptions from various SSL libs
# TODO alternative SSL libs tests for SSP1, GnuTLS, NSS
_add_if("NTLM" NOT (CURL_DISABLE_NTLM) AND
(use_curl_ntlm_core OR USE_WINDOWS_SSPI))
# TODO missing option (autoconf: --enable-ntlm-wb)
_add_if("NTLM_WB" NOT (CURL_DISABLE_NTLM) AND
(use_curl_ntlm_core OR USE_WINDOWS_SSPI) AND
NOT CURL_DISABLE_HTTP AND NTLM_WB_ENABLED)
_add_if("TLS-SRP" USE_TLS_SRP)
# TODO option --with-nghttp2 tests for nghttp2 lib and nghttp2/nghttp2.h header
_add_if("HTTP2" USE_NGHTTP2)
_add_if("HTTP3" USE_NGTCP2 OR USE_QUICHE)
_add_if("MultiSSL" CURL_WITH_MULTI_SSL)
# TODO wolfSSL only support this from v5.0.0 onwards
_add_if("HTTPS-proxy" SSL_ENABLED AND (USE_OPENSSL OR USE_GNUTLS
OR USE_SCHANNEL OR USE_RUSTLS OR USE_BEARSSL OR
USE_MBEDTLS OR USE_SECTRANSP))
_add_if("unicode" ENABLE_UNICODE)
_add_if("threadsafe" HAVE_ATOMIC OR
(USE_THREADS_POSIX AND HAVE_PTHREAD_H) OR
(WIN32 AND HAVE_WIN32_WINNT GREATER_EQUAL 0x600))
_add_if("PSL" USE_LIBPSL)
string(REPLACE ";" " " SUPPORT_FEATURES "${_items}")
message(STATUS "Enabled features: ${SUPPORT_FEATURES}")
# Clear list and try to detect available protocols
set(_items)
_add_if("HTTP" NOT CURL_DISABLE_HTTP)
_add_if("HTTPS" NOT CURL_DISABLE_HTTP AND SSL_ENABLED)
_add_if("FTP" NOT CURL_DISABLE_FTP)
_add_if("FTPS" NOT CURL_DISABLE_FTP AND SSL_ENABLED)
_add_if("FILE" NOT CURL_DISABLE_FILE)
_add_if("TELNET" NOT CURL_DISABLE_TELNET)
_add_if("LDAP" NOT CURL_DISABLE_LDAP)
# CURL_DISABLE_LDAP implies CURL_DISABLE_LDAPS
_add_if("LDAPS" NOT CURL_DISABLE_LDAPS AND
((USE_OPENLDAP AND SSL_ENABLED) OR
(NOT USE_OPENLDAP AND HAVE_LDAP_SSL)))
_add_if("DICT" NOT CURL_DISABLE_DICT)
_add_if("TFTP" NOT CURL_DISABLE_TFTP)
_add_if("GOPHER" NOT CURL_DISABLE_GOPHER)
_add_if("GOPHERS" NOT CURL_DISABLE_GOPHER AND SSL_ENABLED)
_add_if("POP3" NOT CURL_DISABLE_POP3)
_add_if("POP3S" NOT CURL_DISABLE_POP3 AND SSL_ENABLED)
_add_if("IMAP" NOT CURL_DISABLE_IMAP)
_add_if("IMAPS" NOT CURL_DISABLE_IMAP AND SSL_ENABLED)
_add_if("SMB" NOT CURL_DISABLE_SMB AND
use_curl_ntlm_core AND (SIZEOF_CURL_OFF_T GREATER 4))
_add_if("SMBS" NOT CURL_DISABLE_SMB AND SSL_ENABLED AND
use_curl_ntlm_core AND (SIZEOF_CURL_OFF_T GREATER 4))
_add_if("SMTP" NOT CURL_DISABLE_SMTP)
_add_if("SMTPS" NOT CURL_DISABLE_SMTP AND SSL_ENABLED)
_add_if("SCP" USE_LIBSSH2 OR USE_LIBSSH)
_add_if("SFTP" USE_LIBSSH2 OR USE_LIBSSH)
_add_if("RTSP" NOT CURL_DISABLE_RTSP)
_add_if("RTMP" USE_LIBRTMP)
_add_if("MQTT" NOT CURL_DISABLE_MQTT)
_add_if("WS" USE_WEBSOCKETS)
_add_if("WSS" USE_WEBSOCKETS)
if(_items)
list(SORT _items)
endif()
string(REPLACE ";" " " SUPPORT_PROTOCOLS "${_items}")
message(STATUS "Enabled protocols: ${SUPPORT_PROTOCOLS}")
# Clear list and collect SSL backends
set(_items)
_add_if("Schannel" SSL_ENABLED AND USE_SCHANNEL)
_add_if("OpenSSL" SSL_ENABLED AND USE_OPENSSL)
_add_if("Secure Transport" SSL_ENABLED AND USE_SECTRANSP)
_add_if("mbedTLS" SSL_ENABLED AND USE_MBEDTLS)
_add_if("BearSSL" SSL_ENABLED AND USE_BEARSSL)
_add_if("wolfSSL" SSL_ENABLED AND USE_WOLFSSL)
_add_if("GnuTLS" SSL_ENABLED AND USE_GNUTLS)
if(_items)
list(SORT _items)
endif()
string(REPLACE ";" " " SSL_BACKENDS "${_items}")
message(STATUS "Enabled SSL backends: ${SSL_BACKENDS}")
if(CURL_DEFAULT_SSL_BACKEND)
message(STATUS "Default SSL backend: ${CURL_DEFAULT_SSL_BACKEND}")
endif()
# curl-config needs the following options to be set.
set(CC "${CMAKE_C_COMPILER}")
# TODO probably put a -D... options here?
set(CONFIGURE_OPTIONS "")
set(CURLVERSION "${CURL_VERSION}")
set(exec_prefix "\${prefix}")
set(includedir "\${prefix}/include")
set(LDFLAGS "${CMAKE_SHARED_LINKER_FLAGS}")
set(LIBCURL_LIBS "")
set(libdir "${CMAKE_INSTALL_PREFIX}/lib")
foreach(_lib ${CMAKE_C_IMPLICIT_LINK_LIBRARIES} ${CURL_LIBS})
if(TARGET "${_lib}")
set(_libname "${_lib}")
get_target_property(_imported "${_libname}" IMPORTED)
if(NOT _imported)
# Reading the LOCATION property on non-imported target will error out.
# Assume the user won't need this information in the .pc file.
continue()
endif()
get_target_property(_lib "${_libname}" LOCATION)
if(NOT _lib)
message(WARNING "Bad lib in library list: ${_libname}")
continue()
endif()
endif()
if(_lib MATCHES ".*/.*" OR _lib MATCHES "^-")
set(LIBCURL_LIBS "${LIBCURL_LIBS} ${_lib}")
else()
set(LIBCURL_LIBS "${LIBCURL_LIBS} -l${_lib}")
endif()
endforeach()
if(BUILD_SHARED_LIBS)
set(ENABLE_SHARED "yes")
set(LIBCURL_NO_SHARED "")
set(CPPFLAG_CURL_STATICLIB "")
else()
set(LIBCURL_LIBS "${LIBCURL_LIBS} -l${_lib}")
set(ENABLE_SHARED "no")
set(LIBCURL_NO_SHARED "${LIBCURL_LIBS}")
set(CPPFLAG_CURL_STATICLIB "-DCURL_STATICLIB")
endif()
endforeach()
if(BUILD_SHARED_LIBS)
set(ENABLE_SHARED "yes")
set(LIBCURL_NO_SHARED "")
set(CPPFLAG_CURL_STATICLIB "")
else()
set(ENABLE_SHARED "no")
set(LIBCURL_NO_SHARED "${LIBCURL_LIBS}")
set(CPPFLAG_CURL_STATICLIB "-DCURL_STATICLIB")
endif()
if(BUILD_STATIC_LIBS)
set(ENABLE_STATIC "yes")
else()
set(ENABLE_STATIC "no")
endif()
# "a" (Linux) or "lib" (Windows)
string(REPLACE "." "" libext "${CMAKE_STATIC_LIBRARY_SUFFIX}")
set(prefix "${CMAKE_INSTALL_PREFIX}")
# Set this to "yes" to append all libraries on which -lcurl is dependent
set(REQUIRE_LIB_DEPS "no")
# SUPPORT_FEATURES
# SUPPORT_PROTOCOLS
set(VERSIONNUM "${CURL_VERSION_NUM}")
if(BUILD_STATIC_LIBS)
set(ENABLE_STATIC "yes")
else()
set(ENABLE_STATIC "no")
endif()
# "a" (Linux) or "lib" (Windows)
string(REPLACE "." "" libext "${CMAKE_STATIC_LIBRARY_SUFFIX}")
set(prefix "${CMAKE_INSTALL_PREFIX}")
# Set this to "yes" to append all libraries on which -lcurl is dependent
set(REQUIRE_LIB_DEPS "no")
# SUPPORT_FEATURES
# SUPPORT_PROTOCOLS
set(VERSIONNUM "${CURL_VERSION_NUM}")
# Finally generate a "curl-config" matching this config
# Use:
# * ENABLE_SHARED
# * ENABLE_STATIC
configure_file("${CURL_SOURCE_DIR}/curl-config.in"
"${CURL_BINARY_DIR}/curl-config" @ONLY)
install(FILES "${CURL_BINARY_DIR}/curl-config"
DESTINATION ${CMAKE_INSTALL_BINDIR}
PERMISSIONS
OWNER_READ OWNER_WRITE OWNER_EXECUTE
GROUP_READ GROUP_EXECUTE
WORLD_READ WORLD_EXECUTE)
# Finally generate a "curl-config" matching this config
# Use:
# * ENABLE_SHARED
# * ENABLE_STATIC
configure_file("${CURL_SOURCE_DIR}/curl-config.in"
"${CURL_BINARY_DIR}/curl-config" @ONLY)
install(FILES "${CURL_BINARY_DIR}/curl-config"
DESTINATION ${CMAKE_INSTALL_BINDIR}
PERMISSIONS
OWNER_READ OWNER_WRITE OWNER_EXECUTE
GROUP_READ GROUP_EXECUTE
WORLD_READ WORLD_EXECUTE)
# Finally generate a pkg-config file matching this config
configure_file("${CURL_SOURCE_DIR}/libcurl.pc.in"
"${CURL_BINARY_DIR}/libcurl.pc" @ONLY)
install(FILES "${CURL_BINARY_DIR}/libcurl.pc"
DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
# Finally generate a pkg-config file matching this config
configure_file("${CURL_SOURCE_DIR}/libcurl.pc.in"
"${CURL_BINARY_DIR}/libcurl.pc" @ONLY)
install(FILES "${CURL_BINARY_DIR}/libcurl.pc"
DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
# install headers
install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/include/curl"
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
FILES_MATCHING PATTERN "*.h")
# install headers
install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/include/curl"
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
FILES_MATCHING PATTERN "*.h")
include(CMakePackageConfigHelpers)
write_basic_package_version_file(
"${version_config}"
VERSION ${CURL_VERSION}
COMPATIBILITY SameMajorVersion
)
file(READ "${version_config}" generated_version_config)
file(WRITE "${version_config}"
"if(NOT PACKAGE_FIND_VERSION_RANGE AND PACKAGE_FIND_VERSION_MAJOR STREQUAL \"7\")
# Version 8 satisfies version 7... requirements
set(PACKAGE_FIND_VERSION_MAJOR 8)
set(PACKAGE_FIND_VERSION_COUNT 1)
endif()
${generated_version_config}"
)
include(CMakePackageConfigHelpers)
write_basic_package_version_file(
"${version_config}"
VERSION ${CURL_VERSION}
COMPATIBILITY SameMajorVersion
)
file(READ "${version_config}" generated_version_config)
file(WRITE "${version_config}"
"if(NOT PACKAGE_FIND_VERSION_RANGE AND PACKAGE_FIND_VERSION_MAJOR STREQUAL \"7\")
# Version 8 satisfies version 7... requirements
set(PACKAGE_FIND_VERSION_MAJOR 8)
set(PACKAGE_FIND_VERSION_COUNT 1)
endif()
${generated_version_config}"
)
# Use:
# * TARGETS_EXPORT_NAME
# * PROJECT_NAME
configure_package_config_file(CMake/curl-config.cmake.in
"${project_config}"
INSTALL_DESTINATION ${CURL_INSTALL_CMAKE_DIR}
)
# Use:
# * TARGETS_EXPORT_NAME
# * PROJECT_NAME
configure_package_config_file(CMake/curl-config.cmake.in
"${project_config}"
INSTALL_DESTINATION ${CURL_INSTALL_CMAKE_DIR}
)
if(CURL_ENABLE_EXPORT_TARGET)
install(
EXPORT "${TARGETS_EXPORT_NAME}"
NAMESPACE "${PROJECT_NAME}::"
DESTINATION ${CURL_INSTALL_CMAKE_DIR}
)
endif()
if(CURL_ENABLE_EXPORT_TARGET)
install(
EXPORT "${TARGETS_EXPORT_NAME}"
NAMESPACE "${PROJECT_NAME}::"
FILES ${version_config} ${project_config}
DESTINATION ${CURL_INSTALL_CMAKE_DIR}
)
endif()
install(
FILES ${version_config} ${project_config}
DESTINATION ${CURL_INSTALL_CMAKE_DIR}
)
# Workaround for MSVS10 to avoid the Dialog Hell
# FIXME: This could be removed with future version of CMake.
if(MSVC_VERSION EQUAL 1600)
set(CURL_SLN_FILENAME "${CMAKE_CURRENT_BINARY_DIR}/CURL.sln")
if(EXISTS "${CURL_SLN_FILENAME}")
file(APPEND "${CURL_SLN_FILENAME}" "\n# This should be regenerated!\n")
endif()
endif()
# Workaround for MSVS10 to avoid the Dialog Hell
# FIXME: This could be removed with future version of CMake.
if(MSVC_VERSION EQUAL 1600)
set(CURL_SLN_FILENAME "${CMAKE_CURRENT_BINARY_DIR}/CURL.sln")
if(EXISTS "${CURL_SLN_FILENAME}")
file(APPEND "${CURL_SLN_FILENAME}" "\n# This should be regenerated!\n")
if(NOT TARGET curl_uninstall)
configure_file(
${CMAKE_CURRENT_SOURCE_DIR}/CMake/cmake_uninstall.cmake.in
${CMAKE_CURRENT_BINARY_DIR}/CMake/cmake_uninstall.cmake
IMMEDIATE @ONLY)
add_custom_target(curl_uninstall
COMMAND ${CMAKE_COMMAND} -P
${CMAKE_CURRENT_BINARY_DIR}/CMake/cmake_uninstall.cmake)
endif()
endif()
if(NOT TARGET curl_uninstall)
configure_file(
${CMAKE_CURRENT_SOURCE_DIR}/CMake/cmake_uninstall.cmake.in
${CMAKE_CURRENT_BINARY_DIR}/CMake/cmake_uninstall.cmake
IMMEDIATE @ONLY)
add_custom_target(curl_uninstall
COMMAND ${CMAKE_COMMAND} -P
${CMAKE_CURRENT_BINARY_DIR}/CMake/cmake_uninstall.cmake)
endif()
+9 -17
View File
@@ -53,28 +53,19 @@
#include "curlver.h" /* libcurl version defines */
#include "system.h" /* determine things run-time */
/*
* Define CURL_WIN32 when build target is Win32 API
*/
#if (defined(_WIN32) || defined(__WIN32__) || defined(WIN32)) && \
!defined(__SYMBIAN32__)
#define CURL_WIN32
#endif
#include <stdio.h>
#include <limits.h>
#if (defined(__FreeBSD__) && (__FreeBSD__ >= 2)) || defined(__MidnightBSD__)
#if defined(__FreeBSD__) || defined(__MidnightBSD__)
/* Needed for __FreeBSD_version or __MidnightBSD_version symbol definition */
#include <osreldate.h>
#include <sys/param.h>
#endif
/* The include stuff here below is mainly for time_t! */
#include <sys/types.h>
#include <time.h>
#if defined(CURL_WIN32) && !defined(_WIN32_WCE) && !defined(__CYGWIN__)
#if defined(_WIN32) && !defined(_WIN32_WCE) && !defined(__CYGWIN__)
#if !(defined(_WINSOCKAPI_) || defined(_WINSOCK_H) || \
defined(__LWIP_OPT_H__) || defined(LWIP_HDR_OPT_H))
/* The check above prevents the winsock2 inclusion if winsock.h already was
@@ -88,7 +79,7 @@
libc5-based Linux systems. Only include it on systems that are known to
require it! */
#if defined(_AIX) || defined(__NOVELL_LIBC__) || defined(__NetBSD__) || \
defined(__minix) || defined(__SYMBIAN32__) || defined(__INTEGRITY) || \
defined(__minix) || defined(__INTEGRITY) || \
defined(ANDROID) || defined(__ANDROID__) || defined(__OpenBSD__) || \
defined(__CYGWIN__) || defined(AMIGA) || defined(__NuttX__) || \
(defined(__FreeBSD_version) && (__FreeBSD_version < 800000)) || \
@@ -97,11 +88,11 @@
#include <sys/select.h>
#endif
#if !defined(CURL_WIN32) && !defined(_WIN32_WCE)
#if !defined(_WIN32) && !defined(_WIN32_WCE)
#include <sys/socket.h>
#endif
#if !defined(CURL_WIN32)
#if !defined(_WIN32)
#include <sys/time.h>
#endif
@@ -128,7 +119,7 @@ typedef void CURLSH;
#ifdef CURL_STATICLIB
# define CURL_EXTERN
#elif defined(CURL_WIN32) || defined(__SYMBIAN32__) || \
#elif defined(_WIN32) || \
(__has_declspec_attribute(dllexport) && \
__has_declspec_attribute(dllimport))
# if defined(BUILDING_LIBCURL)
@@ -144,7 +135,7 @@ typedef void CURLSH;
#ifndef curl_socket_typedef
/* socket typedef */
#if defined(CURL_WIN32) && !defined(__LWIP_OPT_H__) && !defined(LWIP_HDR_OPT_H)
#if defined(_WIN32) && !defined(__LWIP_OPT_H__) && !defined(LWIP_HDR_OPT_H)
typedef SOCKET curl_socket_t;
#define CURL_SOCKET_BAD INVALID_SOCKET
#else
@@ -3220,6 +3211,7 @@ CURL_EXTERN CURLcode curl_easy_pause(CURL *handle, int bitmask);
#include "options.h"
#include "header.h"
#include "websockets.h"
#include "mprintf.h"
/* the typechecker doesn't work in C++ (yet) */
#if defined(__GNUC__) && defined(__GNUC_MINOR__) && \
+3 -3
View File
@@ -32,12 +32,12 @@
/* This is the version number of the libcurl package from which this header
file origins: */
#define LIBCURL_VERSION "8.4.0"
#define LIBCURL_VERSION "8.5.0"
/* The numeric version number is also available "in parts" by using these
defines: */
#define LIBCURL_VERSION_MAJOR 8
#define LIBCURL_VERSION_MINOR 4
#define LIBCURL_VERSION_MINOR 5
#define LIBCURL_VERSION_PATCH 0
/* This is the numeric version of the libcurl version number, meant for easier
@@ -59,7 +59,7 @@
CURL_VERSION_BITS() macro since curl's own configure script greps for it
and needs it to contain the full number.
*/
#define LIBCURL_VERSION_NUM 0x080400
#define LIBCURL_VERSION_NUM 0x080500
/*
* This is the date and time when the full source package was created. The
+11 -26
View File
@@ -141,29 +141,6 @@
# define CURL_TYPEOF_CURL_SOCKLEN_T int
# endif
#elif defined(__SYMBIAN32__)
# if defined(__EABI__) /* Treat all ARM compilers equally */
# define CURL_TYPEOF_CURL_OFF_T long long
# define CURL_FORMAT_CURL_OFF_T "lld"
# define CURL_FORMAT_CURL_OFF_TU "llu"
# define CURL_SUFFIX_CURL_OFF_T LL
# define CURL_SUFFIX_CURL_OFF_TU ULL
# elif defined(__CW32__)
# pragma longlong on
# define CURL_TYPEOF_CURL_OFF_T long long
# define CURL_FORMAT_CURL_OFF_T "lld"
# define CURL_FORMAT_CURL_OFF_TU "llu"
# define CURL_SUFFIX_CURL_OFF_T LL
# define CURL_SUFFIX_CURL_OFF_TU ULL
# elif defined(__VC32__)
# define CURL_TYPEOF_CURL_OFF_T __int64
# define CURL_FORMAT_CURL_OFF_T "lld"
# define CURL_FORMAT_CURL_OFF_TU "llu"
# define CURL_SUFFIX_CURL_OFF_T LL
# define CURL_SUFFIX_CURL_OFF_TU ULL
# endif
# define CURL_TYPEOF_CURL_SOCKLEN_T unsigned int
#elif defined(macintosh)
# include <ConditionalMacros.h>
# if TYPE_LONGLONG
@@ -201,9 +178,10 @@
# define CURL_TYPEOF_CURL_SOCKLEN_T int
#elif defined(__MINGW32__)
# include <inttypes.h>
# define CURL_TYPEOF_CURL_OFF_T long long
# define CURL_FORMAT_CURL_OFF_T "I64d"
# define CURL_FORMAT_CURL_OFF_TU "I64u"
# define CURL_FORMAT_CURL_OFF_T PRId64
# define CURL_FORMAT_CURL_OFF_TU PRIu64
# define CURL_SUFFIX_CURL_OFF_T LL
# define CURL_SUFFIX_CURL_OFF_TU ULL
# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
@@ -370,7 +348,14 @@
/* ===================================== */
#elif defined(_MSC_VER)
# if (_MSC_VER >= 900) && (_INTEGRAL_MAX_BITS >= 64)
# if (_MSC_VER >= 1800)
# include <inttypes.h>
# define CURL_TYPEOF_CURL_OFF_T __int64
# define CURL_FORMAT_CURL_OFF_T PRId64
# define CURL_FORMAT_CURL_OFF_TU PRIu64
# define CURL_SUFFIX_CURL_OFF_T i64
# define CURL_SUFFIX_CURL_OFF_TU ui64
# elif (_MSC_VER >= 900) && (_INTEGRAL_MAX_BITS >= 64)
# define CURL_TYPEOF_CURL_OFF_T __int64
# define CURL_FORMAT_CURL_OFF_T "I64d"
# define CURL_FORMAT_CURL_OFF_TU "I64u"
+13 -8
View File
@@ -85,20 +85,25 @@ endif()
return() # The rest of this file is not needed for building within CMake.
#-----------------------------------------------------------------------------
add_library(
curlu # special libcurlu library just for unittests
STATIC
EXCLUDE_FROM_ALL
${HHEADERS} ${CSOURCES}
)
target_compile_definitions(curlu PUBLIC UNITTESTS CURL_STATICLIB)
if(BUILD_TESTING)
add_library(
curlu # special libcurlu library just for unittests
STATIC
EXCLUDE_FROM_ALL
${HHEADERS} ${CSOURCES}
)
target_compile_definitions(curlu PUBLIC UNITTESTS CURL_STATICLIB)
endif()
if(ENABLE_CURLDEBUG)
# We must compile these sources separately to avoid memdebug.h redefinitions
# applying to them.
set_source_files_properties(memdebug.c curl_multibyte.c PROPERTIES SKIP_UNITY_BUILD_INCLUSION ON)
endif()
target_link_libraries(curlu PRIVATE ${CURL_LIBS})
if(BUILD_TESTING)
target_link_libraries(curlu PRIVATE ${CURL_LIBS})
endif()
transform_makefile_inc("Makefile.soname" "${CMAKE_CURRENT_BINARY_DIR}/Makefile.soname.cmake")
include(${CMAKE_CURRENT_BINARY_DIR}/Makefile.soname.cmake)
+4 -6
View File
@@ -97,7 +97,7 @@ static struct altsvc *altsvc_createid(const char *srchost,
unsigned int srcport,
unsigned int dstport)
{
struct altsvc *as = calloc(sizeof(struct altsvc), 1);
struct altsvc *as = calloc(1, sizeof(struct altsvc));
size_t hlen;
size_t dlen;
if(!as)
@@ -123,15 +123,13 @@ static struct altsvc *altsvc_createid(const char *srchost,
dlen -= 2;
}
as->src.host = Curl_memdup(srchost, hlen + 1);
as->src.host = Curl_strndup(srchost, hlen);
if(!as->src.host)
goto error;
as->src.host[hlen] = 0;
as->dst.host = Curl_memdup(dsthost, dlen + 1);
as->dst.host = Curl_strndup(dsthost, dlen);
if(!as->dst.host)
goto error;
as->dst.host[dlen] = 0;
as->src.alpnid = srcalpnid;
as->dst.alpnid = dstalpnid;
@@ -301,7 +299,7 @@ static CURLcode altsvc_out(struct altsvc *as, FILE *fp)
*/
struct altsvcinfo *Curl_altsvc_init(void)
{
struct altsvcinfo *asi = calloc(sizeof(struct altsvcinfo), 1);
struct altsvcinfo *asi = calloc(1, sizeof(struct altsvcinfo));
if(!asi)
return NULL;
Curl_llist_init(&asi->list, NULL);
+8 -1
View File
@@ -56,12 +56,14 @@ static const char * const telnetoptions[]=
"TERM SPEED", "LFLOW", "LINEMODE", "XDISPLOC",
"OLD-ENVIRON", "AUTHENTICATION", "ENCRYPT", "NEW-ENVIRON"
};
#define CURL_TELOPT(x) telnetoptions[x]
#else
#define CURL_TELOPT(x) ""
#endif
#define CURL_TELOPT_MAXIMUM CURL_TELOPT_NEW_ENVIRON
#define CURL_TELOPT_OK(x) ((x) <= CURL_TELOPT_MAXIMUM)
#define CURL_TELOPT(x) telnetoptions[x]
#define CURL_NTELOPTS 40
@@ -103,7 +105,12 @@ static const char * const telnetcmds[]=
#define CURL_TELCMD_OK(x) ( ((unsigned int)(x) >= CURL_TELCMD_MINIMUM) && \
((unsigned int)(x) <= CURL_TELCMD_MAXIMUM) )
#ifndef CURL_DISABLE_VERBOSE_STRINGS
#define CURL_TELCMD(x) telnetcmds[(x)-CURL_TELCMD_MINIMUM]
#else
#define CURL_TELCMD(x) ""
#endif
#endif /* CURL_DISABLE_TELNET */
+89 -60
View File
@@ -60,13 +60,13 @@
#include "progress.h"
#include "timediff.h"
# if defined(CURL_STATICLIB) && !defined(CARES_STATICLIB) && \
defined(WIN32)
# define CARES_STATICLIB
# endif
# include <ares.h>
# include <ares_version.h> /* really old c-ares didn't include this by
itself */
#if defined(CURL_STATICLIB) && !defined(CARES_STATICLIB) && \
defined(_WIN32)
# define CARES_STATICLIB
#endif
#include <ares.h>
#include <ares_version.h> /* really old c-ares didn't include this by
itself */
#if ARES_VERSION >= 0x010500
/* c-ares 1.5.0 or later, the callback proto is modified */
@@ -228,9 +228,9 @@ static void destroy_async_data(struct Curl_async *async);
void Curl_resolver_cancel(struct Curl_easy *data)
{
DEBUGASSERT(data);
if(data->state.async.resolver)
ares_cancel((ares_channel)data->state.async.resolver);
destroy_async_data(&data->state.async);
if(data->conn->resolve_async.resolver)
ares_cancel((ares_channel)data->conn->resolve_async.resolver);
destroy_async_data(&data->conn->resolve_async);
}
/*
@@ -278,14 +278,14 @@ int Curl_resolver_getsock(struct Curl_easy *data,
struct timeval timebuf;
struct timeval *timeout;
long milli;
int max = ares_getsock((ares_channel)data->state.async.resolver,
int max = ares_getsock((ares_channel)data->conn->resolve_async.resolver,
(ares_socket_t *)socks, MAX_SOCKSPEREASYHANDLE);
maxtime.tv_sec = CURL_TIMEOUT_RESOLVE;
maxtime.tv_usec = 0;
timeout = ares_timeout((ares_channel)data->state.async.resolver, &maxtime,
&timebuf);
timeout = ares_timeout((ares_channel)data->conn->resolve_async.resolver,
&maxtime, &timebuf);
milli = (long)curlx_tvtoms(timeout);
if(milli == 0)
milli += 10;
@@ -313,8 +313,8 @@ static int waitperform(struct Curl_easy *data, timediff_t timeout_ms)
int i;
int num = 0;
bitmask = ares_getsock((ares_channel)data->state.async.resolver, socks,
ARES_GETSOCK_MAXNUM);
bitmask = ares_getsock((ares_channel)data->conn->resolve_async.resolver,
socks, ARES_GETSOCK_MAXNUM);
for(i = 0; i < ARES_GETSOCK_MAXNUM; i++) {
pfd[i].events = 0;
@@ -344,12 +344,12 @@ static int waitperform(struct Curl_easy *data, timediff_t timeout_ms)
if(!nfds)
/* Call ares_process() unconditionally here, even if we simply timed out
above, as otherwise the ares name resolve won't timeout! */
ares_process_fd((ares_channel)data->state.async.resolver, ARES_SOCKET_BAD,
ARES_SOCKET_BAD);
ares_process_fd((ares_channel)data->conn->resolve_async.resolver,
ARES_SOCKET_BAD, ARES_SOCKET_BAD);
else {
/* move through the descriptors and ask for processing on them */
for(i = 0; i < num; i++)
ares_process_fd((ares_channel)data->state.async.resolver,
ares_process_fd((ares_channel)data->conn->resolve_async.resolver,
(pfd[i].revents & (POLLRDNORM|POLLIN))?
pfd[i].fd:ARES_SOCKET_BAD,
(pfd[i].revents & (POLLWRNORM|POLLOUT))?
@@ -368,7 +368,7 @@ static int waitperform(struct Curl_easy *data, timediff_t timeout_ms)
CURLcode Curl_resolver_is_resolved(struct Curl_easy *data,
struct Curl_dns_entry **dns)
{
struct thread_data *res = data->state.async.tdata;
struct thread_data *res = data->conn->resolve_async.tdata;
CURLcode result = CURLE_OK;
DEBUGASSERT(dns);
@@ -397,7 +397,7 @@ CURLcode Curl_resolver_is_resolved(struct Curl_easy *data,
ARES_ECANCELLED synchronously for all pending responses. This will
leave us with res->num_pending == 0, which is perfect for the next
block. */
ares_cancel((ares_channel)data->state.async.resolver);
ares_cancel((ares_channel)data->conn->resolve_async.resolver);
DEBUGASSERT(res->num_pending == 0);
}
#endif
@@ -408,12 +408,12 @@ CURLcode Curl_resolver_is_resolved(struct Curl_easy *data,
them */
res->temp_ai = NULL;
if(!data->state.async.dns)
if(!data->conn->resolve_async.dns)
result = Curl_resolver_error(data);
else
*dns = data->state.async.dns;
*dns = data->conn->resolve_async.dns;
destroy_async_data(&data->state.async);
destroy_async_data(&data->conn->resolve_async);
}
return result;
@@ -464,7 +464,8 @@ CURLcode Curl_resolver_wait_resolv(struct Curl_easy *data,
store.tv_sec = itimeout/1000;
store.tv_usec = (itimeout%1000)*1000;
tvp = ares_timeout((ares_channel)data->state.async.resolver, &store, &tv);
tvp = ares_timeout((ares_channel)data->conn->resolve_async.resolver,
&store, &tv);
/* use the timeout period ares returned to us above if less than one
second is left, otherwise just use 1000ms to make sure the progress
@@ -478,7 +479,7 @@ CURLcode Curl_resolver_wait_resolv(struct Curl_easy *data,
return CURLE_UNRECOVERABLE_POLL;
result = Curl_resolver_is_resolved(data, entry);
if(result || data->state.async.done)
if(result || data->conn->resolve_async.done)
break;
if(Curl_pgrsUpdate(data))
@@ -499,12 +500,12 @@ CURLcode Curl_resolver_wait_resolv(struct Curl_easy *data,
}
if(result)
/* failure, so we cancel the ares operation */
ares_cancel((ares_channel)data->state.async.resolver);
ares_cancel((ares_channel)data->conn->resolve_async.resolver);
/* Operation complete, if the lookup was successful we now have the entry
in the cache. */
if(entry)
*entry = data->state.async.dns;
*entry = data->conn->resolve_async.dns;
if(result)
/* close the connection, since we can't return failure here without
@@ -571,12 +572,13 @@ static void query_completed_cb(void *arg, /* (struct connectdata *) */
be valid so only defer it when we know the 'status' says its fine! */
return;
res = data->state.async.tdata;
res = data->conn->resolve_async.tdata;
if(res) {
res->num_pending--;
if(CURL_ASYNC_SUCCESS == status) {
struct Curl_addrinfo *ai = Curl_he2ai(hostent, data->state.async.port);
struct Curl_addrinfo *ai = Curl_he2ai(hostent,
data->conn->resolve_async.port);
if(ai) {
compound_results(res, ai);
}
@@ -727,14 +729,16 @@ static void addrinfo_cb(void *arg, int status, int timeouts,
struct ares_addrinfo *result)
{
struct Curl_easy *data = (struct Curl_easy *)arg;
struct thread_data *res = data->state.async.tdata;
(void)timeouts;
if(ARES_SUCCESS == status) {
res->temp_ai = ares2addr(result->nodes);
res->last_status = CURL_ASYNC_SUCCESS;
ares_freeaddrinfo(result);
if(data->conn) {
struct thread_data *res = data->conn->resolve_async.tdata;
(void)timeouts;
if(ARES_SUCCESS == status) {
res->temp_ai = ares2addr(result->nodes);
res->last_status = CURL_ASYNC_SUCCESS;
ares_freeaddrinfo(result);
}
res->num_pending--;
}
res->num_pending--;
}
#endif
@@ -755,15 +759,15 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data,
size_t namelen = strlen(hostname);
*waitp = 0; /* default to synchronous response */
res = calloc(sizeof(struct thread_data) + namelen, 1);
res = calloc(1, sizeof(struct thread_data) + namelen);
if(res) {
strcpy(res->hostname, hostname);
data->state.async.hostname = res->hostname;
data->state.async.port = port;
data->state.async.done = FALSE; /* not done */
data->state.async.status = 0; /* clear */
data->state.async.dns = NULL; /* clear */
data->state.async.tdata = res;
data->conn->resolve_async.hostname = res->hostname;
data->conn->resolve_async.port = port;
data->conn->resolve_async.done = FALSE; /* not done */
data->conn->resolve_async.status = 0; /* clear */
data->conn->resolve_async.dns = NULL; /* clear */
data->conn->resolve_async.tdata = res;
/* initial status - failed */
res->last_status = ARES_ENOTFOUND;
@@ -793,8 +797,8 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data,
hints.ai_flags = ARES_AI_NUMERICSERV;
msnprintf(service, sizeof(service), "%d", port);
res->num_pending = 1;
ares_getaddrinfo((ares_channel)data->state.async.resolver, hostname,
service, &hints, addrinfo_cb, data);
ares_getaddrinfo((ares_channel)data->conn->resolve_async.resolver,
hostname, service, &hints, addrinfo_cb, data);
}
#else
@@ -804,10 +808,10 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data,
res->num_pending = 2;
/* areschannel is already setup in the Curl_open() function */
ares_gethostbyname((ares_channel)data->state.async.resolver, hostname,
PF_INET, query_completed_cb, data);
ares_gethostbyname((ares_channel)data->state.async.resolver, hostname,
PF_INET6, query_completed_cb, data);
ares_gethostbyname((ares_channel)data->conn->resolve_async.resolver,
hostname, PF_INET, query_completed_cb, data);
ares_gethostbyname((ares_channel)data->conn->resolve_async.resolver,
hostname, PF_INET6, query_completed_cb, data);
}
else
#endif
@@ -815,7 +819,7 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data,
res->num_pending = 1;
/* areschannel is already setup in the Curl_open() function */
ares_gethostbyname((ares_channel)data->state.async.resolver,
ares_gethostbyname((ares_channel)data->conn->resolve_async.resolver,
hostname, PF_INET,
query_completed_cb, data);
}
@@ -829,6 +833,7 @@ CURLcode Curl_set_dns_servers(struct Curl_easy *data,
char *servers)
{
CURLcode result = CURLE_NOT_BUILT_IN;
ares_channel channel, lchannel = NULL;
int ares_result;
/* If server is NULL or empty, this would purge all DNS servers
@@ -841,11 +846,23 @@ CURLcode Curl_set_dns_servers(struct Curl_easy *data,
return CURLE_OK;
#ifdef HAVE_CARES_SERVERS_CSV
if(data->conn)
channel = data->conn->resolve_async.resolver;
else {
/* we are called by setopt on a data without a connection (yet). In that
* case we set the value on a local instance for checking.
* The configured data options are set when the connection for this
* transfer is created. */
result = Curl_resolver_init(data, (void **)&lchannel);
if(result)
goto out;
channel = lchannel;
}
#ifdef HAVE_CARES_PORTS_CSV
ares_result = ares_set_servers_ports_csv(data->state.async.resolver,
servers);
ares_result = ares_set_servers_ports_csv(channel, servers);
#else
ares_result = ares_set_servers_csv(data->state.async.resolver, servers);
ares_result = ares_set_servers_csv(channel, servers);
#endif
switch(ares_result) {
case ARES_SUCCESS:
@@ -861,6 +878,9 @@ CURLcode Curl_set_dns_servers(struct Curl_easy *data,
result = CURLE_BAD_FUNCTION_ARGUMENT;
break;
}
out:
if(lchannel)
Curl_resolver_cleanup(lchannel);
#else /* too old c-ares version! */
(void)data;
(void)(ares_result);
@@ -872,11 +892,14 @@ CURLcode Curl_set_dns_interface(struct Curl_easy *data,
const char *interf)
{
#ifdef HAVE_CARES_LOCAL_DEV
if(!interf)
interf = "";
ares_set_local_dev((ares_channel)data->state.async.resolver, interf);
if(data->conn) {
/* not a setopt test run, set the value */
if(!interf)
interf = "";
ares_set_local_dev((ares_channel)data->conn->resolve_async.resolver,
interf);
}
return CURLE_OK;
#else /* c-ares version too old! */
(void)data;
@@ -900,8 +923,11 @@ CURLcode Curl_set_dns_local_ip4(struct Curl_easy *data,
}
}
ares_set_local_ip4((ares_channel)data->state.async.resolver,
ntohl(a4.s_addr));
if(data->conn) {
/* not a setopt test run, set the value */
ares_set_local_ip4((ares_channel)data->conn->resolve_async.resolver,
ntohl(a4.s_addr));
}
return CURLE_OK;
#else /* c-ares version too old! */
@@ -927,7 +953,10 @@ CURLcode Curl_set_dns_local_ip6(struct Curl_easy *data,
}
}
ares_set_local_ip6((ares_channel)data->state.async.resolver, a6);
if(data->conn) {
/* not a setopt test run, set the value */
ares_set_local_ip6((ares_channel)data->conn->resolve_async.resolver, a6);
}
return CURLE_OK;
#else /* c-ares version too old! */
+25 -25
View File
@@ -136,7 +136,7 @@ static void destroy_async_data(struct Curl_async *);
*/
void Curl_resolver_cancel(struct Curl_easy *data)
{
destroy_async_data(&data->state.async);
destroy_async_data(&data->conn->resolve_async);
}
/* This function is used to init a threaded resolve */
@@ -173,7 +173,7 @@ struct thread_data {
static struct thread_sync_data *conn_thread_sync_data(struct Curl_easy *data)
{
return &(data->state.async.tdata->tsd);
return &(data->conn->resolve_async.tdata->tsd);
}
/* Destroy resolver thread synchronization data */
@@ -196,7 +196,7 @@ void destroy_thread_sync_data(struct thread_sync_data *tsd)
* the other end (for reading) is always closed in the parent thread.
*/
if(tsd->sock_pair[1] != CURL_SOCKET_BAD) {
sclose(tsd->sock_pair[1]);
wakeup_close(tsd->sock_pair[1]);
}
#endif
memset(tsd, 0, sizeof(*tsd));
@@ -233,8 +233,8 @@ int init_thread_sync_data(struct thread_data *td,
Curl_mutex_init(tsd->mtx);
#ifndef CURL_DISABLE_SOCKETPAIR
/* create socket pair, avoid AF_LOCAL since it doesn't build on Solaris */
if(Curl_socketpair(AF_UNIX, SOCK_STREAM, 0, &tsd->sock_pair[0]) < 0) {
/* create socket pair or pipe */
if(wakeup_create(&tsd->sock_pair[0]) < 0) {
tsd->sock_pair[0] = CURL_SOCKET_BAD;
tsd->sock_pair[1] = CURL_SOCKET_BAD;
goto err_exit;
@@ -254,7 +254,7 @@ int init_thread_sync_data(struct thread_data *td,
err_exit:
#ifndef CURL_DISABLE_SOCKETPAIR
if(tsd->sock_pair[0] != CURL_SOCKET_BAD) {
sclose(tsd->sock_pair[0]);
wakeup_close(tsd->sock_pair[0]);
tsd->sock_pair[0] = CURL_SOCKET_BAD;
}
#endif
@@ -320,7 +320,7 @@ static unsigned int CURL_STDCALL getaddrinfo_thread(void *arg)
if(tsd->sock_pair[1] != CURL_SOCKET_BAD) {
/* DNS has been resolved, signal client task */
buf[0] = 1;
if(swrite(tsd->sock_pair[1], buf, sizeof(buf)) < 0) {
if(wakeup_write(tsd->sock_pair[1], buf, sizeof(buf)) < 0) {
/* update sock_erro to errno */
tsd->sock_error = SOCKERRNO;
}
@@ -428,9 +428,9 @@ static bool init_resolve_thread(struct Curl_easy *data,
{
struct thread_data *td = calloc(1, sizeof(struct thread_data));
int err = ENOMEM;
struct Curl_async *asp = &data->state.async;
struct Curl_async *asp = &data->conn->resolve_async;
data->state.async.tdata = td;
data->conn->resolve_async.tdata = td;
if(!td)
goto errno_exit;
@@ -488,7 +488,7 @@ static CURLcode thread_wait_resolv(struct Curl_easy *data,
CURLcode result = CURLE_OK;
DEBUGASSERT(data);
td = data->state.async.tdata;
td = data->conn->resolve_async.tdata;
DEBUGASSERT(td);
DEBUGASSERT(td->thread_hnd != curl_thread_t_null);
@@ -500,18 +500,18 @@ static CURLcode thread_wait_resolv(struct Curl_easy *data,
else
DEBUGASSERT(0);
data->state.async.done = TRUE;
data->conn->resolve_async.done = TRUE;
if(entry)
*entry = data->state.async.dns;
*entry = data->conn->resolve_async.dns;
if(!data->state.async.dns && report)
if(!data->conn->resolve_async.dns && report)
/* a name was not resolved, report error */
result = Curl_resolver_error(data);
destroy_async_data(&data->state.async);
destroy_async_data(&data->conn->resolve_async);
if(!data->state.async.dns && report)
if(!data->conn->resolve_async.dns && report)
connclose(data->conn, "asynch resolve failed");
return result;
@@ -524,7 +524,7 @@ static CURLcode thread_wait_resolv(struct Curl_easy *data,
*/
void Curl_resolver_kill(struct Curl_easy *data)
{
struct thread_data *td = data->state.async.tdata;
struct thread_data *td = data->conn->resolve_async.tdata;
/* If we're still resolving, we must wait for the threads to fully clean up,
unfortunately. Otherwise, we can simply cancel to clean up any resolver
@@ -563,7 +563,7 @@ CURLcode Curl_resolver_wait_resolv(struct Curl_easy *data,
CURLcode Curl_resolver_is_resolved(struct Curl_easy *data,
struct Curl_dns_entry **entry)
{
struct thread_data *td = data->state.async.tdata;
struct thread_data *td = data->conn->resolve_async.tdata;
int done = 0;
DEBUGASSERT(entry);
@@ -581,13 +581,13 @@ CURLcode Curl_resolver_is_resolved(struct Curl_easy *data,
if(done) {
getaddrinfo_complete(data);
if(!data->state.async.dns) {
if(!data->conn->resolve_async.dns) {
CURLcode result = Curl_resolver_error(data);
destroy_async_data(&data->state.async);
destroy_async_data(&data->conn->resolve_async);
return result;
}
destroy_async_data(&data->state.async);
*entry = data->state.async.dns;
destroy_async_data(&data->conn->resolve_async);
*entry = data->conn->resolve_async.dns;
}
else {
/* poll for name lookup done with exponential backoff up to 250ms */
@@ -619,9 +619,9 @@ int Curl_resolver_getsock(struct Curl_easy *data, curl_socket_t *socks)
int ret_val = 0;
timediff_t milli;
timediff_t ms;
struct resdata *reslv = (struct resdata *)data->state.async.resolver;
struct resdata *reslv = (struct resdata *)data->conn->resolve_async.resolver;
#ifndef CURL_DISABLE_SOCKETPAIR
struct thread_data *td = data->state.async.tdata;
struct thread_data *td = data->conn->resolve_async.tdata;
#else
(void)socks;
#endif
@@ -662,7 +662,7 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data,
int port,
int *waitp)
{
struct resdata *reslv = (struct resdata *)data->state.async.resolver;
struct resdata *reslv = (struct resdata *)data->conn->resolve_async.resolver;
*waitp = 0; /* default to synchronous response */
@@ -691,7 +691,7 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data,
{
struct addrinfo hints;
int pf = PF_INET;
struct resdata *reslv = (struct resdata *)data->state.async.resolver;
struct resdata *reslv = (struct resdata *)data->conn->resolve_async.resolver;
*waitp = 0; /* default to synchronous response */
+1
View File
@@ -31,6 +31,7 @@
!defined(CURL_DISABLE_SMTP) || \
!defined(CURL_DISABLE_POP3) || \
!defined(CURL_DISABLE_IMAP) || \
!defined(CURL_DISABLE_DIGEST_AUTH) || \
!defined(CURL_DISABLE_DOH) || defined(USE_SSL) || defined(BUILDING_CURL)
#include "curl/curl.h"
#include "warnless.h"
+38 -68
View File
@@ -22,6 +22,10 @@
*
***************************************************************************/
/* Curl's integration with Hyper. This replaces certain functions in http.c,
* based on configuration #defines. This implementation supports HTTP/1.1 but
* not HTTP/2.
*/
#include "curl_setup.h"
#if !defined(CURL_DISABLE_HTTP) && defined(USE_HYPER)
@@ -172,17 +176,15 @@ static int hyper_each_header(void *userdata,
Curl_debug(data, CURLINFO_HEADER_IN, headp, len);
if(!data->state.hconnect || !data->set.suppress_connect_headers) {
writetype = CLIENTWRITE_HEADER;
if(data->state.hconnect)
writetype |= CLIENTWRITE_CONNECT;
if(data->req.httpcode/100 == 1)
writetype |= CLIENTWRITE_1XX;
result = Curl_client_write(data, writetype, headp, len);
if(result) {
data->state.hresult = CURLE_ABORTED_BY_CALLBACK;
return HYPER_ITER_BREAK;
}
writetype = CLIENTWRITE_HEADER;
if(data->state.hconnect)
writetype |= CLIENTWRITE_CONNECT;
if(data->req.httpcode/100 == 1)
writetype |= CLIENTWRITE_1XX;
result = Curl_client_write(data, writetype, headp, len);
if(result) {
data->state.hresult = CURLE_ABORTED_BY_CALLBACK;
return HYPER_ITER_BREAK;
}
result = Curl_bump_headersize(data, len, FALSE);
@@ -201,7 +203,7 @@ static int hyper_body_chunk(void *userdata, const hyper_buf *chunk)
struct SingleRequest *k = &data->req;
CURLcode result = CURLE_OK;
if(0 == k->bodywrites++) {
if(0 == k->bodywrites) {
bool done = FALSE;
#if defined(USE_NTLM)
struct connectdata *conn = data->conn;
@@ -241,11 +243,6 @@ static int hyper_body_chunk(void *userdata, const hyper_buf *chunk)
return HYPER_ITER_BREAK;
}
}
if(k->ignorebody)
return HYPER_ITER_CONTINUE;
if(0 == len)
return HYPER_ITER_CONTINUE;
Curl_debug(data, CURLINFO_DATA_IN, buf, len);
result = Curl_client_write(data, CLIENTWRITE_BODY, buf, len);
if(result) {
@@ -253,12 +250,6 @@ static int hyper_body_chunk(void *userdata, const hyper_buf *chunk)
return HYPER_ITER_BREAK;
}
data->req.bytecount += len;
result = Curl_pgrsSetDownloadCounter(data, data->req.bytecount);
if(result) {
data->state.hresult = result;
return HYPER_ITER_BREAK;
}
return HYPER_ITER_CONTINUE;
}
@@ -310,13 +301,14 @@ static CURLcode status_line(struct Curl_easy *data,
Curl_debug(data, CURLINFO_HEADER_IN, Curl_dyn_ptr(&data->state.headerb),
len);
if(!data->state.hconnect || !data->set.suppress_connect_headers) {
writetype = CLIENTWRITE_HEADER|CLIENTWRITE_STATUS;
result = Curl_client_write(data, writetype,
Curl_dyn_ptr(&data->state.headerb), len);
if(result)
return result;
}
writetype = CLIENTWRITE_HEADER|CLIENTWRITE_STATUS;
if(data->state.hconnect)
writetype |= CLIENTWRITE_CONNECT;
result = Curl_client_write(data, writetype,
Curl_dyn_ptr(&data->state.headerb), len);
if(result)
return result;
result = Curl_bump_headersize(data, len, FALSE);
return result;
}
@@ -551,11 +543,9 @@ CURLcode Curl_hyper_stream(struct Curl_easy *data,
static CURLcode debug_request(struct Curl_easy *data,
const char *method,
const char *path,
bool h2)
const char *path)
{
char *req = aprintf("%s %s HTTP/%s\r\n", method, path,
h2?"2":"1.1");
char *req = aprintf("%s %s HTTP/1.1\r\n", method, path);
if(!req)
return CURLE_OUT_OF_MEMORY;
Curl_debug(data, CURLINFO_HEADER_OUT, req, strlen(req));
@@ -637,7 +627,6 @@ CURLcode Curl_hyper_header(struct Curl_easy *data, hyper_headers *headers,
static CURLcode request_target(struct Curl_easy *data,
struct connectdata *conn,
const char *method,
bool h2,
hyper_request *req)
{
CURLcode result;
@@ -649,26 +638,13 @@ static CURLcode request_target(struct Curl_easy *data,
if(result)
return result;
if(h2 && hyper_request_set_uri_parts(req,
/* scheme */
(uint8_t *)data->state.up.scheme,
strlen(data->state.up.scheme),
/* authority */
(uint8_t *)conn->host.name,
strlen(conn->host.name),
/* path_and_query */
(uint8_t *)Curl_dyn_uptr(&r),
Curl_dyn_len(&r))) {
failf(data, "error setting uri parts to hyper");
result = CURLE_OUT_OF_MEMORY;
}
else if(!h2 && hyper_request_set_uri(req, (uint8_t *)Curl_dyn_uptr(&r),
if(hyper_request_set_uri(req, (uint8_t *)Curl_dyn_uptr(&r),
Curl_dyn_len(&r))) {
failf(data, "error setting uri to hyper");
result = CURLE_OUT_OF_MEMORY;
}
else
result = debug_request(data, method, Curl_dyn_ptr(&r), h2);
result = debug_request(data, method, Curl_dyn_ptr(&r));
Curl_dyn_free(&r);
@@ -899,7 +875,6 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
const char *p_accept; /* Accept: string */
const char *method;
Curl_HttpReq httpreq;
bool h2 = FALSE;
const char *te = NULL; /* transfer-encoding */
hyper_code rc;
@@ -907,6 +882,7 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
may be parts of the request that is not yet sent, since we can deal with
the rest of the request in the PERFORM phase. */
*done = TRUE;
Curl_client_cleanup(data);
infof(data, "Time for the Hyper dance");
memset(h, 0, sizeof(struct hyptransfer));
@@ -917,6 +893,8 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
Curl_http_method(data, conn, &method, &httpreq);
DEBUGASSERT(data->req.bytecount == 0);
/* setup the authentication headers */
{
char *pq = NULL;
@@ -972,8 +950,9 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
goto error;
}
if(conn->alpn == CURL_HTTP_VERSION_2) {
hyper_clientconn_options_http2(options, 1);
h2 = TRUE;
failf(data, "ALPN protocol h2 not supported with Hyper");
result = CURLE_UNSUPPORTED_PROTOCOL;
goto error;
}
hyper_clientconn_options_set_preserve_header_case(options, 1);
hyper_clientconn_options_set_preserve_header_order(options, 1);
@@ -1024,7 +1003,7 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
}
}
else {
if(!h2 && !data->state.disableexpect) {
if(!data->state.disableexpect) {
data->state.expect100header = TRUE;
}
}
@@ -1035,7 +1014,7 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
goto error;
}
result = request_target(data, conn, method, h2, req);
result = request_target(data, conn, method, req);
if(result)
goto error;
@@ -1056,19 +1035,10 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
if(result)
goto error;
if(!h2) {
if(data->state.aptr.host) {
result = Curl_hyper_header(data, headers, data->state.aptr.host);
if(result)
goto error;
}
}
else {
/* For HTTP/2, we show the Host: header as if we sent it, to make it look
like for HTTP/1 but it isn't actually sent since :authority is then
used. */
Curl_debug(data, CURLINFO_HEADER_OUT, data->state.aptr.host,
strlen(data->state.aptr.host));
if(data->state.aptr.host) {
result = Curl_hyper_header(data, headers, data->state.aptr.host);
if(result)
goto error;
}
if(data->state.aptr.proxyuserpwd) {
+25 -30
View File
@@ -374,7 +374,7 @@ static CURLcode recv_CONNECT_resp(struct Curl_cfilter *cf,
curl_socket_t tunnelsocket = Curl_conn_cf_get_socket(cf, data);
char *linep;
size_t perline;
int error;
int error, writetype;
#define SELECT_OK 0
#define SELECT_ERROR 1
@@ -386,12 +386,12 @@ static CURLcode recv_CONNECT_resp(struct Curl_cfilter *cf,
return CURLE_OK;
while(ts->keepon) {
ssize_t gotbytes;
ssize_t nread;
char byte;
/* Read one byte at a time to avoid a race condition. Wait at most one
second before looping to ensure continuous pgrsUpdates. */
result = Curl_read(data, tunnelsocket, &byte, 1, &gotbytes);
result = Curl_read(data, tunnelsocket, &byte, 1, &nread);
if(result == CURLE_AGAIN)
/* socket buffer drained, return */
return CURLE_OK;
@@ -404,7 +404,7 @@ static CURLcode recv_CONNECT_resp(struct Curl_cfilter *cf,
break;
}
if(gotbytes <= 0) {
if(nread <= 0) {
if(data->set.proxyauth && data->state.authproxy.avail &&
data->state.aptr.proxyuserpwd) {
/* proxy auth was requested and there was proxy auth available,
@@ -437,11 +437,11 @@ static CURLcode recv_CONNECT_resp(struct Curl_cfilter *cf,
properly to know when the end of the body is reached */
CHUNKcode r;
CURLcode extra;
ssize_t tookcareof = 0;
size_t consumed = 0;
/* now parse the chunked piece of data so that we can
properly tell when the stream ends */
r = Curl_httpchunk_read(data, &byte, 1, &tookcareof, &extra);
r = Curl_httpchunk_read(data, &byte, 1, &consumed, &extra);
if(r == CHUNKE_STOP) {
/* we're done reading chunks! */
infof(data, "chunk reading DONE");
@@ -467,15 +467,12 @@ static CURLcode recv_CONNECT_resp(struct Curl_cfilter *cf,
/* output debug if that is requested */
Curl_debug(data, CURLINFO_HEADER_IN, linep, perline);
if(!data->set.suppress_connect_headers) {
/* send the header to the callback */
int writetype = CLIENTWRITE_HEADER | CLIENTWRITE_CONNECT |
(ts->headerlines == 1 ? CLIENTWRITE_STATUS : 0);
result = Curl_client_write(data, writetype, linep, perline);
if(result)
return result;
}
/* send the header to the callback */
writetype = CLIENTWRITE_HEADER | CLIENTWRITE_CONNECT |
(ts->headerlines == 1 ? CLIENTWRITE_STATUS : 0);
result = Curl_client_write(data, writetype, linep, perline);
if(result)
return result;
result = Curl_bump_headersize(data, perline, TRUE);
if(result)
@@ -502,6 +499,7 @@ static CURLcode recv_CONNECT_resp(struct Curl_cfilter *cf,
else if(ts->chunked_encoding) {
CHUNKcode r;
CURLcode extra;
size_t consumed = 0;
infof(data, "Ignore chunked response-body");
@@ -516,8 +514,7 @@ static CURLcode recv_CONNECT_resp(struct Curl_cfilter *cf,
/* now parse the chunked piece of data so that we can properly
tell when the stream ends */
r = Curl_httpchunk_read(data, linep + 1, 1, &gotbytes,
&extra);
r = Curl_httpchunk_read(data, linep + 1, 1, &consumed, &extra);
if(r == CHUNKE_STOP) {
/* we're done reading chunks! */
infof(data, "chunk reading DONE");
@@ -1038,31 +1035,29 @@ out:
return result;
}
static int cf_h1_proxy_get_select_socks(struct Curl_cfilter *cf,
static void cf_h1_proxy_adjust_pollset(struct Curl_cfilter *cf,
struct Curl_easy *data,
curl_socket_t *socks)
struct easy_pollset *ps)
{
struct h1_tunnel_state *ts = cf->ctx;
int fds;
fds = cf->next->cft->get_select_socks(cf->next, data, socks);
if(!fds && cf->next->connected && !cf->connected) {
if(!cf->connected) {
/* If we are not connected, but the filter "below" is
* and not waiting on something, we are tunneling. */
socks[0] = Curl_conn_cf_get_socket(cf, data);
curl_socket_t sock = Curl_conn_cf_get_socket(cf, data);
if(ts) {
/* when we've sent a CONNECT to a proxy, we should rather either
wait for the socket to become readable to be able to get the
response headers or if we're still sending the request, wait
for write. */
if(ts->CONNECT.sending == HTTPSEND_REQUEST) {
return GETSOCK_WRITESOCK(0);
}
return GETSOCK_READSOCK(0);
if(ts->CONNECT.sending == HTTPSEND_REQUEST)
Curl_pollset_set_out_only(data, ps, sock);
else
Curl_pollset_set_in_only(data, ps, sock);
}
return GETSOCK_WRITESOCK(0);
else
Curl_pollset_set_out_only(data, ps, sock);
}
return fds;
}
static void cf_h1_proxy_destroy(struct Curl_cfilter *cf,
@@ -1093,7 +1088,7 @@ struct Curl_cftype Curl_cft_h1_proxy = {
cf_h1_proxy_connect,
cf_h1_proxy_close,
Curl_cf_http_proxy_get_host,
cf_h1_proxy_get_select_socks,
cf_h1_proxy_adjust_pollset,
Curl_cf_def_data_pending,
Curl_cf_def_send,
Curl_cf_def_recv,
+26 -39
View File
@@ -688,12 +688,8 @@ static int proxy_h2_on_frame_recv(nghttp2_session *session,
* window and *assume* that we treat this like a WINDOW_UPDATE. Some
* servers send an explicit WINDOW_UPDATE, but not all seem to do that.
* To be safe, we UNHOLD a stream in order not to stall. */
if((data->req.keepon & KEEP_SEND_HOLD) &&
(data->req.keepon & KEEP_SEND)) {
data->req.keepon &= ~KEEP_SEND_HOLD;
if(CURL_WANT_SEND(data)) {
drain_tunnel(cf, data, &ctx->tunnel);
CURL_TRC_CF(data, cf, "[%d] un-holding after SETTINGS",
stream_id);
}
break;
case NGHTTP2_GOAWAY:
@@ -727,12 +723,8 @@ static int proxy_h2_on_frame_recv(nghttp2_session *session,
}
break;
case NGHTTP2_WINDOW_UPDATE:
if((data->req.keepon & KEEP_SEND_HOLD) &&
(data->req.keepon & KEEP_SEND)) {
data->req.keepon &= ~KEEP_SEND_HOLD;
Curl_expire(data, 0, EXPIRE_RUN_NOW);
CURL_TRC_CF(data, cf, "[%d] unpausing after win update",
stream_id);
if(CURL_WANT_SEND(data)) {
drain_tunnel(cf, data, &ctx->tunnel);
}
break;
default:
@@ -909,7 +901,6 @@ static CURLcode proxy_h2_submit(int32_t *pstream_id,
{
struct dynhds h2_headers;
nghttp2_nv *nva = NULL;
unsigned int i;
int32_t stream_id = -1;
size_t nheader;
CURLcode result;
@@ -920,22 +911,12 @@ static CURLcode proxy_h2_submit(int32_t *pstream_id,
if(result)
goto out;
nheader = Curl_dynhds_count(&h2_headers);
nva = malloc(sizeof(nghttp2_nv) * nheader);
nva = Curl_dynhds_to_nva(&h2_headers, &nheader);
if(!nva) {
result = CURLE_OUT_OF_MEMORY;
goto out;
}
for(i = 0; i < nheader; ++i) {
struct dynhds_entry *e = Curl_dynhds_getn(&h2_headers, i);
nva[i].name = (unsigned char *)e->name;
nva[i].namelen = e->namelen;
nva[i].value = (unsigned char *)e->value;
nva[i].valuelen = e->valuelen;
nva[i].flags = NGHTTP2_NV_FLAG_NONE;
}
if(read_callback) {
nghttp2_data_provider data_prd;
@@ -1187,25 +1168,31 @@ static bool cf_h2_proxy_data_pending(struct Curl_cfilter *cf,
return cf->next? cf->next->cft->has_data_pending(cf->next, data) : FALSE;
}
static int cf_h2_proxy_get_select_socks(struct Curl_cfilter *cf,
struct Curl_easy *data,
curl_socket_t *sock)
static void cf_h2_proxy_adjust_pollset(struct Curl_cfilter *cf,
struct Curl_easy *data,
struct easy_pollset *ps)
{
struct cf_h2_proxy_ctx *ctx = cf->ctx;
int bitmap = GETSOCK_BLANK;
struct cf_call_data save;
curl_socket_t sock = Curl_conn_cf_get_socket(cf, data);
bool want_recv, want_send;
CF_DATA_SAVE(save, cf, data);
sock[0] = Curl_conn_cf_get_socket(cf, data);
bitmap |= GETSOCK_READSOCK(0);
Curl_pollset_check(data, ps, sock, &want_recv, &want_send);
if(ctx->h2 && (want_recv || want_send)) {
struct cf_call_data save;
bool c_exhaust, s_exhaust;
/* HTTP/2 layer wants to send data) AND there's a window to send data in */
if(nghttp2_session_want_write(ctx->h2) &&
nghttp2_session_get_remote_window_size(ctx->h2))
bitmap |= GETSOCK_WRITESOCK(0);
CF_DATA_SAVE(save, cf, data);
c_exhaust = !nghttp2_session_get_remote_window_size(ctx->h2);
s_exhaust = ctx->tunnel.stream_id >= 0 &&
!nghttp2_session_get_stream_remote_window_size(
ctx->h2, ctx->tunnel.stream_id);
want_recv = (want_recv || c_exhaust || s_exhaust);
want_send = (!s_exhaust && want_send) ||
(!c_exhaust && nghttp2_session_want_write(ctx->h2));
CF_DATA_RESTORE(cf, save);
return bitmap;
Curl_pollset_set(data, ps, sock, want_recv, want_send);
CF_DATA_RESTORE(cf, save);
}
}
static ssize_t h2_handle_tunnel_close(struct Curl_cfilter *cf,
@@ -1542,7 +1529,7 @@ struct Curl_cftype Curl_cft_h2_proxy = {
cf_h2_proxy_connect,
cf_h2_proxy_close,
Curl_cf_http_proxy_get_host,
cf_h2_proxy_get_select_socks,
cf_h2_proxy_adjust_pollset,
cf_h2_proxy_data_pending,
cf_h2_proxy_send,
cf_h2_proxy_recv,
@@ -1560,7 +1547,7 @@ CURLcode Curl_cf_h2_proxy_insert_after(struct Curl_cfilter *cf,
CURLcode result = CURLE_OUT_OF_MEMORY;
(void)data;
ctx = calloc(sizeof(*ctx), 1);
ctx = calloc(1, sizeof(*ctx));
if(!ctx)
goto out;
+7 -13
View File
@@ -171,23 +171,17 @@ static void cf_haproxy_close(struct Curl_cfilter *cf,
cf->next->cft->do_close(cf->next, data);
}
static int cf_haproxy_get_select_socks(struct Curl_cfilter *cf,
struct Curl_easy *data,
curl_socket_t *socks)
static void cf_haproxy_adjust_pollset(struct Curl_cfilter *cf,
struct Curl_easy *data,
struct easy_pollset *ps)
{
int fds;
fds = cf->next->cft->get_select_socks(cf->next, data, socks);
if(!fds && cf->next->connected && !cf->connected) {
if(cf->next->connected && !cf->connected) {
/* If we are not connected, but the filter "below" is
* and not waiting on something, we are sending. */
socks[0] = Curl_conn_cf_get_socket(cf, data);
return GETSOCK_WRITESOCK(0);
Curl_pollset_set_out_only(data, ps, Curl_conn_cf_get_socket(cf, data));
}
return fds;
}
struct Curl_cftype Curl_cft_haproxy = {
"HAPROXY",
0,
@@ -196,7 +190,7 @@ struct Curl_cftype Curl_cft_haproxy = {
cf_haproxy_connect,
cf_haproxy_close,
Curl_cf_def_get_host,
cf_haproxy_get_select_socks,
cf_haproxy_adjust_pollset,
Curl_cf_def_data_pending,
Curl_cf_def_send,
Curl_cf_def_recv,
@@ -214,7 +208,7 @@ static CURLcode cf_haproxy_create(struct Curl_cfilter **pcf,
CURLcode result;
(void)data;
ctx = calloc(sizeof(*ctx), 1);
ctx = calloc(1, sizeof(*ctx));
if(!ctx) {
result = CURLE_OUT_OF_MEMORY;
goto out;
+16 -36
View File
@@ -188,9 +188,6 @@ static CURLcode baller_connected(struct Curl_cfilter *cf,
#endif
infof(data, "using HTTP/2");
break;
case CURL_HTTP_VERSION_1_1:
infof(data, "using HTTP/1.1");
break;
default:
infof(data, "using HTTP/1.x");
break;
@@ -325,42 +322,25 @@ out:
return result;
}
static int cf_hc_get_select_socks(struct Curl_cfilter *cf,
static void cf_hc_adjust_pollset(struct Curl_cfilter *cf,
struct Curl_easy *data,
curl_socket_t *socks)
struct easy_pollset *ps)
{
struct cf_hc_ctx *ctx = cf->ctx;
size_t i, j, s;
int brc, rc = GETSOCK_BLANK;
curl_socket_t bsocks[MAX_SOCKSPEREASYHANDLE];
struct cf_hc_baller *ballers[2];
if(!cf->connected) {
struct cf_hc_ctx *ctx = cf->ctx;
struct cf_hc_baller *ballers[2];
size_t i;
if(cf->connected)
return cf->next->cft->get_select_socks(cf->next, data, socks);
ballers[0] = &ctx->h3_baller;
ballers[1] = &ctx->h21_baller;
for(i = s = 0; i < sizeof(ballers)/sizeof(ballers[0]); i++) {
struct cf_hc_baller *b = ballers[i];
if(!cf_hc_baller_is_active(b))
continue;
brc = Curl_conn_cf_get_select_socks(b->cf, data, bsocks);
CURL_TRC_CF(data, cf, "get_selected_socks(%s) -> %x", b->name, brc);
if(!brc)
continue;
for(j = 0; j < MAX_SOCKSPEREASYHANDLE && s < MAX_SOCKSPEREASYHANDLE; ++j) {
if((brc & GETSOCK_WRITESOCK(j)) || (brc & GETSOCK_READSOCK(j))) {
socks[s] = bsocks[j];
if(brc & GETSOCK_WRITESOCK(j))
rc |= GETSOCK_WRITESOCK(s);
if(brc & GETSOCK_READSOCK(j))
rc |= GETSOCK_READSOCK(s);
s++;
}
ballers[0] = &ctx->h3_baller;
ballers[1] = &ctx->h21_baller;
for(i = 0; i < sizeof(ballers)/sizeof(ballers[0]); i++) {
struct cf_hc_baller *b = ballers[i];
if(!cf_hc_baller_is_active(b))
continue;
Curl_conn_cf_adjust_pollset(b->cf, data, ps);
}
CURL_TRC_CF(data, cf, "adjust_pollset -> %d socks", ps->num);
}
CURL_TRC_CF(data, cf, "get_selected_socks -> %x", rc);
return rc;
}
static bool cf_hc_data_pending(struct Curl_cfilter *cf,
@@ -455,7 +435,7 @@ struct Curl_cftype Curl_cft_http_connect = {
cf_hc_connect,
cf_hc_close,
Curl_cf_def_get_host,
cf_hc_get_select_socks,
cf_hc_adjust_pollset,
cf_hc_data_pending,
Curl_cf_def_send,
Curl_cf_def_recv,
@@ -475,7 +455,7 @@ static CURLcode cf_hc_create(struct Curl_cfilter **pcf,
CURLcode result = CURLE_OK;
(void)data;
ctx = calloc(sizeof(*ctx), 1);
ctx = calloc(1, sizeof(*ctx));
if(!ctx) {
result = CURLE_OUT_OF_MEMORY;
goto out;
+39 -54
View File
@@ -81,7 +81,7 @@
#include "memdebug.h"
#if defined(ENABLE_IPV6) && defined(IPV6_V6ONLY) && defined(WIN32)
#if defined(ENABLE_IPV6) && defined(IPV6_V6ONLY) && defined(_WIN32)
/* It makes support for IPv4-mapped IPv6 addresses.
* Linux kernel, NetBSD, FreeBSD and Darwin: default is off;
* Windows Vista and later: default is on;
@@ -102,11 +102,7 @@ static void tcpnodelay(struct Curl_easy *data, curl_socket_t sockfd)
#if defined(TCP_NODELAY)
curl_socklen_t onoff = (curl_socklen_t) 1;
int level = IPPROTO_TCP;
#if !defined(CURL_DISABLE_VERBOSE_STRINGS)
char buffer[STRERROR_LEN];
#else
(void) data;
#endif
if(setsockopt(sockfd, level, TCP_NODELAY, (void *)&onoff,
sizeof(onoff)) < 0)
@@ -127,6 +123,7 @@ static void nosigpipe(struct Curl_easy *data,
curl_socket_t sockfd)
{
int onoff = 1;
(void)data;
if(setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, (void *)&onoff,
sizeof(onoff)) < 0) {
#if !defined(CURL_DISABLE_VERBOSE_STRINGS)
@@ -662,7 +659,7 @@ static bool verifyconnect(curl_socket_t sockfd, int *error)
int err = 0;
curl_socklen_t errSize = sizeof(err);
#ifdef WIN32
#ifdef _WIN32
/*
* In October 2003 we effectively nullified this function on Windows due to
* problems with it using all CPU in multi-threaded cases.
@@ -883,34 +880,14 @@ static void cf_socket_close(struct Curl_cfilter *cf, struct Curl_easy *data)
struct cf_socket_ctx *ctx = cf->ctx;
if(ctx && CURL_SOCKET_BAD != ctx->sock) {
if(ctx->active) {
/* We share our socket at cf->conn->sock[cf->sockindex] when active.
* If it is no longer there, someone has stolen (and hopefully
* closed it) and we just forget about it.
*/
if(ctx->sock == cf->conn->sock[cf->sockindex]) {
CURL_TRC_CF(data, cf, "cf_socket_close(%" CURL_FORMAT_SOCKET_T
", active)", ctx->sock);
socket_close(data, cf->conn, !ctx->accepted, ctx->sock);
cf->conn->sock[cf->sockindex] = CURL_SOCKET_BAD;
}
else {
CURL_TRC_CF(data, cf, "cf_socket_close(%" CURL_FORMAT_SOCKET_T
") no longer at conn->sock[], discarding", ctx->sock);
/* TODO: we do not want this to happen. Need to check which
* code is messing with conn->sock[cf->sockindex] */
}
ctx->sock = CURL_SOCKET_BAD;
if(cf->sockindex == FIRSTSOCKET)
cf->conn->remote_addr = NULL;
}
else {
/* this is our local socket, we did never publish it */
CURL_TRC_CF(data, cf, "cf_socket_close(%" CURL_FORMAT_SOCKET_T
", not active)", ctx->sock);
socket_close(data, cf->conn, !ctx->accepted, ctx->sock);
ctx->sock = CURL_SOCKET_BAD;
}
CURL_TRC_CF(data, cf, "cf_socket_close(%" CURL_FORMAT_SOCKET_T
")", ctx->sock);
if(ctx->sock == cf->conn->sock[cf->sockindex])
cf->conn->sock[cf->sockindex] = CURL_SOCKET_BAD;
socket_close(data, cf->conn, !ctx->accepted, ctx->sock);
ctx->sock = CURL_SOCKET_BAD;
if(ctx->active && cf->sockindex == FIRSTSOCKET)
cf->conn->remote_addr = NULL;
Curl_bufq_reset(&ctx->recvbuf);
ctx->active = FALSE;
ctx->buffer_recv = FALSE;
@@ -1169,6 +1146,7 @@ static CURLcode cf_tcp_connect(struct Curl_cfilter *cf,
*done = FALSE; /* a very negative world view is best */
if(ctx->sock == CURL_SOCKET_BAD) {
int error;
result = cf_socket_open(cf, data);
if(result)
@@ -1181,8 +1159,12 @@ static CURLcode cf_tcp_connect(struct Curl_cfilter *cf,
/* Connect TCP socket */
rc = do_connect(cf, data, cf->conn->bits.tcp_fastopen);
error = SOCKERRNO;
set_local_ip(cf, data);
CURL_TRC_CF(data, cf, "local address %s port %d...",
ctx->l_ip, ctx->l_port);
if(-1 == rc) {
result = socket_connect_result(data, ctx->r_ip, SOCKERRNO);
result = socket_connect_result(data, ctx->r_ip, error);
goto out;
}
}
@@ -1220,13 +1202,14 @@ static CURLcode cf_tcp_connect(struct Curl_cfilter *cf,
out:
if(result) {
if(ctx->error) {
set_local_ip(cf, data);
data->state.os_errno = ctx->error;
SET_SOCKERRNO(ctx->error);
#ifndef CURL_DISABLE_VERBOSE_STRINGS
{
char buffer[STRERROR_LEN];
infof(data, "connect to %s port %u failed: %s",
ctx->r_ip, ctx->r_port,
infof(data, "connect to %s port %u from %s port %d failed: %s",
ctx->r_ip, ctx->r_port, ctx->l_ip, ctx->l_port,
Curl_strerror(ctx->error, buffer, sizeof(buffer)));
}
#endif
@@ -1252,20 +1235,19 @@ static void cf_socket_get_host(struct Curl_cfilter *cf,
*pport = cf->conn->port;
}
static int cf_socket_get_select_socks(struct Curl_cfilter *cf,
static void cf_socket_adjust_pollset(struct Curl_cfilter *cf,
struct Curl_easy *data,
curl_socket_t *socks)
struct easy_pollset *ps)
{
struct cf_socket_ctx *ctx = cf->ctx;
int rc = GETSOCK_BLANK;
(void)data;
if(!cf->connected && ctx->sock != CURL_SOCKET_BAD) {
socks[0] = ctx->sock;
rc |= GETSOCK_WRITESOCK(0);
if(ctx->sock != CURL_SOCKET_BAD) {
if(!cf->connected)
Curl_pollset_set_out_only(data, ps, ctx->sock);
else
Curl_pollset_add_in(data, ps, ctx->sock);
CURL_TRC_CF(data, cf, "adjust_pollset -> %d socks", ps->num);
}
return rc;
}
static bool cf_socket_data_pending(struct Curl_cfilter *cf,
@@ -1518,6 +1500,9 @@ static CURLcode cf_socket_cntrl(struct Curl_cfilter *cf,
case CF_CTRL_DATA_SETUP:
Curl_persistconninfo(data, cf->conn, ctx->l_ip, ctx->l_port);
break;
case CF_CTRL_FORGET_SOCKET:
ctx->sock = CURL_SOCKET_BAD;
break;
}
return CURLE_OK;
}
@@ -1612,7 +1597,7 @@ struct Curl_cftype Curl_cft_tcp = {
cf_tcp_connect,
cf_socket_close,
cf_socket_get_host,
cf_socket_get_select_socks,
cf_socket_adjust_pollset,
cf_socket_data_pending,
cf_socket_send,
cf_socket_recv,
@@ -1635,7 +1620,7 @@ CURLcode Curl_cf_tcp_create(struct Curl_cfilter **pcf,
(void)data;
(void)conn;
DEBUGASSERT(transport == TRNSPRT_TCP);
ctx = calloc(sizeof(*ctx), 1);
ctx = calloc(1, sizeof(*ctx));
if(!ctx) {
result = CURLE_OUT_OF_MEMORY;
goto out;
@@ -1742,7 +1727,7 @@ struct Curl_cftype Curl_cft_udp = {
cf_udp_connect,
cf_socket_close,
cf_socket_get_host,
cf_socket_get_select_socks,
cf_socket_adjust_pollset,
cf_socket_data_pending,
cf_socket_send,
cf_socket_recv,
@@ -1765,7 +1750,7 @@ CURLcode Curl_cf_udp_create(struct Curl_cfilter **pcf,
(void)data;
(void)conn;
DEBUGASSERT(transport == TRNSPRT_UDP || transport == TRNSPRT_QUIC);
ctx = calloc(sizeof(*ctx), 1);
ctx = calloc(1, sizeof(*ctx));
if(!ctx) {
result = CURLE_OUT_OF_MEMORY;
goto out;
@@ -1793,7 +1778,7 @@ struct Curl_cftype Curl_cft_unix = {
cf_tcp_connect,
cf_socket_close,
cf_socket_get_host,
cf_socket_get_select_socks,
cf_socket_adjust_pollset,
cf_socket_data_pending,
cf_socket_send,
cf_socket_recv,
@@ -1816,7 +1801,7 @@ CURLcode Curl_cf_unix_create(struct Curl_cfilter **pcf,
(void)data;
(void)conn;
DEBUGASSERT(transport == TRNSPRT_UNIX);
ctx = calloc(sizeof(*ctx), 1);
ctx = calloc(1, sizeof(*ctx));
if(!ctx) {
result = CURLE_OUT_OF_MEMORY;
goto out;
@@ -1857,7 +1842,7 @@ struct Curl_cftype Curl_cft_tcp_accept = {
cf_tcp_accept_connect,
cf_socket_close,
cf_socket_get_host, /* TODO: not accurate */
cf_socket_get_select_socks,
cf_socket_adjust_pollset,
cf_socket_data_pending,
cf_socket_send,
cf_socket_recv,
@@ -1879,7 +1864,7 @@ CURLcode Curl_conn_tcp_listen_set(struct Curl_easy *data,
Curl_conn_cf_discard_all(data, conn, sockindex);
DEBUGASSERT(conn->sock[sockindex] == CURL_SOCKET_BAD);
ctx = calloc(sizeof(*ctx), 1);
ctx = calloc(1, sizeof(*ctx));
if(!ctx) {
result = CURLE_OUT_OF_MEMORY;
goto out;
+179 -25
View File
@@ -33,6 +33,7 @@
#include "sockaddr.h" /* required for Curl_sockaddr_storage */
#include "multiif.h"
#include "progress.h"
#include "select.h"
#include "warnless.h"
/* The last 3 #include files should be in this order */
@@ -70,12 +71,14 @@ void Curl_cf_def_get_host(struct Curl_cfilter *cf, struct Curl_easy *data,
}
}
int Curl_cf_def_get_select_socks(struct Curl_cfilter *cf,
void Curl_cf_def_adjust_pollset(struct Curl_cfilter *cf,
struct Curl_easy *data,
curl_socket_t *socks)
struct easy_pollset *ps)
{
return cf->next?
cf->next->cft->get_select_socks(cf->next, data, socks) : 0;
/* NOP */
(void)cf;
(void)data;
(void)ps;
}
bool Curl_cf_def_data_pending(struct Curl_cfilter *cf,
@@ -212,7 +215,7 @@ CURLcode Curl_cf_create(struct Curl_cfilter **pcf,
CURLcode result = CURLE_OUT_OF_MEMORY;
DEBUGASSERT(cft);
cf = calloc(sizeof(*cf), 1);
cf = calloc(1, sizeof(*cf));
if(!cf)
goto out;
@@ -303,15 +306,6 @@ void Curl_conn_cf_close(struct Curl_cfilter *cf, struct Curl_easy *data)
cf->cft->do_close(cf, data);
}
int Curl_conn_cf_get_select_socks(struct Curl_cfilter *cf,
struct Curl_easy *data,
curl_socket_t *socks)
{
if(cf)
return cf->cft->get_select_socks(cf, data, socks);
return 0;
}
ssize_t Curl_conn_cf_send(struct Curl_cfilter *cf, struct Curl_easy *data,
const void *buf, size_t len, CURLcode *err)
{
@@ -433,22 +427,31 @@ bool Curl_conn_data_pending(struct Curl_easy *data, int sockindex)
return FALSE;
}
int Curl_conn_get_select_socks(struct Curl_easy *data, int sockindex,
curl_socket_t *socks)
void Curl_conn_cf_adjust_pollset(struct Curl_cfilter *cf,
struct Curl_easy *data,
struct easy_pollset *ps)
{
struct Curl_cfilter *cf;
/* Get the lowest not-connected filter, if there are any */
while(cf && !cf->connected && cf->next && !cf->next->connected)
cf = cf->next;
/* From there on, give all filters a chance to adjust the pollset.
* Lower filters are called later, so they may override */
while(cf) {
cf->cft->adjust_pollset(cf, data, ps);
cf = cf->next;
}
}
void Curl_conn_adjust_pollset(struct Curl_easy *data,
struct easy_pollset *ps)
{
int i;
DEBUGASSERT(data);
DEBUGASSERT(data->conn);
cf = data->conn->cfilter[sockindex];
/* if the next one is not yet connected, that's the one we want */
while(cf && cf->next && !cf->next->connected)
cf = cf->next;
if(cf) {
return cf->cft->get_select_socks(cf, data, socks);
for(i = 0; i < 2; ++i) {
Curl_conn_cf_adjust_pollset(data->conn->cfilter[i], data, ps);
}
return GETSOCK_BLANK;
}
void Curl_conn_get_host(struct Curl_easy *data, int sockindex,
@@ -524,6 +527,18 @@ curl_socket_t Curl_conn_get_socket(struct Curl_easy *data, int sockindex)
return data->conn? data->conn->sock[sockindex] : CURL_SOCKET_BAD;
}
void Curl_conn_forget_socket(struct Curl_easy *data, int sockindex)
{
if(data->conn) {
struct Curl_cfilter *cf = data->conn->cfilter[sockindex];
if(cf)
(void)Curl_conn_cf_cntrl(cf, data, TRUE,
CF_CTRL_FORGET_SOCKET, 0, NULL);
fake_sclose(data->conn->sock[sockindex]);
data->conn->sock[sockindex] = CURL_SOCKET_BAD;
}
}
static CURLcode cf_cntrl_all(struct connectdata *conn,
struct Curl_easy *data,
bool ignore_result,
@@ -646,3 +661,142 @@ size_t Curl_conn_get_max_concurrent(struct Curl_easy *data,
&n, NULL) : CURLE_UNKNOWN_OPTION;
return (result || n <= 0)? 1 : (size_t)n;
}
void Curl_pollset_reset(struct Curl_easy *data,
struct easy_pollset *ps)
{
size_t i;
(void)data;
memset(ps, 0, sizeof(*ps));
for(i = 0; i< MAX_SOCKSPEREASYHANDLE; i++)
ps->sockets[i] = CURL_SOCKET_BAD;
}
/**
*
*/
void Curl_pollset_change(struct Curl_easy *data,
struct easy_pollset *ps, curl_socket_t sock,
int add_flags, int remove_flags)
{
unsigned int i;
(void)data;
DEBUGASSERT(VALID_SOCK(sock));
if(!VALID_SOCK(sock))
return;
DEBUGASSERT(add_flags <= (CURL_POLL_IN|CURL_POLL_OUT));
DEBUGASSERT(remove_flags <= (CURL_POLL_IN|CURL_POLL_OUT));
DEBUGASSERT((add_flags&remove_flags) == 0); /* no overlap */
for(i = 0; i < ps->num; ++i) {
if(ps->sockets[i] == sock) {
ps->actions[i] &= (unsigned char)(~remove_flags);
ps->actions[i] |= (unsigned char)add_flags;
/* all gone? remove socket */
if(!ps->actions[i]) {
if((i + 1) < ps->num) {
memmove(&ps->sockets[i], &ps->sockets[i + 1],
(ps->num - (i + 1)) * sizeof(ps->sockets[0]));
memmove(&ps->actions[i], &ps->actions[i + 1],
(ps->num - (i + 1)) * sizeof(ps->actions[0]));
}
--ps->num;
}
return;
}
}
/* not present */
if(add_flags) {
/* Having more SOCKETS per easy handle than what is defined
* is a programming error. This indicates that we need
* to raise this limit, making easy_pollset larger.
* Since we use this in tight loops, we do not want to make
* the pollset dynamic unnecessarily.
* The current maximum in practise is HTTP/3 eyeballing where
* we have up to 4 sockets involved in connection setup.
*/
DEBUGASSERT(i < MAX_SOCKSPEREASYHANDLE);
if(i < MAX_SOCKSPEREASYHANDLE) {
ps->sockets[i] = sock;
ps->actions[i] = (unsigned char)add_flags;
ps->num = i + 1;
}
}
}
void Curl_pollset_set(struct Curl_easy *data,
struct easy_pollset *ps, curl_socket_t sock,
bool do_in, bool do_out)
{
Curl_pollset_change(data, ps, sock,
(do_in?CURL_POLL_IN:0)|(do_out?CURL_POLL_OUT:0),
(!do_in?CURL_POLL_IN:0)|(!do_out?CURL_POLL_OUT:0));
}
static void ps_add(struct Curl_easy *data, struct easy_pollset *ps,
int bitmap, curl_socket_t *socks)
{
if(bitmap) {
int i;
for(i = 0; i < MAX_SOCKSPEREASYHANDLE; ++i) {
if(!(bitmap & GETSOCK_MASK_RW(i)) || !VALID_SOCK((socks[i]))) {
break;
}
if(bitmap & GETSOCK_READSOCK(i)) {
if(bitmap & GETSOCK_WRITESOCK(i))
Curl_pollset_add_inout(data, ps, socks[i]);
else
/* is READ, since we checked MASK_RW above */
Curl_pollset_add_in(data, ps, socks[i]);
}
else
Curl_pollset_add_out(data, ps, socks[i]);
}
}
}
void Curl_pollset_add_socks(struct Curl_easy *data,
struct easy_pollset *ps,
int (*get_socks_cb)(struct Curl_easy *data,
struct connectdata *conn,
curl_socket_t *socks))
{
curl_socket_t socks[MAX_SOCKSPEREASYHANDLE];
int bitmap;
DEBUGASSERT(data->conn);
bitmap = get_socks_cb(data, data->conn, socks);
ps_add(data, ps, bitmap, socks);
}
void Curl_pollset_add_socks2(struct Curl_easy *data,
struct easy_pollset *ps,
int (*get_socks_cb)(struct Curl_easy *data,
curl_socket_t *socks))
{
curl_socket_t socks[MAX_SOCKSPEREASYHANDLE];
int bitmap;
bitmap = get_socks_cb(data, socks);
ps_add(data, ps, bitmap, socks);
}
void Curl_pollset_check(struct Curl_easy *data,
struct easy_pollset *ps, curl_socket_t sock,
bool *pwant_read, bool *pwant_write)
{
unsigned int i;
(void)data;
DEBUGASSERT(VALID_SOCK(sock));
for(i = 0; i < ps->num; ++i) {
if(ps->sockets[i] == sock) {
*pwant_read = !!(ps->actions[i] & CURL_POLL_IN);
*pwant_write = !!(ps->actions[i] & CURL_POLL_OUT);
return;
}
}
*pwant_read = *pwant_write = FALSE;
}
+95 -18
View File
@@ -60,14 +60,34 @@ typedef void Curl_cft_get_host(struct Curl_cfilter *cf,
const char **pdisplay_host,
int *pport);
/* Filters may return sockets and fdset flags they are waiting for.
* The passes array has room for up to MAX_SOCKSPEREASYHANDLE sockets.
* @return read/write fdset for index in socks
* or GETSOCK_BLANK when nothing to wait on
struct easy_pollset;
/* Passing in an easy_pollset for monitoring of sockets, let
* filters add or remove sockets actions (CURL_POLL_OUT, CURL_POLL_IN).
* This may add a socket or, in case no actions remain, remove
* a socket from the set.
*
* Filter implementations need to call filters "below" *after* they have
* made their adjustments. This allows lower filters to override "upper"
* actions. If a "lower" filter is unable to write, it needs to be able
* to disallow POLL_OUT.
*
* A filter without own restrictions/preferences should not modify
* the pollset. Filters, whose filter "below" is not connected, should
* also do no adjustments.
*
* Examples: a TLS handshake, while ongoing, might remove POLL_IN
* when it needs to write, or vice versa. A HTTP/2 filter might remove
* POLL_OUT when a stream window is exhausted and a WINDOW_UPDATE needs
* to be received first and add instead POLL_IN.
*
* @param cf the filter to ask
* @param data the easy handle the pollset is about
* @param ps the pollset (inout) for the easy handle
*/
typedef int Curl_cft_get_select_socks(struct Curl_cfilter *cf,
struct Curl_easy *data,
curl_socket_t *socks);
typedef void Curl_cft_adjust_pollset(struct Curl_cfilter *cf,
struct Curl_easy *data,
struct easy_pollset *ps);
typedef bool Curl_cft_data_pending(struct Curl_cfilter *cf,
const struct Curl_easy *data);
@@ -110,6 +130,7 @@ typedef CURLcode Curl_cft_conn_keep_alive(struct Curl_cfilter *cf,
#define CF_CTRL_DATA_DONE_SEND 8 /* 0 NULL ignored */
/* update conn info at connection and data */
#define CF_CTRL_CONN_INFO_UPDATE (256+0) /* 0 NULL ignored */
#define CF_CTRL_FORGET_SOCKET (256+1) /* 0 NULL ignored */
/**
* Handle event/control for the filter.
@@ -171,7 +192,7 @@ struct Curl_cftype {
Curl_cft_connect *do_connect; /* establish connection */
Curl_cft_close *do_close; /* close conn */
Curl_cft_get_host *get_host; /* host filter talks to */
Curl_cft_get_select_socks *get_select_socks;/* sockets to select on */
Curl_cft_adjust_pollset *adjust_pollset; /* adjust transfer poll set */
Curl_cft_data_pending *has_data_pending;/* conn has data pending */
Curl_cft_send *do_send; /* send data */
Curl_cft_recv *do_recv; /* receive data */
@@ -200,9 +221,9 @@ void Curl_cf_def_destroy_this(struct Curl_cfilter *cf,
void Curl_cf_def_get_host(struct Curl_cfilter *cf, struct Curl_easy *data,
const char **phost, const char **pdisplay_host,
int *pport);
int Curl_cf_def_get_select_socks(struct Curl_cfilter *cf,
struct Curl_easy *data,
curl_socket_t *socks);
void Curl_cf_def_adjust_pollset(struct Curl_cfilter *cf,
struct Curl_easy *data,
struct easy_pollset *ps);
bool Curl_cf_def_data_pending(struct Curl_cfilter *cf,
const struct Curl_easy *data);
ssize_t Curl_cf_def_send(struct Curl_cfilter *cf, struct Curl_easy *data,
@@ -279,9 +300,6 @@ CURLcode Curl_conn_cf_connect(struct Curl_cfilter *cf,
struct Curl_easy *data,
bool blocking, bool *done);
void Curl_conn_cf_close(struct Curl_cfilter *cf, struct Curl_easy *data);
int Curl_conn_cf_get_select_socks(struct Curl_cfilter *cf,
struct Curl_easy *data,
curl_socket_t *socks);
ssize_t Curl_conn_cf_send(struct Curl_cfilter *cf, struct Curl_easy *data,
const void *buf, size_t len, CURLcode *err);
ssize_t Curl_conn_cf_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
@@ -364,11 +382,22 @@ bool Curl_conn_data_pending(struct Curl_easy *data,
curl_socket_t Curl_conn_get_socket(struct Curl_easy *data, int sockindex);
/**
* Get any select fd flags and the socket filters at chain `sockindex`
* at connection `conn` might be waiting for.
* Tell filters to forget about the socket at sockindex.
*/
int Curl_conn_get_select_socks(struct Curl_easy *data, int sockindex,
curl_socket_t *socks);
void Curl_conn_forget_socket(struct Curl_easy *data, int sockindex);
/**
* Adjust the pollset for the filter chain startgin at `cf`.
*/
void Curl_conn_cf_adjust_pollset(struct Curl_cfilter *cf,
struct Curl_easy *data,
struct easy_pollset *ps);
/**
* Adjust pollset from filters installed at transfer's connection.
*/
void Curl_conn_adjust_pollset(struct Curl_easy *data,
struct easy_pollset *ps);
/**
* Receive data through the filter chain at `sockindex` for connection
@@ -468,6 +497,54 @@ size_t Curl_conn_get_max_concurrent(struct Curl_easy *data,
int sockindex);
void Curl_pollset_reset(struct Curl_easy *data,
struct easy_pollset *ps);
/* Change the poll flags (CURL_POLL_IN/CURL_POLL_OUT) to the poll set for
* socket `sock`. If the socket is not already part of the poll set, it
* will be added.
* If the socket is present and all poll flags are cleared, it will be removed.
*/
void Curl_pollset_change(struct Curl_easy *data,
struct easy_pollset *ps, curl_socket_t sock,
int add_flags, int remove_flags);
void Curl_pollset_set(struct Curl_easy *data,
struct easy_pollset *ps, curl_socket_t sock,
bool do_in, bool do_out);
#define Curl_pollset_add_in(data, ps, sock) \
Curl_pollset_change((data), (ps), (sock), CURL_POLL_IN, 0)
#define Curl_pollset_add_out(data, ps, sock) \
Curl_pollset_change((data), (ps), (sock), CURL_POLL_OUT, 0)
#define Curl_pollset_add_inout(data, ps, sock) \
Curl_pollset_change((data), (ps), (sock), \
CURL_POLL_IN|CURL_POLL_OUT, 0)
#define Curl_pollset_set_in_only(data, ps, sock) \
Curl_pollset_change((data), (ps), (sock), \
CURL_POLL_IN, CURL_POLL_OUT)
#define Curl_pollset_set_out_only(data, ps, sock) \
Curl_pollset_change((data), (ps), (sock), \
CURL_POLL_OUT, CURL_POLL_IN)
void Curl_pollset_add_socks(struct Curl_easy *data,
struct easy_pollset *ps,
int (*get_socks_cb)(struct Curl_easy *data,
struct connectdata *conn,
curl_socket_t *socks));
void Curl_pollset_add_socks2(struct Curl_easy *data,
struct easy_pollset *ps,
int (*get_socks_cb)(struct Curl_easy *data,
curl_socket_t *socks));
/**
* Check if the pollset, as is, wants to read and/or write regarding
* the given socket.
*/
void Curl_pollset_check(struct Curl_easy *data,
struct easy_pollset *ps, curl_socket_t sock,
bool *pwant_read, bool *pwant_write);
/**
* Types and macros used to keep the current easy handle in filter calls,
* allowing for nested invocations. See #10336.
+15 -10
View File
@@ -107,7 +107,7 @@ int Curl_conncache_init(struct conncache *connc, int size)
connc->closure_handle = curl_easy_init();
if(!connc->closure_handle)
return 1; /* bad */
connc->closure_handle->internal = true;
connc->closure_handle->state.internal = true;
Curl_hash_init(&connc->hash, size, Curl_hash_str,
Curl_str_key_compare, free_bundle_hash_entry);
@@ -243,7 +243,7 @@ CURLcode Curl_conncache_add_conn(struct Curl_easy *data)
conn->connection_id = connc->next_connection_id++;
connc->num_conn++;
DEBUGF(infof(data, "Added connection %ld. "
DEBUGF(infof(data, "Added connection %" CURL_FORMAT_CURL_OFF_T ". "
"The cache now contains %zu members",
conn->connection_id, connc->num_conn));
@@ -379,21 +379,26 @@ conncache_find_first_connection(struct conncache *connc)
bool Curl_conncache_return_conn(struct Curl_easy *data,
struct connectdata *conn)
{
/* data->multi->maxconnects can be negative, deal with it. */
size_t maxconnects =
(data->multi->maxconnects < 0) ? data->multi->num_easy * 4:
data->multi->maxconnects;
unsigned int maxconnects = !data->multi->maxconnects ?
data->multi->num_easy * 4: data->multi->maxconnects;
struct connectdata *conn_candidate = NULL;
conn->lastused = Curl_now(); /* it was used up until now */
if(maxconnects > 0 &&
Curl_conncache_size(data) > maxconnects) {
if(maxconnects && Curl_conncache_size(data) > maxconnects) {
infof(data, "Connection cache is full, closing the oldest one");
conn_candidate = Curl_conncache_extract_oldest(data);
if(conn_candidate) {
/* the winner gets the honour of being disconnected */
Curl_disconnect(data, conn_candidate, /* dead_connection */ FALSE);
/* Use the closure handle for this disconnect so that anything that
happens during the disconnect is not stored and associated with the
'data' handle which already just finished a transfer and it is
important that details from this (unrelated) disconnect does not
taint meta-data in the data handle. */
struct conncache *connc = data->state.conn_cache;
connc->closure_handle->state.buffer = data->state.buffer;
connc->closure_handle->set.buffer_size = data->set.buffer_size;
Curl_disconnect(connc->closure_handle, conn_candidate,
/* dead_connection */ FALSE);
}
}
+51 -44
View File
@@ -84,6 +84,9 @@
#include "curl_memory.h"
#include "memdebug.h"
#ifndef ARRAYSIZE
#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0]))
#endif
/*
* Curl_timeleft() returns the amount of milliseconds left allowed for the
@@ -348,6 +351,7 @@ void Curl_conncontrol(struct connectdata *conn,
*/
struct eyeballer {
const char *name;
const struct Curl_addrinfo *first; /* complete address list, not owned */
const struct Curl_addrinfo *addr; /* List of addresses to try, not owned */
int ai_family; /* matching address family only */
cf_ip_connect_create *cf_create; /* for creating cf */
@@ -359,9 +363,12 @@ struct eyeballer {
expire_id timeout_id; /* ID for Curl_expire() */
CURLcode result;
int error;
BIT(rewinded); /* if we rewinded the addr list */
BIT(has_started); /* attempts have started */
BIT(is_done); /* out of addresses/time */
BIT(connected); /* cf has connected */
BIT(inconclusive); /* connect was not a hard failure, we
* might talk to a restarting server */
};
@@ -408,7 +415,7 @@ static CURLcode eyeballer_new(struct eyeballer **pballer,
#endif
"ip"));
baller->cf_create = cf_create;
baller->addr = addr;
baller->first = baller->addr = addr;
baller->ai_family = ai_family;
baller->primary = primary;
baller->delay_ms = delay_ms;
@@ -438,6 +445,13 @@ static void baller_free(struct eyeballer *baller,
}
}
static void baller_rewind(struct eyeballer *baller)
{
baller->rewinded = TRUE;
baller->addr = baller->first;
baller->inconclusive = FALSE;
}
static void baller_next_addr(struct eyeballer *baller)
{
baller->addr = addr_next_match(baller->addr, baller->ai_family);
@@ -528,6 +542,10 @@ static CURLcode baller_start_next(struct Curl_cfilter *cf,
{
if(cf->sockindex == FIRSTSOCKET) {
baller_next_addr(baller);
/* If we get inconclusive answers from the server(s), we make
* a second iteration over the address list */
if(!baller->addr && baller->inconclusive && !baller->rewinded)
baller_rewind(baller);
baller_start(cf, data, baller, timeoutms);
}
else {
@@ -566,6 +584,8 @@ static CURLcode baller_connect(struct Curl_cfilter *cf,
baller->result = CURLE_OPERATION_TIMEDOUT;
}
}
else if(baller->result == CURLE_WEIRD_SERVER_REPLY)
baller->inconclusive = TRUE;
}
return baller->result;
}
@@ -595,7 +615,7 @@ evaluate:
*connected = FALSE; /* a very negative world view is best */
now = Curl_now();
ongoing = not_started = 0;
for(i = 0; i < sizeof(ctx->baller)/sizeof(ctx->baller[0]); i++) {
for(i = 0; i < ARRAYSIZE(ctx->baller); i++) {
struct eyeballer *baller = ctx->baller[i];
if(!baller || baller->is_done)
@@ -656,7 +676,7 @@ evaluate:
if(not_started > 0) {
int added = 0;
for(i = 0; i < sizeof(ctx->baller)/sizeof(ctx->baller[0]); i++) {
for(i = 0; i < ARRAYSIZE(ctx->baller); i++) {
struct eyeballer *baller = ctx->baller[i];
if(!baller || baller->has_started)
@@ -691,13 +711,13 @@ evaluate:
/* all ballers have failed to connect. */
CURL_TRC_CF(data, cf, "all eyeballers failed");
result = CURLE_COULDNT_CONNECT;
for(i = 0; i < sizeof(ctx->baller)/sizeof(ctx->baller[0]); i++) {
for(i = 0; i < ARRAYSIZE(ctx->baller); i++) {
struct eyeballer *baller = ctx->baller[i];
if(!baller)
continue;
CURL_TRC_CF(data, cf, "%s assess started=%d, result=%d",
baller?baller->name:NULL,
baller?baller->has_started:0,
baller?baller->result:0);
if(baller && baller->has_started && baller->result) {
baller->name, baller->has_started, baller->result);
if(baller->has_started && baller->result) {
result = baller->result;
break;
}
@@ -838,7 +858,7 @@ static void cf_he_ctx_clear(struct Curl_cfilter *cf, struct Curl_easy *data)
DEBUGASSERT(ctx);
DEBUGASSERT(data);
for(i = 0; i < sizeof(ctx->baller)/sizeof(ctx->baller[0]); i++) {
for(i = 0; i < ARRAYSIZE(ctx->baller); i++) {
baller_free(ctx->baller[i], data);
ctx->baller[i] = NULL;
}
@@ -846,35 +866,22 @@ static void cf_he_ctx_clear(struct Curl_cfilter *cf, struct Curl_easy *data)
ctx->winner = NULL;
}
static int cf_he_get_select_socks(struct Curl_cfilter *cf,
static void cf_he_adjust_pollset(struct Curl_cfilter *cf,
struct Curl_easy *data,
curl_socket_t *socks)
struct easy_pollset *ps)
{
struct cf_he_ctx *ctx = cf->ctx;
size_t i, s;
int wrc, rc = GETSOCK_BLANK;
curl_socket_t wsocks[MAX_SOCKSPEREASYHANDLE];
size_t i;
if(cf->connected)
return cf->next->cft->get_select_socks(cf->next, data, socks);
for(i = s = 0; i < sizeof(ctx->baller)/sizeof(ctx->baller[0]); i++) {
struct eyeballer *baller = ctx->baller[i];
if(!baller || !baller->cf)
continue;
wrc = Curl_conn_cf_get_select_socks(baller->cf, data, wsocks);
if(wrc) {
/* TODO: we assume we get at most one socket back */
socks[s] = wsocks[0];
if(wrc & GETSOCK_WRITESOCK(0))
rc |= GETSOCK_WRITESOCK(s);
if(wrc & GETSOCK_READSOCK(0))
rc |= GETSOCK_READSOCK(s);
s++;
if(!cf->connected) {
for(i = 0; i < ARRAYSIZE(ctx->baller); i++) {
struct eyeballer *baller = ctx->baller[i];
if(!baller || !baller->cf)
continue;
Curl_conn_cf_adjust_pollset(baller->cf, data, ps);
}
CURL_TRC_CF(data, cf, "adjust_pollset -> %d socks", ps->num);
}
return rc;
}
static CURLcode cf_he_connect(struct Curl_cfilter *cf,
@@ -956,7 +963,7 @@ static bool cf_he_data_pending(struct Curl_cfilter *cf,
if(cf->connected)
return cf->next->cft->has_data_pending(cf->next, data);
for(i = 0; i < sizeof(ctx->baller)/sizeof(ctx->baller[0]); i++) {
for(i = 0; i < ARRAYSIZE(ctx->baller); i++) {
struct eyeballer *baller = ctx->baller[i];
if(!baller || !baller->cf)
continue;
@@ -975,7 +982,7 @@ static struct curltime get_max_baller_time(struct Curl_cfilter *cf,
size_t i;
memset(&tmax, 0, sizeof(tmax));
for(i = 0; i < sizeof(ctx->baller)/sizeof(ctx->baller[0]); i++) {
for(i = 0; i < ARRAYSIZE(ctx->baller); i++) {
struct eyeballer *baller = ctx->baller[i];
memset(&t, 0, sizeof(t));
@@ -1000,7 +1007,7 @@ static CURLcode cf_he_query(struct Curl_cfilter *cf,
int reply_ms = -1;
size_t i;
for(i = 0; i < sizeof(ctx->baller)/sizeof(ctx->baller[0]); i++) {
for(i = 0; i < ARRAYSIZE(ctx->baller); i++) {
struct eyeballer *baller = ctx->baller[i];
int breply_ms;
@@ -1055,7 +1062,7 @@ struct Curl_cftype Curl_cft_happy_eyeballs = {
cf_he_connect,
cf_he_close,
Curl_cf_def_get_host,
cf_he_get_select_socks,
cf_he_adjust_pollset,
cf_he_data_pending,
Curl_cf_def_send,
Curl_cf_def_recv,
@@ -1089,7 +1096,7 @@ cf_happy_eyeballs_create(struct Curl_cfilter **pcf,
(void)data;
(void)conn;
*pcf = NULL;
ctx = calloc(sizeof(*ctx), 1);
ctx = calloc(1, sizeof(*ctx));
if(!ctx) {
result = CURLE_OUT_OF_MEMORY;
goto out;
@@ -1122,13 +1129,13 @@ struct transport_provider transport_providers[] = {
#ifdef ENABLE_QUIC
{ TRNSPRT_QUIC, Curl_cf_quic_create },
#endif
#ifndef CURL_DISABLE_TFTP
{ TRNSPRT_UDP, Curl_cf_udp_create },
{ TRNSPRT_UNIX, Curl_cf_unix_create },
};
#ifndef ARRAYSIZE
#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0]))
#endif
#ifdef USE_UNIX_SOCKETS
{ TRNSPRT_UNIX, Curl_cf_unix_create },
#endif
};
static cf_ip_connect_create *get_cf_create(int transport)
{
@@ -1319,7 +1326,7 @@ struct Curl_cftype Curl_cft_setup = {
cf_setup_connect,
cf_setup_close,
Curl_cf_def_get_host,
Curl_cf_def_get_select_socks,
Curl_cf_def_adjust_pollset,
Curl_cf_def_data_pending,
Curl_cf_def_send,
Curl_cf_def_recv,
@@ -1340,7 +1347,7 @@ static CURLcode cf_setup_create(struct Curl_cfilter **pcf,
CURLcode result = CURLE_OK;
(void)data;
ctx = calloc(sizeof(*ctx), 1);
ctx = calloc(1, sizeof(*ctx));
if(!ctx) {
result = CURLE_OUT_OF_MEMORY;
goto out;
+134 -147
View File
@@ -63,6 +63,9 @@
#ifndef CURL_DISABLE_HTTP
/* allow no more than 5 "chained" compression steps */
#define MAX_ENCODE_STACK 5
#define DSIZ CURL_MAX_WRITE_SIZE /* buffer size for decompressed data */
@@ -95,7 +98,7 @@ typedef enum {
/* Deflate and gzip writer. */
struct zlib_writer {
struct contenc_writer super;
struct Curl_cwriter super;
zlibInitState zlib_init; /* zlib init state */
uInt trailerlen; /* Remaining trailer byte count. */
z_stream z; /* State structure for zlib. */
@@ -171,7 +174,7 @@ static CURLcode process_trailer(struct Curl_easy *data,
}
static CURLcode inflate_stream(struct Curl_easy *data,
struct contenc_writer *writer,
struct Curl_cwriter *writer, int type,
zlibInitState started)
{
struct zlib_writer *zp = (struct zlib_writer *) writer;
@@ -196,7 +199,7 @@ static CURLcode inflate_stream(struct Curl_easy *data,
return exit_zlib(data, z, &zp->zlib_init, CURLE_OUT_OF_MEMORY);
/* because the buffer size is fixed, iteratively decompress and transfer to
the client via downstream_write function. */
the client via next_write function. */
while(!done) {
int status; /* zlib status */
done = TRUE;
@@ -217,7 +220,7 @@ static CURLcode inflate_stream(struct Curl_easy *data,
if(z->avail_out != DSIZ) {
if(status == Z_OK || status == Z_STREAM_END) {
zp->zlib_init = started; /* Data started. */
result = Curl_unencode_write(data, writer->downstream, decomp,
result = Curl_cwriter_write(data, writer->next, type, decomp,
DSIZ - z->avail_out);
if(result) {
exit_zlib(data, z, &zp->zlib_init, result);
@@ -274,8 +277,8 @@ static CURLcode inflate_stream(struct Curl_easy *data,
/* Deflate handler. */
static CURLcode deflate_init_writer(struct Curl_easy *data,
struct contenc_writer *writer)
static CURLcode deflate_do_init(struct Curl_easy *data,
struct Curl_cwriter *writer)
{
struct zlib_writer *zp = (struct zlib_writer *) writer;
z_stream *z = &zp->z; /* zlib state structure */
@@ -290,13 +293,16 @@ static CURLcode deflate_init_writer(struct Curl_easy *data,
return CURLE_OK;
}
static CURLcode deflate_unencode_write(struct Curl_easy *data,
struct contenc_writer *writer,
static CURLcode deflate_do_write(struct Curl_easy *data,
struct Curl_cwriter *writer, int type,
const char *buf, size_t nbytes)
{
struct zlib_writer *zp = (struct zlib_writer *) writer;
z_stream *z = &zp->z; /* zlib state structure */
if(!(type & CLIENTWRITE_BODY))
return Curl_cwriter_write(data, writer->next, type, buf, nbytes);
/* Set the compressed input when this function is called */
z->next_in = (Bytef *) buf;
z->avail_in = (uInt) nbytes;
@@ -305,11 +311,11 @@ static CURLcode deflate_unencode_write(struct Curl_easy *data,
return process_trailer(data, zp);
/* Now uncompress the data */
return inflate_stream(data, writer, ZLIB_INFLATING);
return inflate_stream(data, writer, type, ZLIB_INFLATING);
}
static void deflate_close_writer(struct Curl_easy *data,
struct contenc_writer *writer)
static void deflate_do_close(struct Curl_easy *data,
struct Curl_cwriter *writer)
{
struct zlib_writer *zp = (struct zlib_writer *) writer;
z_stream *z = &zp->z; /* zlib state structure */
@@ -317,19 +323,19 @@ static void deflate_close_writer(struct Curl_easy *data,
exit_zlib(data, z, &zp->zlib_init, CURLE_OK);
}
static const struct content_encoding deflate_encoding = {
static const struct Curl_cwtype deflate_encoding = {
"deflate",
NULL,
deflate_init_writer,
deflate_unencode_write,
deflate_close_writer,
deflate_do_init,
deflate_do_write,
deflate_do_close,
sizeof(struct zlib_writer)
};
/* Gzip handler. */
static CURLcode gzip_init_writer(struct Curl_easy *data,
struct contenc_writer *writer)
static CURLcode gzip_do_init(struct Curl_easy *data,
struct Curl_cwriter *writer)
{
struct zlib_writer *zp = (struct zlib_writer *) writer;
z_stream *z = &zp->z; /* zlib state structure */
@@ -441,19 +447,22 @@ static enum {
}
#endif
static CURLcode gzip_unencode_write(struct Curl_easy *data,
struct contenc_writer *writer,
static CURLcode gzip_do_write(struct Curl_easy *data,
struct Curl_cwriter *writer, int type,
const char *buf, size_t nbytes)
{
struct zlib_writer *zp = (struct zlib_writer *) writer;
z_stream *z = &zp->z; /* zlib state structure */
if(!(type & CLIENTWRITE_BODY))
return Curl_cwriter_write(data, writer->next, type, buf, nbytes);
if(zp->zlib_init == ZLIB_INIT_GZIP) {
/* Let zlib handle the gzip decompression entirely */
z->next_in = (Bytef *) buf;
z->avail_in = (uInt) nbytes;
/* Now uncompress the data */
return inflate_stream(data, writer, ZLIB_INIT_GZIP);
return inflate_stream(data, writer, type, ZLIB_INIT_GZIP);
}
#ifndef OLD_ZLIB_SUPPORT
@@ -565,12 +574,12 @@ static CURLcode gzip_unencode_write(struct Curl_easy *data,
}
/* We've parsed the header, now uncompress the data */
return inflate_stream(data, writer, ZLIB_GZIP_INFLATING);
return inflate_stream(data, writer, type, ZLIB_GZIP_INFLATING);
#endif
}
static void gzip_close_writer(struct Curl_easy *data,
struct contenc_writer *writer)
static void gzip_do_close(struct Curl_easy *data,
struct Curl_cwriter *writer)
{
struct zlib_writer *zp = (struct zlib_writer *) writer;
z_stream *z = &zp->z; /* zlib state structure */
@@ -578,12 +587,12 @@ static void gzip_close_writer(struct Curl_easy *data,
exit_zlib(data, z, &zp->zlib_init, CURLE_OK);
}
static const struct content_encoding gzip_encoding = {
static const struct Curl_cwtype gzip_encoding = {
"gzip",
"x-gzip",
gzip_init_writer,
gzip_unencode_write,
gzip_close_writer,
gzip_do_init,
gzip_do_write,
gzip_do_close,
sizeof(struct zlib_writer)
};
@@ -593,7 +602,7 @@ static const struct content_encoding gzip_encoding = {
#ifdef HAVE_BROTLI
/* Brotli writer. */
struct brotli_writer {
struct contenc_writer super;
struct Curl_cwriter super;
BrotliDecoderState *br; /* State structure for brotli. */
};
@@ -635,8 +644,8 @@ static CURLcode brotli_map_error(BrotliDecoderErrorCode be)
return CURLE_WRITE_ERROR;
}
static CURLcode brotli_init_writer(struct Curl_easy *data,
struct contenc_writer *writer)
static CURLcode brotli_do_init(struct Curl_easy *data,
struct Curl_cwriter *writer)
{
struct brotli_writer *bp = (struct brotli_writer *) writer;
(void) data;
@@ -645,8 +654,8 @@ static CURLcode brotli_init_writer(struct Curl_easy *data,
return bp->br? CURLE_OK: CURLE_OUT_OF_MEMORY;
}
static CURLcode brotli_unencode_write(struct Curl_easy *data,
struct contenc_writer *writer,
static CURLcode brotli_do_write(struct Curl_easy *data,
struct Curl_cwriter *writer, int type,
const char *buf, size_t nbytes)
{
struct brotli_writer *bp = (struct brotli_writer *) writer;
@@ -657,6 +666,9 @@ static CURLcode brotli_unencode_write(struct Curl_easy *data,
CURLcode result = CURLE_OK;
BrotliDecoderResult r = BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT;
if(!(type & CLIENTWRITE_BODY))
return Curl_cwriter_write(data, writer->next, type, buf, nbytes);
if(!bp->br)
return CURLE_WRITE_ERROR; /* Stream already ended. */
@@ -670,7 +682,7 @@ static CURLcode brotli_unencode_write(struct Curl_easy *data,
dstleft = DSIZ;
r = BrotliDecoderDecompressStream(bp->br,
&nbytes, &src, &dstleft, &dst, NULL);
result = Curl_unencode_write(data, writer->downstream,
result = Curl_cwriter_write(data, writer->next, type,
decomp, DSIZ - dstleft);
if(result)
break;
@@ -693,8 +705,8 @@ static CURLcode brotli_unencode_write(struct Curl_easy *data,
return result;
}
static void brotli_close_writer(struct Curl_easy *data,
struct contenc_writer *writer)
static void brotli_do_close(struct Curl_easy *data,
struct Curl_cwriter *writer)
{
struct brotli_writer *bp = (struct brotli_writer *) writer;
@@ -706,12 +718,12 @@ static void brotli_close_writer(struct Curl_easy *data,
}
}
static const struct content_encoding brotli_encoding = {
static const struct Curl_cwtype brotli_encoding = {
"br",
NULL,
brotli_init_writer,
brotli_unencode_write,
brotli_close_writer,
brotli_do_init,
brotli_do_write,
brotli_do_close,
sizeof(struct brotli_writer)
};
#endif
@@ -720,13 +732,13 @@ static const struct content_encoding brotli_encoding = {
#ifdef HAVE_ZSTD
/* Zstd writer. */
struct zstd_writer {
struct contenc_writer super;
struct Curl_cwriter super;
ZSTD_DStream *zds; /* State structure for zstd. */
void *decomp;
};
static CURLcode zstd_init_writer(struct Curl_easy *data,
struct contenc_writer *writer)
static CURLcode zstd_do_init(struct Curl_easy *data,
struct Curl_cwriter *writer)
{
struct zstd_writer *zp = (struct zstd_writer *) writer;
@@ -737,8 +749,8 @@ static CURLcode zstd_init_writer(struct Curl_easy *data,
return zp->zds ? CURLE_OK : CURLE_OUT_OF_MEMORY;
}
static CURLcode zstd_unencode_write(struct Curl_easy *data,
struct contenc_writer *writer,
static CURLcode zstd_do_write(struct Curl_easy *data,
struct Curl_cwriter *writer, int type,
const char *buf, size_t nbytes)
{
CURLcode result = CURLE_OK;
@@ -747,6 +759,9 @@ static CURLcode zstd_unencode_write(struct Curl_easy *data,
ZSTD_outBuffer out;
size_t errorCode;
if(!(type & CLIENTWRITE_BODY))
return Curl_cwriter_write(data, writer->next, type, buf, nbytes);
if(!zp->decomp) {
zp->decomp = malloc(DSIZ);
if(!zp->decomp)
@@ -766,7 +781,7 @@ static CURLcode zstd_unencode_write(struct Curl_easy *data,
return CURLE_BAD_CONTENT_ENCODING;
}
if(out.pos > 0) {
result = Curl_unencode_write(data, writer->downstream,
result = Curl_cwriter_write(data, writer->next, type,
zp->decomp, out.pos);
if(result)
break;
@@ -778,8 +793,8 @@ static CURLcode zstd_unencode_write(struct Curl_easy *data,
return result;
}
static void zstd_close_writer(struct Curl_easy *data,
struct contenc_writer *writer)
static void zstd_do_close(struct Curl_easy *data,
struct Curl_cwriter *writer)
{
struct zstd_writer *zp = (struct zstd_writer *) writer;
@@ -795,52 +810,30 @@ static void zstd_close_writer(struct Curl_easy *data,
}
}
static const struct content_encoding zstd_encoding = {
static const struct Curl_cwtype zstd_encoding = {
"zstd",
NULL,
zstd_init_writer,
zstd_unencode_write,
zstd_close_writer,
zstd_do_init,
zstd_do_write,
zstd_do_close,
sizeof(struct zstd_writer)
};
#endif
/* Identity handler. */
static CURLcode identity_init_writer(struct Curl_easy *data,
struct contenc_writer *writer)
{
(void)data;
(void)writer;
return CURLE_OK;
}
static CURLcode identity_unencode_write(struct Curl_easy *data,
struct contenc_writer *writer,
const char *buf, size_t nbytes)
{
return Curl_unencode_write(data, writer->downstream, buf, nbytes);
}
static void identity_close_writer(struct Curl_easy *data,
struct contenc_writer *writer)
{
(void) data;
(void) writer;
}
static const struct content_encoding identity_encoding = {
static const struct Curl_cwtype identity_encoding = {
"identity",
"none",
identity_init_writer,
identity_unencode_write,
identity_close_writer,
sizeof(struct contenc_writer)
Curl_cwriter_def_init,
Curl_cwriter_def_write,
Curl_cwriter_def_close,
sizeof(struct Curl_cwriter)
};
/* supported content encodings table. */
static const struct content_encoding * const encodings[] = {
static const struct Curl_cwtype * const encodings[] = {
&identity_encoding,
#ifdef HAVE_LIBZ
&deflate_encoding,
@@ -856,13 +849,17 @@ static const struct content_encoding * const encodings[] = {
};
/* Return a list of comma-separated names of supported encodings. */
char *Curl_all_content_encodings(void)
/* Provide a list of comma-separated names of supported encodings.
*/
void Curl_all_content_encodings(char *buf, size_t blen)
{
size_t len = 0;
const struct content_encoding * const *cep;
const struct content_encoding *ce;
char *ace;
const struct Curl_cwtype * const *cep;
const struct Curl_cwtype *ce;
DEBUGASSERT(buf);
DEBUGASSERT(blen);
buf[0] = 0;
for(cep = encodings; *cep; cep++) {
ce = *cep;
@@ -870,12 +867,12 @@ char *Curl_all_content_encodings(void)
len += strlen(ce->name) + 2;
}
if(!len)
return strdup(CONTENT_ENCODING_DEFAULT);
ace = malloc(len);
if(ace) {
char *p = ace;
if(!len) {
if(blen >= sizeof(CONTENT_ENCODING_DEFAULT))
strcpy(buf, CONTENT_ENCODING_DEFAULT);
}
else if(blen > len) {
char *p = buf;
for(cep = encodings; *cep; cep++) {
ce = *cep;
if(!strcasecompare(ce->name, CONTENT_ENCODING_DEFAULT)) {
@@ -887,75 +884,60 @@ char *Curl_all_content_encodings(void)
}
p[-2] = '\0';
}
return ace;
}
/* Deferred error dummy writer. */
static CURLcode error_init_writer(struct Curl_easy *data,
struct contenc_writer *writer)
static CURLcode error_do_init(struct Curl_easy *data,
struct Curl_cwriter *writer)
{
(void)data;
(void)writer;
return CURLE_OK;
}
static CURLcode error_unencode_write(struct Curl_easy *data,
struct contenc_writer *writer,
static CURLcode error_do_write(struct Curl_easy *data,
struct Curl_cwriter *writer, int type,
const char *buf, size_t nbytes)
{
char *all = Curl_all_content_encodings();
char all[256];
(void)Curl_all_content_encodings(all, sizeof(all));
(void) writer;
(void) buf;
(void) nbytes;
if(!all)
return CURLE_OUT_OF_MEMORY;
if(!(type & CLIENTWRITE_BODY))
return Curl_cwriter_write(data, writer->next, type, buf, nbytes);
failf(data, "Unrecognized content encoding type. "
"libcurl understands %s content encodings.", all);
free(all);
return CURLE_BAD_CONTENT_ENCODING;
}
static void error_close_writer(struct Curl_easy *data,
struct contenc_writer *writer)
static void error_do_close(struct Curl_easy *data,
struct Curl_cwriter *writer)
{
(void) data;
(void) writer;
}
static const struct content_encoding error_encoding = {
static const struct Curl_cwtype error_writer = {
"ce-error",
NULL,
NULL,
error_init_writer,
error_unencode_write,
error_close_writer,
sizeof(struct contenc_writer)
error_do_init,
error_do_write,
error_do_close,
sizeof(struct Curl_cwriter)
};
/* Write data using an unencoding writer stack. "nbytes" is not
allowed to be 0. */
CURLcode Curl_unencode_write(struct Curl_easy *data,
struct contenc_writer *writer,
const char *buf, size_t nbytes)
{
if(!nbytes)
return CURLE_OK;
if(!writer)
return CURLE_WRITE_ERROR;
return writer->handler->unencode_write(data, writer, buf, nbytes);
}
/* Find the content encoding by name. */
static const struct content_encoding *find_encoding(const char *name,
static const struct Curl_cwtype *find_encoding(const char *name,
size_t len)
{
const struct content_encoding * const *cep;
const struct Curl_cwtype * const *cep;
for(cep = encodings; *cep; cep++) {
const struct content_encoding *ce = *cep;
const struct Curl_cwtype *ce = *cep;
if((strncasecompare(name, ce->name, len) && !ce->name[len]) ||
(ce->alias && strncasecompare(name, ce->alias, len) && !ce->alias[len]))
return ce;
@@ -969,7 +951,8 @@ CURLcode Curl_build_unencoding_stack(struct Curl_easy *data,
const char *enclist, int is_transfer)
{
struct SingleRequest *k = &data->req;
unsigned int order = is_transfer? 2: 1;
Curl_cwriter_phase phase = is_transfer?
CURL_CW_TRANSFER_DECODE:CURL_CW_CONTENT_DECODE;
CURLcode result;
do {
@@ -992,23 +975,32 @@ CURLcode Curl_build_unencoding_stack(struct Curl_easy *data,
Curl_httpchunk_init(data); /* init our chunky engine. */
}
else if(namelen) {
const struct content_encoding *encoding;
struct contenc_writer *writer;
if(is_transfer && !data->set.http_transfer_encoding)
const struct Curl_cwtype *cwt;
struct Curl_cwriter *writer;
if((is_transfer && !data->set.http_transfer_encoding) ||
(!is_transfer && data->set.http_ce_skip)) {
/* not requested, ignore */
return CURLE_OK;
}
encoding = find_encoding(name, namelen);
if(!encoding)
encoding = &error_encoding; /* Defer error at stack use. */
if(Curl_cwriter_count(data, phase) + 1 >= MAX_ENCODE_STACK) {
failf(data, "Reject response due to more than %u content encodings",
MAX_ENCODE_STACK);
return CURLE_BAD_CONTENT_ENCODING;
}
result = Curl_client_create_writer(&writer, data, encoding, order);
cwt = find_encoding(name, namelen);
if(!cwt)
cwt = &error_writer; /* Defer error at use. */
result = Curl_cwriter_create(&writer, data, cwt, phase);
if(result)
return result;
result = Curl_client_add_writer(data, writer);
result = Curl_cwriter_add(data, writer);
if(result) {
Curl_client_free_writer(data, writer);
Curl_cwriter_free(data, writer);
return result;
}
}
@@ -1028,20 +1020,15 @@ CURLcode Curl_build_unencoding_stack(struct Curl_easy *data,
return CURLE_NOT_BUILT_IN;
}
CURLcode Curl_unencode_write(struct Curl_easy *data,
struct contenc_writer *writer,
const char *buf, size_t nbytes)
void Curl_all_content_encodings(char *buf, size_t blen)
{
(void) data;
(void) writer;
(void) buf;
(void) nbytes;
return CURLE_NOT_BUILT_IN;
DEBUGASSERT(buf);
DEBUGASSERT(blen);
if(blen < sizeof(CONTENT_ENCODING_DEFAULT))
buf[0] = 0;
else
strcpy(buf, CONTENT_ENCODING_DEFAULT);
}
char *Curl_all_content_encodings(void)
{
return strdup(CONTENT_ENCODING_DEFAULT); /* Satisfy caller. */
}
#endif /* CURL_DISABLE_HTTP */
+2 -7
View File
@@ -25,15 +25,10 @@
***************************************************************************/
#include "curl_setup.h"
struct contenc_writer;
struct Curl_cwriter;
char *Curl_all_content_encodings(void);
void Curl_all_content_encodings(char *buf, size_t blen);
CURLcode Curl_build_unencoding_stack(struct Curl_easy *data,
const char *enclist, int is_transfer);
CURLcode Curl_unencode_write(struct Curl_easy *data,
struct contenc_writer *writer,
const char *buf, size_t nbytes);
void Curl_unencode_cleanup(struct Curl_easy *data);
#endif /* HEADER_CURL_CONTENT_ENCODING_H */
+19 -13
View File
@@ -330,7 +330,7 @@ static char *sanitize_cookie_path(const char *cookie_path)
*/
void Curl_cookie_loadfiles(struct Curl_easy *data)
{
struct curl_slist *list = data->set.cookielist;
struct curl_slist *list = data->state.cookielist;
if(list) {
Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
while(list) {
@@ -365,9 +365,7 @@ static void strstore(char **str, const char *newstr, size_t len)
DEBUGASSERT(newstr);
DEBUGASSERT(str);
free(*str);
*str = Curl_memdup(newstr, len + 1);
if(*str)
(*str)[len] = 0;
*str = Curl_strndup(newstr, len);
}
/*
@@ -1029,15 +1027,23 @@ Curl_cookie_add(struct Curl_easy *data,
* dereference it.
*/
if(data && (domain && co->domain && !Curl_host_is_ipnum(co->domain))) {
const psl_ctx_t *psl = Curl_psl_use(data);
int acceptable;
if(psl) {
acceptable = psl_is_cookie_domain_acceptable(psl, domain, co->domain);
Curl_psl_release(data);
bool acceptable = FALSE;
char lcase[256];
char lcookie[256];
size_t dlen = strlen(domain);
size_t clen = strlen(co->domain);
if((dlen < sizeof(lcase)) && (clen < sizeof(lcookie))) {
const psl_ctx_t *psl = Curl_psl_use(data);
if(psl) {
/* the PSL check requires lowercase domain name and pattern */
Curl_strntolower(lcase, domain, dlen + 1);
Curl_strntolower(lcookie, co->domain, clen + 1);
acceptable = psl_is_cookie_domain_acceptable(psl, lcase, lcookie);
Curl_psl_release(data);
}
else
acceptable = !bad_domain(domain, strlen(domain));
}
else
acceptable = !bad_domain(domain, strlen(domain));
if(!acceptable) {
infof(data, "cookie '%s' dropped, domain '%s' must not "
@@ -1347,7 +1353,7 @@ static int cookie_sort_ct(const void *p1, const void *p2)
static struct Cookie *dup_cookie(struct Cookie *src)
{
struct Cookie *d = calloc(sizeof(struct Cookie), 1);
struct Cookie *d = calloc(1, sizeof(struct Cookie));
if(d) {
CLONE(domain);
CLONE(path);
+12 -15
View File
@@ -67,9 +67,15 @@
/* disables FTP */
#cmakedefine CURL_DISABLE_FTP 1
/* disables curl_easy_options API for existing options to curl_easy_setopt */
#cmakedefine CURL_DISABLE_GETOPTIONS 1
/* disables GOPHER */
#cmakedefine CURL_DISABLE_GOPHER 1
/* disables headers-api support */
#cmakedefine CURL_DISABLE_HEADERS_API 1
/* disables HSTS support */
#cmakedefine CURL_DISABLE_HSTS 1
@@ -91,6 +97,9 @@
/* disables MIME support */
#cmakedefine CURL_DISABLE_MIME 1
/* disables local binding support */
#cmakedefine CURL_DISABLE_BINDLOCAL 1
/* disables MQTT */
#cmakedefine CURL_DISABLE_MQTT 1
@@ -161,9 +170,6 @@
/* Define to 1 if you have _Atomic support. */
#cmakedefine HAVE_ATOMIC 1
/* Define to 1 if you have the `fchmod' function. */
#cmakedefine HAVE_FCHMOD 1
/* Define to 1 if you have the `fnmatch' function. */
#cmakedefine HAVE_FNMATCH 1
@@ -201,6 +207,9 @@
/* Define to 1 if you have the fseeko function. */
#cmakedefine HAVE_FSEEKO 1
/* Define to 1 if you have the fseeko declaration. */
#cmakedefine HAVE_DECL_FSEEKO 1
/* Define to 1 if you have the _fseeki64 function. */
#cmakedefine HAVE__FSEEKI64 1
@@ -306,9 +315,6 @@
/* Define to 1 if symbol `ADDRESS_FAMILY' exists */
#cmakedefine HAVE_ADDRESS_FAMILY 1
/* Define to 1 if you have the <inttypes.h> header file. */
#cmakedefine HAVE_INTTYPES_H 1
/* Define to 1 if you have the ioctlsocket function. */
#cmakedefine HAVE_IOCTLSOCKET 1
@@ -492,9 +498,6 @@
/* Define to 1 if you have the <stdbool.h> header file. */
#cmakedefine HAVE_STDBOOL_H 1
/* Define to 1 if you have the <stdint.h> header file. */
#cmakedefine HAVE_STDINT_H 1
/* Define to 1 if you have the strcasecmp function. */
#cmakedefine HAVE_STRCASECMP 1
@@ -591,12 +594,6 @@
/* Define to 1 if you have the <utime.h> header file. */
#cmakedefine HAVE_UTIME_H 1
/* Define to 1 if compiler supports C99 variadic macro style. */
#cmakedefine HAVE_VARIADIC_MACROS_C99 1
/* Define to 1 if compiler supports old gcc variadic macro style. */
#cmakedefine HAVE_VARIADIC_MACROS_GCC 1
/* Define to 1 if you have the windows.h header file. */
#cmakedefine HAVE_WINDOWS_H 1
+2 -1
View File
@@ -25,7 +25,8 @@
***************************************************************************/
#if (defined(USE_CURL_NTLM_CORE) && !defined(USE_WINDOWS_SSPI)) \
|| !defined(CURL_DISABLE_AWS) || !defined(CURL_DISABLE_DIGEST_AUTH)
|| !defined(CURL_DISABLE_AWS) || !defined(CURL_DISABLE_DIGEST_AUTH) \
|| defined(USE_LIBSSH2)
#include <curl/curl.h>
+3 -3
View File
@@ -68,7 +68,7 @@
#undef send
#undef recv
#ifdef WIN32
#ifdef _WIN32
# ifdef UNICODE
# undef wcsdup
# undef _wcsdup
@@ -134,7 +134,7 @@ extern curl_free_callback Curl_cfree;
extern curl_realloc_callback Curl_crealloc;
extern curl_strdup_callback Curl_cstrdup;
extern curl_calloc_callback Curl_ccalloc;
#if defined(WIN32) && defined(UNICODE)
#if defined(_WIN32) && defined(UNICODE)
extern curl_wcsdup_callback Curl_cwcsdup;
#endif
@@ -160,7 +160,7 @@ extern curl_wcsdup_callback Curl_cwcsdup;
#undef free
#define free(ptr) Curl_cfree(ptr)
#ifdef WIN32
#ifdef _WIN32
# ifdef UNICODE
# undef wcsdup
# define wcsdup(ptr) Curl_cwcsdup(ptr)
+2 -2
View File
@@ -32,7 +32,7 @@
#include "curl_setup.h"
#if defined(WIN32)
#if defined(_WIN32)
#include "curl_multibyte.h"
@@ -84,7 +84,7 @@ char *curlx_convert_wchar_to_UTF8(const wchar_t *str_w)
return str_utf8;
}
#endif /* WIN32 */
#endif /* _WIN32 */
#if defined(USE_WIN32_LARGE_FILES) || defined(USE_WIN32_SMALL_FILES)
+4 -4
View File
@@ -25,7 +25,7 @@
***************************************************************************/
#include "curl_setup.h"
#if defined(WIN32)
#if defined(_WIN32)
/*
* MultiByte conversions using Windows kernel32 library.
@@ -33,7 +33,7 @@
wchar_t *curlx_convert_UTF8_to_wchar(const char *str_utf8);
char *curlx_convert_wchar_to_UTF8(const wchar_t *str_w);
#endif /* WIN32 */
#endif /* _WIN32 */
/*
* Macros curlx_convert_UTF8_to_tchar(), curlx_convert_tchar_to_UTF8()
@@ -54,7 +54,7 @@ char *curlx_convert_wchar_to_UTF8(const wchar_t *str_w);
* ensure that the curl memdebug override macros do not replace them.
*/
#if defined(UNICODE) && defined(WIN32)
#if defined(UNICODE) && defined(_WIN32)
#define curlx_convert_UTF8_to_tchar(ptr) curlx_convert_UTF8_to_wchar((ptr))
#define curlx_convert_tchar_to_UTF8(ptr) curlx_convert_wchar_to_UTF8((ptr))
@@ -78,7 +78,7 @@ typedef union {
const unsigned char *const_tbyte_ptr;
} xcharp_u;
#endif /* UNICODE && WIN32 */
#endif /* UNICODE && _WIN32 */
#define curlx_unicodefree(ptr) \
do { \
+9
View File
@@ -111,6 +111,7 @@
# include <wincrypt.h>
#else
# error "Can't compile NTLM support without a crypto library with DES."
# define CURL_NTLM_NOT_SUPPORTED
#endif
#include "urldata.h"
@@ -130,6 +131,7 @@
#define NTLMv2_BLOB_SIGNATURE "\x01\x01\x00\x00"
#define NTLMv2_BLOB_LEN (44 -16 + ntlm->target_info_len + 4)
#if !defined(CURL_NTLM_NOT_SUPPORTED)
/*
* Turns a 56-bit key into being 64-bit wide.
*/
@@ -144,6 +146,7 @@ static void extend_key_56_to_64(const unsigned char *key_56, char *key)
key[6] = (unsigned char)(((key_56[5] << 2) & 0xFF) | (key_56[6] >> 6));
key[7] = (unsigned char) ((key_56[6] << 1) & 0xFF);
}
#endif
#if defined(USE_OPENSSL_DES) || defined(USE_WOLFSSL)
/*
@@ -337,6 +340,10 @@ void Curl_ntlm_core_lm_resp(const unsigned char *keys,
encrypt_des(plaintext, results, keys);
encrypt_des(plaintext, results + 8, keys + 7);
encrypt_des(plaintext, results + 16, keys + 14);
#else
(void)keys;
(void)plaintext;
(void)results;
#endif
}
@@ -347,9 +354,11 @@ CURLcode Curl_ntlm_core_mk_lm_hash(const char *password,
unsigned char *lmbuffer /* 21 bytes */)
{
unsigned char pw[14];
#if !defined(CURL_NTLM_NOT_SUPPORTED)
static const unsigned char magic[] = {
0x4B, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25 /* i.e. KGS!@#$% */
};
#endif
size_t len = CURLMIN(strlen(password), 14);
Curl_strntoupper((char *)pw, password, len);
+8 -6
View File
@@ -68,7 +68,9 @@
/* Portable 'sclose_nolog' used only in child process instead of 'sclose'
to avoid fooling the socket leak detector */
#if defined(HAVE_CLOSESOCKET)
#ifdef HAVE_PIPE
# define sclose_nolog(x) close((x))
#elif defined(HAVE_CLOSESOCKET)
# define sclose_nolog(x) closesocket((x))
#elif defined(HAVE_CLOSESOCKET_CAMEL)
# define sclose_nolog(x) CloseSocket((x))
@@ -189,7 +191,7 @@ static CURLcode ntlm_wb_init(struct Curl_easy *data, struct ntlmdata *ntlm,
goto done;
}
if(Curl_socketpair(AF_UNIX, SOCK_STREAM, 0, sockfds)) {
if(wakeup_create(sockfds)) {
failf(data, "Could not open socket pair. errno %d: %s",
errno, Curl_strerror(errno, buffer, sizeof(buffer)));
goto done;
@@ -197,8 +199,8 @@ static CURLcode ntlm_wb_init(struct Curl_easy *data, struct ntlmdata *ntlm,
child_pid = fork();
if(child_pid == -1) {
sclose(sockfds[0]);
sclose(sockfds[1]);
wakeup_close(sockfds[0]);
wakeup_close(sockfds[1]);
failf(data, "Could not fork. errno %d: %s",
errno, Curl_strerror(errno, buffer, sizeof(buffer)));
goto done;
@@ -268,7 +270,7 @@ static CURLcode ntlm_wb_response(struct Curl_easy *data, struct ntlmdata *ntlm,
Curl_dyn_init(&b, MAX_NTLM_WB_RESPONSE);
while(len_in > 0) {
ssize_t written = swrite(ntlm->ntlm_auth_hlpr_socket, input, len_in);
ssize_t written = wakeup_write(ntlm->ntlm_auth_hlpr_socket, input, len_in);
if(written == -1) {
/* Interrupted by a signal, retry it */
if(errno == EINTR)
@@ -282,7 +284,7 @@ static CURLcode ntlm_wb_response(struct Curl_easy *data, struct ntlmdata *ntlm,
/* Read one line */
while(1) {
ssize_t size =
sread(ntlm->ntlm_auth_hlpr_socket, buf, data->set.buffer_size);
wakeup_read(ntlm->ntlm_auth_hlpr_socket, buf, data->set.buffer_size);
if(size == -1) {
if(errno == EINTR)
continue;
+1 -1
View File
@@ -28,7 +28,7 @@
#include <curl/curl.h>
#include "urldata.h"
#ifdef WIN32
#ifdef _WIN32
# undef PATH_MAX
# define PATH_MAX MAX_PATH
# ifndef R_OK
+1 -1
View File
@@ -39,7 +39,7 @@
/* The last #include file should be: */
#include "memdebug.h"
#if defined(WIN32) && !defined(USE_LWIPSOCK)
#if defined(_WIN32) && !defined(USE_LWIPSOCK)
#define setsockopt(a,b,c,d,e) (setsockopt)(a,b,c,(const char *)d,(int)e)
#define SET_RCVTIMEO(tv,s) int tv = s*1000
#elif defined(LWIP_SO_SNDRCVTIMEO_NONSTANDARD)
+3
View File
@@ -262,6 +262,8 @@ static void sasl_state(struct SASL *sasl, struct Curl_easy *data,
sasl->state = newstate;
}
#if defined(USE_NTLM) || defined(USE_GSASL) || defined(USE_KERBEROS5) || \
!defined(CURL_DISABLE_DIGEST_AUTH)
/* Get the SASL server message and convert it to binary. */
static CURLcode get_server_message(struct SASL *sasl, struct Curl_easy *data,
struct bufref *out)
@@ -284,6 +286,7 @@ static CURLcode get_server_message(struct SASL *sasl, struct Curl_easy *data,
}
return result;
}
#endif
/* Encode the outgoing SASL message. */
static CURLcode build_message(struct SASL *sasl, struct bufref *msg)
+48 -93
View File
@@ -28,6 +28,11 @@
#define CURL_NO_OLDIES
#endif
/* Set default _WIN32_WINNT */
#ifdef __MINGW32__
#include <_mingw.h>
#endif
/*
* Disable Visual Studio warnings:
* 4127 "conditional expression is constant"
@@ -36,15 +41,7 @@
#pragma warning(disable:4127)
#endif
/*
* Define WIN32 when build target is Win32 API
*/
#if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32)
#define WIN32
#endif
#ifdef WIN32
#ifdef _WIN32
/*
* Don't include unneeded stuff in Windows headers to avoid compiler
* warnings and macro clashes.
@@ -82,7 +79,7 @@
#ifdef _WIN32_WCE
# include "config-win32ce.h"
#else
# ifdef WIN32
# ifdef _WIN32
# include "config-win32.h"
# endif
#endif
@@ -218,6 +215,23 @@
# define CURL_DISABLE_RTSP
#endif
/*
* When HTTP is disabled, disable HTTP-only features
*/
#if defined(CURL_DISABLE_HTTP)
# define CURL_DISABLE_ALTSVC 1
# define CURL_DISABLE_COOKIES 1
# define CURL_DISABLE_BASIC_AUTH 1
# define CURL_DISABLE_BEARER_AUTH 1
# define CURL_DISABLE_AWS 1
# define CURL_DISABLE_DOH 1
# define CURL_DISABLE_FORM_API 1
# define CURL_DISABLE_HEADERS_API 1
# define CURL_DISABLE_HSTS 1
# define CURL_DISABLE_HTTP_AUTH 1
#endif
/* ================================================================ */
/* No system header file shall be included in this file before this */
/* point. */
@@ -335,23 +349,6 @@
#include <curl/stdcheaders.h>
#endif
#ifdef __POCC__
# include <sys/types.h>
# include <unistd.h>
# define sys_nerr EILSEQ
#endif
/*
* Salford-C kludge section (mostly borrowed from wxWidgets).
*/
#ifdef __SALFORDC__
#pragma suppress 353 /* Possible nested comments */
#pragma suppress 593 /* Define not used */
#pragma suppress 61 /* enum has no name */
#pragma suppress 106 /* unnamed, unused parameter */
#include <clib.h>
#endif
/* Default Windows file API selection. */
#ifdef _WIN32
# if defined(_MSC_VER) && (_INTEGRAL_MAX_BITS >= 64)
@@ -515,11 +512,11 @@
5. set dir/file naming defines
*/
#ifdef WIN32
#ifdef _WIN32
# define DIR_CHAR "\\"
#else /* WIN32 */
#else /* _WIN32 */
# ifdef MSDOS /* Watt-32 */
@@ -544,48 +541,19 @@
# define DIR_CHAR "/"
# ifndef fileno /* sunos 4 have this as a macro! */
int fileno(FILE *stream);
# endif
#endif /* WIN32 */
/*
* msvc 6.0 requires PSDK in order to have INET6_ADDRSTRLEN
* defined in ws2tcpip.h as well as to provide IPv6 support.
* Does not apply if lwIP is used.
*/
#if defined(_MSC_VER) && !defined(__POCC__) && !defined(USE_LWIPSOCK)
# if !defined(HAVE_WS2TCPIP_H) || \
((_MSC_VER < 1300) && !defined(INET6_ADDRSTRLEN))
# undef HAVE_GETADDRINFO_THREADSAFE
# undef HAVE_FREEADDRINFO
# undef HAVE_GETADDRINFO
# undef ENABLE_IPV6
# endif
#endif
#endif /* _WIN32 */
/* ---------------------------------------------------------------- */
/* resolver specialty compile-time defines */
/* CURLRES_* defines to use in the host*.c sources */
/* ---------------------------------------------------------------- */
/*
* lcc-win32 doesn't have _beginthreadex(), lacks threads support.
*/
#if defined(__LCC__) && defined(WIN32)
# undef USE_THREADS_POSIX
# undef USE_THREADS_WIN32
#endif
/*
* MSVC threads support requires a multi-threaded runtime library.
* _beginthreadex() is not available in single-threaded ones.
*/
#if defined(_MSC_VER) && !defined(__POCC__) && !defined(_MT)
#if defined(_MSC_VER) && !defined(_MT)
# undef USE_THREADS_POSIX
# undef USE_THREADS_WIN32
#endif
@@ -596,6 +564,9 @@
#if defined(ENABLE_IPV6) && defined(HAVE_GETADDRINFO)
# define CURLRES_IPV6
#elif defined(ENABLE_IPV6) && (defined(_WIN32) || defined(__CYGWIN__))
/* assume on Windows that IPv6 without getaddrinfo is a broken build */
# error "Unexpected build: IPv6 is enabled but getaddrinfo was not found."
#else
# define CURLRES_IPV4
#endif
@@ -615,35 +586,6 @@
/* ---------------------------------------------------------------- */
/*
* msvc 6.0 does not have struct sockaddr_storage and
* does not define IPPROTO_ESP in winsock2.h. But both
* are available if PSDK is properly installed.
*/
#if defined(_MSC_VER) && !defined(__POCC__)
# if !defined(HAVE_WINSOCK2_H) || ((_MSC_VER < 1300) && !defined(IPPROTO_ESP))
# undef HAVE_STRUCT_SOCKADDR_STORAGE
# endif
#endif
/*
* Intentionally fail to build when using msvc 6.0 without PSDK installed.
* The brave of heart can circumvent this, defining ALLOW_MSVC6_WITHOUT_PSDK
* in lib/config-win32.h although absolutely discouraged and unsupported.
*/
#if defined(_MSC_VER) && !defined(__POCC__)
# if !defined(HAVE_WINDOWS_H) || ((_MSC_VER < 1300) && !defined(_FILETIME_))
# if !defined(ALLOW_MSVC6_WITHOUT_PSDK)
# error MSVC 6.0 requires "February 2003 Platform SDK" a.k.a. \
"Windows Server 2003 PSDK"
# else
# define CURL_DISABLE_LDAP 1
# endif
# endif
#endif
#if defined(HAVE_LIBIDN2) && defined(HAVE_IDN2_H) && !defined(USE_WIN32_IDN)
/* The lib and header are present */
#define USE_LIBIDN2
@@ -709,6 +651,18 @@
# define WARN_UNUSED_RESULT
#endif
/* noreturn attribute */
#if !defined(CURL_NORETURN)
#if (defined(__GNUC__) && (__GNUC__ >= 3)) || defined(__clang__)
# define CURL_NORETURN __attribute__((__noreturn__))
#elif defined(_MSC_VER) && (_MSC_VER >= 1200)
# define CURL_NORETURN __declspec(noreturn)
#else
# define CURL_NORETURN
#endif
#endif
/*
* Include macros and defines that should only be processed once.
*/
@@ -767,7 +721,7 @@
/* In Windows the default file mode is text but an application can override it.
Therefore we specify it explicitly. https://github.com/curl/curl/pull/258
*/
#if defined(WIN32) || defined(MSDOS)
#if defined(_WIN32) || defined(MSDOS)
#define FOPEN_READTEXT "rt"
#define FOPEN_WRITETEXT "wt"
#define FOPEN_APPENDTEXT "at"
@@ -822,7 +776,8 @@ int getpwuid_r(uid_t uid, struct passwd *pwd, char *buf,
#define UNITTEST static
#endif
#if defined(USE_NGHTTP2) || defined(USE_HYPER)
/* Hyper supports HTTP2 also, but Curl's integration with Hyper does not */
#if defined(USE_NGHTTP2)
#define USE_HTTP2
#endif
@@ -835,11 +790,11 @@ int getpwuid_r(uid_t uid, struct passwd *pwd, char *buf,
/* Certain Windows implementations are not aligned with what curl expects,
so always use the local one on this platform. E.g. the mingw-w64
implementation can return wrong results for non-ASCII inputs. */
#if defined(HAVE_BASENAME) && defined(WIN32)
#if defined(HAVE_BASENAME) && defined(_WIN32)
#undef HAVE_BASENAME
#endif
#if defined(USE_UNIX_SOCKETS) && defined(WIN32)
#if defined(USE_UNIX_SOCKETS) && defined(_WIN32)
# if !defined(UNIX_PATH_MAX)
/* Replicating logic present in afunix.h
(distributed with newer Windows 10 SDK versions only) */
+2 -6
View File
@@ -56,7 +56,7 @@
#include <sys/time.h>
#endif
#ifdef WIN32
#ifdef _WIN32
#include <io.h>
#include <fcntl.h>
#endif
@@ -70,11 +70,7 @@
#endif
#ifdef USE_WOLFSSL
# if defined(HAVE_STDINT_H)
# include <stdint.h>
# elif defined(HAVE_INTTYPES_H)
# include <inttypes.h>
# endif
#include <stdint.h>
#endif
#ifdef USE_SCHANNEL
+16
View File
@@ -88,6 +88,22 @@ extern PSecurityFunctionTable s_pSecFn;
# define CRYPT_E_REVOKED ((HRESULT)0x80092010L)
#endif
#ifndef CRYPT_E_NO_REVOCATION_DLL
# define CRYPT_E_NO_REVOCATION_DLL ((HRESULT)0x80092011L)
#endif
#ifndef CRYPT_E_NO_REVOCATION_CHECK
# define CRYPT_E_NO_REVOCATION_CHECK ((HRESULT)0x80092012L)
#endif
#ifndef CRYPT_E_REVOCATION_OFFLINE
# define CRYPT_E_REVOCATION_OFFLINE ((HRESULT)0x80092013L)
#endif
#ifndef CRYPT_E_NOT_IN_REVOCATION_DATABASE
# define CRYPT_E_NOT_IN_REVOCATION_DATABASE ((HRESULT)0x80092014L)
#endif
#ifdef UNICODE
# define SECFLAG_WINNT_AUTH_IDENTITY \
(unsigned long)SEC_WINNT_AUTH_IDENTITY_UNICODE
+6 -20
View File
@@ -61,10 +61,6 @@ void Curl_debug(struct Curl_easy *data, curl_infotype type,
"* ", "< ", "> ", "{ ", "} ", "{ ", "} " };
if(data->set.fdebug) {
bool inCallback = Curl_is_in_callback(data);
/* CURLOPT_DEBUGFUNCTION doc says the user may set CURLOPT_PRIVATE to
distinguish their handle from internal handles. */
if(data->internal)
DEBUGASSERT(!data->set.private_data);
Curl_set_in_callback(data, true);
(void)(*data->set.fdebug)(data, type, ptr, size, data->set.debugdata);
Curl_set_in_callback(data, inCallback);
@@ -109,6 +105,8 @@ void Curl_failf(struct Curl_easy *data, const char *fmt, ...)
}
}
#if !defined(CURL_DISABLE_VERBOSE_STRINGS)
/* Curl_infof() is for info message along the way */
#define MAXINFO 2048
@@ -128,13 +126,11 @@ void Curl_infof(struct Curl_easy *data, const char *fmt, ...)
}
}
#if !defined(CURL_DISABLE_VERBOSE_STRINGS)
void Curl_trc_cf_infof(struct Curl_easy *data, struct Curl_cfilter *cf,
const char *fmt, ...)
{
DEBUGASSERT(cf);
if(data && Curl_trc_cf_is_verbose(cf, data)) {
if(Curl_trc_cf_is_verbose(cf, data)) {
va_list ap;
int len;
char buffer[MAXINFO + 2];
@@ -232,24 +228,14 @@ CURLcode Curl_trc_init(void)
if(config) {
return Curl_trc_opt(config);
}
#endif
#endif /* DEBUGBUILD */
return CURLE_OK;
}
#else /* !CURL_DISABLE_VERBOSE_STRINGS) */
#else /* defined(CURL_DISABLE_VERBOSE_STRINGS) */
CURLcode Curl_trc_init(void)
{
return CURLE_OK;
}
#if !defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L)
void Curl_trc_cf_infof(struct Curl_easy *data, struct Curl_cfilter *cf,
const char *fmt, ...)
{
(void)data;
(void)cf;
(void)fmt;
}
#endif
#endif /* !DEBUGBUILD */
#endif /* !defined(CURL_DISABLE_VERBOSE_STRINGS) */
+52 -56
View File
@@ -54,19 +54,6 @@ CURLcode Curl_trc_opt(const char *config);
void Curl_debug(struct Curl_easy *data, curl_infotype type,
char *ptr, size_t size);
/**
* Output an informational message when transfer's verbose logging is enabled.
*/
void Curl_infof(struct Curl_easy *data,
#if defined(__GNUC__) && !defined(printf) && \
defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \
!defined(__MINGW32__)
const char *fmt, ...)
__attribute__((format(printf, 2, 3)));
#else
const char *fmt, ...);
#endif
/**
* Output a failure message on registered callbacks for transfer.
*/
@@ -82,39 +69,15 @@ void Curl_failf(struct Curl_easy *data,
#define failf Curl_failf
/**
* Output an informational message when both transfer's verbose logging
* and connection filters verbose logging are enabled.
*/
void Curl_trc_cf_infof(struct Curl_easy *data, struct Curl_cfilter *cf,
#if defined(__GNUC__) && !defined(printf) && \
defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \
!defined(__MINGW32__)
const char *fmt, ...)
__attribute__((format(printf, 3, 4)));
#else
const char *fmt, ...);
#endif
#define CURL_LOG_LVL_NONE 0
#define CURL_LOG_LVL_INFO 1
#if !defined(CURL_DISABLE_VERBOSE_STRINGS)
/* informational messages enabled */
#define Curl_trc_is_verbose(data) ((data) && (data)->set.verbose)
#define Curl_trc_cf_is_verbose(cf, data) \
((data) && (data)->set.verbose && \
(cf) && (cf)->cft->log_level >= CURL_LOG_LVL_INFO)
/* explainer: we have some mix configuration and werror settings
* that define HAVE_VARIADIC_MACROS_C99 even though C89 is enforced
* on gnuc and some other compiler. Need to treat carefully.
*/
#if defined(HAVE_VARIADIC_MACROS_C99) && \
defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
#define CURL_HAVE_C99
#endif
#ifdef CURL_HAVE_C99
#define infof(data, ...) \
do { if(Curl_trc_is_verbose(data)) \
Curl_infof(data, __VA_ARGS__); } while(0)
@@ -122,29 +85,62 @@ void Curl_trc_cf_infof(struct Curl_easy *data, struct Curl_cfilter *cf,
do { if(Curl_trc_cf_is_verbose(cf, data)) \
Curl_trc_cf_infof(data, cf, __VA_ARGS__); } while(0)
#else /* no variadic macro args */
#else
#define infof Curl_infof
#define CURL_TRC_CF Curl_trc_cf_infof
#endif /* variadic macro args */
#endif
#else /* !CURL_DISABLE_VERBOSE_STRINGS */
#ifndef CURL_DISABLE_VERBOSE_STRINGS
/* informational messages enabled */
#define Curl_trc_is_verbose(data) ((data) && (data)->set.verbose)
#define Curl_trc_cf_is_verbose(cf, data) \
((data) && (data)->set.verbose && \
(cf) && (cf)->cft->log_level >= CURL_LOG_LVL_INFO)
/**
* Output an informational message when transfer's verbose logging is enabled.
*/
void Curl_infof(struct Curl_easy *data,
#if defined(__GNUC__) && !defined(printf) && defined(CURL_HAVE_C99) && \
!defined(__MINGW32__)
const char *fmt, ...)
__attribute__((format(printf, 2, 3)));
#else
const char *fmt, ...);
#endif
/**
* Output an informational message when both transfer's verbose logging
* and connection filters verbose logging are enabled.
*/
void Curl_trc_cf_infof(struct Curl_easy *data, struct Curl_cfilter *cf,
#if defined(__GNUC__) && !defined(printf) && defined(CURL_HAVE_C99) && \
!defined(__MINGW32__)
const char *fmt, ...)
__attribute__((format(printf, 3, 4)));
#else
const char *fmt, ...);
#endif
#else /* defined(CURL_DISABLE_VERBOSE_STRINGS) */
/* All informational messages are not compiled in for size savings */
#define Curl_trc_is_verbose(d) ((void)(d), FALSE)
#define Curl_trc_cf_is_verbose(x,y) ((void)(x), (void)(y), FALSE)
#if defined(HAVE_VARIADIC_MACROS_C99)
#define infof(...) Curl_nop_stmt
#define CURL_TRC_CF(...) Curl_nop_stmt
#define Curl_trc_cf_infof(...) Curl_nop_stmt
#elif defined(HAVE_VARIADIC_MACROS_GCC)
#define infof(x...) Curl_nop_stmt
#define CURL_TRC_CF(x...) Curl_nop_stmt
#define Curl_trc_cf_infof(x...) Curl_nop_stmt
#else
#error "missing VARIADIC macro define, fix and rebuild!"
#endif
static void Curl_infof(struct Curl_easy *data, const char *fmt, ...)
{
(void)data; (void)fmt;
}
#endif /* CURL_DISABLE_VERBOSE_STRINGS */
static void Curl_trc_cf_infof(struct Curl_easy *data,
struct Curl_cfilter *cf,
const char *fmt, ...)
{
(void)data; (void)cf; (void)fmt;
}
#endif /* !defined(CURL_DISABLE_VERBOSE_STRINGS) */
#endif /* HEADER_CURL_TRC_H */
+26 -17
View File
@@ -242,7 +242,7 @@ static CURLcode dohprobe(struct Curl_easy *data,
/* pass in the struct pointer via a local variable to please coverity and
the gcc typecheck helpers */
struct dynbuf *resp = &p->serverdoh;
doh->internal = true;
doh->state.internal = true;
ERROR_CHECK_SETOPT(CURLOPT_URL, url);
ERROR_CHECK_SETOPT(CURLOPT_DEFAULT_PROTOCOL, "https");
ERROR_CHECK_SETOPT(CURLOPT_WRITEFUNCTION, doh_write_cb);
@@ -252,6 +252,7 @@ static CURLcode dohprobe(struct Curl_easy *data,
ERROR_CHECK_SETOPT(CURLOPT_HTTPHEADER, headers);
#ifdef USE_HTTP2
ERROR_CHECK_SETOPT(CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2TLS);
ERROR_CHECK_SETOPT(CURLOPT_PIPEWAIT, 1L);
#endif
#ifndef CURLDEBUG
/* enforce HTTPS if not debug */
@@ -339,9 +340,10 @@ static CURLcode dohprobe(struct Curl_easy *data,
doh->set.dohfor = data; /* identify for which transfer this is done */
p->easy = doh;
/* DoH private_data must be null because the user must have a way to
distinguish their transfer's handle from DoH handles in user
callbacks (ie SSL CTX callback). */
/* DoH handles must not inherit private_data. The handles may be passed to
the user via callbacks and the user will be able to identify them as
internal handles because private data is not set. The user can then set
private_data via CURLOPT_PRIVATE if they so choose. */
DEBUGASSERT(!doh->set.private_data);
if(curl_multi_add_handle(multi, doh))
@@ -372,7 +374,7 @@ struct Curl_addrinfo *Curl_doh(struct Curl_easy *data,
int slot;
struct dohdata *dohp;
struct connectdata *conn = data->conn;
*waitp = TRUE; /* this never returns synchronously */
*waitp = FALSE;
(void)hostname;
(void)port;
@@ -380,7 +382,7 @@ struct Curl_addrinfo *Curl_doh(struct Curl_easy *data,
DEBUGASSERT(conn);
/* start clean, consider allocating this struct on demand */
dohp = data->req.doh = calloc(sizeof(struct dohdata), 1);
dohp = data->req.doh = calloc(1, sizeof(struct dohdata));
if(!dohp)
return NULL;
@@ -412,12 +414,14 @@ struct Curl_addrinfo *Curl_doh(struct Curl_easy *data,
dohp->pending++;
}
#endif
*waitp = TRUE; /* this never returns synchronously */
return NULL;
error:
curl_slist_free_all(dohp->headers);
data->req.doh->headers = NULL;
for(slot = 0; slot < DOH_PROBE_SLOTS; slot++) {
(void)curl_multi_remove_handle(data->multi, dohp->probe[slot].easy);
Curl_close(&dohp->probe[slot].easy);
}
Curl_safefree(data->req.doh);
@@ -787,8 +791,8 @@ static void showdoh(struct Curl_easy *data,
* must be an associated call later to Curl_freeaddrinfo().
*/
static struct Curl_addrinfo *
doh2ai(const struct dohentry *de, const char *hostname, int port)
static CURLcode doh2ai(const struct dohentry *de, const char *hostname,
int port, struct Curl_addrinfo **aip)
{
struct Curl_addrinfo *ai;
struct Curl_addrinfo *prevai = NULL;
@@ -801,9 +805,10 @@ doh2ai(const struct dohentry *de, const char *hostname, int port)
int i;
size_t hostlen = strlen(hostname) + 1; /* include null-terminator */
if(!de)
/* no input == no output! */
return NULL;
DEBUGASSERT(de);
if(!de->numaddr)
return CURLE_COULDNT_RESOLVE_HOST;
for(i = 0; i < de->numaddr; i++) {
size_t ss_size;
@@ -876,8 +881,9 @@ doh2ai(const struct dohentry *de, const char *hostname, int port)
Curl_freeaddrinfo(firstai);
firstai = NULL;
}
*aip = firstai;
return firstai;
return result;
}
#ifndef CURL_DISABLE_VERBOSE_STRINGS
@@ -898,6 +904,7 @@ UNITTEST void de_cleanup(struct dohentry *d)
CURLcode Curl_doh_is_resolved(struct Curl_easy *data,
struct Curl_dns_entry **dnsp)
{
struct connectdata *conn = data->conn;
CURLcode result;
struct dohdata *dohp = data->req.doh;
*dnsp = NULL; /* defaults to no response */
@@ -906,7 +913,7 @@ CURLcode Curl_doh_is_resolved(struct Curl_easy *data,
if(!dohp->probe[DOH_PROBE_SLOT_IPADDR_V4].easy &&
!dohp->probe[DOH_PROBE_SLOT_IPADDR_V6].easy) {
failf(data, "Could not DoH-resolve: %s", data->state.async.hostname);
failf(data, "Could not DoH-resolve: %s", conn->resolve_async.hostname);
return CONN_IS_PROXIED(data->conn)?CURLE_COULDNT_RESOLVE_PROXY:
CURLE_COULDNT_RESOLVE_HOST;
}
@@ -932,10 +939,12 @@ CURLcode Curl_doh_is_resolved(struct Curl_easy *data,
p->dnstype,
&de);
Curl_dyn_free(&p->serverdoh);
#ifndef CURL_DISABLE_VERBOSE_STRINGS
if(rc[slot]) {
infof(data, "DoH: %s type %s for %s", doh_strerror(rc[slot]),
type2name(p->dnstype), dohp->host);
}
#endif
} /* next slot */
result = CURLE_COULDNT_RESOLVE_HOST; /* until we know better */
@@ -947,10 +956,10 @@ CURLcode Curl_doh_is_resolved(struct Curl_easy *data,
infof(data, "DoH Host name: %s", dohp->host);
showdoh(data, &de);
ai = doh2ai(&de, dohp->host, dohp->port);
if(!ai) {
result = doh2ai(&de, dohp->host, dohp->port, &ai);
if(result) {
de_cleanup(&de);
return CURLE_OUT_OF_MEMORY;
return result;
}
if(data->share)
@@ -967,7 +976,7 @@ CURLcode Curl_doh_is_resolved(struct Curl_easy *data,
Curl_freeaddrinfo(ai);
}
else {
data->state.async.dns = dns;
conn->resolve_async.dns = dns;
*dnsp = dns;
result = CURLE_OK; /* address resolution OK */
}
+5 -1
View File
@@ -77,6 +77,7 @@ static CURLcode dyn_nappend(struct dynbuf *s,
DEBUGASSERT(indx < s->toobig);
DEBUGASSERT(!s->leng || s->bufr);
DEBUGASSERT(a <= s->toobig);
DEBUGASSERT(!len || mem);
if(fit > s->toobig) {
Curl_dyn_free(s);
@@ -174,10 +175,12 @@ CURLcode Curl_dyn_addn(struct dynbuf *s, const void *mem, size_t len)
*/
CURLcode Curl_dyn_add(struct dynbuf *s, const char *str)
{
size_t n = strlen(str);
size_t n;
DEBUGASSERT(str);
DEBUGASSERT(s);
DEBUGASSERT(s->init == DYNINIT);
DEBUGASSERT(!s->leng || s->bufr);
n = strlen(str);
return dyn_nappend(s, (unsigned char *)str, n);
}
@@ -191,6 +194,7 @@ CURLcode Curl_dyn_vaddf(struct dynbuf *s, const char *fmt, va_list ap)
DEBUGASSERT(s);
DEBUGASSERT(s->init == DYNINIT);
DEBUGASSERT(!s->leng || s->bufr);
DEBUGASSERT(fmt);
rc = Curl_dyn_vprintf(s, fmt, ap);
if(!rc)
+29
View File
@@ -27,6 +27,10 @@
#include "strcase.h"
/* The last 3 #include files should be in this order */
#ifdef USE_NGHTTP2
#include <stdint.h>
#include <nghttp2/nghttp2.h>
#endif /* USE_NGHTTP2 */
#include "curl_printf.h"
#include "curl_memory.h"
#include "memdebug.h"
@@ -365,3 +369,28 @@ CURLcode Curl_dynhds_h1_dprint(struct dynhds *dynhds, struct dynbuf *dbuf)
return result;
}
#ifdef USE_NGHTTP2
nghttp2_nv *Curl_dynhds_to_nva(struct dynhds *dynhds, size_t *pcount)
{
nghttp2_nv *nva = calloc(1, sizeof(nghttp2_nv) * dynhds->hds_len);
size_t i;
*pcount = 0;
if(!nva)
return NULL;
for(i = 0; i < dynhds->hds_len; ++i) {
struct dynhds_entry *e = dynhds->hds[i];
DEBUGASSERT(e);
nva[i].name = (unsigned char *)e->name;
nva[i].namelen = e->namelen;
nva[i].value = (unsigned char *)e->value;
nva[i].valuelen = e->valuelen;
nva[i].flags = NGHTTP2_NV_FLAG_NONE;
}
*pcount = dynhds->hds_len;
return nva;
}
#endif /* USE_NGHTTP2 */
+9
View File
@@ -171,4 +171,13 @@ CURLcode Curl_dynhds_h1_add_line(struct dynhds *dynhds,
*/
CURLcode Curl_dynhds_h1_dprint(struct dynhds *dynhds, struct dynbuf *dbuf);
#ifdef USE_NGHTTP2
#include <stdint.h>
#include <nghttp2/nghttp2.h>
nghttp2_nv *Curl_dynhds_to_nva(struct dynhds *dynhds, size_t *pcount);
#endif /* USE_NGHTTP2 */
#endif /* HEADER_CURL_DYNHDS_H */
+25 -59
View File
@@ -112,7 +112,7 @@ static curl_simple_lock s_lock = CURL_SIMPLE_LOCK_INIT;
#define system_strdup strdup
#endif
#if defined(_MSC_VER) && defined(_DLL) && !defined(__POCC__)
#if defined(_MSC_VER) && defined(_DLL)
# pragma warning(disable:4232) /* MSVC extension, dllimport identity */
#endif
@@ -125,11 +125,11 @@ curl_free_callback Curl_cfree = (curl_free_callback)free;
curl_realloc_callback Curl_crealloc = (curl_realloc_callback)realloc;
curl_strdup_callback Curl_cstrdup = (curl_strdup_callback)system_strdup;
curl_calloc_callback Curl_ccalloc = (curl_calloc_callback)calloc;
#if defined(WIN32) && defined(UNICODE)
#if defined(_WIN32) && defined(UNICODE)
curl_wcsdup_callback Curl_cwcsdup = Curl_wcsdup;
#endif
#if defined(_MSC_VER) && defined(_DLL) && !defined(__POCC__)
#if defined(_MSC_VER) && defined(_DLL)
# pragma warning(default:4232) /* MSVC extension, dllimport identity */
#endif
@@ -153,7 +153,7 @@ static CURLcode global_init(long flags, bool memoryfuncs)
Curl_crealloc = (curl_realloc_callback)realloc;
Curl_cstrdup = (curl_strdup_callback)system_strdup;
Curl_ccalloc = (curl_calloc_callback)calloc;
#if defined(WIN32) && defined(UNICODE)
#if defined(_WIN32) && defined(UNICODE)
Curl_cwcsdup = (curl_wcsdup_callback)_wcsdup;
#endif
}
@@ -188,18 +188,10 @@ static CURLcode global_init(long flags, bool memoryfuncs)
goto fail;
}
#if defined(USE_SSH)
if(Curl_ssh_init()) {
DEBUGF(fprintf(stderr, "Error: Curl_ssh_init failed\n"));
goto fail;
}
#endif
#ifdef USE_WOLFSSH
if(WS_SUCCESS != wolfSSH_Init()) {
DEBUGF(fprintf(stderr, "Error: wolfSSH_Init failed\n"));
return CURLE_FAILED_INIT;
}
#endif
easy_init_flags = flags;
@@ -295,7 +287,7 @@ void curl_global_cleanup(void)
Curl_ssl_cleanup();
Curl_resolver_global_cleanup();
#ifdef WIN32
#ifdef _WIN32
Curl_win32_cleanup(easy_init_flags);
#endif
@@ -752,7 +744,7 @@ static CURLcode easy_perform(struct Curl_easy *data, bool events)
return CURLE_RECURSIVE_API_CALL;
/* Copy the MAXCONNECTS option to the multi handle */
curl_multi_setopt(multi, CURLMOPT_MAXCONNECTS, data->set.maxconnects);
curl_multi_setopt(multi, CURLMOPT_MAXCONNECTS, (long)data->set.maxconnects);
mcode = curl_multi_add_handle(multi, data);
if(mcode) {
@@ -845,8 +837,10 @@ static CURLcode dupset(struct Curl_easy *dst, struct Curl_easy *src)
dst->set = src->set;
Curl_mime_initpart(&dst->set.mimepost);
/* clear all string pointers first */
/* clear all dest string and blob pointers first, in case we error out
mid-function */
memset(dst->set.str, 0, STRING_LAST * sizeof(char *));
memset(dst->set.blobs, 0, BLOB_LAST * sizeof(struct curl_blob *));
/* duplicate all strings */
for(i = (enum dupstring)0; i< STRING_LASTZEROTERMINATED; i++) {
@@ -855,8 +849,6 @@ static CURLcode dupset(struct Curl_easy *dst, struct Curl_easy *src)
return result;
}
/* clear all blob pointers first */
memset(dst->set.blobs, 0, BLOB_LAST * sizeof(struct curl_blob *));
/* duplicate all blobs */
for(j = (enum dupblob)0; j < BLOB_LAST; j++) {
result = Curl_setblobopt(&dst->set.blobs[j], src->set.blobs[j]);
@@ -866,10 +858,13 @@ static CURLcode dupset(struct Curl_easy *dst, struct Curl_easy *src)
/* duplicate memory areas pointed to */
i = STRING_COPYPOSTFIELDS;
if(src->set.postfieldsize && src->set.str[i]) {
/* postfieldsize is curl_off_t, Curl_memdup() takes a size_t ... */
dst->set.str[i] = Curl_memdup(src->set.str[i],
curlx_sotouz(src->set.postfieldsize));
if(src->set.str[i]) {
if(src->set.postfieldsize == -1)
dst->set.str[i] = strdup(src->set.str[i]);
else
/* postfieldsize is curl_off_t, Curl_memdup() takes a size_t ... */
dst->set.str[i] = Curl_memdup(src->set.str[i],
curlx_sotouz(src->set.postfieldsize));
if(!dst->set.str[i])
return CURLE_OUT_OF_MEMORY;
/* point to the new copy */
@@ -919,18 +914,19 @@ struct Curl_easy *curl_easy_duphandle(struct Curl_easy *data)
outcurl->progress.callback = data->progress.callback;
#ifndef CURL_DISABLE_COOKIES
if(data->cookies) {
outcurl->state.cookielist = NULL;
if(data->cookies && data->state.cookie_engine) {
/* If cookies are enabled in the parent handle, we enable them
in the clone as well! */
outcurl->cookies = Curl_cookie_init(data, NULL, outcurl->cookies,
outcurl->cookies = Curl_cookie_init(outcurl, NULL, outcurl->cookies,
data->set.cookiesession);
if(!outcurl->cookies)
goto fail;
}
if(data->set.cookielist) {
outcurl->set.cookielist = Curl_slist_duplicate(data->set.cookielist);
if(!outcurl->set.cookielist)
if(data->state.cookielist) {
outcurl->state.cookielist = Curl_slist_duplicate(data->state.cookielist);
if(!outcurl->state.cookielist)
goto fail;
}
#endif
@@ -976,33 +972,6 @@ struct Curl_easy *curl_easy_duphandle(struct Curl_easy *data)
(void)Curl_hsts_loadcb(outcurl, outcurl->hsts);
}
#endif
/* Clone the resolver handle, if present, for the new handle */
if(Curl_resolver_duphandle(outcurl,
&outcurl->state.async.resolver,
data->state.async.resolver))
goto fail;
#ifdef USE_ARES
{
CURLcode rc;
rc = Curl_set_dns_servers(outcurl, data->set.str[STRING_DNS_SERVERS]);
if(rc && rc != CURLE_NOT_BUILT_IN)
goto fail;
rc = Curl_set_dns_interface(outcurl, data->set.str[STRING_DNS_INTERFACE]);
if(rc && rc != CURLE_NOT_BUILT_IN)
goto fail;
rc = Curl_set_dns_local_ip4(outcurl, data->set.str[STRING_DNS_LOCAL_IP4]);
if(rc && rc != CURLE_NOT_BUILT_IN)
goto fail;
rc = Curl_set_dns_local_ip6(outcurl, data->set.str[STRING_DNS_LOCAL_IP6]);
if(rc && rc != CURLE_NOT_BUILT_IN)
goto fail;
}
#endif /* USE_ARES */
Curl_initinfo(outcurl);
@@ -1016,13 +985,10 @@ fail:
if(outcurl) {
#ifndef CURL_DISABLE_COOKIES
curl_slist_free_all(outcurl->set.cookielist);
outcurl->set.cookielist = NULL;
free(outcurl->cookies);
#endif
Curl_safefree(outcurl->state.buffer);
free(outcurl->state.buffer);
Curl_dyn_free(&outcurl->state.headerb);
Curl_safefree(outcurl->state.url);
Curl_safefree(outcurl->state.referer);
Curl_altsvc_cleanup(&outcurl->asi);
Curl_hsts_cleanup(&outcurl->hsts);
Curl_freeset(outcurl);
+9
View File
@@ -93,6 +93,15 @@ static inline void curl_simple_lock_unlock(curl_simple_lock *lock)
atomic_store_explicit(lock, false, memory_order_release);
}
#elif defined(USE_THREADS_POSIX) && defined(HAVE_PTHREAD_H)
#include <pthread.h>
#define curl_simple_lock pthread_mutex_t
#define CURL_SIMPLE_LOCK_INIT PTHREAD_MUTEX_INITIALIZER
#define curl_simple_lock_lock(m) pthread_mutex_lock(m)
#define curl_simple_lock_unlock(m) pthread_mutex_unlock(m)
#else
#undef GLOBAL_INIT_IS_THREADSAFE
+1 -7
View File
@@ -69,7 +69,7 @@
#include "curl_memory.h"
#include "memdebug.h"
#if defined(WIN32) || defined(MSDOS) || defined(__EMX__)
#if defined(_WIN32) || defined(MSDOS) || defined(__EMX__)
#define DOS_FILESYSTEM 1
#elif defined(__amigaos4__)
#define AMIGA_FILESYSTEM 1
@@ -414,7 +414,6 @@ static CURLcode file_do(struct Curl_easy *data, bool *done)
bool size_known;
bool fstated = FALSE;
char *buf = data->state.buffer;
curl_off_t bytecount = 0;
int fd;
struct FILEPROTO *file;
@@ -563,7 +562,6 @@ static CURLcode file_do(struct Curl_easy *data, bool *done)
if(nread <= 0 || (size_known && (expected_size == 0)))
break;
bytecount += nread;
if(size_known)
expected_size -= nread;
@@ -571,10 +569,6 @@ static CURLcode file_do(struct Curl_easy *data, bool *done)
if(result)
return result;
result = Curl_pgrsSetDownloadCounter(data, bytecount);
if(result)
return result;
if(Curl_pgrsUpdate(data))
result = CURLE_ABORTED_BY_CALLBACK;
else
+59 -18
View File
@@ -39,6 +39,51 @@
#include "curl_memory.h"
#include "memdebug.h"
/*
The dirslash() function breaks a null-terminated pathname string into
directory and filename components then returns the directory component up
to, *AND INCLUDING*, a final '/'. If there is no directory in the path,
this instead returns a "" string.
This function returns a pointer to malloc'ed memory.
The input path to this function is expected to have a file name part.
*/
#ifdef _WIN32
#define PATHSEP "\\"
#define IS_SEP(x) (((x) == '/') || ((x) == '\\'))
#elif defined(MSDOS) || defined(__EMX__) || defined(OS2)
#define PATHSEP "\\"
#define IS_SEP(x) ((x) == '\\')
#else
#define PATHSEP "/"
#define IS_SEP(x) ((x) == '/')
#endif
static char *dirslash(const char *path)
{
size_t n;
struct dynbuf out;
DEBUGASSERT(path);
Curl_dyn_init(&out, CURL_MAX_INPUT_LENGTH);
n = strlen(path);
if(n) {
/* find the rightmost path separator, if any */
while(n && !IS_SEP(path[n-1]))
--n;
/* skip over all the path separators, if any */
while(n && IS_SEP(path[n-1]))
--n;
}
if(Curl_dyn_addn(&out, path, n))
return NULL;
/* if there was a directory, append a single trailing slash */
if(n && Curl_dyn_addn(&out, PATHSEP, 1))
return NULL;
return Curl_dyn_ptr(&out);
}
/*
* Curl_fopen() opens a file for writing with a temp name, to be renamed
* to the final name when completed. If there is an existing file using this
@@ -50,47 +95,44 @@ CURLcode Curl_fopen(struct Curl_easy *data, const char *filename,
FILE **fh, char **tempname)
{
CURLcode result = CURLE_WRITE_ERROR;
unsigned char randsuffix[9];
unsigned char randbuf[41];
char *tempstore = NULL;
struct_stat sb;
int fd = -1;
char *dir = NULL;
*tempname = NULL;
*fh = fopen(filename, FOPEN_WRITETEXT);
if(!*fh)
goto fail;
if(fstat(fileno(*fh), &sb) == -1 || !S_ISREG(sb.st_mode))
if(fstat(fileno(*fh), &sb) == -1 || !S_ISREG(sb.st_mode)) {
return CURLE_OK;
}
fclose(*fh);
*fh = NULL;
result = Curl_rand_alnum(data, randsuffix, sizeof(randsuffix));
result = Curl_rand_alnum(data, randbuf, sizeof(randbuf));
if(result)
goto fail;
tempstore = aprintf("%s.%s.tmp", filename, randsuffix);
dir = dirslash(filename);
if(dir) {
/* The temp file name should not end up too long for the target file
system */
tempstore = aprintf("%s%s.tmp", dir, randbuf);
free(dir);
}
if(!tempstore) {
result = CURLE_OUT_OF_MEMORY;
goto fail;
}
result = CURLE_WRITE_ERROR;
fd = open(tempstore, O_WRONLY | O_CREAT | O_EXCL, 0600);
fd = open(tempstore, O_WRONLY | O_CREAT | O_EXCL, 0600|sb.st_mode);
if(fd == -1)
goto fail;
#ifdef HAVE_FCHMOD
{
struct_stat nsb;
if((fstat(fd, &nsb) != -1) &&
(nsb.st_uid == sb.st_uid) && (nsb.st_gid == sb.st_gid)) {
/* if the user and group are the same, clone the original mode */
if(fchmod(fd, (mode_t)sb.st_mode) == -1)
goto fail;
}
}
#endif
*fh = fdopen(fd, FOPEN_WRITETEXT);
if(!*fh)
goto fail;
@@ -105,7 +147,6 @@ fail:
}
free(tempstore);
return result;
}
+4 -4
View File
@@ -603,9 +603,9 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost,
app passed in a bad combo, so we better check for that first. */
if(form->name) {
/* copy name (without strdup; possibly not null-terminated) */
form->name = Curl_memdup(form->name, form->namelength?
form->namelength:
strlen(form->name) + 1);
form->name = Curl_strndup(form->name, form->namelength?
form->namelength:
strlen(form->name));
}
if(!form->name) {
return_value = CURL_FORMADD_MEMORY;
@@ -792,7 +792,7 @@ static CURLcode setname(curl_mimepart *part, const char *name, size_t len)
/* wrap call to fseeko so it matches the calling convention of callback */
static int fseeko_wrapper(void *stream, curl_off_t offset, int whence)
{
#if defined(HAVE_FSEEKO)
#if defined(HAVE_FSEEKO) && defined(HAVE_DECL_FSEEKO)
return fseeko(stream, (off_t)offset, whence);
#elif defined(HAVE__FSEEKI64)
return _fseeki64(stream, (__int64)offset, whence);
+3 -3
View File
@@ -819,7 +819,7 @@ static int ftp_domore_getsock(struct Curl_easy *data,
DEBUGF(infof(data, "ftp_domore_getsock()"));
if(conn->cfilter[SECONDARYSOCKET]
&& !Curl_conn_is_connected(conn, SECONDARYSOCKET))
return Curl_conn_get_select_socks(data, SECONDARYSOCKET, socks);
return 0;
if(FTP_STOP == ftpc->state) {
int bits = GETSOCK_READSOCK(0);
@@ -947,7 +947,7 @@ static CURLcode ftp_state_use_port(struct Curl_easy *data,
char *port_start = NULL;
char *port_sep = NULL;
addr = calloc(addrlen + 1, 1);
addr = calloc(1, addrlen + 1);
if(!addr) {
result = CURLE_OUT_OF_MEMORY;
goto out;
@@ -4380,7 +4380,7 @@ static CURLcode ftp_setup_connection(struct Curl_easy *data,
CURLcode result = CURLE_OK;
struct ftp_conn *ftpc = &conn->proto.ftpc;
ftp = calloc(sizeof(struct FTP), 1);
ftp = calloc(1, sizeof(struct FTP));
if(!ftp)
return CURLE_OUT_OF_MEMORY;
-3
View File
@@ -55,9 +55,6 @@
/* The last #include file should be: */
#include "memdebug.h"
/* allocs buffer which will contain one line of LIST command response */
#define FTP_BUFFER_ALLOCSIZE 160
typedef enum {
PL_UNIX_TOTALSIZE = 0,
PL_UNIX_FILETYPE,
+1 -1
View File
@@ -38,7 +38,7 @@
2. For systems with config-*.h files, define them there.
*/
#ifdef WIN32
#ifdef _WIN32
/* int recv(SOCKET, char *, int, int) */
#define RECV_TYPE_ARG1 SOCKET
#define RECV_TYPE_ARG2 char *
+3 -2
View File
@@ -31,10 +31,11 @@
static char *GetEnv(const char *variable)
{
#if defined(_WIN32_WCE) || defined(CURL_WINDOWS_APP)
#if defined(_WIN32_WCE) || defined(CURL_WINDOWS_APP) || \
defined(__ORBIS__) || defined(__PROSPERO__) /* PlayStation 4 and 5 */
(void)variable;
return NULL;
#elif defined(WIN32)
#elif defined(_WIN32)
/* This uses Windows API instead of C runtime getenv() to get the environment
variable since some changes aren't always visible to the latter. #4774 */
char *buf = NULL;
+6 -5
View File
@@ -67,10 +67,11 @@ CURLcode Curl_addrinfo_callback(struct Curl_easy *data,
int status,
struct Curl_addrinfo *ai)
{
struct connectdata *conn = data->conn;
struct Curl_dns_entry *dns = NULL;
CURLcode result = CURLE_OK;
data->state.async.status = status;
conn->resolve_async.status = status;
if(CURL_ASYNC_SUCCESS == status) {
if(ai) {
@@ -78,8 +79,8 @@ CURLcode Curl_addrinfo_callback(struct Curl_easy *data,
Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);
dns = Curl_cache_addr(data, ai,
data->state.async.hostname, 0,
data->state.async.port);
conn->resolve_async.hostname, 0,
conn->resolve_async.port);
if(data->share)
Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
@@ -94,12 +95,12 @@ CURLcode Curl_addrinfo_callback(struct Curl_easy *data,
}
}
data->state.async.dns = dns;
conn->resolve_async.dns = dns;
/* Set async.done TRUE last in this function since it may be used multi-
threaded and once this is TRUE the other thread may read fields from the
async struct */
data->state.async.done = TRUE;
conn->resolve_async.done = TRUE;
/* IPv4: The input hostent struct will be freed by ares when we return from
this function */
+101 -14
View File
@@ -117,6 +117,13 @@
static void freednsentry(void *freethis);
#ifndef CURL_DISABLE_VERBOSE_STRINGS
static void show_resolve_info(struct Curl_easy *data,
struct Curl_dns_entry *dns);
#else
#define show_resolve_info(x,y) Curl_nop_stmt
#endif
/*
* Curl_printable_address() stores a printable version of the 1st address
* given in the 'ai' argument. The result will be stored in the buf that is
@@ -481,9 +488,11 @@ Curl_cache_addr(struct Curl_easy *data,
return NULL;
}
#endif
if(!hostlen)
hostlen = strlen(hostname);
/* Create a new cache entry */
dns = calloc(1, sizeof(struct Curl_dns_entry));
dns = calloc(1, sizeof(struct Curl_dns_entry) + hostlen);
if(!dns) {
return NULL;
}
@@ -497,6 +506,9 @@ Curl_cache_addr(struct Curl_easy *data,
time(&dns->timestamp);
if(dns->timestamp == 0)
dns->timestamp = 1; /* zero indicates permanent CURLOPT_RESOLVE entry */
dns->hostport = port;
if(hostlen)
memcpy(dns->hostname, hostname, hostlen);
/* Store the resolved data in our DNS cache. */
dns2 = Curl_hash_add(data->dns.hostcache, entry_id, entry_len + 1,
@@ -521,7 +533,7 @@ static struct Curl_addrinfo *get_localhost6(int port, const char *name)
struct sockaddr_in6 sa6;
unsigned char ipv6[16];
unsigned short port16 = (unsigned short)(port & 0xffff);
ca = calloc(sizeof(struct Curl_addrinfo) + ss_size + hostlen + 1, 1);
ca = calloc(1, sizeof(struct Curl_addrinfo) + ss_size + hostlen + 1);
if(!ca)
return NULL;
@@ -568,7 +580,7 @@ static struct Curl_addrinfo *get_localhost(int port, const char *name)
return NULL;
memcpy(&sa.sin_addr, &ipv4, sizeof(ipv4));
ca = calloc(sizeof(struct Curl_addrinfo) + ss_size + hostlen + 1, 1);
ca = calloc(1, sizeof(struct Curl_addrinfo) + ss_size + hostlen + 1);
if(!ca)
return NULL;
ca->ai_flags = 0;
@@ -729,7 +741,7 @@ enum resolve_t Curl_resolv(struct Curl_easy *data,
Curl_set_in_callback(data, true);
st = data->set.resolver_start(
#ifdef USE_CURL_ASYNC
data->state.async.resolver,
conn->resolve_async.resolver,
#else
NULL,
#endif
@@ -823,8 +835,10 @@ enum resolve_t Curl_resolv(struct Curl_easy *data,
if(!dns)
/* returned failure, bail out nicely */
Curl_freeaddrinfo(addr);
else
else {
rc = CURLRESOLV_RESOLVED;
show_resolve_info(data, dns);
}
}
}
@@ -839,7 +853,7 @@ enum resolve_t Curl_resolv(struct Curl_easy *data,
* execution. This effectively causes the remainder of the application to run
* within a signal handler which is nonportable and could lead to problems.
*/
static
CURL_NORETURN static
void alarmfunc(int sig)
{
(void)sig;
@@ -1269,9 +1283,11 @@ err:
Curl_freeaddrinfo(head);
return CURLE_OUT_OF_MEMORY;
}
#ifndef CURL_DISABLE_VERBOSE_STRINGS
infof(data, "Added %.*s:%d:%s to DNS cache%s",
(int)hlen, host_begin, port, addresses,
permanent ? "" : " (non-permanent)");
#endif
/* Wildcard hostname */
if((hlen == 1) && (host_begin[0] == '*')) {
@@ -1285,18 +1301,89 @@ err:
return CURLE_OK;
}
#ifndef CURL_DISABLE_VERBOSE_STRINGS
static void show_resolve_info(struct Curl_easy *data,
struct Curl_dns_entry *dns)
{
struct Curl_addrinfo *a;
CURLcode result = CURLE_OK;
#ifdef CURLRES_IPV6
struct dynbuf out[2];
#else
struct dynbuf out[1];
#endif
DEBUGASSERT(data);
DEBUGASSERT(dns);
if(!data->set.verbose ||
/* ignore no name or numerical IP addresses */
!dns->hostname[0] || Curl_host_is_ipnum(dns->hostname))
return;
a = dns->addr;
infof(data, "Host %s:%d was resolved.",
(dns->hostname[0] ? dns->hostname : "(none)"), dns->hostport);
Curl_dyn_init(&out[0], 1024);
#ifdef CURLRES_IPV6
Curl_dyn_init(&out[1], 1024);
#endif
while(a) {
if(
#ifdef CURLRES_IPV6
a->ai_family == PF_INET6 ||
#endif
a->ai_family == PF_INET) {
char buf[MAX_IPADR_LEN];
struct dynbuf *d = &out[(a->ai_family != PF_INET)];
Curl_printable_address(a, buf, sizeof(buf));
if(Curl_dyn_len(d))
result = Curl_dyn_addn(d, ", ", 2);
if(!result)
result = Curl_dyn_add(d, buf);
if(result) {
infof(data, "too many IP, can't show");
goto fail;
}
}
a = a->ai_next;
}
#ifdef CURLRES_IPV6
infof(data, "IPv6: %s",
(Curl_dyn_len(&out[1]) ? Curl_dyn_ptr(&out[1]) : "(none)"));
#endif
infof(data, "IPv4: %s",
(Curl_dyn_len(&out[0]) ? Curl_dyn_ptr(&out[0]) : "(none)"));
fail:
Curl_dyn_free(&out[0]);
#ifdef CURLRES_IPV6
Curl_dyn_free(&out[1]);
#endif
}
#endif
CURLcode Curl_resolv_check(struct Curl_easy *data,
struct Curl_dns_entry **dns)
{
CURLcode result;
#if defined(CURL_DISABLE_DOH) && !defined(CURLRES_ASYNCH)
(void)data;
(void)dns;
#endif
#ifndef CURL_DISABLE_DOH
if(data->conn->bits.doh)
return Curl_doh_is_resolved(data, dns);
if(data->conn->bits.doh) {
result = Curl_doh_is_resolved(data, dns);
}
else
#endif
return Curl_resolver_is_resolved(data, dns);
result = Curl_resolver_is_resolved(data, dns);
if(*dns)
show_resolve_info(data, *dns);
return result;
}
int Curl_resolv_getsock(struct Curl_easy *data,
@@ -1328,9 +1415,9 @@ CURLcode Curl_once_resolved(struct Curl_easy *data, bool *protocol_done)
struct connectdata *conn = data->conn;
#ifdef USE_CURL_ASYNC
if(data->state.async.dns) {
conn->dns_entry = data->state.async.dns;
data->state.async.dns = NULL;
if(conn->resolve_async.dns) {
conn->dns_entry = conn->resolve_async.dns;
conn->resolve_async.dns = NULL;
}
#endif
@@ -1352,11 +1439,11 @@ CURLcode Curl_once_resolved(struct Curl_easy *data, bool *protocol_done)
#ifdef USE_CURL_ASYNC
CURLcode Curl_resolver_error(struct Curl_easy *data)
{
struct connectdata *conn = data->conn;
const char *host_or_proxy;
CURLcode result;
#ifndef CURL_DISABLE_PROXY
struct connectdata *conn = data->conn;
if(conn->bits.httpproxy) {
host_or_proxy = "proxy";
result = CURLE_COULDNT_RESOLVE_PROXY;
@@ -1369,7 +1456,7 @@ CURLcode Curl_resolver_error(struct Curl_easy *data)
}
failf(data, "Could not resolve %s: %s", host_or_proxy,
data->state.async.hostname);
conn->resolve_async.hostname);
return result;
}
+4
View File
@@ -64,6 +64,10 @@ struct Curl_dns_entry {
time_t timestamp;
/* use-counter, use Curl_resolv_unlock to release reference */
long inuse;
/* hostname port number that resolved to addr. */
int hostport;
/* hostname that resolved to addr. may be NULL (unix domain sockets). */
char hostname[1];
};
bool Curl_host_is_ipnum(const char *hostname);
+3 -4
View File
@@ -71,8 +71,7 @@ bool Curl_ipvalid(struct Curl_easy *data, struct connectdata *conn)
#if defined(CURLRES_SYNCH)
#ifdef DEBUG_ADDRINFO
static void dump_addrinfo(struct connectdata *conn,
const struct Curl_addrinfo *ai)
static void dump_addrinfo(const struct Curl_addrinfo *ai)
{
printf("dump_addrinfo:\n");
for(; ai; ai = ai->ai_next) {
@@ -84,7 +83,7 @@ static void dump_addrinfo(struct connectdata *conn,
}
}
#else
#define dump_addrinfo(x,y) Curl_nop_stmt
#define dump_addrinfo(x) Curl_nop_stmt
#endif
/*
@@ -149,7 +148,7 @@ struct Curl_addrinfo *Curl_getaddrinfo(struct Curl_easy *data,
Curl_addrinfo_set_port(res, port);
}
dump_addrinfo(conn, res);
dump_addrinfo(res);
return res;
}
+18 -10
View File
@@ -40,6 +40,7 @@
#include "fopen.h"
#include "rename.h"
#include "share.h"
#include "strdup.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
@@ -76,7 +77,7 @@ static time_t hsts_debugtime(void *unused)
struct hsts *Curl_hsts_init(void)
{
struct hsts *h = calloc(sizeof(struct hsts), 1);
struct hsts *h = calloc(1, sizeof(struct hsts));
if(h) {
Curl_llist_init(&h->list, NULL);
}
@@ -108,7 +109,7 @@ void Curl_hsts_cleanup(struct hsts **hp)
static struct stsentry *hsts_entry(void)
{
return calloc(sizeof(struct stsentry), 1);
return calloc(1, sizeof(struct stsentry));
}
static CURLcode hsts_create(struct hsts *h,
@@ -116,23 +117,30 @@ static CURLcode hsts_create(struct hsts *h,
bool subdomains,
curl_off_t expires)
{
struct stsentry *sts = hsts_entry();
struct stsentry *sts;
char *duphost;
size_t hlen;
DEBUGASSERT(h);
DEBUGASSERT(hostname);
hlen = strlen(hostname);
if(hlen && (hostname[hlen - 1] == '.'))
/* strip off any trailing dot */
--hlen;
if(!hlen)
/* no host name left */
return CURLE_BAD_FUNCTION_ARGUMENT;
sts = hsts_entry();
if(!sts)
return CURLE_OUT_OF_MEMORY;
duphost = strdup(hostname);
duphost = Curl_strndup(hostname, hlen);
if(!duphost) {
free(sts);
return CURLE_OUT_OF_MEMORY;
}
hlen = strlen(duphost);
if(duphost[hlen - 1] == '.')
/* strip off trailing any dot */
duphost[--hlen] = 0;
sts->host = duphost;
sts->expires = expires;
sts->includeSubDomains = subdomains;
@@ -564,7 +572,7 @@ CURLcode Curl_hsts_loadcb(struct Curl_easy *data, struct hsts *h)
void Curl_hsts_loadfiles(struct Curl_easy *data)
{
struct curl_slist *l = data->set.hstslist;
struct curl_slist *l = data->state.hstslist;
if(l) {
Curl_share_lock(data, CURL_LOCK_DATA_HSTS, CURL_LOCK_ACCESS_SINGLE);
+107 -129
View File
@@ -836,6 +836,7 @@ output_auth_headers(struct Curl_easy *data,
(data->state.aptr.user ?
data->state.aptr.user : ""));
#else
(void)proxy;
infof(data, "Server auth using %s with user '%s'",
auth, data->state.aptr.user ?
data->state.aptr.user : "");
@@ -845,7 +846,7 @@ output_auth_headers(struct Curl_easy *data,
else
authstatus->multipass = FALSE;
return CURLE_OK;
return result;
}
/**
@@ -970,17 +971,21 @@ Curl_http_output_auth(struct Curl_easy *data,
}
#endif
#if defined(USE_SPNEGO) || defined(USE_NTLM) || \
!defined(CURL_DISABLE_DIGEST_AUTH) || \
!defined(CURL_DISABLE_BASIC_AUTH) || \
!defined(CURL_DISABLE_BEARER_AUTH)
static int is_valid_auth_separator(char ch)
{
return ch == '\0' || ch == ',' || ISSPACE(ch);
}
#endif
/*
* Curl_http_input_auth() deals with Proxy-Authenticate: and WWW-Authenticate:
* headers. They are dealt with both in the transfer.c main loop and in the
* proxy CONNECT loop.
*/
static int is_valid_auth_separator(char ch)
{
return ch == '\0' || ch == ',' || ISSPACE(ch);
}
CURLcode Curl_http_input_auth(struct Curl_easy *data, bool proxy,
const char *auth) /* the first non-space */
{
@@ -992,11 +997,15 @@ CURLcode Curl_http_input_auth(struct Curl_easy *data, bool proxy,
curlnegotiate *negstate = proxy ? &conn->proxy_negotiate_state :
&conn->http_negotiate_state;
#endif
#if defined(USE_SPNEGO) || \
defined(USE_NTLM) || \
!defined(CURL_DISABLE_DIGEST_AUTH) || \
!defined(CURL_DISABLE_BASIC_AUTH) || \
!defined(CURL_DISABLE_BEARER_AUTH)
unsigned long *availp;
struct auth *authp;
(void) conn; /* In case conditionals make it unused. */
if(proxy) {
availp = &data->info.proxyauthavail;
authp = &data->state.authproxy;
@@ -1005,6 +1014,11 @@ CURLcode Curl_http_input_auth(struct Curl_easy *data, bool proxy,
availp = &data->info.httpauthavail;
authp = &data->state.authhost;
}
#else
(void) proxy;
#endif
(void) conn; /* In case conditionals make it unused. */
/*
* Here we check if we want the specific single authentication (using ==) and
@@ -1140,7 +1154,14 @@ CURLcode Curl_http_input_auth(struct Curl_easy *data, bool proxy,
}
}
#else
;
{
/*
* Empty block to terminate the if-else chain correctly.
*
* A semicolon would yield the same result here, but can cause a
* compiler warning when -Wextra is enabled.
*/
}
#endif
/* there may be multiple methods on one line, so keep reading */
@@ -1403,7 +1424,7 @@ CURLcode Curl_buffer_send(struct dynbuf *in,
* and install our own `data->state.fread_func` that
* on subsequent calls reads `in` empty.
* - when the whisked away `in` is empty, the `fread_func`
* is restored ot its original state.
* is restored to its original state.
* The problem is that `fread_func` can only return
* `upload_buffer_size` lengths. If the send we do here
* is larger and blocks, we do re-sending with smaller
@@ -1678,8 +1699,6 @@ static CURLcode expect100(struct Curl_easy *data,
struct dynbuf *req)
{
CURLcode result = CURLE_OK;
data->state.expect100header = FALSE; /* default to false unless it is set
to TRUE below */
if(!data->state.disableexpect && Curl_use_http_1_1plus(data, conn) &&
(conn->httpversion < 20)) {
/* if not doing HTTP 1.0 or version 2, or disabled explicitly, we add an
@@ -2414,14 +2433,16 @@ CURLcode Curl_http_body(struct Curl_easy *data, struct connectdata *conn,
/* Convert the form structure into a mime structure, then keep
the conversion */
if(!data->state.formp) {
data->state.formp = calloc(sizeof(curl_mimepart), 1);
data->state.formp = calloc(1, sizeof(curl_mimepart));
if(!data->state.formp)
return CURLE_OUT_OF_MEMORY;
Curl_mime_cleanpart(data->state.formp);
result = Curl_getformdata(data, data->state.formp, data->set.httppost,
data->state.fread_func);
if(result)
if(result) {
Curl_safefree(data->state.formp);
return result;
}
data->state.mimepost = data->state.formp;
}
break;
@@ -2494,6 +2515,29 @@ CURLcode Curl_http_body(struct Curl_easy *data, struct connectdata *conn,
return result;
}
static CURLcode addexpect(struct Curl_easy *data, struct connectdata *conn,
struct dynbuf *r)
{
data->state.expect100header = FALSE;
/* Avoid Expect: 100-continue if Upgrade: is used */
if(data->req.upgr101 == UPGR101_INIT) {
struct HTTP *http = data->req.p.http;
/* For really small puts we don't use Expect: headers at all, and for
the somewhat bigger ones we allow the app to disable it. Just make
sure that the expect100header is always set to the preferred value
here. */
char *ptr = Curl_checkheaders(data, STRCONST("Expect"));
if(ptr) {
data->state.expect100header =
Curl_compareheader(ptr, STRCONST("Expect:"),
STRCONST("100-continue"));
}
else if(http->postsize > EXPECT_100_THRESHOLD || http->postsize < 0)
return expect100(data, conn, r);
}
return CURLE_OK;
}
CURLcode Curl_http_bodysend(struct Curl_easy *data, struct connectdata *conn,
struct dynbuf *r, Curl_HttpReq httpreq)
{
@@ -2506,14 +2550,8 @@ CURLcode Curl_http_bodysend(struct Curl_easy *data, struct connectdata *conn,
#endif
CURLcode result = CURLE_OK;
struct HTTP *http = data->req.p.http;
const char *ptr;
/* If 'authdone' is FALSE, we must not set the write socket index to the
Curl_transfer() call below, as we're not ready to actually upload any
data yet. */
switch(httpreq) {
case HTTPREQ_PUT: /* Let's PUT the data to the server! */
if(conn->bits.authneg)
@@ -2531,20 +2569,9 @@ CURLcode Curl_http_bodysend(struct Curl_easy *data, struct connectdata *conn,
return result;
}
/* For really small puts we don't use Expect: headers at all, and for
the somewhat bigger ones we allow the app to disable it. Just make
sure that the expect100header is always set to the preferred value
here. */
ptr = Curl_checkheaders(data, STRCONST("Expect"));
if(ptr) {
data->state.expect100header =
Curl_compareheader(ptr, STRCONST("Expect:"), STRCONST("100-continue"));
}
else if(http->postsize > EXPECT_100_THRESHOLD || http->postsize < 0) {
result = expect100(data, conn, r);
if(result)
return result;
}
result = addexpect(data, conn, r);
if(result)
return result;
/* end of headers */
result = Curl_dyn_addn(r, STRCONST("\r\n"));
@@ -2617,22 +2644,9 @@ CURLcode Curl_http_bodysend(struct Curl_easy *data, struct connectdata *conn,
}
#endif
/* For really small posts we don't use Expect: headers at all, and for
the somewhat bigger ones we allow the app to disable it. Just make
sure that the expect100header is always set to the preferred value
here. */
ptr = Curl_checkheaders(data, STRCONST("Expect"));
if(ptr) {
data->state.expect100header =
Curl_compareheader(ptr, STRCONST("Expect:"), STRCONST("100-continue"));
}
else if(http->postsize > EXPECT_100_THRESHOLD || http->postsize < 0) {
result = expect100(data, conn, r);
if(result)
return result;
}
else
data->state.expect100header = FALSE;
result = addexpect(data, conn, r);
if(result)
return result;
/* make the request end in a true CRLF */
result = Curl_dyn_addn(r, STRCONST("\r\n"));
@@ -2692,22 +2706,9 @@ CURLcode Curl_http_bodysend(struct Curl_easy *data, struct connectdata *conn,
return result;
}
/* For really small posts we don't use Expect: headers at all, and for
the somewhat bigger ones we allow the app to disable it. Just make
sure that the expect100header is always set to the preferred value
here. */
ptr = Curl_checkheaders(data, STRCONST("Expect"));
if(ptr) {
data->state.expect100header =
Curl_compareheader(ptr, STRCONST("Expect:"), STRCONST("100-continue"));
}
else if(http->postsize > EXPECT_100_THRESHOLD || http->postsize < 0) {
result = expect100(data, conn, r);
if(result)
return result;
}
else
data->state.expect100header = FALSE;
result = addexpect(data, conn, r);
if(result)
return result;
#ifndef USE_HYPER
/* With Hyper the body is always passed on separately */
@@ -3193,7 +3194,7 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
DEBUGASSERT(Curl_conn_is_http2(data, conn, FIRSTSOCKET));
break;
case CURL_HTTP_VERSION_1_1:
/* continue with HTTP/1.1 when explicitly requested */
/* continue with HTTP/1.x when explicitly requested */
break;
default:
/* Check if user wants to use HTTP/2 with clear TCP */
@@ -3685,7 +3686,7 @@ CURLcode Curl_http_header(struct Curl_easy *data, struct connectdata *conn,
k->content_range = TRUE;
}
}
else
else if(k->httpcode < 300)
data->state.resume_from = 0; /* get everything */
}
#if !defined(CURL_DISABLE_COOKIES)
@@ -3996,35 +3997,30 @@ CURLcode Curl_bump_headersize(struct Curl_easy *data,
*/
CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
struct connectdata *conn,
ssize_t *nread,
bool *stop_reading)
const char *buf, size_t blen,
size_t *pconsumed)
{
CURLcode result;
struct SingleRequest *k = &data->req;
ssize_t onread = *nread;
char *ostr = k->str;
char *headp;
char *str_start;
char *end_ptr;
/* header line within buffer loop */
*pconsumed = 0;
do {
size_t rest_length;
size_t full_length;
size_t line_length;
int writetype;
/* str_start is start of line within buf */
str_start = k->str;
/* data is in network encoding so use 0x0a instead of '\n' */
end_ptr = memchr(str_start, 0x0a, *nread);
end_ptr = memchr(buf, 0x0a, blen);
if(!end_ptr) {
/* Not a complete header line within buffer, append the data to
the end of the headerbuff. */
result = Curl_dyn_addn(&data->state.headerb, str_start, *nread);
result = Curl_dyn_addn(&data->state.headerb, buf, blen);
if(result)
return result;
*pconsumed += blen;
if(!k->headerline) {
/* check if this looks like a protocol header */
@@ -4036,31 +4032,28 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
if(st == STATUS_BAD) {
/* this is not the beginning of a protocol first header line */
k->header = FALSE;
k->badheader = HEADER_ALLBAD;
k->badheader = TRUE;
streamclose(conn, "bad HTTP: No end-of-message indicator");
if(!data->set.http09_allowed) {
failf(data, "Received HTTP/0.9 when not allowed");
return CURLE_UNSUPPORTED_PROTOCOL;
}
break;
goto out;
}
}
break; /* read more and try again */
goto out; /* read more and try again */
}
/* decrease the size of the remaining (supposed) header line */
rest_length = (end_ptr - k->str) + 1;
*nread -= (ssize_t)rest_length;
k->str = end_ptr + 1; /* move past new line */
full_length = k->str - str_start;
result = Curl_dyn_addn(&data->state.headerb, str_start, full_length);
line_length = (end_ptr - buf) + 1;
result = Curl_dyn_addn(&data->state.headerb, buf, line_length);
if(result)
return result;
blen -= line_length;
buf += line_length;
*pconsumed += line_length;
/****
* We now have a FULL header line in 'headerb'.
*****/
@@ -4078,14 +4071,12 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
return CURLE_UNSUPPORTED_PROTOCOL;
}
k->header = FALSE;
if(*nread)
if(blen)
/* since there's more, this is a partial bad header */
k->badheader = HEADER_PARTHEADER;
k->badheader = TRUE;
else {
/* this was all we read so it's all a bad header */
k->badheader = HEADER_ALLBAD;
*nread = onread;
k->str = ostr;
k->badheader = TRUE;
return CURLE_OK;
}
break;
@@ -4139,22 +4130,23 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
/* switch to http2 now. The bytes after response headers
are also processed here, otherwise they are lost. */
result = Curl_http2_upgrade(data, conn, FIRSTSOCKET,
k->str, *nread);
result = Curl_http2_upgrade(data, conn, FIRSTSOCKET, buf, blen);
if(result)
return result;
*nread = 0;
*pconsumed += blen;
blen = 0;
}
#ifdef USE_WEBSOCKETS
else if(k->upgr101 == UPGR101_WS) {
/* verify the response */
result = Curl_ws_accept(data, k->str, *nread);
result = Curl_ws_accept(data, buf, blen);
if(result)
return result;
k->header = FALSE; /* no more header to parse! */
if(data->set.connect_only) {
k->keepon &= ~KEEP_RECV; /* read no more content */
*nread = 0;
*pconsumed += blen;
blen = 0;
}
}
#endif
@@ -4366,7 +4358,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
* out and return home.
*/
if(data->req.no_body)
*stop_reading = TRUE;
k->download_done = TRUE;
#ifndef CURL_DISABLE_RTSP
else if((conn->handler->protocol & CURLPROTO_RTSP) &&
(data->set.rtspreq == RTSPREQ_DESCRIBE) &&
@@ -4375,7 +4367,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
absent, a length 0 must be assumed. It will prevent libcurl from
hanging on DESCRIBE request that got refused for whatever
reason */
*stop_reading = TRUE;
k->download_done = TRUE;
#endif
/* If max download size is *zero* (nothing) we already have
@@ -4386,15 +4378,12 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
if(0 == k->maxdownload
&& !Curl_conn_is_http2(data, conn, FIRSTSOCKET)
&& !Curl_conn_is_http3(data, conn, FIRSTSOCKET))
*stop_reading = TRUE;
k->download_done = TRUE;
if(*stop_reading) {
/* we make sure that this socket isn't read more now */
k->keepon &= ~KEEP_RECV;
}
Curl_debug(data, CURLINFO_HEADER_IN, str_start, headerlen);
break; /* exit header line loop */
Curl_debug(data, CURLINFO_HEADER_IN,
Curl_dyn_ptr(&data->state.headerb),
Curl_dyn_len(&data->state.headerb));
goto out; /* exit header line loop */
}
/* We continue reading headers, reset the line-based header */
@@ -4583,12 +4572,12 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
Curl_dyn_reset(&data->state.headerb);
}
while(*k->str); /* header line within buffer */
while(blen);
/* We might have reached the end of the header part here, but
there might be a non-header part left in the end of the read
buffer. */
out:
return CURLE_OK;
}
@@ -4618,17 +4607,6 @@ out:
return result;
}
/* simple implementation of strndup(), which isn't portable */
static char *my_strndup(const char *ptr, size_t len)
{
char *copy = malloc(len + 1);
if(!copy)
return NULL;
memcpy(copy, ptr, len);
copy[len] = '\0';
return copy;
}
CURLcode Curl_http_req_make(struct httpreq **preq,
const char *method, size_t m_len,
const char *scheme, size_t s_len,
@@ -4647,17 +4625,17 @@ CURLcode Curl_http_req_make(struct httpreq **preq,
goto out;
memcpy(req->method, method, m_len);
if(scheme) {
req->scheme = my_strndup(scheme, s_len);
req->scheme = Curl_strndup(scheme, s_len);
if(!req->scheme)
goto out;
}
if(authority) {
req->authority = my_strndup(authority, a_len);
req->authority = Curl_strndup(authority, a_len);
if(!req->authority)
goto out;
}
if(path) {
req->path = my_strndup(path, p_len);
req->path = Curl_strndup(path, p_len);
if(!req->path)
goto out;
}
+3 -3
View File
@@ -227,8 +227,8 @@ CURLcode Curl_http_size(struct Curl_easy *data);
CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
struct connectdata *conn,
ssize_t *nread,
bool *stop_reading);
const char *buf, size_t blen,
size_t *pconsumed);
/**
* Curl_http_output_auth() setups the authentication headers for the
@@ -263,7 +263,7 @@ CURLcode Curl_http_decode_status(int *pstatus, const char *s, size_t len);
* All about a core HTTP request, excluding body and trailers
*/
struct httpreq {
char method[12];
char method[24];
char *scheme;
char *authority;
char *path;
+54 -78
View File
@@ -107,14 +107,14 @@ static int populate_settings(nghttp2_settings_entry *iv,
return 3;
}
static size_t populate_binsettings(uint8_t *binsettings,
struct Curl_easy *data)
static ssize_t populate_binsettings(uint8_t *binsettings,
struct Curl_easy *data)
{
nghttp2_settings_entry iv[H2_SETTINGS_IV_LEN];
int ivlen;
ivlen = populate_settings(iv, data);
/* this returns number of bytes it wrote */
/* this returns number of bytes it wrote or a negative number on error. */
return nghttp2_pack_settings_payload(binsettings, H2_BINSETTINGS_LEN,
iv, ivlen);
}
@@ -369,12 +369,15 @@ static ssize_t nw_out_writer(void *writer_ctx,
{
struct Curl_cfilter *cf = writer_ctx;
struct Curl_easy *data = CF_DATA_CURRENT(cf);
ssize_t nwritten;
nwritten = Curl_conn_cf_send(cf->next, data, (const char *)buf, buflen, err);
if(nwritten > 0)
CURL_TRC_CF(data, cf, "[0] egress: wrote %zd bytes", nwritten);
return nwritten;
if(data) {
ssize_t nwritten = Curl_conn_cf_send(cf->next, data,
(const char *)buf, buflen, err);
if(nwritten > 0)
CURL_TRC_CF(data, cf, "[0] egress: wrote %zd bytes", nwritten);
return nwritten;
}
return 0;
}
static ssize_t send_callback(nghttp2_session *h2,
@@ -452,9 +455,14 @@ static CURLcode cf_h2_ctx_init(struct Curl_cfilter *cf,
* in the H1 request and we upgrade from there. This stream
* is opened implicitly as #1. */
uint8_t binsettings[H2_BINSETTINGS_LEN];
size_t binlen; /* length of the binsettings data */
ssize_t binlen; /* length of the binsettings data */
binlen = populate_binsettings(binsettings, data);
if(binlen <= 0) {
failf(data, "nghttp2 unexpectedly failed on pack_settings_payload");
result = CURLE_FAILED_INIT;
goto out;
}
result = http2_data_setup(cf, data, &stream);
if(result)
@@ -1076,16 +1084,11 @@ static CURLcode on_stream_frame(struct Curl_cfilter *cf,
stream->reset = TRUE;
}
stream->send_closed = TRUE;
data->req.keepon &= ~KEEP_SEND_HOLD;
drain_stream(cf, data, stream);
break;
case NGHTTP2_WINDOW_UPDATE:
if((data->req.keepon & KEEP_SEND_HOLD) &&
(data->req.keepon & KEEP_SEND)) {
data->req.keepon &= ~KEEP_SEND_HOLD;
if(CURL_WANT_SEND(data)) {
drain_stream(cf, data, stream);
CURL_TRC_CF(data, cf, "[%d] un-holding after win update",
stream_id);
}
break;
default:
@@ -1230,15 +1233,10 @@ static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame,
* window and *assume* that we treat this like a WINDOW_UPDATE. Some
* servers send an explicit WINDOW_UPDATE, but not all seem to do that.
* To be safe, we UNHOLD a stream in order not to stall. */
if((data->req.keepon & KEEP_SEND_HOLD) &&
(data->req.keepon & KEEP_SEND)) {
if(CURL_WANT_SEND(data)) {
struct stream_ctx *stream = H2_STREAM_CTX(data);
data->req.keepon &= ~KEEP_SEND_HOLD;
if(stream) {
if(stream)
drain_stream(cf, data, stream);
CURL_TRC_CF(data, cf, "[%d] un-holding after SETTINGS",
stream_id);
}
}
}
break;
@@ -1338,7 +1336,6 @@ static int on_stream_close(nghttp2_session *session, int32_t stream_id,
stream->error = error_code;
if(stream->error)
stream->reset = TRUE;
data_s->req.keepon &= ~KEEP_SEND_HOLD;
if(stream->error)
CURL_TRC_CF(data_s, cf, "[%d] RESET: %s (err %d)",
@@ -1602,10 +1599,10 @@ static int error_callback(nghttp2_session *session,
size_t len,
void *userp)
{
struct Curl_cfilter *cf = userp;
struct Curl_easy *data = CF_DATA_CURRENT(cf);
(void)session;
(void)msg;
(void)len;
(void)userp;
failf(data, "%.*s", (int)len, msg);
return 0;
}
#endif
@@ -1621,7 +1618,7 @@ CURLcode Curl_http2_request_upgrade(struct dynbuf *req,
size_t blen;
struct SingleRequest *k = &data->req;
uint8_t binsettings[H2_BINSETTINGS_LEN];
size_t binlen; /* length of the binsettings data */
ssize_t binlen; /* length of the binsettings data */
binlen = populate_binsettings(binsettings, data);
if(binlen <= 0) {
@@ -2052,23 +2049,13 @@ static ssize_t h2_submit(struct stream_ctx **pstream,
/* no longer needed */
Curl_h1_req_parse_free(&stream->h1);
nheader = Curl_dynhds_count(&h2_headers);
nva = malloc(sizeof(nghttp2_nv) * nheader);
nva = Curl_dynhds_to_nva(&h2_headers, &nheader);
if(!nva) {
*err = CURLE_OUT_OF_MEMORY;
nwritten = -1;
goto out;
}
for(i = 0; i < nheader; ++i) {
struct dynhds_entry *e = Curl_dynhds_getn(&h2_headers, i);
nva[i].name = (unsigned char *)e->name;
nva[i].namelen = e->namelen;
nva[i].value = (unsigned char *)e->value;
nva[i].valuelen = e->valuelen;
nva[i].flags = NGHTTP2_NV_FLAG_NONE;
}
h2_pri_spec(data, &pri_spec);
if(!nghttp2_session_check_request_allowed(ctx->h2))
CURL_TRC_CF(data, cf, "send request NOT allowed (via nghttp2)");
@@ -2272,14 +2259,6 @@ static ssize_t cf_h2_send(struct Curl_cfilter *cf, struct Curl_easy *data,
* frame buffer or our network out buffer. */
size_t rwin = nghttp2_session_get_stream_remote_window_size(ctx->h2,
stream->id);
if(rwin == 0) {
/* H2 flow window exhaustion. We need to HOLD upload until we get
* a WINDOW_UPDATE from the server. */
data->req.keepon |= KEEP_SEND_HOLD;
CURL_TRC_CF(data, cf, "[%d] holding send as remote flow "
"window is exhausted", stream->id);
}
/* Whatever the cause, we need to return CURL_EAGAIN for this call.
* We have unwritten state that needs us being invoked again and EAGAIN
* is the only way to ensure that. */
@@ -2331,38 +2310,34 @@ out:
return nwritten;
}
static int cf_h2_get_select_socks(struct Curl_cfilter *cf,
struct Curl_easy *data,
curl_socket_t *sock)
static void cf_h2_adjust_pollset(struct Curl_cfilter *cf,
struct Curl_easy *data,
struct easy_pollset *ps)
{
struct cf_h2_ctx *ctx = cf->ctx;
struct SingleRequest *k = &data->req;
struct stream_ctx *stream = H2_STREAM_CTX(data);
int bitmap = GETSOCK_BLANK;
struct cf_call_data save;
bool want_recv = CURL_WANT_RECV(data);
bool want_send = CURL_WANT_SEND(data);
CF_DATA_SAVE(save, cf, data);
sock[0] = Curl_conn_cf_get_socket(cf, data);
if(ctx->h2 && (want_recv || want_send)) {
struct stream_ctx *stream = H2_STREAM_CTX(data);
curl_socket_t sock = Curl_conn_cf_get_socket(cf, data);
struct cf_call_data save;
bool c_exhaust, s_exhaust;
if(!(k->keepon & (KEEP_RECV_PAUSE|KEEP_RECV_HOLD)))
/* Unless paused - in an HTTP/2 connection we can basically always get a
frame so we should always be ready for one */
bitmap |= GETSOCK_READSOCK(0);
CF_DATA_SAVE(save, cf, data);
c_exhaust = !nghttp2_session_get_remote_window_size(ctx->h2);
s_exhaust = stream && stream->id >= 0 &&
!nghttp2_session_get_stream_remote_window_size(ctx->h2,
stream->id);
want_recv = (want_recv || c_exhaust || s_exhaust);
want_send = (!s_exhaust && want_send) ||
(!c_exhaust && nghttp2_session_want_write(ctx->h2));
/* we're (still uploading OR the HTTP/2 layer wants to send data) AND
there's a window to send data in */
if((((k->keepon & KEEP_SENDBITS) == KEEP_SEND) ||
nghttp2_session_want_write(ctx->h2)) &&
(nghttp2_session_get_remote_window_size(ctx->h2) &&
nghttp2_session_get_stream_remote_window_size(ctx->h2,
stream->id)))
bitmap |= GETSOCK_WRITESOCK(0);
CF_DATA_RESTORE(cf, save);
return bitmap;
Curl_pollset_set(data, ps, sock, want_recv, want_send);
CF_DATA_RESTORE(cf, save);
}
}
static CURLcode cf_h2_connect(struct Curl_cfilter *cf,
struct Curl_easy *data,
bool blocking, bool *done)
@@ -2511,14 +2486,15 @@ static CURLcode cf_h2_cntrl(struct Curl_cfilter *cf,
case CF_CTRL_DATA_PAUSE:
result = http2_data_pause(cf, data, (arg1 != 0));
break;
case CF_CTRL_DATA_DONE_SEND: {
case CF_CTRL_DATA_DONE_SEND:
result = http2_data_done_send(cf, data);
break;
}
case CF_CTRL_DATA_DONE: {
case CF_CTRL_DATA_DETACH:
http2_data_done(cf, data, TRUE);
break;
case CF_CTRL_DATA_DONE:
http2_data_done(cf, data, arg1 != 0);
break;
}
default:
break;
}
@@ -2606,7 +2582,7 @@ struct Curl_cftype Curl_cft_nghttp2 = {
cf_h2_connect,
cf_h2_close,
Curl_cf_def_get_host,
cf_h2_get_select_socks,
cf_h2_adjust_pollset,
cf_h2_data_pending,
cf_h2_send,
cf_h2_recv,
@@ -2626,7 +2602,7 @@ static CURLcode http2_cfilter_add(struct Curl_cfilter **pcf,
CURLcode result = CURLE_OUT_OF_MEMORY;
DEBUGASSERT(data->conn);
ctx = calloc(sizeof(*ctx), 1);
ctx = calloc(1, sizeof(*ctx));
if(!ctx)
goto out;
@@ -2652,7 +2628,7 @@ static CURLcode http2_cfilter_insert_after(struct Curl_cfilter *cf,
CURLcode result = CURLE_OUT_OF_MEMORY;
(void)data;
ctx = calloc(sizeof(*ctx), 1);
ctx = calloc(1, sizeof(*ctx));
if(!ctx)
goto out;
+10 -1
View File
@@ -456,6 +456,7 @@ static CURLcode canon_query(struct Curl_easy *data,
for(i = 0; !result && (i < entry); i++, ap++) {
size_t len;
const char *q = ap->p;
bool found_equals = false;
if(!ap->len)
continue;
for(len = ap->len; len && !result; q++, len--) {
@@ -467,9 +468,13 @@ static CURLcode canon_query(struct Curl_easy *data,
case '.':
case '_':
case '~':
/* allowed as-is */
result = Curl_dyn_addn(dq, q, 1);
break;
case '=':
/* allowed as-is */
result = Curl_dyn_addn(dq, q, 1);
found_equals = true;
break;
case '%':
/* uppercase the following if hexadecimal */
@@ -497,7 +502,11 @@ static CURLcode canon_query(struct Curl_easy *data,
}
}
}
if(i < entry - 1) {
if(!result && !found_equals) {
/* queries without value still need an equals */
result = Curl_dyn_addn(dq, "=", 1);
}
if(!result && i < entry - 1) {
/* insert ampersands between query pairs */
result = Curl_dyn_addn(dq, "&", 1);
}
+41 -42
View File
@@ -75,8 +75,6 @@
*/
#define isxdigit_ascii(x) Curl_isxdigit(x)
void Curl_httpchunk_init(struct Curl_easy *data)
{
struct connectdata *conn = data->conn;
@@ -98,9 +96,9 @@ void Curl_httpchunk_init(struct Curl_easy *data)
* For example, 0x0d and 0x0a are used instead of '\r' and '\n'.
*/
CHUNKcode Curl_httpchunk_read(struct Curl_easy *data,
char *datap,
ssize_t datalen,
ssize_t *wrote,
char *buf,
size_t blen,
size_t *pconsumed,
CURLcode *extrap)
{
CURLcode result = CURLE_OK;
@@ -108,28 +106,27 @@ CHUNKcode Curl_httpchunk_read(struct Curl_easy *data,
struct Curl_chunker *ch = &conn->chunk;
struct SingleRequest *k = &data->req;
size_t piece;
curl_off_t length = (curl_off_t)datalen;
*wrote = 0; /* nothing's written yet */
*pconsumed = 0; /* nothing's written yet */
/* the original data is written to the client, but we go on with the
chunk read process, to properly calculate the content length */
if(data->set.http_te_skip && !k->ignorebody) {
result = Curl_client_write(data, CLIENTWRITE_BODY, datap, datalen);
result = Curl_client_write(data, CLIENTWRITE_BODY, buf, blen);
if(result) {
*extrap = result;
return CHUNKE_PASSTHRU_ERROR;
}
}
while(length) {
while(blen) {
switch(ch->state) {
case CHUNK_HEX:
if(ISXDIGIT(*datap)) {
if(ISXDIGIT(*buf)) {
if(ch->hexindex < CHUNK_MAXNUM_LEN) {
ch->hexbuffer[ch->hexindex] = *datap;
datap++;
length--;
ch->hexbuffer[ch->hexindex] = *buf;
buf++;
blen--;
ch->hexindex++;
}
else {
@@ -143,7 +140,7 @@ CHUNKcode Curl_httpchunk_read(struct Curl_easy *data,
a hexadecimal digit. */
return CHUNKE_ILLEGAL_HEX;
/* length and datap are unmodified */
/* blen and buf are unmodified */
ch->hexbuffer[ch->hexindex] = 0;
if(curlx_strtoofft(ch->hexbuffer, &endptr, 16, &ch->datasize))
@@ -154,7 +151,7 @@ CHUNKcode Curl_httpchunk_read(struct Curl_easy *data,
case CHUNK_LF:
/* waiting for the LF after a chunk size */
if(*datap == 0x0a) {
if(*buf == 0x0a) {
/* we're now expecting data to come, unless size was zero! */
if(0 == ch->datasize) {
ch->state = CHUNK_TRAILER; /* now check for trailers */
@@ -163,19 +160,21 @@ CHUNKcode Curl_httpchunk_read(struct Curl_easy *data,
ch->state = CHUNK_DATA;
}
datap++;
length--;
buf++;
blen--;
break;
case CHUNK_DATA:
/* We expect 'datasize' of data. We have 'length' right now, it can be
/* We expect 'datasize' of data. We have 'blen' right now, it can be
more or less than 'datasize'. Get the smallest piece.
*/
piece = curlx_sotouz((ch->datasize >= length)?length:ch->datasize);
piece = blen;
if(ch->datasize < (curl_off_t)blen)
piece = curlx_sotouz(ch->datasize);
/* Write the data portion available */
if(!data->set.http_te_skip && !k->ignorebody) {
result = Curl_client_write(data, CLIENTWRITE_BODY, datap, piece);
result = Curl_client_write(data, CLIENTWRITE_BODY, buf, piece);
if(result) {
*extrap = result;
@@ -183,10 +182,10 @@ CHUNKcode Curl_httpchunk_read(struct Curl_easy *data,
}
}
*wrote += piece;
*pconsumed += piece;
ch->datasize -= piece; /* decrease amount left to expect */
datap += piece; /* move read pointer forward */
length -= piece; /* decrease space left in this round */
buf += piece; /* move read pointer forward */
blen -= piece; /* decrease space left in this round */
if(0 == ch->datasize)
/* end of data this round, we now expect a trailing CRLF */
@@ -194,18 +193,18 @@ CHUNKcode Curl_httpchunk_read(struct Curl_easy *data,
break;
case CHUNK_POSTLF:
if(*datap == 0x0a) {
if(*buf == 0x0a) {
/* The last one before we go back to hex state and start all over. */
Curl_httpchunk_init(data); /* sets state back to CHUNK_HEX */
}
else if(*datap != 0x0d)
else if(*buf != 0x0d)
return CHUNKE_BAD_CHUNK;
datap++;
length--;
buf++;
blen--;
break;
case CHUNK_TRAILER:
if((*datap == 0x0d) || (*datap == 0x0a)) {
if((*buf == 0x0d) || (*buf == 0x0a)) {
char *tr = Curl_dyn_ptr(&conn->trailer);
/* this is the end of a trailer, but if the trailer was zero bytes
there was no trailer and we move on */
@@ -229,7 +228,7 @@ CHUNKcode Curl_httpchunk_read(struct Curl_easy *data,
}
Curl_dyn_reset(&conn->trailer);
ch->state = CHUNK_TRAILER_CR;
if(*datap == 0x0a)
if(*buf == 0x0a)
/* already on the LF */
break;
}
@@ -240,19 +239,19 @@ CHUNKcode Curl_httpchunk_read(struct Curl_easy *data,
}
}
else {
result = Curl_dyn_addn(&conn->trailer, datap, 1);
result = Curl_dyn_addn(&conn->trailer, buf, 1);
if(result)
return CHUNKE_OUT_OF_MEMORY;
}
datap++;
length--;
buf++;
blen--;
break;
case CHUNK_TRAILER_CR:
if(*datap == 0x0a) {
if(*buf == 0x0a) {
ch->state = CHUNK_TRAILER_POSTCR;
datap++;
length--;
buf++;
blen--;
}
else
return CHUNKE_BAD_CHUNK;
@@ -261,27 +260,27 @@ CHUNKcode Curl_httpchunk_read(struct Curl_easy *data,
case CHUNK_TRAILER_POSTCR:
/* We enter this state when a CR should arrive so we expect to
have to first pass a CR before we wait for LF */
if((*datap != 0x0d) && (*datap != 0x0a)) {
if((*buf != 0x0d) && (*buf != 0x0a)) {
/* not a CR then it must be another header in the trailer */
ch->state = CHUNK_TRAILER;
break;
}
if(*datap == 0x0d) {
if(*buf == 0x0d) {
/* skip if CR */
datap++;
length--;
buf++;
blen--;
}
/* now wait for the final LF */
ch->state = CHUNK_STOP;
break;
case CHUNK_STOP:
if(*datap == 0x0a) {
length--;
if(*buf == 0x0a) {
blen--;
/* Record the length of any data left in the end of the buffer
even if there's no more chunks to read */
ch->datasize = curlx_sotouz(length);
ch->datasize = blen;
return CHUNKE_STOP; /* return stop */
}
+2 -2
View File
@@ -93,8 +93,8 @@ struct Curl_chunker {
/* The following functions are defined in http_chunks.c */
void Curl_httpchunk_init(struct Curl_easy *data);
CHUNKcode Curl_httpchunk_read(struct Curl_easy *data, char *datap,
ssize_t length, ssize_t *wrote,
CHUNKcode Curl_httpchunk_read(struct Curl_easy *data, char *buf,
size_t blen, size_t *pconsumed,
CURLcode *passthru);
#endif /* HEADER_CURL_HTTP_CHUNKS_H */
+1 -1
View File
@@ -299,7 +299,7 @@ struct Curl_cftype Curl_cft_http_proxy = {
http_proxy_cf_connect,
http_proxy_cf_close,
Curl_cf_http_proxy_get_host,
Curl_cf_def_get_select_socks,
Curl_cf_def_adjust_pollset,
Curl_cf_def_data_pending,
Curl_cf_def_send,
Curl_cf_def_recv,
+1 -1
View File
@@ -36,7 +36,7 @@
#ifdef USE_LIBIDN2
#include <idn2.h>
#if defined(WIN32) && defined(UNICODE)
#if defined(_WIN32) && defined(UNICODE)
#define IDN2_LOOKUP(name, host, flags) \
idn2_lookup_u8((const uint8_t *)name, (uint8_t **)host, flags)
#else
+1 -3
View File
@@ -1194,8 +1194,6 @@ static CURLcode imap_state_fetch_resp(struct Curl_easy *data,
if(result)
return result;
data->req.bytecount += chunk;
infof(data, "Written %zu bytes, %" CURL_FORMAT_CURL_OFF_TU
" bytes are left for transfer", chunk, size - chunk);
@@ -1430,7 +1428,7 @@ static CURLcode imap_init(struct Curl_easy *data)
CURLcode result = CURLE_OK;
struct IMAP *imap;
imap = data->req.p.imap = calloc(sizeof(struct IMAP), 1);
imap = data->req.p.imap = calloc(1, sizeof(struct IMAP));
if(!imap)
result = CURLE_OUT_OF_MEMORY;
+3 -17
View File
@@ -313,7 +313,6 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done)
int ldap_ssl = 0;
char *val_b64 = NULL;
size_t val_b64_sz = 0;
curl_off_t dlsize = 0;
#ifdef LDAP_OPT_NETWORK_TIMEOUT
struct timeval ldap_timeout = {10, 0}; /* 10 sec connection/search timeout */
#endif
@@ -327,7 +326,7 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done)
*done = TRUE; /* unconditionally */
infof(data, "LDAP local: LDAP Vendor = %s ; LDAP Version = %d",
LDAP_VENDOR_NAME, LDAP_VENDOR_VERSION);
LDAP_VENDOR_NAME, LDAP_VENDOR_VERSION);
infof(data, "LDAP local: %s", data->state.url);
#ifdef HAVE_LDAP_URL_PARSE
@@ -345,7 +344,7 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done)
if(conn->given->flags & PROTOPT_SSL)
ldap_ssl = 1;
infof(data, "LDAP local: trying to establish %s connection",
ldap_ssl ? "encrypted" : "cleartext");
ldap_ssl ? "encrypted" : "cleartext");
#if defined(USE_WIN32_LDAP)
host = curlx_convert_UTF8_to_tchar(conn->host.name);
@@ -535,6 +534,7 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done)
goto quit;
}
Curl_pgrsSetDownloadCounter(data, 0);
rc = ldap_search_s(server, ludp->lud_dn, ludp->lud_scope,
ludp->lud_filter, ludp->lud_attrs, 0, &ldapmsg);
@@ -596,8 +596,6 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done)
goto quit;
}
dlsize += name_len + 5;
FREE_ON_WINLDAP(name);
ldap_memfree(dn);
}
@@ -659,8 +657,6 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done)
goto quit;
}
dlsize += attr_len + 3;
if((attr_len > 7) &&
(strcmp(";binary", attr + (attr_len - 7)) == 0)) {
/* Binary attribute, encode to base64. */
@@ -689,8 +685,6 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done)
goto quit;
}
dlsize += val_b64_sz;
}
}
else {
@@ -705,8 +699,6 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done)
goto quit;
}
dlsize += vals[i]->bv_len;
}
result = Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\n", 1);
@@ -719,8 +711,6 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done)
goto quit;
}
dlsize++;
}
/* Free memory used to store values */
@@ -734,10 +724,6 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done)
result = Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\n", 1);
if(result)
goto quit;
dlsize++;
result = Curl_pgrsSetDownloadCounter(data, dlsize);
if(result)
goto quit;
}
if(ber)
+2 -3
View File
@@ -32,9 +32,8 @@
#include "warnless.h"
#ifdef USE_OPENSSL
#include <openssl/opensslconf.h>
#if defined(OPENSSL_VERSION_MAJOR) && (OPENSSL_VERSION_MAJOR >= 3) && \
!defined(USE_AMISSL)
#include <openssl/opensslv.h>
#if (OPENSSL_VERSION_NUMBER >= 0x30000000L) && !defined(USE_AMISSL)
/* OpenSSL 3.0.0 marks the MD4 functions as deprecated */
#define OPENSSL_NO_MD4
#endif
+1 -1
View File
@@ -208,7 +208,7 @@ ALLOC_FUNC char *curl_dbg_strdup(const char *str,
return mem;
}
#if defined(WIN32) && defined(UNICODE)
#if defined(_WIN32) && defined(UNICODE)
ALLOC_FUNC wchar_t *curl_dbg_wcsdup(const wchar_t *str,
int line, const char *source)
{
+2 -2
View File
@@ -64,7 +64,7 @@ CURL_EXTERN ALLOC_SIZE(2) void *curl_dbg_realloc(void *ptr,
CURL_EXTERN void curl_dbg_free(void *ptr, int line, const char *source);
CURL_EXTERN ALLOC_FUNC char *curl_dbg_strdup(const char *str, int line,
const char *src);
#if defined(WIN32) && defined(UNICODE)
#if defined(_WIN32) && defined(UNICODE)
CURL_EXTERN ALLOC_FUNC wchar_t *curl_dbg_wcsdup(const wchar_t *str,
int line,
const char *source);
@@ -121,7 +121,7 @@ CURL_EXTERN int curl_dbg_fclose(FILE *file, int line, const char *source);
#define send(a,b,c,d) curl_dbg_send(a,b,c,d, __LINE__, __FILE__)
#define recv(a,b,c,d) curl_dbg_recv(a,b,c,d, __LINE__, __FILE__)
#ifdef WIN32
#ifdef _WIN32
# ifdef UNICODE
# undef wcsdup
# define wcsdup(ptr) curl_dbg_wcsdup(ptr, __LINE__, __FILE__)
+2 -3
View File
@@ -48,7 +48,7 @@
#include "curl_memory.h"
#include "memdebug.h"
#ifdef WIN32
#ifdef _WIN32
# ifndef R_OK
# define R_OK 4
# endif
@@ -311,8 +311,7 @@ static char *escape_string(struct Curl_easy *data,
table = formtable;
/* data can be NULL when this function is called indirectly from
curl_formget(). */
if(strategy == MIMESTRATEGY_MAIL ||
(data && (data->set.mime_options & CURLMIMEOPT_FORMESCAPE)))
if(strategy == MIMESTRATEGY_MAIL || (data && (data->set.mime_formescape)))
table = mimetable;
Curl_dyn_init(&db, CURL_MAX_INPUT_LENGTH);
+1 -6
View File
@@ -66,9 +66,7 @@
* Non-ANSI integer extensions
*/
#if (defined(__BORLANDC__) && (__BORLANDC__ >= 0x520)) || \
(defined(__POCC__) && defined(_MSC_VER)) || \
(defined(_WIN32_WCE)) || \
#if (defined(_WIN32_WCE)) || \
(defined(__MINGW32__)) || \
(defined(_MSC_VER) && (_MSC_VER >= 900) && (_INTEGRAL_MAX_BITS >= 64))
# define MP_HAVE_INT_EXTENSIONS
@@ -1071,9 +1069,6 @@ static int alloc_addbyter(int output, FILE *data)
return outc; /* fputc() returns like this on success */
}
extern int Curl_dyn_vprintf(struct dynbuf *dyn,
const char *format, va_list ap_save);
/* appends the formatted string, returns 0 on success, 1 on error */
int Curl_dyn_vprintf(struct dynbuf *dyn, const char *format, va_list ap_save)
{
-9
View File
@@ -616,9 +616,6 @@ static void mqstate(struct Curl_easy *data,
}
/* for the publish packet */
#define MQTT_HEADER_LEN 5 /* max 5 bytes */
static CURLcode mqtt_read_publish(struct Curl_easy *data, bool *done)
{
CURLcode result = CURLE_OK;
@@ -677,7 +674,6 @@ MQTT_SUBACK_COMING:
/* FALLTHROUGH */
case MQTT_PUB_REMAIN: {
/* read rest of packet, but no more. Cap to buffer size */
struct SingleRequest *k = &data->req;
size_t rest = mq->npacket;
if(rest > (size_t)data->set.buffer_size)
rest = (size_t)data->set.buffer_size;
@@ -693,13 +689,8 @@ MQTT_SUBACK_COMING:
result = CURLE_PARTIAL_FILE;
goto end;
}
Curl_debug(data, CURLINFO_DATA_IN, (char *)pkt, (size_t)nread);
mq->npacket -= nread;
k->bytecount += nread;
result = Curl_pgrsSetDownloadCounter(data, k->bytecount);
if(result)
goto end;
/* if QoS is set, message contains packet id */
+121 -174
View File
@@ -55,22 +55,6 @@
#include "curl_memory.h"
#include "memdebug.h"
#ifdef __APPLE__
#define wakeup_write write
#define wakeup_read read
#define wakeup_close close
#define wakeup_create pipe
#else /* __APPLE__ */
#define wakeup_write swrite
#define wakeup_read sread
#define wakeup_close sclose
#define wakeup_create(p) Curl_socketpair(AF_UNIX, SOCK_STREAM, 0, p)
#endif /* __APPLE__ */
/*
CURL_SOCKET_HASH_TABLE_SIZE should be a prime number. Increasing it from 97
to 911 takes on a 32-bit machine 4 x 804 = 3211 more bytes. Still, every
@@ -231,10 +215,6 @@ struct Curl_sh_entry {
unsigned int readers; /* this many transfers want to read */
unsigned int writers; /* this many transfers want to write */
};
/* bits for 'action' having no bits means this socket is not expecting any
action */
#define SH_READ 1
#define SH_WRITE 2
/* look up a given socket in the socket hash, skip invalid sockets */
static struct Curl_sh_entry *sh_getentry(struct Curl_hash *sh,
@@ -416,9 +396,6 @@ struct Curl_multi *Curl_multi_handle(int hashsize, /* socket hash */
Curl_llist_init(&multi->msgsent, NULL);
multi->multiplexing = TRUE;
/* -1 means it not set by user, use the default value */
multi->maxconnects = -1;
multi->max_concurrent_streams = 100;
#ifdef USE_WINSOCK
@@ -1040,49 +1017,61 @@ static int protocol_getsock(struct Curl_easy *data,
{
if(conn->handler->proto_getsock)
return conn->handler->proto_getsock(data, conn, socks);
return Curl_conn_get_select_socks(data, FIRSTSOCKET, socks);
return GETSOCK_BLANK;
}
/* returns bitmapped flags for this handle and its sockets. The 'socks[]'
array contains MAX_SOCKSPEREASYHANDLE entries. */
static int multi_getsock(struct Curl_easy *data,
curl_socket_t *socks)
/* Initializes `poll_set` with the current socket poll actions needed
* for transfer `data`. */
static void multi_getsock(struct Curl_easy *data,
struct easy_pollset *ps)
{
struct connectdata *conn = data->conn;
/* The no connection case can happen when this is called from
curl_multi_remove_handle() => singlesocket() => multi_getsock().
*/
if(!conn)
return 0;
Curl_pollset_reset(data, ps);
if(!data->conn)
return;
switch(data->mstate) {
default:
return 0;
break;
case MSTATE_RESOLVING:
return Curl_resolv_getsock(data, socks);
Curl_pollset_add_socks2(data, ps, Curl_resolv_getsock);
/* connection filters are not involved in this phase */
return;
case MSTATE_PROTOCONNECTING:
case MSTATE_PROTOCONNECT:
return protocol_getsock(data, conn, socks);
Curl_pollset_add_socks(data, ps, protocol_getsock);
break;
case MSTATE_DO:
case MSTATE_DOING:
return doing_getsock(data, conn, socks);
Curl_pollset_add_socks(data, ps, doing_getsock);
break;
case MSTATE_TUNNELING:
case MSTATE_CONNECTING:
return Curl_conn_get_select_socks(data, FIRSTSOCKET, socks);
break;
case MSTATE_DOING_MORE:
return domore_getsock(data, conn, socks);
Curl_pollset_add_socks(data, ps, domore_getsock);
break;
case MSTATE_DID: /* since is set after DO is completed, we switch to
waiting for the same as the PERFORMING state */
case MSTATE_PERFORMING:
return Curl_single_getsock(data, conn, socks);
Curl_pollset_add_socks(data, ps, Curl_single_getsock);
break;
case MSTATE_RATELIMITING:
/* nothing to wait for */
return;
}
/* Let connection filters add/remove as needed */
Curl_conn_adjust_pollset(data, ps);
}
CURLMcode curl_multi_fdset(struct Curl_multi *multi,
@@ -1094,8 +1083,8 @@ CURLMcode curl_multi_fdset(struct Curl_multi *multi,
and then we must make sure that is done. */
struct Curl_easy *data;
int this_max_fd = -1;
curl_socket_t sockbunch[MAX_SOCKSPEREASYHANDLE];
int i;
struct easy_pollset ps;
unsigned int i;
(void)exc_fd_set; /* not used */
if(!GOOD_MULTI_HANDLE(multi))
@@ -1104,29 +1093,20 @@ CURLMcode curl_multi_fdset(struct Curl_multi *multi,
if(multi->in_callback)
return CURLM_RECURSIVE_API_CALL;
memset(&ps, 0, sizeof(ps));
for(data = multi->easyp; data; data = data->next) {
int bitmap;
#ifdef __clang_analyzer_
/* to prevent "The left operand of '>=' is a garbage value" warnings */
memset(sockbunch, 0, sizeof(sockbunch));
#endif
bitmap = multi_getsock(data, sockbunch);
multi_getsock(data, &ps);
for(i = 0; i< MAX_SOCKSPEREASYHANDLE; i++) {
if((bitmap & GETSOCK_MASK_RW(i)) && VALID_SOCK((sockbunch[i]))) {
if(!FDSET_SOCK(sockbunch[i]))
/* pretend it doesn't exist */
continue;
if(bitmap & GETSOCK_READSOCK(i))
FD_SET(sockbunch[i], read_fd_set);
if(bitmap & GETSOCK_WRITESOCK(i))
FD_SET(sockbunch[i], write_fd_set);
if((int)sockbunch[i] > this_max_fd)
this_max_fd = (int)sockbunch[i];
}
else {
break;
}
for(i = 0; i < ps.num; i++) {
if(!FDSET_SOCK(ps.sockets[i]))
/* pretend it doesn't exist */
continue;
if(ps.actions[i] & CURL_POLL_IN)
FD_SET(ps.sockets[i], read_fd_set);
if(ps.actions[i] & CURL_POLL_OUT)
FD_SET(ps.sockets[i], write_fd_set);
if((int)ps.sockets[i] > this_max_fd)
this_max_fd = (int)ps.sockets[i];
}
}
@@ -1162,9 +1142,8 @@ static CURLMcode multi_wait(struct Curl_multi *multi,
bool use_wakeup)
{
struct Curl_easy *data;
curl_socket_t sockbunch[MAX_SOCKSPEREASYHANDLE];
int bitmap;
unsigned int i;
struct easy_pollset ps;
size_t i;
unsigned int nfds = 0;
unsigned int curlfds;
long timeout_internal;
@@ -1190,17 +1169,10 @@ static CURLMcode multi_wait(struct Curl_multi *multi,
return CURLM_BAD_FUNCTION_ARGUMENT;
/* Count up how many fds we have from the multi handle */
memset(&ps, 0, sizeof(ps));
for(data = multi->easyp; data; data = data->next) {
bitmap = multi_getsock(data, sockbunch);
for(i = 0; i < MAX_SOCKSPEREASYHANDLE; i++) {
if((bitmap & GETSOCK_MASK_RW(i)) && VALID_SOCK((sockbunch[i]))) {
++nfds;
}
else {
break;
}
}
multi_getsock(data, &ps);
nfds += ps.num;
}
/* If the internally desired timeout is actually shorter than requested from
@@ -1241,40 +1213,35 @@ static CURLMcode multi_wait(struct Curl_multi *multi,
if(curlfds) {
/* Add the curl handles to our pollfds first */
for(data = multi->easyp; data; data = data->next) {
bitmap = multi_getsock(data, sockbunch);
multi_getsock(data, &ps);
for(i = 0; i < MAX_SOCKSPEREASYHANDLE; i++) {
if((bitmap & GETSOCK_MASK_RW(i)) && VALID_SOCK((sockbunch[i]))) {
struct pollfd *ufd = &ufds[nfds++];
for(i = 0; i < ps.num; i++) {
struct pollfd *ufd = &ufds[nfds++];
#ifdef USE_WINSOCK
long mask = 0;
long mask = 0;
#endif
ufd->fd = sockbunch[i];
ufd->events = 0;
if(bitmap & GETSOCK_READSOCK(i)) {
ufd->fd = ps.sockets[i];
ufd->events = 0;
if(ps.actions[i] & CURL_POLL_IN) {
#ifdef USE_WINSOCK
mask |= FD_READ|FD_ACCEPT|FD_CLOSE;
#endif
ufd->events |= POLLIN;
}
if(bitmap & GETSOCK_WRITESOCK(i)) {
#ifdef USE_WINSOCK
mask |= FD_WRITE|FD_CONNECT|FD_CLOSE;
reset_socket_fdwrite(sockbunch[i]);
#endif
ufd->events |= POLLOUT;
}
#ifdef USE_WINSOCK
if(WSAEventSelect(sockbunch[i], multi->wsa_event, mask) != 0) {
if(ufds_malloc)
free(ufds);
return CURLM_INTERNAL_ERROR;
}
mask |= FD_READ|FD_ACCEPT|FD_CLOSE;
#endif
ufd->events |= POLLIN;
}
else {
break;
if(ps.actions[i] & CURL_POLL_OUT) {
#ifdef USE_WINSOCK
mask |= FD_WRITE|FD_CONNECT|FD_CLOSE;
reset_socket_fdwrite(ps.sockets[i]);
#endif
ufd->events |= POLLOUT;
}
#ifdef USE_WINSOCK
if(WSAEventSelect(ps.sockets[i], multi->wsa_event, mask) != 0) {
if(ufds_malloc)
free(ufds);
return CURLM_INTERNAL_ERROR;
}
#endif
}
}
}
@@ -1386,21 +1353,16 @@ static CURLMcode multi_wait(struct Curl_multi *multi,
if(curlfds) {
for(data = multi->easyp; data; data = data->next) {
bitmap = multi_getsock(data, sockbunch);
multi_getsock(data, &ps);
for(i = 0; i < MAX_SOCKSPEREASYHANDLE; i++) {
if(bitmap & (GETSOCK_READSOCK(i) | GETSOCK_WRITESOCK(i))) {
wsa_events.lNetworkEvents = 0;
if(WSAEnumNetworkEvents(sockbunch[i], NULL, &wsa_events) == 0) {
if(ret && !pollrc && wsa_events.lNetworkEvents)
retcode++;
}
WSAEventSelect(sockbunch[i], multi->wsa_event, 0);
}
else {
/* break on entry not checked for being readable or writable */
break;
for(i = 0; i < ps.num; i++) {
wsa_events.lNetworkEvents = 0;
if(WSAEnumNetworkEvents(ps.sockets[i], NULL,
&wsa_events) == 0) {
if(ret && !pollrc && wsa_events.lNetworkEvents)
retcode++;
}
WSAEventSelect(ps.sockets[i], multi->wsa_event, 0);
}
}
}
@@ -2021,8 +1983,8 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
if(dns) {
#ifdef CURLRES_ASYNCH
data->state.async.dns = dns;
data->state.async.done = TRUE;
conn->resolve_async.dns = dns;
conn->resolve_async.done = TRUE;
#endif
result = CURLE_OK;
infof(data, "Hostname '%s' was found in DNS cache", hostname);
@@ -2895,53 +2857,36 @@ CURLMsg *curl_multi_info_read(struct Curl_multi *multi, int *msgs_in_queue)
static CURLMcode singlesocket(struct Curl_multi *multi,
struct Curl_easy *data)
{
curl_socket_t socks[MAX_SOCKSPEREASYHANDLE];
int i;
struct easy_pollset cur_poll;
unsigned int i;
struct Curl_sh_entry *entry;
curl_socket_t s;
int num;
unsigned int curraction;
unsigned char actions[MAX_SOCKSPEREASYHANDLE];
int rc;
for(i = 0; i< MAX_SOCKSPEREASYHANDLE; i++)
socks[i] = CURL_SOCKET_BAD;
/* Fill in the 'current' struct with the state as it is now: what sockets to
supervise and for what actions */
curraction = multi_getsock(data, socks);
multi_getsock(data, &cur_poll);
/* We have 0 .. N sockets already and we get to know about the 0 .. M
sockets we should have from now on. Detect the differences, remove no
longer supervised ones and add new ones */
/* walk over the sockets we got right now */
for(i = 0; (i< MAX_SOCKSPEREASYHANDLE) &&
(curraction & GETSOCK_MASK_RW(i));
i++) {
unsigned char action = CURL_POLL_NONE;
unsigned char prevaction = 0;
for(i = 0; i < cur_poll.num; i++) {
unsigned char cur_action = cur_poll.actions[i];
unsigned char last_action = 0;
int comboaction;
bool sincebefore = FALSE;
s = socks[i];
s = cur_poll.sockets[i];
/* get it from the hash */
entry = sh_getentry(&multi->sockhash, s);
if(curraction & GETSOCK_READSOCK(i))
action |= CURL_POLL_IN;
if(curraction & GETSOCK_WRITESOCK(i))
action |= CURL_POLL_OUT;
actions[i] = action;
if(entry) {
/* check if new for this transfer */
int j;
for(j = 0; j< data->numsocks; j++) {
if(s == data->sockets[j]) {
prevaction = data->actions[j];
sincebefore = TRUE;
unsigned int j;
for(j = 0; j< data->last_poll.num; j++) {
if(s == data->last_poll.sockets[j]) {
last_action = data->last_poll.actions[j];
break;
}
}
@@ -2953,23 +2898,23 @@ static CURLMcode singlesocket(struct Curl_multi *multi,
/* fatal */
return CURLM_OUT_OF_MEMORY;
}
if(sincebefore && (prevaction != action)) {
if(last_action && (last_action != cur_action)) {
/* Socket was used already, but different action now */
if(prevaction & CURL_POLL_IN)
if(last_action & CURL_POLL_IN)
entry->readers--;
if(prevaction & CURL_POLL_OUT)
if(last_action & CURL_POLL_OUT)
entry->writers--;
if(action & CURL_POLL_IN)
if(cur_action & CURL_POLL_IN)
entry->readers++;
if(action & CURL_POLL_OUT)
if(cur_action & CURL_POLL_OUT)
entry->writers++;
}
else if(!sincebefore) {
/* a new user */
else if(!last_action) {
/* a new transfer using this socket */
entry->users++;
if(action & CURL_POLL_IN)
if(cur_action & CURL_POLL_IN)
entry->readers++;
if(action & CURL_POLL_OUT)
if(cur_action & CURL_POLL_OUT)
entry->writers++;
/* add 'data' to the transfer hash on this socket! */
@@ -2980,11 +2925,11 @@ static CURLMcode singlesocket(struct Curl_multi *multi,
}
}
comboaction = (entry->writers? CURL_POLL_OUT : 0) |
comboaction = (entry->writers ? CURL_POLL_OUT : 0) |
(entry->readers ? CURL_POLL_IN : 0);
/* socket existed before and has the same action set as before */
if(sincebefore && ((int)entry->action == comboaction))
if(last_action && ((int)entry->action == comboaction))
/* same, continue */
continue;
@@ -2992,6 +2937,7 @@ static CURLMcode singlesocket(struct Curl_multi *multi,
set_in_callback(multi, TRUE);
rc = multi->socket_cb(data, s, comboaction, multi->socket_userp,
entry->socketp);
set_in_callback(multi, FALSE);
if(rc == -1) {
multi->dead = TRUE;
@@ -3002,16 +2948,15 @@ static CURLMcode singlesocket(struct Curl_multi *multi,
entry->action = comboaction; /* store the current action state */
}
num = i; /* number of sockets */
/* when we've walked over all the sockets we should have right now, we must
make sure to detect sockets that are removed */
for(i = 0; i< data->numsocks; i++) {
int j;
/* Check for last_poll.sockets that no longer appear in cur_poll.sockets.
* Need to remove the easy handle from the multi->sockhash->transfers and
* remove multi->sockhash entry when this was the last transfer */
for(i = 0; i< data->last_poll.num; i++) {
unsigned int j;
bool stillused = FALSE;
s = data->sockets[i];
for(j = 0; j < num; j++) {
if(s == socks[j]) {
s = data->last_poll.sockets[i];
for(j = 0; j < cur_poll.num; j++) {
if(s == cur_poll.sockets[j]) {
/* this is still supervised */
stillused = TRUE;
break;
@@ -3024,7 +2969,7 @@ static CURLMcode singlesocket(struct Curl_multi *multi,
/* if this is NULL here, the socket has been closed and notified so
already by Curl_multi_closed() */
if(entry) {
unsigned char oldactions = data->actions[i];
unsigned char oldactions = data->last_poll.actions[i];
/* this socket has been removed. Decrease user count */
entry->users--;
if(oldactions & CURL_POLL_OUT)
@@ -3052,11 +2997,10 @@ static CURLMcode singlesocket(struct Curl_multi *multi,
}
}
}
} /* for loop over numsocks */
} /* for loop over num */
memcpy(data->sockets, socks, num*sizeof(curl_socket_t));
memcpy(data->actions, actions, num*sizeof(char));
data->numsocks = num;
/* Remember for next time */
memcpy(&data->last_poll, &cur_poll, sizeof(data->last_poll));
return CURLM_OK;
}
@@ -3296,6 +3240,7 @@ CURLMcode curl_multi_setopt(struct Curl_multi *multi,
{
CURLMcode res = CURLM_OK;
va_list param;
unsigned long uarg;
if(!GOOD_MULTI_HANDLE(multi))
return CURLM_BAD_HANDLE;
@@ -3328,7 +3273,9 @@ CURLMcode curl_multi_setopt(struct Curl_multi *multi,
multi->timer_userp = va_arg(param, void *);
break;
case CURLMOPT_MAXCONNECTS:
multi->maxconnects = va_arg(param, long);
uarg = va_arg(param, unsigned long);
if(uarg <= UINT_MAX)
multi->maxconnects = (unsigned int)uarg;
break;
case CURLMOPT_MAX_HOST_CONNECTIONS:
multi->max_host_connections = va_arg(param, long);
@@ -3350,9 +3297,9 @@ CURLMcode curl_multi_setopt(struct Curl_multi *multi,
case CURLMOPT_MAX_CONCURRENT_STREAMS:
{
long streams = va_arg(param, long);
if(streams < 1)
if((streams < 1) || (streams > INT_MAX))
streams = 100;
multi->max_concurrent_streams = curlx_sltoui(streams);
multi->max_concurrent_streams = (unsigned int)streams;
}
break;
default:
@@ -3782,11 +3729,11 @@ struct Curl_easy **curl_multi_get_handles(struct Curl_multi *multi)
struct Curl_easy **a = malloc(sizeof(struct Curl_easy *) *
(multi->num_easy + 1));
if(a) {
int i = 0;
unsigned int i = 0;
struct Curl_easy *e = multi->easyp;
while(e) {
DEBUGASSERT(i < multi->num_easy);
if(!e->internal)
if(!e->state.internal)
a[i++] = e;
e = e->next;
}
+7 -8
View File
@@ -93,9 +93,9 @@ struct Curl_multi {
struct Curl_easy *easyp;
struct Curl_easy *easylp; /* last node */
int num_easy; /* amount of entries in the linked list above. */
int num_alive; /* amount of easy handles that are added but have not yet
reached COMPLETE state */
unsigned int num_easy; /* amount of entries in the linked list above. */
unsigned int num_alive; /* amount of easy handles that are added but have
not yet reached COMPLETE state */
struct Curl_llist msglist; /* a list of messages from completed transfers */
@@ -136,9 +136,6 @@ struct Curl_multi {
/* Shared connection cache (bundles)*/
struct conncache conn_cache;
long maxconnects; /* if >0, a fixed limit of the maximum number of entries
we're allowed to grow the connection cache to */
long max_host_connections; /* if >0, a fixed limit of the maximum number
of connections per host */
@@ -150,8 +147,6 @@ struct Curl_multi {
void *timer_userp;
struct curltime timer_lastcall; /* the fixed time for the timeout for the
previous callback */
unsigned int max_concurrent_streams;
#ifdef USE_WINSOCK
WSAEVENT wsa_event; /* winsock event used for waits */
#else
@@ -160,6 +155,10 @@ struct Curl_multi {
0 is used for read, 1 is used for write */
#endif
#endif
unsigned int max_concurrent_streams;
unsigned int maxconnects; /* if >0, a fixed limit of the maximum number of
entries we're allowed to grow the connection
cache to */
#define IPV6_UNKNOWN 0
#define IPV6_DEAD 1
#define IPV6_WORKS 2
+1 -1
View File
@@ -327,7 +327,7 @@ int Curl_parsenetrc(const char *host, char **loginp, char **passwordp,
}
retcode = parsenetrc(host, loginp, passwordp, filealloc);
free(filealloc);
#ifdef WIN32
#ifdef _WIN32
if(retcode == NETRC_FILE_MISSING) {
/* fallback to the old-style "_netrc" file */
filealloc = curl_maprintf("%s%s_netrc", home, DIR_CHAR);
+27 -27
View File
@@ -319,31 +319,12 @@ static CURLcode oldap_setup_connection(struct Curl_easy *data,
{
CURLcode result;
LDAPURLDesc *lud;
struct ldapconninfo *li;
(void)conn;
/* Early URL syntax check. */
result = oldap_url_parse(data, &lud);
ldap_free_urldesc(lud);
if(!result) {
li = calloc(1, sizeof(struct ldapconninfo));
if(!li)
result = CURLE_OUT_OF_MEMORY;
else {
li->proto = ldap_pvt_url_scheme2proto(data->state.up.scheme);
conn->proto.ldapc = li;
connkeep(conn, "OpenLDAP default");
/* Initialize the SASL storage */
Curl_sasl_init(&li->sasl, data, &saslldap);
/* Clear the TLS upgraded flag */
conn->bits.tls_upgraded = FALSE;
result = oldap_parse_login_options(conn);
}
}
return result;
}
@@ -537,7 +518,7 @@ static CURLcode oldap_perform_starttls(struct Curl_easy *data)
static CURLcode oldap_connect(struct Curl_easy *data, bool *done)
{
struct connectdata *conn = data->conn;
struct ldapconninfo *li = conn->proto.ldapc;
struct ldapconninfo *li;
static const int version = LDAP_VERSION3;
int rc;
char *hosturl;
@@ -547,6 +528,26 @@ static CURLcode oldap_connect(struct Curl_easy *data, bool *done)
(void)done;
DEBUGASSERT(!conn->proto.ldapc);
li = calloc(1, sizeof(struct ldapconninfo));
if(!li)
return CURLE_OUT_OF_MEMORY;
else {
CURLcode result;
li->proto = ldap_pvt_url_scheme2proto(data->state.up.scheme);
conn->proto.ldapc = li;
/* Initialize the SASL storage */
Curl_sasl_init(&li->sasl, data, &saslldap);
/* Clear the TLS upgraded flag */
conn->bits.tls_upgraded = FALSE;
result = oldap_parse_login_options(conn);
if(result)
return result;
}
hosturl = aprintf("ldap%s://%s:%d",
conn->handler->flags & PROTOPT_SSL? "s": "",
conn->host.name, conn->remote_port);
@@ -886,6 +887,11 @@ static CURLcode oldap_do(struct Curl_easy *data, bool *done)
result = oldap_url_parse(data, &lud);
if(!result) {
Sockbuf *sb;
/* re-install the libcurl SSL handlers into the sockbuf. */
ldap_get_option(li->ld, LDAP_OPT_SOCKBUF, &sb);
ber_sockbuf_add_io(sb, &ldapsb_tls, LBER_SBIOD_LEVEL_TRANSPORT, data);
rc = ldap_search_ext(li->ld, lud->lud_dn, lud->lud_scope,
lud->lud_filter, lud->lud_attrs, 0,
NULL, NULL, NULL, 0, &msgid);
@@ -947,18 +953,12 @@ static CURLcode client_write(struct Curl_easy *data,
if(!len && plen && prefix[plen - 1] == ' ')
plen--;
result = Curl_client_write(data, CLIENTWRITE_BODY, (char *) prefix, plen);
if(!result)
data->req.bytecount += plen;
}
if(!result && value) {
result = Curl_client_write(data, CLIENTWRITE_BODY, (char *) value, len);
if(!result)
data->req.bytecount += len;
}
if(!result && suffix) {
result = Curl_client_write(data, CLIENTWRITE_BODY, (char *) suffix, slen);
if(!result)
data->req.bytecount += slen;
}
return result;
}
+1 -1
View File
@@ -1088,7 +1088,7 @@ static CURLcode pop3_init(struct Curl_easy *data)
CURLcode result = CURLE_OK;
struct POP3 *pop3;
pop3 = data->req.p.pop3 = calloc(sizeof(struct POP3), 1);
pop3 = data->req.p.pop3 = calloc(1, sizeof(struct POP3));
if(!pop3)
result = CURLE_OUT_OF_MEMORY;
+1 -7
View File
@@ -304,7 +304,7 @@ timediff_t Curl_pgrsLimitWaitTime(curl_off_t cursize,
* 'actual' is the time in milliseconds it took to actually download the
* last 'size' bytes.
*/
actual = Curl_timediff(now, start);
actual = Curl_timediff_ceil(now, start);
if(actual < minimum) {
/* if it downloaded the data faster than the limit, make it wait the
difference */
@@ -319,12 +319,6 @@ timediff_t Curl_pgrsLimitWaitTime(curl_off_t cursize,
*/
CURLcode Curl_pgrsSetDownloadCounter(struct Curl_easy *data, curl_off_t size)
{
if(data->set.max_filesize && (size > data->set.max_filesize)) {
failf(data, "Exceeded the maximum allowed file size "
"(%" CURL_FORMAT_CURL_OFF_T ")",
data->set.max_filesize);
return CURLE_FILESIZE_EXCEEDED;
}
data->progress.downloaded = size;
return CURLE_OK;
}
+14 -14
View File
@@ -32,10 +32,6 @@
#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
#ifdef HAVE_ARC4RANDOM
/* Some platforms might have the prototype missing (ubuntu + libressl) */
uint32_t arc4random(void);
#endif
#include <curl/curl.h>
#include "urldata.h"
@@ -50,7 +46,7 @@ uint32_t arc4random(void);
#include "curl_memory.h"
#include "memdebug.h"
#ifdef WIN32
#ifdef _WIN32
#if defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x600
# define HAVE_WIN_BCRYPTGENRANDOM
@@ -105,7 +101,6 @@ CURLcode Curl_win32_random(unsigned char *entropy, size_t length)
static CURLcode randit(struct Curl_easy *data, unsigned int *rnd)
{
unsigned int r;
CURLcode result = CURLE_OK;
static unsigned int randseed;
static bool seeded = FALSE;
@@ -138,7 +133,7 @@ static CURLcode randit(struct Curl_easy *data, unsigned int *rnd)
/* ---- non-cryptographic version following ---- */
#ifdef WIN32
#ifdef _WIN32
if(!seeded) {
result = Curl_win32_random((unsigned char *)rnd, sizeof(*rnd));
if(result != CURLE_NOT_BUILT_IN)
@@ -146,12 +141,14 @@ static CURLcode randit(struct Curl_easy *data, unsigned int *rnd)
}
#endif
#ifdef HAVE_ARC4RANDOM
*rnd = (unsigned int)arc4random();
return CURLE_OK;
#if defined(HAVE_ARC4RANDOM) && !defined(USE_OPENSSL)
if(!seeded) {
*rnd = (unsigned int)arc4random();
return CURLE_OK;
}
#endif
#if defined(RANDOM_FILE) && !defined(WIN32)
#if defined(RANDOM_FILE) && !defined(_WIN32)
if(!seeded) {
/* if there's a random file to read a seed from, use it */
int fd = open(RANDOM_FILE, O_RDONLY);
@@ -175,9 +172,12 @@ static CURLcode randit(struct Curl_easy *data, unsigned int *rnd)
seeded = TRUE;
}
/* Return an unsigned 32-bit pseudo-random number. */
r = randseed = randseed * 1103515245 + 12345;
*rnd = (r << 16) | ((r >> 16) & 0xFFFF);
{
unsigned int r;
/* Return an unsigned 32-bit pseudo-random number. */
r = randseed = randseed * 1103515245 + 12345;
*rnd = (r << 16) | ((r >> 16) & 0xFFFF);
}
return CURLE_OK;
}
+1 -1
View File
@@ -41,7 +41,7 @@ CURLcode Curl_rand_hex(struct Curl_easy *data, unsigned char *rnd,
CURLcode Curl_rand_alnum(struct Curl_easy *data, unsigned char *rnd,
size_t num);
#ifdef WIN32
#ifdef _WIN32
/* Random generator shared between the Schannel vtls and Curl_rand*()
functions */
CURLcode Curl_win32_random(unsigned char *entropy, size_t length);
+1 -1
View File
@@ -40,7 +40,7 @@
/* return 0 on success, 1 on error */
int Curl_rename(const char *oldpath, const char *newpath)
{
#ifdef WIN32
#ifdef _WIN32
/* rename() on Windows doesn't overwrite, so we can't use it here.
MoveFileEx() will overwrite and is usually atomic, however it fails
when there are open handles to the file. */
+237 -136
View File
@@ -45,8 +45,8 @@
#include "curl_memory.h"
#include "memdebug.h"
#define RTP_PKT_LENGTH(p) ((((int)((unsigned char)((p)[2]))) << 8) | \
((int)((unsigned char)((p)[3]))))
#define RTP_PKT_LENGTH(p) ((((unsigned int)((unsigned char)((p)[2]))) << 8) | \
((unsigned int)((unsigned char)((p)[3]))))
/* protocol-specific functions set up to be called by the main engine */
static CURLcode rtsp_do(struct Curl_easy *data, bool *done);
@@ -59,14 +59,19 @@ static int rtsp_getsock_do(struct Curl_easy *data,
/*
* Parse and write out any available RTP data.
*
* nread: amount of data left after k->str. will be modified if RTP
* data is parsed and k->str is moved up
* readmore: whether or not the RTP parser needs more data right away
* @param data the transfer
* @param conn the connection
* @param buf data read from connection
* @param blen amount of data in buf
* @param consumed out, number of blen consumed
* @param readmore out, TRUE iff complete buf was consumed and more data
* is needed
*/
static CURLcode rtsp_rtp_readwrite(struct Curl_easy *data,
struct connectdata *conn,
ssize_t *nread,
const char *buf,
size_t blen,
size_t *pconsumed,
bool *readmore);
static CURLcode rtsp_setup_connection(struct Curl_easy *data,
@@ -88,7 +93,7 @@ static int rtsp_getsock_do(struct Curl_easy *data, struct connectdata *conn,
}
static
CURLcode rtp_client_write(struct Curl_easy *data, char *ptr, size_t len);
CURLcode rtp_client_write(struct Curl_easy *data, const char *ptr, size_t len);
static
CURLcode rtsp_parse_transport(struct Curl_easy *data, char *transport);
@@ -585,153 +590,249 @@ static CURLcode rtsp_do(struct Curl_easy *data, bool *done)
return result;
}
static CURLcode rtsp_filter_rtp(struct Curl_easy *data,
struct connectdata *conn,
const char *buf,
size_t blen,
bool in_body,
size_t *pconsumed)
{
struct rtsp_conn *rtspc = &(conn->proto.rtspc);
CURLcode result = CURLE_OK;
*pconsumed = 0;
while(blen) {
switch(rtspc->state) {
case RTP_PARSE_SKIP: {
DEBUGASSERT(Curl_dyn_len(&rtspc->buf) == 0);
if(in_body && buf[0] != '$') {
/* in BODY and no valid start, do not consume and return */
goto out;
}
while(blen && buf[0] != '$') {
if(!in_body && buf[0] == 'R' &&
data->set.rtspreq != RTSPREQ_RECEIVE) {
if(strncmp(buf, "RTSP/", (blen < 5) ? blen : 5) == 0) {
/* This could be the next response, no consume and return */
if(*pconsumed) {
DEBUGF(infof(data, "RTP rtsp_filter_rtp[SKIP] RTSP/ prefix, "
"skipping %zd bytes of junk", *pconsumed));
}
rtspc->state = RTP_PARSE_SKIP;
rtspc->in_header = TRUE;
goto out;
}
}
/* junk, consume without buffering */
*pconsumed += 1;
++buf;
--blen;
}
if(blen && buf[0] == '$') {
/* possible start of an RTP message, buffer */
if(Curl_dyn_addn(&rtspc->buf, buf, 1)) {
result = CURLE_OUT_OF_MEMORY;
goto out;
}
*pconsumed += 1;
++buf;
--blen;
rtspc->state = RTP_PARSE_CHANNEL;
}
break;
}
case RTP_PARSE_CHANNEL: {
int idx = ((unsigned char)buf[0]) / 8;
int off = ((unsigned char)buf[0]) % 8;
DEBUGASSERT(Curl_dyn_len(&rtspc->buf) == 1);
if(!(data->state.rtp_channel_mask[idx] & (1 << off))) {
/* invalid channel number, junk or BODY data */
rtspc->state = RTP_PARSE_SKIP;
if(in_body) {
/* we do not consume this byte, it is BODY data */
DEBUGF(infof(data, "RTSP: invalid RTP channel %d in BODY, "
"treating as BODY data", idx));
if(*pconsumed == 0) {
/* We did not consume the initial '$' in our buffer, but had
* it from an earlier call. We cannot un-consume it and have
* to write it directly as BODY data */
result = Curl_client_write(data, CLIENTWRITE_BODY,
Curl_dyn_ptr(&rtspc->buf), 1);
Curl_dyn_free(&rtspc->buf);
if(result)
goto out;
}
else {
/* un-consume the '$' and leave */
Curl_dyn_free(&rtspc->buf);
*pconsumed -= 1;
--buf;
++blen;
goto out;
}
}
else {
/* not BODY, forget the junk '$'. Do not consume this byte,
* it might be a start */
infof(data, "RTSP: invalid RTP channel %d, skipping", idx);
Curl_dyn_free(&rtspc->buf);
}
break;
}
/* a valid channel, so we expect this to be a real RTP message */
rtspc->rtp_channel = (unsigned char)buf[0];
if(Curl_dyn_addn(&rtspc->buf, buf, 1)) {
result = CURLE_OUT_OF_MEMORY;
goto out;
}
*pconsumed += 1;
++buf;
--blen;
rtspc->state = RTP_PARSE_LEN;
break;
}
case RTP_PARSE_LEN: {
size_t rtp_len = Curl_dyn_len(&rtspc->buf);
const char *rtp_buf;
DEBUGASSERT(rtp_len >= 2 && rtp_len < 4);
if(Curl_dyn_addn(&rtspc->buf, buf, 1)) {
result = CURLE_OUT_OF_MEMORY;
goto out;
}
*pconsumed += 1;
++buf;
--blen;
if(rtp_len == 2)
break;
rtp_buf = Curl_dyn_ptr(&rtspc->buf);
rtspc->rtp_len = RTP_PKT_LENGTH(rtp_buf) + 4;
rtspc->state = RTP_PARSE_DATA;
break;
}
case RTP_PARSE_DATA: {
size_t rtp_len = Curl_dyn_len(&rtspc->buf);
size_t needed;
DEBUGASSERT(rtp_len < rtspc->rtp_len);
needed = rtspc->rtp_len - rtp_len;
if(needed <= blen) {
if(Curl_dyn_addn(&rtspc->buf, buf, needed)) {
result = CURLE_OUT_OF_MEMORY;
goto out;
}
*pconsumed += needed;
buf += needed;
blen -= needed;
/* complete RTP message in buffer */
DEBUGF(infof(data, "RTP write channel %d rtp_len %zu",
rtspc->rtp_channel, rtspc->rtp_len));
result = rtp_client_write(data, Curl_dyn_ptr(&rtspc->buf),
rtspc->rtp_len);
Curl_dyn_free(&rtspc->buf);
rtspc->state = RTP_PARSE_SKIP;
if(result)
goto out;
}
else {
if(Curl_dyn_addn(&rtspc->buf, buf, blen)) {
result = CURLE_OUT_OF_MEMORY;
goto out;
}
*pconsumed += blen;
buf += blen;
blen = 0;
}
break;
}
default:
DEBUGASSERT(0);
return CURLE_RECV_ERROR;
}
}
out:
return result;
}
static CURLcode rtsp_rtp_readwrite(struct Curl_easy *data,
struct connectdata *conn,
ssize_t *nread,
bool *readmore) {
struct SingleRequest *k = &data->req;
const char *buf,
size_t blen,
size_t *pconsumed,
bool *readmore)
{
struct rtsp_conn *rtspc = &(conn->proto.rtspc);
unsigned char *rtp_channel_mask = data->state.rtp_channel_mask;
CURLcode result = CURLE_OK;
size_t consumed = 0;
bool in_body;
char *rtp; /* moving pointer to rtp data */
ssize_t rtp_dataleft; /* how much data left to parse in this round */
CURLcode result;
bool interleaved = false;
size_t skip_size = 0;
if(!data->req.header)
rtspc->in_header = FALSE;
in_body = (data->req.headerline && !rtspc->in_header) &&
(data->req.size >= 0) &&
(data->req.bytecount < data->req.size);
if(Curl_dyn_len(&rtspc->buf)) {
/* There was some leftover data the last time. Append new buffers */
if(Curl_dyn_addn(&rtspc->buf, k->str, *nread))
return CURLE_OUT_OF_MEMORY;
rtp = Curl_dyn_ptr(&rtspc->buf);
rtp_dataleft = Curl_dyn_len(&rtspc->buf);
}
else {
/* Just parse the request buffer directly */
rtp = k->str;
rtp_dataleft = *nread;
*readmore = FALSE;
*pconsumed = 0;
if(!blen) {
goto out;
}
while(rtp_dataleft > 0) {
if(rtp[0] == '$') {
if(rtp_dataleft > 4) {
unsigned char rtp_channel;
int rtp_length;
int idx;
int off;
/* If header parsing is not onging, extract RTP messages */
if(!rtspc->in_header) {
result = rtsp_filter_rtp(data, conn, buf, blen, in_body, &consumed);
if(result)
goto out;
*pconsumed += consumed;
buf += consumed;
blen -= consumed;
}
/* Parse the header */
/* The channel identifier immediately follows and is 1 byte */
rtp_channel = (unsigned char)rtp[1];
idx = rtp_channel / 8;
off = rtp_channel % 8;
if(!(rtp_channel_mask[idx] & (1 << off))) {
/* invalid channel number, maybe not an RTP packet */
rtp++;
rtp_dataleft--;
skip_size++;
continue;
}
if(skip_size > 0) {
DEBUGF(infof(data, "Skip the malformed interleaved data %lu "
"bytes", skip_size));
}
skip_size = 0;
rtspc->rtp_channel = rtp_channel;
/* we want to parse headers, do so */
if(data->req.header && blen) {
rtspc->in_header = TRUE;
result = Curl_http_readwrite_headers(data, conn, buf, blen,
&consumed);
if(result)
goto out;
/* The length is two bytes */
rtp_length = RTP_PKT_LENGTH(rtp);
*pconsumed += consumed;
buf += consumed;
blen -= consumed;
if(rtp_dataleft < rtp_length + 4) {
/* Need more - incomplete payload */
*readmore = TRUE;
break;
}
interleaved = true;
/* We have the full RTP interleaved packet
* Write out the header including the leading '$' */
DEBUGF(infof(data, "RTP write channel %d rtp_length %d",
rtspc->rtp_channel, rtp_length));
result = rtp_client_write(data, &rtp[0], rtp_length + 4);
if(result) {
*readmore = FALSE;
return result;
}
if(!data->req.header)
rtspc->in_header = FALSE;
/* Move forward in the buffer */
rtp_dataleft -= rtp_length + 4;
rtp += rtp_length + 4;
if(data->set.rtspreq == RTSPREQ_RECEIVE) {
/* If we are in a passive receive, give control back
* to the app as often as we can.
*/
k->keepon &= ~KEEP_RECV;
}
}
else {
/* Need more - incomplete header */
*readmore = TRUE;
break;
}
}
else {
/* If the following data begins with 'RTSP/', which might be an RTSP
message, we should stop skipping the data. */
/* If `k-> headerline> 0 && !interleaved` is true, we are maybe in the
middle of an RTSP message. It is difficult to determine this, so we
stop skipping. */
size_t prefix_len = (rtp_dataleft < 5) ? rtp_dataleft : 5;
if((k->headerline > 0 && !interleaved) ||
strncmp(rtp, "RTSP/", prefix_len) == 0) {
if(skip_size > 0) {
DEBUGF(infof(data, "Skip the malformed interleaved data %lu "
"bytes", skip_size));
}
break; /* maybe is an RTSP message */
}
/* Skip incorrect data util the next RTP packet or RTSP message */
do {
rtp++;
rtp_dataleft--;
skip_size++;
} while(rtp_dataleft > 0 && rtp[0] != '$' && rtp[0] != 'R');
if(!rtspc->in_header) {
/* If header parsing is done and data left, extract RTP messages */
in_body = (data->req.headerline && !rtspc->in_header) &&
(data->req.size >= 0) &&
(data->req.bytecount < data->req.size);
result = rtsp_filter_rtp(data, conn, buf, blen, in_body, &consumed);
if(result)
goto out;
*pconsumed += consumed;
}
}
if(rtp_dataleft && rtp[0] == '$') {
DEBUGF(infof(data, "RTP Rewinding %zd %s", rtp_dataleft,
*readmore ? "(READMORE)" : ""));
if(rtspc->state != RTP_PARSE_SKIP)
*readmore = TRUE;
/* Store the incomplete RTP packet for a "rewind" */
if(!Curl_dyn_len(&rtspc->buf)) {
/* nothing was stored, add this data */
if(Curl_dyn_addn(&rtspc->buf, rtp, rtp_dataleft))
return CURLE_OUT_OF_MEMORY;
}
else {
/* keep the remainder */
Curl_dyn_tail(&rtspc->buf, rtp_dataleft);
}
/* As far as the transfer is concerned, this data is consumed */
*nread = 0;
return CURLE_OK;
out:
if(!*readmore && data->set.rtspreq == RTSPREQ_RECEIVE) {
/* In special mode RECEIVE, we just process one chunk of network
* data, so we stop the transfer here, if we have no incomplete
* RTP message pending. */
data->req.keepon &= ~KEEP_RECV;
}
/* Fix up k->str to point just after the last RTP packet */
k->str += *nread - rtp_dataleft;
*nread = rtp_dataleft;
/* If we get here, we have finished with the leftover/merge buffer */
Curl_dyn_free(&rtspc->buf);
return CURLE_OK;
return result;
}
static
CURLcode rtp_client_write(struct Curl_easy *data, char *ptr, size_t len)
CURLcode rtp_client_write(struct Curl_easy *data, const char *ptr, size_t len)
{
size_t wrote;
curl_write_callback writeit;
@@ -756,7 +857,7 @@ CURLcode rtp_client_write(struct Curl_easy *data, char *ptr, size_t len)
}
Curl_set_in_callback(data, true);
wrote = writeit(ptr, 1, len, user_ptr);
wrote = writeit((char *)ptr, 1, len, user_ptr);
Curl_set_in_callback(data, false);
if(CURL_WRITEFUNC_PAUSE == wrote) {
+9
View File
@@ -39,6 +39,12 @@ CURLcode Curl_rtsp_parseheader(struct Curl_easy *data, char *header);
#endif /* CURL_DISABLE_RTSP */
typedef enum {
RTP_PARSE_SKIP,
RTP_PARSE_CHANNEL,
RTP_PARSE_LEN,
RTP_PARSE_DATA
} rtp_parse_st;
/*
* RTSP Connection data
*
@@ -47,6 +53,9 @@ CURLcode Curl_rtsp_parseheader(struct Curl_easy *data, char *header);
struct rtsp_conn {
struct dynbuf buf;
int rtp_channel;
size_t rtp_len;
rtp_parse_st state;
BIT(in_header);
};
/****************************************************************************
+1 -1
View File
@@ -76,7 +76,7 @@ int Curl_wait_ms(timediff_t timeout_ms)
}
#if defined(MSDOS)
delay(timeout_ms);
#elif defined(WIN32)
#elif defined(_WIN32)
/* prevent overflow, timeout_ms is typecast to ULONG/DWORD. */
#if TIMEDIFF_T_MAX >= ULONG_MAX
if(timeout_ms >= ULONG_MAX)
+259 -75
View File
@@ -50,6 +50,7 @@
#include "strdup.h"
#include "http2.h"
#include "headers.h"
#include "progress.h"
#include "ws.h"
/* The last 3 #include files should be in this order */
@@ -57,6 +58,9 @@
#include "curl_memory.h"
#include "memdebug.h"
static CURLcode do_init_stack(struct Curl_easy *data);
#if defined(CURL_DO_LINEEND_CONV) && !defined(CURL_DISABLE_FTP)
/*
* convert_lineends() changes CRLF (\r\n) end-of-line markers to a single LF
@@ -385,17 +389,17 @@ static CURLcode chop_write(struct Curl_easy *data,
the future to leave the original data alone.
*/
CURLcode Curl_client_write(struct Curl_easy *data,
int type,
char *ptr,
size_t len)
int type, char *buf, size_t blen)
{
CURLcode result;
#if !defined(CURL_DISABLE_FTP) && defined(CURL_DO_LINEEND_CONV)
/* FTP data may need conversion. */
if((type & CLIENTWRITE_BODY) &&
(data->conn->handler->protocol & PROTO_FAMILY_FTP) &&
data->conn->proto.ftpc.transfertype == 'A') {
/* convert end-of-line markers */
len = convert_lineends(data, ptr, len);
blen = convert_lineends(data, buf, blen);
}
#endif
/* it is one of those, at least */
@@ -405,14 +409,14 @@ CURLcode Curl_client_write(struct Curl_easy *data,
/* INFO is only INFO */
DEBUGASSERT(!(type & CLIENTWRITE_INFO) || (type == CLIENTWRITE_INFO));
if(type == CLIENTWRITE_BODY) {
if(data->req.ignorebody)
return CURLE_OK;
if(data->req.writer_stack && !data->set.http_ce_skip)
return Curl_unencode_write(data, data->req.writer_stack, ptr, len);
if(!data->req.writer_stack) {
result = do_init_stack(data);
if(result)
return result;
DEBUGASSERT(data->req.writer_stack);
}
return chop_write(data, type, FALSE, ptr, len);
return Curl_cwriter_write(data, data->req.writer_stack, type, buf, blen);
}
CURLcode Curl_client_unpause(struct Curl_easy *data)
@@ -449,12 +453,12 @@ CURLcode Curl_client_unpause(struct Curl_easy *data)
void Curl_client_cleanup(struct Curl_easy *data)
{
struct contenc_writer *writer = data->req.writer_stack;
struct Curl_cwriter *writer = data->req.writer_stack;
size_t i;
while(writer) {
data->req.writer_stack = writer->downstream;
writer->handler->close_writer(data, writer);
data->req.writer_stack = writer->next;
writer->cwt->do_close(data, writer);
free(writer);
writer = data->req.writer_stack;
}
@@ -463,61 +467,222 @@ void Curl_client_cleanup(struct Curl_easy *data)
Curl_dyn_free(&data->state.tempwrite[i].b);
}
data->state.tempcount = 0;
data->req.bytecount = 0;
data->req.headerline = 0;
}
/* Real client writer: no downstream. */
static CURLcode client_cew_init(struct Curl_easy *data,
struct contenc_writer *writer)
/* Write data using an unencoding writer stack. "nbytes" is not
allowed to be 0. */
CURLcode Curl_cwriter_write(struct Curl_easy *data,
struct Curl_cwriter *writer, int type,
const char *buf, size_t nbytes)
{
(void) data;
if(!nbytes)
return CURLE_OK;
if(!writer)
return CURLE_WRITE_ERROR;
return writer->cwt->do_write(data, writer, type, buf, nbytes);
}
CURLcode Curl_cwriter_def_init(struct Curl_easy *data,
struct Curl_cwriter *writer)
{
(void)data;
(void)writer;
return CURLE_OK;
}
static CURLcode client_cew_write(struct Curl_easy *data,
struct contenc_writer *writer,
const char *buf, size_t nbytes)
CURLcode Curl_cwriter_def_write(struct Curl_easy *data,
struct Curl_cwriter *writer, int type,
const char *buf, size_t nbytes)
{
(void)writer;
if(!nbytes || data->req.ignorebody)
return CURLE_OK;
return chop_write(data, CLIENTWRITE_BODY, FALSE, (char *)buf, nbytes);
return Curl_cwriter_write(data, writer->next, type, buf, nbytes);
}
static void client_cew_close(struct Curl_easy *data,
struct contenc_writer *writer)
void Curl_cwriter_def_close(struct Curl_easy *data,
struct Curl_cwriter *writer)
{
(void) data;
(void) writer;
}
static const struct content_encoding client_cew = {
/* Real client writer to installed callbacks. */
static CURLcode cw_client_write(struct Curl_easy *data,
struct Curl_cwriter *writer, int type,
const char *buf, size_t nbytes)
{
(void)writer;
if(!nbytes)
return CURLE_OK;
return chop_write(data, type, FALSE, (char *)buf, nbytes);
}
static const struct Curl_cwtype cw_client = {
"client",
NULL,
Curl_cwriter_def_init,
cw_client_write,
Curl_cwriter_def_close,
sizeof(struct Curl_cwriter)
};
static size_t get_max_body_write_len(struct Curl_easy *data, curl_off_t limit)
{
if(limit != -1) {
/* How much more are we allowed to write? */
curl_off_t remain_diff;
remain_diff = limit - data->req.bytecount;
if(remain_diff < 0) {
/* already written too much! */
return 0;
}
#if SIZEOF_CURL_OFF_T > SIZEOF_SIZE_T
else if(remain_diff > SSIZE_T_MAX) {
return SIZE_T_MAX;
}
#endif
else {
return (size_t)remain_diff;
}
}
return SIZE_T_MAX;
}
/* Download client writer in phase CURL_CW_PROTOCOL that
* sees the "real" download body data. */
static CURLcode cw_download_write(struct Curl_easy *data,
struct Curl_cwriter *writer, int type,
const char *buf, size_t nbytes)
{
CURLcode result;
size_t nwrite, excess_len = 0;
const char *excess_data = NULL;
if(!(type & CLIENTWRITE_BODY)) {
if((type & CLIENTWRITE_CONNECT) && data->set.suppress_connect_headers)
return CURLE_OK;
return Curl_cwriter_write(data, writer->next, type, buf, nbytes);
}
nwrite = nbytes;
if(-1 != data->req.maxdownload) {
size_t wmax = get_max_body_write_len(data, data->req.maxdownload);
if(nwrite > wmax) {
excess_len = nbytes - wmax;
nwrite = wmax;
excess_data = buf + nwrite;
}
if(nwrite == wmax) {
data->req.download_done = TRUE;
}
}
if(data->set.max_filesize) {
size_t wmax = get_max_body_write_len(data, data->set.max_filesize);
if(nwrite > wmax) {
nwrite = wmax;
}
}
data->req.bytecount += nwrite;
++data->req.bodywrites;
if(!data->req.ignorebody && nwrite) {
result = Curl_cwriter_write(data, writer->next, type, buf, nwrite);
if(result)
return result;
}
result = Curl_pgrsSetDownloadCounter(data, data->req.bytecount);
if(result)
return result;
if(excess_len) {
if(data->conn->handler->readwrite) {
/* RTSP hack moved from transfer loop to here */
bool readmore = FALSE; /* indicates data is incomplete, need more */
size_t consumed = 0;
result = data->conn->handler->readwrite(data, data->conn,
excess_data, excess_len,
&consumed, &readmore);
if(result)
return result;
DEBUGASSERT(consumed <= excess_len);
excess_len -= consumed;
if(readmore) {
data->req.download_done = FALSE;
data->req.keepon |= KEEP_RECV; /* we're not done reading */
}
}
if(excess_len && !data->req.ignorebody) {
infof(data,
"Excess found writing body:"
" excess = %zu"
", size = %" CURL_FORMAT_CURL_OFF_T
", maxdownload = %" CURL_FORMAT_CURL_OFF_T
", bytecount = %" CURL_FORMAT_CURL_OFF_T,
excess_len, data->req.size, data->req.maxdownload,
data->req.bytecount);
connclose(data->conn, "excess found in a read");
}
}
else if(nwrite < nbytes) {
failf(data, "Exceeded the maximum allowed file size "
"(%" CURL_FORMAT_CURL_OFF_T ") with %"
CURL_FORMAT_CURL_OFF_T " bytes",
data->set.max_filesize, data->req.bytecount);
return CURLE_FILESIZE_EXCEEDED;
}
return CURLE_OK;
}
static const struct Curl_cwtype cw_download = {
"download",
NULL,
client_cew_init,
client_cew_write,
client_cew_close,
sizeof(struct contenc_writer)
Curl_cwriter_def_init,
cw_download_write,
Curl_cwriter_def_close,
sizeof(struct Curl_cwriter)
};
/* RAW client writer in phase CURL_CW_RAW that
* enabled tracing of raw data. */
static CURLcode cw_raw_write(struct Curl_easy *data,
struct Curl_cwriter *writer, int type,
const char *buf, size_t nbytes)
{
if(type & CLIENTWRITE_BODY && data->set.verbose && !data->req.ignorebody) {
Curl_debug(data, CURLINFO_DATA_IN, (char *)buf, nbytes);
}
return Curl_cwriter_write(data, writer->next, type, buf, nbytes);
}
static const struct Curl_cwtype cw_raw = {
"raw",
NULL,
Curl_cwriter_def_init,
cw_raw_write,
Curl_cwriter_def_close,
sizeof(struct Curl_cwriter)
};
/* Create an unencoding writer stage using the given handler. */
CURLcode Curl_client_create_writer(struct contenc_writer **pwriter,
CURLcode Curl_cwriter_create(struct Curl_cwriter **pwriter,
struct Curl_easy *data,
const struct content_encoding *ce_handler,
int order)
const struct Curl_cwtype *cwt,
Curl_cwriter_phase phase)
{
struct contenc_writer *writer;
struct Curl_cwriter *writer;
CURLcode result = CURLE_OUT_OF_MEMORY;
DEBUGASSERT(ce_handler->writersize >= sizeof(struct contenc_writer));
writer = (struct contenc_writer *) calloc(1, ce_handler->writersize);
DEBUGASSERT(cwt->cwriter_size >= sizeof(struct Curl_cwriter));
writer = (struct Curl_cwriter *) calloc(1, cwt->cwriter_size);
if(!writer)
goto out;
writer->handler = ce_handler;
writer->order = order;
result = ce_handler->init_writer(data, writer);
writer->cwt = cwt;
writer->phase = phase;
result = cwt->do_init(data, writer);
out:
*pwriter = result? NULL : writer;
@@ -526,55 +691,74 @@ out:
return result;
}
void Curl_client_free_writer(struct Curl_easy *data,
struct contenc_writer *writer)
void Curl_cwriter_free(struct Curl_easy *data,
struct Curl_cwriter *writer)
{
if(writer) {
writer->handler->close_writer(data, writer);
writer->cwt->do_close(data, writer);
free(writer);
}
}
/* allow no more than 5 "chained" compression steps */
#define MAX_ENCODE_STACK 5
static CURLcode init_writer_stack(struct Curl_easy *data)
size_t Curl_cwriter_count(struct Curl_easy *data, Curl_cwriter_phase phase)
{
DEBUGASSERT(!data->req.writer_stack);
return Curl_client_create_writer(&data->req.writer_stack,
data, &client_cew, 0);
struct Curl_cwriter *w;
size_t n = 0;
for(w = data->req.writer_stack; w; w = w->next) {
if(w->phase == phase)
++n;
}
return n;
}
CURLcode Curl_client_add_writer(struct Curl_easy *data,
struct contenc_writer *writer)
static CURLcode do_init_stack(struct Curl_easy *data)
{
struct Curl_cwriter *writer;
CURLcode result;
if(!data->req.writer_stack) {
result = init_writer_stack(data);
DEBUGASSERT(!data->req.writer_stack);
result = Curl_cwriter_create(&data->req.writer_stack,
data, &cw_client, CURL_CW_CLIENT);
if(result)
return result;
result = Curl_cwriter_create(&writer, data, &cw_download, CURL_CW_PROTOCOL);
if(result)
return result;
result = Curl_cwriter_add(data, writer);
if(result) {
Curl_cwriter_free(data, writer);
}
result = Curl_cwriter_create(&writer, data, &cw_raw, CURL_CW_RAW);
if(result)
return result;
result = Curl_cwriter_add(data, writer);
if(result) {
Curl_cwriter_free(data, writer);
}
return result;
}
CURLcode Curl_cwriter_add(struct Curl_easy *data,
struct Curl_cwriter *writer)
{
CURLcode result;
struct Curl_cwriter **anchor = &data->req.writer_stack;
if(!*anchor) {
result = do_init_stack(data);
if(result)
return result;
}
if(data->req.writer_stack_depth++ >= MAX_ENCODE_STACK) {
failf(data, "Reject response due to more than %u content encodings",
MAX_ENCODE_STACK);
return CURLE_BAD_CONTENT_ENCODING;
}
/* Stack the unencoding stage. */
if(writer->order >= data->req.writer_stack->order) {
writer->downstream = data->req.writer_stack;
data->req.writer_stack = writer;
}
else {
struct contenc_writer *w = data->req.writer_stack;
while(w->downstream && writer->order < w->downstream->order)
w = w->downstream;
writer->downstream = w->downstream;
w->downstream = writer;
}
/* Insert the writer as first in its phase.
* Skip existing writers of lower phases. */
while(*anchor && (*anchor)->phase < writer->phase)
anchor = &((*anchor)->next);
writer->next = *anchor;
*anchor = writer;
return CURLE_OK;
}
+103 -24
View File
@@ -50,43 +50,122 @@
#define CLIENTWRITE_1XX (1<<5) /* a 1xx response related HEADER */
#define CLIENTWRITE_TRAILER (1<<6) /* a trailer HEADER */
/**
* Write `len` bytes at `prt` to the client. `type` indicates what
* kind of data is being written.
*/
CURLcode Curl_client_write(struct Curl_easy *data, int type, char *ptr,
size_t len) WARN_UNUSED_RESULT;
/**
* For a paused transfer, there might be buffered data held back.
* Attempt to flush this data to the client. This *may* trigger
* another pause of the transfer.
*/
CURLcode Curl_client_unpause(struct Curl_easy *data);
/**
* Free all resources related to client writing.
*/
void Curl_client_cleanup(struct Curl_easy *data);
struct contenc_writer {
const struct content_encoding *handler; /* Encoding handler. */
struct contenc_writer *downstream; /* Downstream writer. */
unsigned int order; /* Ordering within writer stack. */
/**
* Client Writers - a chain passing transfer BODY data to the client.
* Main application: HTTP and related protocols
* Other uses: monitoring of download progress
*
* Writers in the chain are order by their `phase`. First come all
* writers in CURL_CW_RAW, followed by any in CURL_CW_TRANSFER_DECODE,
* followed by any in CURL_CW_PROTOCOL, etc.
*
* When adding a writer, it is inserted as first in its phase. This means
* the order of adding writers of the same phase matters, but writers for
* different phases may be added in any order.
*
* Writers which do modify the BODY data written are expected to be of
* phases TRANSFER_DECODE or CONTENT_DECODE. The other phases are intended
* for monitoring writers. Which do *not* modify the data but gather
* statistics or update progress reporting.
*/
/* Phase a writer operates at. */
typedef enum {
CURL_CW_RAW, /* raw data written, before any decoding */
CURL_CW_TRANSFER_DECODE, /* remove transfer-encodings */
CURL_CW_PROTOCOL, /* after transfer, but before content decoding */
CURL_CW_CONTENT_DECODE, /* remove content-encodings */
CURL_CW_CLIENT /* data written to client */
} Curl_cwriter_phase;
/* Client Writer Type, provides the implementation */
struct Curl_cwtype {
const char *name; /* writer name. */
const char *alias; /* writer name alias, maybe NULL. */
CURLcode (*do_init)(struct Curl_easy *data,
struct Curl_cwriter *writer);
CURLcode (*do_write)(struct Curl_easy *data,
struct Curl_cwriter *writer, int type,
const char *buf, size_t nbytes);
void (*do_close)(struct Curl_easy *data,
struct Curl_cwriter *writer);
size_t cwriter_size; /* sizeof() allocated struct Curl_cwriter */
};
/* Content encoding writer. */
struct content_encoding {
const char *name; /* Encoding name. */
const char *alias; /* Encoding name alias. */
CURLcode (*init_writer)(struct Curl_easy *data,
struct contenc_writer *writer);
CURLcode (*unencode_write)(struct Curl_easy *data,
struct contenc_writer *writer,
const char *buf, size_t nbytes);
void (*close_writer)(struct Curl_easy *data,
struct contenc_writer *writer);
size_t writersize;
/* Client writer instance */
struct Curl_cwriter {
const struct Curl_cwtype *cwt; /* type implementation */
struct Curl_cwriter *next; /* Downstream writer. */
Curl_cwriter_phase phase; /* phase at which it operates */
};
/**
* Create a new cwriter instance with given type and phase. Is not
* inserted into the writer chain by this call.
* Invokes `writer->do_init()`.
*/
CURLcode Curl_cwriter_create(struct Curl_cwriter **pwriter,
struct Curl_easy *data,
const struct Curl_cwtype *ce_handler,
Curl_cwriter_phase phase);
CURLcode Curl_client_create_writer(struct contenc_writer **pwriter,
struct Curl_easy *data,
const struct content_encoding *ce_handler,
int order);
/**
* Free a cwriter instance.
* Invokes `writer->do_close()`.
*/
void Curl_cwriter_free(struct Curl_easy *data,
struct Curl_cwriter *writer);
void Curl_client_free_writer(struct Curl_easy *data,
struct contenc_writer *writer);
/**
* Count the number of writers installed of the given phase.
*/
size_t Curl_cwriter_count(struct Curl_easy *data, Curl_cwriter_phase phase);
CURLcode Curl_client_add_writer(struct Curl_easy *data,
struct contenc_writer *writer);
/**
* Adds a writer to the transfer's writer chain.
* The writers `phase` determines where in the chain it is inserted.
*/
CURLcode Curl_cwriter_add(struct Curl_easy *data,
struct Curl_cwriter *writer);
/**
* Convenience method for calling `writer->do_write()` that
* checks for NULL writer.
*/
CURLcode Curl_cwriter_write(struct Curl_easy *data,
struct Curl_cwriter *writer, int type,
const char *buf, size_t nbytes);
/**
* Default implementations for do_init, do_write, do_close that
* do nothing and pass the data through.
*/
CURLcode Curl_cwriter_def_init(struct Curl_easy *data,
struct Curl_cwriter *writer);
CURLcode Curl_cwriter_def_write(struct Curl_easy *data,
struct Curl_cwriter *writer, int type,
const char *buf, size_t nbytes);
void Curl_cwriter_def_close(struct Curl_easy *data,
struct Curl_cwriter *writer);
/* internal read-function, does plain socket, SSL and krb4 */
+91 -129
View File
@@ -50,6 +50,7 @@
#include "multiif.h"
#include "altsvc.h"
#include "hsts.h"
#include "tftp.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
@@ -171,7 +172,7 @@ static CURLcode protocol2num(const char *str, curl_prot_t *val)
str = strchr(str, ',');
tlen = str? (size_t) (str - token): strlen(token);
if(tlen) {
const struct Curl_handler *h = Curl_builtin_scheme(token, tlen);
const struct Curl_handler *h = Curl_getn_scheme_handler(token, tlen);
if(!h)
return CURLE_UNSUPPORTED_PROTOCOL;
@@ -261,43 +262,43 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
* Set the absolute number of maximum simultaneous alive connection that
* libcurl is allowed to have.
*/
arg = va_arg(param, long);
if(arg < 0)
uarg = va_arg(param, unsigned long);
if(uarg > UINT_MAX)
return CURLE_BAD_FUNCTION_ARGUMENT;
data->set.maxconnects = arg;
data->set.maxconnects = (unsigned int)uarg;
break;
case CURLOPT_FORBID_REUSE:
/*
* When this transfer is done, it must not be left to be reused by a
* subsequent transfer but shall be closed immediately.
*/
data->set.reuse_forbid = (0 != va_arg(param, long)) ? TRUE : FALSE;
data->set.reuse_forbid = (0 != va_arg(param, long));
break;
case CURLOPT_FRESH_CONNECT:
/*
* This transfer shall not use a previously cached connection but
* should be made with a fresh new connect!
*/
data->set.reuse_fresh = (0 != va_arg(param, long)) ? TRUE : FALSE;
data->set.reuse_fresh = (0 != va_arg(param, long));
break;
case CURLOPT_VERBOSE:
/*
* Verbose means infof() calls that give a lot of information about
* the connection and transfer procedures as well as internal choices.
*/
data->set.verbose = (0 != va_arg(param, long)) ? TRUE : FALSE;
data->set.verbose = (0 != va_arg(param, long));
break;
case CURLOPT_HEADER:
/*
* Set to include the header in the general data output stream.
*/
data->set.include_header = (0 != va_arg(param, long)) ? TRUE : FALSE;
data->set.include_header = (0 != va_arg(param, long));
break;
case CURLOPT_NOPROGRESS:
/*
* Shut off the internal supported progress meter
*/
data->set.hide_progress = (0 != va_arg(param, long)) ? TRUE : FALSE;
data->set.hide_progress = (0 != va_arg(param, long));
if(data->set.hide_progress)
data->progress.flags |= PGRS_HIDE;
else
@@ -307,7 +308,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
/*
* Do not include the body part in the output data stream.
*/
data->set.opt_no_body = (0 != va_arg(param, long)) ? TRUE : FALSE;
data->set.opt_no_body = (0 != va_arg(param, long));
#ifndef CURL_DISABLE_HTTP
if(data->set.opt_no_body)
/* in HTTP lingo, no body means using the HEAD request... */
@@ -321,11 +322,10 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
* Don't output the >=400 error code HTML-page, but instead only
* return error.
*/
data->set.http_fail_on_error = (0 != va_arg(param, long)) ? TRUE : FALSE;
data->set.http_fail_on_error = (0 != va_arg(param, long));
break;
case CURLOPT_KEEP_SENDING_ON_ERROR:
data->set.http_keep_sending_on_error = (0 != va_arg(param, long)) ?
TRUE : FALSE;
data->set.http_keep_sending_on_error = (0 != va_arg(param, long));
break;
case CURLOPT_UPLOAD:
case CURLOPT_PUT:
@@ -353,7 +353,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
* Try to get the file time of the remote document. The time will
* later (possibly) become available using curl_easy_getinfo().
*/
data->set.get_filetime = (0 != va_arg(param, long)) ? TRUE : FALSE;
data->set.get_filetime = (0 != va_arg(param, long));
break;
case CURLOPT_SERVER_RESPONSE_TIMEOUT:
/*
@@ -379,7 +379,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
* TFTP option that specifies the block size to use for data transmission.
*/
arg = va_arg(param, long);
if(arg < 0)
if(arg > TFTP_BLKSIZE_MAX || arg < TFTP_BLKSIZE_MIN)
return CURLE_BAD_FUNCTION_ARGUMENT;
data->set.tftp_blksize = arg;
break;
@@ -409,7 +409,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
*
* Transfer using ASCII (instead of BINARY).
*/
data->set.prefer_ascii = (0 != va_arg(param, long)) ? TRUE : FALSE;
data->set.prefer_ascii = (0 != va_arg(param, long));
break;
case CURLOPT_TIMECONDITION:
/*
@@ -577,7 +577,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
/*
* Switch on automatic referer that gets set if curl follows locations.
*/
data->set.http_auto_referer = (0 != va_arg(param, long)) ? TRUE : FALSE;
data->set.http_auto_referer = (0 != va_arg(param, long));
break;
case CURLOPT_ACCEPT_ENCODING:
@@ -592,28 +592,23 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
*/
argptr = va_arg(param, char *);
if(argptr && !*argptr) {
argptr = Curl_all_content_encodings();
if(!argptr)
result = CURLE_OUT_OF_MEMORY;
else {
result = Curl_setstropt(&data->set.str[STRING_ENCODING], argptr);
free(argptr);
}
char all[256];
Curl_all_content_encodings(all, sizeof(all));
result = Curl_setstropt(&data->set.str[STRING_ENCODING], all);
}
else
result = Curl_setstropt(&data->set.str[STRING_ENCODING], argptr);
break;
case CURLOPT_TRANSFER_ENCODING:
data->set.http_transfer_encoding = (0 != va_arg(param, long)) ?
TRUE : FALSE;
data->set.http_transfer_encoding = (0 != va_arg(param, long));
break;
case CURLOPT_FOLLOWLOCATION:
/*
* Follow Location: header hints on an HTTP-server.
*/
data->set.http_follow_location = (0 != va_arg(param, long)) ? TRUE : FALSE;
data->set.http_follow_location = (0 != va_arg(param, long));
break;
case CURLOPT_UNRESTRICTED_AUTH:
@@ -621,8 +616,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
* Send authentication (user+password) when following locations, even when
* hostname changed.
*/
data->set.allow_auth_to_other_hosts =
(0 != va_arg(param, long)) ? TRUE : FALSE;
data->set.allow_auth_to_other_hosts = (0 != va_arg(param, long));
break;
case CURLOPT_MAXREDIRS:
@@ -736,7 +730,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
* Set header option.
*/
arg = va_arg(param, long);
data->set.sep_headers = (bool)((arg & CURLHEADER_SEPARATE)? TRUE: FALSE);
data->set.sep_headers = !!(arg & CURLHEADER_SEPARATE);
break;
#if !defined(CURL_DISABLE_COOKIES)
@@ -760,18 +754,18 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
return CURLE_BAD_FUNCTION_ARGUMENT;
/* append the cookie file name to the list of file names, and deal with
them later */
cl = curl_slist_append(data->set.cookielist, argptr);
cl = curl_slist_append(data->state.cookielist, argptr);
if(!cl) {
curl_slist_free_all(data->set.cookielist);
data->set.cookielist = NULL;
curl_slist_free_all(data->state.cookielist);
data->state.cookielist = NULL;
return CURLE_OUT_OF_MEMORY;
}
data->set.cookielist = cl; /* store the list for later use */
data->state.cookielist = cl; /* store the list for later use */
}
else {
/* clear the list of cookie files */
curl_slist_free_all(data->set.cookielist);
data->set.cookielist = NULL;
curl_slist_free_all(data->state.cookielist);
data->state.cookielist = NULL;
if(!data->share || !data->share->cookies) {
/* throw away all existing cookies if this isn't a shared cookie
@@ -811,17 +805,8 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
* prevent the forthcoming read-cookies-from-file actions to accept
* cookies that are marked as being session cookies, as they belong to a
* previous session.
*
* In the original Netscape cookie spec, "session cookies" are cookies
* with no expire date set. RFC2109 describes the same action if no
* 'Max-Age' is set and RFC2965 includes the RFC2109 description and adds
* a 'Discard' action that can enforce the discard even for cookies that
* have a Max-Age.
*
* We run mostly with the original cookie spec, as hardly anyone implements
* anything else.
*/
data->set.cookiesession = (0 != va_arg(param, long)) ? TRUE : FALSE;
data->set.cookiesession = (0 != va_arg(param, long));
break;
case CURLOPT_COOKIELIST:
@@ -956,7 +941,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
if(arg)
return CURLE_BAD_FUNCTION_ARGUMENT;
#else
data->set.http09_allowed = arg ? TRUE : FALSE;
data->set.http09_allowed = !!arg;
#endif
break;
@@ -997,8 +982,9 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
break;
case CURLOPT_MIME_OPTIONS:
data->set.mime_options = (unsigned int)va_arg(param, long);
break;
arg = va_arg(param, long);
data->set.mime_formescape = !!(arg & CURLMIMEOPT_FORMESCAPE);
break;
# endif
#endif
@@ -1018,8 +1004,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
/* the DIGEST_IE bit is only used to set a special marker, for all the
rest we need to handle it as normal DIGEST */
data->state.authhost.iestyle =
(bool)((auth & CURLAUTH_DIGEST_IE) ? TRUE : FALSE);
data->state.authhost.iestyle = !!(auth & CURLAUTH_DIGEST_IE);
if(auth & CURLAUTH_DIGEST_IE) {
auth |= CURLAUTH_DIGEST; /* set standard digest bit */
@@ -1072,8 +1057,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
/*
* Tunnel operations through the proxy instead of normal proxy use
*/
data->set.tunnel_thru_httpproxy = (0 != va_arg(param, long)) ?
TRUE : FALSE;
data->set.tunnel_thru_httpproxy = (0 != va_arg(param, long));
break;
case CURLOPT_PROXYPORT:
@@ -1102,8 +1086,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
/* the DIGEST_IE bit is only used to set a special marker, for all the
rest we need to handle it as normal DIGEST */
data->state.authproxy.iestyle =
(bool)((auth & CURLAUTH_DIGEST_IE) ? TRUE : FALSE);
data->state.authproxy.iestyle = !!(auth & CURLAUTH_DIGEST_IE);
if(auth & CURLAUTH_DIGEST_IE) {
auth |= CURLAUTH_DIGEST; /* set standard digest bit */
@@ -1203,7 +1186,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
/*
* Set flag for NEC SOCK5 support
*/
data->set.socks5_gssapi_nec = (0 != va_arg(param, long)) ? TRUE : FALSE;
data->set.socks5_gssapi_nec = (0 != va_arg(param, long));
break;
#endif
#ifndef CURL_DISABLE_PROXY
@@ -1251,7 +1234,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
* An option that changes the command to one that asks for a list only, no
* file info details. Used for FTP, POP3 and SFTP.
*/
data->set.list_only = (0 != va_arg(param, long)) ? TRUE : FALSE;
data->set.list_only = (0 != va_arg(param, long));
break;
#endif
case CURLOPT_APPEND:
@@ -1259,7 +1242,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
* We want to upload and append to an existing file. Used for FTP and
* SFTP.
*/
data->set.remote_append = (0 != va_arg(param, long)) ? TRUE : FALSE;
data->set.remote_append = (0 != va_arg(param, long));
break;
#ifndef CURL_DISABLE_FTP
@@ -1270,7 +1253,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
arg = va_arg(param, long);
if((arg < CURLFTPMETHOD_DEFAULT) || (arg >= CURLFTPMETHOD_LAST))
return CURLE_BAD_FUNCTION_ARGUMENT;
data->set.ftp_filemethod = (unsigned char)(curl_ftpfile)arg;
data->set.ftp_filemethod = (unsigned char)arg;
break;
case CURLOPT_FTPPORT:
/*
@@ -1278,26 +1261,26 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
*/
result = Curl_setstropt(&data->set.str[STRING_FTPPORT],
va_arg(param, char *));
data->set.ftp_use_port = (data->set.str[STRING_FTPPORT]) ? TRUE : FALSE;
data->set.ftp_use_port = !!(data->set.str[STRING_FTPPORT]);
break;
case CURLOPT_FTP_USE_EPRT:
data->set.ftp_use_eprt = (0 != va_arg(param, long)) ? TRUE : FALSE;
data->set.ftp_use_eprt = (0 != va_arg(param, long));
break;
case CURLOPT_FTP_USE_EPSV:
data->set.ftp_use_epsv = (0 != va_arg(param, long)) ? TRUE : FALSE;
data->set.ftp_use_epsv = (0 != va_arg(param, long));
break;
case CURLOPT_FTP_USE_PRET:
data->set.ftp_use_pret = (0 != va_arg(param, long)) ? TRUE : FALSE;
data->set.ftp_use_pret = (0 != va_arg(param, long));
break;
case CURLOPT_FTP_SSL_CCC:
arg = va_arg(param, long);
if((arg < CURLFTPSSL_CCC_NONE) || (arg >= CURLFTPSSL_CCC_LAST))
return CURLE_BAD_FUNCTION_ARGUMENT;
data->set.ftp_ccc = (unsigned char)(curl_ftpccc)arg;
data->set.ftp_ccc = (unsigned char)arg;
break;
case CURLOPT_FTP_SKIP_PASV_IP:
@@ -1305,7 +1288,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
* Enable or disable FTP_SKIP_PASV_IP, which will disable/enable the
* bypass of the IP address in PASV responses.
*/
data->set.ftp_skip_ip = (0 != va_arg(param, long)) ? TRUE : FALSE;
data->set.ftp_skip_ip = (0 != va_arg(param, long));
break;
case CURLOPT_FTP_ACCOUNT:
@@ -1333,7 +1316,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
*/
result = Curl_setstropt(&data->set.str[STRING_KRB_LEVEL],
va_arg(param, char *));
data->set.krb = (data->set.str[STRING_KRB_LEVEL]) ? TRUE : FALSE;
data->set.krb = !!(data->set.str[STRING_KRB_LEVEL]);
break;
#endif
#if !defined(CURL_DISABLE_FTP) || defined(USE_SSH)
@@ -1867,14 +1850,14 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
/*
* Kludgy option to enable CRLF conversions. Subject for removal.
*/
data->set.crlf = (0 != va_arg(param, long)) ? TRUE : FALSE;
data->set.crlf = (0 != va_arg(param, long));
break;
#ifndef CURL_DISABLE_PROXY
case CURLOPT_HAPROXYPROTOCOL:
/*
* Set to send the HAProxy Proxy Protocol header
*/
data->set.haproxyprotocol = (0 != va_arg(param, long)) ? TRUE : FALSE;
data->set.haproxyprotocol = (0 != va_arg(param, long));
break;
case CURLOPT_HAPROXY_CLIENT_IP:
/*
@@ -1926,22 +1909,17 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
/*
* Enable peer SSL verifying.
*/
data->set.ssl.primary.verifypeer = (0 != va_arg(param, long)) ?
TRUE : FALSE;
data->set.ssl.primary.verifypeer = (0 != va_arg(param, long));
/* Update the current connection ssl_config. */
if(data->conn) {
data->conn->ssl_config.verifypeer =
data->set.ssl.primary.verifypeer;
}
Curl_ssl_conn_config_update(data, FALSE);
break;
#ifndef CURL_DISABLE_DOH
case CURLOPT_DOH_SSL_VERIFYPEER:
/*
* Enable peer SSL verifying for DoH.
*/
data->set.doh_verifypeer = (0 != va_arg(param, long)) ?
TRUE : FALSE;
data->set.doh_verifypeer = (0 != va_arg(param, long));
break;
#endif
#ifndef CURL_DISABLE_PROXY
@@ -1953,10 +1931,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
(0 != va_arg(param, long))?TRUE:FALSE;
/* Update the current connection proxy_ssl_config. */
if(data->conn) {
data->conn->proxy_ssl_config.verifypeer =
data->set.proxy_ssl.primary.verifypeer;
}
Curl_ssl_conn_config_update(data, TRUE);
break;
#endif
case CURLOPT_SSL_VERIFYHOST:
@@ -1968,13 +1943,10 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
/* Obviously people are not reading documentation and too many thought
this argument took a boolean when it wasn't and misused it.
Treat 1 and 2 the same */
data->set.ssl.primary.verifyhost = (bool)((arg & 3) ? TRUE : FALSE);
data->set.ssl.primary.verifyhost = !!(arg & 3);
/* Update the current connection ssl_config. */
if(data->conn) {
data->conn->ssl_config.verifyhost =
data->set.ssl.primary.verifyhost;
}
Curl_ssl_conn_config_update(data, FALSE);
break;
#ifndef CURL_DISABLE_DOH
case CURLOPT_DOH_SSL_VERIFYHOST:
@@ -1984,7 +1956,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
arg = va_arg(param, long);
/* Treat both 1 and 2 as TRUE */
data->set.doh_verifyhost = (bool)((arg & 3) ? TRUE : FALSE);
data->set.doh_verifyhost = !!(arg & 3);
break;
#endif
#ifndef CURL_DISABLE_PROXY
@@ -1996,12 +1968,8 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
/* Treat both 1 and 2 as TRUE */
data->set.proxy_ssl.primary.verifyhost = (bool)((arg & 3)?TRUE:FALSE);
/* Update the current connection proxy_ssl_config. */
if(data->conn) {
data->conn->proxy_ssl_config.verifyhost =
data->set.proxy_ssl.primary.verifyhost;
}
Curl_ssl_conn_config_update(data, TRUE);
break;
#endif
case CURLOPT_SSL_VERIFYSTATUS:
@@ -2013,14 +1981,10 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
break;
}
data->set.ssl.primary.verifystatus = (0 != va_arg(param, long)) ?
TRUE : FALSE;
data->set.ssl.primary.verifystatus = (0 != va_arg(param, long));
/* Update the current connection ssl_config. */
if(data->conn) {
data->conn->ssl_config.verifystatus =
data->set.ssl.primary.verifystatus;
}
Curl_ssl_conn_config_update(data, FALSE);
break;
#ifndef CURL_DISABLE_DOH
case CURLOPT_DOH_SSL_VERIFYSTATUS:
@@ -2032,8 +1996,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
break;
}
data->set.doh_verifystatus = (0 != va_arg(param, long)) ?
TRUE : FALSE;
data->set.doh_verifystatus = (0 != va_arg(param, long));
break;
#endif
case CURLOPT_SSL_CTX_FUNCTION:
@@ -2067,12 +2030,12 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
break;
}
data->set.ssl.falsestart = (0 != va_arg(param, long)) ? TRUE : FALSE;
data->set.ssl.falsestart = (0 != va_arg(param, long));
break;
case CURLOPT_CERTINFO:
#ifdef USE_SSL
if(Curl_ssl_supports(data, SSLSUPP_CERTINFO))
data->set.ssl.certinfo = (0 != va_arg(param, long)) ? TRUE : FALSE;
data->set.ssl.certinfo = (0 != va_arg(param, long));
else
#endif
result = CURLE_NOT_BUILT_IN;
@@ -2118,14 +2081,14 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
* Specify entire PEM of the CA certificate
*/
#ifdef USE_SSL
if(Curl_ssl_supports(data, SSLSUPP_CAINFO_BLOB))
if(Curl_ssl_supports(data, SSLSUPP_CAINFO_BLOB)) {
result = Curl_setblobopt(&data->set.blobs[BLOB_CAINFO],
va_arg(param, struct curl_blob *));
break;
}
else
#endif
return CURLE_NOT_BUILT_IN;
break;
#ifndef CURL_DISABLE_PROXY
case CURLOPT_PROXY_CAINFO:
/*
@@ -2141,13 +2104,14 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
* Specify entire PEM of the CA certificate
*/
#ifdef USE_SSL
if(Curl_ssl_supports(data, SSLSUPP_CAINFO_BLOB))
if(Curl_ssl_supports(data, SSLSUPP_CAINFO_BLOB)) {
result = Curl_setblobopt(&data->set.blobs[BLOB_CAINFO_PROXY],
va_arg(param, struct curl_blob *));
break;
}
else
#endif
return CURLE_NOT_BUILT_IN;
break;
#endif
case CURLOPT_CAPATH:
/*
@@ -2278,7 +2242,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
* The application asks not to set any signal() or alarm() handlers,
* even when using a timeout.
*/
data->set.no_signal = (0 != va_arg(param, long)) ? TRUE : FALSE;
data->set.no_signal = (0 != va_arg(param, long));
break;
case CURLOPT_SHARE:
@@ -2453,11 +2417,11 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
* Enable or disable TCP_NODELAY, which will disable/enable the Nagle
* algorithm
*/
data->set.tcp_nodelay = (0 != va_arg(param, long)) ? TRUE : FALSE;
data->set.tcp_nodelay = (0 != va_arg(param, long));
break;
case CURLOPT_IGNORE_CONTENT_LENGTH:
data->set.ignorecl = (0 != va_arg(param, long)) ? TRUE : FALSE;
data->set.ignorecl = (0 != va_arg(param, long));
break;
case CURLOPT_CONNECT_ONLY:
@@ -2532,8 +2496,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
break;
case CURLOPT_SSL_SESSIONID_CACHE:
data->set.ssl.primary.sessionid = (0 != va_arg(param, long)) ?
TRUE : FALSE;
data->set.ssl.primary.sessionid = (0 != va_arg(param, long));
#ifndef CURL_DISABLE_PROXY
data->set.proxy_ssl.primary.sessionid = data->set.ssl.primary.sessionid;
#endif
@@ -2622,7 +2585,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
* disable libcurl transfer encoding is used
*/
#ifndef USE_HYPER
data->set.http_te_skip = (0 == va_arg(param, long)) ? TRUE : FALSE;
data->set.http_te_skip = (0 == va_arg(param, long));
break;
#else
return CURLE_NOT_BUILT_IN; /* hyper doesn't support */
@@ -2632,7 +2595,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
/*
* raw data passed to the application when content encoding is used
*/
data->set.http_ce_skip = (0 == va_arg(param, long)) ? TRUE : FALSE;
data->set.http_ce_skip = (0 == va_arg(param, long));
break;
#if !defined(CURL_DISABLE_FTP) || defined(USE_SSH)
@@ -2733,7 +2696,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
break;
case CURLOPT_MAIL_RCPT_ALLOWFAILS:
/* allow RCPT TO command to fail for some recipients */
data->set.mail_rcpt_allowfails = (0 != va_arg(param, long)) ? TRUE : FALSE;
data->set.mail_rcpt_allowfails = (0 != va_arg(param, long));
break;
#endif
@@ -2745,7 +2708,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
case CURLOPT_SASL_IR:
/* Enable/disable SASL initial response */
data->set.sasl_ir = (0 != va_arg(param, long)) ? TRUE : FALSE;
data->set.sasl_ir = (0 != va_arg(param, long));
break;
#ifndef CURL_DISABLE_RTSP
case CURLOPT_RTSP_REQUEST:
@@ -2859,7 +2822,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
#endif
#ifndef CURL_DISABLE_FTP
case CURLOPT_WILDCARDMATCH:
data->set.wildcard_enabled = (0 != va_arg(param, long)) ? TRUE : FALSE;
data->set.wildcard_enabled = (0 != va_arg(param, long));
break;
case CURLOPT_CHUNK_BGN_FUNCTION:
data->set.chunk_bgn = va_arg(param, curl_chunk_bgn_callback);
@@ -2942,7 +2905,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
break;
#endif
case CURLOPT_TCP_KEEPALIVE:
data->set.tcp_keepalive = (0 != va_arg(param, long)) ? TRUE : FALSE;
data->set.tcp_keepalive = (0 != va_arg(param, long));
break;
case CURLOPT_TCP_KEEPIDLE:
arg = va_arg(param, long);
@@ -2971,7 +2934,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
case CURLOPT_SSL_ENABLE_NPN:
break;
case CURLOPT_SSL_ENABLE_ALPN:
data->set.ssl_enable_alpn = (0 != va_arg(param, long)) ? TRUE : FALSE;
data->set.ssl_enable_alpn = (0 != va_arg(param, long));
break;
#ifdef USE_UNIX_SOCKETS
case CURLOPT_UNIX_SOCKET_PATH:
@@ -2987,10 +2950,10 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
#endif
case CURLOPT_PATH_AS_IS:
data->set.path_as_is = (0 != va_arg(param, long)) ? TRUE : FALSE;
data->set.path_as_is = (0 != va_arg(param, long));
break;
case CURLOPT_PIPEWAIT:
data->set.pipewait = (0 != va_arg(param, long)) ? TRUE : FALSE;
data->set.pipewait = (0 != va_arg(param, long));
break;
case CURLOPT_STREAM_WEIGHT:
#if defined(USE_HTTP2) || defined(USE_HTTP3)
@@ -3025,12 +2988,11 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
break;
#ifndef CURL_DISABLE_SHUFFLE_DNS
case CURLOPT_DNS_SHUFFLE_ADDRESSES:
data->set.dns_shuffle_addresses = (0 != va_arg(param, long)) ? TRUE:FALSE;
data->set.dns_shuffle_addresses = (0 != va_arg(param, long));
break;
#endif
case CURLOPT_DISALLOW_USERNAME_IN_URL:
data->set.disallow_username_in_url =
(0 != va_arg(param, long)) ? TRUE : FALSE;
data->set.disallow_username_in_url = (0 != va_arg(param, long));
break;
#ifndef CURL_DISABLE_DOH
case CURLOPT_DOH_URL:
@@ -3095,18 +3057,18 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
/* this needs to build a list of file names to read from, so that it can
read them later, as we might get a shared HSTS handle to load them
into */
h = curl_slist_append(data->set.hstslist, argptr);
h = curl_slist_append(data->state.hstslist, argptr);
if(!h) {
curl_slist_free_all(data->set.hstslist);
data->set.hstslist = NULL;
curl_slist_free_all(data->state.hstslist);
data->state.hstslist = NULL;
return CURLE_OUT_OF_MEMORY;
}
data->set.hstslist = h; /* store the list for later use */
data->state.hstslist = h; /* store the list for later use */
}
else {
/* clear the list of HSTS files */
curl_slist_free_all(data->set.hstslist);
data->set.hstslist = NULL;
curl_slist_free_all(data->state.hstslist);
data->state.hstslist = NULL;
if(!data->share || !data->share->hsts)
/* throw away the HSTS cache unless shared */
Curl_hsts_cleanup(&data->hsts);
+2 -11
View File
@@ -53,14 +53,14 @@
# ifndef NOGDI
# define NOGDI
# endif
# include <winerror.h>
# include <windows.h>
# ifdef HAVE_WINSOCK2_H
# include <winsock2.h>
# ifdef HAVE_WS2TCPIP_H
# include <ws2tcpip.h>
# endif
# endif
# include <windows.h>
# include <winerror.h>
# include <tchar.h>
# ifdef UNICODE
typedef wchar_t *(*curl_wcsdup_callback)(const wchar_t *str);
@@ -96,18 +96,12 @@
#ifndef _WIN32_WINNT_WS03
#define _WIN32_WINNT_WS03 0x0502 /* Windows Server 2003 */
#endif
#ifndef _WIN32_WINNT_WIN6
#define _WIN32_WINNT_WIN6 0x0600 /* Windows Vista */
#endif
#ifndef _WIN32_WINNT_VISTA
#define _WIN32_WINNT_VISTA 0x0600 /* Windows Vista */
#endif
#ifndef _WIN32_WINNT_WS08
#define _WIN32_WINNT_WS08 0x0600 /* Windows Server 2008 */
#endif
#ifndef _WIN32_WINNT_LONGHORN
#define _WIN32_WINNT_LONGHORN 0x0600 /* Windows Vista */
#endif
#ifndef _WIN32_WINNT_WIN7
#define _WIN32_WINNT_WIN7 0x0601 /* Windows 7 */
#endif
@@ -117,9 +111,6 @@
#ifndef _WIN32_WINNT_WINBLUE
#define _WIN32_WINNT_WINBLUE 0x0603 /* Windows 8.1 */
#endif
#ifndef _WIN32_WINNT_WINTHRESHOLD
#define _WIN32_WINNT_WINTHRESHOLD 0x0A00 /* Windows 10 */
#endif
#ifndef _WIN32_WINNT_WIN10
#define _WIN32_WINNT_WIN10 0x0A00 /* Windows 10 */
#endif
+1 -9
View File
@@ -31,14 +31,6 @@
#include "urldata.h"
#include "conncache.h"
/* SalfordC says "A structure member may not be volatile". Hence:
*/
#ifdef __SALFORDC__
#define CURL_VOLATILE
#else
#define CURL_VOLATILE volatile
#endif
#define CURL_GOOD_SHARE 0x7e117a1e
#define GOOD_SHARE_HANDLE(x) ((x) && (x)->magic == CURL_GOOD_SHARE)
@@ -46,7 +38,7 @@
struct Curl_share {
unsigned int magic; /* CURL_GOOD_SHARE */
unsigned int specifier;
CURL_VOLATILE unsigned int dirty;
volatile unsigned int dirty;
curl_lock_function lockfunc;
curl_unlock_function unlockfunc;
+1 -8
View File
@@ -27,7 +27,7 @@
#if !defined(CURL_DISABLE_SMB) && defined(USE_CURL_NTLM_CORE)
#ifdef WIN32
#ifdef _WIN32
#define getpid GetCurrentProcessId
#endif
@@ -1047,14 +1047,7 @@ static CURLcode smb_request_state(struct Curl_easy *data, bool *done)
break;
}
}
data->req.bytecount += len;
data->req.offset += len;
result = Curl_pgrsSetDownloadCounter(data, data->req.bytecount);
if(result) {
req->result = result;
next_state = SMB_CLOSE;
break;
}
next_state = (len < MAX_PAYLOAD_SIZE) ? SMB_CLOSE : SMB_DOWNLOAD;
break;
+1 -1
View File
@@ -1320,7 +1320,7 @@ static CURLcode smtp_init(struct Curl_easy *data)
CURLcode result = CURLE_OK;
struct SMTP *smtp;
smtp = data->req.p.smtp = calloc(sizeof(struct SMTP), 1);
smtp = data->req.p.smtp = calloc(1, sizeof(struct SMTP));
if(!smtp)
result = CURLE_OUT_OF_MEMORY;
+3 -3
View File
@@ -28,7 +28,7 @@
#include "rand.h"
#if !defined(HAVE_SOCKETPAIR) && !defined(CURL_DISABLE_SOCKETPAIR)
#ifdef WIN32
#ifdef _WIN32
/*
* This is a socketpair() implementation for Windows.
*/
@@ -50,7 +50,7 @@
#ifndef INADDR_LOOPBACK
#define INADDR_LOOPBACK 0x7f000001
#endif /* !INADDR_LOOPBACK */
#endif /* !WIN32 */
#endif /* !_WIN32 */
#include "nonblock.h" /* for curlx_nonblock */
#include "timeval.h" /* needed before select.h */
@@ -87,7 +87,7 @@ int Curl_socketpair(int domain, int type, int protocol,
socks[0] = socks[1] = CURL_SOCKET_BAD;
#if defined(WIN32) || defined(__CYGWIN__)
#if defined(_WIN32) || defined(__CYGWIN__)
/* don't set SO_REUSEADDR on Windows */
(void)reuse;
#ifdef SO_EXCLUSIVEADDRUSE

Some files were not shown because too many files have changed in this diff Show More