mirror of
https://github.com/Kitware/CMake.git
synced 2026-05-01 11:50:11 -05:00
Merge topic 'update-curl'
fe2fe52c86curl: Set build options the way we need for CMake548f0cfd1dMerge branch 'upstream-curl' into update-curlfe5ffe06a9curl 2023-12-06 (7161cb17)38f85b8390curl: 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:
@@ -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/*
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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")
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
@@ -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()
|
||||
|
||||
@@ -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__) && \
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 */
|
||||
|
||||
|
||||
@@ -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! */
|
||||
|
||||
@@ -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 */
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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 { \
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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) */
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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) */
|
||||
|
||||
@@ -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
@@ -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 */
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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 *
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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__)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user