Compare commits
149 Commits
curl-7_15_
...
curl-7_15_
Author | SHA1 | Date | |
---|---|---|---|
![]() |
1d3969b215 | ||
![]() |
94116d9ebc | ||
![]() |
cc5174a89a | ||
![]() |
31552100c5 | ||
![]() |
8df5dcb193 | ||
![]() |
7929600798 | ||
![]() |
a05ea124b9 | ||
![]() |
6a03ab3ad4 | ||
![]() |
6a151c1312 | ||
![]() |
990e56fb13 | ||
![]() |
2bd3033f68 | ||
![]() |
fe105a07e3 | ||
![]() |
a5782defd3 | ||
![]() |
bcccd2fe74 | ||
![]() |
404e23734b | ||
![]() |
973d63f4f2 | ||
![]() |
405d98ee63 | ||
![]() |
f81724969d | ||
![]() |
edb5444fa3 | ||
![]() |
e877cb7bd7 | ||
![]() |
482b3ba702 | ||
![]() |
752acedc0b | ||
![]() |
fb88723afc | ||
![]() |
3718737091 | ||
![]() |
3d3f056f7e | ||
![]() |
c60621c367 | ||
![]() |
606562aa7e | ||
![]() |
f689d06ca9 | ||
![]() |
7cfd7f3fb1 | ||
![]() |
4a8dfb3461 | ||
![]() |
3752b3aead | ||
![]() |
b81d41df22 | ||
![]() |
dadf3f06ee | ||
![]() |
8ed0d5675f | ||
![]() |
d5e9041344 | ||
![]() |
d99c20f628 | ||
![]() |
973ed24dc8 | ||
![]() |
5d5f5e3be8 | ||
![]() |
d9e14408f0 | ||
![]() |
c9c5ce2365 | ||
![]() |
975534370f | ||
![]() |
28605f6bd3 | ||
![]() |
3c6d3b69c2 | ||
![]() |
00312e95fe | ||
![]() |
4223130bb0 | ||
![]() |
c811e1ce70 | ||
![]() |
77475f2ad0 | ||
![]() |
3680a2f6f5 | ||
![]() |
1946058e7b | ||
![]() |
73daf8ce33 | ||
![]() |
094ceeba14 | ||
![]() |
3b7359a27a | ||
![]() |
df9108e19b | ||
![]() |
6307e783d8 | ||
![]() |
b9cd73c76d | ||
![]() |
b62c230ca2 | ||
![]() |
800193da9b | ||
![]() |
577ba5783c | ||
![]() |
9bece2b313 | ||
![]() |
e85e30546c | ||
![]() |
758f6eed51 | ||
![]() |
80ee5d3bd8 | ||
![]() |
dd06c60ada | ||
![]() |
6ca627ae74 | ||
![]() |
80a0b81c2a | ||
![]() |
06a7b0561b | ||
![]() |
12db20be4e | ||
![]() |
3cbb1b2b64 | ||
![]() |
d75e587613 | ||
![]() |
414c57d138 | ||
![]() |
c14a84e6f2 | ||
![]() |
def0db30e7 | ||
![]() |
6ef7a81a3b | ||
![]() |
95152aec68 | ||
![]() |
8ed6762363 | ||
![]() |
87c5ed8bec | ||
![]() |
ecc6c1f501 | ||
![]() |
3d8338b0d4 | ||
![]() |
c91e25518f | ||
![]() |
a8dddeab61 | ||
![]() |
8f0a5ab660 | ||
![]() |
db03d4bdd0 | ||
![]() |
0ec96e4279 | ||
![]() |
6e520c4cdc | ||
![]() |
1e8683d72d | ||
![]() |
2df622fd14 | ||
![]() |
fede784fa2 | ||
![]() |
f191b143e9 | ||
![]() |
59212553b5 | ||
![]() |
e532b196cc | ||
![]() |
0f5232280c | ||
![]() |
38898ba4af | ||
![]() |
48f56d9600 | ||
![]() |
17bf5ac2fc | ||
![]() |
343b882d80 | ||
![]() |
db06d21339 | ||
![]() |
19240f08bb | ||
![]() |
d774730f83 | ||
![]() |
c2edf42567 | ||
![]() |
08f0e55b4f | ||
![]() |
deeb74b7e4 | ||
![]() |
0542002d7a | ||
![]() |
c1e307f585 | ||
![]() |
7b4ba43dcf | ||
![]() |
b0e4debaab | ||
![]() |
676597e961 | ||
![]() |
686d90745b | ||
![]() |
5dc02d53c3 | ||
![]() |
0598547b58 | ||
![]() |
67c7745f5d | ||
![]() |
a2c289646d | ||
![]() |
e6efecd054 | ||
![]() |
778b6a86c0 | ||
![]() |
e5babd086d | ||
![]() |
c212ebbdda | ||
![]() |
83b8de3d43 | ||
![]() |
e174d374f2 | ||
![]() |
4edb93508d | ||
![]() |
38c994b83b | ||
![]() |
1b8643d4c9 | ||
![]() |
d3c796f5b0 | ||
![]() |
83d8a6a450 | ||
![]() |
a21a77d230 | ||
![]() |
260b88c197 | ||
![]() |
655331a91b | ||
![]() |
09e569f83d | ||
![]() |
e4a4b562c4 | ||
![]() |
35b4a755f9 | ||
![]() |
5a4b43848a | ||
![]() |
d98869a088 | ||
![]() |
4d33cf739d | ||
![]() |
34e7daf989 | ||
![]() |
b0adcd6a46 | ||
![]() |
be285cde3f | ||
![]() |
0ff1faf7f2 | ||
![]() |
bcc62cc9e3 | ||
![]() |
97b466d409 | ||
![]() |
f17d9bba14 | ||
![]() |
d74725ce67 | ||
![]() |
3dad55d7a8 | ||
![]() |
598ffeea89 | ||
![]() |
83367f67de | ||
![]() |
15f2647d71 | ||
![]() |
6421d69bff | ||
![]() |
18081e30e1 | ||
![]() |
97181b5c0d | ||
![]() |
a63f9887b9 | ||
![]() |
1282aad4a5 | ||
![]() |
b8fad99f09 |
1183
CHANGES.2005
Normal file
1183
CHANGES.2005
Normal file
File diff suppressed because it is too large
Load Diff
6
CVS-INFO
6
CVS-INFO
@@ -53,12 +53,6 @@ installed:
|
||||
give you an older version of the file that isn't up-to-date. That file was
|
||||
checked in once and won't be updated very regularly.
|
||||
|
||||
o yacc/bison
|
||||
|
||||
If you don't have yacc or bison, you must rename the lib/getdate.c.cvs file
|
||||
to lib/getdate.c to be able to build libcurl. yacc/bison is normally used
|
||||
to generate the lib/getdate.c file from the lib/getdate.y source file.
|
||||
|
||||
MAC OS X
|
||||
|
||||
With Mac OS X 10.2 and the associated Developer Tools, the installed versions
|
||||
|
29
README
29
README
@@ -33,34 +33,7 @@ WEB SITE
|
||||
Visit the curl web site or mirrors for the latest news and downloads:
|
||||
|
||||
Sweden http://curl.haxx.se/
|
||||
Australia http://curl.planetmirror.com/
|
||||
Austria http://curl.gds.tuwien.ac.at/
|
||||
Denmark http://curl.cofman.dk/
|
||||
France http://curl.fastmirror.net/
|
||||
Germany http://curl.freemirror.de/
|
||||
Germany http://curl.mirror-server.net/
|
||||
Germany http://curl.mirror.at.stealer.net/
|
||||
Germany http://curl.mirroring.de/
|
||||
Germany http://curl.miscellaneousmirror.org/
|
||||
Germany http://curl.mons-new-media.de/
|
||||
Germany http://curl.storemypix.com/
|
||||
Germany http://curl.triplemind.com/
|
||||
Hong Kong http://curl.hkmirror.org/
|
||||
Japan http://curl.s-lines.net/
|
||||
Netherlands http://curl.nedmirror.nl/
|
||||
Russia http://curl.tsuren.net/
|
||||
Taiwan http://curl.cs.pu.edu.tw/
|
||||
Thailand http://curl.siamu.ac.th/
|
||||
US (AZ) http://curl.islandofpoker.com/
|
||||
US (CA) http://curl.meulie.net/
|
||||
US (CA) http://curl.mirror.redwire.net/
|
||||
US (CA) http://curl.mirrormonster.com/
|
||||
US (CA) http://curl.signal42.com/
|
||||
US (FL) http://curl.hoxt.com/
|
||||
US (TX) http://curl.109k.com/
|
||||
US (TX) http://curl.hostingzero.com/
|
||||
US (TX) http://curl.mirrors.cyberservers.net/
|
||||
US (TX) http://curl.seekmeup.com/
|
||||
Mirrors http://curlm.haxx.se/
|
||||
|
||||
CVS
|
||||
|
||||
|
@@ -1,40 +1,72 @@
|
||||
Curl and libcurl 7.15.3
|
||||
Curl and libcurl 7.15.4
|
||||
|
||||
Public curl release number: 93
|
||||
Releases counted from the very beginning: 120
|
||||
Public curl release number: 94
|
||||
Releases counted from the very beginning: 121
|
||||
Available command line options: 112
|
||||
Available curl_easy_setopt() options: 129
|
||||
Number of public functions in libcurl: 46
|
||||
Amount of public web site mirrors: 31
|
||||
Available curl_easy_setopt() options: 132
|
||||
Number of public functions in libcurl: 49
|
||||
Amount of public web site mirrors: 33
|
||||
Number of known libcurl bindings: 32
|
||||
Number of contributors: 487
|
||||
Number of contributors: 492
|
||||
|
||||
This release includes the following changes:
|
||||
|
||||
o added docs for --ftp-method and CURLOPT_FTP_FILEMETHOD
|
||||
o NTLM2 session response support
|
||||
o CURLOPT_COOKIELIST set to "SESS" clears all session cookies
|
||||
o CURLINFO_LASTSOCKET returned sockets are now checked more before returned
|
||||
o curl-config got a --checkfor option to compare version numbers
|
||||
o line end conversions for FTP ASCII transfers
|
||||
o curl_multi_socket() API added (still mostly untested)
|
||||
o conversion callback options for EBCDIC <=> ASCII conversions
|
||||
o added CURLINFO_FTP_ENTRY_PATH
|
||||
o less blocking for the multi interface during (Open)SSL connect negotiation
|
||||
|
||||
This release includes the following bugfixes:
|
||||
|
||||
o TFTP Packet Buffer Overflow Vulnerability:
|
||||
http://curl.haxx.se/docs/adv_20060320.html
|
||||
o properly detecting problems with sending the FTP command USER
|
||||
o wrong error message shown when certificate verification failed
|
||||
o multi-part formpost with multi interface crash
|
||||
o the CURLFTPSSL_CONTROL setting for CURLOPT_FTP_SSL is acknowledged
|
||||
o "SSL: couldn't set callback" is now treated as a less serious problem
|
||||
o Interix build fix
|
||||
o fixed curl "hang" when out of file handles at start
|
||||
o prevent FTP uploads to URLs with trailing slash
|
||||
o builds fine on cygwin
|
||||
o md5-sess with Digest authentication
|
||||
o dict with letters such as space in a word
|
||||
o dict with url-encoded words in the URL
|
||||
o libcurl.m4 when default=yes but no libcurl was found
|
||||
o numerous bugs fixed in the TFTP code
|
||||
o possible memory leak when adding easy handles to multi stack
|
||||
o TFTP works in a more portable fashion (== on more platforms)
|
||||
o WSAGetLastError() is now used (better) on Windows
|
||||
o GnuTLS non-block case that could cause data trashing
|
||||
o deflate code survives lack of zlib header
|
||||
o CURLOPT_INTERFACE works with hostname
|
||||
o configure runs fine with ICC
|
||||
o closed control connection with FTP when easy handle was removed from multi
|
||||
o curl --trace crash when built with VS2005
|
||||
o SSL connect time-out
|
||||
o improved NTLM functionality
|
||||
o following redirects with more than one question mark in source URL
|
||||
o fixed debug build crash with -d
|
||||
o generates a fine AIX Toolbox RPM spec
|
||||
o treat FTP AUTH failures properly
|
||||
o TFTP transfers could trash data
|
||||
o -d + -G combo crash
|
||||
|
||||
Other curl-related news since the previous public release:
|
||||
Other curl-related news:
|
||||
|
||||
o pycurl-7.15.2 has been released: http://pycurl.sf.net
|
||||
o http://curl.download.nextag.com/ is a new US curl web mirror!
|
||||
o tclcurl 0.15.3 was released:
|
||||
http://personal1.iddeo.es/andresgarci/tclcurl/english/
|
||||
|
||||
New curl mirrors:
|
||||
|
||||
o http://curl.webdesign-zdg.de/ in Frankfurt, Germany
|
||||
o http://curl.de-mirror.de/ in Aachen, Germany
|
||||
o http://curl.osmirror.nl/ in Amsterdam, the Netherlands
|
||||
o http://curl.usphp.com/ in Florida, US
|
||||
o http://curl.oslevel.de/ in Karlsruhe, Germany
|
||||
|
||||
This release would not have looked like this without help, code, reports and
|
||||
advice from friends like these:
|
||||
|
||||
Gisle Vanem, Dan Fandrich, Thomas Klausner, Todd Vierling, Peter Heuchert,
|
||||
Markus Koetter, David McCreedy, Tor Arntsen
|
||||
Dan Fandrich, Ilja van Sprundel, David McCreedy, Tor Arntsen, Xavier Bouchoux,
|
||||
David Byron, Michele Bini, Ates Goral, Katie Wang, Robson Braga Araujo,
|
||||
Ale Vesely, Paul Querna, Gisle Vanem, Mark Eichin, Roland Blom, Andreas
|
||||
Ntaflos, David Shaw, Michael Wallner, Olaf St<53>ben, Mikael Sennerholm,
|
||||
Brian Dessent
|
||||
|
||||
Thanks! (and sorry if I forgot to mention someone)
|
||||
|
@@ -1,4 +1,5 @@
|
||||
To get fixed in 7.15.2 (planned release: Febrary 2006)
|
||||
To get fixed in 7.15.4 (planned release: June 2006)
|
||||
======================
|
||||
|
||||
65 -
|
||||
66 -
|
||||
|
||||
|
45
acinclude.m4
45
acinclude.m4
@@ -5,7 +5,7 @@
|
||||
# | (__| |_| | _ <| |___
|
||||
# \___|\___/|_| \_\_____|
|
||||
#
|
||||
# Copyright (C) 1998 - 2005, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
# Copyright (C) 1998 - 2006, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
#
|
||||
# This software is licensed as described in the file COPYING, which
|
||||
# you should have received as part of this distribution. The terms
|
||||
@@ -1105,12 +1105,44 @@ fi
|
||||
])
|
||||
|
||||
|
||||
dnl **********************************************************************
|
||||
dnl CURL_DETECT_ICC ([ACTION-IF-YES])
|
||||
dnl
|
||||
dnl check if this is the Intel ICC compiler, and if so run the ACTION-IF-YES
|
||||
dnl sets the $ICC variable to "yes" or "no"
|
||||
dnl **********************************************************************
|
||||
AC_DEFUN([CURL_DETECT_ICC],
|
||||
[
|
||||
ICC="no"
|
||||
AC_MSG_CHECKING([for icc in use])
|
||||
if test "$GCC" = "yes"; then
|
||||
dnl check if this is icc acting as gcc in disguise
|
||||
AC_EGREP_CPP([^__INTEL_COMPILER], [__INTEL_COMPILER],
|
||||
dnl action if the text is found, this it has not been replaced by the
|
||||
dnl cpp
|
||||
ICC="no",
|
||||
dnl the text was not found, it was replaced by the cpp
|
||||
ICC="yes"
|
||||
AC_MSG_RESULT([yes])
|
||||
[$1]
|
||||
)
|
||||
fi
|
||||
if test "$ICC" = "no"; then
|
||||
# this is not ICC
|
||||
AC_MSG_RESULT([no])
|
||||
fi
|
||||
])
|
||||
|
||||
dnl We create a function for detecting which compiler we use and then set as
|
||||
dnl pendantic compiler options as possible for that particular compiler. The
|
||||
dnl options are only used for debug-builds.
|
||||
|
||||
AC_DEFUN([CURL_CC_DEBUG_OPTS],
|
||||
[
|
||||
if test "z$ICC" = "z"; then
|
||||
CURL_DETECT_ICC
|
||||
fi
|
||||
|
||||
if test "$GCC" = "yes"; then
|
||||
|
||||
dnl figure out gcc version!
|
||||
@@ -1121,17 +1153,6 @@ AC_DEFUN([CURL_CC_DEBUG_OPTS],
|
||||
gccnum=`(expr $num1 "*" 100 + $num2) 2>/dev/null`
|
||||
AC_MSG_RESULT($gccver)
|
||||
|
||||
AC_MSG_CHECKING([if this is icc in disguise])
|
||||
AC_EGREP_CPP([^__INTEL_COMPILER], [__INTEL_COMPILER],
|
||||
dnl action if the text is found, this it has not been replaced by the
|
||||
dnl cpp
|
||||
ICC="no"
|
||||
AC_MSG_RESULT([no]),
|
||||
dnl the text was not found, it was replaced by the cpp
|
||||
ICC="yes"
|
||||
AC_MSG_RESULT([yes])
|
||||
)
|
||||
|
||||
if test "$ICC" = "yes"; then
|
||||
dnl this is icc, not gcc.
|
||||
|
||||
|
@@ -12,3 +12,5 @@ Gisle Vanem
|
||||
Gunter Knauf
|
||||
Henrik Stoerner
|
||||
Yang Tse
|
||||
Nick Mathewson
|
||||
Alexander Lazic
|
||||
|
17
ares/CHANGES
17
ares/CHANGES
@@ -1,5 +1,18 @@
|
||||
Changelog for the c-ares project
|
||||
|
||||
* May 10, 2006
|
||||
|
||||
- Bram Matthys brought my attention to a libtool peculiarity where detecting
|
||||
things such as C++ compiler actually is a bad thing and since we don't need
|
||||
that detection I added a work-around, much inspired by a previous patch by
|
||||
Paolo Bonzini. This also shortens the configure script quite a lot.
|
||||
|
||||
* May 3, 2006
|
||||
|
||||
- Nick Mathewson added the ARES_OPT_SOCK_STATE_CB option that when set makes
|
||||
c-ares call a callback on socket state changes. A better way than the
|
||||
ares_getsock() to get full control over the socket state.
|
||||
|
||||
* January 9, 2006
|
||||
|
||||
- Alexander Lazic improved the getservbyport_r() configure check.
|
||||
@@ -28,8 +41,8 @@
|
||||
|
||||
- Added constants that will be used by ares_getaddrinfo
|
||||
|
||||
- Made ares_getnameinfo use the reentrant getservbyport (getservbyport_r) if it is
|
||||
available to ensure it works properly in a threaded environment.
|
||||
- Made ares_getnameinfo use the reentrant getservbyport (getservbyport_r) if it
|
||||
is available to ensure it works properly in a threaded environment.
|
||||
|
||||
* September 10
|
||||
|
||||
|
@@ -43,7 +43,13 @@ VER=-version-info 1:0:0
|
||||
# set age to 0. (c:r:a=0)
|
||||
#
|
||||
|
||||
libcares_la_LDFLAGS = $(VER)
|
||||
if NO_UNDEFINED
|
||||
# The -no-undefined flag is crucial for this to build fine on some platforms
|
||||
UNDEF = -no-undefined
|
||||
endif
|
||||
|
||||
|
||||
libcares_la_LDFLAGS = $(UNDEF) $(VER)
|
||||
|
||||
# Makefile.inc provides the CSOURCES and HHEADERS defines
|
||||
include Makefile.inc
|
||||
|
@@ -20,7 +20,7 @@ endif
|
||||
TARGETS = adig.nlm ahost.nlm
|
||||
LTARGET = libcares.lib
|
||||
VERSION = $(LIBCARES_VERSION)
|
||||
COPYR = Copyright (C) 1996 - 2005, Daniel Stenberg, <daniel@haxx.se>
|
||||
COPYR = Copyright (C) 1996 - 2006, Daniel Stenberg, <daniel@haxx.se>
|
||||
DESCR = cURL $(subst .def,,$(notdir $@)) $(LIBCARES_VERSION_STR) - http://curl.haxx.se
|
||||
MTSAFE = YES
|
||||
STACK = 64000
|
||||
@@ -88,7 +88,7 @@ LD = nlmconv
|
||||
LDFLAGS = -T
|
||||
AR = ar
|
||||
ARFLAGS = -cq
|
||||
CFLAGS += -fno-builtin -fpack-struct -fpcc-struct-return -fno-strict-aliasing
|
||||
CFLAGS += -fno-builtin -fpcc-struct-return -fno-strict-aliasing
|
||||
CFLAGS += -Wall -Wno-format -Wno-uninitialized # -pedantic
|
||||
ifeq ($(LIBARCH),LIBC)
|
||||
PRELUDE = $(SDK_LIBC)/imports/libcpre.gcc.o
|
||||
@@ -256,8 +256,8 @@ config.h: Makefile.netware
|
||||
@echo $(DL)** All your changes will be lost!!$(DL) >> $@
|
||||
@echo $(DL)*/$(DL) >> $@
|
||||
@echo $(DL)#define OS "i586-pc-NetWare"$(DL) >> $@
|
||||
@echo $(DL)#define VERSION "$(LIBCURL_VERSION_STR)"$(DL) >> $@
|
||||
@echo $(DL)#define PACKAGE_BUGREPORT "curl-bug@haxx.se"$(DL) >> $@
|
||||
@echo $(DL)#define VERSION "$(LIBCARES_VERSION_STR)"$(DL) >> $@
|
||||
@echo $(DL)#define PACKAGE_BUGREPORT "a suitable curl mailing list => http://curl.haxx.se/mail/"$(DL) >> $@
|
||||
@echo $(DL)#define HAVE_ARPA_INET_H 1$(DL) >> $@
|
||||
@echo $(DL)#define HAVE_ARPA_NAMESER_H 1$(DL) >> $@
|
||||
@echo $(DL)#define HAVE_ASSERT_H 1$(DL) >> $@
|
||||
|
@@ -826,3 +826,39 @@ else
|
||||
fi
|
||||
])
|
||||
|
||||
# Prevent libtool for checking how to run C++ compiler and check for other
|
||||
# tools we don't want to use. We do this by m4-defining the _LT_AC_TAGCONFIG
|
||||
# variable to the code to run, as by default it uses a much more complicated
|
||||
# approach. The code below that is actually added seems to be used for cases
|
||||
# where configure has trouble figuring out what C compiler to use but where
|
||||
# the installed libtool has an idea.
|
||||
#
|
||||
# This function is a re-implemented version of the Paolo Bonzini fix posted to
|
||||
# the c-ares mailing list by Bram Matthys on May 6 2006. My version removes
|
||||
# redundant code but also adds the LTCFLAGS check that wasn't in that patch.
|
||||
#
|
||||
# Some code in this function was extracted from the generated configure script.
|
||||
#
|
||||
# CARES_CLEAR_LIBTOOL_TAGS
|
||||
AC_DEFUN([CARES_CLEAR_LIBTOOL_TAGS],
|
||||
[m4_define([_LT_AC_TAGCONFIG], [
|
||||
if test -f "$ltmain"; then
|
||||
if test ! -f "${ofile}"; then
|
||||
AC_MSG_WARN([output file `$ofile' does not exist])
|
||||
fi
|
||||
|
||||
if test -z "$LTCC"; then
|
||||
eval "`$SHELL ${ofile} --config | grep '^LTCC='`"
|
||||
if test -z "$LTCC"; then
|
||||
AC_MSG_WARN([output file `$ofile' does not look like a libtool
|
||||
script])
|
||||
else
|
||||
AC_MSG_WARN([using `LTCC=$LTCC', extracted from `$ofile'])
|
||||
fi
|
||||
fi
|
||||
if test -z "$LTCFLAGS"; then
|
||||
eval "`$SHELL ${ofile} --config | grep '^LTCFLAGS='`"
|
||||
fi
|
||||
fi
|
||||
])]
|
||||
)
|
||||
|
15
ares/ares.h
15
ares/ares.h
@@ -93,6 +93,7 @@ extern "C" {
|
||||
#define ARES_OPT_SERVERS (1 << 6)
|
||||
#define ARES_OPT_DOMAINS (1 << 7)
|
||||
#define ARES_OPT_LOOKUPS (1 << 8)
|
||||
#define ARES_OPT_SOCK_STATE_CB (1 << 9)
|
||||
|
||||
/* Nameinfo flag values */
|
||||
#define ARES_NI_NOFQDN (1 << 0)
|
||||
@@ -135,6 +136,18 @@ extern "C" {
|
||||
#define ARES_GETSOCK_WRITABLE(bits,num) (bits & (1 << ((num) + \
|
||||
ARES_GETSOCK_MAXNUM)))
|
||||
|
||||
#ifdef WIN32
|
||||
typedef void (*ares_sock_state_cb)(void *data,
|
||||
SOCKET socket,
|
||||
int readable,
|
||||
int writable);
|
||||
#else
|
||||
typedef void (*ares_sock_state_cb)(void *data,
|
||||
int socket,
|
||||
int readable,
|
||||
int writable);
|
||||
#endif
|
||||
|
||||
struct ares_options {
|
||||
int flags;
|
||||
int timeout;
|
||||
@@ -147,6 +160,8 @@ struct ares_options {
|
||||
char **domains;
|
||||
int ndomains;
|
||||
char *lookups;
|
||||
ares_sock_state_cb sock_state_cb;
|
||||
void *sock_state_cb_data;
|
||||
};
|
||||
|
||||
struct hostent;
|
||||
|
@@ -23,7 +23,7 @@
|
||||
#include "ares.h"
|
||||
#include "ares_private.h"
|
||||
|
||||
void ares__close_sockets(struct server_state *server)
|
||||
void ares__close_sockets(ares_channel channel, struct server_state *server)
|
||||
{
|
||||
struct send_request *sendreq;
|
||||
|
||||
@@ -46,11 +46,13 @@ void ares__close_sockets(struct server_state *server)
|
||||
/* Close the TCP and UDP sockets. */
|
||||
if (server->tcp_socket != ARES_SOCKET_BAD)
|
||||
{
|
||||
SOCK_STATE_CALLBACK(channel, server->tcp_socket, 0, 0);
|
||||
closesocket(server->tcp_socket);
|
||||
server->tcp_socket = ARES_SOCKET_BAD;
|
||||
}
|
||||
if (server->udp_socket != ARES_SOCKET_BAD)
|
||||
{
|
||||
SOCK_STATE_CALLBACK(channel, server->udp_socket, 0, 0);
|
||||
closesocket(server->udp_socket);
|
||||
server->udp_socket = ARES_SOCKET_BAD;
|
||||
}
|
||||
|
@@ -38,6 +38,6 @@ void ares_cancel(ares_channel channel)
|
||||
if (!(channel->flags & ARES_FLAG_STAYOPEN))
|
||||
{
|
||||
for (i = 0; i < channel->nservers; i++)
|
||||
ares__close_sockets(&channel->servers[i]);
|
||||
ares__close_sockets(channel, &channel->servers[i]);
|
||||
}
|
||||
}
|
||||
|
@@ -24,7 +24,7 @@ void ares_destroy(ares_channel channel)
|
||||
struct query *query;
|
||||
|
||||
for (i = 0; i < channel->nservers; i++)
|
||||
ares__close_sockets(&channel->servers[i]);
|
||||
ares__close_sockets(channel, &channel->servers[i]);
|
||||
free(channel->servers);
|
||||
for (i = 0; i < channel->ndomains; i++)
|
||||
free(channel->domains[i]);
|
||||
|
@@ -98,6 +98,24 @@ The lookups to perform for host queries.
|
||||
.I lookups
|
||||
should be set to a string of the characters "b" or "f", where "b"
|
||||
indicates a DNS lookup and "f" indicates a lookup in the hosts file.
|
||||
.TP 18
|
||||
.B ARES_OPT_SOCK_STATE_CB
|
||||
.B void (*\fIsock_state_cb\fP)(void *data, int s, int read, int write);
|
||||
.br
|
||||
.B void *\fIsock_state_cb_data\fP;
|
||||
.br
|
||||
A callback function to be invoked when a socket changes state.
|
||||
.I s
|
||||
will be passed the socket whose state has changed;
|
||||
.I read
|
||||
will be set to true if the socket should listen for read events, and
|
||||
.I write
|
||||
will be set to true if the socket should listen for write events.
|
||||
The value of
|
||||
.I sock_state_cb_data
|
||||
will be passed as the
|
||||
.I data
|
||||
argument.
|
||||
.PP
|
||||
The
|
||||
.I flags
|
||||
|
@@ -113,6 +113,7 @@ int ares_init_options(ares_channel *channelptr, struct ares_options *options,
|
||||
channel->queries = NULL;
|
||||
channel->domains = NULL;
|
||||
channel->sortlist = NULL;
|
||||
channel->sock_state_cb = NULL;
|
||||
|
||||
/* Initialize configuration by each of the four sources, from highest
|
||||
* precedence to lowest.
|
||||
@@ -192,6 +193,11 @@ static int init_by_options(ares_channel channel, struct ares_options *options,
|
||||
channel->udp_port = options->udp_port;
|
||||
if ((optmask & ARES_OPT_TCP_PORT) && channel->tcp_port == -1)
|
||||
channel->tcp_port = options->tcp_port;
|
||||
if ((optmask & ARES_OPT_SOCK_STATE_CB) && channel->sock_state_cb == NULL)
|
||||
{
|
||||
channel->sock_state_cb = options->sock_state_cb;
|
||||
channel->sock_state_cb_data = options->sock_state_cb_data;
|
||||
}
|
||||
|
||||
/* Copy the servers, if given. */
|
||||
if ((optmask & ARES_OPT_SERVERS) && channel->nservers == -1)
|
||||
|
@@ -176,13 +176,22 @@ struct ares_channeldata {
|
||||
|
||||
/* Active queries */
|
||||
struct query *queries;
|
||||
|
||||
ares_sock_state_cb sock_state_cb;
|
||||
void *sock_state_cb_data;
|
||||
};
|
||||
|
||||
void ares__send_query(ares_channel channel, struct query *query, time_t now);
|
||||
void ares__close_sockets(struct server_state *server);
|
||||
void ares__close_sockets(ares_channel channel, struct server_state *server);
|
||||
int ares__get_hostent(FILE *fp, int family, struct hostent **host);
|
||||
int ares__read_line(FILE *fp, char **buf, int *bufsize);
|
||||
|
||||
#define SOCK_STATE_CALLBACK(c, s, r, w) \
|
||||
do { \
|
||||
if ((c)->sock_state_cb) \
|
||||
(c)->sock_state_cb((c)->sock_state_cb_data, (s), (r), (w)); \
|
||||
} while (0)
|
||||
|
||||
#ifdef CURLDEBUG
|
||||
/* This is low-level hard-hacking memory leak tracking and similar. Using the
|
||||
libcurl lowlevel code from within library is ugly and only works when
|
||||
|
@@ -149,7 +149,10 @@ static void write_tcp_data(ares_channel channel, fd_set *write_fds, time_t now)
|
||||
wcount -= sendreq->len;
|
||||
server->qhead = sendreq->next;
|
||||
if (server->qhead == NULL)
|
||||
{
|
||||
SOCK_STATE_CALLBACK(channel, server->tcp_socket, 1, 0);
|
||||
server->qtail = NULL;
|
||||
}
|
||||
free(sendreq);
|
||||
}
|
||||
else
|
||||
@@ -179,7 +182,10 @@ static void write_tcp_data(ares_channel channel, fd_set *write_fds, time_t now)
|
||||
{
|
||||
server->qhead = sendreq->next;
|
||||
if (server->qhead == NULL)
|
||||
{
|
||||
SOCK_STATE_CALLBACK(channel, server->tcp_socket, 1, 0);
|
||||
server->qtail = NULL;
|
||||
}
|
||||
free(sendreq);
|
||||
}
|
||||
else
|
||||
@@ -380,7 +386,7 @@ static void handle_error(ares_channel channel, int whichserver, time_t now)
|
||||
struct query *query, *next;
|
||||
|
||||
/* Reset communications with this server. */
|
||||
ares__close_sockets(&channel->servers[whichserver]);
|
||||
ares__close_sockets(channel, &channel->servers[whichserver]);
|
||||
|
||||
/* Tell all queries talking to this server to move on and not try
|
||||
* this server again.
|
||||
@@ -452,7 +458,10 @@ void ares__send_query(ares_channel channel, struct query *query, time_t now)
|
||||
if (server->qtail)
|
||||
server->qtail->next = sendreq;
|
||||
else
|
||||
{
|
||||
SOCK_STATE_CALLBACK(channel, server->tcp_socket, 1, 1);
|
||||
server->qhead = sendreq;
|
||||
}
|
||||
server->qtail = sendreq;
|
||||
query->timeout = 0;
|
||||
}
|
||||
@@ -575,6 +584,7 @@ static int open_tcp_socket(ares_channel channel, struct server_state *server)
|
||||
}
|
||||
}
|
||||
|
||||
SOCK_STATE_CALLBACK(channel, s, 1, 0);
|
||||
server->tcp_buffer_pos = 0;
|
||||
server->tcp_socket = s;
|
||||
return 0;
|
||||
@@ -604,6 +614,8 @@ static int open_udp_socket(ares_channel channel, struct server_state *server)
|
||||
return -1;
|
||||
}
|
||||
|
||||
SOCK_STATE_CALLBACK(channel, s, 1, 0);
|
||||
|
||||
server->udp_socket = s;
|
||||
return 0;
|
||||
}
|
||||
@@ -714,7 +726,7 @@ static struct query *end_query (ares_channel channel, struct query *query, int s
|
||||
if (!channel->queries && !(channel->flags & ARES_FLAG_STAYOPEN))
|
||||
{
|
||||
for (i = 0; i < channel->nservers; i++)
|
||||
ares__close_sockets(&channel->servers[i]);
|
||||
ares__close_sockets(channel, &channel->servers[i]);
|
||||
}
|
||||
return (next);
|
||||
}
|
||||
|
@@ -47,6 +47,15 @@ AC_HELP_STRING([--disable-debug],[Disable debug options]),
|
||||
CPPFLAGS="$CPPFLAGS -DCURLDEBUG -I$srcdir/../include"
|
||||
CFLAGS="$CFLAGS -g"
|
||||
|
||||
dnl check for how to do large files, needed to get the curl_off_t check
|
||||
dnl done right
|
||||
AC_SYS_LARGEFILE
|
||||
|
||||
AC_CHECK_SIZEOF(curl_off_t, ,[
|
||||
#include <stdio.h>
|
||||
#include "$srcdir/../include/curl/curl.h"
|
||||
])
|
||||
|
||||
dnl set compiler "debug" options to become more picky, and remove
|
||||
dnl optimize options from CFLAGS
|
||||
CURL_CC_DEBUG_OPTS
|
||||
@@ -57,8 +66,21 @@ AC_HELP_STRING([--disable-debug],[Disable debug options]),
|
||||
)
|
||||
|
||||
dnl libtool setup
|
||||
CARES_CLEAR_LIBTOOL_TAGS
|
||||
AC_PROG_LIBTOOL
|
||||
|
||||
AC_MSG_CHECKING([if we need -no-undefined])
|
||||
case $host in
|
||||
*-*-cygwin | *-*-mingw* | *-*-pw32*)
|
||||
need_no_undefined=yes
|
||||
;;
|
||||
*)
|
||||
need_no_undefined=no
|
||||
;;
|
||||
esac
|
||||
AC_MSG_RESULT($need_no_undefined)
|
||||
AM_CONDITIONAL(NO_UNDEFINED, test x$need_no_undefined = xyes)
|
||||
|
||||
dnl Checks for header files.
|
||||
AC_HEADER_STDC
|
||||
|
||||
@@ -121,10 +143,6 @@ AC_C_CONST
|
||||
AC_TYPE_SIZE_T
|
||||
AC_HEADER_TIME
|
||||
|
||||
AC_CHECK_SIZEOF(curl_off_t, ,[
|
||||
#include <stdio.h>
|
||||
#include "$srcdir/include/curl/curl.h"
|
||||
])
|
||||
AC_CHECK_SIZEOF(size_t)
|
||||
AC_CHECK_SIZEOF(long)
|
||||
AC_CHECK_SIZEOF(time_t)
|
||||
@@ -428,7 +446,8 @@ int main()
|
||||
}
|
||||
], [
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_DEFINE_UNQUOTED(HAVE_INET_NTOP_IPV6,1,[Define to 1 if inet_ntop supports IPv6.])
|
||||
AC_DEFINE_UNQUOTED(HAVE_INET_NTOP_IPV6,1,
|
||||
[Define to 1 if inet_ntop supports IPv6.])
|
||||
], AC_MSG_RESULT(no),AC_MSG_RESULT(no))
|
||||
fi
|
||||
|
||||
@@ -494,13 +513,15 @@ dnl and get the types of five of its arguments.
|
||||
CURL_CHECK_FUNC_GETNAMEINFO
|
||||
|
||||
|
||||
dnl God bless non-standardized functions! We need to see which getservbyport_r variant is available
|
||||
dnl God bless non-standardized functions! We need to see which getservbyport_r
|
||||
dnl variant is available
|
||||
CARES_CHECK_GETSERVBYPORT_R
|
||||
|
||||
CURL_CHECK_NONBLOCKING_SOCKET
|
||||
|
||||
AC_C_BIGENDIAN(
|
||||
[AC_DEFINE(ARES_BIG_ENDIAN, 1, [define this if ares is built for a big endian system])],
|
||||
[AC_DEFINE(ARES_BIG_ENDIAN, 1,
|
||||
[define this if ares is built for a big endian system])],
|
||||
,
|
||||
[AC_MSG_WARN([couldn't figure out endianess, assuming little endian!])]
|
||||
)
|
||||
|
46
configure.ac
46
configure.ac
@@ -306,6 +306,13 @@ AC_HELP_STRING([--disable-manual],[Disable built-in manual]),
|
||||
dnl The actual use of the USE_MANUAL variable is done much later in this
|
||||
dnl script to allow other actions to disable it as well.
|
||||
|
||||
dnl **********************************************************************
|
||||
dnl check if this is the Intel ICC compiler, and if so make it stricter
|
||||
dnl (convert warning 147 into an error) so that it properly can detect the
|
||||
dnl gethostbyname_r() version
|
||||
dnl **********************************************************************
|
||||
CURL_DETECT_ICC([CFLAGS="$CFLAGS -we 147"])
|
||||
|
||||
dnl **********************************************************************
|
||||
dnl Checks for libraries.
|
||||
dnl **********************************************************************
|
||||
@@ -465,6 +472,15 @@ dnl **********************************************************************
|
||||
dnl Check for the presence of the winmm library.
|
||||
dnl **********************************************************************
|
||||
|
||||
case $host in
|
||||
*-*-cygwin*)
|
||||
dnl Under Cygwin, winmm exists but is not needed as WIN32 is not #defined
|
||||
dnl and gettimeofday() will be used regardless of the outcome of this test.
|
||||
dnl Skip this test, otherwise -lwinmm will be needlessly added to LIBS
|
||||
dnl (and recorded as such in the .la file, potentially affecting downstream
|
||||
dnl clients of the library.)
|
||||
;;
|
||||
*)
|
||||
AC_MSG_CHECKING([for timeGetTime in winmm])
|
||||
my_ac_save_LIBS=$LIBS
|
||||
LIBS="-lwinmm $LIBS"
|
||||
@@ -479,6 +495,8 @@ AC_TRY_LINK([#include <windef.h>
|
||||
LIBS=$my_ac_save_LIBS
|
||||
AC_MSG_RESULT(no)]
|
||||
)
|
||||
;;
|
||||
esac
|
||||
|
||||
dnl **********************************************************************
|
||||
dnl Checks for IPv6
|
||||
@@ -881,6 +899,12 @@ if test X"$OPT_SSL" != Xno; then
|
||||
fi
|
||||
|
||||
dnl This is for Msys/Mingw
|
||||
case $host in
|
||||
*-*-cygwin*)
|
||||
dnl Under Cygwin this is extraneous and causes an unnecessary -lgdi32
|
||||
dnl to be added to LIBS and recorded in the .la file.
|
||||
;;
|
||||
*)
|
||||
AC_MSG_CHECKING([for gdi32])
|
||||
my_ac_save_LIBS=$LIBS
|
||||
LIBS="-lgdi32 $LIBS"
|
||||
@@ -893,6 +917,8 @@ if test X"$OPT_SSL" != Xno; then
|
||||
LIBS=$my_ac_save_LIBS
|
||||
AC_MSG_RESULT(no)]
|
||||
)
|
||||
;;
|
||||
esac
|
||||
|
||||
AC_CHECK_LIB(crypto, CRYPTO_lock,[
|
||||
HAVECRYPTO="yes"
|
||||
@@ -940,9 +966,18 @@ if test X"$OPT_SSL" != Xno; then
|
||||
AC_DEFINE(USE_OPENSSL, 1, [if OpenSSL is in use]))
|
||||
|
||||
if test $ac_cv_header_openssl_x509_h = no; then
|
||||
AC_CHECK_HEADERS(x509.h rsa.h crypto.h pem.h ssl.h err.h,
|
||||
dnl we don't use the "action" part of the AC_CHECK_HEADERS macro
|
||||
dnl since 'err.h' might in fact find a krb4 header with the same
|
||||
dnl name
|
||||
AC_CHECK_HEADERS(x509.h rsa.h crypto.h pem.h ssl.h err.h)
|
||||
|
||||
if test $ac_cv_header_x509_h = yes &&
|
||||
test $ac_cv_header_crypto_h = yes &&
|
||||
test $ac_cv_header_ssl_h = yes; then
|
||||
dnl three matches
|
||||
curl_ssl_msg="enabled (OpenSSL)"
|
||||
OPENSSL_ENABLED=1)
|
||||
OPENSSL_ENABLED=1
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
@@ -1396,7 +1431,8 @@ if test x$cross_compiling != xyes; then
|
||||
AC_MSG_RESULT(no)
|
||||
,
|
||||
dnl not invoked when crosscompiling)
|
||||
])
|
||||
echo "hej"
|
||||
)
|
||||
fi
|
||||
else
|
||||
dnl and for crosscompilings
|
||||
@@ -1562,7 +1598,8 @@ AC_CHECK_FUNCS( strtoll \
|
||||
poll \
|
||||
getprotobyname \
|
||||
getrlimit \
|
||||
setrlimit,
|
||||
setrlimit \
|
||||
fork,
|
||||
dnl if found
|
||||
[],
|
||||
dnl if not found, $ac_func is the name we check for
|
||||
@@ -1956,6 +1993,7 @@ AC_CONFIG_FILES([Makefile \
|
||||
packages/vms/Makefile \
|
||||
packages/AIX/Makefile \
|
||||
packages/AIX/RPM/Makefile \
|
||||
packages/AIX/RPM/curl.spec \
|
||||
curl-config \
|
||||
libcurl.pc
|
||||
])
|
||||
|
@@ -1,10 +1,30 @@
|
||||
#! /bin/sh
|
||||
#***************************************************************************
|
||||
# _ _ ____ _
|
||||
# Project ___| | | | _ \| |
|
||||
# / __| | | | |_) | |
|
||||
# | (__| |_| | _ <| |___
|
||||
# \___|\___/|_| \_\_____|
|
||||
#
|
||||
# Copyright (C) 2001 - 2006, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
#
|
||||
# This software is licensed as described in the file COPYING, which
|
||||
# you should have received as part of this distribution. The terms
|
||||
# are also available at http://curl.haxx.se/docs/copyright.html.
|
||||
#
|
||||
# You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||
# copies of the Software, and permit persons to whom the Software is
|
||||
# furnished to do so, under the terms of the COPYING file.
|
||||
#
|
||||
# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
# KIND, either express or implied.
|
||||
#
|
||||
# $Id$
|
||||
###########################################################################
|
||||
#
|
||||
# The idea to this kind of setup info script was stolen from numerous
|
||||
# other packages, such as neon, libxml and gnome.
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
prefix=@prefix@
|
||||
exec_prefix=@exec_prefix@
|
||||
includedir=@includedir@
|
||||
@@ -19,6 +39,7 @@ Available values for OPTION include:
|
||||
--ca ca bundle install path
|
||||
--cc compiler
|
||||
--cflags pre-processor and compiler flags
|
||||
--checkfor [version] check for (lib)curl of the specified version
|
||||
--features newline separated list of enabled features
|
||||
--protocols newline separated list of enabled protocols
|
||||
--help display this help and exit
|
||||
@@ -122,6 +143,26 @@ while test $# -gt 0; do
|
||||
exit 0
|
||||
;;
|
||||
|
||||
--checkfor)
|
||||
checkfor=$2
|
||||
cmajor=`echo $checkfor | cut -d. -f1`
|
||||
cminor=`echo $checkfor | cut -d. -f2`
|
||||
# when extracting the patch part we strip off everything after a
|
||||
# dash as that's used for things like version 1.2.3-CVS
|
||||
cpatch=`echo $checkfor | cut -d. -f3 | cut -d- -f1`
|
||||
checknum=`echo "$cmajor*256*256 + $cminor*256 + ${cpatch:-0}" | bc`
|
||||
numuppercase=`echo @VERSIONNUM@ | tr 'a-f' 'A-F'`
|
||||
nownum=`echo "obase=10; ibase=16; $numuppercase" | bc`
|
||||
|
||||
if test "$nownum" -ge "$checknum"; then
|
||||
# silent success
|
||||
exit 0
|
||||
else
|
||||
echo "requested version $checkfor is newer than existing @VERSION@"
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
|
||||
--vernum)
|
||||
echo @VERSIONNUM@
|
||||
exit 0
|
||||
|
@@ -155,6 +155,11 @@ S-Lang
|
||||
S-Lang binding written by John E Davis
|
||||
http://www.jedsoft.org/slang/modules/curl.html
|
||||
|
||||
SPL
|
||||
|
||||
SPL binding written by Clifford Wolf
|
||||
http://www.clifford.at/spl/
|
||||
|
||||
Tcl
|
||||
|
||||
Tclcurl is written by Andr<64>s Garc<72>a
|
||||
@@ -173,3 +178,8 @@ wxWidgets
|
||||
|
||||
Written by Casey O'Donnell
|
||||
http://homepage.mac.com/codonnell/wxcurldav/
|
||||
|
||||
XBLite
|
||||
|
||||
Written by David Szafranski
|
||||
http://perso.wanadoo.fr/xblite/libraries.html
|
||||
|
@@ -1,12 +1,12 @@
|
||||
Date: October 27, 2005
|
||||
Date: May 15, 2006
|
||||
Author: Daniel Stenberg <daniel@haxx.se>
|
||||
URL: http://curl.haxx.se/legal/distro-dilemma.html
|
||||
|
||||
Condition
|
||||
|
||||
This document is written to describe the situation as it is right
|
||||
now. libcurl 7.15.0 is currently the latest version available. Things may (or
|
||||
perhaps will) of course change in the future.
|
||||
now. libcurl 7.15.3 is currently the latest version available. Things may of
|
||||
course change in the future.
|
||||
|
||||
This document reflects my view and understanding of these things. Please tell
|
||||
me where and how you think I'm wrong, and I'll try to correct my mistakes.
|
||||
@@ -16,11 +16,10 @@ Background
|
||||
The Free Software Foundation has deemed the Original BSD license[1] to be
|
||||
"incompatible"[2] with GPL[3]. I'd rather say it is the other way around, but
|
||||
the point is the same: if you distribute a binary version of a GPL program,
|
||||
it MUST NOT be linked with any Original BSD-licensed parts or
|
||||
libraries. Doing so will violate the GPL license. For a long time, very many
|
||||
GPL licensed programs have avoided this license mess by adding an
|
||||
exception[8] to their license. And many others have just closed their eyes
|
||||
for this problem.
|
||||
it MUST NOT be linked with any Original BSD-licensed parts or libraries.
|
||||
Doing so will violate the GPL license. For a long time, very many GPL
|
||||
licensed programs have avoided this license mess by adding an exception[8] to
|
||||
their license. And many others have just closed their eyes for this problem.
|
||||
|
||||
libcurl is MIT-style[4] licensed - how on earth did this dilemma fall onto
|
||||
our plates?
|
||||
@@ -49,25 +48,13 @@ Part of the Operating System
|
||||
Debian does however not take this stance and has officially(?) claimed that
|
||||
OpenSSL is not a required part of the Debian operating system
|
||||
|
||||
Debian-legal
|
||||
|
||||
In August 2004 I figured I should start pulling people's attention to this to
|
||||
see if anyone has any bright ideas or if they would dismiss my worries based
|
||||
on some elegant writing I had missed somewhere:
|
||||
|
||||
My post to debian-legal on August 12 2004:
|
||||
|
||||
http://lists.debian.org/debian-legal/2004/08/msg00279.html
|
||||
|
||||
Several people agreed then that this is a known and rather big problem, but
|
||||
the following discussion didn't result in much.
|
||||
|
||||
GnuTLS
|
||||
|
||||
With the release of libcurl 7.14.0 (May 2005), it can now get built to use
|
||||
GnuTLS instead of OpenSSL. GnuTLS is a LGPL[7] licensed library that offers a
|
||||
matching set of features as OpenSSL does. Now, you can build and distribute
|
||||
an SSL capable libcurl without including any Original BSD licensed code.
|
||||
With the release of libcurl 7.14.0 (May 2005), libcurl can now get built to
|
||||
use GnuTLS instead of OpenSSL. GnuTLS is an LGPL[7] licensed library that
|
||||
offers a matching set of features as OpenSSL does. Now, you can build and
|
||||
distribute an TLS/SSL capable libcurl without including any Original BSD
|
||||
licensed code.
|
||||
|
||||
I believe Debian is the first distro to provide libcurl/GnutTLS packages.
|
||||
|
||||
@@ -80,23 +67,20 @@ GnuTLS vs OpenSSL
|
||||
and it has not been tested nor used very extensively, while the OpenSSL
|
||||
equivalent code has been used and thus matured for more than seven (7) years.
|
||||
|
||||
In August 2005, the debian-devel mailing list discovered the license issue as
|
||||
a GPL licensed application wanted SSL capabilities from libcurl and thus was
|
||||
forced to use the GnuTLS powered libcurl. For a reason that is unknown to me,
|
||||
the application authors didn't want to or was unable to add an exception to
|
||||
their GPL license. Alas, the license problem hit the fan again.
|
||||
|
||||
GnuTLS
|
||||
- LGPL licensened
|
||||
- supports SRP
|
||||
- lacks SSLv2 support
|
||||
- lacks MD2 support (used by at least some CA certs)
|
||||
- lacks the crypto functions libcurl uses for NTLM
|
||||
|
||||
OpenSSL
|
||||
- Original BSD licensened
|
||||
- lacks SRP
|
||||
- supports SSLv2
|
||||
- older and more widely used
|
||||
- provides crypto functions libcurl uses for NTLM
|
||||
- libcurl can do non-blocking connects with it in 7.15.4 and later
|
||||
|
||||
The Better License, Original BSD or LGPL?
|
||||
|
||||
@@ -124,20 +108,21 @@ More SSL Libraries
|
||||
Application Angle of this Problem
|
||||
|
||||
libcurl is built to use one SSL/TLS library. It uses a single fixed name (by
|
||||
default), and applications are built/linked to use that single lib. Replacing
|
||||
one libcurl instance with another one that uses the other SSL/TLS library
|
||||
might break one or more applications (due to ABI differences and/or different
|
||||
feature set). You want your application to use the libcurl it was built for.
|
||||
default) on the built/created lib file, and applications are built/linked to
|
||||
use that single lib. Replacing one libcurl instance with another one that
|
||||
uses the other SSL/TLS library might break one or more applications (due to
|
||||
ABI differences and/or different feature set). You want your application to
|
||||
use the libcurl it was built for.
|
||||
|
||||
Project cURL Angle of this Problem
|
||||
|
||||
We distribute libcurl and everyone may build libcurl with either library. At
|
||||
We distribute libcurl and everyone may build libcurl with either library at
|
||||
their choice. This problem is not directly a problem of ours. It merely
|
||||
affects users - GPL application authors only - of our lib as it comes
|
||||
included and delivered on some distros.
|
||||
|
||||
libcurl has different ABI when built with different SSL/TLS libraries due to
|
||||
two reasons:
|
||||
these reasons:
|
||||
|
||||
1. No one has worked on fixing this. The mutex/lock callbacks should be set
|
||||
with a generic libcurl function that should use the proper underlying
|
||||
@@ -146,25 +131,25 @@ Project cURL Angle of this Problem
|
||||
2. The CURLOPT_SSL_CTX_FUNCTION option is not possible to "emulate" on GnuTLS
|
||||
but simply requires OpenSSL.
|
||||
|
||||
3. There might be some other subtle differences just because nobody has yet
|
||||
tried to make a fixed ABI like this.
|
||||
|
||||
Distro Angle of this Problem
|
||||
|
||||
A distro can provide separate libcurls built with different SSL/TLS libraries
|
||||
to work around this, but at least Debian seems to be very hostile against
|
||||
such an approach, probably since it makes things like devel packages for the
|
||||
different libs collide since they would provide the same include files and
|
||||
man pages etc.
|
||||
To my knowledge there is only one distro that ships libcurl built with either
|
||||
one of the SSL libs supported.
|
||||
|
||||
Debian Linux is now (since mid September 2005) providing two different
|
||||
libcurl packages, one for libcurl built with OpenSSL and one built with
|
||||
GnuTLS. They use different .so names and can this both be installed in a
|
||||
single system simultaneously. This has been said to be a transitional system
|
||||
not desired to keep in the long run.
|
||||
|
||||
Fixing the Only Problem
|
||||
|
||||
The only problem is thus for distributions that want to offer libcurl
|
||||
versions built with more than one SSL/TLS library.
|
||||
|
||||
Debian is now (since mid September 2005) providing two different devel
|
||||
packages, one for libcurl built with OpenSSL and one built with GnuTLS. They
|
||||
use different .so names and can this both be installed in a single system
|
||||
simultaneously. This has previously been said as a transitional system not
|
||||
desired to keep in the long run.
|
||||
|
||||
Since multiple libcurl binaries using different names are ruled out, we need
|
||||
to come up with a way to have one single libcurl that someone uses different
|
||||
underlying libraries. The best(?) approach currently suggested involves this:
|
||||
@@ -194,9 +179,9 @@ Fixing the Only Problem
|
||||
|
||||
When Will This Happen
|
||||
|
||||
Note again that this is not a problem in curl, it doesn't solve any actual
|
||||
technical problems in our project. Don't hold your breath for this to happen
|
||||
very soon (if at all) unless you step forward and contribute.
|
||||
This is not a problem in curl, it doesn't solve any actual technical problems
|
||||
in our project. Don't hold your breath for this to happen very soon (if at
|
||||
all) unless you step forward and contribute.
|
||||
|
||||
The suggestion that is outlined above is still only a suggestion. Feel free
|
||||
to bring a better idea!
|
||||
@@ -206,7 +191,7 @@ When Will This Happen
|
||||
code like today (without the use of lib2), should you decide to ignore the
|
||||
problems outlined in this document.
|
||||
|
||||
Update: Work on this has been initiated by Richard Atterer:
|
||||
Work on this was suggested by Richard Atterer:
|
||||
|
||||
http://curl.haxx.se/mail/lib-2005-09/0066.html
|
||||
|
||||
|
@@ -91,8 +91,8 @@ FTP
|
||||
- no dir depth limit
|
||||
|
||||
FTPS (*1)
|
||||
- explicit ftps:// support that use SSL on both connections
|
||||
- implicit "AUTH TSL" and "AUTH SSL" usage to "upgrade" plain ftp://
|
||||
- implicit ftps:// support that use SSL on both connections
|
||||
- explicit "AUTH TSL" and "AUTH SSL" usage to "upgrade" plain ftp://
|
||||
connection to use SSL for both or one of the connections
|
||||
|
||||
TFTP
|
||||
|
@@ -3,6 +3,15 @@ join in and help us correct one or more of these! Also be sure to check the
|
||||
changelog of the current development status, as one or more of these problems
|
||||
may have been fixed since this was written!
|
||||
|
||||
34. The SOCKS connection codes don't properly acknowledge (connect) timeouts.
|
||||
|
||||
33. Doing multi-pass HTTP authentication on a non-default port does not work.
|
||||
This happens because the multi-pass code abuses the redirect following code
|
||||
for doing multiple requests, and when we following redirects to an absolute
|
||||
URL we must use the newly specified port and not the one specified in the
|
||||
original URL. A proper fix to this would need to separate the negotiation
|
||||
"redirect" from an actual redirect.
|
||||
|
||||
32. (At least on Windows) If libcurl is built with c-ares and there's no DNS
|
||||
server configured in the system, the ares_init() call fails and thus
|
||||
curl_easy_init() fails as well. This causes weird effects for people who use
|
||||
@@ -26,8 +35,6 @@ may have been fixed since this was written!
|
||||
|
||||
See http://curl.haxx.se/bug/view.cgi?id=1371118
|
||||
|
||||
28. The TFTP code is not portable and will fail on some architectures.
|
||||
|
||||
26. NTLM authentication using SSPI (on Windows) when (lib)curl is running in
|
||||
"system context" will make it use wrong(?) user name - at least when compared
|
||||
to what winhttp does. See http://curl.haxx.se/bug/view.cgi?id=1281867
|
||||
@@ -59,6 +66,8 @@ may have been fixed since this was written!
|
||||
specification). The receiver will convert the data from the standard
|
||||
form to his own internal form.
|
||||
|
||||
Since 7.15.4 at least line endings are converted.
|
||||
|
||||
19. FTP 3rd party transfers with the multi interface doesn't work. Test:
|
||||
define CURL_MULTIEASY, rebuild curl, run test case 230 - 232.
|
||||
|
||||
|
@@ -726,7 +726,7 @@ LDAP
|
||||
Working with LDAP URLs":
|
||||
http://developer.netscape.com/docs/manuals/dirsdk/csdk30/url.htm
|
||||
|
||||
RFC 2255, "The LDAP URL Format" http://www.rfc-editor.org/rfc/rfc2255.txt
|
||||
RFC 2255, "The LDAP URL Format" http://curl.haxx.se/rfc/rfc2255.txt
|
||||
|
||||
To show you an example, this is now I can get all people from my local LDAP
|
||||
server that has a certain sub-domain in their email address:
|
||||
|
@@ -96,6 +96,7 @@ David James
|
||||
David Kimdon
|
||||
David Lang
|
||||
David LeBlanc
|
||||
David McCreedy
|
||||
David Odin
|
||||
David Phillips
|
||||
David Shaw
|
||||
@@ -293,6 +294,7 @@ Marco G. Salvagno
|
||||
Marcus Webster
|
||||
Mario Schroeder
|
||||
Mark Butler
|
||||
Markus Koetter
|
||||
Markus Moeller
|
||||
Markus Oberhumer
|
||||
Martijn Koster
|
||||
@@ -356,6 +358,7 @@ Pedro Neves
|
||||
Pete Su
|
||||
Peter Bray
|
||||
Peter Forret
|
||||
Peter Heuchert
|
||||
Peter Pentchev
|
||||
Peter Su
|
||||
Peter Sylvester
|
||||
@@ -445,6 +448,7 @@ S
|
||||
T. Bharath
|
||||
T. Yamada
|
||||
Temprimus
|
||||
Thomas Klausner
|
||||
Thomas Schwinge
|
||||
Thomas Tonino
|
||||
Tim Baker
|
||||
@@ -453,6 +457,7 @@ Tim Costello
|
||||
Tim Sneddon
|
||||
Toby Peterson
|
||||
Todd Kulesza
|
||||
Todd Vierling
|
||||
Tom Benoist
|
||||
Tom Lee
|
||||
Tom Mattison
|
||||
|
25
docs/TODO
25
docs/TODO
@@ -14,12 +14,6 @@ TODO
|
||||
|
||||
LIBCURL
|
||||
|
||||
* Introduce an interface to libcurl that allows applications to easier get to
|
||||
know what cookies that are received. CURLINFO_COOKIELIST to get a
|
||||
curl_slist with cookies (netscape/mozilla cookie file formatted), and
|
||||
CURLOPT_COOKIELIST to set a list of cookies (using the same format).
|
||||
http://curl.haxx.se/mail/lib-2004-12/0195.html
|
||||
|
||||
* Introduce another callback interface for upload/download that makes one
|
||||
less copy of data and thus a faster operation.
|
||||
[http://curl.haxx.se/dev/no_copy_callbacks.txt]
|
||||
@@ -64,13 +58,8 @@ TODO
|
||||
|
||||
LIBCURL - multi interface
|
||||
|
||||
* Add a curl_multi_fdset() alternative. this allows apps to avoid the
|
||||
FD_SETSIZE problem with select().
|
||||
|
||||
* Add curl_multi_timeout() to make libcurl's ares-functionality better.
|
||||
|
||||
* Make sure we don't ever loop because of non-blocking sockets return
|
||||
EWOULDBLOCK or similar. This FTP command sending, the SSL connection etc.
|
||||
EWOULDBLOCK or similar. The GnuTLS connection etc.
|
||||
|
||||
* Make transfers treated more carefully. We need a way to tell libcurl we
|
||||
have data to write, as the current system expects us to upload data each
|
||||
@@ -80,10 +69,6 @@ TODO
|
||||
ready to accept read data. Today libcurl feeds the data as soon as it is
|
||||
available for reading, no matter what.
|
||||
|
||||
* Add curl_multi_socket() and family to the multi interface that gets file
|
||||
descriptors, as an alternative to the curl_multi_fdset(). This is necessary
|
||||
to allow apps to properly avoid the FD_SETSIZE problem.
|
||||
|
||||
* Make curl_easy_perform() a wrapper-function that simply creates a multi
|
||||
handle, adds the easy handle to it, runs curl_multi_perform() until the
|
||||
transfer is done, then detach the easy handle, destroy the multi handle and
|
||||
@@ -201,6 +186,11 @@ TODO
|
||||
* Work out a common method with Peter Sylvester's OpenSSL-patch for SRP
|
||||
on the TLS to provide name and password
|
||||
|
||||
* Fix the connection phase to be non-blocking when multi interface is used
|
||||
|
||||
* Add a way to check if the connection seems to be alive, to corrspond to the
|
||||
SSL_peak() way we use with OpenSSL.
|
||||
|
||||
LDAP
|
||||
|
||||
* Look over the implementation. The looping will have to "go away" from the
|
||||
@@ -212,7 +202,8 @@ TODO
|
||||
* RTSP - RFC2326 (protocol - very HTTP-like, also contains URL description)
|
||||
|
||||
* SFTP/SCP/SSH (no RFCs for protocol nor URI/URL format). An implementation
|
||||
should most probably use an existing ssh library, such as OpenSSH.
|
||||
should most probably use an existing ssh library, such as OpenSSH. or
|
||||
libssh2.org
|
||||
|
||||
* RSYNC (no RFCs for protocol nor URI/URL format). An implementation should
|
||||
most probably use an existing rsync library, such as librsync.
|
||||
|
@@ -5,7 +5,7 @@
|
||||
.\" * | (__| |_| | _ <| |___
|
||||
.\" * \___|\___/|_| \_\_____|
|
||||
.\" *
|
||||
.\" * Copyright (C) 1998 - 2005, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
.\" * Copyright (C) 1998 - 2006, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
.\" *
|
||||
.\" * This software is licensed as described in the file COPYING, which
|
||||
.\" * you should have received as part of this distribution. The terms
|
||||
@@ -21,7 +21,7 @@
|
||||
.\" * $Id$
|
||||
.\" **************************************************************************
|
||||
.\"
|
||||
.TH curl-config 1 "25 Jan 2004" "Curl 7.13.0" "curl-config manual"
|
||||
.TH curl-config 1 "25 Jan 2004" "Curl 7.15.4" "curl-config manual"
|
||||
.SH NAME
|
||||
curl-config \- Get information about a libcurl installation
|
||||
.SH SYNOPSIS
|
||||
@@ -37,6 +37,11 @@ Displays the compiler used to build libcurl.
|
||||
.IP "--cflags"
|
||||
Set of compiler options (CFLAGS) to use when compiling files that use
|
||||
libcurl. Currently that is only thw include path to the curl include files.
|
||||
.IP "--checkfor [version]"
|
||||
Specify the oldest possible libcurl version string you want, and this
|
||||
script will return 0 if the current installation is new enough or it
|
||||
returns 1 and outputs a text saying that the current version is not new
|
||||
enough. (Added in 7.15.4)
|
||||
.IP "--feature"
|
||||
Lists what particular main features the installed libcurl was built with. At
|
||||
the time of writing, this list may include SSL, KRB4 or IPv6. Do not assume
|
||||
|
34
docs/curl.1
34
docs/curl.1
@@ -21,7 +21,7 @@
|
||||
.\" * $Id$
|
||||
.\" **************************************************************************
|
||||
.\"
|
||||
.TH curl 1 "21 Feb 2006" "Curl 7.15.2" "Curl Manual"
|
||||
.TH curl 1 "21 Mar 2006" "Curl 7.15.4" "Curl Manual"
|
||||
.SH NAME
|
||||
curl \- transfer a URL
|
||||
.SH SYNOPSIS
|
||||
@@ -43,7 +43,7 @@ curl is powered by libcurl for all transfer-related features. See
|
||||
for details.
|
||||
.SH URL
|
||||
The URL syntax is protocol dependent. You'll find a detailed description in
|
||||
RFC 2396.
|
||||
RFC 3986.
|
||||
|
||||
You can specify multiple URLs or parts of URLs by writing part sets within
|
||||
braces as in:
|
||||
@@ -1131,6 +1131,10 @@ Number of new connects made in the recent transfer. (Added in 7.12.3)
|
||||
.TP
|
||||
.B num_redirects
|
||||
Number of redirects that were followed in the request. (Added in 7.12.3)
|
||||
.TP
|
||||
.B ftp_entry_path
|
||||
The initial path libcurl ended up in when logging on to the remote FTP
|
||||
server. (Added in 7.15.4)
|
||||
.RE
|
||||
|
||||
If this option is used several times, the last one will be used.
|
||||
@@ -1389,6 +1393,32 @@ Unrecognized transfer encoding
|
||||
Invalid LDAP URL
|
||||
.IP 63
|
||||
Maximum file size exceeded
|
||||
.IP 64
|
||||
Requested FTP SSL level failed
|
||||
.IP 65
|
||||
Sending the data requires a rewind that failed
|
||||
.IP 66
|
||||
Failed to initialise SSL Engine
|
||||
.IP 67
|
||||
User, password or similar was not accepted and curl failed to login
|
||||
.IP 68
|
||||
File not found on TFTP server
|
||||
.IP 69
|
||||
Permission problem on TFTP server
|
||||
.IP 70
|
||||
Out of disk space on TFTP server
|
||||
.IP 71
|
||||
Illegal TFTP operation
|
||||
.IP 72
|
||||
Unknown TFTP transfer ID
|
||||
.IP 73
|
||||
File already exists (TFTP)
|
||||
.IP 74
|
||||
No such user (TFTP)
|
||||
.IP 75
|
||||
Character conversion failed
|
||||
.IP 76
|
||||
Character conversion functions required
|
||||
.IP XX
|
||||
There will appear more error codes here in future releases. The existing ones
|
||||
are meant to never change.
|
||||
|
@@ -11,7 +11,7 @@ EXTRA_DIST = README curlgtk.c sepheaders.c simple.c postit2.c \
|
||||
multi-post.c fopen.c simplepost.c makefile.dj curlx.c https.c \
|
||||
multi-debugcallback.c fileupload.c getinfo.c ftp3rdparty.c debug.c \
|
||||
anyauthput.c htmltitle.cc htmltidy.c opensslthreadlock.c \
|
||||
cookie_interface.c cacertinmem.c synctime.c
|
||||
cookie_interface.c cacertinmem.c synctime.c sampleconv.c ftpuploadresume.c
|
||||
|
||||
all:
|
||||
@echo "done"
|
||||
|
154
docs/examples/ftpuploadresume.c
Normal file
154
docs/examples/ftpuploadresume.c
Normal file
@@ -0,0 +1,154 @@
|
||||
/*****************************************************************************
|
||||
* _ _ ____ _
|
||||
* Project ___| | | | _ \| |
|
||||
* / __| | | | |_) | |
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
* Upload to FTP, resuming failed transfers
|
||||
*
|
||||
* Compile for MinGW like this:
|
||||
* gcc -Wall -pedantic -std=c99 ftpuploadwithresume.c -o ftpuploadresume.exe
|
||||
* -lcurl -lmsvcr70
|
||||
*
|
||||
* Written by Philip Bock
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <curl/curl.h>
|
||||
|
||||
|
||||
/* The MinGW headers are missing a few Win32 function definitions,
|
||||
you shouldn't need this if you use VC++ */
|
||||
int __cdecl _snscanf(const char * input, size_t length, const char * format, ...);
|
||||
|
||||
|
||||
/* parse headers for Content-Length */
|
||||
size_t getcontentlengthfunc(void *ptr, size_t size, size_t nmemb, void *stream) {
|
||||
int r;
|
||||
long len = 0;
|
||||
|
||||
/* _snscanf() is Win32 specific */
|
||||
r = _snscanf(ptr, size * nmemb, "Content-Length: %ld\n", &len);
|
||||
|
||||
if (r) /* Microsoft: we don't read the specs */
|
||||
*((long *) stream) = len;
|
||||
|
||||
return size * nmemb;
|
||||
}
|
||||
|
||||
/* discard downloaded data */
|
||||
size_t discardfunc(void *ptr, size_t size, size_t nmemb, void *stream) {
|
||||
return size * nmemb;
|
||||
}
|
||||
|
||||
/* read data to upload */
|
||||
size_t readfunc(void *ptr, size_t size, size_t nmemb, void *stream)
|
||||
{
|
||||
FILE *f = stream;
|
||||
size_t n;
|
||||
|
||||
if (ferror(f))
|
||||
return CURL_READFUNC_ABORT;
|
||||
|
||||
n = fread(ptr, size, nmemb, f) * size;
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
int upload(CURL *curlhandle, const char * remotepath, const char * localpath,
|
||||
long timeout, long tries)
|
||||
{
|
||||
FILE *f;
|
||||
long uploaded_len = 0;
|
||||
CURLcode r = CURLE_GOT_NOTHING;
|
||||
int c;
|
||||
|
||||
f = fopen(localpath, "rb");
|
||||
if (f == NULL) {
|
||||
perror(NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
curl_easy_setopt(curlhandle, CURLOPT_UPLOAD, TRUE);
|
||||
|
||||
curl_easy_setopt(curlhandle, CURLOPT_URL, remotepath);
|
||||
|
||||
if (timeout)
|
||||
curl_easy_setopt(curlhandle, CURLOPT_FTP_RESPONSE_TIMEOUT, timeout);
|
||||
|
||||
curl_easy_setopt(curlhandle, CURLOPT_HEADERFUNCTION, getcontentlengthfunc);
|
||||
curl_easy_setopt(curlhandle, CURLOPT_HEADERDATA, &uploaded_len);
|
||||
|
||||
curl_easy_setopt(curlhandle, CURLOPT_WRITEFUNCTION, discardfunc);
|
||||
|
||||
curl_easy_setopt(curlhandle, CURLOPT_READFUNCTION, readfunc);
|
||||
curl_easy_setopt(curlhandle, CURLOPT_READDATA, f);
|
||||
|
||||
curl_easy_setopt(curlhandle, CURLOPT_FTPPORT, "-"); /* disable passive mode */
|
||||
curl_easy_setopt(curlhandle, CURLOPT_FTP_CREATE_MISSING_DIRS, TRUE);
|
||||
|
||||
curl_easy_setopt(curlhandle, CURLOPT_VERBOSE, TRUE);
|
||||
|
||||
for (c = 0; (r != CURLE_OK) && (c < tries); c++) {
|
||||
/* are we resuming? */
|
||||
if (c) { /* yes */
|
||||
/* determine the length of the file already written */
|
||||
|
||||
/*
|
||||
* With NOBODY and NOHEADER, libcurl will issue a SIZE
|
||||
* command, but the only way to retrieve the result is
|
||||
* to parse the returned Content-Length header. Thus,
|
||||
* getcontentlengthfunc(). We need discardfunc() above
|
||||
* because HEADER will dump the headers to stdout
|
||||
* without it.
|
||||
*/
|
||||
curl_easy_setopt(curlhandle, CURLOPT_NOBODY, TRUE);
|
||||
curl_easy_setopt(curlhandle, CURLOPT_HEADER, TRUE);
|
||||
|
||||
r = curl_easy_perform(curlhandle);
|
||||
if (r != CURLE_OK)
|
||||
continue;
|
||||
|
||||
curl_easy_setopt(curlhandle, CURLOPT_NOBODY, FALSE);
|
||||
curl_easy_setopt(curlhandle, CURLOPT_HEADER, FALSE);
|
||||
|
||||
fseek(f, uploaded_len, SEEK_SET);
|
||||
|
||||
curl_easy_setopt(curlhandle, CURLOPT_FTPAPPEND, TRUE);
|
||||
}
|
||||
else { /* no */
|
||||
curl_easy_setopt(curlhandle, CURLOPT_FTPAPPEND, FALSE);
|
||||
}
|
||||
|
||||
r = curl_easy_perform(curlhandle);
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
|
||||
if (r == CURLE_OK)
|
||||
return 1;
|
||||
else {
|
||||
fprintf(stderr, "%s\n", curl_easy_strerror(r));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int main(int c, char **argv) {
|
||||
CURL *curlhandle = NULL;
|
||||
|
||||
curl_global_init(CURL_GLOBAL_ALL);
|
||||
curlhandle = curl_easy_init();
|
||||
|
||||
upload(curlhandle, "ftp://user:pass@host/path/file", "C:\\file", 0, 3);
|
||||
|
||||
curl_easy_cleanup(curlhandle);
|
||||
curl_global_cleanup();
|
||||
|
||||
return 0;
|
||||
}
|
@@ -24,12 +24,13 @@ int main(int argc, char *argv[])
|
||||
CURLM *multi_handle;
|
||||
int still_running;
|
||||
|
||||
struct HttpPost *formpost=NULL;
|
||||
struct HttpPost *lastptr=NULL;
|
||||
struct curl_httppost *formpost=NULL;
|
||||
struct curl_httppost *lastptr=NULL;
|
||||
struct curl_slist *headerlist=NULL;
|
||||
char buf[] = "Expect:";
|
||||
|
||||
/* Fill in the file upload field */
|
||||
/* Fill in the file upload field. This makes libcurl load data from
|
||||
the given file name when curl_easy_perform() is called. */
|
||||
curl_formadd(&formpost,
|
||||
&lastptr,
|
||||
CURLFORM_COPYNAME, "sendfile",
|
||||
@@ -43,7 +44,6 @@ int main(int argc, char *argv[])
|
||||
CURLFORM_COPYCONTENTS, "postit2.c",
|
||||
CURLFORM_END);
|
||||
|
||||
|
||||
/* Fill in the submit field too, even if this is rarely needed */
|
||||
curl_formadd(&formpost,
|
||||
&lastptr,
|
||||
|
95
docs/examples/sampleconv.c
Normal file
95
docs/examples/sampleconv.c
Normal file
@@ -0,0 +1,95 @@
|
||||
/*****************************************************************************
|
||||
* _ _ ____ _
|
||||
* Project ___| | | | _ \| |
|
||||
* / __| | | | |_) | |
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
/*
|
||||
This is a simple example showing how a program on a non-ASCII platform
|
||||
would invoke callbacks to do its own codeset conversions instead of
|
||||
using the built-in iconv functions in libcurl.
|
||||
|
||||
The IBM-1047 EBCDIC codeset is used for this example but the code
|
||||
would be similar for other non-ASCII codesets.
|
||||
|
||||
Three callback functions are created below:
|
||||
my_conv_from_ascii_to_ebcdic,
|
||||
my_conv_from_ebcdic_to_ascii, and
|
||||
my_conv_from_utf8_to_ebcdic
|
||||
|
||||
The "platform_xxx" calls represent platform-specific conversion routines.
|
||||
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <curl/curl.h>
|
||||
|
||||
CURLcode my_conv_from_ascii_to_ebcdic(char *buffer, size_t length)
|
||||
{
|
||||
char *tempptrin, *tempptrout;
|
||||
size_t bytes = length;
|
||||
int rc;
|
||||
tempptrin = tempptrout = buffer;
|
||||
rc = platform_a2e(&tempptrin, &bytes, &tempptrout, &bytes);
|
||||
if (rc == PLATFORM_CONV_OK) {
|
||||
return(CURLE_OK);
|
||||
} else {
|
||||
return(CURLE_CONV_FAILED);
|
||||
}
|
||||
}
|
||||
|
||||
CURLcode my_conv_from_ebcdic_to_ascii(char *buffer, size_t length)
|
||||
{
|
||||
char *tempptrin, *tempptrout;
|
||||
size_t bytes = length;
|
||||
int rc;
|
||||
tempptrin = tempptrout = buffer;
|
||||
rc = platform_e2a(&tempptrin, &bytes, &tempptrout, &bytes);
|
||||
if (rc == PLATFORM_CONV_OK) {
|
||||
return(CURLE_OK);
|
||||
} else {
|
||||
return(CURLE_CONV_FAILED);
|
||||
}
|
||||
}
|
||||
|
||||
CURLcode my_conv_from_utf8_to_ebcdic(char *buffer, size_t length)
|
||||
{
|
||||
char *tempptrin, *tempptrout;
|
||||
size_t bytes = length;
|
||||
int rc;
|
||||
tempptrin = tempptrout = buffer;
|
||||
rc = platform_u2e(&tempptrin, &bytes, &tempptrout, &bytes);
|
||||
if (rc == PLATFORM_CONV_OK) {
|
||||
return(CURLE_OK);
|
||||
} else {
|
||||
return(CURLE_CONV_FAILED);
|
||||
}
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
CURL *curl;
|
||||
CURLcode res;
|
||||
|
||||
curl = curl_easy_init();
|
||||
if(curl) {
|
||||
curl_easy_setopt(curl, CURLOPT_URL, "curl.haxx.se");
|
||||
|
||||
/* use platform-specific functions for codeset conversions */
|
||||
curl_easy_setopt(curl, CURLOPT_CONV_FROM_NETWORK_FUNCTION,
|
||||
my_conv_from_ascii_to_ebcdic);
|
||||
curl_easy_setopt(curl, CURLOPT_CONV_TO_NETWORK_FUNCTION,
|
||||
my_conv_from_ebcdic_to_ascii);
|
||||
curl_easy_setopt(curl, CURLOPT_CONV_FROM_UTF8_FUNCTION,
|
||||
my_conv_from_utf8_to_ebcdic);
|
||||
|
||||
res = curl_easy_perform(curl);
|
||||
|
||||
/* always cleanup */
|
||||
curl_easy_cleanup(curl);
|
||||
}
|
||||
return 0;
|
||||
}
|
@@ -9,14 +9,16 @@ man_MANS = curl_easy_cleanup.3 curl_easy_getinfo.3 curl_easy_init.3 \
|
||||
curl_formadd.3 curl_formfree.3 curl_getdate.3 curl_getenv.3 \
|
||||
curl_slist_append.3 curl_slist_free_all.3 curl_version.3 \
|
||||
curl_version_info.3 curl_escape.3 curl_unescape.3 curl_free.3 \
|
||||
curl_strequal.3 curl_mprintf.3 curl_global_init.3 \
|
||||
curl_global_cleanup.3 curl_multi_add_handle.3 curl_multi_cleanup.3 \
|
||||
curl_multi_fdset.3 curl_multi_info_read.3 curl_multi_init.3 \
|
||||
curl_multi_perform.3 curl_multi_remove_handle.3 curl_share_cleanup.3 \
|
||||
curl_share_init.3 curl_share_setopt.3 libcurl.3 libcurl-easy.3 \
|
||||
libcurl-multi.3 libcurl-share.3 libcurl-errors.3 curl_easy_strerror.3 \
|
||||
curl_strequal.3 curl_mprintf.3 curl_global_init.3 curl_global_cleanup.3 \
|
||||
curl_multi_add_handle.3 curl_multi_cleanup.3 curl_multi_fdset.3 \
|
||||
curl_multi_info_read.3 curl_multi_init.3 curl_multi_perform.3 \
|
||||
curl_multi_remove_handle.3 curl_share_cleanup.3 curl_share_init.3 \
|
||||
curl_share_setopt.3 libcurl.3 libcurl-easy.3 libcurl-multi.3 \
|
||||
libcurl-share.3 libcurl-errors.3 curl_easy_strerror.3 \
|
||||
curl_multi_strerror.3 curl_share_strerror.3 curl_global_init_mem.3 \
|
||||
libcurl-tutorial.3 curl_easy_reset.3
|
||||
libcurl-tutorial.3 curl_easy_reset.3 curl_easy_escape.3 \
|
||||
curl_easy_unescape.3 curl_multi_setopt.3 curl_multi_socket.3 \
|
||||
curl_multi_timeout.3
|
||||
|
||||
HTMLPAGES = curl_easy_cleanup.html curl_easy_getinfo.html \
|
||||
curl_easy_init.html curl_easy_perform.html curl_easy_setopt.html \
|
||||
@@ -25,30 +27,31 @@ HTMLPAGES = curl_easy_cleanup.html curl_easy_getinfo.html \
|
||||
curl_slist_free_all.html curl_version.html curl_version_info.html \
|
||||
curl_escape.html curl_unescape.html curl_free.html curl_strequal.html \
|
||||
curl_mprintf.html curl_global_init.html curl_global_cleanup.html \
|
||||
curl_multi_add_handle.html curl_multi_cleanup.html \
|
||||
curl_multi_fdset.html curl_multi_info_read.html curl_multi_init.html \
|
||||
curl_multi_perform.html curl_multi_remove_handle.html \
|
||||
curl_share_cleanup.html curl_share_init.html curl_share_setopt.html \
|
||||
libcurl.html libcurl-multi.html libcurl-easy.html libcurl-share.html \
|
||||
curl_multi_add_handle.html curl_multi_cleanup.html curl_multi_fdset.html \
|
||||
curl_multi_info_read.html curl_multi_init.html curl_multi_perform.html \
|
||||
curl_multi_remove_handle.html curl_share_cleanup.html \
|
||||
curl_share_init.html curl_share_setopt.html libcurl.html \
|
||||
libcurl-multi.html libcurl-easy.html libcurl-share.html \
|
||||
libcurl-errors.html curl_easy_strerror.html curl_multi_strerror.html \
|
||||
curl_share_strerror.html curl_global_init_mem.html \
|
||||
libcurl-tutorial.html curl_easy_reset.html
|
||||
curl_share_strerror.html curl_global_init_mem.html libcurl-tutorial.html \
|
||||
curl_easy_reset.html curl_easy_escape.html curl_easy_unescape.html \
|
||||
curl_multi_setopt.html curl_multi_socket.html curl_multi_timeout.html
|
||||
|
||||
PDFPAGES = curl_easy_cleanup.pdf curl_easy_getinfo.pdf \
|
||||
curl_easy_init.pdf curl_easy_perform.pdf curl_easy_setopt.pdf \
|
||||
curl_easy_duphandle.pdf curl_formadd.pdf curl_formfree.pdf \
|
||||
curl_getdate.pdf curl_getenv.pdf curl_slist_append.pdf \
|
||||
curl_slist_free_all.pdf curl_version.pdf curl_version_info.pdf \
|
||||
curl_escape.pdf curl_unescape.pdf curl_free.pdf curl_strequal.pdf \
|
||||
curl_mprintf.pdf curl_global_init.pdf curl_global_cleanup.pdf \
|
||||
curl_multi_add_handle.pdf curl_multi_cleanup.pdf curl_multi_fdset.pdf \
|
||||
curl_multi_info_read.pdf curl_multi_init.pdf curl_multi_perform.pdf \
|
||||
curl_multi_remove_handle.pdf curl_share_cleanup.pdf \
|
||||
curl_share_init.pdf curl_share_setopt.pdf libcurl.pdf \
|
||||
libcurl-multi.pdf libcurl-easy.pdf libcurl-share.pdf \
|
||||
PDFPAGES = curl_easy_cleanup.pdf curl_easy_getinfo.pdf curl_easy_init.pdf \
|
||||
curl_easy_perform.pdf curl_easy_setopt.pdf curl_easy_duphandle.pdf \
|
||||
curl_formadd.pdf curl_formfree.pdf curl_getdate.pdf curl_getenv.pdf \
|
||||
curl_slist_append.pdf curl_slist_free_all.pdf curl_version.pdf \
|
||||
curl_version_info.pdf curl_escape.pdf curl_unescape.pdf curl_free.pdf \
|
||||
curl_strequal.pdf curl_mprintf.pdf curl_global_init.pdf \
|
||||
curl_global_cleanup.pdf curl_multi_add_handle.pdf curl_multi_cleanup.pdf \
|
||||
curl_multi_fdset.pdf curl_multi_info_read.pdf curl_multi_init.pdf \
|
||||
curl_multi_perform.pdf curl_multi_remove_handle.pdf \
|
||||
curl_share_cleanup.pdf curl_share_init.pdf curl_share_setopt.pdf \
|
||||
libcurl.pdf libcurl-multi.pdf libcurl-easy.pdf libcurl-share.pdf \
|
||||
libcurl-errors.pdf curl_easy_strerror.pdf curl_multi_strerror.pdf \
|
||||
curl_share_strerror.pdf curl_global_init_mem.pdf libcurl-tutorial.pdf \
|
||||
curl_easy_reset.pdf
|
||||
curl_easy_reset.pdf curl_easy_escape.pdf curl_easy_unescape.pdf \
|
||||
curl_multi_setopt.pdf curl_multi_socket.pdf curl_multi_timeout.pdf
|
||||
|
||||
CLEANFILES = $(HTMLPAGES) $(PDFPAGES)
|
||||
|
||||
|
47
docs/libcurl/curl_easy_escape.3
Normal file
47
docs/libcurl/curl_easy_escape.3
Normal file
@@ -0,0 +1,47 @@
|
||||
.\" **************************************************************************
|
||||
.\" * _ _ ____ _
|
||||
.\" * Project ___| | | | _ \| |
|
||||
.\" * / __| | | | |_) | |
|
||||
.\" * | (__| |_| | _ <| |___
|
||||
.\" * \___|\___/|_| \_\_____|
|
||||
.\" *
|
||||
.\" * Copyright (C) 1998 - 2006, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
.\" *
|
||||
.\" * This software is licensed as described in the file COPYING, which
|
||||
.\" * you should have received as part of this distribution. The terms
|
||||
.\" * are also available at http://curl.haxx.se/docs/copyright.html.
|
||||
.\" *
|
||||
.\" * You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||
.\" * copies of the Software, and permit persons to whom the Software is
|
||||
.\" * furnished to do so, under the terms of the COPYING file.
|
||||
.\" *
|
||||
.\" * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
.\" * KIND, either express or implied.
|
||||
.\" *
|
||||
.\" * $Id$
|
||||
.\" **************************************************************************
|
||||
.\"
|
||||
.TH curl_easy_escape 3 "7 April 2006" "libcurl 7.15.4" "libcurl Manual"
|
||||
.SH NAME
|
||||
curl_easy_escape - URL encodes the given string
|
||||
.SH SYNOPSIS
|
||||
.B #include <curl/curl.h>
|
||||
.sp
|
||||
.BI "char *curl_easy_escape( CURL *" curl ", char *" url ", int "length " );"
|
||||
.ad
|
||||
.SH DESCRIPTION
|
||||
This function converts the given input string to an URL encoded string and
|
||||
returns that as a new allocated string. All input characters that are not a-z,
|
||||
A-Z or 0-9 are converted to their "URL escaped" version (%NN where NN is a
|
||||
two-digit hexadecimal number).
|
||||
|
||||
If the \fBlength\fP argument is set to 0 (zero), curl_easy_escape() uses
|
||||
strlen() on the input \fBurl\fP to find out the size.
|
||||
|
||||
You must \fIcurl_free(3)\fP the returned string when you're done with it.
|
||||
.SH AVAILABILITY
|
||||
Added in 7.15.4 and replaces the old curl_escape() function.
|
||||
.SH RETURN VALUE
|
||||
A pointer to a zero terminated string or NULL if it failed.
|
||||
.SH "SEE ALSO"
|
||||
.BR curl_easy_unescape "(3), " curl_free "(3), " RFC 2396
|
@@ -1,8 +1,27 @@
|
||||
.\" You can view this file with:
|
||||
.\" nroff -man [file]
|
||||
.\" $Id$
|
||||
.\" **************************************************************************
|
||||
.\" * _ _ ____ _
|
||||
.\" * Project ___| | | | _ \| |
|
||||
.\" * / __| | | | |_) | |
|
||||
.\" * | (__| |_| | _ <| |___
|
||||
.\" * \___|\___/|_| \_\_____|
|
||||
.\" *
|
||||
.\" * Copyright (C) 1998 - 2006, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
.\" *
|
||||
.\" * This software is licensed as described in the file COPYING, which
|
||||
.\" * you should have received as part of this distribution. The terms
|
||||
.\" * are also available at http://curl.haxx.se/docs/copyright.html.
|
||||
.\" *
|
||||
.\" * You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||
.\" * copies of the Software, and permit persons to whom the Software is
|
||||
.\" * furnished to do so, under the terms of the COPYING file.
|
||||
.\" *
|
||||
.\" * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
.\" * KIND, either express or implied.
|
||||
.\" *
|
||||
.\" * $Id$
|
||||
.\" **************************************************************************
|
||||
.\"
|
||||
.TH curl_easy_getinfo 3 "6 Oct 2005" "libcurl 7.12.3" "libcurl Manual"
|
||||
.TH curl_easy_getinfo 3 "21 Mar 2006" "libcurl 7.15.4" "libcurl Manual"
|
||||
.SH NAME
|
||||
curl_easy_getinfo - extract information from a curl handle
|
||||
.SH SYNOPSIS
|
||||
@@ -44,10 +63,8 @@ information before the transfer is made, by using the CURLOPT_FILETIME option
|
||||
to \fIcurl_easy_setopt(3)\fP or you will unconditionally get a -1 back. (Added
|
||||
in 7.5)
|
||||
.IP CURLINFO_TOTAL_TIME
|
||||
Pass a pointer to a double to receive the total transaction time in seconds
|
||||
for the previous transfer. This time does not include the connect time, so if
|
||||
you want the complete operation time, you should add the
|
||||
CURLINFO_CONNECT_TIME.
|
||||
Pass a pointer to a double to receive the total time in seconds for the
|
||||
previous transfer, including name resolving, TCP connect etc.
|
||||
.IP CURLINFO_NAMELOOKUP_TIME
|
||||
Pass a pointer to a double to receive the time, in seconds, it took from the
|
||||
start until the name resolving was completed.
|
||||
@@ -148,6 +165,11 @@ working with the socket, you must call curl_easy_cleanup() as usual and let
|
||||
libcurl close the socket and cleanup other resources associated with the
|
||||
handle. This is typically used in combination with \fICURLOPT_CONNECT_ONLY\fP.
|
||||
(Added in 7.15.2)
|
||||
.IP CURLINFO_FTP_ENTRY_PATH
|
||||
Pass a pointer to a 'char *' to receive a pointer to a string holding the path
|
||||
of the entry path. That is the initial path libcurl ended up in when logging
|
||||
on to the remote FTP server. This stores a NULL as pointer if something is
|
||||
wrong. (Added in 7.15.4)
|
||||
.SH TIMES
|
||||
.NF
|
||||
An overview of the six time values available from curl_easy_getinfo()
|
||||
@@ -158,7 +180,7 @@ curl_easy_perform()
|
||||
|--|--CT
|
||||
|--|--|--PT
|
||||
|--|--|--|--ST
|
||||
|--|--|--TT
|
||||
|--|--|--|--|--TT
|
||||
|--|--|--|--|--RT
|
||||
.FI
|
||||
.IP NT
|
||||
@@ -175,9 +197,7 @@ and negotiations that are specific to the particular protocol(s) involved.
|
||||
\fICURLINFO_STARTTRANSFER_TIME\fP. The time it took from the start until the
|
||||
first byte is just about to be transferred.
|
||||
.IP TT
|
||||
\fICURLINFO_TOTAL_TIME\fP. Time of the previous transfer. This time does not
|
||||
include the connect time (CT), so if you want the complete operation time, you
|
||||
should add that.
|
||||
\fICURLINFO_TOTAL_TIME\fP. Total time of the previous request.
|
||||
.IP RT
|
||||
\fICURLINFO_REDIRECT_TIME\fP. The time it took for all redirection steps
|
||||
include name lookup, connect, pretransfer and transfer before final
|
||||
|
@@ -21,7 +21,7 @@
|
||||
.\" * $Id$
|
||||
.\" **************************************************************************
|
||||
.\"
|
||||
.TH curl_easy_setopt 3 "21 Feb 2006" "libcurl 7.15.2" "libcurl Manual"
|
||||
.TH curl_easy_setopt 3 "19 Apr 2006" "libcurl 7.15.4" "libcurl Manual"
|
||||
.SH NAME
|
||||
curl_easy_setopt \- set options for a curl easy handle
|
||||
.SH SYNOPSIS
|
||||
@@ -263,6 +263,51 @@ and trust file settings.
|
||||
Data pointer to pass to the ssl context callback set by the option
|
||||
\fICURLOPT_SSL_CTX_FUNCTION\fP, this is the pointer you'll get as third
|
||||
parameter, otherwise \fBNULL\fP. (Added in 7.11.0)
|
||||
.IP CURLOPT_CONV_TO_NETWORK_FUNCTION
|
||||
.IP CURLOPT_CONV_FROM_NETWORK_FUNCTION
|
||||
.IP CURLOPT_CONV_FROM_UTF8_FUNCTION
|
||||
Function pointers that should match the following prototype: CURLcode
|
||||
function(char *ptr, size_t length);
|
||||
|
||||
These three options apply to non-ASCII platforms only. They are available
|
||||
only if \fBCURL_DOES_CONVERSIONS\fP was defined when libcurl was built. When
|
||||
this is the case, \fIcurl_version_info(3)\fP will return the CURL_VERSION_CONV
|
||||
feature bit set.
|
||||
|
||||
The data to be converted is in a buffer pointed to by the ptr parameter. The
|
||||
amount of data to convert is indicated by the length parameter. The converted
|
||||
data overlays the input data in the buffer pointed to by the ptr parameter.
|
||||
CURLE_OK should be returned upon successful conversion. A CURLcode return
|
||||
value defined by curl.h, such as CURLE_CONV_FAILED, should be returned if an
|
||||
error was encountered.
|
||||
|
||||
\fBCURLOPT_CONV_TO_NETWORK_FUNCTION\fP and
|
||||
\fBCURLOPT_CONV_FROM_NETWORK_FUNCTION\fP convert between the host encoding and
|
||||
the network encoding. They are used when commands or ASCII data are
|
||||
sent/received over the network.
|
||||
|
||||
\fBCURLOPT_CONV_FROM_UTF8_FUNCTION\fP is called to convert from UTF8 into the
|
||||
host encoding. It is required only for SSL processing.
|
||||
|
||||
If you set a callback pointer to NULL, or don't set it at all, the built-in
|
||||
libcurl iconv functions will be used. If HAVE_ICONV was not defined when
|
||||
libcurl was built, and no callback has been established, conversion will
|
||||
return the CURLE_CONV_REQD error code.
|
||||
|
||||
If HAVE_ICONV is defined, CURL_ICONV_CODESET_OF_HOST must also be defined.
|
||||
For example:
|
||||
|
||||
\&#define CURL_ICONV_CODESET_OF_HOST "IBM-1047"
|
||||
|
||||
The iconv code in libcurl will default the network and UTF8 codeset names as
|
||||
follows:
|
||||
|
||||
\&#define CURL_ICONV_CODESET_OF_NETWORK "ISO8859-1"
|
||||
|
||||
\&#define CURL_ICONV_CODESET_FOR_UTF8 "UTF-8"
|
||||
|
||||
You will need to override these definitions if they are different on your
|
||||
system.
|
||||
.SH ERROR OPTIONS
|
||||
.IP CURLOPT_ERRORBUFFER
|
||||
Pass a char * to a buffer that the libcurl may store human readable error
|
||||
@@ -295,7 +340,10 @@ given protocol of the set URL is not supported, libcurl will return on error
|
||||
\fIcurl_multi_perform(3)\fP. Use \fIcurl_version_info(3)\fP for detailed info
|
||||
on which protocols that are supported.
|
||||
|
||||
\fICURLOPT_URL\fP is the only option that must be set before
|
||||
The string given to CURLOPT_URL must be url-encoded and following the RFC 2396
|
||||
(http://curl.haxx.se/rfc/rfc2396.txt).
|
||||
|
||||
\fICURLOPT_URL\fP is the only option that \fBmust\fP be set before
|
||||
\fIcurl_easy_perform(3)\fP is called.
|
||||
.IP CURLOPT_PROXY
|
||||
Set HTTP proxy to use. The parameter should be a char * to a zero terminated
|
||||
@@ -714,6 +762,8 @@ Pass a char * to a cookie string. Cookie can be either in Netscape / Mozilla
|
||||
format or just regular HTTP-style header (Set-Cookie: ...) format. If cURL
|
||||
cookie engine was not enabled it will enable its cookie engine. Passing a
|
||||
magic string \&"ALL" will erase all cookies known by cURL. (Added in 7.14.1)
|
||||
Passing the special string \&"SESS" will only erase all session cookies known
|
||||
by cURL. (Added in 7.15.4)
|
||||
.IP CURLOPT_HTTPGET
|
||||
Pass a long. If the long is non-zero, this forces the HTTP request to get back
|
||||
to GET. usable if a POST, HEAD, PUT or a custom request have been used
|
||||
|
52
docs/libcurl/curl_easy_unescape.3
Normal file
52
docs/libcurl/curl_easy_unescape.3
Normal file
@@ -0,0 +1,52 @@
|
||||
.\" **************************************************************************
|
||||
.\" * _ _ ____ _
|
||||
.\" * Project ___| | | | _ \| |
|
||||
.\" * / __| | | | |_) | |
|
||||
.\" * | (__| |_| | _ <| |___
|
||||
.\" * \___|\___/|_| \_\_____|
|
||||
.\" *
|
||||
.\" * Copyright (C) 1998 - 2006, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
.\" *
|
||||
.\" * This software is licensed as described in the file COPYING, which
|
||||
.\" * you should have received as part of this distribution. The terms
|
||||
.\" * are also available at http://curl.haxx.se/docs/copyright.html.
|
||||
.\" *
|
||||
.\" * You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||
.\" * copies of the Software, and permit persons to whom the Software is
|
||||
.\" * furnished to do so, under the terms of the COPYING file.
|
||||
.\" *
|
||||
.\" * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
.\" * KIND, either express or implied.
|
||||
.\" *
|
||||
.\" * $Id$
|
||||
.\" **************************************************************************
|
||||
.\"
|
||||
.TH curl_easy_unescape 3 "7 April 2006" "libcurl 7.15.4" "libcurl Manual"
|
||||
.SH NAME
|
||||
curl_easy_unescape - URL decodes the given string
|
||||
.SH SYNOPSIS
|
||||
.B #include <curl/curl.h>
|
||||
.sp
|
||||
.BI "char *curl_easy_unescape( CURL *" curl ", char *" url ", int "inlength
|
||||
.BI ", int *" outlength " );"
|
||||
.ad
|
||||
.SH DESCRIPTION
|
||||
This function converts the given URL encoded input string to a "plain string"
|
||||
and returns that in an allocated memory area. All input characters that are
|
||||
URL encoded (%XX where XX is a two-digit hexadecimal number) are converted to
|
||||
their binary versions.
|
||||
|
||||
If the \fBlength\fP argument is set to 0 (zero), curl_easy_unescape() will use
|
||||
strlen() on the input \fIurl\fP string to find out the size.
|
||||
|
||||
If \fBoutlength\fP is non-NULL, the function will write the length of the
|
||||
returned string in the integer it points to. This allows an escaped string
|
||||
containing %00 to still get used properly after unescaping.
|
||||
|
||||
You must \fIcurl_free(3)\fP the returned string when you're done with it.
|
||||
.SH AVAILABILITY
|
||||
Added in 7.15.4 and replaces the old curl_unescape() function.
|
||||
.SH RETURN VALUE
|
||||
A pointer to a zero terminated string or NULL if it failed.
|
||||
.SH "SEE ALSO"
|
||||
.I curl_easy_escape(3), curl_free(3), RFC 2396
|
@@ -11,6 +11,8 @@ curl_escape - URL encodes the given string
|
||||
.BI "char *curl_escape( char *" url ", int "length " );"
|
||||
.ad
|
||||
.SH DESCRIPTION
|
||||
Obsolete function. Use \fIcurl_easy_escape(3)\fP instead!
|
||||
|
||||
This function will convert the given input string to an URL encoded string and
|
||||
return that as a new allocated string. All input characters that are not a-z,
|
||||
A-Z or 0-9 will be converted to their "URL escaped" version (%NN where NN is a
|
||||
@@ -20,6 +22,9 @@ If the 'length' argument is set to 0, curl_escape() will use strlen() on the
|
||||
input 'url' string to find out the size.
|
||||
|
||||
You must curl_free() the returned string when you're done with it.
|
||||
.SH AVAILABILITY
|
||||
Since 7.15.4, \fIcurl_easy_escape(3)\fP should be used. This function will
|
||||
be removed in a future release.
|
||||
.SH RETURN VALUE
|
||||
A pointer to a zero terminated string or NULL if it failed.
|
||||
.SH "SEE ALSO"
|
||||
|
@@ -11,6 +11,8 @@ curl_unescape - URL decodes the given string
|
||||
.BI "char *curl_unescape( char *" url ", int "length " );"
|
||||
.ad
|
||||
.SH DESCRIPTION
|
||||
Obsolete function. Use \fIcurl_easy_unescape(3)\fP instead!
|
||||
|
||||
This function will convert the given URL encoded input string to a "plain
|
||||
string" and return that as a new allocated string. All input characters that
|
||||
are URL encoded (%XX where XX is a two-digit hexadecimal number) will be
|
||||
@@ -20,7 +22,10 @@ If the 'length' argument is set to 0, curl_unescape() will use strlen() on the
|
||||
input 'url' string to find out the size.
|
||||
|
||||
You must curl_free() the returned string when you're done with it.
|
||||
.SH AVAILABILITY
|
||||
Since 7.15.4, \fIcurl_easy_unescape(3)\fP should be used. This function will
|
||||
be removed in a future release.
|
||||
.SH RETURN VALUE
|
||||
A pointer to a zero terminated string or NULL if it failed.
|
||||
.SH "SEE ALSO"
|
||||
.I curl_escape(3), curl_free(3), RFC 2396
|
||||
.I curl_easy_escape(3), curl_easy_unescape(3), curl_free(3), RFC 2396
|
||||
|
@@ -1,6 +1,27 @@
|
||||
.\" $Id$
|
||||
.\" **************************************************************************
|
||||
.\" * _ _ ____ _
|
||||
.\" * Project ___| | | | _ \| |
|
||||
.\" * / __| | | | |_) | |
|
||||
.\" * | (__| |_| | _ <| |___
|
||||
.\" * \___|\___/|_| \_\_____|
|
||||
.\" *
|
||||
.\" * Copyright (C) 1998 - 2006, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
.\" *
|
||||
.\" * This software is licensed as described in the file COPYING, which
|
||||
.\" * you should have received as part of this distribution. The terms
|
||||
.\" * are also available at http://curl.haxx.se/docs/copyright.html.
|
||||
.\" *
|
||||
.\" * You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||
.\" * copies of the Software, and permit persons to whom the Software is
|
||||
.\" * furnished to do so, under the terms of the COPYING file.
|
||||
.\" *
|
||||
.\" * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
.\" * KIND, either express or implied.
|
||||
.\" *
|
||||
.\" * $Id$
|
||||
.\" **************************************************************************
|
||||
.\"
|
||||
.TH curl_version_info 3 "11 Mar 2005" "libcurl 7.13.2" "libcurl Manual"
|
||||
.TH curl_version_info 3 "19 Apr 2006" "libcurl 7.15.4" "libcurl Manual"
|
||||
.SH NAME
|
||||
curl_version_info - returns run-time libcurl version info
|
||||
.SH SYNOPSIS
|
||||
@@ -98,6 +119,9 @@ libcurl was built with support for SSPI. This is only available on Windows and
|
||||
makes libcurl use Windows-provided functions for NTLM authentication. It also
|
||||
allows libcurl to use the current user and the current user's password without
|
||||
the app having to pass them on. (Added in 7.13.2)
|
||||
.IP CURL_VERSION_CONV
|
||||
libcurl was built with support for character conversions, as provided by the
|
||||
CUURLOPT_CONV_* callbacks. (Added in 7.15.4)
|
||||
.RE
|
||||
\fIssl_version\fP is an ascii string for the OpenSSL version used. If libcurl
|
||||
has no SSL support, this is NULL.
|
||||
|
@@ -30,7 +30,7 @@ or problem.
|
||||
.IP "CURLE_URL_MALFORMAT (3)"
|
||||
The URL was not properly formatted.
|
||||
.IP "CURLE_URL_MALFORMAT_USER (4)"
|
||||
URL user malformatted. The user-part of the URL syntax was not correct.
|
||||
This is never returned by current libcurl.
|
||||
.IP "CURLE_COULDNT_RESOLVE_PROXY (5)"
|
||||
Couldn't resolve proxy. The given proxy host could not be resolved.
|
||||
.IP "CURLE_COULDNT_RESOLVE_HOST (6)"
|
||||
@@ -45,9 +45,7 @@ remote server is probably not an OK FTP server.
|
||||
We were denied access when trying to login to an FTP server or when trying to
|
||||
change working directory to the one given in the URL.
|
||||
.IP "CURLE_FTP_USER_PASSWORD_INCORRECT (10)"
|
||||
The FTP server rejected access to the server after the password was sent to
|
||||
it. It might be because the username and/or the password were incorrect or
|
||||
just that the server is not allowing you access for the moment etc.
|
||||
This is never returned by current libcurl.
|
||||
.IP "CURLE_FTP_WEIRD_PASS_REPLY (11)"
|
||||
After having sent the FTP password to the server, libcurl expects a proper
|
||||
reply. This error code indicates that an unexpected code was returned.
|
||||
@@ -87,7 +85,7 @@ returns an error code that is >= 400.
|
||||
An error occurred when writing received data to a local file, or an error was
|
||||
returned to libcurl from a write callback.
|
||||
.IP "CURLE_MALFORMAT_USER (24)"
|
||||
Malformat user. User name badly specified. *Not currently used*
|
||||
This is never returned by current libcurl.
|
||||
.IP "CURLE_FTP_COULDNT_STOR_FILE (25)"
|
||||
FTP couldn't STOR file. The server denied the STOR operation. The error buffer
|
||||
usually contains the server's explanation to this.
|
||||
@@ -138,15 +136,13 @@ Aborted by callback. A callback returned "abort" to libcurl.
|
||||
.IP "CURLE_BAD_FUNCTION_ARGUMENT (43)"
|
||||
Internal error. A function was called with a bad parameter.
|
||||
.IP "CURLE_BAD_CALLING_ORDER (44)"
|
||||
Internal error. A function was called in a bad order.
|
||||
This is never returned by current libcurl.
|
||||
.IP "CURLE_HTTP_PORT_FAILED (45)"
|
||||
Interface error. A specified outgoing interface could not be used. Set which
|
||||
interface to use for outgoing connections' source IP address with
|
||||
CURLOPT_INTERFACE.
|
||||
.IP "CURLE_BAD_PASSWORD_ENTERED (46)"
|
||||
Bad password entered. An error was signaled when the password was
|
||||
entered. This can also be the result of a "bad password" returned from a
|
||||
specified password callback.
|
||||
This is never returned by current libcurl.
|
||||
.IP "CURLE_TOO_MANY_REDIRECTS (47)"
|
||||
Too many redirects. When following redirects, libcurl hit the maximum amount.
|
||||
Set your limit with CURLOPT_MAXREDIRS.
|
||||
@@ -194,6 +190,24 @@ rewinding operation failed
|
||||
Initiating the SSL Engine failed
|
||||
.IP "CURLE_LOGIN_DENIED (67)"
|
||||
The remote server denied curl to login (Added in 7.13.1)
|
||||
.IP "CURLE_TFTP_NOTFOUND (68)"
|
||||
File not found on TFTP server
|
||||
.IP "CURLE_TFTP_PERM (69"
|
||||
Permission problem on TFTP server
|
||||
.IP "CURLE_TFTP_DISKFULL (70)"
|
||||
Out of disk space on TFTP server
|
||||
.IP "CURLE_TFTP_ILLEGAL (71)"
|
||||
Illegal TFTP operation
|
||||
.IP "CURLE_TFTP_UNKNOWNID (72)"
|
||||
Unknown TFTP transfer ID
|
||||
.IP "CURLE_TFTP_EXISTS (73)"
|
||||
TFTP File already exists
|
||||
.IP "CURLE_TFTP_NOSUCHUSER (74)"
|
||||
No such TFTP user
|
||||
.IP "CURLE_CONV_FAILED (75)"
|
||||
Character conversion failed
|
||||
.IP "CURLE_CONV_REQD (76)"
|
||||
Caller must register conversion callbacks
|
||||
.SH "CURLMcode"
|
||||
This is the generic return code used by functions in the libcurl multi
|
||||
interface. Also consider \fIcurl_multi_strerror(3)\fP.
|
||||
|
@@ -1,7 +1,7 @@
|
||||
# LIBCURL_CHECK_CONFIG ([DEFAULT-ACTION], [MINIMUM-VERSION],
|
||||
# [ACTION-IF-YES], [ACTION-IF-NO])
|
||||
# ----------------------------------------------------------
|
||||
# David Shaw <dshaw@jabberwocky.com> Jan-17-2006
|
||||
# David Shaw <dshaw@jabberwocky.com> May-09-2006
|
||||
#
|
||||
# Checks for libcurl. DEFAULT-ACTION is the string yes or no to
|
||||
# specify whether to default to --with-libcurl or --without-libcurl.
|
||||
@@ -210,6 +210,9 @@ x=CURLOPT_VERBOSE;
|
||||
AC_DEFINE_UNQUOTED(AS_TR_CPP(libcurl_protocol_$_libcurl_protocol),[1])
|
||||
eval AS_TR_SH(libcurl_protocol_$_libcurl_protocol)=yes
|
||||
done
|
||||
else
|
||||
unset LIBCURL
|
||||
unset LIBCURL_CPPFLAGS
|
||||
fi
|
||||
fi
|
||||
|
||||
|
@@ -1,13 +1,14 @@
|
||||
#
|
||||
# Build a little app for the Hiper project
|
||||
# Build test apps for the Hiper project
|
||||
# During dev at least, we use a static libcurl.
|
||||
#
|
||||
|
||||
LDFLAGS = -lcrypt -lidn -lssl -lcrypto -ldl -lz -lresolv -L../ares/.libs -lcares
|
||||
LDFLAGS = -lcrypt -lidn -lssl -lcrypto -ldl -lz -lresolv -L../ares/.libs \
|
||||
-lcares
|
||||
LIBCURL = -L../lib/.libs/ -lcurl
|
||||
CFLAGS = -I../include -g -DHAVE_CURL_MULTI_SOCKET
|
||||
CFLAGS = -I../include -g
|
||||
|
||||
all: shiper hiper ulimiter
|
||||
all: shiper hiper hipev ulimiter
|
||||
|
||||
hiper: hiper.o $(LIBCURL)
|
||||
$(CC) -o $@ $< $(LIBCURL) $(LDFLAGS)
|
||||
@@ -15,6 +16,12 @@ hiper: hiper.o $(LIBCURL)
|
||||
hiper.o: hiper.c
|
||||
$(CC) $(CFLAGS) -c $<
|
||||
|
||||
hipev: hipev.o $(LIBCURL)
|
||||
$(CC) -o $@ $< $(LIBCURL) $(LDFLAGS) -levent
|
||||
|
||||
hipev.o: hipev.c
|
||||
$(CC) $(CFLAGS) -c $<
|
||||
|
||||
shiper: shiper.o $(LIBCURL)
|
||||
$(CC) -o $@ $< $(LIBCURL) $(LDFLAGS)
|
||||
|
||||
|
29
hiper/STATUS
29
hiper/STATUS
@@ -238,3 +238,32 @@ Roadmap Ahead
|
||||
I plan and hope to return to full-time hiper work later on this spring or
|
||||
possibly summer to continue where I pause now. Of course some spare time
|
||||
might also be spent until then to get us moving forward.
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
April 11, 2006
|
||||
|
||||
While sitting staring on my screen trying to write up a *nice* sample script
|
||||
using libevent, it strikes me that since libevent is pretty much based around
|
||||
its structs that you setup for each event/file descriptor, my application
|
||||
wants to figure out the correct struct that is associted with the file
|
||||
descriptor that libcurl provides in the socket callback.
|
||||
|
||||
This feels like an operation most applications will need when using the
|
||||
multi_socket API, so it feels like I should better try to figure out a decent
|
||||
way to offer this basic functionality already in libcurl - and the fact that
|
||||
we already have the file descriptors in a hash we can probably just as well
|
||||
extend it somewhat and store some custom pointers as well.
|
||||
|
||||
We need to offer the app a way to set a private pointer to be associated with
|
||||
the particular file descriptor, and then be able to provide that pointer on
|
||||
subsequent callback calls.
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
April 20, 2006
|
||||
|
||||
I was wrong when I previously claimed we could have more than one easy handle
|
||||
using the same socket. I've cleaned up and simplified code now to adjust to
|
||||
this.
|
||||
|
||||
|
550
hiper/hipev.c
Normal file
550
hiper/hipev.c
Normal file
@@ -0,0 +1,550 @@
|
||||
/*****************************************************************************
|
||||
* _ _ ____ _
|
||||
* Project ___| | | | _ \| |
|
||||
* / __| | | | |_) | |
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
* Connect N connections. Z are idle, and X are active. Transfer as fast as
|
||||
* possible.
|
||||
*
|
||||
* Run for a specific amount of time (10 secs for now). Output detailed timing
|
||||
* information.
|
||||
*
|
||||
* Uses libevent.
|
||||
*
|
||||
*/
|
||||
|
||||
/* The maximum number of simultanoues connections/transfers we support */
|
||||
#define NCONNECTIONS 50000
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/poll.h>
|
||||
|
||||
#include <curl/curl.h>
|
||||
|
||||
#include <event.h> /* for libevent */
|
||||
|
||||
#ifndef FALSE
|
||||
#define FALSE 0
|
||||
#endif
|
||||
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
#endif
|
||||
|
||||
#define MICROSEC 1000000 /* number of microseconds in one second */
|
||||
|
||||
/* The maximum time (in microseconds) we run the test */
|
||||
#define RUN_FOR_THIS_LONG (5*MICROSEC)
|
||||
|
||||
/* Number of loops (seconds) we allow the total download amount and alive
|
||||
connections to remain the same until we bail out. Set this slightly higher
|
||||
when using asynch supported libcurl. */
|
||||
#define IDLE_TIME 10
|
||||
|
||||
struct ourfdset {
|
||||
/* __fds_bits is what the Linux glibc headers use when they declare the
|
||||
fd_set struct so by using this we can actually avoid the typecase for the
|
||||
FD_SET() macro usage but it would hardly be portable */
|
||||
char __fds_bits[NCONNECTIONS/8];
|
||||
};
|
||||
#define FD2_ZERO(x) memset(x, 0, sizeof(struct ourfdset))
|
||||
|
||||
typedef struct ourfdset fd2_set;
|
||||
|
||||
struct globalinfo {
|
||||
size_t dlcounter;
|
||||
};
|
||||
|
||||
struct connection {
|
||||
CURL *e;
|
||||
int id; /* just a counter for easy browsing */
|
||||
char *url;
|
||||
size_t dlcounter;
|
||||
struct globalinfo *global;
|
||||
char error[CURL_ERROR_SIZE];
|
||||
struct event ev[3]; /* maximum 3 events per handle NOTE: should this rather
|
||||
be a define in a public curl header file or possibly
|
||||
just documented somewhere or... ? */
|
||||
};
|
||||
|
||||
struct fdinfo {
|
||||
/* create a link list of fdinfo structs */
|
||||
struct fdinfo *next;
|
||||
struct fdinfo *prev;
|
||||
curl_socket_t sockfd;
|
||||
CURL *easy;
|
||||
int action; /* as set by libcurl */
|
||||
long timeout; /* as set by libcurl */
|
||||
};
|
||||
|
||||
static struct fdinfo *allsocks;
|
||||
|
||||
static struct fdinfo *findsock(curl_socket_t s)
|
||||
{
|
||||
/* return the struct for the given socket */
|
||||
struct fdinfo *fdp = allsocks;
|
||||
|
||||
while(fdp) {
|
||||
if(fdp->sockfd == s)
|
||||
break;
|
||||
fdp = fdp->next;
|
||||
}
|
||||
return fdp; /* a struct pointer or NULL */
|
||||
}
|
||||
|
||||
static void remsock(curl_socket_t s)
|
||||
{
|
||||
struct fdinfo *fdp = allsocks;
|
||||
|
||||
while(fdp) {
|
||||
if(fdp->sockfd == s)
|
||||
break;
|
||||
fdp = fdp->next;
|
||||
}
|
||||
if(!fdp)
|
||||
/* did not find socket to remove! */
|
||||
return;
|
||||
|
||||
if(fdp->prev)
|
||||
fdp->prev->next = fdp->next;
|
||||
if(fdp->next)
|
||||
fdp->next->prev = fdp->prev;
|
||||
else
|
||||
/* this was the last entry */
|
||||
allsocks = NULL;
|
||||
}
|
||||
|
||||
static void setsock(struct fdinfo *fdp, curl_socket_t s, CURL *easy,
|
||||
int action)
|
||||
{
|
||||
fdp->sockfd = s;
|
||||
fdp->action = action;
|
||||
fdp->easy = easy;
|
||||
}
|
||||
|
||||
static void addsock(curl_socket_t s, CURL *easy, int action)
|
||||
{
|
||||
struct fdinfo *fdp = calloc(sizeof(struct fdinfo), 1);
|
||||
|
||||
setsock(fdp, s, easy, action);
|
||||
|
||||
if(allsocks) {
|
||||
fdp->next = allsocks;
|
||||
allsocks->prev = fdp;
|
||||
|
||||
/* now set allsocks to point to the new struct */
|
||||
allsocks = fdp;
|
||||
}
|
||||
else
|
||||
allsocks = fdp;
|
||||
}
|
||||
|
||||
static void fdinfo2fdset(fd2_set *fdread, fd2_set *fdwrite, int *maxfd)
|
||||
{
|
||||
struct fdinfo *fdp = allsocks;
|
||||
int writable=0;
|
||||
|
||||
FD2_ZERO(fdread);
|
||||
FD2_ZERO(fdwrite);
|
||||
|
||||
*maxfd = 0;
|
||||
|
||||
#if 0
|
||||
printf("Wait for: ");
|
||||
#endif
|
||||
|
||||
while(fdp) {
|
||||
if(fdp->action & CURL_POLL_IN) {
|
||||
FD_SET(fdp->sockfd, (fd_set *)fdread);
|
||||
}
|
||||
if(fdp->action & CURL_POLL_OUT) {
|
||||
FD_SET(fdp->sockfd, (fd_set *)fdwrite);
|
||||
writable++;
|
||||
}
|
||||
|
||||
#if 0
|
||||
printf("%d (%s%s) ",
|
||||
fdp->sockfd,
|
||||
(fdp->action & CURL_POLL_IN)?"r":"",
|
||||
(fdp->action & CURL_POLL_OUT)?"w":"");
|
||||
#endif
|
||||
|
||||
if(fdp->sockfd > *maxfd)
|
||||
*maxfd = fdp->sockfd;
|
||||
|
||||
fdp = fdp->next;
|
||||
}
|
||||
#if 0
|
||||
if(writable)
|
||||
printf("Check for %d writable sockets\n", writable);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* on port 8999 we run a fork enabled sws that supports 'idle' and 'stream' */
|
||||
#define PORT "8999"
|
||||
|
||||
#define HOST "192.168.1.13"
|
||||
|
||||
#define URL_IDLE "http://" HOST ":" PORT "/1000"
|
||||
#define URL_ACTIVE "http://" HOST ":" PORT "/1001"
|
||||
|
||||
|
||||
static int socket_callback(CURL *easy, /* easy handle */
|
||||
curl_socket_t s, /* socket */
|
||||
int what, /* see above */
|
||||
void *userp) /* "private" pointer */
|
||||
{
|
||||
struct fdinfo *fdp;
|
||||
printf("socket %d easy %p what %d\n", s, easy, what);
|
||||
|
||||
if(what == CURL_POLL_REMOVE)
|
||||
remsock(s);
|
||||
else {
|
||||
fdp = findsock(s);
|
||||
|
||||
if(!fdp) {
|
||||
addsock(s, easy, what);
|
||||
}
|
||||
else {
|
||||
/* we already know about it, just change action/timeout */
|
||||
printf("Changing info for socket %d from %d to %d\n",
|
||||
s, fdp->action, what);
|
||||
setsock(fdp, s, easy, what);
|
||||
}
|
||||
}
|
||||
return 0; /* return code meaning? */
|
||||
}
|
||||
|
||||
|
||||
static size_t
|
||||
writecallback(void *ptr, size_t size, size_t nmemb, void *data)
|
||||
{
|
||||
size_t realsize = size * nmemb;
|
||||
struct connection *c = (struct connection *)data;
|
||||
|
||||
c->dlcounter += realsize;
|
||||
c->global->dlcounter += realsize;
|
||||
|
||||
#if 0
|
||||
printf("%02d: %d, total %d\n",
|
||||
c->id, c->dlcounter, c->global->dlcounter);
|
||||
#endif
|
||||
return realsize;
|
||||
}
|
||||
|
||||
/* return the diff between two timevals, in us */
|
||||
static long tvdiff(struct timeval *newer, struct timeval *older)
|
||||
{
|
||||
return (newer->tv_sec-older->tv_sec)*1000000+
|
||||
(newer->tv_usec-older->tv_usec);
|
||||
}
|
||||
|
||||
|
||||
/* store the start time of the program in this variable */
|
||||
static struct timeval timer;
|
||||
|
||||
static void timer_start(void)
|
||||
{
|
||||
/* capture the time of the start moment */
|
||||
gettimeofday(&timer, NULL);
|
||||
}
|
||||
|
||||
static struct timeval cont; /* at this moment we continued */
|
||||
|
||||
int still_running; /* keep number of running handles */
|
||||
|
||||
struct conncount {
|
||||
long time_us;
|
||||
long laps;
|
||||
long maxtime;
|
||||
};
|
||||
|
||||
static struct timeval timerpause;
|
||||
static void timer_pause(void)
|
||||
{
|
||||
/* capture the time of the pause moment */
|
||||
gettimeofday(&timerpause, NULL);
|
||||
|
||||
/* If we have a previous continue (all times except the first), we can now
|
||||
store the time for a whole "lap" */
|
||||
if(cont.tv_sec) {
|
||||
long lap;
|
||||
|
||||
lap = tvdiff(&timerpause, &cont);
|
||||
}
|
||||
}
|
||||
|
||||
static long paused; /* amount of us we have been pausing */
|
||||
|
||||
static void timer_continue(void)
|
||||
{
|
||||
/* Capture the time of the restored operation moment, now calculate how long
|
||||
time we were paused and added that to the 'paused' variable.
|
||||
*/
|
||||
gettimeofday(&cont, NULL);
|
||||
|
||||
paused += tvdiff(&cont, &timerpause);
|
||||
}
|
||||
|
||||
static long total; /* amount of us from start to stop */
|
||||
static void timer_total(void)
|
||||
{
|
||||
struct timeval stop;
|
||||
/* Capture the time of the operation stopped moment, now calculate how long
|
||||
time we were running and how much of that pausing.
|
||||
*/
|
||||
gettimeofday(&stop, NULL);
|
||||
|
||||
total = tvdiff(&stop, &timer);
|
||||
}
|
||||
|
||||
struct globalinfo info;
|
||||
struct connection *conns;
|
||||
|
||||
long selects;
|
||||
long timeouts;
|
||||
|
||||
long multi_socket;
|
||||
long performalive;
|
||||
long performselect;
|
||||
long topselect;
|
||||
|
||||
int num_total;
|
||||
int num_idle;
|
||||
int num_active;
|
||||
|
||||
static void report(void)
|
||||
{
|
||||
int i;
|
||||
long active = total - paused;
|
||||
long numdl = 0;
|
||||
|
||||
for(i=0; i < num_total; i++) {
|
||||
if(conns[i].dlcounter)
|
||||
numdl++;
|
||||
}
|
||||
|
||||
printf("Summary from %d simultanoues transfers (%d active)\n",
|
||||
num_total, num_active);
|
||||
printf("%d out of %d connections provided data\n", numdl, num_total);
|
||||
|
||||
printf("Total time: %ldus paused: %ldus curl_multi_socket(): %ldus\n",
|
||||
total, paused, active);
|
||||
|
||||
printf("%d calls to select() "
|
||||
"Average time: %dus\n",
|
||||
selects, paused/selects);
|
||||
printf(" Average number of readable connections per select() return: %d\n",
|
||||
performselect/selects);
|
||||
|
||||
printf(" Max number of readable connections for a single select() "
|
||||
"return: %d\n",
|
||||
topselect);
|
||||
|
||||
printf("%ld calls to multi_socket(), "
|
||||
"Average time: %ldus\n",
|
||||
multi_socket, active/multi_socket);
|
||||
|
||||
printf("%ld select() timeouts\n", timeouts);
|
||||
|
||||
printf("Downloaded %ld bytes in %ld bytes/sec, %ld usec/byte\n",
|
||||
info.dlcounter,
|
||||
info.dlcounter/(total/1000000),
|
||||
total/info.dlcounter);
|
||||
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
CURLM *multi_handle;
|
||||
CURLMsg *msg;
|
||||
CURLcode code = CURLE_OK;
|
||||
CURLMcode mcode = CURLM_OK;
|
||||
int rc;
|
||||
int i;
|
||||
fd2_set fdsizecheck;
|
||||
int selectmaxamount;
|
||||
struct fdinfo *fdp;
|
||||
char act;
|
||||
|
||||
memset(&info, 0, sizeof(struct globalinfo));
|
||||
|
||||
if(argc < 3) {
|
||||
printf("Usage: hiper-event [num idle] [num active]\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
num_idle = atoi(argv[1]);
|
||||
num_active = atoi(argv[2]);
|
||||
|
||||
num_total = num_idle + num_active;
|
||||
|
||||
conns = calloc(num_total, sizeof(struct connection));
|
||||
if(!conns) {
|
||||
printf("Out of memory\n");
|
||||
return 3;
|
||||
}
|
||||
|
||||
if(num_total >= NCONNECTIONS) {
|
||||
printf("Too many connections requested, increase NCONNECTIONS!\n");
|
||||
return 2;
|
||||
}
|
||||
|
||||
event_init(); /* Initalize the event library */
|
||||
|
||||
printf("About to do %d connections\n", num_total);
|
||||
|
||||
/* init the multi stack */
|
||||
multi_handle = curl_multi_init();
|
||||
|
||||
for(i=0; i< num_total; i++) {
|
||||
CURL *e;
|
||||
char *nl;
|
||||
|
||||
memset(&conns[i], 0, sizeof(struct connection));
|
||||
|
||||
if(i < num_idle)
|
||||
conns[i].url = URL_IDLE;
|
||||
else
|
||||
conns[i].url = URL_ACTIVE;
|
||||
|
||||
e = curl_easy_init();
|
||||
|
||||
if(!e) {
|
||||
printf("curl_easy_init() for handle %d failed, exiting!\n", i);
|
||||
return 2;
|
||||
}
|
||||
|
||||
conns[i].e = e;
|
||||
conns[i].id = i;
|
||||
conns[i].global = &info;
|
||||
|
||||
curl_easy_setopt(e, CURLOPT_URL, conns[i].url);
|
||||
curl_easy_setopt(e, CURLOPT_WRITEFUNCTION, writecallback);
|
||||
curl_easy_setopt(e, CURLOPT_WRITEDATA, &conns[i]);
|
||||
curl_easy_setopt(e, CURLOPT_VERBOSE, 0);
|
||||
curl_easy_setopt(e, CURLOPT_ERRORBUFFER, conns[i].error);
|
||||
curl_easy_setopt(e, CURLOPT_PRIVATE, &conns[i]);
|
||||
|
||||
/* add the easy to the multi */
|
||||
if(CURLM_OK != curl_multi_add_handle(multi_handle, e)) {
|
||||
printf("curl_multi_add_handle() returned error for %d\n", i);
|
||||
return 3;
|
||||
}
|
||||
}
|
||||
|
||||
curl_multi_setopt(multi_handle, CURLMOPT_SOCKETFUNCTION, socket_callback);
|
||||
curl_multi_setopt(multi_handle, CURLMOPT_SOCKETDATA, NULL);
|
||||
|
||||
/* we start the action by calling *socket() right away */
|
||||
while(CURLM_CALL_MULTI_PERFORM == curl_multi_socket_all(multi_handle));
|
||||
|
||||
printf("Starting timer, expects to run for %ldus\n", RUN_FOR_THIS_LONG);
|
||||
timer_start();
|
||||
timer_pause();
|
||||
|
||||
while(1) {
|
||||
struct timeval timeout;
|
||||
int rc; /* select() return code */
|
||||
long timeout_ms;
|
||||
|
||||
fd2_set fdread;
|
||||
fd2_set fdwrite;
|
||||
int maxfd;
|
||||
|
||||
curl_multi_timeout(multi_handle, &timeout_ms);
|
||||
|
||||
/* set timeout to wait */
|
||||
timeout.tv_sec = timeout_ms/1000;
|
||||
timeout.tv_usec = (timeout_ms%1000)*1000;
|
||||
|
||||
/* convert file descriptors from the transfers to fd_sets */
|
||||
fdinfo2fdset(&fdread, &fdwrite, &maxfd);
|
||||
|
||||
selects++;
|
||||
rc = select(maxfd+1,
|
||||
(fd_set *)&fdread,
|
||||
(fd_set *)&fdwrite,
|
||||
NULL, &timeout);
|
||||
switch(rc) {
|
||||
case -1:
|
||||
/* select error */
|
||||
break;
|
||||
case 0:
|
||||
timeouts++;
|
||||
curl_multi_socket(multi_handle, CURL_SOCKET_TIMEOUT);
|
||||
break;
|
||||
|
||||
default:
|
||||
/* timeout or readable/writable sockets */
|
||||
|
||||
for(i=0, fdp = allsocks; fdp; fdp = fdp->next) {
|
||||
act = 0;
|
||||
if((fdp->action & CURL_POLL_IN) &&
|
||||
FD_ISSET(fdp->sockfd, &fdread)) {
|
||||
act |= CURL_POLL_IN;
|
||||
i++;
|
||||
}
|
||||
if((fdp->action & CURL_POLL_OUT) &&
|
||||
FD_ISSET(fdp->sockfd, &fdwrite)) {
|
||||
act |= CURL_POLL_OUT;
|
||||
i++;
|
||||
}
|
||||
|
||||
if(act) {
|
||||
multi_socket++;
|
||||
timer_continue();
|
||||
if(act & CURL_POLL_OUT)
|
||||
act--;
|
||||
curl_multi_socket(multi_handle, fdp->sockfd);
|
||||
timer_pause();
|
||||
}
|
||||
}
|
||||
|
||||
performselect += rc;
|
||||
if(rc > topselect)
|
||||
topselect = rc;
|
||||
break;
|
||||
}
|
||||
|
||||
timer_total(); /* calculate the total time spent so far */
|
||||
|
||||
if(total > RUN_FOR_THIS_LONG) {
|
||||
printf("Stopped after %ldus\n", total);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(still_running != num_total) {
|
||||
/* something made connections fail, extract the reason and tell */
|
||||
int msgs_left;
|
||||
struct connection *cptr;
|
||||
while ((msg = curl_multi_info_read(multi_handle, &msgs_left))) {
|
||||
if (msg->msg == CURLMSG_DONE) {
|
||||
curl_easy_getinfo(msg->easy_handle, CURLINFO_PRIVATE, &cptr);
|
||||
|
||||
printf("%d => (%d) %s", cptr->id, msg->data.result, cptr->error);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
curl_multi_cleanup(multi_handle);
|
||||
|
||||
/* cleanup all the easy handles */
|
||||
for(i=0; i< num_total; i++)
|
||||
curl_easy_cleanup(conns[i].e);
|
||||
|
||||
report();
|
||||
|
||||
return code;
|
||||
}
|
@@ -16,7 +16,8 @@
|
||||
* The same is hiper.c but instead using the new *socket() API instead of the
|
||||
* "old" *perform() call.
|
||||
*
|
||||
* Uses libevent.
|
||||
* Uses a select() approach but only for keeping the code simple and
|
||||
* stand-alone. See hipev.c for a libevent-based example.
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -33,8 +34,6 @@
|
||||
|
||||
#include <curl/curl.h>
|
||||
|
||||
#include <event.h> /* for libevent */
|
||||
|
||||
#ifndef FALSE
|
||||
#define FALSE 0
|
||||
#endif
|
||||
@@ -84,7 +83,6 @@ struct fdinfo {
|
||||
CURL *easy;
|
||||
int action; /* as set by libcurl */
|
||||
long timeout; /* as set by libcurl */
|
||||
struct event ev;
|
||||
};
|
||||
|
||||
static struct fdinfo *allsocks;
|
||||
|
@@ -242,7 +242,7 @@ typedef enum {
|
||||
CURLE_UNSUPPORTED_PROTOCOL, /* 1 */
|
||||
CURLE_FAILED_INIT, /* 2 */
|
||||
CURLE_URL_MALFORMAT, /* 3 */
|
||||
CURLE_URL_MALFORMAT_USER, /* 4 (NOT USED) */
|
||||
CURLE_URL_MALFORMAT_USER, /* 4 - NOT USED */
|
||||
CURLE_COULDNT_RESOLVE_PROXY, /* 5 */
|
||||
CURLE_COULDNT_RESOLVE_HOST, /* 6 */
|
||||
CURLE_COULDNT_CONNECT, /* 7 */
|
||||
@@ -250,7 +250,7 @@ typedef enum {
|
||||
CURLE_FTP_ACCESS_DENIED, /* 9 a service was denied by the FTP server
|
||||
due to lack of access - when login fails
|
||||
this is not returned. */
|
||||
CURLE_FTP_USER_PASSWORD_INCORRECT, /* 10 */
|
||||
CURLE_FTP_USER_PASSWORD_INCORRECT, /* 10 - NOT USED */
|
||||
CURLE_FTP_WEIRD_PASS_REPLY, /* 11 */
|
||||
CURLE_FTP_WEIRD_USER_REPLY, /* 12 */
|
||||
CURLE_FTP_WEIRD_PASV_REPLY, /* 13 */
|
||||
@@ -268,6 +268,10 @@ typedef enum {
|
||||
CURLE_FTP_COULDNT_STOR_FILE, /* 25 - failed FTP upload */
|
||||
CURLE_READ_ERROR, /* 26 - could open/read from file */
|
||||
CURLE_OUT_OF_MEMORY, /* 27 */
|
||||
/* Note: CURLE_OUT_OF_MEMORY may sometimes indicate a conversion error
|
||||
instead of a memory allocation error if CURL_DOES_CONVERSIONS
|
||||
is defined
|
||||
*/
|
||||
CURLE_OPERATION_TIMEOUTED, /* 28 - the timeout time was reached */
|
||||
CURLE_FTP_COULDNT_SET_ASCII, /* 29 - TYPE A failed */
|
||||
CURLE_FTP_PORT_FAILED, /* 30 - FTP PORT operation failed */
|
||||
@@ -318,9 +322,18 @@ typedef enum {
|
||||
CURLE_TFTP_UNKNOWNID, /* 72 - Unknown transfer ID */
|
||||
CURLE_TFTP_EXISTS, /* 73 - File already exists */
|
||||
CURLE_TFTP_NOSUCHUSER, /* 74 - No such user */
|
||||
CURLE_CONV_FAILED, /* 75 - conversion failed */
|
||||
CURLE_CONV_REQD, /* 76 - caller must register conversion
|
||||
callbacks using curl_easy_setopt options
|
||||
CURLOPT_CONV_FROM_NETWORK_FUNCTION,
|
||||
CURLOPT_CONV_TO_NETWORK_FUNCTION, and
|
||||
CURLOPT_CONV_FROM_UTF8_FUNCTION */
|
||||
CURL_LAST /* never use! */
|
||||
} CURLcode;
|
||||
|
||||
/* This prototype applies to all conversion callbacks */
|
||||
typedef CURLcode (*curl_conv_callback)(char *buffer, size_t length);
|
||||
|
||||
typedef CURLcode (*curl_ssl_ctx_callback)(CURL *curl, /* easy handle */
|
||||
void *ssl_ctx, /* actually an
|
||||
OpenSSL SSL_CTX */
|
||||
@@ -412,7 +425,7 @@ typedef enum {
|
||||
*/
|
||||
#if defined(__STDC__) || defined(_MSC_VER) || defined(__cplusplus) || \
|
||||
defined(__HP_aCC) || defined(__BORLANDC__) || defined(__LCC__) || \
|
||||
defined(__POCC__)
|
||||
defined(__POCC__) || defined(__SALFORDC__)
|
||||
/* This compiler is believed to have an ISO compatible preprocessor */
|
||||
#define CURL_ISOCPP
|
||||
#else
|
||||
@@ -937,6 +950,19 @@ typedef enum {
|
||||
extracting it with CURLINFO_LASTSOCKET */
|
||||
CINIT(CONNECT_ONLY, LONG, 141),
|
||||
|
||||
/* Function that will be called to convert from the
|
||||
network encoding (instead of using the iconv calls in libcurl) */
|
||||
CINIT(CONV_FROM_NETWORK_FUNCTION, FUNCTIONPOINT, 142),
|
||||
|
||||
/* Function that will be called to convert to the
|
||||
network encoding (instead of using the iconv calls in libcurl) */
|
||||
CINIT(CONV_TO_NETWORK_FUNCTION, FUNCTIONPOINT, 143),
|
||||
|
||||
/* Function that will be called to convert from UTF8
|
||||
(instead of using the iconv calls in libcurl)
|
||||
Note that this is used only for SSL certificate processing */
|
||||
CINIT(CONV_FROM_UTF8_FUNCTION, FUNCTIONPOINT, 144),
|
||||
|
||||
CURLOPT_LASTENTRY /* the last unused */
|
||||
} CURLoption;
|
||||
|
||||
@@ -1146,7 +1172,7 @@ CURL_EXTERN char *curl_getenv(const char *variable);
|
||||
CURL_EXTERN char *curl_version(void);
|
||||
|
||||
/*
|
||||
* NAME curl_escape()
|
||||
* NAME curl_easy_escape()
|
||||
*
|
||||
* DESCRIPTION
|
||||
*
|
||||
@@ -1154,18 +1180,34 @@ CURL_EXTERN char *curl_version(void);
|
||||
* %XX versions). This function returns a new allocated string or NULL if an
|
||||
* error occurred.
|
||||
*/
|
||||
CURL_EXTERN char *curl_escape(const char *string, int length);
|
||||
CURL_EXTERN char *curl_easy_escape(CURL *handle,
|
||||
const char *string,
|
||||
int length);
|
||||
|
||||
/* the previous version: */
|
||||
CURL_EXTERN char *curl_escape(const char *string,
|
||||
int length);
|
||||
|
||||
|
||||
/*
|
||||
* NAME curl_unescape()
|
||||
* NAME curl_easy_unescape()
|
||||
*
|
||||
* DESCRIPTION
|
||||
*
|
||||
* Unescapes URL encoding in strings (converts all %XX codes to their 8bit
|
||||
* versions). This function returns a new allocated string or NULL if an error
|
||||
* occurred.
|
||||
* Conversion Note: On non-ASCII platforms the ASCII %XX codes are
|
||||
* converted into the host encoding.
|
||||
*/
|
||||
CURL_EXTERN char *curl_unescape(const char *string, int length);
|
||||
CURL_EXTERN char *curl_easy_unescape(CURL *handle,
|
||||
const char *string,
|
||||
int length,
|
||||
int *outlength);
|
||||
|
||||
/* the previous version */
|
||||
CURL_EXTERN char *curl_unescape(const char *string,
|
||||
int length);
|
||||
|
||||
/*
|
||||
* NAME curl_free()
|
||||
@@ -1292,9 +1334,10 @@ typedef enum {
|
||||
CURLINFO_SSL_ENGINES = CURLINFO_SLIST + 27,
|
||||
CURLINFO_COOKIELIST = CURLINFO_SLIST + 28,
|
||||
CURLINFO_LASTSOCKET = CURLINFO_LONG + 29,
|
||||
CURLINFO_FTP_ENTRY_PATH = CURLINFO_STRING + 30,
|
||||
/* Fill in new entries below here! */
|
||||
|
||||
CURLINFO_LASTONE = 29
|
||||
CURLINFO_LASTONE = 30
|
||||
} CURLINFO;
|
||||
|
||||
/* CURLINFO_RESPONSE_CODE is the new name for the option previously known as
|
||||
@@ -1431,6 +1474,8 @@ typedef struct {
|
||||
#define CURL_VERSION_LARGEFILE (1<<9) /* supports files bigger than 2GB */
|
||||
#define CURL_VERSION_IDN (1<<10) /* International Domain Names support */
|
||||
#define CURL_VERSION_SSPI (1<<11) /* SSPI is supported */
|
||||
#define CURL_VERSION_CONV (1<<12) /* character conversions are
|
||||
supported */
|
||||
|
||||
/*
|
||||
* NAME curl_version_info()
|
||||
|
@@ -28,13 +28,13 @@
|
||||
|
||||
/* This is the version number of the libcurl package from which this header
|
||||
file origins: */
|
||||
#define LIBCURL_VERSION "7.15.3-CVS"
|
||||
#define LIBCURL_VERSION "7.15.4-CVS"
|
||||
|
||||
/* The numeric version number is also available "in parts" by using these
|
||||
defines: */
|
||||
#define LIBCURL_VERSION_MAJOR 7
|
||||
#define LIBCURL_VERSION_MINOR 15
|
||||
#define LIBCURL_VERSION_PATCH 3
|
||||
#define LIBCURL_VERSION_PATCH 4
|
||||
|
||||
/* This is the numeric version of the libcurl version number, meant for easier
|
||||
parsing and comparions by programs. The LIBCURL_VERSION_NUM define will
|
||||
@@ -51,6 +51,6 @@
|
||||
and it is always a greater number in a more recent release. It makes
|
||||
comparisons with greater than and less than work.
|
||||
*/
|
||||
#define LIBCURL_VERSION_NUM 0x070f03
|
||||
#define LIBCURL_VERSION_NUM 0x070f04
|
||||
|
||||
#endif /* __CURL_CURLVER_H */
|
||||
|
@@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2005, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2006, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -42,11 +42,18 @@ CURL_EXTERN char *curl_mvaprintf(const char *format, va_list args);
|
||||
#ifdef _MPRINTF_REPLACE
|
||||
# define printf curl_mprintf
|
||||
# define fprintf curl_mfprintf
|
||||
#ifdef CURLDEBUG
|
||||
/* When built with CURLDEBUG we define away the sprintf() functions since we
|
||||
don't want internal code to be using them */
|
||||
# define sprintf sprintf_was_used
|
||||
# define vsprintf vsprintf_was_used
|
||||
#else
|
||||
# define sprintf curl_msprintf
|
||||
# define vsprintf curl_mvsprintf
|
||||
#endif
|
||||
# define snprintf curl_msnprintf
|
||||
# define vprintf curl_mvprintf
|
||||
# define vfprintf curl_mvfprintf
|
||||
# define vsprintf curl_mvsprintf
|
||||
# define vsnprintf curl_mvsnprintf
|
||||
# define aprintf curl_maprintf
|
||||
# define vaprintf curl_mvaprintf
|
||||
|
@@ -83,8 +83,6 @@ extern "C" {
|
||||
|
||||
typedef void CURLM;
|
||||
|
||||
#ifdef HAVE_CURL_MULTI_SOCKET /* this is not set by anything yet */
|
||||
|
||||
#ifndef curl_socket_typedef
|
||||
/* Public socket typedef */
|
||||
#ifdef WIN32
|
||||
@@ -97,8 +95,6 @@ typedef int curl_socket_t;
|
||||
#define curl_socket_typedef
|
||||
#endif /* curl_socket_typedef */
|
||||
|
||||
#endif /* HAVE_CURL_MULTI_SOCKET */
|
||||
|
||||
typedef enum {
|
||||
CURLM_CALL_MULTI_PERFORM = -1, /* please call curl_multi_perform() soon */
|
||||
CURLM_OK,
|
||||
@@ -106,6 +102,8 @@ typedef enum {
|
||||
CURLM_BAD_EASY_HANDLE, /* an easy handle was not good/valid */
|
||||
CURLM_OUT_OF_MEMORY, /* if you ever get this, you're in deep sh*t */
|
||||
CURLM_INTERNAL_ERROR, /* this is a libcurl bug */
|
||||
CURLM_BAD_SOCKET, /* the passed in socket argument did not match */
|
||||
CURLM_UNKNOWN_OPTION, /* curl_multi_setopt() with unsupported option */
|
||||
CURLM_LAST
|
||||
} CURLMcode;
|
||||
|
||||
@@ -243,7 +241,6 @@ CURL_EXTERN CURLMsg *curl_multi_info_read(CURLM *multi_handle,
|
||||
*/
|
||||
CURL_EXTERN const char *curl_multi_strerror(CURLMcode);
|
||||
|
||||
#ifdef HAVE_CURL_MULTI_SOCKET
|
||||
/*
|
||||
* Name: curl_multi_socket() and
|
||||
* curl_multi_socket_all()
|
||||
@@ -259,8 +256,6 @@ CURL_EXTERN const char *curl_multi_strerror(CURLMcode);
|
||||
#define CURL_POLL_INOUT 3
|
||||
#define CURL_POLL_REMOVE 4
|
||||
|
||||
#define CURL_EASY_NONE (CURL *)0
|
||||
#define CURL_EASY_TIMEOUT (CURL *)0
|
||||
#define CURL_SOCKET_TIMEOUT CURL_SOCKET_BAD
|
||||
|
||||
typedef int (*curl_socket_callback)(CURL *easy, /* easy handle */
|
||||
@@ -268,15 +263,9 @@ typedef int (*curl_socket_callback)(CURL *easy, /* easy handle */
|
||||
int what, /* see above */
|
||||
void *userp); /* "private" pointer */
|
||||
|
||||
CURLMcode curl_multi_socket(CURLM *multi_handle,
|
||||
curl_socket_t s,
|
||||
CURL *easy,
|
||||
curl_socket_callback callback,
|
||||
void *userp); /* passed to callback */
|
||||
CURLMcode curl_multi_socket(CURLM *multi_handle, curl_socket_t s);
|
||||
|
||||
CURLMcode curl_multi_socket_all(CURLM *multi_handle,
|
||||
curl_socket_callback callback,
|
||||
void *userp); /* passed to callback */
|
||||
CURLMcode curl_multi_socket_all(CURLM *multi_handle);
|
||||
|
||||
/*
|
||||
* Name: curl_multi_timeout()
|
||||
@@ -289,7 +278,39 @@ CURLMcode curl_multi_socket_all(CURLM *multi_handle,
|
||||
*/
|
||||
CURLMcode curl_multi_timeout(CURLM *multi_handle, long *milliseconds);
|
||||
|
||||
#endif /* HAVE_CURL_MULTI_SOCKET */
|
||||
#undef CINIT /* re-using the same name as in curl.h */
|
||||
|
||||
#ifdef CURL_ISOCPP
|
||||
#define CINIT(name,type,number) CURLMOPT_ ## name = CURLOPTTYPE_ ## type + number
|
||||
#else
|
||||
/* The macro "##" is ISO C, we assume pre-ISO C doesn't support it. */
|
||||
#define LONG CURLOPTTYPE_LONG
|
||||
#define OBJECTPOINT CURLOPTTYPE_OBJECTPOINT
|
||||
#define FUNCTIONPOINT CURLOPTTYPE_FUNCTIONPOINT
|
||||
#define OFF_T CURLOPTTYPE_OFF_T
|
||||
#define CINIT(name,type,number) CURLMOPT_/**/name = type + number
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
/* This is the socket callback function pointer */
|
||||
CINIT(SOCKETFUNCTION, FUNCTIONPOINT, 1),
|
||||
|
||||
/* This is the argument passed to the socket callback */
|
||||
CINIT(SOCKETDATA, OBJECTPOINT, 2),
|
||||
|
||||
CURLMOPT_LASTENTRY /* the last unused */
|
||||
} CURLMoption;
|
||||
|
||||
|
||||
/*
|
||||
* Name: curl_multi_setopt()
|
||||
*
|
||||
* Desc: Sets options for the multi handle.
|
||||
*
|
||||
* Returns: CURLM error code.
|
||||
*/
|
||||
CURLMcode curl_multi_setopt(CURLM *multi_handle,
|
||||
CURLMoption option, ...);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* end of extern "C" */
|
||||
|
@@ -45,7 +45,8 @@ OBJS = $(OBJ_DIR)\transfer.obj $(OBJ_DIR)\file.obj &
|
||||
$(OBJ_DIR)\hostip6.obj $(OBJ_DIR)\inet_ntop.obj &
|
||||
$(OBJ_DIR)\hostsyn.obj $(OBJ_DIR)\parsedate.obj &
|
||||
$(OBJ_DIR)\select.obj $(OBJ_DIR)\sslgen.obj &
|
||||
$(OBJ_DIR)\gtls.obj $(OBJ_DIR)\tftp.obj
|
||||
$(OBJ_DIR)\gtls.obj $(OBJ_DIR)\tftp.obj &
|
||||
$(OBJ_DIR)\splay.obj
|
||||
|
||||
RESOURCE = $(OBJ_DIR)\libcurl.res
|
||||
|
||||
|
@@ -5,7 +5,7 @@
|
||||
# | (__| |_| | _ <| |___
|
||||
# \___|\___/|_| \_\_____|
|
||||
#
|
||||
# Copyright (C) 1998 - 2005, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
# Copyright (C) 1998 - 2006, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
#
|
||||
# This software is licensed as described in the file COPYING, which
|
||||
# you should have received as part of this distribution. The terms
|
||||
@@ -30,7 +30,8 @@ EXTRA_DIST = Makefile.b32 Makefile.m32 Makefile.vc6 Makefile.riscos $(DSP) \
|
||||
README.ares README.curlx makefile.dj config.dj libcurl.framework.make \
|
||||
libcurl.plist libcurl.rc config-amigaos.h amigaos.c amigaos.h makefile.amiga \
|
||||
Makefile.netware nwlib.c libcurl.imp msvcproj.head msvcproj.foot \
|
||||
config-win32ce.h README.httpauth Makefile.Watcom README.hostip
|
||||
config-win32ce.h README.httpauth Makefile.Watcom README.hostip \
|
||||
README.multi_socket config-tpf.h
|
||||
|
||||
CLEANFILES = $(DSP)
|
||||
|
||||
|
@@ -8,7 +8,7 @@ CSOURCES = file.c timeval.c base64.c hostip.c progress.c formdata.c \
|
||||
content_encoding.c share.c http_digest.c md5.c http_negotiate.c \
|
||||
http_ntlm.c inet_pton.c strtoofft.c strerror.c hostares.c hostasyn.c \
|
||||
hostip4.c hostip6.c hostsyn.c hostthre.c inet_ntop.c parsedate.c \
|
||||
select.c gtls.c sslgen.c tftp.c
|
||||
select.c gtls.c sslgen.c tftp.c splay.c
|
||||
|
||||
HHEADERS = arpa_telnet.h netrc.h file.h timeval.h base64.h hostip.h \
|
||||
progress.h formdata.h cookie.h http.h sendf.h ftp.h url.h dict.h \
|
||||
@@ -18,6 +18,6 @@ HHEADERS = arpa_telnet.h netrc.h file.h timeval.h base64.h hostip.h \
|
||||
share.h md5.h http_digest.h http_negotiate.h http_ntlm.h ca-bundle.h \
|
||||
inet_pton.h strtoofft.h strerror.h inet_ntop.h curlx.h memory.h \
|
||||
setup.h transfer.h select.h easyif.h multiif.h parsedate.h sslgen.h \
|
||||
gtls.h tftp.h sockaddr.h
|
||||
gtls.h tftp.h sockaddr.h splay.h
|
||||
|
||||
|
||||
|
@@ -19,7 +19,7 @@ endif
|
||||
|
||||
# Edit the path below to point to the base of your OpenSSL package.
|
||||
ifndef OPENSSL_PATH
|
||||
OPENSSL_PATH = ../../openssl-0.9.8
|
||||
OPENSSL_PATH = ../../openssl-0.9.8a
|
||||
endif
|
||||
|
||||
ifndef INSTDIR
|
||||
@@ -29,7 +29,7 @@ endif
|
||||
# Edit the vars below to change NLM target settings.
|
||||
TARGET = libcurl
|
||||
VERSION = $(LIBCURL_VERSION)
|
||||
COPYR = Copyright (C) 1996 - 2005, Daniel Stenberg, <daniel@haxx.se>
|
||||
COPYR = Copyright (C) 1996 - 2006, Daniel Stenberg, <daniel@haxx.se>
|
||||
DESCR = cURL libcurl $(LIBCURL_VERSION_STR) - http://curl.haxx.se
|
||||
MTSAFE = YES
|
||||
STACK = 64000
|
||||
@@ -95,7 +95,7 @@ LD = nlmconv
|
||||
LDFLAGS = -T
|
||||
AR = ar
|
||||
ARFLAGS = -cq
|
||||
CFLAGS += -fno-builtin -fpack-struct -fpcc-struct-return -fno-strict-aliasing
|
||||
CFLAGS += -fno-builtin -fpcc-struct-return -fno-strict-aliasing
|
||||
CFLAGS += -Wall # -pedantic
|
||||
ifeq ($(LIBARCH),LIBC)
|
||||
PRELUDE = $(SDK_LIBC)/imports/libcpre.gcc.o
|
||||
|
@@ -480,6 +480,7 @@ X_OBJS= \
|
||||
$(DIROBJ)\select.obj \
|
||||
$(DIROBJ)\content_encoding.obj \
|
||||
$(DIROBJ)\tftp.obj \
|
||||
$(DIROBJ)\splay.obj \
|
||||
$(RESOURCE)
|
||||
|
||||
all : $(TARGET)
|
||||
|
112
lib/README.multi_socket
Normal file
112
lib/README.multi_socket
Normal file
@@ -0,0 +1,112 @@
|
||||
Implementation of the curl_multi_socket API
|
||||
|
||||
Most of the design decisions and debates about this new API have already
|
||||
been held on the curl-library mailing list a long time ago so I had a basic
|
||||
idea on what approach to use. The main ideas of the new API are simply:
|
||||
|
||||
1 - The application can use whatever event system it likes as it gets info
|
||||
from libcurl about what file descriptors libcurl waits for what action
|
||||
on. (The previous API returns fd_sets which is very select()-centric).
|
||||
|
||||
2 - When the application discovers action on a single socket, it calls
|
||||
libcurl and informs that there was action on this particular socket and
|
||||
libcurl can then act on that socket/transfer only and not care about
|
||||
any other transfers. (The previous API always had to scan through all
|
||||
the existing transfers.)
|
||||
|
||||
The idea is that curl_multi_socket() calls a given callback with information
|
||||
about what socket to wait for what action on, and the callback only gets
|
||||
called if the status of that socket has changed.
|
||||
|
||||
In the API draft from before, we have a timeout argument on a per socket
|
||||
basis and we also allowed curl_multi_socket() to pass in an 'easy handle'
|
||||
instead of socket to allow libcurl to shortcut a lookup and work on the
|
||||
affected easy handle right away. Both these turned out to be bad ideas.
|
||||
|
||||
The timeout argument was removed from the socket callback since after much
|
||||
thinking I came to the conclusion that we really don't want to handle
|
||||
timeouts on a per socket basis. We need it on a per transfer (easy handle)
|
||||
basis and thus we can't provide it in the callbacks in a nice way. Instead,
|
||||
we have to offer a curl_multi_timeout() that returns the largest amount of
|
||||
time we should wait before we call the "timeout action" of libcurl, to
|
||||
trigger the proper internal timeout action on the affected transfer. To get
|
||||
this to work, I added a struct to each easy handle in which we store an
|
||||
"expire time" (if any). The structs are then "splay sorted" so that we can
|
||||
add and remove times from the linked list and yet somewhat swiftly figure
|
||||
out 1 - how long time there is until the next timer expires and 2 - which
|
||||
timer (handle) should we take care of now. Of course, the upside of all this
|
||||
is that we get a curl_multi_timeout() that should also work with old-style
|
||||
applications that use curl_multi_perform().
|
||||
|
||||
The easy handle argument was removed fom the curl_multi_socket() function
|
||||
because having it there would require the application to do a socket to easy
|
||||
handle conversion on its own. I find it very unlikely that applications
|
||||
would want to do that and since libcurl would need such a lookup on its own
|
||||
anyway since we didn't want to force applications to do that translation
|
||||
code (it would be optional), it seemed like an unnecessary option.
|
||||
|
||||
Instead I created an internal "socket to easy handles" hash table that given
|
||||
a socket (file descriptor) return the easy handle that waits for action on
|
||||
that socket. This hash is made using the already existing hash code
|
||||
(previously only used for the DNS cache).
|
||||
|
||||
To make libcurl be able to report plain sockets in the socket callback, I
|
||||
had to re-organize the internals of the curl_multi_fdset() etc so that the
|
||||
conversion from sockets to fd_sets for that function is only done in the
|
||||
last step before the data is returned. I also had to extend c-ares to get a
|
||||
function that can return plain sockets, as that library too returned only
|
||||
fd_sets and that is no longer good enough. The changes done to c-ares have
|
||||
been committed and are available in the c-ares CVS repository destined to be
|
||||
included in the upcoming c-ares 1.3.1 release.
|
||||
|
||||
The 'shiper' tool is the test application I wrote that uses the new
|
||||
curl_multi_socket() in its current state. It seems to be working and it uses
|
||||
the API as it is documented and supposed to work. It is still using
|
||||
select(), because I needed that during development (like until I had the
|
||||
socket hash implemented etc) and because I haven't yet learned how to use
|
||||
libevent or similar.
|
||||
|
||||
The hiper/shiper tools are very simple and initiates lots of connections and
|
||||
have them running for the test period and then kills them all.
|
||||
|
||||
Since I wasn't done with the implementation until early January I haven't
|
||||
had time to run very many measurements and checks, but I have done a few
|
||||
runs with up to a few hundred connections (with a single active one). The
|
||||
curl_multi_socket() invoke then takes 3-6 microseconds in average (using the
|
||||
read-only-1-byte-at-a-time hack). If this number does increase a lot when we
|
||||
add connections, it certainly matches my in my opinion very ambitious goal.
|
||||
We are now below the 60 microseconds "per socket action" goal. It is
|
||||
destined to be somewhat higher the more connections we have since the hash
|
||||
table gets more populated and the splay tree will grow etc.
|
||||
|
||||
Some tests at 7000 and 9000 connections showed that the socket hash lookup
|
||||
is somewhat of a bottle neck. Its current implementation may be a bit too
|
||||
limiting. It simply has a fixed-size array, and on each entry in the array
|
||||
it has a linked list with entries. So the hash only checks which list to
|
||||
scan through. The code I had used so for used a list with merely 7 slots (as
|
||||
that is what the DNS hash uses) but with 7000 connections that would make an
|
||||
average of 1000 nodes in each list to run through. I upped that to 97 slots
|
||||
(I believe a prime is suitable) and noticed a significant speed increase. I
|
||||
need to reconsider the hash implementation or use a rather large default
|
||||
value like this. At 9000 connections I was still below 10us per call.
|
||||
|
||||
Status Right Now
|
||||
|
||||
The curl_multi_socket() API is implemented according to how it is
|
||||
documented.
|
||||
|
||||
http://curl.haxx.se/libcurl/c/curl_multi_socket.html
|
||||
http://curl.haxx.se/libcurl/c/curl_multi_timeout.html
|
||||
http://curl.haxx.se/libcurl/c/curl_multi_setopt.html
|
||||
|
||||
What is Left for the curl_multi_socket API
|
||||
|
||||
1 - More measuring with more extreme number of connections
|
||||
|
||||
2 - More testing with actual URLs and complete from start to end transfers.
|
||||
|
||||
I'm quite sure we don't set expire times all over in the code properly, so
|
||||
there is bound to be some timeout bugs left.
|
||||
|
||||
What it really takes is for me to commit the code and to make an official
|
||||
release with it so that we get people "out there" to help out testing it.
|
688
lib/config-tpf.h
Normal file
688
lib/config-tpf.h
Normal file
@@ -0,0 +1,688 @@
|
||||
#ifndef __LIBCONFIGTPF_H
|
||||
#define __LIBCONFIGTPF_H
|
||||
|
||||
/* ================================================================ */
|
||||
/* lib/config-tpf.h - Hand crafted config file for TPF */
|
||||
/* ================================================================ */
|
||||
|
||||
/* ---------------------------------------------------------------- */
|
||||
/* FEATURES, FUNCTIONS, and DEFINITIONS */
|
||||
/* ---------------------------------------------------------------- */
|
||||
|
||||
/* NOTE: Refer also to the .mak file for some of the flags below */
|
||||
|
||||
/* when building libcurl itself */
|
||||
/* #undef BUILDING_LIBCURL */
|
||||
|
||||
/* to disable cookies support */
|
||||
/* #undef CURL_DISABLE_COOKIES */
|
||||
|
||||
/* to disable cryptographic authentication */
|
||||
/* #undef CURL_DISABLE_CRYPTO_AUTH */
|
||||
|
||||
/* to disable DICT */
|
||||
/* #undef CURL_DISABLE_DICT */
|
||||
|
||||
/* to disable FILE */
|
||||
/* #undef CURL_DISABLE_FILE */
|
||||
|
||||
/* to disable FTP */
|
||||
/* #undef CURL_DISABLE_FTP */
|
||||
|
||||
/* to disable HTTP */
|
||||
/* #undef CURL_DISABLE_HTTP */
|
||||
|
||||
/* to disable LDAP */
|
||||
/* #undef CURL_DISABLE_LDAP */
|
||||
|
||||
/* to disable TELNET */
|
||||
/* #undef CURL_DISABLE_TELNET */
|
||||
|
||||
/* to disable TFTP */
|
||||
/* #undef CURL_DISABLE_TFTP */
|
||||
|
||||
/* to disable verbose strings */
|
||||
/* #undef CURL_DISABLE_VERBOSE_STRINGS */
|
||||
|
||||
/* when not building a shared library */
|
||||
/* #undef CURL_STATICLIB */
|
||||
|
||||
/* Set to explicitly specify we don't want to use thread-safe functions */
|
||||
/* #undef DISABLED_THREADSAFE */
|
||||
|
||||
/* lber dynamic library file */
|
||||
/* #undef DL_LBER_FILE */
|
||||
|
||||
/* ldap dynamic library file */
|
||||
/* #undef DL_LDAP_FILE */
|
||||
|
||||
/* your Entropy Gathering Daemon socket pathname */
|
||||
/* #undef EGD_SOCKET */
|
||||
|
||||
/* Define if you want to enable IPv6 support */
|
||||
/* #undef ENABLE_IPV6 */
|
||||
|
||||
/* Define to the type of arg 1 for getnameinfo. */
|
||||
/* #undef GETNAMEINFO_TYPE_ARG1 */
|
||||
|
||||
/* Define to the type of arg 2 for getnameinfo. */
|
||||
/* #undef GETNAMEINFO_TYPE_ARG2 */
|
||||
|
||||
/* Define to the type of args 4 and 6 for getnameinfo. */
|
||||
/* #undef GETNAMEINFO_TYPE_ARG46 */
|
||||
|
||||
/* Define to the type of arg 7 for getnameinfo. */
|
||||
/* #undef GETNAMEINFO_TYPE_ARG7 */
|
||||
|
||||
/* Define to 1 if you have the <alloca.h> header file. */
|
||||
#define HAVE_ALLOCA_H 1
|
||||
|
||||
/* Define to 1 if you have the <arpa/inet.h> header file. */
|
||||
#define HAVE_ARPA_INET_H 1
|
||||
|
||||
/* Define to 1 if you have the <arpa/tftp.h> header file. */
|
||||
/* #undef HAVE_ARPA_TFTP_H */
|
||||
|
||||
/* Define to 1 if you have the <assert.h> header file. */
|
||||
#define HAVE_ASSERT_H 1
|
||||
|
||||
/* Define to 1 if you have the `basename' function. */
|
||||
#define HAVE_BASENAME 1
|
||||
|
||||
/* Define to 1 if you have the `closesocket' function. */
|
||||
/* #undef HAVE_CLOSESOCKET */
|
||||
|
||||
/* Define to 1 if you have the `CRYPTO_cleanup_all_ex_data' function. */
|
||||
/* #undef HAVE_CRYPTO_CLEANUP_ALL_EX_DATA */
|
||||
#define HAVE_CRYPTO_CLEANUP_ALL_EX_DATA 1
|
||||
|
||||
/* Define to 1 if you have the <crypto.h> header file. */
|
||||
/* #undef HAVE_CRYPTO_H */
|
||||
#define HAVE_CRYPTO_H 1
|
||||
|
||||
/* Define to 1 if you have the <des.h> header file. */
|
||||
/* #undef HAVE_DES_H */
|
||||
#define HAVE_DES_H 1
|
||||
|
||||
/* disabled non-blocking sockets */
|
||||
/* #undef HAVE_DISABLED_NONBLOCKING */
|
||||
|
||||
/* Define to 1 if you have the <dlfcn.h> header file. */
|
||||
#define HAVE_DLFCN_H 1
|
||||
|
||||
/* Define to 1 if you have the `dlopen' function. */
|
||||
#define HAVE_DLOPEN 1
|
||||
|
||||
/* Define to 1 if you have the `ENGINE_load_builtin_engines' function. */
|
||||
/* #undef HAVE_ENGINE_LOAD_BUILTIN_ENGINES */
|
||||
#define HAVE_ENGINE_LOAD_BUILTIN_ENGINES 1
|
||||
|
||||
/* Define to 1 if you have the <errno.h> header file. */
|
||||
#define HAVE_ERRNO_H 1
|
||||
|
||||
/* Define to 1 if you have the <err.h> header file. */
|
||||
/* #undef HAVE_ERR_H */
|
||||
#define HAVE_ERR_H 1
|
||||
|
||||
/* Define to 1 if you have the <fcntl.h> header file. */
|
||||
#define HAVE_FCNTL_H 1
|
||||
|
||||
/* use FIONBIO for non-blocking sockets */
|
||||
/* #undef HAVE_FIONBIO */
|
||||
#define HAVE_FIONBIO 1
|
||||
|
||||
/* Define to 1 if you have the `fork' function. */
|
||||
/* #undef HAVE_FORK */
|
||||
#define HAVE_FORK 1
|
||||
|
||||
/* Define to 1 if you have the `ftruncate' function. */
|
||||
#define HAVE_FTRUNCATE 1
|
||||
|
||||
/* Define if getaddrinfo exists and works */
|
||||
/* #undef HAVE_GETADDRINFO */
|
||||
|
||||
/* Define to 1 if you have the `geteuid' function. */
|
||||
#define HAVE_GETEUID 1
|
||||
|
||||
/* Define to 1 if you have the `gethostbyaddr' function. */
|
||||
#define HAVE_GETHOSTBYADDR 1
|
||||
|
||||
/* If you have gethostbyname */
|
||||
#define HAVE_GETHOSTBYNAME 1
|
||||
|
||||
/* Define to 1 if you have the `gethostbyname_r' function. */
|
||||
/* #undef HAVE_GETHOSTBYNAME_R */
|
||||
|
||||
/* gethostbyname_r() takes 3 args */
|
||||
/* #undef HAVE_GETHOSTBYNAME_R_3 */
|
||||
|
||||
/* gethostbyname_r() takes 5 args */
|
||||
/* #undef HAVE_GETHOSTBYNAME_R_5 */
|
||||
|
||||
/* gethostbyname_r() takes 6 args */
|
||||
/* #undef HAVE_GETHOSTBYNAME_R_6 1 */
|
||||
|
||||
/* Define to 1 if you have the getnameinfo function. */
|
||||
/* #undef HAVE_GETNAMEINFO */
|
||||
|
||||
/* Define to 1 if you have the `getpass_r' function. */
|
||||
/* #undef HAVE_GETPASS_R */
|
||||
|
||||
/* Define to 1 if you have the `getprotobyname' function. */
|
||||
/* #undef HAVE_GETPROTOBYNAME */
|
||||
|
||||
/* Define to 1 if you have the `getpwuid' function. */
|
||||
#define HAVE_GETPWUID 1
|
||||
|
||||
/* Define to 1 if you have the `getrlimit' function. */
|
||||
/* #undef HAVE_GETRLIMIT */
|
||||
|
||||
/* Define to 1 if you have the `gettimeofday' function. */
|
||||
#define HAVE_GETTIMEOFDAY 1
|
||||
|
||||
/* we have a glibc-style strerror_r() */
|
||||
/* #undef HAVE_GLIBC_STRERROR_R */
|
||||
#define HAVE_GLIBC_STRERROR_R 1
|
||||
|
||||
/* Define to 1 if you have the `gmtime_r' function. */
|
||||
#define HAVE_GMTIME_R 1
|
||||
|
||||
/* if you have the gssapi libraries */
|
||||
/* #undef HAVE_GSSAPI */
|
||||
|
||||
/* if you have the GNU gssapi libraries */
|
||||
/* #undef HAVE_GSSGNU */
|
||||
|
||||
/* if you have the Heimdal gssapi libraries */
|
||||
/* #undef HAVE_GSSHEIMDAL */
|
||||
|
||||
/* if you have the MIT gssapi libraries */
|
||||
/* #undef HAVE_GSSMIT */
|
||||
|
||||
/* Define to 1 if you have the `iconv' functions. */
|
||||
#define HAVE_ICONV 1
|
||||
|
||||
/* Define to 1 if you have the `idna_strerror' function. */
|
||||
/* #undef HAVE_IDNA_STRERROR */
|
||||
|
||||
/* Define to 1 if you have the `idn_free' function. */
|
||||
/* #undef HAVE_IDN_FREE */
|
||||
|
||||
/* Define to 1 if you have the <idn-free.h> header file. */
|
||||
/* #undef HAVE_IDN_FREE_H */
|
||||
|
||||
/* Define to 1 if you have the `inet_addr' function. */
|
||||
#define HAVE_INET_ADDR 1
|
||||
|
||||
/* Define to 1 if you have the `inet_ntoa' function. */
|
||||
#define HAVE_INET_NTOA 1
|
||||
|
||||
/* Define to 1 if you have the `inet_ntoa_r' function. */
|
||||
/* #undef HAVE_INET_NTOA_R */
|
||||
|
||||
/* inet_ntoa_r() is declared */
|
||||
/* #undef HAVE_INET_NTOA_R_DECL */
|
||||
|
||||
/* Define to 1 if you have the `inet_pton' function. */
|
||||
/* #undef HAVE_INET_PTON */
|
||||
|
||||
/* Define to 1 if you have the <inttypes.h> header file. */
|
||||
#define HAVE_INTTYPES_H 1
|
||||
|
||||
/* use ioctlsocket() for non-blocking sockets */
|
||||
/* #undef HAVE_IOCTLSOCKET */
|
||||
|
||||
/* use Ioctlsocket() for non-blocking sockets */
|
||||
/* #undef HAVE_IOCTLSOCKET_CASE */
|
||||
|
||||
/* Define to 1 if you have the <io.h> header file. */
|
||||
/* #undef HAVE_IO_H */
|
||||
|
||||
/* if you have the Kerberos4 libraries (including -ldes) */
|
||||
/* #undef HAVE_KRB4 */
|
||||
|
||||
/* Define to 1 if you have the `krb_get_our_ip_for_realm' function. */
|
||||
/* #undef HAVE_KRB_GET_OUR_IP_FOR_REALM */
|
||||
|
||||
/* Define to 1 if you have the <krb.h> header file. */
|
||||
/* #undef HAVE_KRB_H */
|
||||
|
||||
/* Define to 1 if you have the `dl' library (-ldl). */
|
||||
#define HAVE_LIBDL 1
|
||||
|
||||
/* Define to 1 if you have the <libgen.h> header file. */
|
||||
/* #undef HAVE_LIBGEN_H 1 */
|
||||
|
||||
/* Define to 1 if you have the `idn' library (-lidn). */
|
||||
/* #undef HAVE_LIBIDN */
|
||||
|
||||
/* Define to 1 if you have the `resolv' library (-lresolv). */
|
||||
/* #undef HAVE_LIBRESOLV */
|
||||
|
||||
/* Define to 1 if you have the `resolve' library (-lresolve). */
|
||||
/* #undef HAVE_LIBRESOLVE */
|
||||
|
||||
/* Define to 1 if you have the `socket' library (-lsocket). */
|
||||
/* #undef HAVE_LIBSOCKET */
|
||||
|
||||
/* Define to 1 if you have the `ssl' library (-lssl). */
|
||||
/* #undef HAVE_LIBSSL */
|
||||
#define HAVE_LIBSSL 1
|
||||
|
||||
/* if zlib is available */
|
||||
/* #undef HAVE_LIBZ */
|
||||
|
||||
/* Define to 1 if you have the <limits.h> header file. */
|
||||
#define HAVE_LIMITS_H 1
|
||||
|
||||
/* if your compiler supports LL */
|
||||
#define HAVE_LL 1
|
||||
|
||||
/* Define to 1 if you have the <locale.h> header file. */
|
||||
#define HAVE_LOCALE_H 1
|
||||
|
||||
/* Define to 1 if you have the `localtime_r' function. */
|
||||
#define HAVE_LOCALTIME_R 1
|
||||
|
||||
/* if your compiler supports long long */
|
||||
#define HAVE_LONGLONG 1
|
||||
|
||||
/* Define to 1 if you have the <malloc.h> header file. */
|
||||
/* #undef HAVE_MALLOC_H */
|
||||
|
||||
/* Define to 1 if you have the <memory.h> header file. */
|
||||
#define HAVE_MEMORY_H 1
|
||||
|
||||
/* Define to 1 if you have the <netdb.h> header file. */
|
||||
#define HAVE_NETDB_H 1
|
||||
|
||||
/* Define to 1 if you have the <netinet/in.h> header file. */
|
||||
#define HAVE_NETINET_IN_H 1
|
||||
|
||||
/* Define to 1 if you have the <netinet/tcp.h> header file. */
|
||||
/* undef HAVE_NETINET_TCP_H */
|
||||
|
||||
/* Define to 1 if you have the <net/if.h> header file. */
|
||||
#define HAVE_NET_IF_H 1
|
||||
|
||||
/* Define if NI_WITHSCOPEID exists and works */
|
||||
/* #undef HAVE_NI_WITHSCOPEID */
|
||||
|
||||
/* Defined if no inet_pton() prototype available */
|
||||
/* #undef HAVE_NO_INET_PTON_PROTO */
|
||||
|
||||
/* we have no strerror_r() proto */
|
||||
/* #undef HAVE_NO_STRERROR_R_DECL */
|
||||
|
||||
/* Define to 1 if you have the <openssl/crypto.h> header file. */
|
||||
/* #undef HAVE_OPENSSL_CRYPTO_H */
|
||||
#define HAVE_OPENSSL_CRYPTO_H 1
|
||||
|
||||
/* Define to 1 if you have the <openssl/engine.h> header file. */
|
||||
/* #undef HAVE_OPENSSL_ENGINE_H */
|
||||
#define HAVE_OPENSSL_ENGINE_H 1
|
||||
|
||||
/* Define to 1 if you have the <openssl/err.h> header file. */
|
||||
/* #undef HAVE_OPENSSL_ERR_H */
|
||||
#define HAVE_OPENSSL_ERR_H 1
|
||||
|
||||
/* Define to 1 if you have the <openssl/pem.h> header file. */
|
||||
/* #undef HAVE_OPENSSL_PEM_H */
|
||||
#define HAVE_OPENSSL_PEM_H 1
|
||||
|
||||
/* Define to 1 if you have the <openssl/pkcs12.h> header file. */
|
||||
/* #undef HAVE_OPENSSL_PKCS12_H */
|
||||
#define HAVE_OPENSSL_PKCS12_H 1
|
||||
|
||||
/* Define to 1 if you have the <openssl/rsa.h> header file. */
|
||||
/* #undef HAVE_OPENSSL_RSA_H */
|
||||
#define HAVE_OPENSSL_RSA_H 1
|
||||
|
||||
/* Define to 1 if you have the <openssl/ssl.h> header file. */
|
||||
/* #undef HAVE_OPENSSL_SSL_H */
|
||||
#define HAVE_OPENSSL_SSL_H 1
|
||||
|
||||
/* Define to 1 if you have the <openssl/x509.h> header file. */
|
||||
/* #undef HAVE_OPENSSL_X509_H */
|
||||
#define HAVE_OPENSSL_X509_H 1
|
||||
|
||||
/* use O_NONBLOCK for non-blocking sockets */
|
||||
/* #undef HAVE_O_NONBLOCK 1 */
|
||||
|
||||
/* Define to 1 if you have the <pem.h> header file. */
|
||||
/* #undef HAVE_PEM_H */
|
||||
#define HAVE_PEM_H 1
|
||||
|
||||
/* Define to 1 if you have the `perror' function. */
|
||||
#define HAVE_PERROR 1
|
||||
|
||||
/* Define to 1 if you have the `pipe' function. */
|
||||
#define HAVE_PIPE 1
|
||||
|
||||
/* Define to 1 if you have the `poll' function. */
|
||||
/* #undef HAVE_POLL */
|
||||
|
||||
/* If you have a fine poll */
|
||||
/* #undef HAVE_POLL_FINE */
|
||||
|
||||
/* we have a POSIX-style strerror_r() */
|
||||
/* #undef HAVE_POSIX_STRERROR_R */
|
||||
|
||||
/* Define to 1 if you have the <pwd.h> header file. */
|
||||
#define HAVE_PWD_H 1
|
||||
|
||||
/* Define to 1 if you have the `RAND_egd' function. */
|
||||
/* #undef HAVE_RAND_EGD */
|
||||
#define HAVE_RAND_EGD 1
|
||||
|
||||
/* Define to 1 if you have the `RAND_screen' function. */
|
||||
/* #undef HAVE_RAND_SCREEN */
|
||||
|
||||
/* Define to 1 if you have the `RAND_status' function. */
|
||||
/* #undef HAVE_RAND_STATUS */
|
||||
#define HAVE_RAND_STATUS 1
|
||||
|
||||
/* Define to 1 if you have the <rsa.h> header file. */
|
||||
/* #undef HAVE_RSA_H */
|
||||
#define HAVE_RSA_H 1
|
||||
|
||||
/* Define to 1 if you have the `select' function. */
|
||||
#define HAVE_SELECT 1
|
||||
|
||||
/* Define to 1 if you have the <setjmp.h> header file. */
|
||||
#define HAVE_SETJMP_H 1
|
||||
|
||||
/* Define to 1 if you have the `setlocale' function. */
|
||||
#define HAVE_SETLOCALE 1
|
||||
|
||||
/* Define to 1 if you have the `setrlimit' function. */
|
||||
#define HAVE_SETRLIMIT 1
|
||||
|
||||
/* Define to 1 if you have the <sgtty.h> header file. */
|
||||
/* #undef HAVE_SGTTY_H 1 */
|
||||
|
||||
/* Define to 1 if you have the `sigaction' function. */
|
||||
#define HAVE_SIGACTION 1
|
||||
|
||||
/* Define to 1 if you have the `siginterrupt' function. */
|
||||
/* #undef HAVE_SIGINTERRUPT */
|
||||
|
||||
/* Define to 1 if you have the `signal' function. */
|
||||
#define HAVE_SIGNAL 1
|
||||
|
||||
/* If you have sigsetjmp */
|
||||
/* #undef HAVE_SIGSETJMP */
|
||||
|
||||
/* Define to 1 if you have the `socket' function. */
|
||||
#define HAVE_SOCKET 1
|
||||
|
||||
/* use SO_NONBLOCK for non-blocking sockets */
|
||||
/* #undef HAVE_SO_NONBLOCK */
|
||||
|
||||
/* Define this if you have the SPNEGO library fbopenssl */
|
||||
/* #undef HAVE_SPNEGO */
|
||||
|
||||
/* Define to 1 if you have the <ssl.h> header file. */
|
||||
/* #undef HAVE_SSL_H */
|
||||
#define HAVE_SSL_H 1
|
||||
|
||||
/* Define to 1 if you have the <stdint.h> header file. */
|
||||
#define HAVE_STDINT_H 1
|
||||
|
||||
/* Define to 1 if you have the <stdlib.h> header file. */
|
||||
#define HAVE_STDLIB_H 1
|
||||
|
||||
/* Define to 1 if you have the `strcasecmp' function. */
|
||||
#define HAVE_STRCASECMP 1
|
||||
|
||||
/* Define to 1 if you have the `strcmpi' function. */
|
||||
/* #undef HAVE_STRCMPI */
|
||||
|
||||
/* Define to 1 if you have the `strdup' function. */
|
||||
#define HAVE_STRDUP 1
|
||||
|
||||
/* Define to 1 if you have the `strerror_r' function. */
|
||||
#define HAVE_STRERROR_R 1
|
||||
|
||||
/* Define to 1 if you have the `stricmp' function. */
|
||||
/* #undef HAVE_STRICMP */
|
||||
#define HAVE_STRICMP 1
|
||||
|
||||
/* Define to 1 if you have the <strings.h> header file. */
|
||||
#define HAVE_STRINGS_H 1
|
||||
|
||||
/* Define to 1 if you have the <string.h> header file. */
|
||||
#define HAVE_STRING_H 1
|
||||
|
||||
/* Define to 1 if you have the `strlcat' function. */
|
||||
/* #undef HAVE_STRLCAT */
|
||||
|
||||
/* Define to 1 if you have the `strlcpy' function. */
|
||||
/* #undef HAVE_STRLCPY */
|
||||
|
||||
/* Define to 1 if you have the `strstr' function. */
|
||||
#define HAVE_STRSTR 1
|
||||
|
||||
/* Define to 1 if you have the `strtok_r' function. */
|
||||
#define HAVE_STRTOK_R 1
|
||||
|
||||
/* Define to 1 if you have the `strtoll' function. */
|
||||
#define HAVE_STRTOLL 1
|
||||
|
||||
/* if struct sockaddr_storage is defined */
|
||||
/* #undef HAVE_STRUCT_SOCKADDR_STORAGE */
|
||||
|
||||
/* Define to 1 if you have the <sys/filio.h> header file. */
|
||||
#define HAVE_SYS_FILIO_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/ioctl.h> header file. */
|
||||
#define HAVE_SYS_IOCTL_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/param.h> header file. */
|
||||
#define HAVE_SYS_PARAM_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/poll.h> header file. */
|
||||
/* #undef HAVE_SYS_POLL_H */
|
||||
|
||||
/* Define to 1 if you have the <sys/resource.h> header file. */
|
||||
#define HAVE_SYS_RESOURCE_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/select.h> header file. */
|
||||
#define HAVE_SYS_SELECT_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/socket.h> header file. */
|
||||
#define HAVE_SYS_SOCKET_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/sockio.h> header file. */
|
||||
/* #undef HAVE_SYS_SOCKIO_H */
|
||||
#define HAVE_SYS_SOCKIO_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/stat.h> header file. */
|
||||
#define HAVE_SYS_STAT_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/time.h> header file. */
|
||||
#define HAVE_SYS_TIME_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/types.h> header file. */
|
||||
#define HAVE_SYS_TYPES_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/utime.h> header file. */
|
||||
/* #undef HAVE_SYS_UTIME_H */
|
||||
|
||||
/* Define to 1 if you have the <termios.h> header file. */
|
||||
/* #undef HAVE_TERMIOS_H */
|
||||
|
||||
/* Define to 1 if you have the <termio.h> header file. */
|
||||
/* #undef HAVE_TERMIO_H */
|
||||
|
||||
/* Define to 1 if you have the <time.h> header file. */
|
||||
#define HAVE_TIME_H 1
|
||||
|
||||
/* Define to 1 if you have the <tld.h> header file. */
|
||||
/* #undef HAVE_TLD_H */
|
||||
|
||||
/* Define to 1 if you have the `tld_strerror' function. */
|
||||
/* #undef HAVE_TLD_STRERROR */
|
||||
|
||||
/* Define to 1 if you have the `uname' function. */
|
||||
/* #undef HAVE_UNAME */
|
||||
|
||||
/* Define to 1 if you have the <unistd.h> header file. */
|
||||
#define HAVE_UNISTD_H 1
|
||||
|
||||
/* Define to 1 if you have the `utime' function. */
|
||||
#define HAVE_UTIME 1
|
||||
|
||||
/* Define to 1 if you have the <utime.h> header file. */
|
||||
#define HAVE_UTIME_H 1
|
||||
|
||||
/* Define to 1 if you have the <winsock2.h> header file. */
|
||||
/* #undef HAVE_WINSOCK2_H */
|
||||
|
||||
/* Define to 1 if you have the <winsock.h> header file. */
|
||||
/* #undef HAVE_WINSOCK_H */
|
||||
|
||||
/* Define this symbol if your OS supports changing the contents of argv */
|
||||
/* #undef HAVE_WRITABLE_ARGV */
|
||||
|
||||
/* Define to 1 if you have the ws2tcpip.h header file. */
|
||||
/* #undef HAVE_WS2TCPIP_H */
|
||||
|
||||
/* Define to 1 if you have the <x509.h> header file. */
|
||||
/* #undef HAVE_X509_H */
|
||||
|
||||
/* if you have the zlib.h header file */
|
||||
/* #undef HAVE_ZLIB_H */
|
||||
|
||||
/* If you lack a fine basename() prototype */
|
||||
/* #undef NEED_BASENAME_PROTO */
|
||||
|
||||
/* need REENTRANT defined */
|
||||
/* #undef NEED_REENTRANT */
|
||||
|
||||
/* cpu-machine-OS */
|
||||
#define OS "s390x-ibm-tpf"
|
||||
|
||||
/* Name of package */
|
||||
#define PACKAGE "curl"
|
||||
|
||||
/* Define to the address where bug reports for this package should be sent. */
|
||||
#define PACKAGE_BUGREPORT "a suitable curl mailing list => http://curl.haxx.se/mail/"
|
||||
|
||||
/* Define to the full name of this package. */
|
||||
#define PACKAGE_NAME "curl"
|
||||
|
||||
/* Define to the full name and version of this package. */
|
||||
#define PACKAGE_STRING "curl -"
|
||||
|
||||
/* Define to the one symbol short name of this package. */
|
||||
#define PACKAGE_TARNAME "curl"
|
||||
|
||||
/* Define to the version of this package. */
|
||||
#define PACKAGE_VERSION "-"
|
||||
|
||||
/* a suitable file to read random data from */
|
||||
/* #undef RANDOM_FILE */
|
||||
|
||||
/* Define as the return type of signal handlers (`int' or `void'). */
|
||||
#define RETSIGTYPE void
|
||||
|
||||
/* Define to the type of arg 1 for `select'. */
|
||||
#define SELECT_TYPE_ARG1 int
|
||||
|
||||
/* Define to the type of args 2, 3 and 4 for `select'. */
|
||||
#define SELECT_TYPE_ARG234 (fd_set *)
|
||||
|
||||
/* Define to the type of arg 5 for `select'. */
|
||||
#define SELECT_TYPE_ARG5 (struct timeval *)
|
||||
|
||||
/* The size of a `curl_off_t', as computed by sizeof. */
|
||||
#define SIZEOF_CURL_OFF_T 8
|
||||
|
||||
/* The size of a `long', as computed by sizeof. */
|
||||
#define SIZEOF_LONG 8
|
||||
|
||||
/* The size of a `size_t', as computed by sizeof. */
|
||||
#define SIZEOF_SIZE_T 8
|
||||
|
||||
/* The size of a `time_t', as computed by sizeof. */
|
||||
#define SIZEOF_TIME_T 8
|
||||
|
||||
/* Define to 1 if you have the ANSI C header files. */
|
||||
#define STDC_HEADERS 1
|
||||
|
||||
/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
|
||||
#define TIME_WITH_SYS_TIME 1
|
||||
|
||||
/* Define if you want to enable ares support */
|
||||
/* #undef USE_ARES */
|
||||
|
||||
/* if GnuTLS is enabled */
|
||||
/* #undef USE_GNUTLS */
|
||||
|
||||
/* If you want to build curl with the built-in manual */
|
||||
/* #undef USE_MANUAL */
|
||||
|
||||
/* if OpenSSL is in use */
|
||||
/* #undef USE_OPENSSL */
|
||||
|
||||
/* if SSL is enabled */
|
||||
/* #undef USE_SSLEAY */
|
||||
|
||||
/* to enable SSPI support */
|
||||
/* #undef USE_WINDOWS_SSPI */
|
||||
|
||||
/* Version number of package */
|
||||
#define VERSION "not-used"
|
||||
|
||||
/* Define to avoid automatic inclusion of winsock.h */
|
||||
/* #undef WIN32_LEAN_AND_MEAN */
|
||||
|
||||
/* Define to 1 if on AIX 3.
|
||||
System headers sometimes define this.
|
||||
We just want to avoid a redefinition error message. */
|
||||
#ifndef _ALL_SOURCE
|
||||
/* # undef _ALL_SOURCE */
|
||||
#endif
|
||||
|
||||
/* Number of bits in a file offset, on hosts where this is settable. */
|
||||
/* #undef _FILE_OFFSET_BITS */
|
||||
|
||||
/* Define for large files, on AIX-style hosts. */
|
||||
/* #undef _LARGE_FILES */
|
||||
|
||||
/* define this if you need it to compile thread-safe code */
|
||||
/* #undef _THREAD_SAFE */
|
||||
|
||||
/* Define to empty if `const' does not conform to ANSI C. */
|
||||
/* #undef const */
|
||||
|
||||
/* type to use in place of in_addr_t if not defined */
|
||||
/* #undef in_addr_t */
|
||||
|
||||
/* Define to `unsigned' if <sys/types.h> does not define. */
|
||||
/* #undef size_t */
|
||||
|
||||
/* type to use in place of socklen_t if not defined */
|
||||
/* #undef socklen_t */
|
||||
|
||||
/* the signed version of size_t */
|
||||
/* #undef ssize_t */
|
||||
|
||||
#define CURL_DOES_CONVERSIONS
|
||||
#ifndef CURL_ICONV_CODESET_OF_HOST
|
||||
#define CURL_ICONV_CODESET_OF_HOST "IBM-1047"
|
||||
#endif
|
||||
|
||||
/* ---------------------------------------------------------------- */
|
||||
/* HEADER FILES */
|
||||
/* ---------------------------------------------------------------- */
|
||||
|
||||
#include <strings.h> /* for bzero, strcasecmp, and strncasecmp */
|
||||
#include <string.h> /* for strcpy and strlen */
|
||||
#include <stdlib.h> /* for rand and srand */
|
||||
#include <sys/socket.h> /* for select and ioctl*/
|
||||
#include <netdb.h> /* for in_addr_t definition */
|
||||
#include <tpf/sysapi.h> /* for tpf_process_signals */
|
||||
|
||||
#endif /* __LIBCONFIGTPF_H */
|
@@ -37,7 +37,9 @@
|
||||
#define HAVE_IO_H 1
|
||||
|
||||
/* Define if you have the <malloc.h> header file. */
|
||||
#ifndef __SALFORDC__
|
||||
#define HAVE_MALLOC_H 1
|
||||
#endif
|
||||
|
||||
/* Define if you have the <netdb.h> header file. */
|
||||
/* #define HAVE_NETDB_H 1 */
|
||||
@@ -45,6 +47,11 @@
|
||||
/* Define if you have the <netinet/in.h> header file. */
|
||||
/* #define HAVE_NETINET_IN_H 1 */
|
||||
|
||||
/* Define if you have the <process.h> header file. */
|
||||
#ifndef __SALFORDC__
|
||||
#define HAVE_PROCESS_H 1
|
||||
#endif
|
||||
|
||||
/* Define if you have the <sgtty.h> header file. */
|
||||
/* #define HAVE_SGTTY_H 1 */
|
||||
|
||||
@@ -98,11 +105,13 @@
|
||||
/* Define if you have the <winsock.h> header file. */
|
||||
#define HAVE_WINSOCK_H 1
|
||||
|
||||
#ifndef __SALFORDC__
|
||||
/* Define if you have the <winsock2.h> header file. */
|
||||
#define HAVE_WINSOCK2_H 1
|
||||
|
||||
/* Define if you have the <ws2tcpip.h> header file. */
|
||||
#define HAVE_WS2TCPIP_H 1
|
||||
#endif
|
||||
|
||||
/* ---------------------------------------------------------------- */
|
||||
/* OTHER HEADER INFO */
|
||||
@@ -246,8 +255,10 @@
|
||||
#endif
|
||||
|
||||
/* Define SIZEOF_CURL_OFF_T as computed by sizeof(curl_off_t) */
|
||||
/* Borland/PellesC lacks _lseeki64(), so we don't support >2GB files. */
|
||||
#if defined(__BORLANDC__) || defined(__POCC__)
|
||||
/* Borland/PellesC/SalfordC lacks _lseeki64(), so we don't support
|
||||
* >2GB files.
|
||||
*/
|
||||
#if defined(__BORLANDC__) || defined(__POCC__) || defined(__SALFORDC__)
|
||||
#define SIZEOF_CURL_OFF_T 4
|
||||
#else
|
||||
#define SIZEOF_CURL_OFF_T 8
|
||||
@@ -258,7 +269,9 @@
|
||||
/* ---------------------------------------------------------------- */
|
||||
|
||||
/* Define this if you have struct sockaddr_storage */
|
||||
#ifndef __SALFORDC__
|
||||
#define HAVE_STRUCT_SOCKADDR_STORAGE 1
|
||||
#endif
|
||||
|
||||
/* ---------------------------------------------------------------- */
|
||||
/* COMPILER SPECIFIC */
|
||||
|
@@ -54,6 +54,9 @@
|
||||
/* Define if you have the <stdlib.h> header file. */
|
||||
#define HAVE_STDLIB_H 1
|
||||
|
||||
/* Define if you have the <process.h> header file. */
|
||||
#define HAVE_PROCESS_H 1
|
||||
|
||||
/* Define if you have the <sys/param.h> header file. */
|
||||
/* #define HAVE_SYS_PARAM_H 1 */
|
||||
|
||||
|
@@ -36,6 +36,7 @@
|
||||
#define HAVE_NETINET_IN_H 1
|
||||
#define HAVE_NETINET_TCP_H 1
|
||||
#define HAVE_NET_IF_H 1
|
||||
#define HAVE_PROCESS_H 1
|
||||
#define HAVE_PERROR 1
|
||||
#define HAVE_SELECT 1
|
||||
#define HAVE_SETJMP_H 1
|
||||
|
@@ -98,7 +98,9 @@
|
||||
#include "memory.h"
|
||||
#include "select.h"
|
||||
#include "url.h" /* for Curl_safefree() */
|
||||
#include "multiif.h"
|
||||
#include "sockaddr.h" /* required for Curl_sockaddr_storage */
|
||||
#include "inet_ntop.h"
|
||||
|
||||
/* The last #include file should be: */
|
||||
#include "memdebug.h"
|
||||
@@ -112,13 +114,13 @@ singleipconnect(struct connectdata *conn,
|
||||
bool *connected);
|
||||
|
||||
/*
|
||||
* Curl_ourerrno() returns the errno (or equivalent) on this platform to
|
||||
* hide platform specific for the function that calls this.
|
||||
* Curl_sockerrno() returns the *socket-related* errno (or equivalent) on this
|
||||
* platform to hide platform specific for the function that calls this.
|
||||
*/
|
||||
int Curl_ourerrno(void)
|
||||
int Curl_sockerrno(void)
|
||||
{
|
||||
#ifdef WIN32
|
||||
return (int)GetLastError();
|
||||
return (int)WSAGetLastError();
|
||||
#else
|
||||
return errno;
|
||||
#endif
|
||||
@@ -287,6 +289,12 @@ static CURLcode bindlocal(struct connectdata *conn,
|
||||
(void)Curl_wait_for_resolv(conn, &h);
|
||||
|
||||
if(h) {
|
||||
if(in == CURL_INADDR_NONE)
|
||||
/* convert the resolved address, sizeof myhost >= INET_ADDRSTRLEN */
|
||||
Curl_inet_ntop(h->addr->ai_addr->sa_family,
|
||||
&((struct sockaddr_in*)h->addr->ai_addr)->sin_addr,
|
||||
myhost, sizeof myhost);
|
||||
else
|
||||
/* we know data->set.device is shorter than the myhost array */
|
||||
strcpy(myhost, data->set.device);
|
||||
Curl_resolv_unlock(data, h);
|
||||
@@ -322,7 +330,7 @@ static CURLcode bindlocal(struct connectdata *conn,
|
||||
if (setsockopt(sockfd, SOL_SOCKET, SO_BINDTODEVICE,
|
||||
data->set.device, strlen(data->set.device)+1) != 0) {
|
||||
/* printf("Failed to BINDTODEVICE, socket: %d device: %s error: %s\n",
|
||||
sockfd, data->set.device, Curl_strerror(Curl_ourerrno())); */
|
||||
sockfd, data->set.device, Curl_strerror(Curl_sockerrno())); */
|
||||
infof(data, "SO_BINDTODEVICE %s failed\n",
|
||||
data->set.device);
|
||||
/* This is typically "errno 1, error: Operation not permitted" if
|
||||
@@ -374,7 +382,6 @@ static CURLcode bindlocal(struct connectdata *conn,
|
||||
if( bind(sockfd, sock, socksize) >= 0) {
|
||||
/* we succeeded to bind */
|
||||
struct Curl_sockaddr_storage add;
|
||||
unsigned short port = 0;
|
||||
size_t size;
|
||||
|
||||
size = sizeof(add);
|
||||
@@ -383,6 +390,7 @@ static CURLcode bindlocal(struct connectdata *conn,
|
||||
failf(data, "getsockname() failed");
|
||||
return CURLE_HTTP_PORT_FAILED;
|
||||
}
|
||||
/* We re-use/clobber the port variable here below */
|
||||
if(((struct sockaddr *)&add)->sa_family == AF_INET)
|
||||
port = ntohs(((struct sockaddr_in *)&add)->sin_port);
|
||||
#ifdef ENABLE_IPV6
|
||||
@@ -400,7 +408,7 @@ static CURLcode bindlocal(struct connectdata *conn,
|
||||
break;
|
||||
} while(1);
|
||||
|
||||
data->state.os_errno = Curl_ourerrno();
|
||||
data->state.os_errno = Curl_sockerrno();
|
||||
failf(data, "bind failure: %s",
|
||||
Curl_strerror(conn, data->state.os_errno));
|
||||
return CURLE_HTTP_PORT_FAILED;
|
||||
@@ -444,7 +452,7 @@ static bool verifyconnect(curl_socket_t sockfd, int *error)
|
||||
|
||||
if( -1 == getsockopt(sockfd, SOL_SOCKET, SO_ERROR,
|
||||
(void *)&err, &errSize))
|
||||
err = Curl_ourerrno();
|
||||
err = Curl_sockerrno();
|
||||
|
||||
#ifdef _WIN32_WCE
|
||||
/* Always returns this error, bug in CE? */
|
||||
@@ -463,7 +471,7 @@ static bool verifyconnect(curl_socket_t sockfd, int *error)
|
||||
#else
|
||||
(void)sockfd;
|
||||
if (error)
|
||||
*error = Curl_ourerrno();
|
||||
*error = Curl_sockerrno();
|
||||
#endif
|
||||
return rc;
|
||||
}
|
||||
@@ -534,6 +542,7 @@ CURLcode Curl_is_connected(struct connectdata *conn,
|
||||
CURLcode code = CURLE_OK;
|
||||
curl_socket_t sockfd = conn->sock[sockindex];
|
||||
long allow = DEFAULT_CONNECT_TIMEOUT;
|
||||
long allow_total = 0;
|
||||
long has_passed;
|
||||
|
||||
curlassert(sockindex >= FIRSTSOCKET && sockindex <= SECONDARYSOCKET);
|
||||
@@ -546,12 +555,12 @@ CURLcode Curl_is_connected(struct connectdata *conn,
|
||||
/* subtract the most strict timeout of the ones */
|
||||
if(data->set.timeout && data->set.connecttimeout) {
|
||||
if (data->set.timeout < data->set.connecttimeout)
|
||||
allow = data->set.timeout*1000;
|
||||
allow_total = allow = data->set.timeout*1000;
|
||||
else
|
||||
allow = data->set.connecttimeout*1000;
|
||||
}
|
||||
else if(data->set.timeout) {
|
||||
allow = data->set.timeout*1000;
|
||||
allow_total = allow = data->set.timeout*1000;
|
||||
}
|
||||
else if(data->set.connecttimeout) {
|
||||
allow = data->set.connecttimeout*1000;
|
||||
@@ -564,10 +573,13 @@ CURLcode Curl_is_connected(struct connectdata *conn,
|
||||
}
|
||||
if(conn->bits.tcpconnect) {
|
||||
/* we are connected already! */
|
||||
Curl_expire(data, allow_total);
|
||||
*connected = TRUE;
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
Curl_expire(data, allow);
|
||||
|
||||
/* check for connect without timeout as we want to return immediately */
|
||||
rc = waitconnect(sockfd, 0);
|
||||
|
||||
@@ -598,7 +610,7 @@ CURLcode Curl_is_connected(struct connectdata *conn,
|
||||
infof(data, "Connection failed\n");
|
||||
|
||||
if(trynextip(conn, sockindex, connected)) {
|
||||
error = Curl_ourerrno();
|
||||
error = Curl_sockerrno();
|
||||
data->state.os_errno = error;
|
||||
failf(data, "Failed connect to %s:%d; %s",
|
||||
conn->host.name, conn->port, Curl_strerror(conn,error));
|
||||
@@ -630,7 +642,7 @@ static void tcpnodelay(struct connectdata *conn,
|
||||
if(setsockopt(sockfd, proto, TCP_NODELAY, (void *)&onoff,
|
||||
sizeof(onoff)) < 0)
|
||||
infof(data, "Could not set TCP_NODELAY: %s\n",
|
||||
Curl_strerror(conn, Curl_ourerrno()));
|
||||
Curl_strerror(conn, Curl_sockerrno()));
|
||||
else
|
||||
infof(data,"TCP_NODELAY set\n");
|
||||
#else
|
||||
@@ -652,7 +664,7 @@ static void nosigpipe(struct connectdata *conn,
|
||||
if(setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, (void *)&onoff,
|
||||
sizeof(onoff)) < 0)
|
||||
infof(data, "Could not set SO_NOSIGPIPE: %s\n",
|
||||
Curl_strerror(conn, Curl_ourerrno()));
|
||||
Curl_strerror(conn, Curl_sockerrno()));
|
||||
}
|
||||
#else
|
||||
#define nosigpipe(x,y)
|
||||
@@ -705,7 +717,7 @@ singleipconnect(struct connectdata *conn,
|
||||
rc = 0;
|
||||
|
||||
if(-1 == rc) {
|
||||
error = Curl_ourerrno();
|
||||
error = Curl_sockerrno();
|
||||
|
||||
switch (error) {
|
||||
case EINPROGRESS:
|
||||
@@ -818,6 +830,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */
|
||||
return CURLE_OPERATION_TIMEOUTED;
|
||||
}
|
||||
}
|
||||
Curl_expire(data, timeout_ms);
|
||||
|
||||
/* Max time for each address */
|
||||
num_addr = Curl_num_addresses(remotehost->addr);
|
||||
|
@@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2005, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2006, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -37,7 +37,7 @@ CURLcode Curl_connecthost(struct connectdata *conn,
|
||||
bool *connected /* truly connected? */
|
||||
);
|
||||
|
||||
int Curl_ourerrno(void);
|
||||
int Curl_sockerrno(void);
|
||||
|
||||
CURLcode Curl_store_ip_addr(struct connectdata *conn);
|
||||
|
||||
|
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2005, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2006, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -87,7 +87,10 @@ static CURLcode
|
||||
inflate_stream(struct SessionHandle *data,
|
||||
struct Curl_transfer_keeper *k)
|
||||
{
|
||||
int allow_restart = 1;
|
||||
z_stream *z = &k->z; /* zlib state structure */
|
||||
uInt nread = z->avail_in;
|
||||
Bytef *orig_in = z->next_in;
|
||||
int status; /* zlib status */
|
||||
CURLcode result = CURLE_OK; /* Curl_client_write status */
|
||||
char *decomp; /* Put the decompressed data here. */
|
||||
@@ -108,6 +111,7 @@ inflate_stream(struct SessionHandle *data,
|
||||
|
||||
status = inflate(z, Z_SYNC_FLUSH);
|
||||
if (status == Z_OK || status == Z_STREAM_END) {
|
||||
allow_restart = 0;
|
||||
if(DSIZ - z->avail_out) {
|
||||
result = Curl_client_write(data, CLIENTWRITE_BODY, decomp,
|
||||
DSIZ - z->avail_out);
|
||||
@@ -133,6 +137,19 @@ inflate_stream(struct SessionHandle *data,
|
||||
return result;
|
||||
}
|
||||
}
|
||||
else if (allow_restart && status == Z_DATA_ERROR) {
|
||||
/* some servers seem to not generate zlib headers, so this is an attempt
|
||||
to fix and continue anyway */
|
||||
|
||||
inflateReset(z);
|
||||
if (inflateInit2(z, -MAX_WBITS) != Z_OK) {
|
||||
return process_zlib_error(data, z);
|
||||
}
|
||||
z->next_in = orig_in;
|
||||
z->avail_in = nread;
|
||||
allow_restart = 0;
|
||||
continue;
|
||||
}
|
||||
else { /* Error; exit loop, handle below */
|
||||
free(decomp);
|
||||
return exit_zlib(z, &k->zlib_init, process_zlib_error(data, z));
|
||||
|
54
lib/cookie.c
54
lib/cookie.c
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2005, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2006, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -795,6 +795,19 @@ struct Cookie *Curl_cookie_getlist(struct CookieInfo *c,
|
||||
return mainco; /* return the new list */
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Curl_cookie_clearall()
|
||||
*
|
||||
* Clear all existing cookies and reset the counter.
|
||||
*
|
||||
****************************************************************************/
|
||||
void Curl_cookie_clearall(struct CookieInfo *cookies)
|
||||
{
|
||||
Curl_cookie_freelist(cookies->cookies);
|
||||
cookies->cookies = NULL;
|
||||
cookies->numcookies = 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
@@ -817,6 +830,45 @@ void Curl_cookie_freelist(struct Cookie *co)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Curl_cookie_clearsess()
|
||||
*
|
||||
* Free all session cookies in the cookies list.
|
||||
*
|
||||
****************************************************************************/
|
||||
void Curl_cookie_clearsess(struct CookieInfo *cookies)
|
||||
{
|
||||
struct Cookie *first, *curr, *next, *prev = NULL;
|
||||
|
||||
if(!cookies->cookies)
|
||||
return;
|
||||
|
||||
first = curr = prev = cookies->cookies;
|
||||
|
||||
for(; curr; curr = next) {
|
||||
next = curr->next;
|
||||
if(!curr->expires) {
|
||||
if(first == curr)
|
||||
first = next;
|
||||
|
||||
if(prev == curr)
|
||||
prev = next;
|
||||
else
|
||||
prev->next = next;
|
||||
|
||||
free(curr);
|
||||
cookies->numcookies--;
|
||||
}
|
||||
else
|
||||
prev = curr;
|
||||
}
|
||||
|
||||
cookies->cookies = first;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Curl_cookie_cleanup()
|
||||
|
@@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2005, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2006, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -89,6 +89,8 @@ struct CookieInfo *Curl_cookie_init(struct SessionHandle *data,
|
||||
char *, struct CookieInfo *, bool);
|
||||
struct Cookie *Curl_cookie_getlist(struct CookieInfo *, char *, char *, bool);
|
||||
void Curl_cookie_freelist(struct Cookie *);
|
||||
void Curl_cookie_clearall(struct CookieInfo *cookies);
|
||||
void Curl_cookie_clearsess(struct CookieInfo *cookies);
|
||||
void Curl_cookie_cleanup(struct CookieInfo *);
|
||||
int Curl_cookie_output(struct CookieInfo *, char *);
|
||||
|
||||
|
59
lib/dict.c
59
lib/dict.c
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2005, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2006, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -38,8 +38,6 @@
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#if defined(WIN32) && !defined(__GNUC__) || defined(__MINGW32__)
|
||||
#include <time.h>
|
||||
#include <io.h>
|
||||
@@ -85,9 +83,46 @@
|
||||
#define _MPRINTF_REPLACE /* use our functions only */
|
||||
#include <curl/mprintf.h>
|
||||
|
||||
/* The last #include file should be: */
|
||||
#include "memdebug.h"
|
||||
|
||||
static char *unescape_word(struct SessionHandle *data, char *inp)
|
||||
{
|
||||
char *newp;
|
||||
char *dictp;
|
||||
char *ptr;
|
||||
int len;
|
||||
unsigned char byte;
|
||||
int olen=0;
|
||||
|
||||
newp = curl_easy_unescape(data, inp, 0, &len);
|
||||
if(!newp)
|
||||
return NULL;
|
||||
|
||||
dictp = malloc(len*2 + 1); /* add one for terminating zero */
|
||||
if(dictp) {
|
||||
/* According to RFC2229 section 2.2, these letters need to be escaped with
|
||||
\[letter] */
|
||||
for(ptr = newp;
|
||||
(byte = (unsigned char)*ptr);
|
||||
ptr++) {
|
||||
if ((byte <= 32) || (byte == 127) ||
|
||||
(byte == '\'') || (byte == '\"') || (byte == '\\')) {
|
||||
dictp[olen++] = '\\';
|
||||
}
|
||||
dictp[olen++] = byte;
|
||||
}
|
||||
dictp[olen]=0;
|
||||
|
||||
free(newp);
|
||||
}
|
||||
return dictp;
|
||||
}
|
||||
|
||||
CURLcode Curl_dict(struct connectdata *conn, bool *done)
|
||||
{
|
||||
char *word;
|
||||
char *eword;
|
||||
char *ppath;
|
||||
char *database = NULL;
|
||||
char *strategy = NULL;
|
||||
@@ -137,6 +172,10 @@ CURLcode Curl_dict(struct connectdata *conn, bool *done)
|
||||
strategy = (char *)".";
|
||||
}
|
||||
|
||||
eword = unescape_word(data, word);
|
||||
if(!eword)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
result = Curl_sendf(sockfd, conn,
|
||||
"CLIENT " LIBCURL_NAME " " LIBCURL_VERSION "\r\n"
|
||||
"MATCH "
|
||||
@@ -147,8 +186,11 @@ CURLcode Curl_dict(struct connectdata *conn, bool *done)
|
||||
|
||||
database,
|
||||
strategy,
|
||||
word
|
||||
eword
|
||||
);
|
||||
|
||||
free(eword);
|
||||
|
||||
if(result)
|
||||
failf(data, "Failed sending DICT request");
|
||||
else
|
||||
@@ -181,6 +223,10 @@ CURLcode Curl_dict(struct connectdata *conn, bool *done)
|
||||
database = (char *)"!";
|
||||
}
|
||||
|
||||
eword = unescape_word(data, word);
|
||||
if(!eword)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
result = Curl_sendf(sockfd, conn,
|
||||
"CLIENT " LIBCURL_NAME " " LIBCURL_VERSION "\r\n"
|
||||
"DEFINE "
|
||||
@@ -188,7 +234,10 @@ CURLcode Curl_dict(struct connectdata *conn, bool *done)
|
||||
"%s\r\n" /* word */
|
||||
"QUIT\r\n",
|
||||
database,
|
||||
word);
|
||||
eword);
|
||||
|
||||
free(eword);
|
||||
|
||||
if(result)
|
||||
failf(data, "Failed sending DICT request");
|
||||
else
|
||||
|
189
lib/easy.c
189
lib/easy.c
@@ -83,10 +83,22 @@
|
||||
#include "memory.h"
|
||||
#include "progress.h"
|
||||
#include "easyif.h"
|
||||
#include "sendf.h" /* for failf function prototype */
|
||||
|
||||
#define _MPRINTF_REPLACE /* use our functions only */
|
||||
#include <curl/mprintf.h>
|
||||
|
||||
#if defined(CURL_DOES_CONVERSIONS) && defined(HAVE_ICONV)
|
||||
#include <iconv.h>
|
||||
/* set default codesets for iconv */
|
||||
#ifndef CURL_ICONV_CODESET_OF_NETWORK
|
||||
#define CURL_ICONV_CODESET_OF_NETWORK "ISO8859-1"
|
||||
#endif
|
||||
#ifndef CURL_ICONV_CODESET_FOR_UTF8
|
||||
#define CURL_ICONV_CODESET_FOR_UTF8 "UTF-8"
|
||||
#endif
|
||||
#endif /* CURL_DOES_CONVERSIONS && HAVE_ICONV */
|
||||
|
||||
/* The last #include file should be: */
|
||||
#include "memdebug.h"
|
||||
|
||||
@@ -656,3 +668,180 @@ void curl_easy_reset(CURL *curl)
|
||||
data->set.ssl.CAfile = (char *)CURL_CA_BUNDLE;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef CURL_DOES_CONVERSIONS
|
||||
/*
|
||||
* Curl_convert_to_network() is an internal function
|
||||
* for performing ASCII conversions on non-ASCII platforms.
|
||||
*/
|
||||
CURLcode Curl_convert_to_network(struct SessionHandle *data,
|
||||
char *buffer, size_t length)
|
||||
{
|
||||
CURLcode rc;
|
||||
|
||||
if(data->set.convtonetwork) {
|
||||
/* use translation callback */
|
||||
rc = data->set.convtonetwork(buffer, length);
|
||||
if(rc != CURLE_OK) {
|
||||
failf(data,
|
||||
"CURLOPT_CONV_TO_NETWORK_FUNCTION callback returned %i: %s",
|
||||
rc, curl_easy_strerror(rc));
|
||||
}
|
||||
return(rc);
|
||||
} else {
|
||||
#ifdef HAVE_ICONV
|
||||
/* do the translation ourselves */
|
||||
char *input_ptr, *output_ptr;
|
||||
size_t in_bytes, out_bytes, rc;
|
||||
|
||||
/* open an iconv conversion descriptor if necessary */
|
||||
if(data->outbound_cd == (iconv_t)-1) {
|
||||
data->outbound_cd = iconv_open(CURL_ICONV_CODESET_OF_NETWORK,
|
||||
CURL_ICONV_CODESET_OF_HOST);
|
||||
if(data->outbound_cd == (iconv_t)-1) {
|
||||
failf(data,
|
||||
"The iconv_open(\"%s\", \"%s\") call failed with errno %i: %s",
|
||||
CURL_ICONV_CODESET_OF_NETWORK,
|
||||
CURL_ICONV_CODESET_OF_HOST,
|
||||
errno, strerror(errno));
|
||||
return CURLE_CONV_FAILED;
|
||||
}
|
||||
}
|
||||
/* call iconv */
|
||||
input_ptr = output_ptr = buffer;
|
||||
in_bytes = out_bytes = length;
|
||||
rc = iconv(data->outbound_cd, &input_ptr, &in_bytes,
|
||||
&output_ptr, &out_bytes);
|
||||
if ((rc == -1) || (in_bytes != 0)) {
|
||||
failf(data,
|
||||
"The Curl_convert_to_network iconv call failed with errno %i: %s",
|
||||
errno, strerror(errno));
|
||||
return CURLE_CONV_FAILED;
|
||||
}
|
||||
#else
|
||||
failf(data, "CURLOPT_CONV_TO_NETWORK_FUNCTION callback required");
|
||||
return CURLE_CONV_REQD;
|
||||
#endif /* HAVE_ICONV */
|
||||
}
|
||||
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Curl_convert_from_network() is an internal function
|
||||
* for performing ASCII conversions on non-ASCII platforms.
|
||||
*/
|
||||
CURLcode Curl_convert_from_network(struct SessionHandle *data,
|
||||
char *buffer, size_t length)
|
||||
{
|
||||
CURLcode rc;
|
||||
|
||||
if(data->set.convfromnetwork) {
|
||||
/* use translation callback */
|
||||
rc = data->set.convfromnetwork(buffer, length);
|
||||
if(rc != CURLE_OK) {
|
||||
failf(data,
|
||||
"CURLOPT_CONV_FROM_NETWORK_FUNCTION callback returned %i: %s",
|
||||
rc, curl_easy_strerror(rc));
|
||||
}
|
||||
return(rc);
|
||||
} else {
|
||||
#ifdef HAVE_ICONV
|
||||
/* do the translation ourselves */
|
||||
char *input_ptr, *output_ptr;
|
||||
size_t in_bytes, out_bytes, rc;
|
||||
|
||||
/* open an iconv conversion descriptor if necessary */
|
||||
if(data->inbound_cd == (iconv_t)-1) {
|
||||
data->inbound_cd = iconv_open(CURL_ICONV_CODESET_OF_HOST,
|
||||
CURL_ICONV_CODESET_OF_NETWORK);
|
||||
if(data->inbound_cd == (iconv_t)-1) {
|
||||
failf(data,
|
||||
"The iconv_open(\"%s\", \"%s\") call failed with errno %i: %s",
|
||||
CURL_ICONV_CODESET_OF_HOST,
|
||||
CURL_ICONV_CODESET_OF_NETWORK,
|
||||
errno, strerror(errno));
|
||||
return CURLE_CONV_FAILED;
|
||||
}
|
||||
}
|
||||
/* call iconv */
|
||||
input_ptr = output_ptr = buffer;
|
||||
in_bytes = out_bytes = length;
|
||||
rc = iconv(data->inbound_cd, &input_ptr, &in_bytes,
|
||||
&output_ptr, &out_bytes);
|
||||
if ((rc == -1) || (in_bytes != 0)) {
|
||||
failf(data,
|
||||
"The Curl_convert_from_network iconv call failed with errno %i: %s",
|
||||
errno, strerror(errno));
|
||||
return CURLE_CONV_FAILED;
|
||||
}
|
||||
#else
|
||||
failf(data, "CURLOPT_CONV_FROM_NETWORK_FUNCTION callback required");
|
||||
return CURLE_CONV_REQD;
|
||||
#endif /* HAVE_ICONV */
|
||||
}
|
||||
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Curl_convert_from_utf8() is an internal function
|
||||
* for performing UTF-8 conversions on non-ASCII platforms.
|
||||
*/
|
||||
CURLcode Curl_convert_from_utf8(struct SessionHandle *data,
|
||||
char *buffer, size_t length)
|
||||
{
|
||||
CURLcode rc;
|
||||
|
||||
if(data->set.convfromutf8) {
|
||||
/* use translation callback */
|
||||
rc = data->set.convfromutf8(buffer, length);
|
||||
if(rc != CURLE_OK) {
|
||||
failf(data,
|
||||
"CURLOPT_CONV_FROM_UTF8_FUNCTION callback returned %i: %s",
|
||||
rc, curl_easy_strerror(rc));
|
||||
}
|
||||
return(rc);
|
||||
} else {
|
||||
#ifdef HAVE_ICONV
|
||||
/* do the translation ourselves */
|
||||
char *input_ptr, *output_ptr;
|
||||
size_t in_bytes, out_bytes, rc;
|
||||
|
||||
/* open an iconv conversion descriptor if necessary */
|
||||
if(data->utf8_cd == (iconv_t)-1) {
|
||||
data->utf8_cd = iconv_open(CURL_ICONV_CODESET_OF_HOST,
|
||||
CURL_ICONV_CODESET_FOR_UTF8);
|
||||
if(data->utf8_cd == (iconv_t)-1) {
|
||||
failf(data,
|
||||
"The iconv_open(\"%s\", \"%s\") call failed with errno %i: %s",
|
||||
CURL_ICONV_CODESET_OF_HOST,
|
||||
CURL_ICONV_CODESET_FOR_UTF8,
|
||||
errno, strerror(errno));
|
||||
return CURLE_CONV_FAILED;
|
||||
}
|
||||
}
|
||||
/* call iconv */
|
||||
input_ptr = output_ptr = buffer;
|
||||
in_bytes = out_bytes = length;
|
||||
rc = iconv(data->utf8_cd, &input_ptr, &in_bytes, &output_ptr, &out_bytes);
|
||||
if ((rc == -1) || (in_bytes != 0)) {
|
||||
failf(data,
|
||||
"The Curl_convert_from_utf8 iconv call failed with errno %i: %s",
|
||||
errno, strerror(errno));
|
||||
return CURLE_CONV_FAILED;
|
||||
}
|
||||
if (output_ptr < input_ptr) {
|
||||
/* null terminate the now shorter output string */
|
||||
*output_ptr = 0x00;
|
||||
}
|
||||
#else
|
||||
failf(data, "CURLOPT_CONV_FROM_UTF8_FUNCTION callback required");
|
||||
return CURLE_CONV_REQD;
|
||||
#endif /* HAVE_ICONV */
|
||||
}
|
||||
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
#endif /* CURL_DOES_CONVERSIONS */
|
||||
|
@@ -28,4 +28,11 @@
|
||||
*/
|
||||
void Curl_easy_addmulti(struct SessionHandle *data, void *multi);
|
||||
|
||||
CURLcode Curl_convert_to_network(struct SessionHandle *data,
|
||||
char *buffer, size_t length);
|
||||
CURLcode Curl_convert_from_network(struct SessionHandle *data,
|
||||
char *buffer, size_t length);
|
||||
CURLcode Curl_convert_from_utf8(struct SessionHandle *data,
|
||||
char *buffer, size_t length);
|
||||
|
||||
#endif /* __EASYIF_H */
|
||||
|
54
lib/escape.c
54
lib/escape.c
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2006, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -32,6 +32,9 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "memory.h"
|
||||
/* urldata.h and easyif.h are included for Curl_convert_... prototypes */
|
||||
#include "urldata.h"
|
||||
#include "easyif.h"
|
||||
|
||||
#define _MPRINTF_REPLACE /* use our functions only */
|
||||
#include <curl/mprintf.h>
|
||||
@@ -39,7 +42,19 @@
|
||||
/* The last #include file should be: */
|
||||
#include "memdebug.h"
|
||||
|
||||
/* for ABI-compatibility with previous versions */
|
||||
char *curl_escape(const char *string, int inlength)
|
||||
{
|
||||
return curl_easy_escape(NULL, string, inlength);
|
||||
}
|
||||
|
||||
/* for ABI-compatibility with previous versions */
|
||||
char *curl_unescape(const char *string, int length)
|
||||
{
|
||||
return curl_easy_unescape(NULL, string, length, NULL);
|
||||
}
|
||||
|
||||
char *curl_easy_escape(CURL *handle, const char *string, int inlength)
|
||||
{
|
||||
size_t alloc = (inlength?(size_t)inlength:strlen(string))+1;
|
||||
char *ns;
|
||||
@@ -49,6 +64,10 @@ char *curl_escape(const char *string, int inlength)
|
||||
int strindex=0;
|
||||
size_t length;
|
||||
|
||||
#ifndef CURL_DOES_CONVERSIONS
|
||||
/* avoid compiler warnings */
|
||||
(void)handle;
|
||||
#endif
|
||||
ns = malloc(alloc);
|
||||
if(!ns)
|
||||
return NULL;
|
||||
@@ -72,6 +91,17 @@ char *curl_escape(const char *string, int inlength)
|
||||
ns = testing_ptr;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CURL_DOES_CONVERSIONS
|
||||
/* escape sequences are always in ASCII so convert them on non-ASCII hosts */
|
||||
if (!handle ||
|
||||
(Curl_convert_to_network(handle, &in, 1) != CURLE_OK)) {
|
||||
/* Curl_convert_to_network calls failf if unsuccessful */
|
||||
free(ns);
|
||||
return NULL;
|
||||
}
|
||||
#endif /* CURL_DOES_CONVERSIONS */
|
||||
|
||||
snprintf(&ns[strindex], 4, "%%%02X", in);
|
||||
|
||||
strindex+=3;
|
||||
@@ -90,7 +120,8 @@ char *curl_escape(const char *string, int inlength)
|
||||
(in >= 'A' && in <= 'F') || \
|
||||
(in >= '0' && in <= '9'))
|
||||
|
||||
char *curl_unescape(const char *string, int length)
|
||||
char *curl_easy_unescape(CURL *handle, const char *string, int length,
|
||||
int *olen)
|
||||
{
|
||||
int alloc = (length?length:(int)strlen(string))+1;
|
||||
char *ns = malloc(alloc);
|
||||
@@ -98,6 +129,10 @@ char *curl_unescape(const char *string, int length)
|
||||
int strindex=0;
|
||||
long hex;
|
||||
|
||||
#ifndef CURL_DOES_CONVERSIONS
|
||||
/* avoid compiler warnings */
|
||||
(void)handle;
|
||||
#endif
|
||||
if( !ns )
|
||||
return NULL;
|
||||
|
||||
@@ -114,6 +149,17 @@ char *curl_unescape(const char *string, int length)
|
||||
hex = strtol(hexstr, &ptr, 16);
|
||||
|
||||
in = (unsigned char)hex; /* this long is never bigger than 255 anyway */
|
||||
|
||||
#ifdef CURL_DOES_CONVERSIONS
|
||||
/* escape sequences are always in ASCII so convert them on non-ASCII hosts */
|
||||
if (!handle ||
|
||||
(Curl_convert_from_network(handle, &in, 1) != CURLE_OK)) {
|
||||
/* Curl_convert_from_network calls failf if unsuccessful */
|
||||
free(ns);
|
||||
return NULL;
|
||||
}
|
||||
#endif /* CURL_DOES_CONVERSIONS */
|
||||
|
||||
string+=2;
|
||||
alloc-=2;
|
||||
}
|
||||
@@ -122,6 +168,10 @@ char *curl_unescape(const char *string, int length)
|
||||
string++;
|
||||
}
|
||||
ns[strindex]=0; /* terminate it */
|
||||
|
||||
if(olen)
|
||||
/* store output size */
|
||||
*olen = strindex;
|
||||
return ns;
|
||||
}
|
||||
|
||||
|
@@ -8,7 +8,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2005, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2006, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -26,7 +26,5 @@
|
||||
/* Escape and unescape URL encoding in strings. The functions return a new
|
||||
* allocated string or NULL if an error occurred. */
|
||||
|
||||
char *curl_escape(const char *string, int length);
|
||||
char *curl_unescape(const char *string, int length);
|
||||
|
||||
#endif
|
||||
|
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2005, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2006, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -37,8 +37,6 @@
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#if defined(WIN32) && !defined(__GNUC__) || defined(__MINGW32__)
|
||||
#include <time.h>
|
||||
#include <io.h>
|
||||
@@ -102,7 +100,7 @@
|
||||
*/
|
||||
CURLcode Curl_file_connect(struct connectdata *conn)
|
||||
{
|
||||
char *real_path = curl_unescape(conn->path, 0);
|
||||
char *real_path = curl_easy_unescape(conn->data, conn->path, 0, NULL);
|
||||
struct FILEPROTO *file;
|
||||
int fd;
|
||||
#if defined(WIN32) || defined(MSDOS) || defined(__EMX__)
|
||||
|
@@ -1279,7 +1279,7 @@ static size_t readfromfile(struct Form *form, char *buffer, size_t size)
|
||||
/* this file hasn't yet been opened */
|
||||
form->fp = fopen(form->data->line, "rb"); /* b is for binary */
|
||||
if(!form->fp)
|
||||
return -1; /* failure */
|
||||
return (size_t)-1; /* failure */
|
||||
}
|
||||
nread = fread(buffer, 1, size, form->fp);
|
||||
|
||||
|
206
lib/ftp.c
206
lib/ftp.c
@@ -29,7 +29,6 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
@@ -60,10 +59,6 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(WIN32) && defined(__GNUC__) || defined(__MINGW32__)
|
||||
#include <errno.h>
|
||||
#endif
|
||||
|
||||
#if (defined(NETWARE) && defined(__NOVELL_LIBC__))
|
||||
#undef in_addr_t
|
||||
#define in_addr_t unsigned long
|
||||
@@ -72,6 +67,7 @@
|
||||
#include <curl/curl.h>
|
||||
#include "urldata.h"
|
||||
#include "sendf.h"
|
||||
#include "easyif.h" /* for Curl_convert_... prototypes */
|
||||
|
||||
#include "if2ip.h"
|
||||
#include "hostip.h"
|
||||
@@ -95,6 +91,7 @@
|
||||
#include "select.h"
|
||||
#include "parsedate.h" /* for the week day and month names */
|
||||
#include "sockaddr.h" /* required for Curl_sockaddr_storage */
|
||||
#include "multiif.h"
|
||||
|
||||
#if defined(HAVE_INET_NTOA_R) && !defined(HAVE_INET_NTOA_R_DECL)
|
||||
#include "inet_ntoa_r.h"
|
||||
@@ -159,12 +156,15 @@ static void freedirs(struct FTP *ftp)
|
||||
}
|
||||
}
|
||||
|
||||
/* Returns non-zero iff the given string contains CR (0x0D) or LF (0x0A), which
|
||||
are not allowed within RFC 959 <string>.
|
||||
/* Returns non-zero if the given string contains CR (\r) or LF (\n),
|
||||
which are not allowed within RFC 959 <string>.
|
||||
Note: The input string is in the client's encoding which might
|
||||
not be ASCII, so escape sequences \r & \n must be used instead
|
||||
of hex values 0x0d & 0x0a.
|
||||
*/
|
||||
static bool isBadFtpString(const char *string)
|
||||
{
|
||||
return strchr(string, 0x0D) != NULL || strchr(string, 0x0A) != NULL;
|
||||
return strchr(string, '\r') != NULL || strchr(string, '\n') != NULL;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
@@ -295,6 +295,14 @@ static CURLcode ftp_readresp(curl_socket_t sockfd,
|
||||
/* EWOULDBLOCK */
|
||||
return CURLE_OK; /* return */
|
||||
|
||||
#ifdef CURL_DOES_CONVERSIONS
|
||||
if((res == CURLE_OK) && (gotbytes > 0)) {
|
||||
/* convert from the network encoding */
|
||||
result = res = Curl_convert_from_network(data, ptr, gotbytes);
|
||||
/* Curl_convert_from_network calls failf if unsuccessful */
|
||||
}
|
||||
#endif /* CURL_DOES_CONVERSIONS */
|
||||
|
||||
if(CURLE_OK != res)
|
||||
keepon = FALSE;
|
||||
}
|
||||
@@ -479,7 +487,8 @@ CURLcode Curl_GetFTPResponse(ssize_t *nreadp, /* return number of bytes read */
|
||||
switch (Curl_select(sockfd, CURL_SOCKET_BAD, interval_ms)) {
|
||||
case -1: /* select() error, stop reading */
|
||||
result = CURLE_RECV_ERROR;
|
||||
failf(data, "FTP response aborted due to select() error: %d", errno);
|
||||
failf(data, "FTP response aborted due to select() error: %d",
|
||||
Curl_sockerrno());
|
||||
break;
|
||||
case 0: /* timeout */
|
||||
if(Curl_pgrsUpdate(conn))
|
||||
@@ -518,6 +527,14 @@ CURLcode Curl_GetFTPResponse(ssize_t *nreadp, /* return number of bytes read */
|
||||
/* EWOULDBLOCK */
|
||||
continue; /* go looping again */
|
||||
|
||||
#ifdef CURL_DOES_CONVERSIONS
|
||||
if((res == CURLE_OK) && (gotbytes > 0)) {
|
||||
/* convert from the network encoding */
|
||||
result = res = Curl_convert_from_network(data, ptr, gotbytes);
|
||||
/* Curl_convert_from_network calls failf if unsuccessful */
|
||||
}
|
||||
#endif /* CURL_DOES_CONVERSIONS */
|
||||
|
||||
if(CURLE_OK != res)
|
||||
keepon = FALSE;
|
||||
}
|
||||
@@ -698,27 +715,24 @@ static CURLcode ftp_state_pwd(struct connectdata *conn)
|
||||
}
|
||||
|
||||
/* For the FTP "protocol connect" and "doing" phases only */
|
||||
CURLcode Curl_ftp_fdset(struct connectdata *conn,
|
||||
fd_set *read_fd_set,
|
||||
fd_set *write_fd_set,
|
||||
int *max_fdp)
|
||||
int Curl_ftp_getsock(struct connectdata *conn,
|
||||
curl_socket_t *socks,
|
||||
int numsocks)
|
||||
{
|
||||
struct FTP *ftp = conn->proto.ftp;
|
||||
curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
|
||||
|
||||
if(!numsocks)
|
||||
return GETSOCK_BLANK;
|
||||
|
||||
socks[0] = conn->sock[FIRSTSOCKET];
|
||||
|
||||
if(ftp->sendleft) {
|
||||
/* write mode */
|
||||
FD_SET(sockfd, write_fd_set);
|
||||
return GETSOCK_WRITESOCK(0);
|
||||
}
|
||||
else {
|
||||
|
||||
/* read mode */
|
||||
FD_SET(sockfd, read_fd_set);
|
||||
}
|
||||
|
||||
if((int)sockfd > *max_fdp)
|
||||
*max_fdp = (int)sockfd;
|
||||
|
||||
return CURLE_OK;
|
||||
return GETSOCK_READSOCK(0);
|
||||
}
|
||||
|
||||
/* This is called after the FTP_QUOTE state is passed.
|
||||
@@ -853,7 +867,7 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
|
||||
|
||||
portsock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
|
||||
if (portsock == CURL_SOCKET_BAD) {
|
||||
error = Curl_ourerrno();
|
||||
error = Curl_sockerrno();
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
@@ -885,7 +899,7 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
|
||||
((struct sockaddr_in6 *)sa)->sin6_port =0;
|
||||
|
||||
if(bind(portsock, (struct sockaddr *)sa, sslen) < 0) {
|
||||
failf(data, "bind failed: %s", Curl_strerror(conn, Curl_ourerrno()));
|
||||
failf(data, "bind failed: %s", Curl_strerror(conn, Curl_sockerrno()));
|
||||
sclose(portsock);
|
||||
return CURLE_FTP_PORT_FAILED;
|
||||
}
|
||||
@@ -896,14 +910,14 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
|
||||
sslen = sizeof(ss);
|
||||
if(getsockname(portsock, (struct sockaddr *)sa, &sslen)<0) {
|
||||
failf(data, "getsockname() failed: %s",
|
||||
Curl_strerror(conn, Curl_ourerrno()) );
|
||||
Curl_strerror(conn, Curl_sockerrno()) );
|
||||
return CURLE_FTP_PORT_FAILED;
|
||||
}
|
||||
|
||||
/* step 4, listen on the socket */
|
||||
|
||||
if (listen(portsock, 1) < 0) {
|
||||
error = Curl_ourerrno();
|
||||
error = Curl_sockerrno();
|
||||
sclose(portsock);
|
||||
failf(data, "socket failure: %s", Curl_strerror(conn, error));
|
||||
return CURLE_FTP_PORT_FAILED;
|
||||
@@ -1309,6 +1323,8 @@ static CURLcode ftp_state_post_mdtm(struct connectdata *conn)
|
||||
NBFTPSENDF(conn, "TYPE %c",
|
||||
data->set.ftp_ascii?'A':'I');
|
||||
state(conn, FTP_TYPE);
|
||||
/* keep track of our current transfer type */
|
||||
data->ftp_in_ascii_mode = data->set.ftp_ascii;
|
||||
}
|
||||
else
|
||||
result = ftp_state_post_type(conn);
|
||||
@@ -2430,8 +2446,14 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
|
||||
result = Curl_nbftpsendf(conn, "AUTH %s", ftpauth[ftp->count1]);
|
||||
/* remain in this same state */
|
||||
}
|
||||
else {
|
||||
if(data->set.ftp_ssl > CURLFTPSSL_TRY)
|
||||
/* we failed and CURLFTPSSL_CONTROL or CURLFTPSSL_ALL is set */
|
||||
result = CURLE_FTP_SSL_FAILED;
|
||||
else
|
||||
/* ignore the failure and continue */
|
||||
result = ftp_state_user(conn);
|
||||
}
|
||||
|
||||
if(result)
|
||||
return result;
|
||||
@@ -2524,6 +2546,8 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
|
||||
}
|
||||
ftp->entrypath =dir; /* remember this */
|
||||
infof(data, "Entry path is '%s'\n", ftp->entrypath);
|
||||
/* also save it where getinfo can access it: */
|
||||
data->state.most_recent_ftp_entrypath = ftp->entrypath;
|
||||
}
|
||||
else {
|
||||
/* couldn't get the path */
|
||||
@@ -2863,7 +2887,8 @@ CURLcode Curl_ftp_done(struct connectdata *conn, CURLcode status)
|
||||
if(ftp->prevpath)
|
||||
free(ftp->prevpath);
|
||||
|
||||
path = curl_unescape(conn->path, 0); /* get the "raw" path */
|
||||
/* get the "raw" path */
|
||||
path = curl_easy_unescape(conn->data, conn->path, 0, NULL);
|
||||
if(!path)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
@@ -2883,42 +2908,6 @@ CURLcode Curl_ftp_done(struct connectdata *conn, CURLcode status)
|
||||
/* free the dir tree and file parts */
|
||||
freedirs(ftp);
|
||||
|
||||
ftp->ctl_valid = FALSE;
|
||||
|
||||
if(data->set.upload) {
|
||||
if((-1 != data->set.infilesize) &&
|
||||
(data->set.infilesize != *ftp->bytecountp) &&
|
||||
!data->set.crlf &&
|
||||
!ftp->no_transfer) {
|
||||
failf(data, "Uploaded unaligned file size (%" FORMAT_OFF_T
|
||||
" out of %" FORMAT_OFF_T " bytes)",
|
||||
*ftp->bytecountp, data->set.infilesize);
|
||||
conn->bits.close = TRUE; /* close this connection since we don't
|
||||
know what state this error leaves us in */
|
||||
return CURLE_PARTIAL_FILE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if((-1 != conn->size) && (conn->size != *ftp->bytecountp) &&
|
||||
(conn->maxdownload != *ftp->bytecountp)) {
|
||||
failf(data, "Received only partial file: %" FORMAT_OFF_T " bytes",
|
||||
*ftp->bytecountp);
|
||||
conn->bits.close = TRUE; /* close this connection since we don't
|
||||
know what state this error leaves us in */
|
||||
return CURLE_PARTIAL_FILE;
|
||||
}
|
||||
else if(!ftp->dont_check &&
|
||||
!*ftp->bytecountp &&
|
||||
(conn->size>0)) {
|
||||
/* We consider this an error, but there's no true FTP error received
|
||||
why we need to continue to "read out" the server response too.
|
||||
We don't want to leave a "waiting" server reply if we'll get told
|
||||
to make a second request on this same connection! */
|
||||
failf(data, "No data was received!");
|
||||
result = CURLE_FTP_COULDNT_RETR_FILE;
|
||||
}
|
||||
}
|
||||
|
||||
switch(status) {
|
||||
case CURLE_BAD_DOWNLOAD_RESUME:
|
||||
case CURLE_FTP_WEIRD_PASV_REPLY:
|
||||
@@ -2952,19 +2941,23 @@ CURLcode Curl_ftp_done(struct connectdata *conn, CURLcode status)
|
||||
conn->sock[SECONDARYSOCKET] = CURL_SOCKET_BAD;
|
||||
|
||||
if(!ftp->no_transfer && !status) {
|
||||
/* Let's see what the server says about the transfer we just performed,
|
||||
/*
|
||||
* Let's see what the server says about the transfer we just performed,
|
||||
* but lower the timeout as sometimes this connection has died while the
|
||||
* data has been transfered. This happens when doing through NATs etc that
|
||||
* abandon old silent connections.
|
||||
*/
|
||||
long old_time = ftp->response_time;
|
||||
|
||||
ftp->response_time = 60; /* give it only a minute for now */
|
||||
|
||||
result = Curl_GetFTPResponse(&nread, conn, &ftpcode);
|
||||
|
||||
ftp->response_time = 3600; /* set this back to one hour waits */
|
||||
ftp->response_time = old_time; /* set this back to previous value */
|
||||
|
||||
if(!nread && (CURLE_OPERATION_TIMEDOUT == result)) {
|
||||
failf(data, "control connection looks dead");
|
||||
ftp->ctl_valid = FALSE; /* mark control connection as bad */
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -2975,11 +2968,48 @@ CURLcode Curl_ftp_done(struct connectdata *conn, CURLcode status)
|
||||
/* 226 Transfer complete, 250 Requested file action okay, completed. */
|
||||
if((ftpcode != 226) && (ftpcode != 250)) {
|
||||
failf(data, "server did not report OK, got %d", ftpcode);
|
||||
return CURLE_FTP_WRITE_ERROR;
|
||||
result = CURLE_PARTIAL_FILE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(result)
|
||||
/* the response code from the transfer showed an error already so no
|
||||
use checking further */
|
||||
;
|
||||
else if(data->set.upload) {
|
||||
if((-1 != data->set.infilesize) &&
|
||||
(data->set.infilesize != *ftp->bytecountp) &&
|
||||
!data->set.crlf &&
|
||||
!ftp->no_transfer) {
|
||||
failf(data, "Uploaded unaligned file size (%" FORMAT_OFF_T
|
||||
" out of %" FORMAT_OFF_T " bytes)",
|
||||
*ftp->bytecountp, data->set.infilesize);
|
||||
result = CURLE_PARTIAL_FILE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if((-1 != conn->size) && (conn->size != *ftp->bytecountp) &&
|
||||
#ifdef CURL_DO_LINEEND_CONV
|
||||
/* Most FTP servers don't adjust their file SIZE response for CRLFs, so
|
||||
* we'll check to see if the discrepancy can be explained by the number
|
||||
* of CRLFs we've changed to LFs.
|
||||
*/
|
||||
((conn->size + data->state.crlf_conversions) != *ftp->bytecountp) &&
|
||||
#endif /* CURL_DO_LINEEND_CONV */
|
||||
(conn->maxdownload != *ftp->bytecountp)) {
|
||||
failf(data, "Received only partial file: %" FORMAT_OFF_T " bytes",
|
||||
*ftp->bytecountp);
|
||||
result = CURLE_PARTIAL_FILE;
|
||||
}
|
||||
else if(!ftp->dont_check &&
|
||||
!*ftp->bytecountp &&
|
||||
(conn->size>0)) {
|
||||
failf(data, "No data was received!");
|
||||
result = CURLE_FTP_COULDNT_RETR_FILE;
|
||||
}
|
||||
}
|
||||
|
||||
/* clear these for next connection */
|
||||
ftp->no_transfer = FALSE;
|
||||
ftp->dont_check = FALSE;
|
||||
@@ -3059,6 +3089,8 @@ static CURLcode ftp_transfertype(struct connectdata *conn,
|
||||
ascii?"ASCII":"binary");
|
||||
return ascii? CURLE_FTP_COULDNT_SET_ASCII:CURLE_FTP_COULDNT_SET_BINARY;
|
||||
}
|
||||
/* keep track of our current transfer type */
|
||||
data->ftp_in_ascii_mode = ascii;
|
||||
|
||||
return CURLE_OK;
|
||||
}
|
||||
@@ -3160,6 +3192,8 @@ CURLcode Curl_ftp_nextconnect(struct connectdata *conn)
|
||||
if(data->set.upload) {
|
||||
NBFTPSENDF(conn, "TYPE %c", data->set.ftp_ascii?'A':'I');
|
||||
state(conn, FTP_STOR_TYPE);
|
||||
/* keep track of our current transfer type */
|
||||
data->ftp_in_ascii_mode = data->set.ftp_ascii;
|
||||
}
|
||||
else {
|
||||
/* download */
|
||||
@@ -3174,10 +3208,14 @@ CURLcode Curl_ftp_nextconnect(struct connectdata *conn)
|
||||
need to set ASCII transfer mode. */
|
||||
NBFTPSENDF(conn, "TYPE A", NULL);
|
||||
state(conn, FTP_LIST_TYPE);
|
||||
/* keep track of our current transfer type */
|
||||
data->ftp_in_ascii_mode = 1;
|
||||
}
|
||||
else {
|
||||
NBFTPSENDF(conn, "TYPE %c", data->set.ftp_ascii?'A':'I');
|
||||
state(conn, FTP_RETR_TYPE);
|
||||
/* keep track of our current transfer type */
|
||||
data->ftp_in_ascii_mode = data->set.ftp_ascii;
|
||||
}
|
||||
}
|
||||
result = ftp_easy_statemach(conn);
|
||||
@@ -3300,6 +3338,14 @@ CURLcode Curl_nbftpsendf(struct connectdata *conn,
|
||||
|
||||
ftp_respinit(conn);
|
||||
|
||||
#ifdef CURL_DOES_CONVERSIONS
|
||||
res = Curl_convert_to_network(data, s, write_len);
|
||||
/* Curl_convert_to_network calls failf if unsuccessful */
|
||||
if(res != CURLE_OK) {
|
||||
return res;
|
||||
}
|
||||
#endif /* CURL_DOES_CONVERSIONS */
|
||||
|
||||
res = Curl_write(conn, conn->sock[FIRSTSOCKET], sptr, write_len,
|
||||
&bytes_written);
|
||||
|
||||
@@ -3349,6 +3395,14 @@ CURLcode Curl_ftpsendf(struct connectdata *conn,
|
||||
bytes_written=0;
|
||||
write_len = strlen(s);
|
||||
|
||||
#ifdef CURL_DOES_CONVERSIONS
|
||||
res = Curl_convert_to_network(conn->data, s, write_len);
|
||||
/* Curl_convert_to_network calls failf if unsuccessful */
|
||||
if(res != CURLE_OK) {
|
||||
return(res);
|
||||
}
|
||||
#endif /* CURL_DOES_CONVERSIONS */
|
||||
|
||||
while(1) {
|
||||
res = Curl_write(conn, conn->sock[FIRSTSOCKET], sptr, write_len,
|
||||
&bytes_written);
|
||||
@@ -3417,8 +3471,12 @@ CURLcode Curl_ftp_disconnect(struct connectdata *conn)
|
||||
if(ftp) {
|
||||
(void)ftp_quit(conn); /* ignore errors on the QUIT */
|
||||
|
||||
if(ftp->entrypath)
|
||||
if(ftp->entrypath) {
|
||||
struct SessionHandle *data = conn->data;
|
||||
data->state.most_recent_ftp_entrypath = NULL;
|
||||
free(ftp->entrypath);
|
||||
ftp->entrypath = NULL;
|
||||
}
|
||||
if(ftp->cache) {
|
||||
free(ftp->cache);
|
||||
ftp->cache = NULL;
|
||||
@@ -3735,7 +3793,8 @@ CURLcode ftp_parse_url_path(struct connectdata *conn)
|
||||
if(!ftp->dirs)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
ftp->dirs[0] = curl_unescape(cur_pos, (int)(slash_pos-cur_pos));
|
||||
ftp->dirs[0] = curl_easy_unescape(conn->data, cur_pos,
|
||||
(int)(slash_pos-cur_pos), NULL);
|
||||
if(!ftp->dirs[0]) {
|
||||
free(ftp->dirs);
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
@@ -3765,8 +3824,9 @@ CURLcode ftp_parse_url_path(struct connectdata *conn)
|
||||
requires a parameter and a non-existant parameter a) doesn't work on
|
||||
many servers and b) has no effect on the others. */
|
||||
int len = (int)(slash_pos - cur_pos + absolute_dir);
|
||||
ftp->dirs[ftp->dirdepth] = curl_unescape(cur_pos - absolute_dir, len);
|
||||
|
||||
ftp->dirs[ftp->dirdepth] = curl_easy_unescape(conn->data,
|
||||
cur_pos - absolute_dir,
|
||||
len, NULL);
|
||||
if (!ftp->dirs[ftp->dirdepth]) { /* run out of memory ... */
|
||||
failf(data, "no memory");
|
||||
freedirs(ftp);
|
||||
@@ -3803,7 +3863,7 @@ CURLcode ftp_parse_url_path(struct connectdata *conn)
|
||||
}
|
||||
|
||||
if(*ftp->file) {
|
||||
ftp->file = curl_unescape(ftp->file, 0);
|
||||
ftp->file = curl_easy_unescape(conn->data, ftp->file, 0, NULL);
|
||||
if(NULL == ftp->file) {
|
||||
freedirs(ftp);
|
||||
failf(data, "no memory");
|
||||
@@ -3830,7 +3890,7 @@ CURLcode ftp_parse_url_path(struct connectdata *conn)
|
||||
if(ftp->prevpath) {
|
||||
/* prevpath is "raw" so we convert the input path before we compare the
|
||||
strings */
|
||||
char *path = curl_unescape(conn->path, 0);
|
||||
char *path = curl_easy_unescape(conn->data, conn->path, 0, NULL);
|
||||
if(!path)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
|
@@ -34,10 +34,9 @@ CURLcode Curl_GetFTPResponse(ssize_t *nread, struct connectdata *conn,
|
||||
int *ftpcode);
|
||||
CURLcode Curl_ftp_nextconnect(struct connectdata *conn);
|
||||
CURLcode Curl_ftp_multi_statemach(struct connectdata *conn, bool *done);
|
||||
CURLcode Curl_ftp_fdset(struct connectdata *conn,
|
||||
fd_set *read_fd_set,
|
||||
fd_set *write_fd_set,
|
||||
int *max_fdp);
|
||||
int Curl_ftp_getsock(struct connectdata *conn,
|
||||
curl_socket_t *socks,
|
||||
int numsocks);
|
||||
CURLcode Curl_ftp_doing(struct connectdata *conn,
|
||||
bool *dophase_done);
|
||||
#endif /* CURL_DISABLE_FTP */
|
||||
|
@@ -75,6 +75,8 @@ CURLcode Curl_getinfo(struct SessionHandle *data, CURLINFO info, ...)
|
||||
double *param_doublep=NULL;
|
||||
char **param_charp=NULL;
|
||||
struct curl_slist **param_slistp=NULL;
|
||||
char buf;
|
||||
|
||||
va_start(arg, info);
|
||||
|
||||
switch(info&CURLINFO_TYPEMASK) {
|
||||
@@ -187,11 +189,33 @@ CURLcode Curl_getinfo(struct SessionHandle *data, CURLINFO info, ...)
|
||||
case CURLINFO_COOKIELIST:
|
||||
*param_slistp = Curl_cookie_list(data);
|
||||
break;
|
||||
case CURLINFO_FTP_ENTRY_PATH:
|
||||
/* Return the entrypath string from the most recent connection.
|
||||
This pointer was copied from the connectdata structure by FTP.
|
||||
The actual string may be free()ed by subsequent libcurl calls so
|
||||
it must be copied to a safer area before the next libcurl call.
|
||||
Callers must never free it themselves. */
|
||||
*param_charp = data->state.most_recent_ftp_entrypath;
|
||||
break;
|
||||
case CURLINFO_LASTSOCKET:
|
||||
if((data->state.lastconnect != -1) &&
|
||||
(data->state.connects[data->state.lastconnect] != NULL))
|
||||
(data->state.connects[data->state.lastconnect] != NULL)) {
|
||||
*param_longp = data->state.connects[data->state.lastconnect]->
|
||||
sock[FIRSTSOCKET];
|
||||
/* we have a socket connected, let's determine if the server shut down */
|
||||
/* determine if ssl */
|
||||
if(data->state.connects[data->state.lastconnect]->ssl[FIRSTSOCKET].use) {
|
||||
/* use the SSL context */
|
||||
if (!Curl_ssl_check_cxn(data->state.connects[data->state.lastconnect]))
|
||||
*param_longp = -1; /* FIN received */
|
||||
}
|
||||
else {
|
||||
/* use the socket */
|
||||
if(recv((int)data->state.connects[data->state.lastconnect]->
|
||||
sock[FIRSTSOCKET], (void*)&buf, 1, MSG_PEEK) == 0)
|
||||
*param_longp = -1; /* FIN received */
|
||||
}
|
||||
}
|
||||
else
|
||||
*param_longp = -1;
|
||||
break;
|
||||
|
@@ -159,7 +159,7 @@ static CURLcode handshake(struct connectdata *conn,
|
||||
}
|
||||
else {
|
||||
/* anything that gets here is fatally bad */
|
||||
failf(data, "select on SSL socket, errno: %d", Curl_ourerrno());
|
||||
failf(data, "select on SSL socket, errno: %d", Curl_sockerrno());
|
||||
return CURLE_SSL_CONNECT_ERROR;
|
||||
}
|
||||
}
|
||||
@@ -458,6 +458,12 @@ int Curl_gtls_send(struct connectdata *conn,
|
||||
int rc;
|
||||
rc = gnutls_record_send(conn->ssl[sockindex].session, mem, len);
|
||||
|
||||
if(rc < 0 ) {
|
||||
if(rc == GNUTLS_E_AGAIN)
|
||||
return 0; /* EWOULDBLOCK equivalent */
|
||||
rc = -1; /* generic error code for send failure */
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
26
lib/hash.c
26
lib/hash.c
@@ -124,8 +124,11 @@ mk_hash_element(char *key, size_t key_len, const void *p)
|
||||
(struct curl_hash_element *) malloc(sizeof(struct curl_hash_element));
|
||||
|
||||
if(he) {
|
||||
char *dup = strdup(key);
|
||||
char *dup = malloc(key_len);
|
||||
if(dup) {
|
||||
/* copy the key */
|
||||
memcpy(dup, key, key_len);
|
||||
|
||||
he->key = dup;
|
||||
he->key_len = key_len;
|
||||
he->ptr = (void *) p;
|
||||
@@ -179,6 +182,23 @@ Curl_hash_add(struct curl_hash *h, char *key, size_t key_len, void *p)
|
||||
return NULL; /* failure */
|
||||
}
|
||||
|
||||
/* remove the identified hash entry, returns non-zero on failure */
|
||||
int Curl_hash_delete(struct curl_hash *h, char *key, size_t key_len)
|
||||
{
|
||||
struct curl_llist_element *le;
|
||||
struct curl_hash_element *he;
|
||||
struct curl_llist *l = FETCH_LIST(h, key, key_len);
|
||||
|
||||
for (le = l->head; le; le = le->next) {
|
||||
he = le->ptr;
|
||||
if (hash_key_compare(he->key, he->key_len, key, key_len)) {
|
||||
Curl_llist_remove(l, le, (void *) h);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void *
|
||||
Curl_hash_pick(struct curl_hash *h, char *key, size_t key_len)
|
||||
{
|
||||
@@ -186,9 +206,7 @@ Curl_hash_pick(struct curl_hash *h, char *key, size_t key_len)
|
||||
struct curl_hash_element *he;
|
||||
struct curl_llist *l = FETCH_LIST(h, key, key_len);
|
||||
|
||||
for (le = l->head;
|
||||
le;
|
||||
le = le->next) {
|
||||
for (le = l->head; le; le = le->next) {
|
||||
he = le->ptr;
|
||||
if (hash_key_compare(he->key, he->key_len, key, key_len)) {
|
||||
return he->ptr;
|
||||
|
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2005, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2006, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -24,11 +24,10 @@
|
||||
#include "setup.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#if defined(WIN32) && !defined(__GNUC__) || defined(__MINGW32__)
|
||||
#ifdef HAVE_MALLOC_H /* Win32 */
|
||||
#include <malloc.h>
|
||||
#else
|
||||
#endif
|
||||
#ifdef HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
@@ -55,13 +54,12 @@
|
||||
#include <inet.h>
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SETJMP_H
|
||||
#include <setjmp.h>
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
#ifdef HAVE_PROCESS_H
|
||||
#include <process.h>
|
||||
#endif
|
||||
|
||||
@@ -77,6 +75,7 @@
|
||||
#include "share.h"
|
||||
#include "strerror.h"
|
||||
#include "url.h"
|
||||
#include "connect.h" /* for the Curl_sockerrno() proto */
|
||||
|
||||
#define _MPRINTF_REPLACE /* use our functions only */
|
||||
#include <curl/mprintf.h>
|
||||
@@ -105,17 +104,15 @@
|
||||
* Returns: CURLE_OK always!
|
||||
*/
|
||||
|
||||
CURLcode Curl_resolv_fdset(struct connectdata *conn,
|
||||
fd_set *read_fd_set,
|
||||
fd_set *write_fd_set,
|
||||
int *max_fdp)
|
||||
int Curl_resolv_getsock(struct connectdata *conn,
|
||||
curl_socket_t *socks,
|
||||
int numsocks)
|
||||
|
||||
{
|
||||
int max = ares_fds(conn->data->state.areschannel,
|
||||
read_fd_set, write_fd_set);
|
||||
*max_fdp = max;
|
||||
int max = ares_getsock(conn->data->state.areschannel,
|
||||
(int *)socks, numsocks);
|
||||
|
||||
return CURLE_OK;
|
||||
return max;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -211,7 +208,7 @@ CURLcode Curl_wait_for_resolv(struct connectdata *conn,
|
||||
break;
|
||||
tvp = ares_timeout(data->state.areschannel, &store, &tv);
|
||||
count = select(nfds, &read_fds, &write_fds, NULL, tvp);
|
||||
if (count < 0 && errno != EINVAL)
|
||||
if (count < 0 && Curl_sockerrno() != EINVAL)
|
||||
break;
|
||||
|
||||
ares_process(data->state.areschannel, &read_fds, &write_fds);
|
||||
|
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2005, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2006, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -24,11 +24,10 @@
|
||||
#include "setup.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#if defined(WIN32) && !defined(__GNUC__) || defined(__MINGW32__)
|
||||
#ifdef HAVE_MALLOC_H /* Win32 */
|
||||
#include <malloc.h>
|
||||
#else
|
||||
#endif
|
||||
#ifdef HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
@@ -55,13 +54,12 @@
|
||||
#include <inet.h>
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SETJMP_H
|
||||
#include <setjmp.h>
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
#ifdef HAVE_PROCESS_H
|
||||
#include <process.h>
|
||||
#endif
|
||||
|
||||
|
@@ -24,11 +24,10 @@
|
||||
#include "setup.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#if defined(WIN32) && !defined(__GNUC__) || defined(__MINGW32__)
|
||||
#ifdef HAVE_MALLOC_H /* Win32 */
|
||||
#include <malloc.h>
|
||||
#else
|
||||
#endif
|
||||
#ifdef HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
@@ -55,13 +54,12 @@
|
||||
#include <inet.h>
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SETJMP_H
|
||||
#include <setjmp.h>
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
#ifdef HAVE_PROCESS_H
|
||||
#include <process.h>
|
||||
#endif
|
||||
|
||||
|
20
lib/hostip.h
20
lib/hostip.h
@@ -160,15 +160,19 @@ CURLcode Curl_is_resolved(struct connectdata *conn,
|
||||
CURLcode Curl_wait_for_resolv(struct connectdata *conn,
|
||||
struct Curl_dns_entry **dnsentry);
|
||||
|
||||
/* Curl_resolv_fdset() is a generic function that exists in multiple versions
|
||||
depending on what name resolve technology we've built to use. The function
|
||||
is called from the curl_multi_fdset() function */
|
||||
CURLcode Curl_resolv_fdset(struct connectdata *conn,
|
||||
fd_set *read_fd_set,
|
||||
fd_set *write_fd_set,
|
||||
int *max_fdp);
|
||||
/* Curl_resolv_getsock() is a generic function that exists in multiple
|
||||
versions depending on what name resolve technology we've built to use. The
|
||||
function is called from the multi_getsock() function. 'sock' is a pointer
|
||||
to an array to hold the file descriptors, with 'numsock' being the size of
|
||||
that array (in number of entries). This function is supposed to return
|
||||
bitmask indicating what file descriptors (referring to array indexes in the
|
||||
'sock' array) to wait for, read/write. */
|
||||
int Curl_resolv_getsock(struct connectdata *conn, curl_socket_t *sock,
|
||||
int numsocks);
|
||||
|
||||
/* unlock a previously resolved dns entry */
|
||||
void Curl_resolv_unlock(struct SessionHandle *data, struct Curl_dns_entry *dns);
|
||||
void Curl_resolv_unlock(struct SessionHandle *data,
|
||||
struct Curl_dns_entry *dns);
|
||||
|
||||
/* for debugging purposes only: */
|
||||
void Curl_scan_cache_used(void *user, void *ptr);
|
||||
|
@@ -26,9 +26,9 @@
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#if defined(WIN32) && !defined(__GNUC__) || defined(__MINGW32__)
|
||||
#ifdef HAVE_MALLOC_H /* Win32 */
|
||||
#include <malloc.h>
|
||||
#else
|
||||
#endif
|
||||
#ifdef HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
@@ -55,13 +55,12 @@
|
||||
#include <inet.h>
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SETJMP_H
|
||||
#include <setjmp.h>
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
#ifdef HAVE_PROCESS_H
|
||||
#include <process.h>
|
||||
#endif
|
||||
|
||||
|
@@ -24,11 +24,10 @@
|
||||
#include "setup.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#if defined(WIN32) && !defined(__GNUC__) || defined(__MINGW32__)
|
||||
#ifdef HAVE_MALLOC_H
|
||||
#include <malloc.h>
|
||||
#else
|
||||
#endif
|
||||
#ifdef HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
@@ -55,13 +54,12 @@
|
||||
#include <inet.h>
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SETJMP_H
|
||||
#include <setjmp.h>
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
#ifdef HAVE_PROCESS_H
|
||||
#include <process.h>
|
||||
#endif
|
||||
|
||||
@@ -203,7 +201,7 @@ static void dump_addrinfo(struct connectdata *conn, const struct addrinfo *ai)
|
||||
if (Curl_printable_address(ai, buf, sizeof(buf)))
|
||||
printf("%s\n", buf);
|
||||
else
|
||||
printf("failed; %s\n", Curl_strerror(conn, Curl_ourerrno()));
|
||||
printf("failed; %s\n", Curl_strerror(conn, Curl_sockerrno()));
|
||||
}
|
||||
}
|
||||
#else
|
||||
|
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2005, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2006, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -24,11 +24,10 @@
|
||||
#include "setup.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#if defined(WIN32) && !defined(__GNUC__) || defined(__MINGW32__)
|
||||
#ifdef HAVE_MALLOC_H
|
||||
#include <malloc.h>
|
||||
#else
|
||||
#endif
|
||||
#ifdef HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
@@ -55,13 +54,12 @@
|
||||
#include <inet.h>
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SETJMP_H
|
||||
#include <setjmp.h>
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
#ifdef HAVE_PROCESS_H
|
||||
#include <process.h>
|
||||
#endif
|
||||
|
||||
@@ -126,17 +124,15 @@ CURLcode Curl_is_resolved(struct connectdata *conn,
|
||||
* It is present here to keep #ifdefs out from multi.c
|
||||
*/
|
||||
|
||||
CURLcode Curl_resolv_fdset(struct connectdata *conn,
|
||||
fd_set *read_fd_set,
|
||||
fd_set *write_fd_set,
|
||||
int *max_fdp)
|
||||
int Curl_resolv_getsock(struct connectdata *conn,
|
||||
curl_socket_t *sock,
|
||||
int numsocks)
|
||||
{
|
||||
(void)conn;
|
||||
(void)read_fd_set;
|
||||
(void)write_fd_set;
|
||||
(void)max_fdp;
|
||||
(void)sock;
|
||||
(void)numsocks;
|
||||
|
||||
return CURLE_OK;
|
||||
return 0; /* no bits since we don't use any socks */
|
||||
}
|
||||
|
||||
#endif /* truly sync */
|
||||
|
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2005, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2006, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -26,9 +26,9 @@
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#if defined(WIN32) && !defined(__GNUC__) || defined(__MINGW32__)
|
||||
#ifdef HAVE_MALLOC_H
|
||||
#include <malloc.h>
|
||||
#else
|
||||
#endif
|
||||
#ifdef HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
@@ -55,14 +55,12 @@
|
||||
#include <inet.h>
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SETJMP_H
|
||||
#include <setjmp.h>
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
#include <stdlib.h>
|
||||
#ifdef HAVE_PROCESS_H
|
||||
#include <process.h>
|
||||
#endif
|
||||
|
||||
@@ -78,6 +76,7 @@
|
||||
#include "share.h"
|
||||
#include "strerror.h"
|
||||
#include "url.h"
|
||||
#include "multiif.h"
|
||||
|
||||
#define _MPRINTF_REPLACE /* use our functions only */
|
||||
#include <curl/mprintf.h>
|
||||
@@ -300,7 +299,7 @@ static unsigned __stdcall gethostbyname_thread (void *arg)
|
||||
struct thread_sync_data tsd = { 0,0,0,NULL };
|
||||
if (!init_thread_sync_data(td, conn->async.hostname, &tsd)) {
|
||||
/* thread synchronization data initialization failed */
|
||||
return -1;
|
||||
return (unsigned)-1;
|
||||
}
|
||||
|
||||
/* Sharing the same _iob[] element with our parent thread should
|
||||
@@ -569,7 +568,7 @@ static bool init_resolve_thread (struct connectdata *conn,
|
||||
thread_and_event[1] = td->event_thread_started;
|
||||
if (WaitForMultipleObjects(sizeof(thread_and_event) /
|
||||
sizeof(thread_and_event[0]),
|
||||
thread_and_event, FALSE,
|
||||
(const HANDLE*)thread_and_event, FALSE,
|
||||
INFINITE) == WAIT_FAILED) {
|
||||
/* The resolver thread has been created,
|
||||
* most probably it works now - ignoring this "minor" error
|
||||
@@ -715,20 +714,22 @@ CURLcode Curl_is_resolved(struct connectdata *conn,
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
CURLcode Curl_resolv_fdset(struct connectdata *conn,
|
||||
fd_set *read_fd_set,
|
||||
fd_set *write_fd_set,
|
||||
int *max_fdp)
|
||||
int Curl_resolv_getsock(struct connectdata *conn,
|
||||
curl_socket_t *socks,
|
||||
int numsocks)
|
||||
{
|
||||
const struct thread_data *td =
|
||||
(const struct thread_data *) conn->async.os_specific;
|
||||
|
||||
if (td && td->dummy_sock != CURL_SOCKET_BAD) {
|
||||
FD_SET(td->dummy_sock,write_fd_set);
|
||||
*max_fdp = (int)td->dummy_sock;
|
||||
if(numsocks) {
|
||||
/* return one socket waiting for writable, even though this is just
|
||||
a dummy */
|
||||
socks[0] = td->dummy_sock;
|
||||
return GETSOCK_WRITESOCK(0);
|
||||
}
|
||||
(void) read_fd_set;
|
||||
return CURLE_OK;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CURLRES_IPV4
|
||||
|
80
lib/http.c
80
lib/http.c
@@ -37,8 +37,6 @@
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#if defined(WIN32) && !defined(__GNUC__) || defined(__MINGW32__)
|
||||
#include <time.h>
|
||||
#include <io.h>
|
||||
@@ -97,6 +95,7 @@
|
||||
#include "select.h"
|
||||
#include "parsedate.h" /* for the week day and month names */
|
||||
#include "strtoofft.h"
|
||||
#include "multiif.h"
|
||||
|
||||
#define _MPRINTF_REPLACE /* use our functions only */
|
||||
#include <curl/mprintf.h>
|
||||
@@ -1371,13 +1370,6 @@ CURLcode Curl_http_connect(struct connectdata *conn, bool *done)
|
||||
return result;
|
||||
}
|
||||
|
||||
if(conn->protocol & PROT_HTTPS) {
|
||||
/* perform SSL initialization for this socket */
|
||||
result = Curl_ssl_connect(conn, FIRSTSOCKET);
|
||||
if(result)
|
||||
return result;
|
||||
}
|
||||
|
||||
if(!data->state.this_is_a_follow) {
|
||||
/* this is not a followed location, get the original host name */
|
||||
if (data->state.first_host)
|
||||
@@ -1387,11 +1379,81 @@ CURLcode Curl_http_connect(struct connectdata *conn, bool *done)
|
||||
data->state.first_host = strdup(conn->host.name);
|
||||
}
|
||||
|
||||
if(conn->protocol & PROT_HTTPS) {
|
||||
/* perform SSL initialization */
|
||||
if(data->state.used_interface == Curl_if_multi) {
|
||||
result = Curl_https_connecting(conn, done);
|
||||
if(result)
|
||||
return result;
|
||||
}
|
||||
else {
|
||||
/* BLOCKING */
|
||||
result = Curl_ssl_connect(conn, FIRSTSOCKET);
|
||||
if(result)
|
||||
return result;
|
||||
*done = TRUE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
*done = TRUE;
|
||||
}
|
||||
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
CURLcode Curl_https_connecting(struct connectdata *conn, bool *done)
|
||||
{
|
||||
CURLcode result;
|
||||
curlassert(conn->protocol & PROT_HTTPS);
|
||||
|
||||
/* perform SSL initialization for this socket */
|
||||
result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, done);
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
#ifdef USE_SSLEAY
|
||||
/* This function is OpenSSL-specific. It should be made to query the generic
|
||||
SSL layer instead. */
|
||||
int Curl_https_getsock(struct connectdata *conn,
|
||||
curl_socket_t *socks,
|
||||
int numsocks)
|
||||
{
|
||||
if (conn->protocol & PROT_HTTPS) {
|
||||
struct ssl_connect_data *connssl = &conn->ssl[FIRSTSOCKET];
|
||||
|
||||
if(!numsocks)
|
||||
return GETSOCK_BLANK;
|
||||
|
||||
if (connssl->connecting_state == ssl_connect_2_writing) {
|
||||
/* write mode */
|
||||
socks[0] = conn->sock[FIRSTSOCKET];
|
||||
return GETSOCK_WRITESOCK(0);
|
||||
}
|
||||
else if (connssl->connecting_state == ssl_connect_2_reading) {
|
||||
/* read mode */
|
||||
socks[0] = conn->sock[FIRSTSOCKET];
|
||||
return GETSOCK_READSOCK(0);
|
||||
}
|
||||
}
|
||||
return CURLE_OK;
|
||||
}
|
||||
#else
|
||||
#ifdef USE_GNUTLS
|
||||
int Curl_https_getsock(struct connectdata *conn,
|
||||
curl_socket_t *socks,
|
||||
int numsocks)
|
||||
{
|
||||
(void)conn;
|
||||
(void)socks;
|
||||
(void)numsocks;
|
||||
return GETSOCK_BLANK;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Curl_http_done() gets called from Curl_done() after a single HTTP request
|
||||
* has been performed.
|
||||
|
@@ -8,7 +8,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2005, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2006, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -37,6 +37,10 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
|
||||
CURLcode Curl_http(struct connectdata *conn, bool *done);
|
||||
CURLcode Curl_http_done(struct connectdata *, CURLcode);
|
||||
CURLcode Curl_http_connect(struct connectdata *conn, bool *done);
|
||||
CURLcode Curl_https_connecting(struct connectdata *conn, bool *done);
|
||||
int Curl_https_getsock(struct connectdata *conn,
|
||||
curl_socket_t *socks,
|
||||
int numsocks);
|
||||
|
||||
/* The following functions are defined in http_chunks.c */
|
||||
void Curl_httpchunk_init(struct connectdata *conn);
|
||||
|
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2006, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -303,10 +303,11 @@ CURLcode Curl_output_digest(struct connectdata *conn,
|
||||
if(d->algo == CURLDIGESTALGO_MD5SESS) {
|
||||
/* nonce and cnonce are OUTSIDE the hash */
|
||||
tmp = aprintf("%s:%s:%s", ha1, d->nonce, d->cnonce);
|
||||
free(ha1);
|
||||
if(!tmp)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
ha1 = (unsigned char *)tmp;
|
||||
Curl_md5it(md5buf, (unsigned char *)tmp);
|
||||
free(tmp); /* free this again */
|
||||
md5_to_ascii(md5buf, ha1);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2005, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2006, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -34,7 +34,6 @@
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "urldata.h"
|
||||
#include "sendf.h"
|
||||
|
456
lib/http_ntlm.c
456
lib/http_ntlm.c
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2005, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2006, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -27,11 +27,16 @@
|
||||
http://davenport.sourceforge.net/ntlm.html
|
||||
http://www.innovation.ch/java/ntlm.html
|
||||
|
||||
Another implementation:
|
||||
http://lxr.mozilla.org/mozilla/source/security/manager/ssl/src/nsNTLMAuthModule.cpp
|
||||
|
||||
*/
|
||||
|
||||
#ifndef CURL_DISABLE_HTTP
|
||||
#ifdef USE_NTLM
|
||||
|
||||
#define DEBUG_ME 0
|
||||
|
||||
/* -- WIN32 approved -- */
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
@@ -46,6 +51,7 @@
|
||||
#include "http_ntlm.h"
|
||||
#include "url.h"
|
||||
#include "memory.h"
|
||||
#include "ssluse.h"
|
||||
|
||||
#define _MPRINTF_REPLACE /* use our functions only */
|
||||
#include <curl/mprintf.h>
|
||||
@@ -54,7 +60,9 @@
|
||||
|
||||
#include <openssl/des.h>
|
||||
#include <openssl/md4.h>
|
||||
#include <openssl/md5.h>
|
||||
#include <openssl/ssl.h>
|
||||
#include <openssl/rand.h>
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER < 0x00907001L
|
||||
#define DES_key_schedule des_key_schedule
|
||||
@@ -89,6 +97,102 @@ static PSecurityFunctionTable s_pSecFn = NULL;
|
||||
/* Define this to make the type-3 message include the NT response message */
|
||||
#define USE_NTRESPONSES 1
|
||||
|
||||
/* Define this to make the type-3 message include the NTLM2Session response
|
||||
message, requires USE_NTRESPONSES. */
|
||||
#define USE_NTLM2SESSION 1
|
||||
|
||||
#ifndef USE_WINDOWS_SSPI
|
||||
/* this function converts from the little endian format used in the incoming
|
||||
package to whatever endian format we're using natively */
|
||||
static unsigned int readint_le(unsigned char *buf) /* must point to a
|
||||
4 bytes buffer*/
|
||||
{
|
||||
return ((unsigned int)buf[0]) | ((unsigned int)buf[1] << 8) |
|
||||
((unsigned int)buf[2] << 16) | ((unsigned int)buf[3] << 24);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if DEBUG_ME
|
||||
# define DEBUG_OUT(x) x
|
||||
static void print_flags(FILE *handle, unsigned long flags)
|
||||
{
|
||||
if(flags & NTLMFLAG_NEGOTIATE_UNICODE)
|
||||
fprintf(handle, "NTLMFLAG_NEGOTIATE_UNICODE ");
|
||||
if(flags & NTLMFLAG_NEGOTIATE_OEM)
|
||||
fprintf(handle, "NTLMFLAG_NEGOTIATE_OEM ");
|
||||
if(flags & NTLMFLAG_REQUEST_TARGET)
|
||||
fprintf(handle, "NTLMFLAG_REQUEST_TARGET ");
|
||||
if(flags & (1<<3))
|
||||
fprintf(handle, "NTLMFLAG_UNKNOWN_3 ");
|
||||
if(flags & NTLMFLAG_NEGOTIATE_SIGN)
|
||||
fprintf(handle, "NTLMFLAG_NEGOTIATE_SIGN ");
|
||||
if(flags & NTLMFLAG_NEGOTIATE_SEAL)
|
||||
fprintf(handle, "NTLMFLAG_NEGOTIATE_SEAL ");
|
||||
if(flags & NTLMFLAG_NEGOTIATE_DATAGRAM_STYLE)
|
||||
fprintf(handle, "NTLMFLAG_NEGOTIATE_DATAGRAM_STYLE ");
|
||||
if(flags & NTLMFLAG_NEGOTIATE_LM_KEY)
|
||||
fprintf(handle, "NTLMFLAG_NEGOTIATE_LM_KEY ");
|
||||
if(flags & NTLMFLAG_NEGOTIATE_NETWARE)
|
||||
fprintf(handle, "NTLMFLAG_NEGOTIATE_NETWARE ");
|
||||
if(flags & NTLMFLAG_NEGOTIATE_NTLM_KEY)
|
||||
fprintf(handle, "NTLMFLAG_NEGOTIATE_NTLM_KEY ");
|
||||
if(flags & (1<<10))
|
||||
fprintf(handle, "NTLMFLAG_UNKNOWN_10 ");
|
||||
if(flags & (1<<11))
|
||||
fprintf(handle, "NTLMFLAG_UNKNOWN_11 ");
|
||||
if(flags & NTLMFLAG_NEGOTIATE_DOMAIN_SUPPLIED)
|
||||
fprintf(handle, "NTLMFLAG_NEGOTIATE_DOMAIN_SUPPLIED ");
|
||||
if(flags & NTLMFLAG_NEGOTIATE_WORKSTATION_SUPPLIED)
|
||||
fprintf(handle, "NTLMFLAG_NEGOTIATE_WORKSTATION_SUPPLIED ");
|
||||
if(flags & NTLMFLAG_NEGOTIATE_LOCAL_CALL)
|
||||
fprintf(handle, "NTLMFLAG_NEGOTIATE_LOCAL_CALL ");
|
||||
if(flags & NTLMFLAG_NEGOTIATE_ALWAYS_SIGN)
|
||||
fprintf(handle, "NTLMFLAG_NEGOTIATE_ALWAYS_SIGN ");
|
||||
if(flags & NTLMFLAG_TARGET_TYPE_DOMAIN)
|
||||
fprintf(handle, "NTLMFLAG_TARGET_TYPE_DOMAIN ");
|
||||
if(flags & NTLMFLAG_TARGET_TYPE_SERVER)
|
||||
fprintf(handle, "NTLMFLAG_TARGET_TYPE_SERVER ");
|
||||
if(flags & NTLMFLAG_TARGET_TYPE_SHARE)
|
||||
fprintf(handle, "NTLMFLAG_TARGET_TYPE_SHARE ");
|
||||
if(flags & NTLMFLAG_NEGOTIATE_NTLM2_KEY)
|
||||
fprintf(handle, "NTLMFLAG_NEGOTIATE_NTLM2_KEY ");
|
||||
if(flags & NTLMFLAG_REQUEST_INIT_RESPONSE)
|
||||
fprintf(handle, "NTLMFLAG_REQUEST_INIT_RESPONSE ");
|
||||
if(flags & NTLMFLAG_REQUEST_ACCEPT_RESPONSE)
|
||||
fprintf(handle, "NTLMFLAG_REQUEST_ACCEPT_RESPONSE ");
|
||||
if(flags & NTLMFLAG_REQUEST_NONNT_SESSION_KEY)
|
||||
fprintf(handle, "NTLMFLAG_REQUEST_NONNT_SESSION_KEY ");
|
||||
if(flags & NTLMFLAG_NEGOTIATE_TARGET_INFO)
|
||||
fprintf(handle, "NTLMFLAG_NEGOTIATE_TARGET_INFO ");
|
||||
if(flags & (1<<24))
|
||||
fprintf(handle, "NTLMFLAG_UNKNOWN_24 ");
|
||||
if(flags & (1<<25))
|
||||
fprintf(handle, "NTLMFLAG_UNKNOWN_25 ");
|
||||
if(flags & (1<<26))
|
||||
fprintf(handle, "NTLMFLAG_UNKNOWN_26 ");
|
||||
if(flags & (1<<27))
|
||||
fprintf(handle, "NTLMFLAG_UNKNOWN_27 ");
|
||||
if(flags & (1<<28))
|
||||
fprintf(handle, "NTLMFLAG_UNKNOWN_28 ");
|
||||
if(flags & NTLMFLAG_NEGOTIATE_128)
|
||||
fprintf(handle, "NTLMFLAG_NEGOTIATE_128 ");
|
||||
if(flags & NTLMFLAG_NEGOTIATE_KEY_EXCHANGE)
|
||||
fprintf(handle, "NTLMFLAG_NEGOTIATE_KEY_EXCHANGE ");
|
||||
if(flags & NTLMFLAG_NEGOTIATE_56)
|
||||
fprintf(handle, "NTLMFLAG_NEGOTIATE_56 ");
|
||||
}
|
||||
|
||||
static void print_hex(FILE *handle, const char *buf, size_t len)
|
||||
{
|
||||
const char *p = buf;
|
||||
fprintf(stderr, "0x");
|
||||
while (len-- > 0)
|
||||
fprintf(stderr, "%02.2x", (unsigned int)*p++);
|
||||
}
|
||||
#else
|
||||
# define DEBUG_OUT(x)
|
||||
#endif
|
||||
|
||||
/*
|
||||
(*) = A "security buffer" is a triplet consisting of two shorts and one
|
||||
long:
|
||||
@@ -107,6 +211,9 @@ CURLntlm Curl_input_ntlm(struct connectdata *conn,
|
||||
{
|
||||
/* point to the correct struct with this */
|
||||
struct ntlmdata *ntlm;
|
||||
#ifndef USE_WINDOWS_SSPI
|
||||
static const char type2_marker[] = { 0x02, 0x00, 0x00, 0x00 };
|
||||
#endif
|
||||
|
||||
ntlm = proxy?&conn->proxyntlm:&conn->ntlm;
|
||||
|
||||
@@ -143,19 +250,34 @@ CURLntlm Curl_input_ntlm(struct connectdata *conn,
|
||||
ntlm->state = NTLMSTATE_TYPE2; /* we got a type-2 */
|
||||
|
||||
#ifdef USE_WINDOWS_SSPI
|
||||
if ((ntlm->type_2 = malloc(size+1)) == NULL) {
|
||||
ntlm->type_2 = malloc(size+1);
|
||||
if (ntlm->type_2 == NULL) {
|
||||
free(buffer);
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
ntlm->n_type_2 = size;
|
||||
memcpy(ntlm->type_2, buffer, size);
|
||||
#else
|
||||
if(size >= 48)
|
||||
/* the nonce of interest is index [24 .. 31], 8 bytes */
|
||||
memcpy(ntlm->nonce, &buffer[24], 8);
|
||||
/* FIX: add an else here! */
|
||||
ntlm->flags = 0;
|
||||
|
||||
/* at index decimal 20, there's a 32bit NTLM flag field */
|
||||
if((size < 32) ||
|
||||
(memcmp(buffer, "NTLMSSP", 8) != 0) ||
|
||||
(memcmp(buffer+8, type2_marker, sizeof(type2_marker)) != 0)) {
|
||||
/* This was not a good enough type-2 message */
|
||||
free(buffer);
|
||||
return CURLNTLM_BAD;
|
||||
}
|
||||
|
||||
ntlm->flags = readint_le(&buffer[20]);
|
||||
memcpy(ntlm->nonce, &buffer[24], 8);
|
||||
|
||||
DEBUG_OUT({
|
||||
fprintf(stderr, "**** TYPE2 header flags=0x%08.8lx ", ntlm->flags);
|
||||
print_flags(stderr, ntlm->flags);
|
||||
fprintf(stderr, "\n nonce=");
|
||||
print_hex(stderr, ntlm->nonce, 8);
|
||||
fprintf(stderr, "\n****\n");
|
||||
});
|
||||
|
||||
free(buffer);
|
||||
#endif
|
||||
@@ -199,7 +321,7 @@ static void setup_des_key(unsigned char *key_56,
|
||||
* 8 byte plaintext is encrypted with each key and the resulting 24
|
||||
* bytes are stored in the results array.
|
||||
*/
|
||||
static void calc_resp(unsigned char *keys,
|
||||
static void lm_resp(unsigned char *keys,
|
||||
unsigned char *plaintext,
|
||||
unsigned char *results)
|
||||
{
|
||||
@@ -218,35 +340,19 @@ static void calc_resp(unsigned char *keys,
|
||||
DESKEY(ks), DES_ENCRYPT);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Set up lanmanager and nt hashed passwords
|
||||
* Set up lanmanager hashed password
|
||||
*/
|
||||
static void mkhash(char *password,
|
||||
unsigned char *nonce, /* 8 bytes */
|
||||
unsigned char *lmresp /* must fit 0x18 bytes */
|
||||
#ifdef USE_NTRESPONSES
|
||||
, unsigned char *ntresp /* must fit 0x18 bytes */
|
||||
#endif
|
||||
)
|
||||
static void mk_lm_hash(char *password, unsigned char *lmbuffer /* 21 bytes */)
|
||||
{
|
||||
/* 21 bytes fits 3 7-bytes chunks, as we use 56 bit (7 bytes) as DES input,
|
||||
and we add three different ones, see the calc_resp() function */
|
||||
unsigned char lmbuffer[21];
|
||||
#ifdef USE_NTRESPONSES
|
||||
unsigned char ntbuffer[21];
|
||||
#endif
|
||||
unsigned char *pw;
|
||||
unsigned char pw[14];
|
||||
static const unsigned char magic[] = {
|
||||
0x4B, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25
|
||||
0x4B, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25 /* i.e. KGS!@#$% */
|
||||
};
|
||||
unsigned int i;
|
||||
size_t len = strlen(password);
|
||||
|
||||
/* make it fit at least 14 bytes */
|
||||
pw = malloc(len<7?14:len*2);
|
||||
if(!pw)
|
||||
return; /* this will lead to a badly generated package */
|
||||
|
||||
if (len > 14)
|
||||
len = 14;
|
||||
|
||||
@@ -257,7 +363,8 @@ static void mkhash(char *password,
|
||||
pw[i] = 0;
|
||||
|
||||
{
|
||||
/* create LanManager hashed password */
|
||||
/* Create LanManager hashed password. */
|
||||
|
||||
DES_key_schedule ks;
|
||||
|
||||
setup_des_key(pw, DESKEY(ks));
|
||||
@@ -268,35 +375,46 @@ static void mkhash(char *password,
|
||||
DES_ecb_encrypt((DES_cblock *)magic, (DES_cblock *)(lmbuffer+8),
|
||||
DESKEY(ks), DES_ENCRYPT);
|
||||
|
||||
memset(lmbuffer+16, 0, sizeof(lmbuffer)-16);
|
||||
memset(lmbuffer + 16, 0, 21 - 16);
|
||||
}
|
||||
}
|
||||
/* create LM responses */
|
||||
calc_resp(lmbuffer, nonce, lmresp);
|
||||
|
||||
#ifdef USE_NTRESPONSES
|
||||
#if USE_NTRESPONSES
|
||||
static void utf8_to_unicode_le(unsigned char *dest, const char *src,
|
||||
size_t srclen)
|
||||
{
|
||||
/* create NT hashed password */
|
||||
MD4_CTX MD4;
|
||||
|
||||
len = strlen(password);
|
||||
|
||||
for (i=0; i<len; i++) {
|
||||
pw[2*i] = password[i];
|
||||
pw[2*i+1] = 0;
|
||||
size_t i;
|
||||
for (i=0; i<srclen; i++) {
|
||||
dest[2*i] = (unsigned char)src[i];
|
||||
dest[2*i+1] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Set up nt hashed passwords
|
||||
*/
|
||||
static void mk_nt_hash(char *password, unsigned char *ntbuffer /* 21 bytes */)
|
||||
{
|
||||
size_t len = strlen(password);
|
||||
unsigned char *pw = malloc(len*2);
|
||||
|
||||
utf8_to_unicode_le(pw, password, len);
|
||||
|
||||
{
|
||||
/* Create NT hashed password. */
|
||||
MD4_CTX MD4;
|
||||
|
||||
MD4_Init(&MD4);
|
||||
MD4_Update(&MD4, pw, 2*len);
|
||||
MD4_Final(ntbuffer, &MD4);
|
||||
|
||||
memset(ntbuffer+16, 0, sizeof(ntbuffer)-16);
|
||||
memset(ntbuffer + 16, 0, 21 - 16);
|
||||
}
|
||||
|
||||
calc_resp(ntbuffer, nonce, ntresp);
|
||||
#endif
|
||||
|
||||
free(pw);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -324,25 +442,28 @@ ntlm_sspi_cleanup(struct ntlmdata *ntlm)
|
||||
|
||||
#endif
|
||||
|
||||
#define SHORTPAIR(x) ((x) & 0xff), ((x) >> 8)
|
||||
#define SHORTPAIR(x) ((x) & 0xff), (((x) >> 8) & 0xff)
|
||||
#define LONGQUARTET(x) ((x) & 0xff), (((x) >> 8)&0xff), \
|
||||
(((x) >>16)&0xff), ((x)>>24)
|
||||
(((x) >>16)&0xff), (((x)>>24) & 0xff)
|
||||
|
||||
#define HOSTNAME_MAX 1024
|
||||
|
||||
/* this is for creating ntlm header output */
|
||||
CURLcode Curl_output_ntlm(struct connectdata *conn,
|
||||
bool proxy)
|
||||
{
|
||||
const char *domain=""; /* empty */
|
||||
const char *host=""; /* empty */
|
||||
char host [HOSTNAME_MAX+ 1] = ""; /* empty */
|
||||
#ifndef USE_WINDOWS_SSPI
|
||||
int domlen=(int)strlen(domain);
|
||||
int hostlen = (int)strlen(host);
|
||||
int hostoff; /* host name offset */
|
||||
int domoff; /* domain name offset */
|
||||
size_t domlen = strlen(domain);
|
||||
size_t hostlen = strlen(host);
|
||||
size_t hostoff; /* host name offset */
|
||||
size_t domoff; /* domain name offset */
|
||||
#endif
|
||||
size_t size;
|
||||
char *base64=NULL;
|
||||
unsigned char ntlmbuf[512]; /* enough, unless the host/domain is very long */
|
||||
unsigned char ntlmbuf[1024]; /* enough, unless the user+host+domain is very
|
||||
long */
|
||||
|
||||
/* point to the address of the pointer that holds the string to sent to the
|
||||
server, which is for a plain host or for a HTTP proxy */
|
||||
@@ -500,8 +621,9 @@ CURLcode Curl_output_ntlm(struct connectdata *conn,
|
||||
size = buf.cbBuffer;
|
||||
}
|
||||
#else
|
||||
hostoff = 32;
|
||||
domoff = hostoff + hostlen;
|
||||
hostoff = 0;
|
||||
domoff = hostoff + hostlen; /* This is 0: remember that host and domain
|
||||
are empty */
|
||||
|
||||
/* Create and send a type-1 message:
|
||||
|
||||
@@ -515,7 +637,11 @@ CURLcode Curl_output_ntlm(struct connectdata *conn,
|
||||
32 start of data block
|
||||
|
||||
*/
|
||||
|
||||
#if USE_NTLM2SESSION
|
||||
#define NTLM2FLAG NTLMFLAG_NEGOTIATE_NTLM2_KEY
|
||||
#else
|
||||
#define NTLM2FLAG 0
|
||||
#endif
|
||||
snprintf((char *)ntlmbuf, sizeof(ntlmbuf), "NTLMSSP%c"
|
||||
"\x01%c%c%c" /* 32-bit type = 1 */
|
||||
"%c%c%c%c" /* 32-bit NTLM flag field */
|
||||
@@ -533,9 +659,11 @@ CURLcode Curl_output_ntlm(struct connectdata *conn,
|
||||
0,0,0, /* part of type-1 long */
|
||||
|
||||
LONGQUARTET(
|
||||
NTLMFLAG_NEGOTIATE_OEM| /* 2 */
|
||||
NTLMFLAG_NEGOTIATE_NTLM_KEY /* 200 */
|
||||
/* equals 0x0202 */
|
||||
NTLMFLAG_NEGOTIATE_OEM|
|
||||
NTLMFLAG_REQUEST_TARGET|
|
||||
NTLMFLAG_NEGOTIATE_NTLM_KEY|
|
||||
NTLM2FLAG|
|
||||
NTLMFLAG_NEGOTIATE_ALWAYS_SIGN
|
||||
),
|
||||
SHORTPAIR(domlen),
|
||||
SHORTPAIR(domlen),
|
||||
@@ -545,13 +673,34 @@ CURLcode Curl_output_ntlm(struct connectdata *conn,
|
||||
SHORTPAIR(hostlen),
|
||||
SHORTPAIR(hostoff),
|
||||
0,0,
|
||||
host, domain);
|
||||
host /* this is empty */, domain /* this is empty */);
|
||||
|
||||
/* initial packet length */
|
||||
size = 32 + hostlen + domlen;
|
||||
#endif
|
||||
|
||||
/* now keeper of the base64 encoded package size */
|
||||
DEBUG_OUT({
|
||||
fprintf(stderr, "**** TYPE1 header flags=0x%02.2x%02.2x%02.2x%02.2x 0x%08.8x ",
|
||||
LONGQUARTET(NTLMFLAG_NEGOTIATE_OEM|
|
||||
NTLMFLAG_REQUEST_TARGET|
|
||||
NTLMFLAG_NEGOTIATE_NTLM_KEY|
|
||||
NTLM2FLAG|
|
||||
NTLMFLAG_NEGOTIATE_ALWAYS_SIGN),
|
||||
NTLMFLAG_NEGOTIATE_OEM|
|
||||
NTLMFLAG_REQUEST_TARGET|
|
||||
NTLMFLAG_NEGOTIATE_NTLM_KEY|
|
||||
NTLM2FLAG|
|
||||
NTLMFLAG_NEGOTIATE_ALWAYS_SIGN);
|
||||
print_flags(stderr,
|
||||
NTLMFLAG_NEGOTIATE_OEM|
|
||||
NTLMFLAG_REQUEST_TARGET|
|
||||
NTLMFLAG_NEGOTIATE_NTLM_KEY|
|
||||
NTLM2FLAG|
|
||||
NTLMFLAG_NEGOTIATE_ALWAYS_SIGN);
|
||||
fprintf(stderr, "\n****\n");
|
||||
});
|
||||
|
||||
/* now size is the size of the base64 encoded package size */
|
||||
size = Curl_base64_encode((char *)ntlmbuf, size, &base64);
|
||||
|
||||
if(size >0 ) {
|
||||
@@ -567,7 +716,7 @@ CURLcode Curl_output_ntlm(struct connectdata *conn,
|
||||
break;
|
||||
|
||||
case NTLMSTATE_TYPE2:
|
||||
/* We received the type-2 already, create a type-3 message:
|
||||
/* We received the type-2 message already, create a type-3 message:
|
||||
|
||||
Index Description Content
|
||||
0 NTLMSSP Signature Null-terminated ASCII "NTLMSSP"
|
||||
@@ -622,14 +771,14 @@ CURLcode Curl_output_ntlm(struct connectdata *conn,
|
||||
|
||||
#else
|
||||
int lmrespoff;
|
||||
unsigned char lmresp[24]; /* fixed-size */
|
||||
#if USE_NTRESPONSES
|
||||
int ntrespoff;
|
||||
int useroff;
|
||||
unsigned char lmresp[0x18]; /* fixed-size */
|
||||
#ifdef USE_NTRESPONSES
|
||||
unsigned char ntresp[0x18]; /* fixed-size */
|
||||
unsigned char ntresp[24]; /* fixed-size */
|
||||
#endif
|
||||
size_t useroff;
|
||||
const char *user;
|
||||
int userlen;
|
||||
size_t userlen;
|
||||
|
||||
user = strchr(userp, '\\');
|
||||
if(!user)
|
||||
@@ -637,31 +786,90 @@ CURLcode Curl_output_ntlm(struct connectdata *conn,
|
||||
|
||||
if (user) {
|
||||
domain = userp;
|
||||
domlen = (int)(user - domain);
|
||||
domlen = (user - domain);
|
||||
user++;
|
||||
}
|
||||
else
|
||||
user = userp;
|
||||
userlen = (int)strlen(user);
|
||||
userlen = strlen(user);
|
||||
|
||||
mkhash(passwdp, &ntlm->nonce[0], lmresp
|
||||
#ifdef USE_NTRESPONSES
|
||||
, ntresp
|
||||
if (gethostname(host, HOSTNAME_MAX)) {
|
||||
infof(conn->data, "gethostname() failed, continuing without!");
|
||||
hostlen = 0;
|
||||
}
|
||||
else {
|
||||
hostlen = strlen(host);
|
||||
}
|
||||
|
||||
#if USE_NTLM2SESSION
|
||||
/* We don't support NTLM2 if we don't have USE_NTRESPONSES */
|
||||
if (ntlm->flags & NTLMFLAG_NEGOTIATE_NTLM2_KEY) {
|
||||
unsigned char ntbuffer[0x18];
|
||||
unsigned char tmp[0x18];
|
||||
unsigned char md5sum[MD5_DIGEST_LENGTH];
|
||||
MD5_CTX MD5;
|
||||
unsigned char random[8];
|
||||
|
||||
/* Need to create 8 bytes random data */
|
||||
Curl_ossl_seed(conn->data); /* Initiate the seed if not already done */
|
||||
RAND_bytes(random,8);
|
||||
|
||||
/* 8 bytes random data as challenge in lmresp */
|
||||
memcpy(lmresp,random,8);
|
||||
/* Pad with zeros */
|
||||
memset(lmresp+8,0,0x10);
|
||||
|
||||
/* Fill tmp with challenge(nonce?) + random */
|
||||
memcpy(tmp,&ntlm->nonce[0],8);
|
||||
memcpy(tmp+8,random,8);
|
||||
|
||||
MD5_Init(&MD5);
|
||||
MD5_Update(&MD5, tmp, 16);
|
||||
MD5_Final(md5sum, &MD5);
|
||||
/* We shall only use the first 8 bytes of md5sum,
|
||||
but the des code in lm_resp only encrypt the first 8 bytes */
|
||||
mk_nt_hash(passwdp, ntbuffer);
|
||||
lm_resp(ntbuffer, md5sum, ntresp);
|
||||
|
||||
/* End of NTLM2 Session code */
|
||||
}
|
||||
else {
|
||||
#endif
|
||||
);
|
||||
|
||||
domoff = 64; /* always */
|
||||
#if USE_NTRESPONSES
|
||||
unsigned char ntbuffer[0x18];
|
||||
#endif
|
||||
unsigned char lmbuffer[0x18];
|
||||
|
||||
#if USE_NTRESPONSES
|
||||
mk_nt_hash(passwdp, ntbuffer);
|
||||
lm_resp(ntbuffer, &ntlm->nonce[0], ntresp);
|
||||
#endif
|
||||
|
||||
mk_lm_hash(passwdp, lmbuffer);
|
||||
lm_resp(lmbuffer, &ntlm->nonce[0], lmresp);
|
||||
/* A safer but less compatible alternative is:
|
||||
* lm_resp(ntbuffer, &ntlm->nonce[0], lmresp);
|
||||
* See http://davenport.sourceforge.net/ntlm.html#ntlmVersion2 */
|
||||
}
|
||||
|
||||
lmrespoff = 64; /* size of the message header */
|
||||
#if USE_NTRESPONSES
|
||||
ntrespoff = lmrespoff + 0x18;
|
||||
domoff = ntrespoff + 0x18;
|
||||
#else
|
||||
domoff = lmrespoff + 0x18;
|
||||
#endif
|
||||
useroff = domoff + domlen;
|
||||
hostoff = useroff + userlen;
|
||||
lmrespoff = hostoff + hostlen;
|
||||
ntrespoff = lmrespoff + 0x18;
|
||||
|
||||
/* Create the big type-3 message binary blob */
|
||||
size = snprintf((char *)ntlmbuf, sizeof(ntlmbuf),
|
||||
"NTLMSSP%c"
|
||||
"\x03%c%c%c" /* type-3, 32 bits */
|
||||
|
||||
"%c%c%c%c" /* LanManager length + allocated space */
|
||||
"%c%c" /* LanManager length */
|
||||
"%c%c" /* LanManager allocated space */
|
||||
"%c%c" /* LanManager offset */
|
||||
"%c%c" /* 2 zeroes */
|
||||
|
||||
@@ -683,14 +891,15 @@ CURLcode Curl_output_ntlm(struct connectdata *conn,
|
||||
"%c%c" /* host length */
|
||||
"%c%c" /* host allocated space */
|
||||
"%c%c" /* host offset */
|
||||
"%c%c%c%c%c%c" /* 6 zeroes */
|
||||
|
||||
"\xff\xff" /* message length */
|
||||
"%c%c" /* 2 zeroes */
|
||||
|
||||
"\x01\x82" /* flags */
|
||||
"%c%c" /* session key length (unknown purpose) */
|
||||
"%c%c" /* session key allocated space (unknown purpose) */
|
||||
"%c%c" /* session key offset (unknown purpose) */
|
||||
"%c%c" /* 2 zeroes */
|
||||
|
||||
"%c%c%c%c" /* flags */
|
||||
|
||||
/* domain string */
|
||||
/* user string */
|
||||
/* host string */
|
||||
@@ -705,16 +914,17 @@ CURLcode Curl_output_ntlm(struct connectdata *conn,
|
||||
SHORTPAIR(lmrespoff),
|
||||
0x0, 0x0,
|
||||
|
||||
#ifdef USE_NTRESPONSES
|
||||
#if USE_NTRESPONSES
|
||||
SHORTPAIR(0x18), /* NT-response length, twice */
|
||||
SHORTPAIR(0x18),
|
||||
SHORTPAIR(ntrespoff),
|
||||
0x0, 0x0,
|
||||
#else
|
||||
0x0, 0x0,
|
||||
0x0, 0x0,
|
||||
#endif
|
||||
SHORTPAIR(ntrespoff),
|
||||
0x0, 0x0,
|
||||
|
||||
0x0, 0x0,
|
||||
#endif
|
||||
SHORTPAIR(domlen),
|
||||
SHORTPAIR(domlen),
|
||||
SHORTPAIR(domoff),
|
||||
@@ -728,44 +938,68 @@ CURLcode Curl_output_ntlm(struct connectdata *conn,
|
||||
SHORTPAIR(hostlen),
|
||||
SHORTPAIR(hostlen),
|
||||
SHORTPAIR(hostoff),
|
||||
0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||
|
||||
0x0, 0x0,
|
||||
|
||||
0x0, 0x0);
|
||||
0x0, 0x0,
|
||||
0x0, 0x0,
|
||||
0x0, 0x0,
|
||||
0x0, 0x0,
|
||||
|
||||
/* size is now 64 */
|
||||
size=64;
|
||||
ntlmbuf[62]=ntlmbuf[63]=0;
|
||||
LONGQUARTET(ntlm->flags));
|
||||
DEBUG_OUT(assert(size==64));
|
||||
|
||||
/* Make sure that the user and domain strings fit in the target buffer
|
||||
before we copy them there. */
|
||||
if(size + userlen + domlen >= sizeof(ntlmbuf)) {
|
||||
failf(conn->data, "user + domain name too big");
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
memcpy(&ntlmbuf[size], domain, domlen);
|
||||
size += domlen;
|
||||
|
||||
memcpy(&ntlmbuf[size], user, userlen);
|
||||
size += userlen;
|
||||
|
||||
/* we append the binary hashes to the end of the blob */
|
||||
if(size < ((int)sizeof(ntlmbuf) - 0x18)) {
|
||||
DEBUG_OUT(assert(size == lmrespoff));
|
||||
/* We append the binary hashes */
|
||||
if(size < (sizeof(ntlmbuf) - 0x18)) {
|
||||
memcpy(&ntlmbuf[size], lmresp, 0x18);
|
||||
size += 0x18;
|
||||
}
|
||||
|
||||
#ifdef USE_NTRESPONSES
|
||||
if(size < ((int)sizeof(ntlmbuf) - 0x18)) {
|
||||
DEBUG_OUT({
|
||||
fprintf(stderr, "**** TYPE3 header lmresp=");
|
||||
print_hex(stderr, &ntlmbuf[lmrespoff], 0x18);
|
||||
});
|
||||
|
||||
#if USE_NTRESPONSES
|
||||
if(size < (sizeof(ntlmbuf) - 0x18)) {
|
||||
DEBUG_OUT(assert(size == ntrespoff));
|
||||
memcpy(&ntlmbuf[size], ntresp, 0x18);
|
||||
size += 0x18;
|
||||
}
|
||||
|
||||
DEBUG_OUT({
|
||||
fprintf(stderr, "\n ntresp=");
|
||||
print_hex(stderr, &ntlmbuf[ntrespoff], 0x18);
|
||||
});
|
||||
|
||||
#endif
|
||||
|
||||
ntlmbuf[56] = (unsigned char)(size & 0xff);
|
||||
ntlmbuf[57] = (unsigned char)(size >> 8);
|
||||
DEBUG_OUT({
|
||||
fprintf(stderr, "\n flags=0x%02.2x%02.2x%02.2x%02.2x 0x%08.8x ",
|
||||
LONGQUARTET(ntlm->flags), ntlm->flags);
|
||||
print_flags(stderr, ntlm->flags);
|
||||
fprintf(stderr, "\n****\n");
|
||||
});
|
||||
|
||||
|
||||
/* Make sure that the domain, user and host strings fit in the target
|
||||
buffer before we copy them there. */
|
||||
if(size + userlen + domlen + hostlen >= sizeof(ntlmbuf)) {
|
||||
failf(conn->data, "user + domain + host name too big");
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
curlassert(size == domoff);
|
||||
memcpy(&ntlmbuf[size], domain, domlen);
|
||||
size += domlen;
|
||||
|
||||
curlassert(size == useroff);
|
||||
memcpy(&ntlmbuf[size], user, userlen);
|
||||
size += userlen;
|
||||
|
||||
curlassert(size == hostoff);
|
||||
memcpy(&ntlmbuf[size], host, hostlen);
|
||||
size += hostlen;
|
||||
|
||||
#endif
|
||||
|
||||
|
@@ -33,7 +33,7 @@
|
||||
|
||||
#include "if2ip.h"
|
||||
|
||||
#if !defined(WIN32) && !defined(__BEOS__) && !defined(__CYGWIN32__) && \
|
||||
#if !defined(WIN32) && !defined(__BEOS__) && !defined(__CYGWIN__) && \
|
||||
!defined(__riscos__) && !defined(__INTERIX) && !defined(NETWARE) && \
|
||||
!defined(_AMIGASF)
|
||||
|
||||
|
16
lib/ldap.c
16
lib/ldap.c
@@ -36,10 +36,12 @@
|
||||
#ifdef HAVE_SYS_STAT_H
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
#ifdef HAVE_MALLOC_H
|
||||
#include <malloc.h>
|
||||
#endif
|
||||
#include <errno.h>
|
||||
|
||||
#if defined(WIN32)
|
||||
# include <malloc.h>
|
||||
# include <winldap.h>
|
||||
#endif
|
||||
|
||||
@@ -498,31 +500,31 @@ static char **split_str (char *str)
|
||||
/*
|
||||
* Unescape the LDAP-URL components
|
||||
*/
|
||||
static bool unescape_elements (LDAPURLDesc *ludp)
|
||||
static bool unescape_elements (void *data, LDAPURLDesc *ludp)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (ludp->lud_filter) {
|
||||
ludp->lud_filter = curl_unescape(ludp->lud_filter, 0);
|
||||
ludp->lud_filter = curl_easy_unescape(data, ludp->lud_filter, 0, NULL);
|
||||
if (!ludp->lud_filter)
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
for (i = 0; ludp->lud_attrs && ludp->lud_attrs[i]; i++) {
|
||||
ludp->lud_attrs[i] = curl_unescape(ludp->lud_attrs[i], 0);
|
||||
ludp->lud_attrs[i] = curl_easy_unescape(data, ludp->lud_attrs[i], 0, NULL);
|
||||
if (!ludp->lud_attrs[i])
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
for (i = 0; ludp->lud_exts && ludp->lud_exts[i]; i++) {
|
||||
ludp->lud_exts[i] = curl_unescape(ludp->lud_exts[i], 0);
|
||||
ludp->lud_exts[i] = curl_easy_unescape(data, ludp->lud_exts[i], 0, NULL);
|
||||
if (!ludp->lud_exts[i])
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
if (ludp->lud_dn) {
|
||||
char *dn = ludp->lud_dn;
|
||||
char *new_dn = curl_unescape(dn, 0);
|
||||
char *new_dn = curl_easy_unescape(data, dn, 0, NULL);
|
||||
|
||||
free(dn);
|
||||
ludp->lud_dn = new_dn;
|
||||
@@ -633,7 +635,7 @@ static int _ldap_url_parse2 (const struct connectdata *conn, LDAPURLDesc *ludp)
|
||||
LDAP_TRACE (("exts[%d] '%s'\n", i, ludp->lud_exts[i]));
|
||||
|
||||
success:
|
||||
if (!unescape_elements(ludp))
|
||||
if (!unescape_elements(conn->data, ludp))
|
||||
return LDAP_NO_MEMORY;
|
||||
return LDAP_SUCCESS;
|
||||
}
|
||||
|
@@ -3,19 +3,27 @@
|
||||
TMP_DIR = ../lib/.lib
|
||||
LIB_DIR = ../lib
|
||||
|
||||
# Sets the SDK. 10.4u.sdk is the minimum for building a Universal Binary.
|
||||
SDK = /Developer/SDKs/MacOSX10.4u.sdk
|
||||
|
||||
# Sets the minimum OSX version where the framework will work.
|
||||
ENVP = MACOSX_DEPLOYMENT_TARGET=10.3
|
||||
|
||||
# for debug symbols add the -g option. Remove the -O2 option for best debuggin.
|
||||
# Can be compiled with -O3 optimizations.
|
||||
C_OPTIONS = \
|
||||
C_OPTIONS = -isysroot $(SDK) \
|
||||
-fno-common \
|
||||
-O2 \
|
||||
-Os \
|
||||
-DHAVE_CONFIG_H \
|
||||
-DPIC \
|
||||
-I../lib \
|
||||
-I../include \
|
||||
-Wall
|
||||
-Wall \
|
||||
-arch ppc \
|
||||
-arch i386
|
||||
|
||||
LIBRARIES = /usr/lib/libssl.dylib \
|
||||
/usr/lib/libcrypto.dylib \
|
||||
LIBRARIES = $(SDK)/usr/lib/libssl.dylib \
|
||||
$(SDK)/usr/lib/libcrypto.dylib \
|
||||
-lz
|
||||
|
||||
# These libtool options are needed for a framework.
|
||||
@@ -25,7 +33,11 @@ LIBRARIES = /usr/lib/libssl.dylib \
|
||||
# For prebinding 0x10400000 was chosen a bit at random.
|
||||
# If this overlaps one of you current libs just change in the makefile.
|
||||
# This address is safe for all built in frameworks.
|
||||
LINK_OPTIONS = -prebind \
|
||||
LINK_OPTIONS = \
|
||||
-Wl,-syslibroot,$(SDK) \
|
||||
-arch ppc \
|
||||
-arch i386 \
|
||||
-prebind \
|
||||
-seg1addr 0x10400000 \
|
||||
-dynamiclib \
|
||||
-install_name @executable_path/../Frameworks/libcurl.framework/libcurl
|
||||
@@ -71,6 +83,7 @@ OBJECTS = $(TMP_DIR)/base64.o \
|
||||
$(TMP_DIR)/parsedate.o \
|
||||
$(TMP_DIR)/progress.o \
|
||||
$(TMP_DIR)/security.o \
|
||||
$(TMP_DIR)/select.o \
|
||||
$(TMP_DIR)/sendf.o \
|
||||
$(TMP_DIR)/share.o \
|
||||
$(TMP_DIR)/speedcheck.o \
|
||||
@@ -81,6 +94,7 @@ OBJECTS = $(TMP_DIR)/base64.o \
|
||||
$(TMP_DIR)/strtok.o \
|
||||
$(TMP_DIR)/strtoofft.o \
|
||||
$(TMP_DIR)/telnet.o \
|
||||
$(TMP_DIR)/tftp.o \
|
||||
$(TMP_DIR)/timeval.o \
|
||||
$(TMP_DIR)/transfer.o \
|
||||
$(TMP_DIR)/url.o \
|
||||
@@ -97,12 +111,16 @@ $(LIB_DIR) :
|
||||
# This builds the framework structure and links everything properly
|
||||
$(LIB_DIR)/libcurl.framework: $(OBJECTS) $(LIB_DIR)/libcurl.plist
|
||||
mkdir -p $(LIB_DIR)/libcurl.framework/Versions/A/Resources
|
||||
$(CC) $(LINK_OPTIONS) $(LIBRARIES) $(OBJECTS) \
|
||||
$(ENVP) $(CC) $(LINK_OPTIONS) $(LIBRARIES) $(OBJECTS) \
|
||||
-o $(LIB_DIR)/libcurl.framework/Versions/A/libcurl
|
||||
cp $(LIB_DIR)/libcurl.plist $(LIB_DIR)/libcurl.framework/Versions/A/Resources/Info.plist
|
||||
mkdir -p $(LIB_DIR)/libcurl.framework/Versions/A/Headers
|
||||
cp $(LIB_DIR)/../include/curl/* $(LIB_DIR)/libcurl.framework/Versions/A/Headers
|
||||
rm $(LIB_DIR)/libcurl.framework/Versions/A/Headers/Make*
|
||||
cd $(LIB_DIR)/libcurl.framework; \
|
||||
ln -fs ./Versions/A/libcurl libcurl; \
|
||||
ln -fs ./Versions/A/Resources Resources
|
||||
ln -fs ./Versions/A/Resources Resources; \
|
||||
ln -fs ./Versions/A/Headers Headers
|
||||
cd $(LIB_DIR)/libcurl.framework/Versions; \
|
||||
ln -fs ./A Current
|
||||
|
||||
|
@@ -3,6 +3,8 @@
|
||||
#
|
||||
# (LIBCURL)
|
||||
curl_easy_cleanup,
|
||||
curl_easy_escape,
|
||||
curl_easy_unescape,
|
||||
curl_easy_getinfo,
|
||||
curl_easy_init,
|
||||
curl_easy_perform,
|
||||
|
676
lib/multi.c
676
lib/multi.c
@@ -46,6 +46,7 @@
|
||||
#include "easyif.h"
|
||||
#include "multiif.h"
|
||||
#include "sendf.h"
|
||||
#include "timeval.h"
|
||||
|
||||
/* The last #include file should be: */
|
||||
#include "memdebug.h"
|
||||
@@ -73,6 +74,17 @@ typedef enum {
|
||||
CURLM_STATE_LAST /* not a true state, never use this */
|
||||
} CURLMstate;
|
||||
|
||||
/* we support 16 sockets per easy handle. Set the corresponding bit to what
|
||||
action we should wait for */
|
||||
#define MAX_SOCKSPEREASYHANDLE 16
|
||||
#define GETSOCK_READABLE (0x00ff)
|
||||
#define GETSOCK_WRITABLE (0xff00)
|
||||
|
||||
struct socketstate {
|
||||
curl_socket_t socks[MAX_SOCKSPEREASYHANDLE];
|
||||
unsigned int action; /* socket action bitmap */
|
||||
};
|
||||
|
||||
struct Curl_one_easy {
|
||||
/* first, two fields for the linked list of these */
|
||||
struct Curl_one_easy *next;
|
||||
@@ -90,6 +102,8 @@ struct Curl_one_easy {
|
||||
will be deleted when this handle is removed
|
||||
from the multi-handle */
|
||||
int msg_num; /* number of messages left in 'msg' to return */
|
||||
|
||||
struct socketstate sockstate; /* for the socket API magic */
|
||||
};
|
||||
|
||||
#define CURL_MULTI_HANDLE 0x000bab1e
|
||||
@@ -111,8 +125,21 @@ struct Curl_multi {
|
||||
|
||||
int num_msgs; /* total amount of messages in the easy handles */
|
||||
|
||||
/* callback function and user data pointer for the *socket() API */
|
||||
curl_socket_callback socket_cb;
|
||||
void *socket_userp;
|
||||
|
||||
/* Hostname cache */
|
||||
struct curl_hash *hostcache;
|
||||
|
||||
/* timetree points to the splay-tree of time nodes to figure out expire
|
||||
times of all currently set timers */
|
||||
struct Curl_tree *timetree;
|
||||
|
||||
/* 'sockhash' is the lookup hash for socket descriptor => easy handles (note
|
||||
the pluralis form, there can be more than one easy handle waiting on the
|
||||
same actual socket) */
|
||||
struct curl_hash *sockhash;
|
||||
};
|
||||
|
||||
/* always use this function to change state, to make debugging easier */
|
||||
@@ -134,6 +161,7 @@ static void multistate(struct Curl_one_easy *easy, CURLMstate state)
|
||||
};
|
||||
CURLMstate oldstate = easy->state;
|
||||
#endif
|
||||
|
||||
easy->state = state;
|
||||
|
||||
#ifdef CURLDEBUG
|
||||
@@ -143,25 +171,120 @@ static void multistate(struct Curl_one_easy *easy, CURLMstate state)
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* We add one of these structs to the sockhash for a particular socket
|
||||
*/
|
||||
|
||||
struct Curl_sh_entry {
|
||||
struct SessionHandle *easy;
|
||||
time_t timestamp;
|
||||
long inuse;
|
||||
int action; /* what action READ/WRITE this socket waits for */
|
||||
void *userp; /* settable by users (not yet decided exactly how) */
|
||||
};
|
||||
/* bits for 'action' having no bits means this socket is not expecting any
|
||||
action */
|
||||
#define SH_READ 1
|
||||
#define SH_WRITE 2
|
||||
|
||||
/* make sure this socket is present in the hash for this handle */
|
||||
static int sh_addentry(struct curl_hash *sh,
|
||||
curl_socket_t s,
|
||||
struct SessionHandle *data)
|
||||
{
|
||||
struct Curl_sh_entry *there =
|
||||
Curl_hash_pick(sh, (char *)&s, sizeof(curl_socket_t));
|
||||
struct Curl_sh_entry *check;
|
||||
|
||||
if(there)
|
||||
/* it is present, return fine */
|
||||
return 0;
|
||||
|
||||
/* not present, add it */
|
||||
check = calloc(sizeof(struct Curl_sh_entry), 1);
|
||||
if(!check)
|
||||
return 1; /* major failure */
|
||||
check->easy = data;
|
||||
|
||||
/* make/add new hash entry */
|
||||
if(NULL == Curl_hash_add(sh, (char *)&s, sizeof(curl_socket_t), check))
|
||||
return 1; /* major failure */
|
||||
|
||||
return 0; /* things are good in sockhash land */
|
||||
}
|
||||
|
||||
|
||||
/* delete the given socket + handle from the hash */
|
||||
static void sh_delentry(struct curl_hash *sh, curl_socket_t s)
|
||||
{
|
||||
struct Curl_sh_entry *there =
|
||||
Curl_hash_pick(sh, (char *)&s, sizeof(curl_socket_t));
|
||||
|
||||
if(there) {
|
||||
/* this socket is in the hash */
|
||||
/* We remove the hash entry. (This'll end up in a call to
|
||||
sh_freeentry().) */
|
||||
Curl_hash_delete(sh, (char *)&s, sizeof(curl_socket_t));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* free a sockhash entry
|
||||
*/
|
||||
static void sh_freeentry(void *freethis)
|
||||
{
|
||||
struct Curl_sh_entry *p = (struct Curl_sh_entry *) freethis;
|
||||
|
||||
free(p);
|
||||
}
|
||||
|
||||
/*
|
||||
* sh_init() creates a new socket hash and returns the handle for it.
|
||||
*
|
||||
* Quote from README.multi_socket:
|
||||
*
|
||||
* "Some tests at 7000 and 9000 connections showed that the socket hash lookup
|
||||
* is somewhat of a bottle neck. Its current implementation may be a bit too
|
||||
* limiting. It simply has a fixed-size array, and on each entry in the array
|
||||
* it has a linked list with entries. So the hash only checks which list to
|
||||
* scan through. The code I had used so for used a list with merely 7 slots
|
||||
* (as that is what the DNS hash uses) but with 7000 connections that would
|
||||
* make an average of 1000 nodes in each list to run through. I upped that to
|
||||
* 97 slots (I believe a prime is suitable) and noticed a significant speed
|
||||
* increase. I need to reconsider the hash implementation or use a rather
|
||||
* large default value like this. At 9000 connections I was still below 10us
|
||||
* per call."
|
||||
*
|
||||
*/
|
||||
static struct curl_hash *sh_init(void)
|
||||
{
|
||||
return Curl_hash_alloc(97, sh_freeentry);
|
||||
}
|
||||
|
||||
CURLM *curl_multi_init(void)
|
||||
{
|
||||
struct Curl_multi *multi;
|
||||
struct Curl_multi *multi = (void *)calloc(sizeof(struct Curl_multi), 1);
|
||||
|
||||
multi = (void *)malloc(sizeof(struct Curl_multi));
|
||||
|
||||
if(multi) {
|
||||
memset(multi, 0, sizeof(struct Curl_multi));
|
||||
multi->type = CURL_MULTI_HANDLE;
|
||||
}
|
||||
else
|
||||
if(!multi)
|
||||
return NULL;
|
||||
|
||||
multi->type = CURL_MULTI_HANDLE;
|
||||
|
||||
multi->hostcache = Curl_mk_dnscache();
|
||||
if(!multi->hostcache) {
|
||||
/* failure, free mem and bail out */
|
||||
free(multi);
|
||||
multi = NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
multi->sockhash = sh_init();
|
||||
if(!multi->sockhash) {
|
||||
/* failure, free mem and bail out */
|
||||
Curl_hash_destroy(multi->hostcache);
|
||||
free(multi);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return (CURLM *) multi;
|
||||
}
|
||||
|
||||
@@ -170,6 +293,7 @@ CURLMcode curl_multi_add_handle(CURLM *multi_handle,
|
||||
{
|
||||
struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
|
||||
struct Curl_one_easy *easy;
|
||||
int i;
|
||||
|
||||
/* First, make some basic checks that the CURLM handle is a good handle */
|
||||
if(!GOOD_MULTI_HANDLE(multi))
|
||||
@@ -180,18 +304,23 @@ CURLMcode curl_multi_add_handle(CURLM *multi_handle,
|
||||
return CURLM_BAD_EASY_HANDLE;
|
||||
|
||||
/* Now, time to add an easy handle to the multi stack */
|
||||
easy = (struct Curl_one_easy *)malloc(sizeof(struct Curl_one_easy));
|
||||
easy = (struct Curl_one_easy *)calloc(sizeof(struct Curl_one_easy), 1);
|
||||
if(!easy)
|
||||
return CURLM_OUT_OF_MEMORY;
|
||||
|
||||
/* clean it all first (just to be sure) */
|
||||
memset(easy, 0, sizeof(struct Curl_one_easy));
|
||||
for(i=0; i< MAX_SOCKSPEREASYHANDLE; i++)
|
||||
easy->sockstate.socks[i] = CURL_SOCKET_BAD;
|
||||
|
||||
/* set the easy handle */
|
||||
easy->easy_handle = easy_handle;
|
||||
multistate(easy, CURLM_STATE_INIT);
|
||||
|
||||
/* for multi interface connections, we share DNS cache automaticly */
|
||||
/* for multi interface connections, we share DNS cache automaticly.
|
||||
First kill the existing one if there is any. */
|
||||
if (easy->easy_handle->hostcache &&
|
||||
easy->easy_handle->hostcache != multi->hostcache)
|
||||
Curl_hash_destroy(easy->easy_handle->hostcache);
|
||||
|
||||
easy->easy_handle->hostcache = multi->hostcache;
|
||||
|
||||
/* We add this new entry first in the list. We make our 'next' point to the
|
||||
@@ -209,6 +338,9 @@ CURLMcode curl_multi_add_handle(CURLM *multi_handle,
|
||||
|
||||
Curl_easy_addmulti(easy_handle, multi_handle);
|
||||
|
||||
/* make the SessionHandle struct refer back to this struct */
|
||||
easy->easy_handle->set.one_easy = easy;
|
||||
|
||||
/* increase the node-counter */
|
||||
multi->num_easy++;
|
||||
|
||||
@@ -257,6 +389,8 @@ CURLMcode curl_multi_remove_handle(CURLM *multi_handle,
|
||||
if(easy->next)
|
||||
easy->next->prev = easy->prev;
|
||||
|
||||
easy->easy_handle->set.one_easy = NULL; /* detached */
|
||||
|
||||
/* NOTE NOTE NOTE
|
||||
We do not touch the easy handle here! */
|
||||
if (easy->msg)
|
||||
@@ -271,6 +405,65 @@ CURLMcode curl_multi_remove_handle(CURLM *multi_handle,
|
||||
return CURLM_BAD_EASY_HANDLE; /* twasn't found */
|
||||
}
|
||||
|
||||
static int waitconnect_getsock(struct connectdata *conn,
|
||||
curl_socket_t *sock,
|
||||
int numsocks)
|
||||
{
|
||||
if(!numsocks)
|
||||
return GETSOCK_BLANK;
|
||||
|
||||
sock[0] = conn->sock[FIRSTSOCKET];
|
||||
return GETSOCK_WRITESOCK(0);
|
||||
}
|
||||
|
||||
static int domore_getsock(struct connectdata *conn,
|
||||
curl_socket_t *sock,
|
||||
int numsocks)
|
||||
{
|
||||
if(!numsocks)
|
||||
return GETSOCK_BLANK;
|
||||
|
||||
/* When in DO_MORE state, we could be either waiting for us
|
||||
to connect to a remote site, or we could wait for that site
|
||||
to connect to us. It makes a difference in the way: if we
|
||||
connect to the site we wait for the socket to become writable, if
|
||||
the site connects to us we wait for it to become readable */
|
||||
sock[0] = conn->sock[SECONDARYSOCKET];
|
||||
|
||||
return GETSOCK_WRITESOCK(0);
|
||||
}
|
||||
|
||||
/* returns bitmapped flags for this handle and its sockets */
|
||||
static int multi_getsock(struct Curl_one_easy *easy,
|
||||
curl_socket_t *socks, /* points to numsocks number
|
||||
of sockets */
|
||||
int numsocks)
|
||||
{
|
||||
switch(easy->state) {
|
||||
default:
|
||||
return 0;
|
||||
|
||||
case CURLM_STATE_WAITRESOLVE:
|
||||
return Curl_resolv_getsock(easy->easy_conn, socks, numsocks);
|
||||
|
||||
case CURLM_STATE_PROTOCONNECT:
|
||||
return Curl_protocol_getsock(easy->easy_conn, socks, numsocks);
|
||||
|
||||
case CURLM_STATE_DOING:
|
||||
return Curl_doing_getsock(easy->easy_conn, socks, numsocks);
|
||||
|
||||
case CURLM_STATE_WAITCONNECT:
|
||||
return waitconnect_getsock(easy->easy_conn, socks, numsocks);
|
||||
|
||||
case CURLM_STATE_DO_MORE:
|
||||
return domore_getsock(easy->easy_conn, socks, numsocks);
|
||||
|
||||
case CURLM_STATE_PERFORM:
|
||||
return Curl_single_getsock(easy->easy_conn, socks, numsocks);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
CURLMcode curl_multi_fdset(CURLM *multi_handle,
|
||||
fd_set *read_fd_set, fd_set *write_fd_set,
|
||||
fd_set *exc_fd_set, int *max_fd)
|
||||
@@ -281,104 +474,58 @@ CURLMcode curl_multi_fdset(CURLM *multi_handle,
|
||||
struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
|
||||
struct Curl_one_easy *easy;
|
||||
int this_max_fd=-1;
|
||||
curl_socket_t sockbunch[MAX_SOCKSPEREASYHANDLE];
|
||||
int bitmap;
|
||||
int i;
|
||||
(void)exc_fd_set; /* not used */
|
||||
|
||||
if(!GOOD_MULTI_HANDLE(multi))
|
||||
return CURLM_BAD_HANDLE;
|
||||
|
||||
*max_fd = -1; /* so far none! */
|
||||
|
||||
easy=multi->easy.next;
|
||||
while(easy) {
|
||||
switch(easy->state) {
|
||||
default:
|
||||
break;
|
||||
case CURLM_STATE_WAITRESOLVE:
|
||||
/* waiting for a resolve to complete */
|
||||
Curl_resolv_fdset(easy->easy_conn, read_fd_set, write_fd_set,
|
||||
&this_max_fd);
|
||||
if(this_max_fd > *max_fd)
|
||||
*max_fd = this_max_fd;
|
||||
break;
|
||||
bitmap = multi_getsock(easy, sockbunch, MAX_SOCKSPEREASYHANDLE);
|
||||
|
||||
case CURLM_STATE_PROTOCONNECT:
|
||||
Curl_protocol_fdset(easy->easy_conn, read_fd_set, write_fd_set,
|
||||
&this_max_fd);
|
||||
if(this_max_fd > *max_fd)
|
||||
*max_fd = this_max_fd;
|
||||
break;
|
||||
for(i=0; i< MAX_SOCKSPEREASYHANDLE; i++) {
|
||||
curl_socket_t s = CURL_SOCKET_BAD;
|
||||
|
||||
case CURLM_STATE_DOING:
|
||||
Curl_doing_fdset(easy->easy_conn, read_fd_set, write_fd_set,
|
||||
&this_max_fd);
|
||||
if(this_max_fd > *max_fd)
|
||||
*max_fd = this_max_fd;
|
||||
break;
|
||||
|
||||
case CURLM_STATE_WAITCONNECT:
|
||||
case CURLM_STATE_DO_MORE:
|
||||
{
|
||||
/* when we're waiting for a connect, we wait for the socket to
|
||||
become writable */
|
||||
struct connectdata *conn = easy->easy_conn;
|
||||
curl_socket_t sockfd;
|
||||
|
||||
if(CURLM_STATE_WAITCONNECT == easy->state) {
|
||||
sockfd = conn->sock[FIRSTSOCKET];
|
||||
FD_SET(sockfd, write_fd_set);
|
||||
if(bitmap & GETSOCK_READSOCK(i)) {
|
||||
FD_SET(sockbunch[i], read_fd_set);
|
||||
s = sockbunch[i];
|
||||
}
|
||||
if(bitmap & GETSOCK_WRITESOCK(i)) {
|
||||
FD_SET(sockbunch[i], write_fd_set);
|
||||
s = sockbunch[i];
|
||||
}
|
||||
if(s == CURL_SOCKET_BAD)
|
||||
/* this socket is unused, break out of loop */
|
||||
break;
|
||||
else {
|
||||
/* When in DO_MORE state, we could be either waiting for us
|
||||
to connect to a remote site, or we could wait for that site
|
||||
to connect to us. It makes a difference in the way: if we
|
||||
connect to the site we wait for the socket to become writable, if
|
||||
the site connects to us we wait for it to become readable */
|
||||
sockfd = conn->sock[SECONDARYSOCKET];
|
||||
FD_SET(sockfd, write_fd_set);
|
||||
if(s > (curl_socket_t)this_max_fd)
|
||||
this_max_fd = (int)s;
|
||||
}
|
||||
}
|
||||
|
||||
if((int)sockfd > *max_fd)
|
||||
*max_fd = (int)sockfd;
|
||||
}
|
||||
break;
|
||||
case CURLM_STATE_PERFORM:
|
||||
/* This should have a set of file descriptors for us to set. */
|
||||
/* after the transfer is done, go DONE */
|
||||
|
||||
Curl_single_fdset(easy->easy_conn,
|
||||
read_fd_set, write_fd_set,
|
||||
exc_fd_set, &this_max_fd);
|
||||
|
||||
/* remember the maximum file descriptor */
|
||||
if(this_max_fd > *max_fd)
|
||||
*max_fd = this_max_fd;
|
||||
|
||||
break;
|
||||
}
|
||||
easy = easy->next; /* check next handle */
|
||||
}
|
||||
|
||||
*max_fd = this_max_fd;
|
||||
|
||||
return CURLM_OK;
|
||||
}
|
||||
|
||||
CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles)
|
||||
static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
||||
struct Curl_one_easy *easy,
|
||||
int *running_handles)
|
||||
{
|
||||
struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
|
||||
struct Curl_one_easy *easy;
|
||||
bool done;
|
||||
CURLMcode result=CURLM_OK;
|
||||
struct Curl_message *msg = NULL;
|
||||
bool connected;
|
||||
bool async;
|
||||
bool protocol_connect;
|
||||
bool dophase_done;
|
||||
bool done;
|
||||
CURLMcode result = CURLM_OK;
|
||||
|
||||
*running_handles = 0; /* bump this once for every living handle */
|
||||
|
||||
if(!GOOD_MULTI_HANDLE(multi))
|
||||
return CURLM_BAD_HANDLE;
|
||||
|
||||
easy=multi->easy.next;
|
||||
while(easy) {
|
||||
do {
|
||||
if (CURLM_STATE_WAITCONNECT <= easy->state &&
|
||||
easy->state <= CURLM_STATE_DO &&
|
||||
@@ -638,7 +785,7 @@ CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles)
|
||||
/* if we failed anywhere, we must clean up the secondary socket if
|
||||
it was used */
|
||||
sclose(easy->easy_conn->sock[SECONDARYSOCKET]);
|
||||
easy->easy_conn->sock[SECONDARYSOCKET]=-1;
|
||||
easy->easy_conn->sock[SECONDARYSOCKET] = CURL_SOCKET_BAD;
|
||||
}
|
||||
Curl_posttransfer(easy->easy_handle);
|
||||
Curl_done(&easy->easy_conn, easy->result);
|
||||
@@ -731,10 +878,45 @@ CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles)
|
||||
|
||||
multi->num_msgs++; /* increase message counter */
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles)
|
||||
{
|
||||
struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
|
||||
struct Curl_one_easy *easy;
|
||||
CURLMcode returncode=CURLM_OK;
|
||||
struct Curl_tree *t;
|
||||
|
||||
*running_handles = 0; /* bump this once for every living handle */
|
||||
|
||||
if(!GOOD_MULTI_HANDLE(multi))
|
||||
return CURLM_BAD_HANDLE;
|
||||
|
||||
easy=multi->easy.next;
|
||||
while(easy) {
|
||||
CURLMcode result = multi_runsingle(multi, easy, running_handles);
|
||||
if(result)
|
||||
returncode = result;
|
||||
|
||||
easy = easy->next; /* operate on next handle */
|
||||
}
|
||||
|
||||
return result;
|
||||
/*
|
||||
* Simply remove all expired timers from the splay since handles are dealt
|
||||
* with unconditionally by this function and curl_multi_timeout() requires
|
||||
* that already passed/handled expire times are removed from the splay.
|
||||
*/
|
||||
do {
|
||||
struct timeval now = Curl_tvnow();
|
||||
int key = now.tv_sec; /* drop the usec part */
|
||||
|
||||
multi->timetree = Curl_splaygetbest(key, multi->timetree, &t);
|
||||
} while(t);
|
||||
|
||||
return returncode;
|
||||
}
|
||||
|
||||
/* This is called when an easy handle is cleanup'ed that is part of a multi
|
||||
@@ -753,6 +935,7 @@ CURLMcode curl_multi_cleanup(CURLM *multi_handle)
|
||||
if(GOOD_MULTI_HANDLE(multi)) {
|
||||
multi->type = 0; /* not good anymore */
|
||||
Curl_hash_destroy(multi->hostcache);
|
||||
Curl_hash_destroy(multi->sockhash);
|
||||
|
||||
/* remove all easy handles */
|
||||
easy = multi->easy.next;
|
||||
@@ -807,3 +990,320 @@ CURLMsg *curl_multi_info_read(CURLM *multi_handle, int *msgs_in_queue)
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* singlesocket() checks what sockets we deal with and their "action state"
|
||||
* and if we have a different state in any of those sockets from last time we
|
||||
* call the callback accordingly.
|
||||
*/
|
||||
static void singlesocket(struct Curl_multi *multi,
|
||||
struct Curl_one_easy *easy)
|
||||
{
|
||||
struct socketstate current;
|
||||
int i;
|
||||
|
||||
memset(¤t, 0, sizeof(current));
|
||||
for(i=0; i< MAX_SOCKSPEREASYHANDLE; i++)
|
||||
current.socks[i] = CURL_SOCKET_BAD;
|
||||
|
||||
/* first fill in the 'current' struct with the state as it is now */
|
||||
current.action = multi_getsock(easy, current.socks, MAX_SOCKSPEREASYHANDLE);
|
||||
|
||||
/* when filled in, we compare with the previous round's state in a first
|
||||
quick memory compare check */
|
||||
if(memcmp(¤t, &easy->sockstate, sizeof(struct socketstate))) {
|
||||
|
||||
/* there is difference, call the callback once for every socket change ! */
|
||||
for(i=0; i< MAX_SOCKSPEREASYHANDLE; i++) {
|
||||
int action;
|
||||
curl_socket_t s = current.socks[i];
|
||||
|
||||
/* Ok, this approach is probably too naive and simple-minded but
|
||||
it might work for a start */
|
||||
|
||||
if((easy->sockstate.socks[i] == CURL_SOCKET_BAD) &&
|
||||
(s == CURL_SOCKET_BAD)) {
|
||||
/* no socket now and there was no socket before */
|
||||
break;
|
||||
}
|
||||
|
||||
if(s == CURL_SOCKET_BAD) {
|
||||
/* socket is removed */
|
||||
action = CURL_POLL_REMOVE;
|
||||
s = easy->sockstate.socks[i]; /* this is the removed socket */
|
||||
}
|
||||
else {
|
||||
if(easy->sockstate.socks[i] == s) {
|
||||
/* still the same socket, but are we waiting for the same actions? */
|
||||
unsigned int curr;
|
||||
unsigned int prev;
|
||||
|
||||
/* the current read/write bits for this particular socket */
|
||||
curr = current.action & (GETSOCK_READSOCK(i) | GETSOCK_WRITESOCK(i));
|
||||
|
||||
/* the previous read/write bits for this particular socket */
|
||||
prev = easy->sockstate.action &
|
||||
(GETSOCK_READSOCK(i) | GETSOCK_WRITESOCK(i));
|
||||
|
||||
if(curr == prev)
|
||||
continue;
|
||||
}
|
||||
|
||||
action = ((current.action & GETSOCK_READSOCK(i))?CURL_POLL_IN:0) |
|
||||
((current.action & GETSOCK_WRITESOCK(i))?CURL_POLL_OUT:0);
|
||||
}
|
||||
|
||||
/* call the callback with this new info */
|
||||
if(multi->socket_cb) {
|
||||
multi->socket_cb(easy->easy_handle,
|
||||
s,
|
||||
action,
|
||||
multi->socket_userp);
|
||||
}
|
||||
|
||||
/* Update the sockhash accordingly */
|
||||
if(action == CURL_POLL_REMOVE)
|
||||
/* remove from hash for this easy handle */
|
||||
sh_delentry(multi->sockhash, s);
|
||||
else
|
||||
/* make sure this socket is present in the hash for this handle */
|
||||
sh_addentry(multi->sockhash, s, easy->easy_handle);
|
||||
}
|
||||
/* copy the current state to the storage area */
|
||||
memcpy(&easy->sockstate, ¤t, sizeof(struct socketstate));
|
||||
}
|
||||
else {
|
||||
/* identical, nothing new happened so we don't do any callbacks */
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static CURLMcode multi_socket(struct Curl_multi *multi,
|
||||
bool checkall,
|
||||
curl_socket_t s)
|
||||
{
|
||||
CURLMcode result = CURLM_OK;
|
||||
int running_handles;
|
||||
struct SessionHandle *data = NULL;
|
||||
struct Curl_tree *t;
|
||||
|
||||
if(checkall) {
|
||||
struct Curl_one_easy *easyp;
|
||||
result = curl_multi_perform(multi, &running_handles);
|
||||
|
||||
/* walk through each easy handle and do the socket state change magic
|
||||
and callbacks */
|
||||
easyp=multi->easy.next;
|
||||
while(easyp) {
|
||||
singlesocket(multi, easyp);
|
||||
easyp = easyp->next;
|
||||
}
|
||||
|
||||
/* or should we fall-through and do the timer-based stuff? */
|
||||
return result;
|
||||
}
|
||||
else if (s != CURL_SOCKET_TIMEOUT) {
|
||||
|
||||
struct Curl_sh_entry *entry =
|
||||
Curl_hash_pick(multi->sockhash, (char *)&s, sizeof(s));
|
||||
|
||||
if(!entry)
|
||||
/* unmatched socket, major problemo! */
|
||||
return CURLM_BAD_SOCKET; /* better return code? */
|
||||
|
||||
/* Now, there is potentially a chain of easy handles in this hash
|
||||
entry struct and we need to deal with all of them */
|
||||
|
||||
data = entry->easy;
|
||||
|
||||
result = multi_runsingle(multi, data->set.one_easy, &running_handles);
|
||||
|
||||
if(result == CURLM_OK)
|
||||
/* get the socket(s) and check if the state has been changed since
|
||||
last */
|
||||
singlesocket(multi, data->set.one_easy);
|
||||
|
||||
/* or should we fall-through and do the timer-based stuff? */
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* The loop following here will go on as long as there are expire-times left
|
||||
* to process in the splay and 'data' will be re-assigned for every expired
|
||||
* handle we deal with.
|
||||
*/
|
||||
do {
|
||||
int key;
|
||||
struct timeval now;
|
||||
|
||||
/* the first loop lap 'data' can be NULL */
|
||||
if(data) {
|
||||
result = multi_runsingle(multi, data->set.one_easy, &running_handles);
|
||||
|
||||
if(result == CURLM_OK)
|
||||
/* get the socket(s) and check if the state has been changed since
|
||||
last */
|
||||
singlesocket(multi, data->set.one_easy);
|
||||
}
|
||||
|
||||
/* Check if there's one (more) expired timer to deal with! This function
|
||||
extracts a matching node if there is one */
|
||||
|
||||
now = Curl_tvnow();
|
||||
key = now.tv_sec; /* drop the usec part */
|
||||
|
||||
multi->timetree = Curl_splaygetbest(key, multi->timetree, &t);
|
||||
if(t)
|
||||
data = t->payload;
|
||||
|
||||
} while(t);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
CURLMcode curl_multi_setopt(CURLM *multi_handle,
|
||||
CURLMoption option, ...)
|
||||
{
|
||||
struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
|
||||
CURLMcode res = CURLM_OK;
|
||||
va_list param;
|
||||
|
||||
if(!GOOD_MULTI_HANDLE(multi))
|
||||
return CURLM_BAD_HANDLE;
|
||||
|
||||
va_start(param, option);
|
||||
|
||||
switch(option) {
|
||||
case CURLMOPT_SOCKETFUNCTION:
|
||||
multi->socket_cb = va_arg(param, curl_socket_callback);
|
||||
break;
|
||||
case CURLMOPT_SOCKETDATA:
|
||||
multi->socket_userp = va_arg(param, void *);
|
||||
break;
|
||||
default:
|
||||
res = CURLM_UNKNOWN_OPTION;
|
||||
}
|
||||
va_end(param);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
CURLMcode curl_multi_socket(CURLM *multi_handle, curl_socket_t s)
|
||||
{
|
||||
#if 0
|
||||
printf("multi_socket(%d)\n", (int)s);
|
||||
#endif
|
||||
|
||||
return multi_socket((struct Curl_multi *)multi_handle, FALSE, s);
|
||||
}
|
||||
|
||||
CURLMcode curl_multi_socket_all(CURLM *multi_handle)
|
||||
|
||||
{
|
||||
return multi_socket((struct Curl_multi *)multi_handle,
|
||||
TRUE, CURL_SOCKET_BAD);
|
||||
}
|
||||
|
||||
CURLMcode curl_multi_timeout(CURLM *multi_handle,
|
||||
long *timeout_ms)
|
||||
{
|
||||
struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
|
||||
|
||||
/* First, make some basic checks that the CURLM handle is a good handle */
|
||||
if(!GOOD_MULTI_HANDLE(multi))
|
||||
return CURLM_BAD_HANDLE;
|
||||
|
||||
if(multi->timetree) {
|
||||
/* we have a tree of expire times */
|
||||
struct timeval now = Curl_tvnow();
|
||||
|
||||
/* splay the lowest to the bottom */
|
||||
multi->timetree = Curl_splay(0, multi->timetree);
|
||||
|
||||
/* At least currently, the splay key is a time_t for the expire time */
|
||||
*timeout_ms = (multi->timetree->key - now.tv_sec) * 1000 -
|
||||
now.tv_usec/1000;
|
||||
if(*timeout_ms < 0)
|
||||
/* 0 means immediately */
|
||||
*timeout_ms = 0;
|
||||
}
|
||||
else
|
||||
*timeout_ms = -1;
|
||||
|
||||
return CURLM_OK;
|
||||
}
|
||||
|
||||
/* given a number of milliseconds from now to use to set the 'act before
|
||||
this'-time for the transfer, to be extracted by curl_multi_timeout() */
|
||||
void Curl_expire(struct SessionHandle *data, long milli)
|
||||
{
|
||||
struct Curl_multi *multi = data->multi;
|
||||
struct timeval *nowp = &data->state.expiretime;
|
||||
int rc;
|
||||
|
||||
/* this is only interesting for multi-interface using libcurl, and only
|
||||
while there is still a multi interface struct remaining! */
|
||||
if(!multi)
|
||||
return;
|
||||
|
||||
if(!milli) {
|
||||
/* No timeout, clear the time data. */
|
||||
if(nowp->tv_sec) {
|
||||
/* Since this is an cleared time, we must remove the previous entry from
|
||||
the splay tree */
|
||||
rc = Curl_splayremovebyaddr(multi->timetree,
|
||||
&data->state.timenode,
|
||||
&multi->timetree);
|
||||
if(rc)
|
||||
infof(data, "Internal error clearing splay node = %d\n", rc);
|
||||
infof(data, "Expire cleared\n");
|
||||
nowp->tv_sec = nowp->tv_usec = 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
struct timeval set;
|
||||
int rest;
|
||||
|
||||
set = Curl_tvnow();
|
||||
set.tv_sec += milli/1000;
|
||||
set.tv_usec += (milli%1000)*1000;
|
||||
|
||||
rest = (int)(set.tv_usec - 1000000);
|
||||
if(rest > 0) {
|
||||
/* bigger than a full microsec */
|
||||
set.tv_sec++;
|
||||
set.tv_usec -= 1000000;
|
||||
}
|
||||
|
||||
if(nowp->tv_sec) {
|
||||
/* This means that the struct is added as a node in the splay tree.
|
||||
Compare if the new time is earlier, and only remove-old/add-new if it
|
||||
is. */
|
||||
long diff = curlx_tvdiff(set, *nowp);
|
||||
if(diff > 0)
|
||||
/* the new expire time was later so we don't change this */
|
||||
return;
|
||||
|
||||
/* Since this is an updated time, we must remove the previous entry from
|
||||
the splay tree first and then re-add the new value */
|
||||
rc = Curl_splayremovebyaddr(multi->timetree,
|
||||
&data->state.timenode,
|
||||
&multi->timetree);
|
||||
if(rc)
|
||||
infof(data, "Internal error removing splay node = %d\n", rc);
|
||||
}
|
||||
|
||||
*nowp = set;
|
||||
infof(data, "Expire at %ld / %ld (%ldms)\n",
|
||||
(long)nowp->tv_sec, (long)nowp->tv_usec, milli);
|
||||
|
||||
data->state.timenode.payload = data;
|
||||
multi->timetree = Curl_splayinsert((int)nowp->tv_sec,
|
||||
multi->timetree,
|
||||
&data->state.timenode);
|
||||
}
|
||||
#if 0
|
||||
Curl_splayprint(multi->timetree, 0, TRUE);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@@ -26,5 +26,19 @@
|
||||
/*
|
||||
* Prototypes for library-wide functions provided by multi.c
|
||||
*/
|
||||
void Curl_expire(struct SessionHandle *data, long milli);
|
||||
|
||||
void Curl_multi_rmeasy(void *multi, CURL *data);
|
||||
|
||||
/* the write bits start at bit 16 for the *getsock() bitmap */
|
||||
#define GETSOCK_WRITEBITSTART 16
|
||||
|
||||
#define GETSOCK_BLANK 0 /* no bits set */
|
||||
|
||||
/* set the bit for the given sock number to make the bitmap for writable */
|
||||
#define GETSOCK_WRITESOCK(x) (1 << (GETSOCK_WRITEBITSTART + (x)))
|
||||
|
||||
/* set the bit for the given sock number to make the bitmap for readable */
|
||||
#define GETSOCK_READSOCK(x) (1 << (x))
|
||||
|
||||
#endif /* __MULTIIF_H */
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user