Compare commits

...

308 Commits

Author SHA1 Message Date
Daniel Stenberg
f2f07dad34 spell and 7.20.0 2010-02-09 10:06:48 +00:00
Daniel Stenberg
06ae8ca5a6 - When downloading compressed content over HTTP and the app as asked libcurl
to automatically uncompress it with the CURLOPT_ENCODING option, libcurl
  could wrongly provide the callback with more data than what the maximum
  documented amount. An application could thus get tricked into badness if the
  maximum limit was trusted to be enforced by libcurl itself (as it is
  documented).

  This is further detailed and explained in the libcurl security advisory
  20100209 at

    http://curl.haxx.se/docs/adv_20100209.html
2010-02-09 09:35:48 +00:00
Daniel Stenberg
d33da42334 set VERSIONINFO accordingly for the 7.20.0 release 2010-02-09 09:35:07 +00:00
Yang Tse
e118cd4ca0 warning fix 2010-02-06 17:31:09 +00:00
Yang Tse
71593dfe57 OOM handling fix 2010-02-06 17:30:06 +00:00
Yang Tse
0f4a91afde OOM handling fix 2010-02-06 13:21:45 +00:00
Yang Tse
2c2464a682 fix compiler warning 2010-02-05 20:52:00 +00:00
Yang Tse
880452d2ed fix compiler warning 2010-02-05 19:24:22 +00:00
Yang Tse
e3009f2950 fix compiler warning 2010-02-05 19:19:34 +00:00
Yang Tse
cad9c3f55f Addes OOM handling for curl_easy_setopt() calls in test 2010-02-05 18:07:19 +00:00
Yang Tse
12d01bc5f7 - avoid OpenSSL 0.9.8 ENGINE_by_id memory leak
- cleanup parenthesis usage in return statements
2010-02-05 09:33:36 +00:00
Yang Tse
bc7615ae2d - attempt to workaround icc 9.1 optimizer issue 2010-02-05 09:32:11 +00:00
Yang Tse
7aef172a34 fix printf-style format strings 2010-02-04 19:44:31 +00:00
Yang Tse
f47b84b57f Validate server port argument 2010-02-04 17:17:19 +00:00
Yang Tse
1a5749424b Fix variable initialization 2010-02-04 14:50:58 +00:00
Yang Tse
a9a5a8e45c Modified test case 557 to additionally verify libcurl's internal curl_m*printf()
functions formatting functionality when handling signed and unsigned shorts.
2010-02-04 14:41:01 +00:00
Yang Tse
8044366134 Added size check for 'short' data type 2010-02-04 14:40:11 +00:00
Yang Tse
15efa262bb Fix compiler warning: unused variable 2010-02-04 10:08:39 +00:00
Yang Tse
429e544556 added an additional second to allow test to pass on heavily loaded servers 2010-02-04 09:55:45 +00:00
Dan Fandrich
680434f313 Changed the Watcom makefiles to make them easier to keep in sync with
Makefile.inc since that can't be included directly.
2010-02-03 23:07:11 +00:00
Daniel Stenberg
c9f46446d5 more symbols added in 7.20.0 2010-02-03 18:18:13 +00:00
Yang Tse
b77d0db59e Fix OOM handling 2010-02-03 13:28:47 +00:00
Yang Tse
3205ac35b0 Fix progressmode Configurable struct member data type. Changed to
'int' which fits better with existing CURL_PROGRESS_* definitions.
2010-02-03 10:57:42 +00:00
Yang Tse
381a4d6efe Fix portability issue related with unaligned memory access 2010-02-03 06:49:27 +00:00
Yang Tse
f6d288a397 Fix compiler warnings: conversion from 'const int ' to 'unsigned char ', possible loss of data 2010-02-03 06:44:18 +00:00
Yang Tse
013ec6a92f cookies with same path length might get sorted in different order when
using different qsort implementations. In order to make this test give
same results on different systems, paths now have different lengths.
2010-02-03 01:53:47 +00:00
Yang Tse
e2fc294470 added an additional second to allow test to pass on heavily loaded servers 2010-02-03 01:41:07 +00:00
Yang Tse
d1717e7c90 Fix compiler warning: conditional expression is constant 2010-02-02 16:25:07 +00:00
Yang Tse
e569ff959f Fix compiler warning: local variable may be used without having been initialized. 2010-02-02 16:23:42 +00:00
Yang Tse
839b61c32a Fix compiler warnings: conversion from 'const int ' to 'unsigned char ', possible loss of data 2010-02-02 16:23:01 +00:00
Yang Tse
d28b8d3158 Fix compiler warnings:
(1) conversion from 'const int ' to 'unsigned char ', possible loss of data
(2) conditional expression is constant
2010-02-02 16:21:37 +00:00
Yang Tse
2dfbd0d050 mention a couple of changes back from November 2010-02-02 15:23:13 +00:00
Yang Tse
54879d7763 mention run time statistics options 2010-02-02 14:46:55 +00:00
Yang Tse
49ba75af26 - Symbol CURL_FORMAT_OFF_T now obsoleted, will be removed in a future release,
symbol will not be available when building with CURL_NO_OLDIES defined. Use
  of CURL_FORMAT_CURL_OFF_T is preferred since 7.19.0
2010-02-02 12:58:49 +00:00
Yang Tse
232d17ec64 avoid possibility of using obsoleted stuff 2010-02-02 12:39:10 +00:00
Yang Tse
bafba6946c remove setup.h inclusion which is already done from test.h inclusion 2010-02-02 12:36:16 +00:00
Kamil Dudka
da23b16ad8 mention SOCKS related problems in the curl(1) man page 2010-02-02 12:27:12 +00:00
Yang Tse
46de140aca Fix compiler warning: variable was set but never used
Simplify preprocessor symbol checking
2010-02-02 09:15:52 +00:00
Daniel Stenberg
17a2c32ca9 Julien Chaffraix pointed out a comment mistake, and I re-indented the code
slightly while editing
2010-02-02 08:48:58 +00:00
Yang Tse
9f6c4daa27 include headers 2010-02-02 07:01:21 +00:00
Yang Tse
ea72194650 Conroy added a check to the coded message size since the docs stipulate
that each call will contain a full protocol packet.
2010-02-01 22:14:22 +00:00
Yang Tse
35e220606d Conroy's fix to make the code match with the RTP documentation regarding
writing out the whole header. The docs say it writes the whole header,
but the code (before this patch) did not write out the leading $.
2010-02-01 22:13:55 +00:00
Daniel Stenberg
55f1e787f3 We introduce a loop in lib/multi.c around all calls to multi_runsingle() and
simply check for CURLM_CALL_MULTI_PERFORM internally. This has the added
benefit that this goes in line with my long-term wishes to get rid of the
CURLM_CALL_MULTI_PERFORM all together from the public API.
2010-02-01 21:42:44 +00:00
Yang Tse
516cf5c8dd update rtsp server header field from SWS to RTSPD 2010-02-01 19:57:11 +00:00
Yang Tse
35fbeda003 Test suite support for RTSP 2010-02-01 12:05:08 +00:00
Yang Tse
715e3a806f Make Curl_pop3_write() additionally truncate trailing POP3_EOB from received
string buffer, otherwise Curl_client_write() call with zero size would write
to the end of string buffer including matched POP3_EOB.
2010-01-30 05:22:30 +00:00
Yang Tse
6ebd71d186 WIN32 fix, _beginthreadex() may return either 0 or -1L upon failure 2010-01-29 17:47:54 +00:00
Yang Tse
4ee4e66c4f fix errno usage for WIN32 builds 2010-01-29 16:38:43 +00:00
Yang Tse
4d19ebe738 fix printf-style format strings 2010-01-29 12:29:26 +00:00
Yang Tse
5312fdcd73 Chris Conroy fixed test #568 issues with carriage returns 2010-01-29 02:58:39 +00:00
Yang Tse
fce02e1cab RTSP followup fix. Both the pipelined and non-pipelined case need to
check for (excess > 0 && !k->ignorebody).
2010-01-29 01:16:23 +00:00
Daniel Stenberg
15ddc1f134 - Tommie Gannert pointed out a silly bug in ares_process_fd() since it didn't
check for broken connections like ares_process() did. Based on that, I
  merged the two functions into a single generic one with two front-ends.
2010-01-28 22:03:48 +00:00
Yang Tse
d65cf7889b fix printf-style format strings 2010-01-28 15:34:18 +00:00
Yang Tse
ddab9bd2ec Use 'size_t' for GETNAMEINFO_TYPE_ARG2 definition for VMS.
http://curl.haxx.se/mail/lib-2009-12/0293.html
2010-01-28 10:56:43 +00:00
Yang Tse
eff18763a1 portability fix 2010-01-28 10:27:09 +00:00
Yang Tse
3e21f1e971 fix printf-style format strings 2010-01-28 07:52:12 +00:00
Yang Tse
ccffed997e Known bug #64 fixed by Constantine Sapuntzakis and Joshua Kwan in 7.20.0 2010-01-28 05:09:19 +00:00
Yang Tse
6259bcd51f Chris Conroy provided first RTSP tests 2010-01-28 04:58:03 +00:00
Yang Tse
a4031dbd85 RTSP tests disabled until test harness RTSP support is updated 2010-01-28 04:55:19 +00:00
Yang Tse
2f3bce1193 Chris Conroy's RTSP followup fixes 2010-01-28 01:39:16 +00:00
Yang Tse
3cb76e5ebb mention asynchronous DNS lookups enhancements 2010-01-27 18:10:35 +00:00
Yang Tse
6418c0588d Restore normal operation:
c-ares is only enabled when specifically requested.

  Consequently, c-ares default setting is disabled.
2010-01-27 06:59:02 +00:00
Yang Tse
124b35aafe fix c-ares assumed check being skipped 2010-01-27 04:56:07 +00:00
Yang Tse
bbefdf88fd fix compiler warning 2010-01-27 03:43:34 +00:00
Yang Tse
06c96d01d2 fix LDFLAGS preservation in CURL_CHECK_LIB_ARES 2010-01-27 03:41:05 +00:00
Daniel Stenberg
83e91586ef no need to take precautiono for how things were before 7.16.0 since that
is now a very long time ago
2010-01-26 23:02:13 +00:00
Daniel Stenberg
c82a1f95eb - Mike Crowe made libcurl return CURLE_COULDNT_RESOLVE_PROXY when it is the
proxy that cannot be resolved when using c-ares. This matches the behaviour
  when not using c-ares.
2010-01-26 22:59:43 +00:00
Dan Fandrich
d34982bb65 Added curl_threads.c to a few more non-configure build files 2010-01-26 18:51:39 +00:00
Yang Tse
22ed0f5059 minor fixes for --enable-ares configure option 2010-01-26 15:07:40 +00:00
Daniel Stenberg
9bc897f380 Andre Guibert de Bruet improved the libssh2 error code translation 2010-01-26 12:25:03 +00:00
Yang Tse
9b0e57b0f7 resolver selection for non-configure Windows builds, default is threaded DNS 2010-01-26 12:13:39 +00:00
Yang Tse
1d86ebfc88 add curl_threads.c to non-configure target build files 2010-01-26 09:20:09 +00:00
Yang Tse
a9b860765d onstantine Sapuntzakis threaded resolver enhancements 2010-01-26 08:43:21 +00:00
Yang Tse
483ff1ca75 Constantine Sapuntzakis threaded resolver enhancements 2010-01-25 23:50:13 +00:00
Yang Tse
c054b8bfa7 Constantine Sapuntzakis provided initial thread abstraction layer 2010-01-25 23:46:27 +00:00
Yang Tse
340ab2f87f make Curl_handler_*_proxy definition static 2010-01-25 23:41:02 +00:00
Dan Fandrich
f8b16e5ccb Updated minimum library sizes 2010-01-25 23:28:09 +00:00
Yang Tse
4bb80cfd75 fix compiler warning 2010-01-25 04:36:13 +00:00
Daniel Stenberg
de2cc11a73 Julien Chaffraix corrected bad #elif lines to silence warnings 2010-01-24 22:44:10 +00:00
Yang Tse
c656098ee0 HAVE_GETADDRINFO_THREADSAFE definition for non-configure win32 builds 2010-01-24 01:13:47 +00:00
Bjorn Stenberg
94f33457d3 Mention -J change 2010-01-23 20:14:39 +00:00
Bjorn Stenberg
80675818e0 Added -J/--remote-header-name. 2010-01-23 20:07:12 +00:00
Daniel Stenberg
b0e2d47a3e "remove progress meter from libcurl" at next API break 2010-01-23 20:02:50 +00:00
Yang Tse
0abd928d3d add inclusion of curl_memory.h 2010-01-23 17:31:54 +00:00
Yang Tse
597ad5a2ce adjust preprocessor symbol definition check relative to resolver specialty 2010-01-23 13:53:33 +00:00
Yang Tse
703fa98a48 PKTSIZE might have been already defined in arpa/tftp.h 2010-01-23 13:51:53 +00:00
Dan Fandrich
ec4647c0f9 Include "curl_memory.h" to get the strdup replacement when necessary 2010-01-23 10:04:04 +00:00
Daniel Stenberg
33ce0ec1f1 wrap long lines and do some indent policing 2010-01-22 23:21:39 +00:00
Yang Tse
1435864030 Definitions of resolver specialty compile-time defines CURLRES_* moved
from hostip.h to setup.h in order to allow proper inclusion in any file.

This represents no functional change at all in which resolver is used,
everything still works as usual, internally and externally there is no
difference in behavior.
2010-01-22 20:27:48 +00:00
Yang Tse
4a8a731476 adjust rtsp protocol support in curl-config and libcurl.pc when http is disabled 2010-01-22 16:38:32 +00:00
Yang Tse
6636fbf238 deal with the possibility that CURL_DISABLE_RTSP may already be defined 2010-01-22 15:15:08 +00:00
Yang Tse
c94d44505f fix compiler warning: statement is unreachable 2010-01-22 14:21:28 +00:00
Yang Tse
0032ce762e fix compilation when http is disabled 2010-01-22 14:20:56 +00:00
Yang Tse
bdb338b3c7 disabling of rtsp when http isn't enabled required here for non-configure systems 2010-01-22 14:20:08 +00:00
Daniel Stenberg
099eed7bf1 wrap long lines, remove (very old) attribution from code 2010-01-22 13:52:35 +00:00
Daniel Stenberg
bc253a4d5f cleanups by Julien Chaffraix 2010-01-22 13:14:51 +00:00
Daniel Stenberg
a771fb0d41 alphabetically sort the list of supported protocols 2010-01-22 13:06:50 +00:00
Daniel Stenberg
c047fe8e90 In spite claiming to tbe disabled by default, RTSP is enabled and it now
also says so. I also made the list of protocols get sorted.
2010-01-22 12:52:35 +00:00
Daniel Stenberg
e45eefcb90 expanded to provide info about the newer protocols too 2010-01-22 12:27:38 +00:00
Daniel Stenberg
844c19cc5b s/RTPFUNCTION/INTERLEAVEFUNCTION/
s/RTPDATA/INTERLEAVEDATA/
2010-01-22 12:17:03 +00:00
Daniel Stenberg
4a8570313a keep lines shorter than 80 columns, and reduce/remove the use of the word
'note' in most description as it is mostly useless.
2010-01-22 09:19:10 +00:00
Yang Tse
e59a5cbe4e Julien Chaffraix adjusted "<name> section" line length 2010-01-22 07:32:09 +00:00
Yang Tse
bfc4c33985 Constantine Sapuntzakis refactoring of async callbacks, allowing
removal of Curl_addrinfo_copy(), Curl_addrinfo6_callback(), and
Curl_addrinfo4_callback()
2010-01-22 06:36:52 +00:00
Dan Fandrich
5af20c70e4 Added rtsp.c to the non-configure target build files 2010-01-21 22:03:26 +00:00
Yang Tse
bd7430c1ee fix compiler warning 2010-01-21 19:27:32 +00:00
Yang Tse
6e5acc2fc1 make tftp_translate_code() static, it is only used from within tftp.c 2010-01-21 14:44:28 +00:00
Yang Tse
abe3e6b36c fix warning triggered when debugging on cygwin 2010-01-21 14:29:04 +00:00
Yang Tse
105e430641 allow exporting of exe_ext() sub 2010-01-21 14:26:32 +00:00
Yang Tse
4a349f7a54 improve displaylogcontent() sub fixing a warning 2010-01-21 14:25:41 +00:00
Daniel Stenberg
2f9a17fc44 remove typedef we ended up not using 2010-01-21 14:05:06 +00:00
Daniel Stenberg
bc4582b68a Chris Conroy brought support for RTSP transfers, and with it comes 8(!) new
libcurl options for controlling what to get and how to receive posssibly
interleaved RTP data. Initial commit.
2010-01-21 13:58:30 +00:00
Daniel Stenberg
e09718d457 Julien Chaffraix fixed line lengths 2010-01-21 12:28:29 +00:00
Daniel Stenberg
2c0418f154 Julien Chaffraix removed an old obsolete typedef 2010-01-21 11:48:48 +00:00
Daniel Stenberg
a74e885bef Yun Fu pointed out a flaw in the loop that checks handles, and I indented
the code more curl-style
2010-01-21 09:53:30 +00:00
Daniel Stenberg
6291a1cf23 "5.3 Sort outgoing cookies" removed, we now sort them 2010-01-21 09:32:51 +00:00
Yang Tse
a872ff742c SIGTERM is the signal to trap here, SIGKILL can't be caught. 2010-01-20 21:16:32 +00:00
Yang Tse
58a1557088 Use killsockfilters() to kill sockfilter processes, this ensures that when
killing a sockfilter process the actual PID from the pid file is used and
not the one returned by open2() which might be different.
2010-01-20 20:42:21 +00:00
Yang Tse
422a7869be Allow killsockfilters() to take a 5th optional parameter that when provided
indicates that only one of the two possible sockfilter processes should be
killed.  Valid values for this parameter are 'main' and 'data'.
2010-01-20 20:39:56 +00:00
Yang Tse
471e8eefb6 Use delete() to unset environment variables instead of assigning undef which
generates warning 'Use of uninitialized value in scalar assignment' with perl
versions older than 5.10
2010-01-20 20:08:50 +00:00
Yang Tse
d2e1ec58f2 Adjust valgrind logs file name detection.
Adjust environment vars setting and restoring from test definition.

Avoid using strftime in torture sub.
2010-01-20 18:31:52 +00:00
Daniel Stenberg
48032c0880 modified test case 8 to also make sure that we deal with cookies using
identical names but different paths properly
2010-01-20 09:39:40 +00:00
Daniel Stenberg
877dad1e24 - As was pointed out on the http-state mailing list, the order of cookies in a
HTTP Cookie: header _needs_ to be sorted on the path length in the cases
  where two cookies using the same name are set more than once using
  (overlapping) paths. Realizing this, identically named cookies must be
  sorted correctly. But detecting only identically named cookies and take care
  of them individually is harder than just to blindly and unconditionally sort
  all cookies based on their path lengths. All major browsers also already do
  this, so this makes our behavior one step closer to them in the cookie area.

  Test case 8 was the only one that broke due to this change and I updated it
  accordingly.
2010-01-19 23:19:59 +00:00
Daniel Stenberg
01030e9240 oops, I forgot to cvs add this before my previous commit (Dan Fandrich
pointed it out to me)
2010-01-19 22:22:54 +00:00
Daniel Stenberg
a5ca3f1754 - David McCreedy brought a fix and a new test case (129) to make libcurl work
again when downloading files over FTP using ASCII and it turns out that the
  final size of the file is not the same as the initial size the server
  reported. This is very common since servers don't take the newline
  conversions into account.
2010-01-19 21:39:10 +00:00
Daniel Stenberg
77a17a21d1 "260 - IMAP, POP3 and SMTP support" done! 2010-01-19 21:29:29 +00:00
Daniel Stenberg
6035a4b044 avoid "Use of uninitialized value $l in concatenation" 2010-01-19 21:20:24 +00:00
Yang Tse
469d3ed591 Fail harder when curl coredumps trying to verify http and ftp servers.
Add some debug messages to see what's going on with valgrind logs.
2010-01-19 17:40:15 +00:00
Yang Tse
3afe2b65b6 prevent %runcert hash growth when clearing items 2010-01-19 02:01:01 +00:00
Yang Tse
afdc3d81e9 update copyright year notice 2010-01-19 01:30:07 +00:00
Yang Tse
ccfe279117 Constantine Sapuntzakis enhancements to make memory tracking log file writing
of messages atomic, on systems where an fwrite of a memory buffer is atomic.
2010-01-18 20:22:04 +00:00
Dan Fandrich
5b5ff41ef1 Added PEM certificate keyword 2010-01-18 20:20:07 +00:00
Yang Tse
0a713139f6 fix warnings 2010-01-18 17:47:01 +00:00
Yang Tse
0687bc6bd6 Stop ssl running server when cert file currently used by server is
different than the one specified in test definition for same server
2010-01-18 17:03:59 +00:00
Yang Tse
424a8882fb fix warnings 2010-01-18 14:49:31 +00:00
Yang Tse
3fdced357b - Remove QD restarting of https servers. Proper fixing required.
This will make tests 310 311 and 312 fail while fixing.

- Remove some debug messages
2010-01-18 02:53:25 +00:00
Yang Tse
ce2ac665e4 make verifyhttp use different file names depending on server characteristics 2010-01-18 02:36:39 +00:00
Yang Tse
0375f70b5c add serverfactors() sub which returns server characterization factors 2010-01-18 02:32:48 +00:00
Yang Tse
7f8980114b fix warnings 2010-01-17 20:28:07 +00:00
Yang Tse
312494f25f fix warnings 2010-01-17 14:47:30 +00:00
Yang Tse
8d97b33347 fix warnings 2010-01-17 14:31:13 +00:00
Yang Tse
b51b703a5b add some debug messages 2010-01-17 13:33:27 +00:00
Yang Tse
071c38988d use servername_id() from serverhelp.pm 2010-01-17 02:50:48 +00:00
Yang Tse
365e75a270 refactored stopping of test harness servers 2010-01-17 02:45:24 +00:00
Yang Tse
b992928f3d Store now this file in CVS with unix line endings.
maketgz already converts this file to DOS style with an awk filter.
2010-01-15 20:23:35 +00:00
Yang Tse
32413a8e34 Declaration of $sshdlog is done in sshhelp.pm 2010-01-15 20:14:37 +00:00
Yang Tse
ada2774ab2 Start using the centralized pidfile and logfile name generation
subroutines for ssh and socks test suite servers.
2010-01-15 18:55:01 +00:00
Dan Fandrich
a644af129e Added the new protocol source files to the non-autoconf build files 2010-01-15 06:33:46 +00:00
Yang Tse
7624527591 Squeeze slack time when killing more than one server from
the <killserver> section of test harness definition files.
2010-01-14 17:36:57 +00:00
Kamil Dudka
383bf1e476 - Suppressed side effect of OpenSSL configure checks, which prevented NSS from
being properly detected under certain circumstances. It had been caused by
  strange behavior of pkg-config when handling PKG_CONFIG_LIBDIR. pkg-config
  distinguishes among empty and non-existent environment variable in that case.
2010-01-14 01:37:55 +00:00
Yang Tse
8c8df3966b Give the test a bit mote time to run so it passes on slow machines 2010-01-13 01:21:40 +00:00
Kamil Dudka
4344215309 remove trailing spaces from configure.ac 2010-01-13 01:13:23 +00:00
Yang Tse
0643829444 Added test case #1112 which does an FTPS download with strict timeout
and slow data transfer in a similar way as test case #1086 does for FTP.

This also exercises <killserver> section for the FTPS server.
2010-01-12 22:29:18 +00:00
Yang Tse
7525670610 Make runtests.pl actually support any (valid) server specification
for the <killserver> section of test harness definition files.
2010-01-12 22:22:55 +00:00
Yang Tse
b32a96eda0 Fix tftp and sftp supported protocols in servername_str() 2010-01-12 22:11:13 +00:00
Yang Tse
82f5ffff8f Make sockfilter kill messages look alike server ones 2010-01-12 14:01:44 +00:00
Yang Tse
3fd67b5f36 Adjust vor VPATH builds 2010-01-12 03:01:00 +00:00
Daniel Stenberg
1647d64a4b - Gil Weber reported a peculiar flaw with the multi interface when doing SFTP
transfers: curl_multi_fdset() would return -1 and not set and file
  descriptors several times during a transfer of a single file. It turned out
  to be due to two different flaws now fixed. Gil's excellent recipe helped me
  nail this.
2010-01-11 23:15:10 +00:00
Daniel Stenberg
d17416190b ssh_statemach_act() is now modified to loop over the switch() to perform as
much as possible in one go, as long as it doesn't block and hasn't reached the
end of the state machine.
This avoids spurious -1 returns from curl_multi_fdset() simply because
previously it would return from this function without anything in EWOUDLBLOCK
and thus basically it wasn't actually waiting for anything!!
2010-01-11 23:10:53 +00:00
Daniel Stenberg
2158e234aa After the TCP connect is confirmed in CURLM_STATE_WAITCONNECT and it changes
state, we return CURLM_CALL_MULTI_PERFORM unconditionally then so that we
can act faster like in the case the protocol-specific connect doesn't block
on anything and we can just persue on the next action immediately. It also
then avoids a case where curl_multi_fdset() would return -1.
2010-01-11 23:05:35 +00:00
Daniel Stenberg
cb348a5b1f progress callback called repeatedly during slow connects 2010-01-11 21:38:35 +00:00
Daniel Stenberg
377b2db05b - Made sure that the progress callback is repeatedly called at a regular
interval even during very slow connects.
2010-01-11 21:38:13 +00:00
Daniel Stenberg
78b7d7f7a8 - The tests/runtests.pl script now checks to see if the test case that runs is
present in the tests/data/Makefile.am and outputs a notice message on the
  screen if not. Each test file has to be included in that Makefile.am to get
  included in release archives and forgetting to add files there is a common
  mistake. This is an attempt to make it harder to forget.
2010-01-11 15:50:30 +00:00
Yang Tse
5bec1b1cf0 secureserver.pl is now the test harness script used for SSL/TLS. 2010-01-11 04:51:14 +00:00
Yang Tse
cd7b12edff secureserver.pl is now the test harness script used for SSL/TLS.
Start using the centralized pidfile and logfile name generation
subroutines for https and ftps test suite servers.
2010-01-11 04:49:13 +00:00
Yang Tse
1103d0c718 Update error message to include port number 2010-01-10 04:24:46 +00:00
Yang Tse
aae97c998a Previous commit adjustments 2010-01-10 02:41:44 +00:00
Yang Tse
017c14cc99 Start using the centralized pidfile and logfile name generation
subroutines for ftp, pop3, imap and smtp test suite servers.
2010-01-09 18:35:59 +00:00
Daniel Stenberg
b90703f594 struct Curl_sh_entry's 'inuse' member was no longer used and is now removed 2010-01-09 00:03:33 +00:00
Daniel Stenberg
552c3de357 - Johan van Selst found and fixed a OpenSSL session ref count leak:
ossl_connect_step3() increments an SSL session handle reference counter on
  each call. When sessions are re-used this reference counter may be
  incremented many times, but it will be decremented only once when done (by
  Curl_ossl_session_free()); and the internal OpenSSL data will not be freed
  if this reference count remains positive. When a session is re-used the
  reference counter should be corrected by explicitly calling
  SSL_SESSION_free() after each consecutive SSL_get1_session() to avoid
  introducing a memory leak.

  (http://curl.haxx.se/bug/view.cgi?id=2926284)
2010-01-08 23:45:23 +00:00
Yang Tse
aa2f447400 Start using the centralized pidfile and logfile name generation
subroutines for http and tftp test suite servers.
2010-01-08 15:54:07 +00:00
Yang Tse
184f92d243 Remove extra line feed 2010-01-08 12:01:35 +00:00
Yang Tse
a1d701d05a Use '_stunnel.log' ending also for https test server log 2010-01-08 01:54:29 +00:00
Yang Tse
a114b7b1c0 sws and tftpd command line option naming adjustments 2010-01-08 01:48:54 +00:00
Daniel Stenberg
8524c04ca9 removed a parameter from the Curl_http_readwrite_headers() prototype to remove
the need for the struct forward declaration from http.h which caused problems
with gcc 2.96 and quite frankly the parameter wasn't necessary anyway
2010-01-07 22:48:28 +00:00
Claes Jakobsson
31630203b1 List fragment tests in Makefile.am and better provide better names 2010-01-07 14:44:04 +00:00
Daniel Stenberg
d37a9c4f87 removed Curl_http_header_append() prototype as it isn't used anymore, the
function was moved to http.c and was made static and renamed
2010-01-07 14:02:05 +00:00
Daniel Stenberg
88944eb13a - Make sure the progress callback is called repeatedly even during very slow
name resolves when c-ares is used for resolving.
2010-01-06 23:04:17 +00:00
Yang Tse
bd8096b42b Disable tests 802 and 803 2010-01-06 18:28:15 +00:00
Yang Tse
1e87e4bb4e Prevent detection of stdint.h on IRIX systems, even when available.
IRIX MIPSpro 7.4 C++ compiler does not tolerate inclusion of stdint.h
2010-01-06 18:25:10 +00:00
Claes Jakobsson
9bd03483ce Julien Chaffraix fixed so that the fragment part in an URL is not sent to the server anymore 2010-01-06 16:01:48 +00:00
Daniel Stenberg
2e83006603 use the modern name for this option 2010-01-04 18:43:29 +00:00
Kamil Dudka
fd903eb6be - Julien Chaffraix eliminated a duplicated initialization in singlesocket(). 2010-01-03 13:46:37 +00:00
Daniel Stenberg
2c93ec5303 - Make curl support --ssl and --ssl-reqd instead of the previous FTP-specific
versions --ftp-ssl and --ftp-ssl-reqd as these options are now used to
  control SSL/TLS for IMAP, POP3 and SMTP as well in addition to FTP. The old
  option names are still working but the new ones are the prefered ones
  (listed and documented).
2010-01-02 22:09:31 +00:00
Daniel Stenberg
d79b5a0613 stop at once if the EOB marker shows up, even if something else might get
sent afterwards
2010-01-01 19:49:44 +00:00
Daniel Stenberg
a62f32d3c2 update copyright year since we are in 2010 now 2010-01-01 14:52:50 +00:00
Daniel Stenberg
241c0ad5bd added CURLOPT_FTP_USE_PRET 2010-01-01 14:52:12 +00:00
Daniel Stenberg
605bbfc4c0 - Ingmar Runge enhanced libcurl's FTP engine to support the PRET command. This
command is a special "hack" used by the drftpd server, but even though it is
  a custom extension I've deemed it fine to add to libcurl since this server
  seems to survive and people keep using it and want libcurl to support
  it. The new libcurl option is named CURLOPT_FTP_USE_PRET, and it is also
  usable from the curl tool with --ftp-pret. Using this option on a server
  that doesn't support this command will make libcurl fail.
2010-01-01 14:44:44 +00:00
Daniel Stenberg
42d365f199 added descriptions for CURLOPT_MAIL_FROM and CURLOPT_MAIL_RCPT 2009-12-31 22:38:10 +00:00
Daniel Stenberg
31266ca92a --mail-rcpt and --mail-from are starting to settle and work like this... 2009-12-31 21:59:50 +00:00
Daniel Stenberg
3f3f6be825 turned CURLOPT_MAIL_RCPT into a curl_slist list instead to support multiple
receivers, and made the command line tool thus support the option specified
many times
2009-12-31 21:52:01 +00:00
Yang Tse
01682cca55 Use '_stunnel.log' file name ending for stunneled server logs 2009-12-31 15:26:16 +00:00
Yang Tse
99a5a5a3e9 VMS adjustments by Steven M. Schweda 2009-12-31 13:35:24 +00:00
Yang Tse
eb0479575a Subs for refactoring purposes 2009-12-31 02:29:55 +00:00
Daniel Stenberg
97141d08f7 CURLOPT_HEADERDATA was added in 7.10 2009-12-30 23:14:30 +00:00
Daniel Stenberg
99e9938617 s/CURLOPT_WRITEHEADER/CURLOPT_HEADERDATA simply because it is a better name 2009-12-30 23:14:00 +00:00
Daniel Stenberg
6c6dc3f879 modified to get the EHLO domain from the path part of the URL instead of the
user name
2009-12-30 22:50:42 +00:00
Daniel Stenberg
a1311e5a24 moved the SMTP payload escape function into Curl_smtp_escape_eob and put
it in smtp.c
2009-12-30 22:09:43 +00:00
Daniel Stenberg
5e6ffe353a (SMTP) support DATA better in the server and make sure to "escape" CRLF.CRLF
sequences in uploaded data. The test server doesn't "decode" escaped dot-lines
but instead test cases must be written to take them into account. Added test
case 803 to verify dot-escaping.
2009-12-30 21:52:27 +00:00
Yang Tse
d7cd761047 Oops, should have removed 'not' in previous commit. 2009-12-30 19:43:12 +00:00
Yang Tse
05488d63d0 VMS build system enhancements by Steven M. Schweda and Craig A. Berry 2009-12-30 19:37:53 +00:00
Yang Tse
3184a91ec8 VMS specific preprocessor symbol checking adjustments 2009-12-30 17:59:56 +00:00
Yang Tse
0dde9056d7 VMS specific preprocessor symbol definition adjustments 2009-12-30 17:59:10 +00:00
Yang Tse
a487c80535 Replaced stricmp() usage with our portable strequal() 2009-12-30 15:47:23 +00:00
Daniel Stenberg
1e9a946e6d move HTTP-specific functions to http.c where they belong 2009-12-29 21:45:02 +00:00
Daniel Stenberg
7cd5ffc1bf test 802 is the first SMTP test, although not strictly SMTP yet... 2009-12-29 21:28:53 +00:00
Yang Tse
fa6631edd5 Mention last changes 2009-12-29 02:32:12 +00:00
Yang Tse
e70c0913b1 - Fix configure_socket() to use ares_socket_t instead of int data type. 2009-12-29 02:04:17 +00:00
Yang Tse
5b2a31ae41 - Where run-time error checks enabling compiler option /GZ was used it is now
replaced with equivalent /RTCsu for Visual Studio 2003 and newer versions.

- Compiler option /GX is now replaced with equivalent /EHsc for all versions.
2009-12-29 01:51:57 +00:00
Yang Tse
c796f2646e Leftover from previous commit 2009-12-28 20:10:00 +00:00
Yang Tse
d0f6bde732 Initial refactoring step for server name strings centralized generation 2009-12-28 20:00:41 +00:00
Daniel Stenberg
1bd5784a13 Julien Chaffraix's clarifications 2009-12-27 20:54:26 +00:00
Yang Tse
1f7d9f4f7b Adjust FreeBSD version check to follow FreeBSD Porter's Handbook
http://www.freebsd.org/doc/en/books/porters-handbook/porting-versions.html
2009-12-27 02:31:29 +00:00
Daniel Stenberg
b6ac8d62a1 symbols added in the CVS version meant for 7.20.0 2009-12-26 18:42:25 +00:00
Yang Tse
4ec17a08bc global variables reordering/refactoring/commenting 2009-12-26 18:32:19 +00:00
Daniel Stenberg
aefe0299e0 add pointer to the bug report 2009-12-25 23:35:16 +00:00
Daniel Stenberg
b89789d82f - Renato Botelho and Peter Pentchev brought a patch that makes the libcurl
headers work correctly even on FreeBSD systems before v8.
2009-12-25 23:32:01 +00:00
Daniel Stenberg
a218235964 first shot at actually doing the SMTP upload as well, not doing the proper
end-of-body treatment
2009-12-25 22:50:11 +00:00
Daniel Stenberg
73ad32e125 When verifying the SMTP server I had to add some hackery since SMTP in itself
doesn't really return any body data to check so I made SMTP check "headers"
as well.
2009-12-25 22:21:46 +00:00
Daniel Stenberg
77625f8560 first basic SMTP support 2009-12-25 22:20:37 +00:00
Yang Tse
1af64730e0 Adjust test number mismatch 2009-12-24 12:04:33 +00:00
Yang Tse
eacf62792f Enable warnings 2009-12-24 12:01:53 +00:00
Yang Tse
6ce407305b Fix warnings 2009-12-24 12:00:43 +00:00
Yang Tse
ae3892e8ab Fix warnings 2009-12-23 18:46:55 +00:00
Yang Tse
c74875d94e Back out some pingpong server stopping changes introduced last week in
order to re-use 'classic' stopping and allow taking test-suite run time
references from this state.
2009-12-23 15:20:20 +00:00
Yang Tse
271dc9c582 use Time::HiRes whenever available, independently of perl version 2009-12-22 13:46:06 +00:00
Yang Tse
7bede9180d log a message when continuing once sleep time is over 2009-12-22 13:45:01 +00:00
Yang Tse
f0917cabb5 - Ingmar Runge noticed that Windows config-win32.h configuration file
did not include a definition for HAVE_CLOSESOCKET which resulted in
  function close() being inappropriately used to close sockets.
2009-12-21 16:55:39 +00:00
Yang Tse
96395a908a Make 'classic' output end of a test-suite run become again the end
of output, even when run time statistics are shown.
2009-12-21 15:50:24 +00:00
Yang Tse
e9a993b9e9 Move stopping of servers instructed by test definition, after the removal of
server logs advisor read lock and before test results verifications are done.

When stopping a pingpong server, stop server before its slaves.
2009-12-21 14:53:07 +00:00
Daniel Stenberg
982fe33924 test 566 was missing 2009-12-21 14:51:07 +00:00
Yang Tse
fa188eec7b dead_child_handler also takes care of reaping pingpong server dead child processes 2009-12-21 14:43:29 +00:00
Yang Tse
bdd3763980 Reap processes dead children ASAP without blocking 2009-12-21 14:36:01 +00:00
Yang Tse
1cfa52b67d Reinstate hi resolution time logging since this is not what is
now adding 90 extra seconds to the total time some autobuilds
need to make a full test-run.
2009-12-21 14:33:01 +00:00
Patrick Monnerat
57d3488a0d Take new SMTP definitions into account in OS400 wrapper and RPG binding 2009-12-21 12:26:48 +00:00
Daniel Stenberg
83d34a246e first small steps towards smtp 2009-12-21 08:33:47 +00:00
Yang Tse
76b3c9d70f Replaced tabs with spaces 2009-12-21 02:37:23 +00:00
Daniel Stenberg
d911e22d8f remove some unused code 2009-12-20 22:11:16 +00:00
Yang Tse
efd1d9dc04 Improve delay command interruptability 2009-12-20 22:09:53 +00:00
Daniel Stenberg
88a0060b2e revert that, we already had a function named like that! 2009-12-20 22:08:06 +00:00
Daniel Stenberg
4adf7d62d4 rename the verifyftp function to verifyserver since it is used to verify
a wide variety of protocol servers
2009-12-20 22:00:23 +00:00
Daniel Stenberg
6add5baa3a free the allocated mailbox name at disconnect 2009-12-20 11:10:08 +00:00
Daniel Stenberg
2a3dafc0cd introducing the first IMAP FETCH test 2009-12-20 11:07:04 +00:00
Yang Tse
f912f8d5d2 - Attempt to fix script compilation failure on versions older than 5.007003,
corelist -a Time::HiRes lists this as the first version released with it.

- Ensure ftp check delay timer is always an integral number.
2009-12-20 03:48:32 +00:00
Daniel Stenberg
af7a5b297f support IMAP select and LOGOUT 2009-12-19 23:23:26 +00:00
Daniel Stenberg
344bbcf259 fix the ftp check delay timer to never be set below 1 to work correctly
in cases like test 190
2009-12-19 23:10:33 +00:00
Daniel Stenberg
240fa29e94 fixed a precaution check in the cookie code, pointed out by Julien Chaffraix 2009-12-19 19:20:26 +00:00
Yang Tse
010fe5acd5 Slack time reduction 2009-12-19 13:20:07 +00:00
Yang Tse
aeec8e0b38 Added runtests.pl '-r' option for run time statistics 2009-12-19 04:15:22 +00:00
Yang Tse
2d15ac3d4e server start and verification time as well as test preparation time
data is required in order to closer match total test execution time.
2009-12-18 19:17:14 +00:00
Yang Tse
53deae3781 Added test harness simple time execution stats 2009-12-18 15:23:18 +00:00
Yang Tse
39cc424e81 Comment out hi resolution time logging to verify if this is what might
be contributing 90 additional seconds to the total time some autobuilds
now need to make a full test-run.
2009-12-17 22:28:40 +00:00
Yang Tse
4d0b0cae9e Fix compilation failure 2009-12-17 20:01:24 +00:00
Yang Tse
8343cb8910 Test harness process control enhancements 2009-12-17 19:37:01 +00:00
Daniel Stenberg
a75d9d9169 uh, assign the bool it points to properly 2009-12-17 16:07:02 +00:00
Daniel Stenberg
54c60d0067 Stop overloading the conn->protocol field with the PROT_MISSING bit. It
really didn't belong there and had no real point.
2009-12-17 16:03:39 +00:00
Daniel Stenberg
91d05903b4 Remove pointless storing of the protocol as a string within the connectdata
struct, and instead use the already stored string in the handler struct.
2009-12-17 15:45:04 +00:00
Daniel Stenberg
10a11e3abe - David Byron fixed Curl_ossl_cleanup to actually call ENGINE_cleanup when
available.
2009-12-17 13:29:41 +00:00
Yang Tse
414180b363 gettimeofday() requires perl version newer than 5.6 2009-12-17 03:50:32 +00:00
Daniel Stenberg
7603a29fc3 Follow-up fix for the proxy fix I did for Jon Nelson's bug. It turned out I
was a bit too quick and broke test case 1101 with that change. The order of
some of the setups is sensitive. I now changed it slightly again.
2009-12-16 23:11:47 +00:00
Yang Tse
002ed5f298 Test harness process control enhancements 2009-12-16 19:55:35 +00:00
Yang Tse
044ba6dad2 Test #1106 needs an ftp enabled client 2009-12-16 15:24:12 +00:00
Yang Tse
3802d027cd Test harness process control enhancements 2009-12-16 15:16:06 +00:00
Daniel Stenberg
3111701c38 - Jon Nelson found a regression that turned out to be a flaw in how libcurl
detects and uses proxies based on the environment variables. If the proxy
  was given as an explicit option it worked, but due to the setup order
  mistake proxies would not be used fine for a few protocols when picked up
  from '[protocol]_proxy'. Obviously this broke after 7.19.4. I now also added
  test case 1106 that verifies this functionality.

  (http://curl.haxx.se/bug/view.cgi?id=2913886)
2009-12-14 23:16:09 +00:00
Yang Tse
2c9644b812 Fix compiler warning 2009-12-14 16:05:57 +00:00
Yang Tse
99daca5a48 Prevent perl script dying messages in output, since tearing down the pinpong
server in this way, upon sysread failures, is part of the expected behavior.
2009-12-14 15:39:15 +00:00
Yang Tse
a6abbb120e Adjust uppercase protocol string usage 2009-12-14 14:42:48 +00:00
Yang Tse
b0f548fb56 Fix compiler warnings 2009-12-14 14:02:43 +00:00
Yang Tse
364d76aca7 Fix compiler warnings 2009-12-14 13:27:50 +00:00
Yang Tse
6e9a484ea6 signal handling to cleanup on SIGINT and SIGTERM, followup 2009-12-13 03:45:32 +00:00
Yang Tse
303f74c740 reapply diff between revisions 1.103 and 1.102 2009-12-13 03:44:45 +00:00
Daniel Stenberg
4ea8ad584b updated with the new protocols 2009-12-12 22:48:11 +00:00
Daniel Stenberg
19b8a80ee9 might as well output all supported protocols at the end of configure to
make it more obvious how the output will be
2009-12-12 22:39:29 +00:00
Daniel Stenberg
30eb452adf show POP3S, IMAPS and SMTPS as protocols if SSL is enabled 2009-12-12 22:33:18 +00:00
Daniel Stenberg
92b9b46831 support disabling POP3, IMAP and SMTP and now they also appear in curl-config
--protocols output
2009-12-12 22:31:00 +00:00
Daniel Stenberg
83a6b34803 split out more protocol-specific structs from urldata.h into their own
protocol-specific header files
2009-12-12 22:17:51 +00:00
Daniel Stenberg
43fefab2a1 IMAP, POP3 and SMTP support 2009-12-12 22:05:11 +00:00
Daniel Stenberg
ec3bb8f727 introducing IMAP, POP3 and SMTP support (still lots of polish left to do) 2009-12-12 21:54:01 +00:00
Yang Tse
463d2d395c Prevent rewinding unless pipelining.
See http://curl.haxx.se/mail/lib-2009-12/0107.html
2009-12-11 18:41:29 +00:00
Yang Tse
2fc1752d6e Removed function prototype without implementation 2009-12-11 02:14:11 +00:00
Daniel Stenberg
296ebf382c - Siegfried Gyuricsko found out that the curl manual said --retry would retry
on FTP errors in the transient 5xx range. Transient FTP errors are in the
  4xx range. The code itself only tried on 5xx errors that occured _at login_.
  Now the retry code retries on all FTP transfer failures that ended with a
  4xx response.

  (http://curl.haxx.se/bug/view.cgi?id=2911279)
2009-12-10 21:02:11 +00:00
Daniel Stenberg
b91ed67276 argh, use the correct bug id 2009-12-10 20:26:44 +00:00
Daniel Stenberg
315253b367 - Constantine Sapuntzakis figured out a case which would lead to libcurl
accessing alredy freed memory and thus crash when using HTTPS (with
  OpenSSL), multi interface and the CURLOPT_DEBUGFUNCTION and a certain order
  of cleaning things up. I fixed it.

  (http://curl.haxx.se/bug/view.cgi?id=2891591)
2009-12-10 20:20:15 +00:00
Daniel Stenberg
3b1de97eaa minor indent change 2009-12-10 20:19:56 +00:00
Yang Tse
5ce6454d33 - Fixed curl erroneously reporting output stream write failures with disabled buffering 2009-12-10 16:46:21 +00:00
Yang Tse
0653fa107f signal handling to cleanup on SIGINT and SIGTERM, followup 2009-12-09 18:41:43 +00:00
Daniel Stenberg
ebe5339003 - Martin Storsjo made libcurl use the Expect: 100-continue header for posts
with unknown size. Previously it was only used for posts with a known size
  larger than 1024 bytes.
2009-12-07 20:25:17 +00:00
Daniel Stenberg
95362af43c 74. The HTTP spec allows headers to be merged and become comma-separated
instead of being repeated several times. This also include Authenticate: and
  Proxy-Authenticate: headers and while this hardly every happens in real life
  it will confuse libcurl which does not properly support it for all headers -
  like those Authenticate headers.
2009-12-04 21:52:58 +00:00
Yang Tse
d14bf09ab8 Fix 'uploaded' file descriptor leak 2009-12-03 20:37:49 +00:00
Yang Tse
636d2fe00a signal handling to cleanup on SIGINT and SIGTERM 2009-12-03 13:12:04 +00:00
Kamil Dudka
fb2425b147 lib/nss.c: avoid use of uninitialized value 2009-12-02 17:24:38 +00:00
Yang Tse
2286f566d0 signal handling to cleanup on SIGINT and SIGTERM 2009-12-02 15:02:30 +00:00
Yang Tse
ed2aa87e63 Set socket option SO_REUSEADDR=true on stunnel accept'ing port 2009-12-01 15:36:34 +00:00
Daniel Stenberg
f0826974f2 - If the Expect: 100-continue header has been set by the application through
curl_easy_setopt with CURLOPT_HTTPHEADER, the library should set
  data->state.expect100header accordingly - the current code (in 7.19.7 at
  least) doesn't handle this properly. Martin Storsjo provided the fix!
2009-12-01 12:04:54 +00:00
Daniel Stenberg
d61690ef46 start working on 1.7.1 2009-11-30 22:39:04 +00:00
Yang Tse
a72ce23f16 - In order to better reflect that the returned pid is extracted from the
given file, serverpid sub is renamed to pidfromfile. In addition it is
  enhanced to make sure that it always returns zero unless a numerical
  positive value is returned.

- To better reflect that only process existance is actually checked,
  checkserver sub is renamed to processexists. In addition it is enhanced
  making it remove the given pid file when the extracted pid is no longer
  alive.
2009-11-30 13:48:51 +00:00
Daniel Stenberg
bfae1bd999 #71 "TFTP block size / better integration in transfer" is now expected to
have been fixed!
2009-11-29 23:14:56 +00:00
Daniel Stenberg
8a7231d7ae a binding for Falcon 2009-11-29 19:12:00 +00:00
Yang Tse
4d922545d5 - Added Diffie-Hellman parameters to several test harness certificate files in
PEM format. Required by several stunnel versions used by our test harness.
2009-11-28 10:01:21 +00:00
Yang Tse
1fc32d866a Use different log files for each protocol 2009-11-28 05:06:19 +00:00
Yang Tse
230dc699e2 s/socklen_t/curl_socklen_t/g 2009-11-28 04:34:46 +00:00
Yang Tse
3f6854272f Fix compiler warning: unused variable `data' 2009-11-28 03:00:32 +00:00
Daniel Stenberg
448f6684bb 7.20.0 is the planned next version number 2009-11-27 23:53:50 +00:00
Daniel Stenberg
af06a0e497 document --tftp-blksize 2009-11-27 23:51:05 +00:00
Daniel Stenberg
6e38cc9048 - Markus Koetter provided a polished and updated version of Chad Monroe's TFTP
rework patch that now integrates TFTP properly into libcurl so that it can
  be used non-blocking with the multi interface and more. BLKSIZE also works.

  The --tftp-blksize option was added to allow setting the TFTP BLKSIZE from
  the command line.
2009-11-27 23:46:29 +00:00
Yang Tse
a240f4d1df Attempt to enhance stunnel 3.X logging 2009-11-27 19:52:56 +00:00
Yang Tse
6f273b1a5f Prevent running stunnel unless its version can be determined. 2009-11-27 13:01:10 +00:00
Yang Tse
f07f17f2a4 Log sws IPv version, port and pid when exiting due to SIGINT or SIGTERM. 2009-11-27 12:01:25 +00:00
Yang Tse
c713627412 To allow remote log inspection avoid redirecting messages to stderr.
Set 0600 file permissions on certificate pem files.
2009-11-27 12:00:53 +00:00
248 changed files with 20438 additions and 7079 deletions

299
CHANGES
View File

@@ -6,13 +6,297 @@
Changelog
Version 7.20.0 (9 February 2010)
Daniel Stenberg (9 Feb 2010)
- When downloading compressed content over HTTP and the app asked libcurl to
automatically uncompress it with the CURLOPT_ENCODING option, libcurl could
wrongly provide the callback with more data than the maximum documented
amount. An application could thus get tricked into badness if the maximum
limit was trusted to be enforced by libcurl itself (as it is documented).
This is further detailed and explained in the libcurl security advisory
20100209 at
http://curl.haxx.se/docs/adv_20100209.html
Daniel Fandrich (3 Feb 2010)
- Changed the Watcom makefiles to make them easier to keep in sync with
Makefile.inc since that can't be included directly.
Yang Tse (2 Feb 2010)
- Symbol CURL_FORMAT_OFF_T now obsoleted, will be removed in a future release,
symbol will not be available when building with CURL_NO_OLDIES defined. Use
of CURL_FORMAT_CURL_OFF_T is preferred since 7.19.0
Daniel Stenberg (1 Feb 2010)
- Using the multi_socket API, it turns out at times it seemed to "forget"
connections (which caused a hang). It turned out to be an existing (7.19.7)
bug in libcurl (that's been around for a long time) and it happened like
this:
The app calls curl_multi_add_handle() to add a new easy handle, libcurl will
then set it to timeout in 1 millisecond so libcurl will tell the app about
it.
The app's timeout fires off that there's a timeout, the app calls libcurl as
we so often document it:
do {
res = curl_multi_socket_action(... TIMEOUT ...);
} while(CURLM_CALL_MULTI_PERFORM == res);
And this is the problem number one:
When curl_multi_socket_action() is called with no specific handle, but only
a timeout-action, it will *only* perform actions within libcurl that are
marked to run at this time. In this case, the request would go from INIT to
CONNECT and return CURLM_CALL_MULTI_PERFORM. When the app then calls libcurl
again, there's no timer set for this handle so it remains in the CONNECT
state. The CONNECT state is a transitional state in libcurl so it reports no
sockets there, and thus libcurl never tells the app anything more about that
easy handle/connection.
libcurl _does_ set a 1ms timeout for the handle at the end of
multi_runsingle() if it returns CURLM_CALL_MULTI_PERFORM, but since the loop
is instant the new job is not ready to run at that point (and there's no
code that makes libcurl call the app to update the timout for this new
timeout). It will simply rely on that some other timeout will trigger later
on or that something else will update the timeout callback. This makes the
bug fairly hard to repeat.
The fix made to adress this issue:
We introduce a loop in lib/multi.c around all calls to multi_runsingle() and
simply check for CURLM_CALL_MULTI_PERFORM internally. This has the added
benefit that this goes in line with my long-term wishes to get rid of the
CURLM_CALL_MULTI_PERFORM all together from the public API.
The downside of this fix, is that the counter we return in 'running_handles'
in several of our public functions then gets a slightly new and possibly
confusing behavior during times:
If an app adds a handle that fails to connect (very quickly) it may just
as well never appear as a 'running_handle' with this fix. Previously it
would first bump the counter only to get it decreased again at next call.
Even I have used that change in handle counter to signal "end of a
transfer". The only *good* way to find the end of a individual transfer
is calling curl_multi_info_read() to see if it returns one.
Of course, if the app previously did the looping before it checked the
counter, it really shouldn't be any new effect.
Yang Tse (26 Jan 2010)
- Constantine Sapuntzakis' and Joshua Kwan's work done in the last four months
relative to the asynchronous DNS lookups, along with with some integration
adjustments I have done are finally committed to CVS.
Currently these enhancements will benefit builds done using c-ares on any
platform as well as Windows builds using the default threaded resolver.
This release does not make generally available POSIX threaded DNS lookups
yet. There is no configure option to enable this feature yet. It is possible
to experimantally try this feature running configure with compiler flags that
make simultaneous definition of preprocessor symbols USE_THREADS_POSIX and
HAVE_PTHREAD_H, as well as whatever reentrancy compiler flags and linker ones
are required to link and properly use pthread_* functions on each platform.
Daniel Stenberg (26 Jan 2010)
- Mike Crowe made libcurl return CURLE_COULDNT_RESOLVE_PROXY when it is the
proxy that cannot be resolved when using c-ares. This matches the behaviour
when not using c-ares.
Bj<EFBFBD>rn Stenberg (23 Jan 2010)
- Added a new flag: -J/--remote-header-name. This option tells the
-O/--remote-name option to use the server-specified Content-Disposition
filename instead of extracting a filename from the URL.
Daniel Stenberg (21 Jan 2010)
- Chris Conroy brought support for RTSP transfers, and with it comes 8(!) new
libcurl options for controlling what to get and how to receive posssibly
interleaved RTP data.
Daniel Stenberg (20 Jan 2010)
- As was pointed out on the http-state mailing list, the order of cookies in a
HTTP Cookie: header _needs_ to be sorted on the path length in the cases
where two cookies using the same name are set more than once using
(overlapping) paths. Realizing this, identically named cookies must be
sorted correctly. But detecting only identically named cookies and take care
of them individually is harder than just to blindly and unconditionally sort
all cookies based on their path lengths. All major browsers also already do
this, so this makes our behavior one step closer to them in the cookie area.
Test case 8 was the only one that broke due to this change and I updated it
accordingly.
Daniel Stenberg (19 Jan 2010)
- David McCreedy brought a fix and a new test case (129) to make libcurl work
again when downloading files over FTP using ASCII and it turns out that the
final size of the file is not the same as the initial size the server
reported. This is very common since servers don't take the newline
conversions into account.
Kamil Dudka (14 Jan 2010)
- Suppressed side effect of OpenSSL configure checks, which prevented NSS from
being properly detected under certain circumstances. It had been caused by
strange behavior of pkg-config when handling PKG_CONFIG_LIBDIR. pkg-config
distinguishes among empty and non-existent environment variable in that case.
Daniel Stenberg (12 Jan 2010)
- Gil Weber reported a peculiar flaw with the multi interface when doing SFTP
transfers: curl_multi_fdset() would return -1 and not set and file
descriptors several times during a transfer of a single file. It turned out
to be due to two different flaws now fixed. Gil's excellent recipe helped me
nail this.
Daniel Stenberg (11 Jan 2010)
- Made sure that the progress callback is repeatedly called at a regular
interval even during very slow connects.
- The tests/runtests.pl script now checks to see if the test case that runs is
present in the tests/data/Makefile.am and outputs a notice message on the
screen if not. Each test file has to be included in that Makefile.am to get
included in release archives and forgetting to add files there is a common
mistake. This is an attempt to make it harder to forget.
Daniel Stenberg (9 Jan 2010)
- Johan van Selst found and fixed a OpenSSL session ref count leak:
ossl_connect_step3() increments an SSL session handle reference counter on
each call. When sessions are re-used this reference counter may be
incremented many times, but it will be decremented only once when done (by
Curl_ossl_session_free()); and the internal OpenSSL data will not be freed
if this reference count remains positive. When a session is re-used the
reference counter should be corrected by explicitly calling
SSL_SESSION_free() after each consecutive SSL_get1_session() to avoid
introducing a memory leak.
(http://curl.haxx.se/bug/view.cgi?id=2926284)
Daniel Stenberg (7 Jan 2010)
- Make sure the progress callback is called repeatedly even during very slow
name resolves when c-ares is used for resolving.
Claes Jakobsson (6 Jan 2010)
- Julien Chaffraix fixed so that the fragment part in an URL is not sent
to the server anymore.
Kamil Dudka (3 Jan 2010)
- Julien Chaffraix eliminated a duplicated initialization in singlesocket().
Daniel Stenberg (2 Jan 2010)
- Make curl support --ssl and --ssl-reqd instead of the previous FTP-specific
versions --ftp-ssl and --ftp-ssl-reqd as these options are now used to
control SSL/TLS for IMAP, POP3 and SMTP as well in addition to FTP. The old
option names are still working but the new ones are the ones listed and
documented.
Daniel Stenberg (1 Jan 2010)
- Ingmar Runge enhanced libcurl's FTP engine to support the PRET command. This
command is a special "hack" used by the drftpd server, but even though it is
a custom extension I've deemed it fine to add to libcurl since this server
seems to survive and people keep using it and want libcurl to support
it. The new libcurl option is named CURLOPT_FTP_USE_PRET, and it is also
usable from the curl tool with --ftp-pret. Using this option on a server
that doesn't support this command will make libcurl fail.
I added test cases 1107 and 1108 to verify the functionality.
The PRET command is documented at
http://www.drftpd.org/index.php/Distributed_PASV
Yang Tse (30 Dec 2009)
- Steven M. Schweda improved VMS build system, and Craig A. Berry helped
with the patch and testing.
Daniel Stenberg (26 Dec 2009)
- Renato Botelho and Peter Pentchev brought a patch that makes the libcurl
headers work correctly even on FreeBSD systems before v8.
(http://curl.haxx.se/bug/view.cgi?id=2916915)
Daniel Stenberg (17 Dec 2009)
- David Byron fixed Curl_ossl_cleanup to actually call ENGINE_cleanup when
available.
- Follow-up fix for the proxy fix I did for Jon Nelson's bug. It turned out I
was a bit too quick and broke test case 1101 with that change. The order of
some of the setups is sensitive. I now changed it slightly again to make
sure we do them in this order:
1 - parse URL and figure out what protocol is used in the URL
2 - prepend protocol:// to URL if missing
3 - parse name+password off URL, which needs to know what protocol is used
(since only some allows for name+password in the URL)
4 - figure out if a proxy should be used set by an option
5 - if no proxy option, check proxy environment variables
6 - run the protocol-specific setup function, which needs to have the proxy
already set
Daniel Stenberg (15 Dec 2009)
- Jon Nelson found a regression that turned out to be a flaw in how libcurl
detects and uses proxies based on the environment variables. If the proxy
was given as an explicit option it worked, but due to the setup order
mistake proxies would not be used fine for a few protocols when picked up
from '[protocol]_proxy'. Obviously this broke after 7.19.4. I now also added
test case 1106 that verifies this functionality.
(http://curl.haxx.se/bug/view.cgi?id=2913886)
Daniel Stenberg (12 Dec 2009)
- IMAP, POP3 and SMTP support and their TLS versions (including IMAPS, POP3S
and SMTPS) are now supported. The current state may not yet be solid, but
the foundation is in place and the test suite has some initial support for
these protocols. Work will now persue to make them nice libcurl citizens
until release.
The work with supporting these new protocols was sponsored by
networking4all.com - thanks!
Daniel Stenberg (10 Dec 2009)
- Siegfried Gyuricsko found out that the curl manual said --retry would retry
on FTP errors in the transient 5xx range. Transient FTP errors are in the
4xx range. The code itself only tried on 5xx errors that occured _at login_.
Now the retry code retries on all FTP transfer failures that ended with a
4xx response.
(http://curl.haxx.se/bug/view.cgi?id=2911279)
- Constantine Sapuntzakis figured out a case which would lead to libcurl
accessing alredy freed memory and thus crash when using HTTPS (with
OpenSSL), multi interface and the CURLOPT_DEBUGFUNCTION and a certain order
of cleaning things up. I fixed it.
(http://curl.haxx.se/bug/view.cgi?id=2905220)
Daniel Stenberg (7 Dec 2009)
- Martin Storsjo made libcurl use the Expect: 100-continue header for posts
with unknown size. Previously it was only used for posts with a known size
larger than 1024 bytes.
Daniel Stenberg (1 Dec 2009)
- If the Expect: 100-continue header has been set by the application through
curl_easy_setopt with CURLOPT_HTTPHEADER, the library should set
data->state.expect100header accordingly - the current code (in 7.19.7 at
least) doesn't handle this properly. Martin Storsjo provided the fix!
Yang Tse (28 Nov 2009)
- Added Diffie-Hellman parameters to several test harness certificate files in
PEM format. Required by several stunnel versions used by our test harness.
Daniel Stenberg (28 Nov 2009)
- Markus Koetter provided a polished and updated version of Chad Monroe's TFTP
rework patch that now integrates TFTP properly into libcurl so that it can
be used non-blocking with the multi interface and more. BLKSIZE also works.
The --tftp-blksize option was added to allow setting the TFTP BLKSIZE from
the command line.
Daniel Stenberg (26 Nov 2009)
- Extended and fixed the change I did on Dec 11 for the the progress
meter/callback during FTP command/response sequences. It turned out it was
really lame before and now the progress meter SHOULD get called at least
once per second.
- Extended and fixed the change I did on Dec 11 for the the progress
meter/callback during FTP command/response sequences. It turned out it was
really lame before and now the progress meter SHOULD get called at least
once per second.
Daniel Stenberg (23 Nov 2009)
- Bjorn Augustsson reported a bug which made curl not report any problems even
@@ -70,6 +354,11 @@ Kamil Dudka (15 Nov 2009)
(and in particular the list of required libraries) even if a path is given
as argument to --with-ssl
Yang Tse (15 Nov 2009)
- I removed enable-thread / disable-thread configure option. These were only
placebo options. The library is always built as thread safe as possible on
every system.
Claes Jakobsson (14 Nov 2009)
- curl-config now accepts '--configure' to see what arguments was
passed to the configure script when building curl.
@@ -90,6 +379,8 @@ Yang Tse (14 Nov 2009)
- Constantine Sapuntzakis provided the fix that ensures that an SSL connection
won't be reused unless protection level for peer and host verification match.
I refactored how preprocessor symbol _THREAD_SAFE definition is done.
Kamil Dudka (12 Nov 2009)
- Kevin Baughman provided a fix preventing libcurl-NSS from crash on doubly
closed NSPR descriptor. The issue was hard to find, reported several times

View File

@@ -1,16 +1,27 @@
Curl and libcurl 7.19.8
Curl and libcurl 7.20.0
Public curl releases: 114
Command line options: 132
curl_easy_setopt() options: 163
Command line options: 136
curl_easy_setopt() options: 174
Public functions in libcurl: 58
Known libcurl bindings: 38
Known libcurl bindings: 39
Contributors: 761
This release includes the following changes:
o support SSL_FILETYPE_ENGINE for client certificate
o curl-config can now show the arguments used when building curl
o non-blocking TFTP
o send Expect: 100-continue for POSTs with unknown sizes
o added support for IMAP(S), POP3(S), SMTP(S) and RTSP
o added new curl_easy_setopt() options for SMTP and RTSP
o added --mail-from and --mail-rcpt for SMTP
o VMS build system enhancements
o added support for the PRET ftp command
o curl supports --ssl and --ssl-reqd
o added -J/--remote-header-name for using server-provided filename with -O
o enhanced asynchronous DNS lookups
o symbol CURL_FORMAT_OFF_T is obsoleted
This release includes the following bugfixes:
@@ -26,6 +37,23 @@ This release includes the following bugfixes:
o HTTP proxy tunnel re-used connection even if tunnel got disabled
o SSL lib post-close write
o curl failed to report write errors for tiny failed downloads
o TFTP BLKSIZE
o Expect: 100-continue handling when set by the application
o multi interface with OpenSSL read already freed memory when closing down
o --retry didn't do right for FTP transient errors
o some *_proxy environment variables didn't function
o libcurl-OpenSSL engine cleanup
o header include fix for FreeBSD versions before v8
o fragment part of URLs are no longer sent to the server
o progress callback called repeatedly with c-ares for resolving
o OpenSSL session id ref count leak
o progress callback called repeatedly during slow connects
o curl_multi_fdset() would return -1 too often during SCP/SFTP transfers
o FTP file size checks with ASCII transfers
o HTTP Cookie: headers sort cookies based on specified path lengths
o CURLM_CALL_MULTI_PERFORM fix for multi socket timeout calls
o libcurl data callback excessive length:
http://curl.haxx.se/docs/adv_20100209.html
This release includes the following known bugs:
@@ -36,6 +64,10 @@ advice from friends like these:
Yang Tse, Kamil Dudka, Christian Schmitz, Constantine Sapuntzakis,
Marco Maggi, Camille Moncelier, Claes Jakobsson, Kevin Baughman,
Marc Kleine-Budde, Jad Chamcham, Bjorn Augustsson, David Byron
Marc Kleine-Budde, Jad Chamcham, Bjorn Augustsson, David Byron,
Markus Koetter, Chad Monroe, Martin Storsjo, Siegfried Gyuricsko,
Jon Nelson, Julien Chaffraix, Renato Botelho, Peter Pentchev, Ingmar Runge,
Johan van Selst, Charles Kerr, Gil Weber, David McCreedy, Chris Conroy,
Bjorn Stenberg, Mike Crowe, Joshua Kwan, Daniel Fandrich, Wesley Miaw
Thanks! (and sorry if I forgot to mention someone)

View File

@@ -1,4 +1,4 @@
To be addressed in 7.19.8 (planned release: January 2010)
To be addressed in 7.20.0 (planned release: January 2010)
=========================
244 - patch for [out] parameters
@@ -12,11 +12,4 @@ To be addressed in 7.19.8 (planned release: January 2010)
253 - add option to disable SNI for TLS handshakes
257 - bug #2891595 DNS cache
258 - bug #2891591 Curl_dns_entry
259 - Avoding connection re-use when using CURLOPT_HTTPPROXYTUNNEL
260 -
261 -

View File

@@ -3190,7 +3190,22 @@ AC_DEFUN([CURL_CHECK_WIN32_LARGEFILE], [
esac
])
dnl CURL_CHECK_PKGCONFIG ($module)
dnl CURL_EXPORT_PCDIR ($pcdir)
dnl ------------------------
dnl if $pcdir is not empty, set PKG_CONFIG_LIBDIR to $pcdir and export
dnl
dnl we need this macro since pkg-config distinguishes among empty and unset
dnl variable while checking PKG_CONFIG_LIBDIR
dnl
AC_DEFUN([CURL_EXPORT_PCDIR], [
if test -n "$1"; then
PKG_CONFIG_LIBDIR="$1"
export PKG_CONFIG_LIBDIR
fi
])
dnl CURL_CHECK_PKGCONFIG ($module, [$pcdir])
dnl ------------------------
dnl search for the pkg-config tool (if not cross-compiling). Set the PKGCONFIG
dnl variable to hold the path to it, or 'no' if not found/present.
@@ -3198,6 +3213,8 @@ dnl
dnl If pkg-config is present, check that it has info about the $module or
dnl return "no" anyway!
dnl
dnl Optionally PKG_CONFIG_LIBDIR may be given as $pcdir.
dnl
AC_DEFUN([CURL_CHECK_PKGCONFIG], [
@@ -3216,8 +3233,10 @@ AC_DEFUN([CURL_CHECK_PKGCONFIG], [
if test x$PKGCONFIG != xno; then
AC_MSG_CHECKING([for $1 options with pkg-config])
dnl ask pkg-config about $1
$PKGCONFIG --exists $1
if test "$?" -ne "0"; then
itexists=`CURL_EXPORT_PCDIR([$2]) dnl
$PKGCONFIG --exists $1 >/dev/null 2>&1 && echo 1`
if test -z "$itexists"; then
dnl pkg-config does not have info about the given module! set the
dnl variable to 'no'
PKGCONFIG="no"

View File

@@ -1,5 +1,24 @@
Changelog for the c-ares project
* January 28, 2010 (Daniel Stenberg)
- Tommie Gannert pointed out a silly bug in ares_process_fd() since it didn't
check for broken connections like ares_process() did. Based on that, I
merged the two functions into a single generic one with two front-ends.
* December 29, 2009 (Yang Tse)
- Laszlo Tamas Szabo adjusted Makefile.msvc compiler options so that where
run-time error checks enabling compiler option /GZ was used it is replaced
with equivalent /RTCsu for Visual Studio 2003 and newer versions. Option
/GX is replaced with equivalent /EHsc for all versions. Also fixed socket
data type for internal configure_socket function.
* December 21, 2009 (Yang Tse)
- Ingmar Runge noticed that Windows config-win32.h configuration file
did not include a definition for HAVE_CLOSESOCKET which resulted in
function close() being inappropriately used to close sockets.
Version 1.7.0 (Nov 30, 2009)
* November 26, 2009 (Yang Tse)
- Larry Lansing fixed ares_parse_srv_reply to properly parse replies
which might contain non-SRV answers, skipping over potential non-SRV

View File

@@ -222,13 +222,19 @@ PDBTYPE_CONSOLIDATE = /pdbtype:consolidate
!UNDEF PDBTYPE_CONSOLIDATE
!ENDIF
!IF $(CC_VERS_NUM) <= 70
RT_ERROR_CHECKING = /GZ
!ELSE
RT_ERROR_CHECKING = /RTCsu
!ENDIF
# ----------------------------
# Assorted commands and flags
# ----------------------------
CC_CMD_REL = cl.exe /nologo $(RTLIB) /DNDEBUG /O2
CC_CMD_DBG = cl.exe /nologo $(RTLIBD) /D_DEBUG /Od /Zi /GZ
CC_CFLAGS = $(CFLAGS) /I. /W3 /GX /FD
CC_CMD_DBG = cl.exe /nologo $(RTLIBD) /D_DEBUG /Od /Zi $(RT_ERROR_CHECKING)
CC_CFLAGS = $(CFLAGS) /I. /W3 /EHsc /FD
RC_CMD_REL = rc.exe /l 0x409 /d "NDEBUG"
RC_CMD_DBG = rc.exe /l 0x409 /d "_DEBUG"

View File

@@ -1,36 +1,17 @@
This is what's new and changed in the c-ares 1.7.0 release:
This is what's new and changed in the c-ares 1.7.1 release:
Changed:
o in6_addr is not used in ares.h anymore, but a private ares_in6_addr is
instead declared and used
o ares_gethostbyname() now supports 'AF_UNSPEC' as a family for resolving
either AF_INET6 or AF_INET
o a build-time configured ares_socklen_t is now used instead of socklen_t
o new ares_library_init() and ares_library_cleanup() functions
o new --enable-curldebug configure option
o ARES_ECANCELLED is now sent as reason for ares_cancel()
o added ares_parse_srv_reply()
o added ares_parse_txt_reply()
o added ares_free_data()
o new --enable-symbol-hiding configure option
o new Makefile.msvc for any MSVC compiler or MS Visual Studio version
o addrttl and addr6ttl structs renamed to ares_addrttl and ares_addr6ttl
o naming convention for libraries built with MSVC, see README.msvc
o
Fixed:
o ares_parse_*_reply() functions now return ARES_EBADRESP instead of
ARES_EBADNAME if the name in the response failed to decode
o only expose/export symbols starting with 'ares_'
o fix \Device\TCP handle leaks triggered by buggy iphlpapi.dll
o init without internet gone no longer fails
o out of bounds memory overwrite triggered with malformed /etc/hosts file
o function prototypes in man pages out of sync with ares.h
o closing of sockets on Windows systems
o MSVC deprecated compiler options warnings
o ares_process_fd() didn't check broken connections
Thanks go to these friendly people for their efforts and contributions:
Phil Blundell, Japheth Cleaver, Yang Tse, Gregor Jasny, Joshua Kwan,
Timo Teras, Jakub Hrozek, John Engelhart, Larry Lansing
Ingmar Runge, Laszlo Tamas Szabo, Yang Tse, Tommie Gannert
Have fun!

View File

@@ -1,7 +1,7 @@
/* $Id$ */
/* Copyright 1998 by the Massachusetts Institute of Technology.
* Copyright (C) 2004-2009 by Daniel Stenberg
* Copyright (C) 2004-2010 by Daniel Stenberg
*
* Permission to use, copy, modify, and distribute this
* software and its documentation for any purpose and without
@@ -92,7 +92,7 @@ static void skip_server(ares_channel channel, struct query *query,
int whichserver);
static void next_server(ares_channel channel, struct query *query,
struct timeval *now);
static int configure_socket(int s, ares_channel channel);
static int configure_socket(ares_socket_t s, ares_channel channel);
static int open_tcp_socket(ares_channel channel, struct server_state *server);
static int open_udp_socket(ares_channel channel, struct server_state *server);
static int same_questions(const unsigned char *qbuf, int qlen,
@@ -139,18 +139,28 @@ long ares__timeoffset(struct timeval *now,
}
/*
* generic process function
*/
static void processfds(ares_channel channel,
fd_set *read_fds, ares_socket_t read_fd,
fd_set *write_fds, ares_socket_t write_fd)
{
struct timeval now = ares__tvnow();
write_tcp_data(channel, write_fds, write_fd, &now);
read_tcp_data(channel, read_fds, read_fd, &now);
read_udp_packets(channel, read_fds, read_fd, &now);
process_timeouts(channel, &now);
process_broken_connections(channel, &now);
}
/* Something interesting happened on the wire, or there was a timeout.
* See what's up and respond accordingly.
*/
void ares_process(ares_channel channel, fd_set *read_fds, fd_set *write_fds)
{
struct timeval now = ares__tvnow();
write_tcp_data(channel, write_fds, ARES_SOCKET_BAD, &now);
read_tcp_data(channel, read_fds, ARES_SOCKET_BAD, &now);
read_udp_packets(channel, read_fds, ARES_SOCKET_BAD, &now);
process_timeouts(channel, &now);
process_broken_connections(channel, &now);
processfds(channel, read_fds, ARES_SOCKET_BAD, write_fds, ARES_SOCKET_BAD);
}
/* Something interesting happened on the wire, or there was a timeout.
@@ -161,12 +171,7 @@ void ares_process_fd(ares_channel channel,
file descriptors */
ares_socket_t write_fd)
{
struct timeval now = ares__tvnow();
write_tcp_data(channel, NULL, write_fd, &now);
read_tcp_data(channel, NULL, read_fd, &now);
read_udp_packets(channel, NULL, read_fd, &now);
process_timeouts(channel, &now);
processfds(channel, NULL, read_fd, NULL, write_fd);
}
@@ -174,7 +179,8 @@ void ares_process_fd(ares_channel channel,
* otherwise. This is mostly for HP-UX, which could return EAGAIN or
* EWOULDBLOCK. See this man page
*
* http://devrsrc1.external.hp.com/STKS/cgi-bin/man2html?manpage=/usr/share/man/man2.Z/send.2
* http://devrsrc1.external.hp.com/STKS/cgi-bin/man2html?
* manpage=/usr/share/man/man2.Z/send.2
*/
static int try_again(int errnum)
{
@@ -802,8 +808,9 @@ void ares__send_query(ares_channel channel, struct query *query,
}
/*
* setsocknonblock sets the given socket to either blocking or non-blocking mode
* based on the 'nonblock' boolean argument. This function is highly portable.
* setsocknonblock sets the given socket to either blocking or non-blocking
* mode based on the 'nonblock' boolean argument. This function is highly
* portable.
*/
static int setsocknonblock(ares_socket_t sockfd, /* operate on this */
int nonblock /* TRUE or FALSE */)
@@ -856,7 +863,7 @@ static int setsocknonblock(ares_socket_t sockfd, /* operate on this */
#endif
}
static int configure_socket(int s, ares_channel channel)
static int configure_socket(ares_socket_t s, ares_channel channel)
{
setsocknonblock(s, TRUE);
@@ -902,10 +909,10 @@ static int open_tcp_socket(ares_channel channel, struct server_state *server)
#ifdef TCP_NODELAY
/*
* Disable the Nagle algorithm (only relevant for TCP sockets, and thus not in
* configure_socket). In general, in DNS lookups we're pretty much interested
* in firing off a single request and then waiting for a reply, so batching
* isn't very interesting in general.
* Disable the Nagle algorithm (only relevant for TCP sockets, and thus not
* in configure_socket). In general, in DNS lookups we're pretty much
* interested in firing off a single request and then waiting for a reply,
* so batching isn't very interesting in general.
*/
opt = 1;
if (setsockopt(s, IPPROTO_TCP, TCP_NODELAY,

View File

@@ -5,11 +5,11 @@
#define ARES_VERSION_MAJOR 1
#define ARES_VERSION_MINOR 7
#define ARES_VERSION_PATCH 0
#define ARES_VERSION_PATCH 1
#define ARES_VERSION ((ARES_VERSION_MAJOR<<16)|\
(ARES_VERSION_MINOR<<8)|\
(ARES_VERSION_PATCH))
#define ARES_VERSION_STR "1.7.0-CVS"
#define ARES_VERSION_STR "1.7.1-CVS"
#if (ARES_VERSION >= 0x010700)
# define CARES_HAVE_ARES_LIBRARY_INIT 1

View File

@@ -85,6 +85,9 @@
/* FUNCTIONS */
/* ---------------------------------------------------------------- */
/* Define if you have the closesocket function. */
#define HAVE_CLOSESOCKET 1
/* Define if you have the gethostname function. */
#define HAVE_GETHOSTNAME 1

View File

@@ -415,7 +415,7 @@ typedef int sig_atomic_t;
* Actually use __32_getpwuid() on 64-bit VMS builds for getpwuid()
*/
#if defined(VMS) && \
#if defined(__VMS) && \
defined(__INITIAL_POINTER_SIZE) && (__INITIAL_POINTER_SIZE == 64)
#define getpwuid __32_getpwuid
#endif
@@ -425,7 +425,7 @@ typedef int sig_atomic_t;
* Macro argv_item_t hides platform details to code using it.
*/
#ifdef VMS
#ifdef __VMS
#define argv_item_t __char_ptr32
#else
#define argv_item_t char *

View File

@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
# Copyright (C) 1998 - 2009, Daniel Stenberg, <daniel@haxx.se>, et al.
# Copyright (C) 1998 - 2010, 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,6 +42,7 @@ CURL_CHECK_OPTION_DEBUG
CURL_CHECK_OPTION_OPTIMIZE
CURL_CHECK_OPTION_WARNINGS
CURL_CHECK_OPTION_CURLDEBUG
CURL_CHECK_OPTION_ARES
CURL_CHECK_PATH_SEPARATOR_REQUIRED
@@ -135,6 +136,7 @@ curl_verbose_msg="enabled (--disable-verbose)"
curl_sspi_msg="no (--enable-sspi)"
curl_ldap_msg="no (--enable-ldap / --with-ldap-lib / --with-lber-lib)"
curl_ldaps_msg="no (--enable-ldaps)"
curl_rtsp_msg="no (--enable-rtsp)"
dnl
dnl Save anything in $LIBS for later
@@ -318,8 +320,10 @@ AC_HELP_STRING([--disable-http],[Disable HTTP support]),
no)
AC_MSG_RESULT(no)
AC_DEFINE(CURL_DISABLE_HTTP, 1, [to disable HTTP])
AC_MSG_WARN([disable HTTP disables FTP over proxy])
AC_MSG_WARN([disable HTTP disables FTP over proxy and RTSP])
AC_SUBST(CURL_DISABLE_HTTP, [1])
AC_DEFINE(CURL_DISABLE_RTSP, 1, [to disable RTSP])
AC_SUBST(CURL_DISABLE_RTSP, [1])
;;
*) AC_MSG_RESULT(yes)
;;
@@ -416,6 +420,32 @@ AC_HELP_STRING([--disable-ldaps],[Disable LDAPS support]),
AC_SUBST(CURL_DISABLE_LDAPS, [1])
)
AC_MSG_CHECKING([whether to support rtsp])
AC_ARG_ENABLE(rtsp,
AC_HELP_STRING([--enable-rtsp],[Enable RTSP support])
AC_HELP_STRING([--disable-rtsp],[Disable RTSP support]),
[ case "$enableval" in
no)
AC_MSG_RESULT(no)
AC_DEFINE(CURL_DISABLE_RTSP, 1, [to disable RTSP])
AC_SUBST(CURL_DISABLE_RTSP, [1])
;;
*) if test x$CURL_DISABLE_HTTP = x1 ; then
AC_MSG_ERROR(HTTP support needs to be enabled in order to enable RTSP support!)
else
AC_MSG_RESULT(yes)
curl_rtsp_msg="enabled"
fi
;;
esac ],
if test "x$CURL_DISABLE_HTTP" != "x1"; then
AC_MSG_RESULT(yes)
curl_rtsp_msg="enabled"
else
AC_MSG_RESULT(no)
fi
)
AC_MSG_CHECKING([whether to support proxies])
AC_ARG_ENABLE(proxy,
AC_HELP_STRING([--enable-proxy],[Enable proxy support])
@@ -478,6 +508,57 @@ AC_HELP_STRING([--disable-tftp],[Disable TFTP support]),
AC_MSG_RESULT(yes)
)
AC_MSG_CHECKING([whether to support pop3])
AC_ARG_ENABLE(pop3,
AC_HELP_STRING([--enable-pop3],[Enable POP3 support])
AC_HELP_STRING([--disable-pop3],[Disable POP3 support]),
[ case "$enableval" in
no)
AC_MSG_RESULT(no)
AC_DEFINE(CURL_DISABLE_POP3, 1, [to disable POP3])
AC_SUBST(CURL_DISABLE_POP3, [1])
;;
*) AC_MSG_RESULT(yes)
;;
esac ],
AC_MSG_RESULT(yes)
)
AC_MSG_CHECKING([whether to support imap])
AC_ARG_ENABLE(imap,
AC_HELP_STRING([--enable-imap],[Enable IMAP support])
AC_HELP_STRING([--disable-imap],[Disable IMAP support]),
[ case "$enableval" in
no)
AC_MSG_RESULT(no)
AC_DEFINE(CURL_DISABLE_IMAP, 1, [to disable IMAP])
AC_SUBST(CURL_DISABLE_IMAP, [1])
;;
*) AC_MSG_RESULT(yes)
;;
esac ],
AC_MSG_RESULT(yes)
)
AC_MSG_CHECKING([whether to support smtp])
AC_ARG_ENABLE(smtp,
AC_HELP_STRING([--enable-smtp],[Enable SMTP support])
AC_HELP_STRING([--disable-smtp],[Disable SMTP support]),
[ case "$enableval" in
no)
AC_MSG_RESULT(no)
AC_DEFINE(CURL_DISABLE_SMTP, 1, [to disable SMTP])
AC_SUBST(CURL_DISABLE_SMTP, [1])
;;
*) AC_MSG_RESULT(yes)
;;
esac ],
AC_MSG_RESULT(yes)
)
dnl **********************************************************************
dnl Check for built-in manual
dnl **********************************************************************
@@ -1154,7 +1235,6 @@ if test X"$OPT_SSL" != Xno; then
CLEANLDFLAGS="$LDFLAGS"
CLEANCPPFLAGS="$CPPFLAGS"
CLEANLIBS="$LIBS"
SAVE_PKG_CONFIG_LIBDIR="$PKG_CONFIG_LIBDIR"
case "$OPT_SSL" in
yes)
@@ -1182,10 +1262,9 @@ if test X"$OPT_SSL" != Xno; then
dnl Try pkg-config even when cross-compiling. Since we
dnl specify PKG_CONFIG_LIBDIR we're only looking where
dnl the user told us to look
PKG_CONFIG_LIBDIR=$OPT_SSL/lib/pkgconfig
export PKG_CONFIG_LIBDIR
AC_MSG_NOTICE([set PKG_CONFIG_LIBDIR to "$PKG_CONFIG_LIBDIR"])
if test -e "$PKG_CONFIG_LIBDIR/openssl.pc"; then
OPENSSL_PCDIR="$OPT_SSL/lib/pkgconfig"
AC_MSG_NOTICE([PKG_CONFIG_LIBDIR will be set to "$OPENSSL_PCDIR"])
if test -e "$OPENSSL_PCDIR/openssl.pc"; then
PKGTEST="yes"
fi
@@ -1202,12 +1281,17 @@ if test X"$OPT_SSL" != Xno; then
if test "$PKGTEST" = "yes"; then
CURL_CHECK_PKGCONFIG(openssl)
CURL_CHECK_PKGCONFIG(openssl, [$OPENSSL_PCDIR])
if test "$PKGCONFIG" != "no" ; then
SSL_LIBS=`$PKGCONFIG --libs-only-l openssl 2>/dev/null`
SSL_LDFLAGS=`$PKGCONFIG --libs-only-L openssl 2>/dev/null`
SSL_CPPFLAGS=`$PKGCONFIG --cflags-only-I openssl 2>/dev/null`
SSL_LIBS=`CURL_EXPORT_PCDIR([$OPENSSL_PCDIR]) dnl
$PKGCONFIG --libs-only-l openssl 2>/dev/null`
SSL_LDFLAGS=`CURL_EXPORT_PCDIR([$OPENSSL_PCDIR]) dnl
$PKGCONFIG --libs-only-L openssl 2>/dev/null`
SSL_CPPFLAGS=`CURL_EXPORT_PCDIR([$OPENSSL_PCDIR]) dnl
$PKGCONFIG --cflags-only-I openssl 2>/dev/null`
AC_MSG_NOTICE([pkg-config: SSL_LIBS: "$SSL_LIBS"])
AC_MSG_NOTICE([pkg-config: SSL_LDFLAGS: "$SSL_LDFLAGS"])
@@ -1225,10 +1309,6 @@ if test X"$OPT_SSL" != Xno; then
fi
fi
dnl we're done using pkg-config for openssl
PKG_CONFIG_LIBDIR="$SAVE_PKG_CONFIG_LIBDIR"
export PKG_CONFIG_LIBDIR
dnl finally, set flags to use SSL
CPPFLAGS="$CPPFLAGS $SSL_CPPFLAGS"
LDFLAGS="$LDFLAGS $SSL_LDFLAGS"
@@ -1346,6 +1426,7 @@ if test X"$OPT_SSL" != Xno; then
AC_CHECK_FUNCS( RAND_status \
RAND_screen \
RAND_egd \
ENGINE_cleanup \
CRYPTO_cleanup_all_ex_data \
SSL_get_shutdown )
@@ -1654,14 +1735,14 @@ if test "$OPENSSL_ENABLED" != "1" -a "$GNUTLS_ENABLED" != "1"; then
version="unknown"
fi
fi
else
# Without pkg-config, we'll kludge in some defaults
addlib="-L$OPT_NSS/lib -lssl3 -lsmime3 -lnss3 -lplds4 -lplc4 -lnspr4 -lpthread -ldl"
addcflags="-I$OPT_NSS/include"
version="unknown"
else
# Without pkg-config, we'll kludge in some defaults
addlib="-L$OPT_NSS/lib -lssl3 -lsmime3 -lnss3 -lplds4 -lplc4 -lnspr4 -lpthread -ldl"
addcflags="-I$OPT_NSS/include"
version="unknown"
nssprefix=$OPT_NSS
fi
dnl Check for functionPK11_CreateGenericObject
dnl this is needed for using the PEM PKCS#11 module
AC_CHECK_LIB(nss3, PK11_CreateGenericObject,
@@ -1755,7 +1836,7 @@ if test X"$OPT_LIBSSH2" != Xno; then
version=`$PKGCONFIG --modversion libssh2`
DIR_SSH2=`echo $LD_SSH2 | $SED -e 's/-L//'`
fi
;;
off)
dnl no --with-libssh2 option given, just check default places
@@ -1957,8 +2038,9 @@ CURL_CHECK_STRUCT_TIMEVAL
CURL_VERIFY_RUNTIMELIBS
AC_CHECK_SIZEOF(size_t)
AC_CHECK_SIZEOF(int)
AC_CHECK_SIZEOF(long)
AC_CHECK_SIZEOF(int)
AC_CHECK_SIZEOF(short)
CURL_CONFIGURE_LONG
AC_CHECK_SIZEOF(time_t)
AC_CHECK_SIZEOF(off_t)
@@ -2194,81 +2276,8 @@ fi
dnl set variable for use in automakefile(s)
AM_CONDITIONAL(USE_MANUAL, test x"$USE_MANUAL" = x1)
aresembedded="unknown"
configure_rundir=`pwd`
embedded_ares_builddir="$configure_rundir/ares"
AC_MSG_CHECKING([whether to enable c-ares])
AC_ARG_ENABLE(ares,
AC_HELP_STRING([--enable-ares=PATH],[Enable c-ares for name lookups])
AC_HELP_STRING([--disable-ares],[Disable c-ares for name lookups]),
[ case "$enableval" in
no)
AC_MSG_RESULT(no)
;;
*) AC_MSG_RESULT(yes)
if test "x$IPV6_ENABLED" = "x1"; then
AC_MSG_NOTICE([c-ares may not work properly with ipv6])
fi
AC_DEFINE(USE_ARES, 1, [Define if you want to enable c-ares support])
dnl substitute HAVE_ARES for curl-config and similar
HAVE_ARES="1"
AC_SUBST(HAVE_ARES)
curl_ares_msg="enabled"
LIBS="-lcares $LIBS"
dnl For backwards compatibility default to includes/lib in srcdir/ares
dnl If a value is specified it is assumed that the libs are in $val/lib
dnl and the includes are in $val/include. This is the default setup for
dnl ares so it should not be a problem.
if test "x$enableval" = "xyes" ; then
if test -d "$srcdir/ares"; then
aresembedded="yes"
AC_CONFIG_SUBDIRS(ares)
dnl Since c-ares has installable configured header files, path
dnl inclusion is fully done in makefiles for in-tree builds.
LDFLAGS="$LDFLAGS -L$embedded_ares_builddir"
fi
else
CPPFLAGS="$CPPFLAGS -I$enableval/include"
LDFLAGS="$LDFLAGS -L$enableval/lib"
fi
if test -z "$aresembedded"; then
dnl verify that a sufficient c-ares is here if we have pointed one
dnl out and don't use the "embedded" ares dir (in which case we don't
dnl check it because it might not have been built yet)
AC_MSG_CHECKING([that c-ares is good and recent enough])
AC_LINK_IFELSE([
AC_LANG_PROGRAM([[
#include <ares.h>
/* set of dummy functions in case c-ares was built with debug */
void curl_dofree() { }
void curl_sclose() { }
void curl_domalloc() { }
void curl_docalloc() { }
void curl_socket() { }
]],[[
ares_channel channel;
ares_cancel(channel); /* added in 1.2.0 */
ares_process_fd(channel, 0, 0); /* added in 1.4.0 */
]])
],[
AC_MSG_RESULT([yes])
],[
AC_MSG_RESULT([no])
AC_MSG_ERROR([c-ares library defective or too old])
])
fi
;;
esac ],
AC_MSG_RESULT(no)
)
dnl set variable for use in automakefile(s)
AM_CONDITIONAL(USE_EMBEDDED_ARES, test x$aresembedded = xyes)
CURL_CHECK_LIB_ARES
AM_CONDITIONAL(USE_EMBEDDED_ARES, test x$embedded_ares = xyes)
dnl ************************************************************
dnl disable verbose text strings
@@ -2302,7 +2311,7 @@ AC_HELP_STRING([--disable-sspi],[Disable SSPI]),
AC_MSG_RESULT(yes)
AC_DEFINE(USE_WINDOWS_SSPI, 1, [to enable SSPI support])
AC_SUBST(USE_WINDOWS_SSPI, [1])
curl_sspi_msg="yes"
curl_sspi_msg="enabled"
else
AC_MSG_RESULT(no)
AC_MSG_WARN([--enable-sspi Ignored. Only supported on native Windows builds.])
@@ -2460,7 +2469,7 @@ fi
if test "x$HAVE_LIBZ" = "x1"; then
SUPPORT_FEATURES="$SUPPORT_FEATURES libz"
fi
if test "x$HAVE_ARES" = "x1"; then
if test "x$USE_ARES" = "x1"; then
SUPPORT_FEATURES="$SUPPORT_FEATURES AsynchDNS"
fi
if test "x$IDN_ENABLED" = "x1"; then
@@ -2506,10 +2515,36 @@ fi
if test "x$CURL_DISABLE_TFTP" != "x1"; then
SUPPORT_PROTOCOLS="$SUPPORT_PROTOCOLS TFTP"
fi
if test "x$CURL_DISABLE_POP3" != "x1"; then
SUPPORT_PROTOCOLS="$SUPPORT_PROTOCOLS POP3"
if test "x$SSL_ENABLED" = "x1"; then
SUPPORT_PROTOCOLS="$SUPPORT_PROTOCOLS POP3S"
fi
fi
if test "x$CURL_DISABLE_IMAP" != "x1"; then
SUPPORT_PROTOCOLS="$SUPPORT_PROTOCOLS IMAP"
if test "x$SSL_ENABLED" = "x1"; then
SUPPORT_PROTOCOLS="$SUPPORT_PROTOCOLS IMAPS"
fi
fi
if test "x$CURL_DISABLE_SMTP" != "x1"; then
SUPPORT_PROTOCOLS="$SUPPORT_PROTOCOLS SMTP"
if test "x$SSL_ENABLED" = "x1"; then
SUPPORT_PROTOCOLS="$SUPPORT_PROTOCOLS SMTPS"
fi
fi
if test "x$USE_LIBSSH2" = "x1"; then
SUPPORT_PROTOCOLS="$SUPPORT_PROTOCOLS SCP"
SUPPORT_PROTOCOLS="$SUPPORT_PROTOCOLS SFTP"
fi
if test "x$CURL_DISABLE_RTSP" != "x1"; then
SUPPORT_PROTOCOLS="$SUPPORT_PROTOCOLS RTSP"
fi
dnl replace spaces with newlines
dnl sort the lines
dnl replace the newlines back to spaces
SUPPORT_PROTOCOLS=`echo $SUPPORT_PROTOCOLS | tr ' ' '\012' | sort | tr '\012' ' '`
AC_SUBST(SUPPORT_PROTOCOLS)
@@ -2525,8 +2560,11 @@ squeeze CURL_LIBS
squeeze LIBCURL_LIBS
squeeze TEST_SERVER_LIBS
squeeze SUPPORT_FEATURES
squeeze SUPPORT_PROTOCOLS
if test "x$want_curldebug_assumed" = "xyes" &&
test "x$want_curldebug" = "xyes" && test "x$HAVE_ARES" = "x1"; then
test "x$want_curldebug" = "xyes" && test "x$USE_ARES" = "x1"; then
ac_configure_args="$ac_configure_args --enable-curldebug"
fi
@@ -2584,6 +2622,8 @@ AC_MSG_NOTICE([Configured to build curl/libcurl:
ca cert path: ${capath}
LDAP support: ${curl_ldap_msg}
LDAPS support: ${curl_ldaps_msg}
RTSP support: ${curl_rtsp_msg}
Protocols: ${SUPPORT_PROTOCOLS}
])
if test "x$soname_bump" = "xyes"; then

View File

@@ -63,6 +63,10 @@ Euphoria
Written by Ray Smith
http://rays-web.com/eulibcurl.htm
Falcon
http://www.falconpl.org/index.ftd?page_id=prjs&prj_id=curl
Ferite
Written by Paul Querna

View File

@@ -874,9 +874,9 @@ REDUCING SIZE
.comment section).
Using these techniques it is possible to create a basic HTTP-only shared
libcurl library for i386 Linux platforms that is only 94 KiB in size, and
an FTP-only library that is 87 KiB in size (as of libcurl version 7.19.1,
using gcc 4.2.2).
libcurl library for i386 Linux platforms that is only 98 KiB in size, and
an FTP-only library that is 94 KiB in size (as of libcurl version 7.20.0,
using gcc 4.3.3).
You may find that statically linking libcurl to your application will
result in a lower total size than dynamically linking.

View File

@@ -3,6 +3,12 @@ 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!
74. The HTTP spec allows headers to be merged and become comma-separated
instead of being repeated several times. This also include Authenticate: and
Proxy-Authenticate: headers and while this hardly every happens in real life
it will confuse libcurl which does not properly support it for all headers -
like those Authenticate headers.
73. if a connection is made to a FTP server but the server then just never
sends the 220 response or otherwise is dead slow, libcurl will not
acknowledge the connection timeout during that phase but only the "real"
@@ -13,12 +19,6 @@ may have been fixed since this was written!
72. "Pausing pipeline problems."
http://curl.haxx.se/mail/lib-2009-07/0214.html
71. TFTP block size / better integration in transfer
http://curl.haxx.se/mail/lib-2009-08/0028.html
Related problems with TFTP is also that currently (7.19.6) upload file sizes
are limited to 32MB (http://curl.haxx.se/bug/view.cgi?id=2848436)
70. Problem re-using easy handle after call to curl_multi_remove_handle
http://curl.haxx.se/mail/lib-2009-07/0249.html
@@ -40,11 +40,6 @@ may have been fixed since this was written!
properly wait for the connect to be confirmed. See test case 564 for a first
shot at a test case.
64. The threaded resolver used in libcurl on Windows has some kind of race
problem when multiple simultanoes resolves are done, like with the multi
interface transferring many files in parallell:
http://curl.haxx.se/mail/lib-2009-04/0028.html
63. When CURLOPT_CONNECT_ONLY is used, the handle cannot reliably be re-used
for any further requests or transfers. The work-around is then to close that
handle with curl_easy_cleanup() and create a new. Some more details:

View File

@@ -379,6 +379,7 @@ Judson Bishop
Juergen Wilke
Jukka Pihl
Julian Noble
Julien Chaffraix
Jun-ichiro itojun Hagino
Jurij Smakov
Justin Fletcher

View File

@@ -37,8 +37,7 @@
5. HTTP
5.1 Better persistency for HTTP 1.0
5.2 support FF3 sqlite cookie files
5.3 Sort outgoing cookies
5.4 Rearrange request header order
5.3 Rearrange request header order
6. TELNET
6.1 ditch stdin
@@ -105,6 +104,7 @@
15.4 remove several functions
15.5 remove CURLOPT_FAILONERROR
15.6 remove CURLOPT_DNS_USE_GLOBAL_CACHE
15.7 remove progress meter from libcurl
==============================================================================
@@ -237,14 +237,7 @@
We should consider how (lib)curl can/should support this.
http://curl.haxx.se/bug/feature.cgi?id=1871388
5.3 Sort outgoing cookies
All the major browsers sort the cookies sent in the Cookie: header based on
the length of the path for which the cookie is set with. This could lead to
a small fraction of servers to not play well with curl:
http://www.ietf.org/mail-archive/web/http-state/current/msg00150.html
5.4 Rearrange request header order
5.3 Rearrange request header order
Server implementors often make an effort to detect browser and to reject
clients it can detect to not match. One of the last details we cannot yet
@@ -585,3 +578,13 @@ to provide the data to send.
Remove support for a global DNS cache. Anything global is silly, and we
already offer the share interface for the same functionality but done
"right".
15.7 remove progress meter from libcurl
The internally provided progress meter output doesn't belong in the library.
Basically no application wants it (apart from curl) but instead applications
can and should do their own progress meters using the progress callback.
The progress callback should then be bumped as well to get proper 64bit
variable types passed to it instead of doubles so that big files work
correctly.

View File

@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
.\" * Copyright (C) 1998 - 2009, Daniel Stenberg, <daniel@haxx.se>, et al.
.\" * Copyright (C) 1998 - 2010, 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 1 "10 July 2008" "Curl 7.19.0" "Curl Manual"
.TH curl 1 "28 November 2009" "Curl 7.20.0" "Curl Manual"
.SH NAME
curl \- transfer a URL
.SH SYNOPSIS
@@ -461,19 +461,29 @@ will re-use the same IP address it already uses for the control
connection. (Added in 7.14.2)
This option has no effect if PORT, EPRT or EPSV is used instead of PASV.
.IP "--ftp-ssl"
(FTP) Try to use SSL/TLS for the FTP connection. Reverts to a non-secure
connection if the server doesn't support SSL/TLS. See also
\fI--ftp-ssl-control\fP and \fI--ftp-ssl-reqd\fP for different levels of
encryption required. (Added in 7.11.0)
.IP "--ftp-pret"
(FTP) Tell curl to send a PRET command before PASV (and EPSV). Certain
FTP servers, mainly drftpd, require this non-standard command for
directory listings as well as up and downloads in PASV mode.
(Added in 7.20.x)
.IP "--ssl"
(FTP, POP3, IMAP, SMTP) Try to use SSL/TLS for the connection. Reverts to a
non-secure connection if the server doesn't support SSL/TLS. See also
\fI--ftp-ssl-control\fP and \fI--ssl-reqd\fP for different levels of
encryption required. (Added in 7.20.0)
This option was formerly known as \fI--ftp-ssl\fP (Added in 7.11.0) and that
can still be used but will be removed in a future version.
.IP "--ftp-ssl-control"
(FTP) Require SSL/TLS for the FTP login, clear for transfer. Allows secure
authentication, but non-encrypted data transfers for efficiency. Fails the
transfer if the server doesn't support SSL/TLS. (Added in 7.16.0)
.IP "--ftp-ssl-reqd"
(FTP) Require SSL/TLS for the FTP connection.
Terminates the connection if the server doesn't support SSL/TLS.
(Added in 7.15.5)
.IP "--ssl-reqd"
(FTP, POP3, IMAP, SMTP) Require SSL/TLS for the connection. Terminates the
connection if the server doesn't support SSL/TLS. (Added in 7.20.0)
This option was formerly known as \fI--ftp-ssl-reqd\fP (added in 7.15.5) and
that can still be used but will be removed in a future version.
.IP "--ftp-ssl-ccc"
(FTP) Use CCC (Clear Command Channel)
Shuts down the SSL/TLS layer after authenticating. The rest of the
@@ -598,6 +608,9 @@ time only.
make it discard all "session cookies". This will basically have the same effect
as if a new session is started. Typical browsers always discard session
cookies when they're closed down.
.IP "-J/--remote-header-name"
(HTTP) This option tells the -O/--remote-name option to use the server-specified
Content-Disposition filename instead of extracting a filename from the URL.
.IP "-k/--insecure"
(SSL) This option explicitly allows curl to perform "insecure" SSL connections
and transfers. All SSL connections are attempted to be made secure by using
@@ -756,7 +769,15 @@ password to all hosts that the site may redirect to. This may or may not
introduce a security breach if the site redirects you to a site to which
you'll send your authentication info (which is plaintext in the case of HTTP
Basic authentication).
.IP "--mail-rcpt <address>"
(SMTP) Specify a single address that the given mail should get sent to. This
option can be used multiple times to specify many recipients.
(Added in 7.20.0)
.IP "--mail-from <address>"
(SMTP) Specify a single address that the given mail should get sent from.
(Added in 7.20.0)
.IP "--max-filesize <bytes>"
Specify the maximum size (in bytes) of a file to download. If the file
requested is larger than this value, the transfer will not start and curl will
@@ -1079,7 +1100,7 @@ timestamp.
If a transient error is returned when curl tries to perform a transfer, it
will retry this number of times before giving up. Setting the number to 0
makes curl do no retries (which is the default). Transient error means either:
a timeout, an FTP 5xx response code or an HTTP 5xx response code.
a timeout, an FTP 4xx response code or an HTTP 5xx response code.
When curl is about to retry a transfer, it will first wait one second and then
for all forthcoming retries it will double the waiting time until it reaches
@@ -1149,6 +1170,8 @@ mutually exclusive.
If this option is used several times, the last one will be used. (This option
was previously wrongly documented and used as --socks without the number
appended.)
This option (as well as \fI--socks4\fP) does not work with IPV6, FTPS or LDAP.
.IP "--socks5-gssapi-service <servicename>"
The default service name for a socks server is rcmd/server-fqdn. This option
allows you to change it.
@@ -1181,6 +1204,14 @@ TTYPE=<term> Sets the terminal type.
XDISPLOC=<X display> Sets the X display location.
NEW_ENV=<var,val> Sets an environment variable.
.IP "--tftp-blksize <value>"
(TFTP) Set TFTP BLKSIZE option (must be >512). This is the block size that
curl will try to use when tranferring data to or from a TFTP server. By
default 512 bytes will be used.
If this option is used several times, the last one will be used.
(Added in 7.20.0)
.IP "-T/--upload-file <file>"
This transfers the specified local file to the remote URL. If there is no file
part in the specified URL, Curl will append the local file name. NOTE that you

View File

@@ -453,7 +453,7 @@ int main(int argc, char **argv) {
{
FILE *outfp;
BIO_get_fp(out,&outfp);
curl_easy_setopt(p.curl, CURLOPT_FILE,outfp);
curl_easy_setopt(p.curl, CURLOPT_WRITEDATA, outfp);
}
res = curl_easy_setopt(p.curl, CURLOPT_SSL_CTX_FUNCTION, sslctxfun) ;

View File

@@ -105,20 +105,23 @@ int main(int argc, char **argv)
/* See how the transfers went */
while ((msg = curl_multi_info_read(multi_handle, &msgs_left))) {
if (msg->msg == CURLMSG_DONE) {
int idx, found = 0;
int idx, found = 0;
/* Find out which handle this message is about */
for (idx=0; idx<HANDLECOUNT; idx++) {
found = (msg->easy_handle == handles[idx]);
if(found)
break;
}
/* Find out which handle this message is about */
for (idx=0; (!found && (idx<HANDLECOUNT)); idx++) found = (msg->easy_handle == handles[idx]);
switch (idx) {
case HTTP_HANDLE:
printf("HTTP transfer completed with status %d\n", msg->data.result);
break;
case FTP_HANDLE:
printf("FTP transfer completed with status %d\n", msg->data.result);
break;
}
switch (idx) {
case HTTP_HANDLE:
printf("HTTP transfer completed with status %d\n", msg->data.result);
break;
case FTP_HANDLE:
printf("FTP transfer completed with status %d\n", msg->data.result);
break;
}
}
}

View File

@@ -209,6 +209,28 @@ the previous request didn't match (see \fICURLOPT_TIMECONDITION\fP). Alas, if
this returns a 1 you know that the reason you didn't get data in return is
because it didn't fulfill the condition. The long ths argument points to will
get a zero stored if the condition instead was met. (Added in 7.19.4)
.IP CURLINFO_RTSP_SESSION_ID
Pass a pointer to a char pointer to receive a pointer to a string holding the
most recent RTSP Session ID.
Applications wishing to resume an RTSP session on another connection should
retreive this info before closing the active connection.
.IP CURLINFO_RTSP_CLIENT_CSEQ
Pass a pointer to a long to receive the next CSeq that will be used by the
application.
.IP CURLINFO_RTSP_SERVER_CSEQ
Pass a pointer to a long to receive the next server CSeq that will be expected
by the application.
\fI(NOTE: listening for server initiated requests is currently
unimplemented).\fP
Applications wishing to resume an RTSP session on another connection should
retreive this info before closing the active connection.
.IP CURLINFO_RTSP_CSEQ_RECV
Pass a pointer to a long to receive the most recently received CSeq from the
server. If your application encounters a \fICURLE_RTSP_CSEQ_ERROR\fP then you
may wish to troubleshoot and/or fix the CSeq mismatch by peeking at this value.
.SH TIMES
.nf
An overview of the six time values available from curl_easy_getinfo()

View File

@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
.\" * Copyright (C) 1998 - 2009, Daniel Stenberg, <daniel@haxx.se>, et al.
.\" * Copyright (C) 1998 - 2010, 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_easy_setopt 3 "11 Dec 2008" "libcurl 7.19.3" "libcurl Manual"
.TH curl_easy_setopt 3 "1 Jan 2010" "libcurl 7.20.0" "libcurl Manual"
.SH NAME
curl_easy_setopt \- set options for a curl easy handle
.SH SYNOPSIS
@@ -49,8 +49,8 @@ thus the string storage associated to the pointer argument may be overwritten
after curl_easy_setopt() returns. Exceptions to this rule are described in
the option details below.
NOTE: before 7.17.0 strings were not copied. Instead the user was forced keep
them available until libcurl no longer needed them.
Before version 7.17.0, strings were not copied. Instead the user was forced
keep them available until libcurl no longer needed them.
The \fIhandle\fP is the return code from a \fIcurl_easy_init(3)\fP or
\fIcurl_easy_duphandle(3)\fP call.
@@ -347,9 +347,9 @@ This function will get called on all new connections made to a server, during
the SSL negotiation. The SSL_CTX pointer will be a new one every time.
To use this properly, a non-trivial amount of knowledge of the openssl
libraries is necessary. For example, using this function allows you to use openssl
callbacks to add additional validation code for certificates, and even to
change the actual URI of an HTTPS request (example used in the lib509 test
libraries is necessary. For example, using this function allows you to use
openssl callbacks to add additional validation code for certificates, and even
to change the actual URI of an HTTPS request (example used in the lib509 test
case). See also the example section for a replacement of the key, certificate
and trust file settings.
.IP CURLOPT_SSL_CTX_DATA
@@ -401,6 +401,30 @@ follows:
You will need to override these definitions if they are different on your
system.
.IP CURLOPT_INTERLEAVEFUNCTION
Function pointer that should match the following prototype: \fIsize_t
function( void *ptr, size_t size, size_t nmemb, void *stream)\fP. This
function gets called by libcurl as soon as it has received interleaved RTP
data. This function gets called for each $ block and therefore contains
exactly one upper-layer protocol unit (e.g. one RTP packet). Curl writes the
interleaved header as well as the included data for each call. The first byte
is always an ASCII dollar sign. The dollar sign is followed by a one byte
channel identifier and then a 2 byte integer length in network byte order. See
\fIRFC 2326 Section 10.12\fP for more information on how RTP interleaving
behaves. If unset or set to NULL, curl will use the default write function.
Interleaved RTP poses some challeneges for the client application. Since the
stream data is sharing the RTSP control connection, it is critical to service
the RTP in a timely fashion. If the RTP data is not handled quickly,
subsequent response processing may become unreasonably delayed and the
connection may close. The application may use \fICURL_RTSPREQ_RECEIVE\fP to
service RTP data when no requests are desired. If the application makes a
request, (e.g. \fICURL_RTSPREQ_PAUSE\fP) then the response handler will
process any pending RTP data before marking the request as finished. (Added
in 7.20.0)
.IP CURLOPT_INTERLEAVEDATA
This is the stream that will be passed to \fICURLOPT_INTERLEAVEFUNCTION\fP when
interleaved RTP data is received. (Added in 7.20.0)
.SH ERROR OPTIONS
.IP CURLOPT_ERRORBUFFER
Pass a char * to a buffer that the libcurl may store human readable error
@@ -449,6 +473,9 @@ on which protocols are supported.
The string given to CURLOPT_URL must be url-encoded and follow RFC 2396
(http://curl.haxx.se/rfc/rfc2396.txt).
Starting with version 7.20.0, the fragment part of the URI will not be send as
part of the path, which was the case previously.
\fICURLOPT_URL\fP is the only option that \fBmust\fP be set before
\fIcurl_easy_perform(3)\fP is called.
@@ -537,23 +564,23 @@ name.
Pass a long. This sets the local port number of the socket used for
connection. This can be used in combination with \fICURLOPT_INTERFACE\fP and
you are recommended to use \fICURLOPT_LOCALPORTRANGE\fP as well when this is
set. Note that the only valid port numbers are 1 - 65535. (Added in 7.15.2)
set. Valid port numbers are 1 - 65535. (Added in 7.15.2)
.IP CURLOPT_LOCALPORTRANGE
Pass a long. This is the number of attempts libcurl should make to find a
working local port number. It starts with the given \fICURLOPT_LOCALPORT\fP
and adds one to the number for each retry. Setting this to 1 or below will
make libcurl do only one try for the exact port number. Note that port numbers
by nature are scarce resources that will be busy at times so setting this
value to something too low might cause unnecessary connection setup
failures. (Added in 7.15.2)
make libcurl do only one try for the exact port number. Port numbers by nature
are scarce resources that will be busy at times so setting this value to
something too low might cause unnecessary connection setup failures. (Added in
7.15.2)
.IP CURLOPT_DNS_CACHE_TIMEOUT
Pass a long, this sets the timeout in seconds. Name resolves will be kept in
memory for this number of seconds. Set to zero to completely disable
caching, or set to -1 to make the cached entries remain forever. By default,
libcurl caches this info for 60 seconds.
NOTE: the name resolve functions of various libc implementations don't re-read
name server information unless explicitly told so (for example, by calling
The name resolve functions of various libc implementations don't re-read name
server information unless explicitly told so (for example, by calling
\fIres_init(3)\fP). This may cause libcurl to keep using the older server even
if DHCP has updated the server info, and this may look like a DNS cache issue
to the casual libcurl-app user.
@@ -674,12 +701,12 @@ Pass a char * as parameter, which should be pointing to the zero terminated
user name to use for the transfer while connecting to Proxy.
The CURLOPT_PROXYUSERNAME option should be used in same way as the
\fICURLOPT_PROXYUSERPWD\fP is used. In comparison to \fICURLOPT_PROXYUSERPWD\fP
the CURLOPT_PROXYUSERNAME allows the username to contain a colon,
like in the following example: "sip:user@example.com".
Note the CURLOPT_PROXYUSERNAME option is an alternative way to set the user name
while connecting to Proxy. There is no meaning to use it together
with the \fICURLOPT_PROXYUSERPWD\fP option.
\fICURLOPT_PROXYUSERPWD\fP is used. In comparison to
\fICURLOPT_PROXYUSERPWD\fP the CURLOPT_PROXYUSERNAME allows the username to
contain a colon, like in the following example: "sip:user@example.com". The
CURLOPT_PROXYUSERNAME option is an alternative way to set the user name while
connecting to Proxy. There is no meaning to use it together with the
\fICURLOPT_PROXYUSERPWD\fP option.
In order to specify the password to be used in conjunction with the user name
use the \fICURLOPT_PROXYPASSWORD\fP option. (Added in 7.19.1)
@@ -736,8 +763,8 @@ it finds suitable. libcurl will automatically select the one it finds most
secure.
.IP CURLAUTH_ANYSAFE
This is a convenience macro that sets all bits except Basic and thus makes
libcurl pick any it finds suitable. libcurl will automatically select the one it
finds most secure.
libcurl pick any it finds suitable. libcurl will automatically select the one
it finds most secure.
.RE
.IP CURLOPT_PROXYAUTH
Pass a long as parameter, which is set to a bitmask, to tell libcurl which
@@ -775,7 +802,7 @@ and follow new Location: headers all the way until no more such headers are
returned. \fICURLOPT_MAXREDIRS\fP can be used to limit the number of redirects
libcurl will follow.
NOTE: since 7.19.4, libcurl can limit to what protocols it will automatically
Since 7.19.4, libcurl can limit what protocols it will automatically
follow. The accepted protocols are set with \fICURLOPT_REDIR_PROTOCOLS\fP and
it excludes the FILE protocol by default.
.IP CURLOPT_UNRESTRICTED_AUTH
@@ -851,7 +878,7 @@ re-used handle, you must explicitly set the new request type using
Pass a void * as parameter, which should be the full data to post in an HTTP
POST operation. You must make sure that the data is formatted the way you want
the server to receive it. libcurl will not convert or encode it for you. Most
web servers will assume this data to be url-encoded. Take note.
web servers will assume this data to be url-encoded.
The pointed data are NOT copied by the library: as a consequence, they must
be preserved by the calling application until the transfer finishes.
@@ -970,9 +997,9 @@ option and thus you need to concatenate them all in one single string. Set
multiple cookies in one string like this: "name1=content1; name2=content2;"
etc.
Note that this option sets the cookie header explictly in the outgoing
request(s). If multiple requests are done due to authentication, followed
redirections or similar, they will all get this cookie passed on.
This option sets the cookie header explictly in the outgoing request(s). If
multiple requests are done due to authentication, followed redirections or
similar, they will all get this cookie passed on.
Using this option multiple times will only make the latest string override the
previous ones.
@@ -1045,14 +1072,27 @@ progress, and will simply stop the download when the server ends the
connection. (added in 7.14.1)
.IP CURLOPT_HTTP_CONTENT_DECODING
Pass a long to tell libcurl how to act on content decoding. If set to zero,
content decoding will be disabled. If set to 1 it is enabled. Note however
that libcurl has no default content decoding but requires you to use
\fICURLOPT_ENCODING\fP for that. (added in 7.16.2)
content decoding will be disabled. If set to 1 it is enabled. Libcurl has no
default content decoding but requires you to use \fICURLOPT_ENCODING\fP for
that. (added in 7.16.2)
.IP CURLOPT_HTTP_TRANSFER_DECODING
Pass a long to tell libcurl how to act on transfer decoding. If set to zero,
transfer decoding will be disabled, if set to 1 it is enabled
(default). libcurl does chunked transfer decoding by default unless this
option is set to zero. (added in 7.16.2)
.SH SMTP OPTIONS
.IP CURLOPT_MAIL_FROM
Pass a pointer to a zero terminated string as parameter. It will be used to
specify the sender address in a mail when sending an SMTP mail with libcurl.
(Added in 7.20.0)
.IP CURLOPT_MAIL_RCPT
Pass a pointer to a linked list of recipients to pass to the server in your
SMTP mail request. The linked list should be a fully valid list of \fBstruct
curl_slist\fP structs properly filled in. Use \fIcurl_slist_append(3)\fP to
create the list and \fIcurl_slist_free_all(3)\fP to clean up an entire list.
(Added in 7.20.0)
.SH TFTP OPTIONS
.IP CURLOPT_TFTP_BLKSIZE
Specify block size to use for TFTP data transmission. Valid range as per RFC
@@ -1147,6 +1187,11 @@ means that it will first attempt to use EPSV before using PASV, but if you
pass zero to this option, it will not try using EPSV, only plain PASV.
If the server is an IPv6 host, this option will have no effect as of 7.12.3.
.IP CURLOPT_FTP_USE_PRET
Pass a long. If the value is 1, it tells curl to send a PRET command before
PASV (and EPSV). Certain FTP servers, mainly drftpd, require this non-standard
command for directory listings as well as up and downloads in PASV mode. Has
no effect when using the active FTP transfers mode. (Added in 7.20.0)
.IP CURLOPT_FTP_CREATE_MISSING_DIRS
Pass a long. If the value is 1, curl will attempt to create any remote
directory that it fails to CWD into. CWD is the command that changes working
@@ -1254,6 +1299,107 @@ file \&"normally" (like in the multicwd case). This is somewhat more standards
compliant than 'nocwd' but without the full penalty of 'multicwd'.
.RE
(Added in 7.15.1)
.SH RTSP OPTIONS
.IP CURLOPT_RTSP_REQUEST
Tell libcurl what kind of RTSP request to make. Pass one of the following RTSP
enum values. Unless noted otherwise, commands require the Session ID to be
initialized. (Added in 7.20.0)
.RS
.IP CURL_RTSPREQ_OPTIONS
Used to retrieve the available methods of the server. The application is
responsbile for parsing and obeying the response. \fB(The session ID is not
needed for this method.)\fP (Added in 7.20.0)
.IP CURL_RTSPREQ_DESCRIBE
Used to get the low level description of a stream. The application should note
what formats it understands in the \fI'Accept:'\fP header. Unless set
manually, libcurl will automatically fill in \fI'Accept:
application/sdp'\fP. Time-condition headers will be added to Describe requests
if the \fICURLOPT_TIMECONDITION\fP option is active. \fB(The session ID is not
needed for this method)\fP (Added in 7.20.0)
.IP CURL_RTSPREQ_ANNOUNCE
When sent by a client, this method changes the description of the session. For
example, if a client is using the server to record a meeting, the client can
use Announce to inform the server of all the meta-information about the
session. ANNOUNCE acts like an HTTP PUT or POST just like
\fICURL_RTSPREQ_SET_PARAMETER\fP (Added in 7.20.0)
.IP CURL_RTSPREQ_SETUP
Setup is used to initialize the transport layer for the session. The
application must set the desired Transport options for a session by using the
\fICURLOPT_RTSP_TRANSPORT\fP option prior to calling setup. If no session ID
is currently set with \fICURLOPT_RTSP_SESSION_ID\fP, libcurl will extract and
use the session ID in the response to this request. \fB(The session ID is not
needed for this method).\fP (Added in 7.20.0)
.IP CURL_RTSPREQ_PLAY
Send a Play command to the server. Use the \fICURLOPT_RANGE\fP option to
modify the playback time (e.g. 'npt=10-15'). (Added in 7.20.0)
.IP CURL_RTSPREQ_PAUSE
Send a Pause command to the server. Use the \fICURLOPT_RANGE\fP option with a
single value to indicate when the stream should be halted. (e.g. npt='25')
(Added in 7.20.0)
.IP CURL_RTSPREQ_TEARDOWN
This command terminates an RTSP session. Simply closing a connection does not
terminate the RTSP session since it is valid to control an RTSP session over
different connections. (Added in 7.20.0)
.IP CURL_RTSPREQ_GET_PARAMETER
Retrieve a parameter from the server. By default, libcurl will automatically
include an \fIAccept: text/parameters\fP header unless a custom one is set.
Applications wishing to send a heartbeat message (e.g. in the presence of a
server-specified timeout) should send use an empty GET_PARAMETER request.
(Added in 7.20.0)
.IP CURL_RTSPREQ_SET_PARAMETER
Set a parameter on the server. By default, libcurl will automatically include
a \fIContent-Type: text/parameters\fP header unless a custom one is set. The
interaction with SET_PARAMTER is much like an HTTP PUT or POST. An application
may either use \fICURLOPT_UPLOAD\fP with \fICURLOPT_READDATA\fP like an HTTP
PUT, or it may use \fICURLOPT_POSTFIELDS\fP like an HTTP POST. No chunked
transfers are allowed, so the application must set the
\fICURLOPT_INFILESIZE\fP in the former and \fICURLOPT_POSTFIELDSIZE\fP in the
latter. Also, there is no use of multi-part POSTs within RTSP. (Added in
7.20.0)
.IP CURL_RTSPREQ_RECORD
Used to tell the server to record a session. Use the \fICURLOPT_RANGE\fP
option to modify the record time. (Added in 7.20.0)
.IP CURL_RTSPREQ_RECEIVE
This is a special request because it does not send any data to the server. The
application may call this function in order to receive interleaved RTP
data. It will return after processing one read buffer of data in order to give
the application a chance to run. (Added in 7.20.0)
.RE
.IP CURLOPT_RTSP_SESSION_ID
Pass a char * as a parameter to set the value of the current RTSP Session ID
for the handle. Useful for resuming an in-progress session. Once this value is
set to any non-NULL value, libcurl will return \fICURLE_RTSP_SESSION_ERROR\fP
if ID received from the server does not match. If unset (or set to NULL),
libcurl will automatically set the ID the first time the server sets it in a
response. (Added in 7.20.0)
.IP CURLOPT_RTSP_STREAM_URI
Set the stream URI to operate on by passing a char * . For example, a single
session may be controlling \fIrtsp://foo/twister/audio\fP and
\fIrtsp://foo/twister/video\fP and the application can switch to the
appropriate stream using this option. If unset, libcurl will default to
operating on generic server options by passing '*' in the place of the RTSP
Stream URI. This option is distinct from \fICURLOPT_URL\fP. When working with
RTSP, the \fICURLOPT_STREAM_URI\fP indicates what URL to send to the server in
the request header while the \fICURLOPT_URL\fP indicates where to make the
connection to. (e.g. the \fICURLOPT_URL\fP for the above examples might be
set to \fIrtsp://foo/twister\fP (Added in 7.20.0)
.IP CURLOPT_RTSP_TRANSPORT
Pass a char * to tell libcurl what to pass for the Transport: header for this
RTSP session. This is mainly a convenience method to avoid needing to set a
custom Transport: header for every SETUP request. The application must set a
Transport: header before issuing a SETUP request. (Added in 7.20.0)
.IP CURLOPT_RTSP_HEADER
This option is simply an alias for \fICURLOPT_HTTP_HEADER\fP. Use this to
replace the standard headers that RTSP and HTTP share. It is also valid to use
the shortcuts such as \fICURLOPT_USERAGENT\fP. (Added in 7.20.0)
.IP CURLOPT_RTSP_CLIENT_CSEQ
Manually set the the CSEQ number to issue for the next RTSP request. Useful if
the application is resuming a previously broken connection. The CSEQ will
increment from this new number henceforth. (Added in 7.20.0)
.IP CURLOPT_RTSP_SERVER_CSEQ
Manually set the CSEQ number to expect for the next RTSP Server->Client
request. At the moment, this feature (listening for Server requests) is
unimplemented. (Added in 7.20.0)
.SH PROTOCOL OPTIONS
.IP CURLOPT_TRANSFERTEXT
A parameter set to 1 tells the library to use ASCII mode for FTP transfers,
@@ -1280,9 +1426,14 @@ want. It should be in the format "X-Y", where X or Y may be left out. HTTP
transfers also support several intervals, separated with commas as in
\fI"X-Y,N-M"\fP. Using this kind of multiple intervals will cause the HTTP
server to send the response document in pieces (using standard MIME separation
techniques). Pass a NULL to this option to disable the use of ranges.
techniques). For RTSP, the formatting of a range should follow RFC 2326
Section 12.29. For RTSP, byte ranges are \fBnot\fP permitted. Instead, ranges
should be given in npt, utc, or smpte formats.
Ranges work on HTTP, FTP and FILE (since 7.18.0) transfers only.
Pass a NULL to this option to disable the use of ranges.
Ranges work on HTTP, FTP, FILE (since 7.18.0), and RTSP (since 7.20.0)
transfers only.
.IP CURLOPT_RESUME_FROM
Pass a long as parameter. It contains the offset in number of bytes that you
want the transfer to start from. Set this option to 0 to make the transfer
@@ -1341,8 +1492,8 @@ as a long. See also \fICURLOPT_INFILESIZE_LARGE\fP.
For uploading using SCP, this option or \fICURLOPT_INFILESIZE_LARGE\fP is
mandatory.
Note that this option does not limit how much data libcurl will actually send,
as that is controlled entirely by what the read callback returns.
This option does not limit how much data libcurl will actually send, as that
is controlled entirely by what the read callback returns.
.IP CURLOPT_INFILESIZE_LARGE
When uploading a file to a remote site, this option should be used to tell
libcurl what the expected size of the infile is. This value should be passed
@@ -1350,8 +1501,8 @@ as a curl_off_t. (Added in 7.11.0)
For uploading using SCP, this option or \fICURLOPT_INFILESIZE\fP is mandatory.
Note that this option does not limit how much data libcurl will actually send,
as that is controlled entirely by what the read callback returns.
This option does not limit how much data libcurl will actually send, as that
is controlled entirely by what the read callback returns.
.IP CURLOPT_UPLOAD
A parameter set to 1 tells the library to prepare for an upload. The
\fICURLOPT_READDATA\fP and \fICURLOPT_INFILESIZE\fP or
@@ -1387,7 +1538,8 @@ given limit. This concerns both FTP and HTTP transfers.
.IP CURLOPT_TIMECONDITION
Pass a long as parameter. This defines how the \fICURLOPT_TIMEVALUE\fP time
value is treated. You can set this parameter to \fICURL_TIMECOND_IFMODSINCE\fP
or \fICURL_TIMECOND_IFUNMODSINCE\fP. This feature applies to HTTP and FTP.
or \fICURL_TIMECOND_IFUNMODSINCE\fP. This feature applies to HTTP, FTP, and
RTSP.
The last modification time of a file is not always known and in such instances
this feature will have no effect even if the given time condition would not
@@ -1447,9 +1599,9 @@ If you already have performed transfers with this curl handle, setting a
smaller MAXCONNECTS than before may cause open connections to get closed
unnecessarily.
Note that if you add this easy handle to a multi handle, this setting is not
acknowledged, and you must instead use \fIcurl_multi_setopt(3)\fP and
the \fICURLMOPT_MAXCONNECTS\fP option.
If you add this easy handle to a multi handle, this setting is not
acknowledged, and you must instead use \fIcurl_multi_setopt(3)\fP and the
\fICURLMOPT_MAXCONNECTS\fP option.
.IP CURLOPT_CLOSEPOLICY
(Obsolete) This option does nothing.
.IP CURLOPT_FRESH_CONNECT
@@ -1549,10 +1701,9 @@ operations.
If the crypto device cannot be set, \fICURLE_SSL_ENGINE_SETFAILED\fP is
returned.
Note that even though this option doesn't need any parameter, in some
configurations \fIcurl_easy_setopt\fP might be defined as a macro taking
exactly three arguments. Therefore, it's recommended to pass 1 as parameter to
this option.
Even though this option doesn't need any parameter, in some configurations
\fIcurl_easy_setopt\fP might be defined as a macro taking exactly three
arguments. Therefore, it's recommended to pass 1 as parameter to this option.
.IP CURLOPT_SSLVERSION
Pass a long as parameter to control what version of SSL/TLS to attempt to use.
The available options are:
@@ -1598,8 +1749,8 @@ combination with the \fICURLOPT_SSL_VERIFYPEER\fP option. If
\fICURLOPT_SSL_VERIFYPEER\fP is zero, \fICURLOPT_CAINFO\fP need not
even indicate an accessible file.
Note that option is by default set to the system path where libcurl's cacert
bundle is assumed to be stored, as established at build time.
This option is by default set to the system path where libcurl's cacert bundle
is assumed to be stored, as established at build time.
When built against NSS, this is the directory that the NSS certificate
database resides in.
@@ -1608,8 +1759,8 @@ Pass a char * to a zero terminated string naming a file holding a CA
certificate in PEM format. If the option is set, an additional check against
the peer certificate is performed to verify the issuer is indeed the one
associated with the certificate provided by the option. This additional check
is useful in multi-level PKI where one needs to enforce that the peer certificate is
from a specific branch of the tree.
is useful in multi-level PKI where one needs to enforce that the peer
certificate is from a specific branch of the tree.
This option makes sense only when used in combination with the
\fICURLOPT_SSL_VERIFYPEER\fP option. Otherwise, the result of the check is not
@@ -1644,8 +1795,8 @@ This option makes sense only when used in combination with the
A specific error code (CURLE_SSL_CRL_BADFILE) is defined with the option. It
is returned when the SSL exchange fails because the CRL file cannot be loaded.
Note that a failure in certificate verification due to a revocation information
found in the CRL does not trigger this specific error. (Added in 7.19.0)
A failure in certificate verification due to a revocation information found in
the CRL does not trigger this specific error. (Added in 7.19.0)
.IP CURLOPT_CERTINFO
Pass a long set to 1 to enable libcurl's certificate chain info gatherer. With
this enabled, libcurl (if built with OpenSSL) will extract lots of information
@@ -1712,7 +1863,7 @@ You'll find more details about the NSS cipher lists on this URL:
.IP CURLOPT_SSL_SESSIONID_CACHE
Pass a long set to 0 to disable libcurl's use of SSL session-ID caching. Set
this to 1 to enable it. By default all transfers are done using the
cache. Note that while nothing ever should get hurt by attempting to reuse SSL
cache. While nothing ever should get hurt by attempting to reuse SSL
session-IDs, there seem to be broken SSL implementations in the wild that may
require you to disable this in order for you to succeed. (Added in 7.16.0)
.IP CURLOPT_KRBLEVEL
@@ -1740,9 +1891,9 @@ libcurl defaults to using \fB~/.ssh/id_dsa.pub\fP.
(Added in 7.16.1)
.IP CURLOPT_SSH_PRIVATE_KEYFILE
Pass a char * pointing to a file name for your private key. If not used,
libcurl defaults to using \fB~/.ssh/id_dsa\fP.
If the file is password-protected, set the password with \fICURLOPT_KEYPASSWD\fP.
(Added in 7.16.1)
libcurl defaults to using \fB~/.ssh/id_dsa\fP. If the file is
password-protected, set the password with \fICURLOPT_KEYPASSWD\fP. (Added in
7.16.1)
.IP CURLOPT_SSH_KNOWNHOSTS
Pass a pointer to a zero terminated string holding the file name of the
known_host file to use. The known_hosts file should use the OpenSSH file
@@ -1761,9 +1912,9 @@ MUST return one of the following return codes to tell libcurl how to act:
.IP CURLKHSTAT_FINE_ADD_TO_FILE
The host+key is accepted and libcurl will append it to the known_hosts file
before continuing with the connection. This will also add the host+key combo
to the known_host pool kept in memory if it wasn't already present there. Note
that the adding of data to the file is done by completely replacing the file
with a new copy, so the permissions of the file must allow this.
to the known_host pool kept in memory if it wasn't already present there. The
adding of data to the file is done by completely replacing the file with a new
copy, so the permissions of the file must allow this.
.IP CURLKHSTAT_FINE
The host+key is accepted libcurl will continue with the connection. This will
also add the host+key combo to the known_host pool kept in memory if it wasn't

View File

@@ -21,21 +21,22 @@ but be sure to FD_ZERO them before calling this function as
otherwise remove any others. The \fIcurl_multi_perform(3)\fP function should be
called as soon as one of them is ready to be read from or written to.
To be sure to have up-to-date results, you should call
\fIcurl_multi_perform\fP until it does not return CURLM_CALL_MULTI_PERFORM
prior to calling \fIcurl_multi_fdset\fP. This will make sure that libcurl has
updated the handles' socket states.
If no file descriptors are set by libcurl, \fImax_fd\fP will contain -1 when
this function returns. Otherwise it will contain the higher descriptor number
libcurl set.
You should also be aware that when doing select(), you should consider using a
rather small (single-digit number of seconds) timeout and call
\fIcurl_multi_perform\fP regularly - even if no activity has been seen on the
fd_sets - as otherwise libcurl-internal retries and timeouts may not work as
you'd think and want.
Starting with libcurl 7.16.0, you should use \fBcurl_multi_timeout\fP to
figure out how long to wait for action.
When doing select(), you should use \fBcurl_multi_timeout\fP to figure out how
long to wait for action. Call \fIcurl_multi_perform\fP even if no activity has
been seen on the fd_sets after the timeout expires as otherwise internal
retries and timeouts may not work as you'd think and want.
.SH RETURN VALUE
CURLMcode type, general libcurl multi interface error code. See
\fIlibcurl-errors(3)\fP
.SH "SEE ALSO"
.BR curl_multi_cleanup "(3)," curl_multi_init "(3), "
.BR curl_multi_timeout "(3) "
.BR curl_multi_cleanup "(3), " curl_multi_init "(3), "
.BR curl_multi_timeout "(3), " curl_multi_perform "(3) "

View File

@@ -22,25 +22,26 @@ changed from the previous call (or is less than the amount of easy handles
you've added to the multi handle), you know that there is one or more
transfers less "running". You can then call \fIcurl_multi_info_read(3)\fP to
get information about each individual completed transfer, and that returned
info includes CURLcode and more.
info includes CURLcode and more. If an added handle fails very quickly, it may
never be counted as a running_handle.
When \fIrunning_handles\fP is set to zero (0) on the return of this function,
there is no longer any transfers in progress.
.SH "RETURN VALUE"
CURLMcode type, general libcurl multi interface error code.
If you receive \fICURLM_CALL_MULTI_PERFORM\fP, this basically means that you
should call \fIcurl_multi_perform\fP again, before you select() on more
actions. You don't have to do it immediately, but the return code means that
libcurl may have more data available to return or that there may be more data
to send off before it is "satisfied". Do note that \fIcurl_multi_perform(3)\fP
will return \fICURLM_CALL_MULTI_PERFORM\fP only when it wants to be called
again \fBimmediately\fP. When things are fine and there is nothing immediate
it wants done, it'll return \fICURLM_OK\fP and you need to wait for \&"action"
and then call this function again.
Before version 7.20.0: If you receive \fICURLM_CALL_MULTI_PERFORM\fP, this
basically means that you should call \fIcurl_multi_perform\fP again, before
you select() on more actions. You don't have to do it immediately, but the
return code means that libcurl may have more data available to return or that
there may be more data to send off before it is "satisfied". Do note that
\fIcurl_multi_perform(3)\fP will return \fICURLM_CALL_MULTI_PERFORM\fP only
when it wants to be called again \fBimmediately\fP. When things are fine and
there is nothing immediate it wants done, it'll return \fICURLM_OK\fP and you
need to wait for \&"action" and then call this function again.
NOTE that this only returns errors etc regarding the whole multi stack. Problems
still might have occurred on individual transfers even when this
This function only returns errors etc regarding the whole multi stack.
Problems still might have occurred on individual transfers even when this
function returns \fICURLM_OK\fP.
.SH "TYPICAL USAGE"
Most applications will use \fIcurl_multi_fdset(3)\fP to get the multi_handle's

View File

@@ -22,8 +22,8 @@ CURL_CSELECT_ERR. When the events on a socket are unknown, pass 0 instead, and
libcurl will test the descriptor internally.
At return, the integer \fBrunning_handles\fP points to will contain the number
of still running easy handles within the multi handle. When this number
reaches zero, all transfers are complete/done. Note that when you call
of running easy handles within the multi handle. When this number reaches
zero, all transfers are complete/done. When you call
\fIcurl_multi_socket_action(3)\fP on a specific socket and the counter
decreases by one, it DOES NOT necessarily mean that this exact socket/transfer
is the one that completed. Use \fIcurl_multi_info_read(3)\fP to figure out
@@ -89,19 +89,16 @@ The \fIuserp\fP argument is a private pointer you have previously set with
.SH "RETURN VALUE"
CURLMcode type, general libcurl multi interface error code.
Legacy: If you receive \fICURLM_CALL_MULTI_PERFORM\fP, this basically means
that you should call \fIcurl_multi_socket_action(3)\fP again, before you wait
for more actions on libcurl's sockets. You don't have to do it immediately,
but the return code means that libcurl may have more data available to return
or that there may be more data to send off before it is "satisfied".
Before version 7.20.0: If you receive \fICURLM_CALL_MULTI_PERFORM\fP, this
basically means that you should call \fIcurl_multi_socket_action(3)\fP again
before you wait for more actions on libcurl's sockets. You don't have to do it
immediately, but the return code means that libcurl may have more data
available to return or that there may be more data to send off before it is
"satisfied".
In modern libcurls (from around 7.19.0 or later),
\fICURLM_CALL_MULTI_PERFORM\fP or \fICURLM_CALL_MULTI_SOKCET\fP will not be
returned and no application needs to care about them.
NOTE that the return code from this function is for the whole multi stack.
Problems still might have occurred on individual transfers even when one of
these functions return OK.
The return code from this function is for the whole multi stack. Problems
still might have occurred on individual transfers even when one of these
functions return OK.
.SH "TYPICAL USAGE"
1. Create a multi handle

View File

@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
.\" * Copyright (C) 1998 - 2008, Daniel Stenberg, <daniel@haxx.se>, et al.
.\" * Copyright (C) 1998 - 2010, 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 libcurl-errors 3 "8 Jun 2008" "libcurl 7.19.0" "libcurl errors"
.TH libcurl-errors 3 "1 Jan 2010" "libcurl 7.20.0" "libcurl errors"
.SH NAME
libcurl-errors \- error codes in libcurl
.SH DESCRIPTION
@@ -70,6 +70,11 @@ either a PASV or a EPSV command. The server is flawed.
.IP "CURLE_FTP_WEIRD_227_FORMAT (14)"
FTP servers return a 227-line as a response to a PASV command. If libcurl
fails to parse that line, this return code is passed back.
.IP "CURLE_FTP_PRET_FAILED (84)"
The FTP server does not understand the PRET command at all or does not support
the given argument. Be careful when using \fICURLOPT_CUSTOMREQUEST\fP, a
custom LIST command will be sent with PRET CMD before PASV as well. (Added in
7.20.0)
.IP "CURLE_FTP_CANT_GET_HOST (15)"
An internal failure to lookup the host used for the new connection.
.IP "CURLE_FTP_COULDNT_SET_TYPE (17)"
@@ -87,15 +92,13 @@ returned an error code that was 400 or higher (for FTP) or otherwise
indicated unsuccessful completion of the command.
.IP "CURLE_HTTP_RETURNED_ERROR (22)"
This is returned if CURLOPT_FAILONERROR is set TRUE and the HTTP server
returns an error code that is >= 400. (This error code was formerly known as
CURLE_HTTP_NOT_FOUND.)
returns an error code that is >= 400.
.IP "CURLE_WRITE_ERROR (23)"
An error occurred when writing received data to a local file, or an error was
returned to libcurl from a write callback.
.IP "CURLE_UPLOAD_FAILED (25)"
Failed starting the upload. For FTP, the server typically denied the STOR
command. The error buffer usually contains the server's explanation for this.
(This error code was formerly known as CURLE_FTP_COULDNT_STOR_FILE.)
.IP "CURLE_READ_ERROR (26)"
There was a problem reading a local file or an error returned by the read
callback.
@@ -120,8 +123,9 @@ A problem occurred somewhere in the SSL/TLS handshake. You really want the
error buffer and read the message there as it pinpoints the problem slightly
more. Could be certificates (file formats, paths, permissions), passwords, and
others.
.IP "CURLE_FTP_BAD_DOWNLOAD_RESUME (36)"
Attempting FTP resume beyond file size.
.IP "CURLE_BAD_DOWNLOAD_RESUME (36)"
The download could not be resumed because the specified offset was out of the
file boundary.
.IP "CURLE_FILE_COULDNT_READ_FILE (37)"
A file given with FILE:// couldn't be opened. Most likely because the file
path doesn't identify an existing file. Did you check file permissions?
@@ -138,8 +142,7 @@ Internal error. A function was called with a bad parameter.
.IP "CURLE_INTERFACE_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. (This error code was formerly known as
CURLE_HTTP_PORT_FAILED.)
CURLOPT_INTERFACE.
.IP "CURLE_TOO_MANY_REDIRECTS (47)"
Too many redirects. When following redirects, libcurl hit the maximum amount.
Set your limit with CURLOPT_MAXREDIRS.

View File

@@ -55,6 +55,10 @@ AC_DEFUN([LIBCURL_CHECK_CONFIG],
AH_TEMPLATE([LIBCURL_PROTOCOL_LDAP],[Defined if libcurl supports LDAP])
AH_TEMPLATE([LIBCURL_PROTOCOL_DICT],[Defined if libcurl supports DICT])
AH_TEMPLATE([LIBCURL_PROTOCOL_TFTP],[Defined if libcurl supports TFTP])
AH_TEMPLATE([LIBCURL_PROTOCOL_RTSP],[Defined if libcurl supports RTSP])
AH_TEMPLATE([LIBCURL_PROTOCOL_POP3],[Defined if libcurl supports POP3])
AH_TEMPLATE([LIBCURL_PROTOCOL_IMAP],[Defined if libcurl supports IMAP])
AH_TEMPLATE([LIBCURL_PROTOCOL_SMTP],[Defined if libcurl supports SMTP])
AC_ARG_WITH(libcurl,
AC_HELP_STRING([--with-libcurl=DIR],[look for the curl library in DIR]),
@@ -194,17 +198,23 @@ x=CURLOPT_VERBOSE;
# We don't have --protocols, so just assume that all
# protocols are available
_libcurl_protocols="HTTP FTP FILE TELNET LDAP DICT"
_libcurl_protocols="HTTP FTP FILE TELNET LDAP DICT TFTP
if test x$libcurl_feature_SSL = xyes ; then
_libcurl_protocols="$_libcurl_protocols HTTPS"
# FTPS wasn't standards-compliant until version
# 7.11.0
# 7.11.0 (0x070b00 == 461568)
if test $_libcurl_version -ge 461568; then
_libcurl_protocols="$_libcurl_protocols FTPS"
fi
fi
# RTSP, IMAP, POP3 and SMTP were added in
# 7.20.0 (0x071400 == 463872)
if test $_libcurl_version -ge 463872; then
_libcurl_protocols="$_libcurl_protocols RTSP IMAP POP3 SMTP"
fi
fi
for _libcurl_protocol in $_libcurl_protocols ; do

View File

@@ -37,7 +37,7 @@ CURLE_FAILED_INIT 7.1
CURLE_FILESIZE_EXCEEDED 7.10.8
CURLE_FILE_COULDNT_READ_FILE 7.1
CURLE_FTP_ACCESS_DENIED 7.1
CURLE_FTP_BAD_DOWNLOAD_RESUME 7.1
CURLE_FTP_BAD_DOWNLOAD_RESUME 7.1 7.1
CURLE_FTP_CANT_GET_HOST 7.1
CURLE_FTP_CANT_RECONNECT 7.1 7.17.0
CURLE_FTP_COULDNT_GET_SIZE 7.1 7.17.0
@@ -47,7 +47,9 @@ CURLE_FTP_COULDNT_SET_BINARY 7.1 7.17.0
CURLE_FTP_COULDNT_SET_TYPE 7.17.0
CURLE_FTP_COULDNT_STOR_FILE 7.1
CURLE_FTP_COULDNT_USE_REST 7.1
CURLE_FTP_PARTIAL_FILE 7.1 7.1
CURLE_FTP_PORT_FAILED 7.1
CURLE_FTP_PRET_FAILED 7.20.0
CURLE_FTP_QUOTE_ERROR 7.1 7.17.0
CURLE_FTP_SSL_FAILED - 7.17.0
CURLE_FTP_USER_PASSWORD_INCORRECT 7.1 7.17.0
@@ -74,13 +76,15 @@ CURLE_OPERATION_TIMEDOUT 7.17.0
CURLE_OPERATION_TIMEOUTED 7.1 7.17.0
CURLE_OUT_OF_MEMORY 7.1
CURLE_PARTIAL_FILE 7.1
CURLE_PEER_FAILED_VERIFICATION - 7.17.1
CURLE_PEER_FAILED_VERIFICATION 7.17.1
CURLE_QUOTE_ERROR 7.17.0
CURLE_RANGE_ERROR 7.17.0
CURLE_READ_ERROR 7.1
CURLE_RECV_ERROR 7.13.0
CURLE_REMOTE_ACCESS_DENIED 7.17.0
CURLE_REMOTE_DISK_FULL 7.17.0
CURLE_RTSP_CSEQ_ERROR 7.20.0
CURLE_RTSP_SESSION_ERROR 7.20.0
CURLE_SEND_ERROR 7.13.0
CURLE_SHARE_IN_USE - 7.17.0
CURLE_SSH 7.16.1
@@ -93,7 +97,7 @@ CURLE_SSL_ENGINE_INITFAILED 7.13.0
CURLE_SSL_ENGINE_NOTFOUND 7.9.3
CURLE_SSL_ENGINE_SETFAILED 7.9.3
CURLE_SSL_ISSUER_ERROR 7.19.0
CURLE_SSL_PEER_CERTIFICATE 7.17.1
CURLE_SSL_PEER_CERTIFICATE - 7.17.1
CURLE_SSL_SHUTDOWN_FAILED 7.16.1
CURLE_TELNET_OPTION_SYNTAX 7.7
CURLE_TFTP_DISKFULL 7.15.0 7.17.0
@@ -231,7 +235,17 @@ CURLOPT_FTP_SSL 7.11.0 7.16.4
CURLOPT_FTP_SSL_CCC 7.16.1
CURLOPT_FTP_USE_EPRT 7.10.5
CURLOPT_FTP_USE_EPSV 7.9.2
CURLOPT_FTP_USE_PRET 7.20.0
CURLOPT_RTSP_REQUEST 7.20.0
CURLOPT_RTSP_SESSION_ID 7.20.0
CURLOPT_RTSP_STREAM_URI 7.20.0
CURLOPT_RTSP_TRANSPORT 7.20.0
CURLOPT_RTSP_CLIENT_CSEQ 7.20.0
CURLOPT_RTSP_SERVER_CSEQ 7.20.0
CURLOPT_INTERLEAVEDATA 7.20.0
CURLOPT_INTERLEAVEFUNCTION 7.20.0
CURLOPT_HEADER 7.1
CURLOPT_HEADERDATA 7.10
CURLOPT_HEADERFUNCTION 7.7.2
CURLOPT_HTTP200ALIASES 7.10.3
CURLOPT_HTTPAUTH 7.10.6
@@ -259,6 +273,8 @@ CURLOPT_LOCALPORT 7.15.2
CURLOPT_LOCALPORTRANGE 7.15.2
CURLOPT_LOW_SPEED_LIMIT 7.1
CURLOPT_LOW_SPEED_TIME 7.1
CURLOPT_MAIL_FROM 7.20.0
CURLOPT_MAIL_RCPT 7.20.0
CURLOPT_MAXCONNECTS 7.7
CURLOPT_MAXFILESIZE 7.10.8
CURLOPT_MAXFILESIZE_LARGE 7.11.0
@@ -374,10 +390,17 @@ CURLPROTO_FTP 7.19.4
CURLPROTO_FTPS 7.19.4
CURLPROTO_HTTP 7.19.4
CURLPROTO_HTTPS 7.19.4
CURLPROTO_IMAP 7.20.0
CURLPROTO_IMAPS 7.20.0
CURLPROTO_LDAP 7.19.4
CURLPROTO_LDAPS 7.19.4
CURLPROTO_POP3 7.20.0
CURLPROTO_POP3S 7.20.0
CURLPROTO_RTSP 7.20.0
CURLPROTO_SCP 7.19.4
CURLPROTO_SFTP 7.19.4
CURLPROTO_SMTP 7.20.0
CURLPROTO_SMTPS 7.20.0
CURLPROTO_TELNET 7.19.4
CURLPROTO_TFTP 7.19.4
CURLPROXY_HTTP 7.10

View File

@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2009, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2010, 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
@@ -47,6 +47,11 @@
#include <stdio.h>
#include <limits.h>
#if defined(__FreeBSD__) && (__FreeBSD__ >= 2)
/* Needed for __FreeBSD_version symbol definition */
#include <osreldate.h>
#endif
/* The include stuff here below is mainly for time_t! */
#include <sys/types.h>
#include <time.h>
@@ -66,7 +71,8 @@
require it! */
#if defined(_AIX) || defined(__NOVELL_LIBC__) || defined(__NetBSD__) || \
defined(__minix) || defined(__SYMBIAN32__) || defined(__INTEGRITY) || \
defined(ANDROID)
defined(ANDROID) || \
(defined(__FreeBSD_version) && (__FreeBSD_version < 800000))
#include <sys/select.h>
#endif
@@ -236,14 +242,6 @@ typedef curl_socket_t
curlsocktype purpose,
struct curl_sockaddr *address);
#ifndef CURL_NO_OLDIES
/* not used since 7.10.8, will be removed in a future release */
typedef int (*curl_passwd_callback)(void *clientp,
const char *prompt,
char *buffer,
int buflen);
#endif
typedef enum {
CURLIOE_OK, /* I/O operation successful */
CURLIOE_UNKNOWNCMD, /* command was unknown to callback */
@@ -407,6 +405,10 @@ typedef enum {
wrong format (Added in 7.19.0) */
CURLE_SSL_ISSUER_ERROR, /* 83 - Issuer check failed. (Added in
7.19.0) */
CURLE_FTP_PRET_FAILED, /* 84 - a PRET command failed */
CURLE_RTSP_CSEQ_ERROR, /* 85 - mismatch of RTSP CSeq numbers */
CURLE_RTSP_SESSION_ERROR, /* 86 - mismatch of RTSP Session Identifiers */
CURL_LAST /* never use! */
} CURLcode;
@@ -613,6 +615,13 @@ typedef enum {
#define CURLPROTO_DICT (1<<9)
#define CURLPROTO_FILE (1<<10)
#define CURLPROTO_TFTP (1<<11)
#define CURLPROTO_IMAP (1<<12)
#define CURLPROTO_IMAPS (1<<13)
#define CURLPROTO_POP3 (1<<14)
#define CURLPROTO_POP3S (1<<15)
#define CURLPROTO_SMTP (1<<16)
#define CURLPROTO_SMTPS (1<<17)
#define CURLPROTO_RTSP (1<<18)
#define CURLPROTO_ALL (~0) /* enable everything */
/* long may be 32 or 64 bits, but we should never depend on anything else
@@ -1028,6 +1037,7 @@ typedef enum {
essentially places a demand on the FTP server to acknowledge commands
in a timely manner. */
CINIT(FTP_RESPONSE_TIMEOUT, LONG, 112),
#define CURLOPT_SERVER_RESPONSE_TIMEOUT CURLOPT_FTP_RESPONSE_TIMEOUT
/* Set this option to one of the CURL_IPRESOLVE_* defines (see below) to
tell libcurl to resolve names to those IP versions only. This only has
@@ -1272,6 +1282,39 @@ typedef enum {
/* set the SSH host key callback custom pointer */
CINIT(SSH_KEYDATA, OBJECTPOINT, 185),
/* set the SMTP mail originator */
CINIT(MAIL_FROM, OBJECTPOINT, 186),
/* set the SMTP mail receiver(s) */
CINIT(MAIL_RCPT, OBJECTPOINT, 187),
/* FTP: send PRET before PASV */
CINIT(FTP_USE_PRET, LONG, 188),
/* RTSP request method (OPTIONS, SETUP, PLAY, etc...) */
CINIT(RTSP_REQUEST, LONG, 189),
/* The RTSP session identifier */
CINIT(RTSP_SESSION_ID, OBJECTPOINT, 190),
/* The RTSP stream URI */
CINIT(RTSP_STREAM_URI, OBJECTPOINT, 191),
/* The Transport: header to use in RTSP requests */
CINIT(RTSP_TRANSPORT, OBJECTPOINT, 192),
/* Manually initialize the client RTSP CSeq for this handle */
CINIT(RTSP_CLIENT_CSEQ, LONG, 193),
/* Manually initialize the server RTSP CSeq for this handle */
CINIT(RTSP_SERVER_CSEQ, LONG, 194),
/* The stream to pass to INTERLEAVEFUNCTION. */
CINIT(INTERLEAVEDATA, OBJECTPOINT, 195),
/* Let the application define a custom write method for RTP data */
CINIT(INTERLEAVEFUNCTION, FUNCTIONPOINT, 196),
CURLOPT_LASTENTRY /* the last unused */
} CURLoption;
@@ -1315,6 +1358,7 @@ typedef enum {
#define CURLOPT_WRITEDATA CURLOPT_FILE
#define CURLOPT_READDATA CURLOPT_INFILE
#define CURLOPT_HEADERDATA CURLOPT_WRITEHEADER
#define CURLOPT_RTSPHEADER CURLOPT_HTTPHEADER
/* These enums are for use with the CURLOPT_HTTP_VERSION option. */
enum {
@@ -1327,6 +1371,25 @@ enum {
CURL_HTTP_VERSION_LAST /* *ILLEGAL* http version */
};
/*
* Public API enums for RTSP requests
*/
enum {
CURL_RTSPREQ_NONE, /* first in list */
CURL_RTSPREQ_OPTIONS,
CURL_RTSPREQ_DESCRIBE,
CURL_RTSPREQ_ANNOUNCE,
CURL_RTSPREQ_SETUP,
CURL_RTSPREQ_PLAY,
CURL_RTSPREQ_PAUSE,
CURL_RTSPREQ_TEARDOWN,
CURL_RTSPREQ_GET_PARAMETER,
CURL_RTSPREQ_SET_PARAMETER,
CURL_RTSPREQ_RECORD,
CURL_RTSPREQ_RECEIVE,
CURL_RTSPREQ_LAST /* last in list */
};
/* These enums are for use with the CURLOPT_NETRC option. */
enum CURL_NETRC_OPTION {
CURL_NETRC_IGNORED, /* The .netrc will never be read.
@@ -1696,9 +1759,13 @@ typedef enum {
CURLINFO_APPCONNECT_TIME = CURLINFO_DOUBLE + 33,
CURLINFO_CERTINFO = CURLINFO_SLIST + 34,
CURLINFO_CONDITION_UNMET = CURLINFO_LONG + 35,
CURLINFO_RTSP_SESSION_ID = CURLINFO_STRING + 36,
CURLINFO_RTSP_CLIENT_CSEQ = CURLINFO_LONG + 37,
CURLINFO_RTSP_SERVER_CSEQ = CURLINFO_LONG + 38,
CURLINFO_RTSP_CSEQ_RECV = CURLINFO_LONG + 39,
/* Fill in new entries below here! */
CURLINFO_LASTONE = 35
CURLINFO_LASTONE = 39
} CURLINFO;
/* CURLINFO_RESPONSE_CODE is the new name for the option previously known as

View File

@@ -370,16 +370,7 @@
# define CURL_SIZEOF_CURL_SOCKLEN_T 4
#elif defined(__VMS)
# if defined(__alpha) || defined(__ia64)
# define CURL_SIZEOF_LONG 4
# define CURL_TYPEOF_CURL_OFF_T long long
# define CURL_FORMAT_CURL_OFF_T "lld"
# define CURL_FORMAT_CURL_OFF_TU "llu"
# define CURL_FORMAT_OFF_T "%lld"
# define CURL_SIZEOF_CURL_OFF_T 8
# define CURL_SUFFIX_CURL_OFF_T LL
# define CURL_SUFFIX_CURL_OFF_TU ULL
# else
# if defined(__VAX)
# define CURL_SIZEOF_LONG 4
# define CURL_TYPEOF_CURL_OFF_T long
# define CURL_FORMAT_CURL_OFF_T "ld"
@@ -388,6 +379,15 @@
# define CURL_SIZEOF_CURL_OFF_T 4
# define CURL_SUFFIX_CURL_OFF_T L
# define CURL_SUFFIX_CURL_OFF_TU UL
# else
# define CURL_SIZEOF_LONG 4
# define CURL_TYPEOF_CURL_OFF_T long long
# define CURL_FORMAT_CURL_OFF_T "lld"
# define CURL_FORMAT_CURL_OFF_TU "llu"
# define CURL_FORMAT_OFF_T "%lld"
# define CURL_SIZEOF_CURL_OFF_T 8
# define CURL_SUFFIX_CURL_OFF_T LL
# define CURL_SUFFIX_CURL_OFF_TU ULL
# endif
# define CURL_TYPEOF_CURL_SOCKLEN_T unsigned int
# define CURL_SIZEOF_CURL_SOCKLEN_T 4

View File

@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2009, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2010, 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
@@ -246,4 +246,8 @@ typedef char
#undef CURL_TYPEOF_CURL_SOCKLEN_T
#undef CURL_TYPEOF_CURL_OFF_T
#ifdef CURL_NO_OLDIES
#undef CURL_FORMAT_OFF_T /* not required since 7.19.0 - obsoleted in 7.20.0 */
#endif
#endif /* __CURL_CURLRULES_H */

View File

@@ -31,13 +31,13 @@
/* This is the version number of the libcurl package from which this header
file origins: */
#define LIBCURL_VERSION "7.19.8-CVS"
#define LIBCURL_VERSION "7.20.0-CVS"
/* The numeric version number is also available "in parts" by using these
defines: */
#define LIBCURL_VERSION_MAJOR 7
#define LIBCURL_VERSION_MINOR 19
#define LIBCURL_VERSION_PATCH 8
#define LIBCURL_VERSION_MINOR 20
#define LIBCURL_VERSION_PATCH 0
/* This is the numeric version of the libcurl version number, meant for easier
parsing and comparions by programs. The LIBCURL_VERSION_NUM define will
@@ -54,7 +54,7 @@
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 0x071308
#define LIBCURL_VERSION_NUM 0x071400
/*
* This is the date and time when the full source package was created. The

View File

@@ -39,38 +39,23 @@ C_ARG = $(OBJ_BASE)\wcc386.arg
LINK_ARG = $(OBJ_BASE)\dyn\wlink.arg
LIB_ARG = $(OBJ_BASE)\stat\wlib.arg
OBJS = $(OBJ_DIR)\base64.obj $(OBJ_DIR)\connect.obj &
$(OBJ_DIR)\content_encoding.obj $(OBJ_DIR)\cookie.obj &
$(OBJ_DIR)\curl_addrinfo.obj $(OBJ_DIR)\dict.obj &
$(OBJ_DIR)\easy.obj $(OBJ_DIR)\escape.obj &
$(OBJ_DIR)\file.obj $(OBJ_DIR)\formdata.obj &
$(OBJ_DIR)\ftp.obj $(OBJ_DIR)\getenv.obj &
$(OBJ_DIR)\getinfo.obj $(OBJ_DIR)\gtls.obj &
$(OBJ_DIR)\hash.obj $(OBJ_DIR)\hostares.obj &
$(OBJ_DIR)\hostasyn.obj $(OBJ_DIR)\hostip.obj &
$(OBJ_DIR)\hostip4.obj $(OBJ_DIR)\hostip6.obj &
$(OBJ_DIR)\hostsyn.obj $(OBJ_DIR)\hostthre.obj &
$(OBJ_DIR)\http.obj $(OBJ_DIR)\http_chunks.obj &
$(OBJ_DIR)\http_digest.obj $(OBJ_DIR)\http_negotiate.obj &
$(OBJ_DIR)\http_ntlm.obj $(OBJ_DIR)\if2ip.obj &
$(OBJ_DIR)\inet_ntop.obj $(OBJ_DIR)\inet_pton.obj &
$(OBJ_DIR)\krb4.obj $(OBJ_DIR)\ldap.obj &
$(OBJ_DIR)\llist.obj $(OBJ_DIR)\md5.obj &
$(OBJ_DIR)\memdebug.obj $(OBJ_DIR)\mprintf.obj &
$(OBJ_DIR)\multi.obj $(OBJ_DIR)\netrc.obj &
$(OBJ_DIR)\parsedate.obj $(OBJ_DIR)\progress.obj &
$(OBJ_DIR)\security.obj $(OBJ_DIR)\rawstr.obj &
$(OBJ_DIR)\select.obj $(OBJ_DIR)\sendf.obj &
$(OBJ_DIR)\share.obj $(OBJ_DIR)\socks.obj &
$(OBJ_DIR)\speedcheck.obj $(OBJ_DIR)\splay.obj &
$(OBJ_DIR)\sslgen.obj $(OBJ_DIR)\ssluse.obj &
$(OBJ_DIR)\strequal.obj $(OBJ_DIR)\strerror.obj &
$(OBJ_DIR)\strtok.obj $(OBJ_DIR)\strtoofft.obj &
$(OBJ_DIR)\telnet.obj $(OBJ_DIR)\tftp.obj &
$(OBJ_DIR)\timeval.obj $(OBJ_DIR)\transfer.obj &
$(OBJ_DIR)\url.obj $(OBJ_DIR)\version.obj &
$(OBJ_DIR)\slist.obj $(OBJ_DIR)\nonblock.obj &
$(OBJ_DIR)\curl_rand.obj $(OBJ_DIR)\curl_memrchr.obj
# Unfortunately, we can't include Makefile.inc here because wmake doesn't
# use backslash as the line continuation character by default
CSOURCES = file.c timeval.c base64.c hostip.c progress.c formdata.c &
cookie.c http.c sendf.c ftp.c url.c dict.c if2ip.c speedcheck.c &
ldap.c ssluse.c version.c getenv.c escape.c mprintf.c telnet.c &
netrc.c getinfo.c transfer.c strequal.c easy.c security.c krb4.c &
krb5.c memdebug.c http_chunks.c strtok.c connect.c llist.c hash.c &
multi.c content_encoding.c share.c http_digest.c md5.c curl_rand.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 splay.c &
strdup.c socks.c ssh.c nss.c qssl.c rawstr.c curl_addrinfo.c &
socks_gssapi.c socks_sspi.c curl_sspi.c slist.c nonblock.c &
curl_memrchr.c imap.c pop3.c smtp.c pingpong.c rtsp.c curl_threads.c
OBJS = $(CSOURCES:.c=.obj)
OBJS = $OBJ_DIR\$(OBJS: = $OBJ_DIR\)
#
# Use $(OBJS) as a template to generate $(OBJS_STAT) and $(OBJS_DYN).
@@ -554,3 +539,27 @@ $(OBJ_DIR)\curl_memrchr.obj: curl_memrchr.c setup.h config-win32.h &
..\include\curl\curlrules.h ..\include\curl\easy.h &
..\include\curl\multi.h ..\include\curl\curl.h curl_memrchr.h &
..\include\curl\mprintf.h curl_memory.h memdebug.h
$(OBJ_DIR)\imap.obj: imap.c setup.h config-win32.h &
..\include\curl\curlbuild.h ..\include\curl\curlrules.h setup_once.h &
..\include\curl\curl.h ..\include\curl\curlver.h &
..\include\curl\curlrules.h ..\include\curl\easy.h &
..\include\curl\multi.h ..\include\curl\curl.h imap.h &
..\include\curl\mprintf.h curl_memory.h memdebug.h
$(OBJ_DIR)\pop3.obj: pop3.c setup.h config-win32.h &
..\include\curl\curlbuild.h ..\include\curl\curlrules.h setup_once.h &
..\include\curl\curl.h ..\include\curl\curlver.h &
..\include\curl\curlrules.h ..\include\curl\easy.h &
..\include\curl\multi.h ..\include\curl\curl.h pop3.h &
..\include\curl\mprintf.h curl_memory.h memdebug.h
$(OBJ_DIR)\smtp.obj: smtp.c setup.h config-win32.h &
..\include\curl\curlbuild.h ..\include\curl\curlrules.h setup_once.h &
..\include\curl\curl.h ..\include\curl\curlver.h &
..\include\curl\curlrules.h ..\include\curl\easy.h &
..\include\curl\multi.h ..\include\curl\curl.h smtp.h &
..\include\curl\mprintf.h curl_memory.h memdebug.h
$(OBJ_DIR)\pingpong.obj: pingpong.c setup.h config-win32.h &
..\include\curl\curlbuild.h ..\include\curl\curlrules.h setup_once.h &
..\include\curl\curl.h ..\include\curl\curlver.h &
..\include\curl\curlrules.h ..\include\curl\easy.h &
..\include\curl\multi.h ..\include\curl\curl.h pingpong.h &
..\include\curl\mprintf.h curl_memory.h memdebug.h

View File

@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
# Copyright (C) 1998 - 2009, Daniel Stenberg, <daniel@haxx.se>, et al.
# Copyright (C) 1998 - 2010, 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,7 +27,7 @@ VCPROJ = libcurl.vcproj
DOCS = README.encoding README.memoryleak README.ares README.curlx \
README.hostip README.multi_socket README.httpauth README.pipelining \
README.curl_off_t README.cmake
README.curl_off_t README.cmake README.pingpong
CMAKE_DIST = CMakeLists.txt curl_config.h.cmake
@@ -84,9 +84,9 @@ if SONAME_BUMP
#
# This conditional soname bump SHOULD be removed at next "proper" bump.
#
VERSIONINFO=-version-info 6:1:1
VERSIONINFO=-version-info 7:0:2
else
VERSIONINFO=-version-info 5:1:1
VERSIONINFO=-version-info 6:0:2
endif
# This flag accepts an argument of the form current[:revision[:age]]. So,

View File

@@ -11,7 +11,7 @@ CSOURCES = file.c timeval.c base64.c hostip.c progress.c formdata.c \
inet_ntop.c parsedate.c select.c gtls.c sslgen.c tftp.c splay.c \
strdup.c socks.c ssh.c nss.c qssl.c rawstr.c curl_addrinfo.c \
socks_gssapi.c socks_sspi.c curl_sspi.c slist.c nonblock.c \
curl_memrchr.c
curl_memrchr.c imap.c pop3.c smtp.c pingpong.c rtsp.c curl_threads.c
HHEADERS = arpa_telnet.h netrc.h file.h timeval.h qssl.h hostip.h \
progress.h formdata.h cookie.h http.h sendf.h ftp.h url.h dict.h \
@@ -23,5 +23,4 @@ HHEADERS = arpa_telnet.h netrc.h file.h timeval.h qssl.h hostip.h \
transfer.h select.h easyif.h multiif.h parsedate.h sslgen.h gtls.h \
tftp.h sockaddr.h splay.h strdup.h setup_once.h socks.h ssh.h nssg.h \
curl_base64.h rawstr.h curl_addrinfo.h curl_sspi.h slist.h nonblock.h \
curl_memrchr.h
curl_memrchr.h imap.h pop3.h smtp.h pingpong.h rtsp.h curl_threads.h

View File

@@ -14,7 +14,8 @@ objs = o.base64 o.connect o.cookie o.dict \
o.strequal o.strtok o.telnet o.timeval \
o.transfer o.url o.version o.strtoofft o.sslgen o.gtls \
o.rawstr o.curl_addrinfo o.slist o.nonblock o.curl_rand \
o.curl_memrchr
o.curl_memrchr o.imap o.pop3 o.smtp o.pingpong o.rtsp \
o.curl_threads
# Compile options:
@@ -44,6 +45,9 @@ o.curl_memrchr: c.curl_memrchr
o.curl_rand: c.curl_rand
gcc $(compileropts) -c -o curl_rand.o c.curl_rand
o.curl_threads: c.curl_threads
gcc $(compileropts) -c -o curl_threads.o c.curl_threads
o.dict: c.dict
gcc $(compileropts) -c -o dict.o c.dict
@@ -92,6 +96,9 @@ o.http_chunks: c.http_chunks
o.if2ip: c.if2ip
gcc $(compileropts) -c -o if2ip.o c.if2ip
o.imap: c.imap
gcc $(compileropts) -c -o imap.o c.imap
o.inet_ntop: c.inet_ntop
gcc $(compileropts) -c -o inet_ntop.o c.inet_ntop
@@ -116,9 +123,18 @@ o.netrc: c.netrc
o.parsedate: c.parsedate
gcc $(compileropts) -c -o parsedate.o c.parsedate
o.pingpong: c.pingpong
gcc $(compileropts) -c -o pingpong.o c.pingpong
o.pop3: c.pop3
gcc $(compileropts) -c -o pop3.o c.pop3
o.progress: c.progress
gcc $(compileropts) -c -o progress.o c.progress
o.rtsp: c.rtsp
gcc $(compileropts) -c -o rtsp.o c.rtsp
o.security: c.security
gcc $(compileropts) -c -o security.o c.security
@@ -131,6 +147,9 @@ o.sendf: c.sendf
o.slist: c.slist
gcc $(compileropts) -c -o slist.o c.slist
o.smtp: c.smtp
gcc $(compileropts) -c -o smtp.o c.smtp
o.speedcheck: c.speedcheck
gcc $(compileropts) -c -o speedcheck.o c.speedcheck

View File

@@ -453,6 +453,7 @@ X_OBJS= \
$(DIROBJ)\curl_memrchr.obj \
$(DIROBJ)\curl_rand.obj \
$(DIROBJ)\curl_sspi.obj \
$(DIROBJ)\curl_threads.obj \
$(DIROBJ)\dict.obj \
$(DIROBJ)\easy.obj \
$(DIROBJ)\escape.obj \
@@ -476,6 +477,7 @@ X_OBJS= \
$(DIROBJ)\http_negotiate.obj \
$(DIROBJ)\http_ntlm.obj \
$(DIROBJ)\if2ip.obj \
$(DIROBJ)\imap.obj \
$(DIROBJ)\inet_ntop.obj \
$(DIROBJ)\inet_pton.obj \
$(DIROBJ)\ldap.obj \
@@ -487,12 +489,16 @@ X_OBJS= \
$(DIROBJ)\netrc.obj \
$(DIROBJ)\nonblock.obj \
$(DIROBJ)\parsedate.obj \
$(DIROBJ)\pingpong.obj \
$(DIROBJ)\pop3.obj \
$(DIROBJ)\progress.obj \
$(DIROBJ)\rawstr.obj \
$(DIROBJ)\rtsp.obj \
$(DIROBJ)\select.obj \
$(DIROBJ)\sendf.obj \
$(DIROBJ)\share.obj \
$(DIROBJ)\slist.obj \
$(DIROBJ)\smtp.obj \
$(DIROBJ)\socks.obj \
$(DIROBJ)\socks_gssapi.obj \
$(DIROBJ)\socks_sspi.obj \

30
lib/README.pingpong Normal file
View File

@@ -0,0 +1,30 @@
Date: December 5, 2009
Pingpong
========
Pingpong is just my (Daniel's) jestful collective name on the protocols that
share a very similar kind of back-and-forth procedure with command and
responses to and from the server. FTP was previously the only protocol in
that family that libcurl supported, but when POP3, IMAP and SMTP joined the
team I moved some of the internals into a separate pingpong module to be
easier to get used by all these protocols to reduce code duplication and ease
code re-use between these protocols.
FTP
In 7.20.0 we converted code to use the new pingpong code from previously
having been all "native" FTP code.
POP3
There's no support in the documented URL format to specify the exact mail to
get, but we support that as the path specified in the URL.
IMAP
SMTP
There's no official URL syntax defined for SMTP, but we use only the generic
one and we provide two additional libcurl options to specify receivers and
sender of the actual mail.

View File

@@ -456,17 +456,20 @@
quite convoluted, compiler dependent and even build target dependent. */
#if defined(HAVE_WS2TCPIP_H)
# if defined(__POCC__)
# define HAVE_FREEADDRINFO 1
# define HAVE_GETADDRINFO 1
# define HAVE_GETNAMEINFO 1
# define HAVE_FREEADDRINFO 1
# define HAVE_GETADDRINFO 1
# define HAVE_GETADDRINFO_THREADSAFE 1
# define HAVE_GETNAMEINFO 1
# elif defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0501)
# define HAVE_FREEADDRINFO 1
# define HAVE_GETADDRINFO 1
# define HAVE_GETNAMEINFO 1
# define HAVE_FREEADDRINFO 1
# define HAVE_GETADDRINFO 1
# define HAVE_GETADDRINFO_THREADSAFE 1
# define HAVE_GETNAMEINFO 1
# elif defined(_MSC_VER) && (_MSC_VER >= 1200)
# define HAVE_FREEADDRINFO 1
# define HAVE_GETADDRINFO 1
# define HAVE_GETNAMEINFO 1
# define HAVE_FREEADDRINFO 1
# define HAVE_GETADDRINFO 1
# define HAVE_GETADDRINFO_THREADSAFE 1
# define HAVE_GETNAMEINFO 1
# endif
#endif
@@ -503,6 +506,24 @@
# define USE_WIN32_SMALL_FILES
#endif
/* ---------------------------------------------------------------- */
/* DNS RESOLVER SPECIALTY */
/* ---------------------------------------------------------------- */
/*
* Undefine both USE_ARES and USE_THREADS_WIN32 for synchronous DNS
*/
/* Define USE_ARES to enable c-ares asynchronous DNS lookups */
/* #define USE_ARES 1 */
/* Define USE_THREADS_WIN32 to enable threaded asynchronous DNS lookups */
#define USE_THREADS_WIN32 1
#if defined(USE_ARES) && defined(USE_THREADS_WIN32)
# error "Only one DNS lookup specialty may be defined at most"
#endif
/* ---------------------------------------------------------------- */
/* LDAP SUPPORT */
/* ---------------------------------------------------------------- */

View File

@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2009, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2010, 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
@@ -64,7 +64,7 @@
#undef in_addr_t
#define in_addr_t unsigned long
#endif
#ifdef VMS
#ifdef __VMS
#include <in.h>
#include <inet.h>
#endif
@@ -89,6 +89,7 @@
#include "inet_ntop.h"
#include "inet_pton.h"
#include "sslgen.h" /* for Curl_ssl_check_cxn() */
#include "progress.h"
/* The last #include file should be: */
#include "memdebug.h"
@@ -192,7 +193,8 @@ long Curl_timeleft(struct connectdata *conn,
#define WAITCONN_FDSET_ERROR 2
static
int waitconnect(curl_socket_t sockfd, /* socket */
int waitconnect(struct connectdata *conn,
curl_socket_t sockfd, /* socket */
long timeout_msec)
{
int rc;
@@ -203,21 +205,34 @@ int waitconnect(curl_socket_t sockfd, /* socket */
(void)verifyconnect(sockfd, NULL);
#endif
/* now select() until we get connect or timeout */
rc = Curl_socket_ready(CURL_SOCKET_BAD, sockfd, (int)timeout_msec);
if(-1 == rc)
/* error, no connect here, try next */
return WAITCONN_SELECT_ERROR;
for(;;) {
else if(0 == rc)
/* timeout, no connect today */
return WAITCONN_TIMEOUT;
/* now select() until we get connect or timeout */
rc = Curl_socket_ready(CURL_SOCKET_BAD, sockfd, (int)(timeout_msec>1000?
1000:timeout_msec));
if(rc & CURL_CSELECT_ERR)
/* error condition caught */
return WAITCONN_FDSET_ERROR;
if(Curl_pgrsUpdate(conn))
return CURLE_ABORTED_BY_CALLBACK;
/* we have a connect! */
if(-1 == rc)
/* error, no connect here, try next */
return WAITCONN_SELECT_ERROR;
else if(0 == rc) {
/* timeout */
timeout_msec -= 1000;
if(timeout_msec <= 0)
return WAITCONN_TIMEOUT;
continue;
}
if(rc & CURL_CSELECT_ERR)
/* error condition caught */
return WAITCONN_FDSET_ERROR;
break;
}
return WAITCONN_CONNECTED;
}
@@ -370,7 +385,7 @@ static CURLcode bindlocal(struct connectdata *conn,
}
}
do {
for(;;) {
if( bind(sockfd, sock, sizeof_sa) >= 0) {
/* we succeeded to bind */
struct Curl_sockaddr_storage add;
@@ -382,13 +397,13 @@ static CURLcode bindlocal(struct connectdata *conn,
error, Curl_strerror(conn, error));
return CURLE_INTERFACE_FAILED;
}
infof(data, "Local port: %d\n", port);
infof(data, "Local port: %hu\n", port);
conn->bits.bound = TRUE;
return CURLE_OK;
}
if(--portnum > 0) {
infof(data, "Bind to local port %d failed, trying next\n", port);
infof(data, "Bind to local port %hu failed, trying next\n", port);
port++; /* try next port */
/* We re-use/clobber the port variable here below */
if(sock->sa_family == AF_INET)
@@ -400,7 +415,7 @@ static CURLcode bindlocal(struct connectdata *conn,
}
else
break;
} while(1);
}
data->state.os_errno = error = SOCKERRNO;
failf(data, "bind failed with errno %d: %s",
@@ -553,7 +568,7 @@ CURLcode Curl_is_connected(struct connectdata *conn,
Curl_expire(data, allow);
/* check for connect without timeout as we want to return immediately */
rc = waitconnect(sockfd, 0);
rc = waitconnect(conn, sockfd, 0);
if(WAITCONN_CONNECTED == rc) {
int error;
@@ -566,7 +581,7 @@ CURLcode Curl_is_connected(struct connectdata *conn,
data->state.os_errno = error;
infof(data, "Connection failed\n");
if(trynextip(conn, sockindex, connected)) {
failf(data, "Failed connect to %s:%d; %s",
failf(data, "Failed connect to %s:%ld; %s",
conn->host.name, conn->port, Curl_strerror(conn, error));
code = CURLE_COULDNT_CONNECT;
}
@@ -586,7 +601,7 @@ CURLcode Curl_is_connected(struct connectdata *conn,
if(trynextip(conn, sockindex, connected)) {
error = SOCKERRNO;
data->state.os_errno = error;
failf(data, "Failed connect to %s:%d; %s",
failf(data, "Failed connect to %s:%ld; %s",
conn->host.name, conn->port, Curl_strerror(conn, error));
code = CURLE_COULDNT_CONNECT;
}
@@ -719,12 +734,13 @@ singleipconnect(struct connectdata *conn,
if(data->set.fopensocket)
/*
* If the opensocket callback is set, all the destination address information
* is passed to the callback. Depending on this information the callback may
* opt to abort the connection, this is indicated returning CURL_SOCKET_BAD;
* otherwise it will return a not-connected socket. When the callback returns
* a valid socket the destination address information might have been changed
* and this 'new' address will actually be used here to connect.
* If the opensocket callback is set, all the destination address
* information is passed to the callback. Depending on this information the
* callback may opt to abort the connection, this is indicated returning
* CURL_SOCKET_BAD; otherwise it will return a not-connected socket. When
* the callback returns a valid socket the destination address information
* might have been changed and this 'new' address will actually be used
* here to connect.
*/
sockfd = data->set.fopensocket(data->set.opensocket_client,
CURLSOCKTYPE_IPCXN,
@@ -823,7 +839,7 @@ singleipconnect(struct connectdata *conn,
case EAGAIN:
#endif
#endif
rc = waitconnect(sockfd, timeout_ms);
rc = waitconnect(conn, sockfd, timeout_ms);
break;
default:
/* unknown error, fallthrough and try another address! */

View File

@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2009, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2010, 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
@@ -40,7 +40,7 @@
(doing so will reduce code size slightly). */
#define OLD_ZLIB_SUPPORT 1
#define DSIZ 0x10000 /* buffer size for decompressed data */
#define DSIZ CURL_MAX_WRITE_SIZE /* buffer size for decompressed data */
#define GZIP_MAGIC_0 0x1f
#define GZIP_MAGIC_1 0x8b
@@ -280,27 +280,27 @@ Curl_unencode_gzip_write(struct connectdata *conn,
z->avail_in = 0;
if(strcmp(zlibVersion(), "1.2.0.4") >= 0) {
/* zlib ver. >= 1.2.0.4 supports transparent gzip decompressing */
if(inflateInit2(z, MAX_WBITS+32) != Z_OK) {
return process_zlib_error(conn, z);
}
k->zlib_init = ZLIB_INIT_GZIP; /* Transparent gzip decompress state */
} else {
/* we must parse the gzip header ourselves */
if(inflateInit2(z, -MAX_WBITS) != Z_OK) {
return process_zlib_error(conn, z);
}
k->zlib_init = ZLIB_INIT; /* Initial call state */
/* zlib ver. >= 1.2.0.4 supports transparent gzip decompressing */
if(inflateInit2(z, MAX_WBITS+32) != Z_OK) {
return process_zlib_error(conn, z);
}
k->zlib_init = ZLIB_INIT_GZIP; /* Transparent gzip decompress state */
}
else {
/* we must parse the gzip header ourselves */
if(inflateInit2(z, -MAX_WBITS) != Z_OK) {
return process_zlib_error(conn, z);
}
k->zlib_init = ZLIB_INIT; /* Initial call state */
}
}
if(k->zlib_init == ZLIB_INIT_GZIP) {
/* Let zlib handle the gzip decompression entirely */
z->next_in = (Bytef *)k->str;
z->avail_in = (uInt)nread;
/* Now uncompress the data */
return inflate_stream(conn, k);
/* Let zlib handle the gzip decompression entirely */
z->next_in = (Bytef *)k->str;
z->avail_in = (uInt)nread;
/* Now uncompress the data */
return inflate_stream(conn, k);
}
#ifndef OLD_ZLIB_SUPPORT

View File

@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2009, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2010, 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
@@ -681,7 +681,8 @@ Curl_cookie_add(struct SessionHandle *data,
if(c->running)
/* Only show this when NOT reading the cookies from a file */
infof(data, "%s cookie %s=\"%s\" for domain %s, path %s, expire %d\n",
infof(data, "%s cookie %s=\"%s\" for domain %s, path %s, "
"expire %" FORMAT_OFF_T "\n",
replace_old?"Replaced":"Added", co->name, co->value,
co->domain, co->path, co->expires);
@@ -774,6 +775,18 @@ struct CookieInfo *Curl_cookie_init(struct SessionHandle *data,
return c;
}
/* sort this so that the longest path gets before the shorter path */
static int cookie_sort(const void *p1, const void *p2)
{
struct Cookie *c1 = *(struct Cookie **)p1;
struct Cookie *c2 = *(struct Cookie **)p2;
size_t l1 = c1->path?strlen(c1->path):0;
size_t l2 = c2->path?strlen(c2->path):0;
return (int)(l2 - l1);
}
/*****************************************************************************
*
* Curl_cookie_getlist()
@@ -794,6 +807,7 @@ struct Cookie *Curl_cookie_getlist(struct CookieInfo *c,
struct Cookie *co;
time_t now = time(NULL);
struct Cookie *mainco=NULL;
size_t matches = 0;
if(!c || !c->cookies)
return NULL; /* no cookie struct or no cookies in the struct */
@@ -834,8 +848,11 @@ struct Cookie *Curl_cookie_getlist(struct CookieInfo *c,
/* point the main to us */
mainco = newco;
matches++;
}
else {
fail:
/* failure, clear up the allocated chain and return NULL */
while(mainco) {
co = mainco->next;
@@ -851,6 +868,36 @@ struct Cookie *Curl_cookie_getlist(struct CookieInfo *c,
co = co->next;
}
if(matches) {
/* Now we need to make sure that if there is a name appearing more than
once, the longest specified path version comes first. To make this
the swiftest way, we just sort them all based on path length. */
struct Cookie **array;
size_t i;
/* alloc an array and store all cookie pointers */
array = (struct Cookie **)malloc(sizeof(struct Cookie *) * matches);
if(!array)
goto fail;
co = mainco;
for(i=0; co; co = co->next)
array[i++] = co;
/* now sort the cookie pointers in path lenth order */
qsort(array, matches, sizeof(struct Cookie *), cookie_sort);
/* remake the linked list order according to the new order */
mainco = array[0]; /* start here */
for(i=0; i<matches-1; i++)
array[i]->next = array[i+1];
array[matches-1]->next = NULL; /* terminate the list */
free(array); /* remove the temporary data again */
}
return mainco; /* return the new list */
}
@@ -909,7 +956,7 @@ void Curl_cookie_clearsess(struct CookieInfo *cookies)
{
struct Cookie *first, *curr, *next, *prev = NULL;
if(!cookies->cookies || !cookies->cookies)
if(!cookies || !cookies->cookies)
return;
first = curr = prev = cookies->cookies;

View File

@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2009, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2010, 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,7 +38,7 @@
# include <arpa/inet.h>
#endif
#ifdef VMS
#ifdef __VMS
# include <in.h>
# include <inet.h>
# include <stdlib.h>
@@ -365,7 +365,7 @@ Curl_ip2addr(int af, const void *inaddr, const char *hostname, int port)
{
Curl_addrinfo *ai;
#if defined(VMS) && \
#if defined(__VMS) && \
defined(__INITIAL_POINTER_SIZE) && (__INITIAL_POINTER_SIZE == 64)
#pragma pointer_size save
#pragma pointer_size short
@@ -418,7 +418,7 @@ Curl_ip2addr(int af, const void *inaddr, const char *hostname, int port)
h->h_addr_list[0] = addrentry;
h->h_addr_list[1] = NULL; /* terminate list of entries */
#if defined(VMS) && \
#if defined(__VMS) && \
defined(__INITIAL_POINTER_SIZE) && (__INITIAL_POINTER_SIZE == 64)
#pragma pointer_size restore
#pragma message enable PTRMISMATCH
@@ -447,9 +447,8 @@ curl_dofreeaddrinfo(struct addrinfo *freethis,
int line, const char *source)
{
(freeaddrinfo)(freethis);
if(logfile)
fprintf(logfile, "ADDR %s:%d freeaddrinfo(%p)\n",
source, line, (void *)freethis);
curl_memlog("ADDR %s:%d freeaddrinfo(%p)\n",
source, line, (void *)freethis);
}
#endif /* defined(CURLDEBUG) && defined(HAVE_FREEADDRINFO) */
@@ -471,17 +470,13 @@ curl_dogetaddrinfo(const char *hostname,
int line, const char *source)
{
int res=(getaddrinfo)(hostname, service, hints, result);
if(0 == res) {
if(0 == res)
/* success */
if(logfile)
fprintf(logfile, "ADDR %s:%d getaddrinfo() = %p\n",
source, line, (void *)*result);
}
else {
if(logfile)
fprintf(logfile, "ADDR %s:%d getaddrinfo() failed\n",
source, line);
}
curl_memlog("ADDR %s:%d getaddrinfo() = %p\n",
source, line, (void *)*result);
else
curl_memlog("ADDR %s:%d getaddrinfo() failed\n",
source, line);
return res;
}
#endif /* defined(CURLDEBUG) && defined(HAVE_GETADDRINFO) */

View File

@@ -38,7 +38,7 @@
# include <arpa/inet.h>
#endif
#ifdef VMS
#ifdef __VMS
# include <in.h>
# include <inet.h>
# include <stdlib.h>

128
lib/curl_threads.c Normal file
View File

@@ -0,0 +1,128 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2010, 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$
***************************************************************************/
#include "setup.h"
#if defined(USE_THREADS_POSIX)
# ifdef HAVE_PTHREAD_H
# include <pthread.h>
# endif
#elif defined(USE_THREADS_WIN32)
# ifdef HAVE_PROCESS_H
# include <process.h>
# endif
#endif
#include "curl_threads.h"
#define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h>
#include "curl_memory.h"
/* The last #include file should be: */
#include "memdebug.h"
#if defined(USE_THREADS_POSIX)
struct curl_actual_call {
unsigned int (*func)(void *);
void *arg;
};
static void *curl_thread_create_thunk(void *arg)
{
struct curl_actual_call * ac = arg;
unsigned int (*func)(void *) = ac->func;
void *real_arg = ac->arg;
free(ac);
(*func)(real_arg);
return 0;
}
curl_thread_t Curl_thread_create(unsigned int (*func) (void*), void *arg)
{
curl_thread_t t;
struct curl_actual_call *ac = malloc(sizeof(struct curl_actual_call));
if(!ac)
return curl_thread_t_null;
ac->func = func;
ac->arg = arg;
if(pthread_create(&t, NULL, curl_thread_create_thunk, ac) != 0) {
free(ac);
return curl_thread_t_null;
}
return t;
}
void Curl_thread_destroy(curl_thread_t hnd)
{
if(hnd != curl_thread_t_null)
pthread_detach(hnd);
}
int Curl_thread_join(curl_thread_t *hnd)
{
int ret = (pthread_join(*hnd, NULL) == 0);
*hnd = curl_thread_t_null;
return ret;
}
#elif defined(USE_THREADS_WIN32)
curl_thread_t Curl_thread_create(unsigned int (CURL_STDCALL *func) (void*), void *arg)
{
#ifdef _WIN32_WCE
return CreateThread(NULL, 0, func, arg, 0, NULL);
#else
curl_thread_t t;
t = (curl_thread_t)_beginthreadex(NULL, 0, func, arg, 0, NULL);
if((t == 0) || (t == (curl_thread_t)-1L))
return curl_thread_t_null;
return t;
#endif
}
void Curl_thread_destroy(curl_thread_t hnd)
{
CloseHandle(hnd);
}
int Curl_thread_join(curl_thread_t *hnd)
{
int ret = (WaitForSingleObject(*hnd, INFINITE) == WAIT_OBJECT_0);
Curl_thread_destroy(*hnd);
*hnd = curl_thread_t_null;
return ret;
}
#endif /* USE_THREADS_* */

58
lib/curl_threads.h Normal file
View File

@@ -0,0 +1,58 @@
#ifndef HEADER_CURL_THREADS_H
#define HEADER_CURL_THREADS_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2010, 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$
***************************************************************************/
#include "setup.h"
#if defined(USE_THREADS_POSIX)
# define CURL_STDCALL
# define curl_mutex_t pthread_mutex_t
# define curl_thread_t pthread_t
# define curl_thread_t_null (pthread_t)0
# define Curl_mutex_init(m) pthread_mutex_init(m, NULL)
# define Curl_mutex_acquire(m) pthread_mutex_lock(m)
# define Curl_mutex_release(m) pthread_mutex_unlock(m)
# define Curl_mutex_destroy(m) pthread_mutex_destroy(m)
#elif defined(USE_THREADS_WIN32)
# define CURL_STDCALL __stdcall
# define curl_mutex_t CRITICAL_SECTION
# define curl_thread_t HANDLE
# define curl_thread_t_null (HANDLE)0
# define Curl_mutex_init(m) InitializeCriticalSection(m)
# define Curl_mutex_acquire(m) EnterCriticalSection(m)
# define Curl_mutex_release(m) LeaveCriticalSection(m)
# define Curl_mutex_destroy(m) DeleteCriticalSection(m)
#endif
#if defined(USE_THREADS_POSIX) || defined(USE_THREADS_WIN32)
curl_thread_t Curl_thread_create(unsigned int (CURL_STDCALL *func) (void*),
void *arg);
void Curl_thread_destroy(curl_thread_t hnd);
int Curl_thread_join(curl_thread_t *hnd);
#endif /* USE_THREADS_POSIX || USE_THREADS_WIN32 */
#endif /* HEADER_CURL_THREADS_H */

View File

@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2009, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2010, 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
@@ -882,11 +882,12 @@ CURLcode Curl_convert_to_network(struct SessionHandle *data,
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));
"CURLOPT_CONV_TO_NETWORK_FUNCTION callback returned %d: %s",
(int)rc, curl_easy_strerror(rc));
}
return(rc);
} else {
}
else {
#ifdef HAVE_ICONV
/* do the translation ourselves */
char *input_ptr, *output_ptr;
@@ -942,8 +943,8 @@ CURLcode Curl_convert_from_network(struct SessionHandle *data,
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));
"CURLOPT_CONV_FROM_NETWORK_FUNCTION callback returned %d: %s",
(int)rc, curl_easy_strerror(rc));
}
return(rc);
}
@@ -1003,11 +1004,12 @@ CURLcode Curl_convert_from_utf8(struct SessionHandle *data,
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));
"CURLOPT_CONV_FROM_UTF8_FUNCTION callback returned %d: %s",
(int)rc, curl_easy_strerror(rc));
}
return(rc);
} else {
}
else {
#ifdef HAVE_ICONV
/* do the translation ourselves */
const char *input_ptr;

View File

@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2009, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2010, 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
@@ -103,7 +103,8 @@ char *curl_easy_escape(CURL *handle, const char *string, int inlength)
if (Curl_isalnum(in)) {
/* just copy this */
ns[strindex++]=in;
} else {
}
else {
/* encode it */
newlen += 2; /* the size grows with two, since this'll become a %XX */
if(newlen > alloc) {

View File

@@ -8,7 +8,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2009, 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
@@ -23,6 +23,18 @@
*
* $Id$
***************************************************************************/
/****************************************************************************
* FILE unique setup
***************************************************************************/
struct FILEPROTO {
char *path; /* the path we operate on */
char *freepath; /* pointer to the allocated block we must free, this might
differ from the 'path' pointer */
int fd; /* open file descriptor to read from! */
};
#ifndef CURL_DISABLE_FILE
extern const struct Curl_handler Curl_handler_file;
#endif

View File

@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2009, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2010, 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
@@ -998,7 +998,8 @@ int curl_formget(struct curl_httppost *form, void *arg,
return -1;
}
} while(nread == sizeof(buffer));
} else {
}
else {
if(ptr->length != append(arg, ptr->line, ptr->length)) {
Curl_formclean(&data);
return -1;

713
lib/ftp.c

File diff suppressed because it is too large Load Diff

121
lib/ftp.h
View File

@@ -1,5 +1,5 @@
#ifndef __FTP_H
#define __FTP_H
#ifndef HEADER_CURL_FTP_H
#define HEADER_CURL_FTP_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2010, 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
@@ -23,6 +23,8 @@
* $Id$
***************************************************************************/
#include "pingpong.h"
#ifndef CURL_DISABLE_FTP
extern const struct Curl_handler Curl_handler_ftp;
@@ -30,17 +32,110 @@ extern const struct Curl_handler Curl_handler_ftp;
extern const struct Curl_handler Curl_handler_ftps;
#endif
#ifndef CURL_DISABLE_HTTP
extern const struct Curl_handler Curl_handler_ftp_proxy;
# ifdef USE_SSL
extern const struct Curl_handler Curl_handler_ftps_proxy;
# endif
#endif
CURLcode Curl_ftpsendf(struct connectdata *, const char *fmt, ...);
CURLcode Curl_nbftpsendf(struct connectdata *, const char *fmt, ...);
CURLcode Curl_GetFTPResponse(ssize_t *nread, struct connectdata *conn,
int *ftpcode);
#endif /* CURL_DISABLE_FTP */
#endif /* __FTP_H */
/****************************************************************************
* FTP unique setup
***************************************************************************/
typedef enum {
FTP_STOP, /* do nothing state, stops the state machine */
FTP_WAIT220, /* waiting for the initial 220 response immediately after
a connect */
FTP_AUTH,
FTP_USER,
FTP_PASS,
FTP_ACCT,
FTP_PBSZ,
FTP_PROT,
FTP_CCC,
FTP_PWD,
FTP_SYST,
FTP_NAMEFMT,
FTP_QUOTE, /* waiting for a response to a command sent in a quote list */
FTP_RETR_PREQUOTE,
FTP_STOR_PREQUOTE,
FTP_POSTQUOTE,
FTP_CWD, /* change dir */
FTP_MKD, /* if the dir didn't exist */
FTP_MDTM, /* to figure out the datestamp */
FTP_TYPE, /* to set type when doing a head-like request */
FTP_LIST_TYPE, /* set type when about to do a dir list */
FTP_RETR_TYPE, /* set type when about to RETR a file */
FTP_STOR_TYPE, /* set type when about to STOR a file */
FTP_SIZE, /* get the remote file's size for head-like request */
FTP_RETR_SIZE, /* get the remote file's size for RETR */
FTP_STOR_SIZE, /* get the size for (resumed) STOR */
FTP_REST, /* when used to check if the server supports it in head-like */
FTP_RETR_REST, /* when asking for "resume" in for RETR */
FTP_PORT, /* generic state for PORT, LPRT and EPRT, check count1 */
FTP_PRET, /* generic state for PRET RETR, PRET STOR and PRET LIST/NLST */
FTP_PASV, /* generic state for PASV and EPSV, check count1 */
FTP_LIST, /* generic state for LIST, NLST or a custom list command */
FTP_RETR,
FTP_STOR, /* generic state for STOR and APPE */
FTP_QUIT,
FTP_LAST /* never used */
} ftpstate;
typedef enum {
FTPFILE_MULTICWD = 1, /* as defined by RFC1738 */
FTPFILE_NOCWD = 2, /* use SIZE / RETR / STOR on the full path */
FTPFILE_SINGLECWD = 3 /* make one CWD, then SIZE / RETR / STOR on the file */
} curl_ftpfile;
typedef enum {
FTPTRANSFER_BODY, /* yes do transfer a body */
FTPTRANSFER_INFO, /* do still go through to get info/headers */
FTPTRANSFER_NONE, /* don't get anything and don't get info */
FTPTRANSFER_LAST /* end of list marker, never used */
} curl_ftptransfer;
/* This FTP struct is used in the SessionHandle. All FTP data that is
connection-oriented must be in FTP_conn to properly deal with the fact that
perhaps the SessionHandle is changed between the times the connection is
used. */
struct FTP {
curl_off_t *bytecountp;
char *user; /* user name string */
char *passwd; /* password string */
/* transfer a file/body or not, done as a typedefed enum just to make
debuggers display the full symbol and not just the numerical value */
curl_ftptransfer transfer;
curl_off_t downloadsize;
};
/* ftp_conn is used for struct connection-oriented data in the connectdata
struct */
struct ftp_conn {
struct pingpong pp;
char *entrypath; /* the PWD reply when we logged on */
char **dirs; /* realloc()ed array for path components */
int dirdepth; /* number of entries used in the 'dirs' array */
int diralloc; /* number of entries allocated for the 'dirs' array */
char *file; /* decoded file */
bool dont_check; /* Set to TRUE to prevent the final (post-transfer)
file size and 226/250 status check. It should still
read the line, just ignore the result. */
bool ctl_valid; /* Tells Curl_ftp_quit() whether or not to do anything. If
the connection has timed out or been closed, this
should be FALSE when it gets to Curl_ftp_quit() */
bool cwddone; /* if it has been determined that the proper CWD combo
already has been done */
bool cwdfail; /* set TRUE if a CWD command fails, as then we must prevent
caching the current directory */
char *prevpath; /* conn->path from the previous transfer */
char transfertype; /* set by ftp_transfertype for use by Curl_client_write()a
and others (A/I or zero) */
int count1; /* general purpose counter for the state machine */
int count2; /* general purpose counter for the state machine */
int count3; /* general purpose counter for the state machine */
ftpstate state; /* always use ftp.c:state() to change state! */
char * server_os; /* The target server operating system. */
};
#endif /* HEADER_CURL_FTP_H */

View File

@@ -27,7 +27,7 @@
#include <stdlib.h>
#include <string.h>
#ifdef VMS
#ifdef __VMS
#include <unixlib.h>
#endif
@@ -51,7 +51,7 @@ char *GetEnv(const char *variable)
return (env[0] != '\0')?strdup(env):NULL;
#else
char *env = getenv(variable);
#ifdef VMS
#ifdef __VMS
if(env && strcmp("HOME",variable) == 0)
env = decc_translate_vms(env);
#endif

View File

@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2009, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2010, 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
@@ -235,6 +235,19 @@ CURLcode Curl_getinfo(struct SessionHandle *data, CURLINFO info, ...)
/* return if the condition prevented the document to get transfered */
*param_longp = data->info.timecond;
break;
case CURLINFO_RTSP_SESSION_ID:
*param_charp = data->set.str[STRING_RTSP_SESSION_ID];
break;
case CURLINFO_RTSP_CLIENT_CSEQ:
*param_longp = data->state.rtsp_next_client_CSeq;
break;
case CURLINFO_RTSP_SERVER_CSEQ:
*param_longp = data->state.rtsp_next_server_CSeq;
break;
case CURLINFO_RTSP_CSEQ_RECV:
*param_longp = data->state.rtsp_CSeq_recv;
break;
default:
return CURLE_BAD_FUNCTION_ARGUMENT;
}

View File

@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2009, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2010, 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
@@ -46,7 +46,7 @@
#ifdef HAVE_UNISTD_H
#include <unistd.h> /* for the close() proto */
#endif
#ifdef VMS
#ifdef __VMS
#include <in.h>
#include <inet.h>
#include <stdlib.h>
@@ -72,6 +72,7 @@
#include "inet_pton.h"
#include "connect.h"
#include "select.h"
#include "progress.h"
#define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h>
@@ -119,7 +120,7 @@ int Curl_resolv_getsock(struct connectdata *conn,
}
/*
* ares_waitperform()
* waitperform()
*
* 1) Ask ares what sockets it currently plays with, then
* 2) wait for the timeout period to check for action on ares' sockets.
@@ -128,7 +129,7 @@ int Curl_resolv_getsock(struct connectdata *conn,
* return number of sockets it worked on
*/
static int ares_waitperform(struct connectdata *conn, int timeout_ms)
static int waitperform(struct connectdata *conn, int timeout_ms)
{
struct SessionHandle *data = conn->data;
int nfds;
@@ -192,7 +193,7 @@ CURLcode Curl_is_resolved(struct connectdata *conn,
*dns = NULL;
ares_waitperform(conn, 0);
waitperform(conn, 0);
if(conn->async.done) {
/* we're done, kill the ares handle */
@@ -238,6 +239,7 @@ CURLcode Curl_wait_for_resolv(struct connectdata *conn,
struct timeval *tvp, tv, store;
long timediff;
int itimeout;
int timeout_ms;
itimeout = (timeout > (long)INT_MAX) ? INT_MAX : (int)timeout;
@@ -246,14 +248,27 @@ CURLcode Curl_wait_for_resolv(struct connectdata *conn,
tvp = ares_timeout(data->state.areschannel, &store, &tv);
/* use the timeout period ares returned to us above */
ares_waitperform(conn, (int)(tvp->tv_sec * 1000 + tvp->tv_usec/1000));
/* use the timeout period ares returned to us above if less than one
second is left, otherwise just use 1000ms to make sure the progress
callback gets called frequent enough */
if(!tvp->tv_sec)
timeout_ms = tvp->tv_usec/1000;
else
timeout_ms = 1000;
waitperform(conn, timeout_ms);
if(conn->async.done)
break;
timediff = Curl_tvdiff(Curl_tvnow(), now); /* spent time */
timeout -= timediff?timediff:1; /* always deduct at least 1 */
if(Curl_pgrsUpdate(conn)) {
rc = CURLE_ABORTED_BY_CALLBACK;
timeout = -1; /* trigger the cancel below */
}
else {
timediff = Curl_tvdiff(Curl_tvnow(), now); /* spent time */
timeout -= timediff?timediff:1; /* always deduct at least 1 */
}
if(timeout < 0) {
/* our timeout, so we cancel the ares operation */
ares_cancel(data->state.areschannel);
@@ -270,13 +285,26 @@ CURLcode Curl_wait_for_resolv(struct connectdata *conn,
if(!conn->async.dns) {
/* a name was not resolved */
if((timeout < 0) || (conn->async.status == ARES_ETIMEOUT)) {
failf(data, "Resolving host timed out: %s", conn->host.dispname);
rc = CURLE_COULDNT_RESOLVE_HOST;
if (conn->bits.httpproxy) {
failf(data, "Resolving proxy timed out: %s", conn->proxy.dispname);
rc = CURLE_COULDNT_RESOLVE_PROXY;
}
else {
failf(data, "Resolving host timed out: %s", conn->host.dispname);
rc = CURLE_COULDNT_RESOLVE_HOST;
}
}
else if(conn->async.done) {
failf(data, "Could not resolve host: %s (%s)", conn->host.dispname,
ares_strerror(conn->async.status));
rc = CURLE_COULDNT_RESOLVE_HOST;
if (conn->bits.httpproxy) {
failf(data, "Could not resolve proxy: %s (%s)", conn->proxy.dispname,
ares_strerror(conn->async.status));
rc = CURLE_COULDNT_RESOLVE_PROXY;
}
else {
failf(data, "Could not resolve host: %s (%s)", conn->host.dispname,
ares_strerror(conn->async.status));
rc = CURLE_COULDNT_RESOLVE_HOST;
}
}
else
rc = CURLE_OPERATION_TIMEDOUT;
@@ -289,6 +317,31 @@ CURLcode Curl_wait_for_resolv(struct connectdata *conn,
return rc;
}
/*
* ares_query_completed_cb() is the callback that ares will call when
* the host query initiated by ares_gethostbyname() from Curl_getaddrinfo(),
* when using ares, is completed either successfully or with failure.
*/
static void ares_query_completed_cb(void *arg, /* (struct connectdata *) */
int status,
#ifdef HAVE_CARES_CALLBACK_TIMEOUTS
int timeouts,
#endif
struct hostent *hostent)
{
struct connectdata *conn = (struct connectdata *)arg;
struct Curl_addrinfo * ai = NULL;
#ifdef HAVE_CARES_CALLBACK_TIMEOUTS
(void)timeouts; /* ignored */
#endif
if (status == CURL_ASYNC_SUCCESS) {
ai = Curl_he2ai(hostent, conn->async.port);
}
(void)Curl_addrinfo_callback(arg, status, ai);
}
/*
* Curl_getaddrinfo() - when using ares
@@ -310,7 +363,8 @@ Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
#ifdef ENABLE_IPV6 /* CURLRES_IPV6 */
struct in6_addr in6;
#endif /* CURLRES_IPV6 */
*waitp = FALSE;
*waitp = 0; /* default to synchronous response */
/* First check if this is an IPv4 address string */
if(Curl_inet_pton(AF_INET, hostname, &in) > 0) {
@@ -354,9 +408,9 @@ Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
/* areschannel is already setup in the Curl_open() function */
ares_gethostbyname(data->state.areschannel, hostname, family,
(ares_host_callback)Curl_addrinfo4_callback, conn);
(ares_host_callback)ares_query_completed_cb, conn);
*waitp = TRUE; /* please wait for the response */
*waitp = 1; /* expect asynchronous response */
}
return NULL; /* no struct yet */
}

View File

@@ -43,7 +43,7 @@
#ifdef HAVE_UNISTD_H
#include <unistd.h> /* for the close() proto */
#endif
#ifdef VMS
#ifdef __VMS
#include <in.h>
#include <inet.h>
#include <stdlib.h>
@@ -72,38 +72,27 @@
* Only for builds using asynchronous name resolves
**********************************************************************/
#ifdef CURLRES_ASYNCH
/*
* addrinfo_callback() gets called by ares, gethostbyname_thread() or
* getaddrinfo_thread() when we got the name resolved (or not!).
* Curl_addrinfo_callback() gets called by ares, gethostbyname_thread()
* or getaddrinfo_thread() when we got the name resolved (or not!).
*
* If the status argument is CURL_ASYNC_SUCCESS, we might need to copy the
* address field since it might be freed when this function returns. This
* operation stores the resolved data in the DNS cache.
*
* NOTE: for IPv6 operations, Curl_addrinfo_copy() returns the same
* pointer it is given as argument!
* If the status argument is CURL_ASYNC_SUCCESS, this function takes
* ownership of the Curl_addrinfo passed, storing the resolved data
* in the DNS cache.
*
* The storage operation locks and unlocks the DNS cache.
*/
static CURLcode addrinfo_callback(void *arg, /* "struct connectdata *" */
int status,
void *addr)
CURLcode Curl_addrinfo_callback(struct connectdata * conn,
int status,
struct Curl_addrinfo *ai)
{
struct connectdata *conn = (struct connectdata *)arg;
struct Curl_dns_entry *dns = NULL;
CURLcode rc = CURLE_OK;
conn->async.status = status;
if(CURL_ASYNC_SUCCESS == status) {
/*
* IPv4/ares: Curl_addrinfo_copy() copies the address and returns an
* allocated version.
*
* IPv6: Curl_addrinfo_copy() returns the input pointer!
*/
Curl_addrinfo *ai = Curl_addrinfo_copy(addr, conn->async.port);
if(ai) {
struct SessionHandle *data = conn->data;
@@ -138,35 +127,4 @@ static CURLcode addrinfo_callback(void *arg, /* "struct connectdata *" */
return rc;
}
CURLcode Curl_addrinfo4_callback(void *arg, /* "struct connectdata *" */
int status,
#ifdef HAVE_CARES_CALLBACK_TIMEOUTS
int timeouts,
#endif
struct hostent *hostent)
{
#ifdef HAVE_CARES_CALLBACK_TIMEOUTS
(void)timeouts; /* ignored */
#endif
return addrinfo_callback(arg, status, hostent);
}
#ifdef CURLRES_IPV6
CURLcode Curl_addrinfo6_callback(void *arg, /* "struct connectdata *" */
int status,
#ifdef HAVE_CARES_CALLBACK_TIMEOUTS
int timeouts,
#endif
Curl_addrinfo *ai)
{
/* NOTE: for CURLRES_ARES, the 'ai' argument is really a
* 'struct hostent' pointer.
*/
#ifdef HAVE_CARES_CALLBACK_TIMEOUTS
(void)timeouts; /* ignored */
#endif
return addrinfo_callback(arg, status, ai);
}
#endif
#endif /* CURLRES_ASYNC */
#endif /* CURLRES_ASYNCH */

View File

@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2009, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2010, 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
@@ -43,7 +43,7 @@
#ifdef HAVE_UNISTD_H
#include <unistd.h> /* for the close() proto */
#endif
#ifdef VMS
#ifdef __VMS
#include <in.h>
#include <inet.h>
#include <stdlib.h>
@@ -76,8 +76,8 @@
/* The last #include file should be: */
#include "memdebug.h"
#if defined(HAVE_ALARM) && defined(SIGALRM) && defined(HAVE_SIGSETJMP) \
&& !defined(USE_ARES)
#if defined(CURLRES_SYNCH) && \
defined(HAVE_ALARM) && defined(SIGALRM) && defined(HAVE_SIGSETJMP)
/* alarm-based timeouts can only be used with all the dependencies satisfied */
#define USE_ALARM_TIMEOUT
#endif
@@ -189,12 +189,14 @@ Curl_printable_address(const Curl_addrinfo *ai, char *buf, size_t bufsize)
case AF_INET:
sa4 = (const void *)ai->ai_addr;
ipaddr4 = &sa4->sin_addr;
return Curl_inet_ntop(ai->ai_family, (const void *)ipaddr4, buf, bufsize);
return Curl_inet_ntop(ai->ai_family, (const void *)ipaddr4, buf,
bufsize);
#ifdef ENABLE_IPV6
case AF_INET6:
sa6 = (const void *)ai->ai_addr;
ipaddr6 = &sa6->sin6_addr;
return Curl_inet_ntop(ai->ai_family, (const void *)ipaddr6, buf, bufsize);
return Curl_inet_ntop(ai->ai_family, (const void *)ipaddr6, buf,
bufsize);
#endif
default:
break;
@@ -712,20 +714,4 @@ struct curl_hash *Curl_mk_dnscache(void)
return Curl_hash_alloc(7, Curl_hash_str, Curl_str_key_compare, freednsentry);
}
#ifdef CURLRES_ADDRINFO_COPY
/* align on even 64bit boundaries */
#define MEMALIGN(x) ((x)+(8-(((unsigned long)(x))&0x7)))
/*
* Curl_addrinfo_copy() performs a "deep" copy of a hostent into a buffer and
* returns a pointer to the malloc()ed copy. You need to call free() on the
* returned buffer when you're done with it.
*/
Curl_addrinfo *Curl_addrinfo_copy(const void *org, int port)
{
const struct hostent *orig = org;
return Curl_he2ai(orig, port);
}
#endif /* CURLRES_ADDRINFO_COPY */

View File

@@ -1,5 +1,5 @@
#ifndef __HOSTIP_H
#define __HOSTIP_H
#ifndef HEADER_CURL_HOSTIP_H
#define HEADER_CURL_HOSTIP_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2008, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2010, 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,51 +37,13 @@
#endif
/*
* Setup comfortable CURLRES_* defines to use in the host*.c sources.
* Comfortable CURLRES_* definitions are included from setup.h
*/
#ifdef USE_ARES
#include <ares_version.h>
#endif
#ifdef USE_ARES
#define CURLRES_ASYNCH
#define CURLRES_ARES
#endif
#ifdef USE_THREADING_GETHOSTBYNAME
#define CURLRES_ASYNCH
#define CURLRES_THREADED
#endif
#ifdef USE_THREADING_GETADDRINFO
#define CURLRES_ASYNCH
#define CURLRES_THREADED
#endif
#ifdef ENABLE_IPV6
#define CURLRES_IPV6
#else
#define CURLRES_IPV4
#endif
#if defined(CURLRES_IPV4) || defined(CURLRES_ARES)
#if !defined(HAVE_GETHOSTBYNAME_R) || defined(CURLRES_ASYNCH)
/* If built for ipv4 and missing gethostbyname_r(), or if using async name
resolve, we need the Curl_addrinfo_copy() function (which itself needs the
Curl_he2ai() function)) */
#define CURLRES_ADDRINFO_COPY
#endif
#endif /* IPv4/ares-only */
#ifndef CURLRES_ASYNCH
#define CURLRES_SYNCH
#endif
#ifndef USE_LIBIDN
#define CURLRES_IDN
#endif
/* Allocate enough memory to hold the full name information structs and
* everything. OSF1 is known to require at least 8872 bytes. The buffer
* required for storing all possible aliases and IP numbers is according to
@@ -203,26 +165,18 @@ int curl_dogetnameinfo(GETNAMEINFO_QUAL_ARG1 GETNAMEINFO_TYPE_ARG1 sa,
int line, const char *source);
#endif
/* This is the callback function that is used when we build with asynch
resolve, ipv4 */
CURLcode Curl_addrinfo4_callback(void *arg,
int status,
#ifdef HAVE_CARES_CALLBACK_TIMEOUTS
int timeouts,
#endif
struct hostent *hostent);
/* This is the callback function that is used when we build with asynch
resolve, ipv6 */
CURLcode Curl_addrinfo6_callback(void *arg,
int status,
#ifdef HAVE_CARES_CALLBACK_TIMEOUTS
int timeouts,
#endif
Curl_addrinfo *ai);
/* IPv4 threadsafe resolve function used for synch and asynch builds */
Curl_addrinfo *Curl_ipv4_resolve_r(const char * hostname, int port);
/* Clone a Curl_addrinfo struct, works protocol independently */
Curl_addrinfo *Curl_addrinfo_copy(const void *orig, int port);
/*
* Curl_addrinfo_callback() is used when we build with any asynch specialty.
* Handles end of async request processing. Inserts ai into hostcache when
* status is CURL_ASYNC_SUCCESS. Twiddles fields in conn to indicate async
* request completed wether successfull or failed.
*/
CURLcode Curl_addrinfo_callback(struct connectdata *conn,
int status,
Curl_addrinfo *ai);
/*
* Curl_printable_address() returns a printable version of the 1st address
@@ -263,4 +217,4 @@ void Curl_destroy_thread_data(struct Curl_async *async);
extern sigjmp_buf curl_jmpenv;
#endif
#endif
#endif /* HEADER_CURL_HOSTIP_H */

View File

@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2009, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2010, 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
@@ -44,7 +44,7 @@
#ifdef HAVE_UNISTD_H
#include <unistd.h> /* for the close() proto */
#endif
#ifdef VMS
#ifdef __VMS
#include <in.h>
#include <inet.h>
#include <stdlib.h>
@@ -87,8 +87,7 @@ bool Curl_ipvalid(struct SessionHandle *data)
return TRUE; /* OK, proceed */
}
#ifdef CURLRES_SYNCH /* the functions below are for synchronous resolves */
#ifdef CURLRES_SYNCH
/*
* Curl_getaddrinfo() - the ipv4 synchronous version.
*
@@ -110,7 +109,34 @@ Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
int port,
int *waitp)
{
#if defined(HAVE_GETHOSTBYNAME_R_3)
Curl_addrinfo *ai = NULL;
#ifdef CURL_DISABLE_VERBOSE_STRINGS
(void)conn;
#endif
*waitp = 0; /* synchronous response only */
ai = Curl_ipv4_resolve_r(hostname, port);
if(!ai)
infof(conn->data, "Curl_ipv4_resolve_r failed for %s\n", hostname);
return ai;
}
#endif /* CURLRES_SYNCH */
#endif /* CURLRES_IPV4 */
/*
* Curl_ipv4_resolve_r() - ipv4 threadsafe resolver function.
*
* This is used for both synchronous and asynchronous resolver builds,
* implying that only threadsafe code and function calls may be used.
*
*/
Curl_addrinfo *Curl_ipv4_resolve_r(const char *hostname,
int port)
{
#if !defined(HAVE_GETADDRINFO_THREADSAFE) && defined(HAVE_GETHOSTBYNAME_R_3)
int res;
#endif
Curl_addrinfo *ai = NULL;
@@ -118,17 +144,27 @@ Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
struct in_addr in;
struct hostent *buf = NULL;
#ifdef CURL_DISABLE_VERBOSE_STRINGS
(void)conn;
#endif
*waitp = 0; /* don't wait, we act synchronously */
if(Curl_inet_pton(AF_INET, hostname, &in) > 0)
/* This is a dotted IP address 123.123.123.123-style */
return Curl_ip2addr(AF_INET, &in, hostname, port);
#if defined(HAVE_GETHOSTBYNAME_R)
#if defined(HAVE_GETADDRINFO_THREADSAFE)
else {
struct addrinfo hints;
char sbuf[NI_MAXSERV];
char *sbufptr = NULL;
memset(&hints, 0, sizeof(hints));
hints.ai_family = PF_INET;
hints.ai_socktype = SOCK_STREAM;
if(port) {
snprintf(sbuf, sizeof(sbuf), "%d", port);
sbufptr = sbuf;
}
hints.ai_flags = AI_CANONNAME;
(void)Curl_getaddrinfo_ex(hostname, sbufptr, &hints, &ai);
#elif defined(HAVE_GETHOSTBYNAME_R)
/*
* gethostbyname_r() is the preferred resolve function for many platforms.
* Since there are three different versions of it, the following code is
@@ -146,7 +182,7 @@ Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
* platforms.
*/
#ifdef HAVE_GETHOSTBYNAME_R_5
#if defined(HAVE_GETHOSTBYNAME_R_5)
/* Solaris, IRIX and more */
h = gethostbyname_r(hostname,
(struct hostent *)buf,
@@ -164,8 +200,7 @@ Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
;
}
else
#endif /* HAVE_GETHOSTBYNAME_R_5 */
#ifdef HAVE_GETHOSTBYNAME_R_6
#elif defined(HAVE_GETHOSTBYNAME_R_6)
/* Linux */
(void)gethostbyname_r(hostname,
@@ -206,8 +241,7 @@ Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
*/
if(!h) /* failure */
#endif/* HAVE_GETHOSTBYNAME_R_6 */
#ifdef HAVE_GETHOSTBYNAME_R_3
#elif defined(HAVE_GETHOSTBYNAME_R_3)
/* AIX, Digital Unix/Tru64, HPUX 10, more? */
/* For AIX 4.3 or later, we don't use gethostbyname_r() at all, because of
@@ -259,26 +293,20 @@ Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
*/
}
else
#endif /* HAVE_GETHOSTBYNAME_R_3 */
{
infof(conn->data, "gethostbyname_r(2) failed for %s\n", hostname);
#endif /* HAVE_...BYNAME_R_5 || HAVE_...BYNAME_R_6 || HAVE_...BYNAME_R_3 */
{
h = NULL; /* set return code to NULL */
free(buf);
}
#else /* HAVE_GETHOSTBYNAME_R */
#else /* HAVE_GETADDRINFO_THREADSAFE || HAVE_GETHOSTBYNAME_R */
/*
* Here is code for platforms that don't have gethostbyname_r() or for
* which the gethostbyname() is the preferred() function.
* Here is code for platforms that don't have a thread safe
* getaddrinfo() nor gethostbyname_r() function or for which
* gethostbyname() is the preferred one.
*/
else {
#if (defined(NETWARE) && !defined(__NOVELL_LIBC__))
h = gethostbyname((char*)hostname);
#else
h = gethostbyname(hostname);
#endif
if(!h)
infof(conn->data, "gethostbyname(2) failed for %s\n", hostname);
#endif /*HAVE_GETHOSTBYNAME_R */
h = gethostbyname((void*)hostname);
#endif /* HAVE_GETADDRINFO_THREADSAFE || HAVE_GETHOSTBYNAME_R */
}
if(h) {
@@ -290,7 +318,3 @@ Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
return ai;
}
#endif /* CURLRES_SYNCH */
#endif /* CURLRES_IPV4 */

View File

@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2009, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2010, 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
@@ -43,7 +43,7 @@
#ifdef HAVE_UNISTD_H
#include <unistd.h> /* for the close() proto */
#endif
#ifdef VMS
#ifdef __VMS
#include <in.h>
#include <inet.h>
#include <stdlib.h>
@@ -75,20 +75,6 @@
**********************************************************************/
#ifdef CURLRES_IPV6
#ifndef CURLRES_ARES
#ifdef CURLRES_ASYNCH
/*
* Curl_addrinfo_copy() is used by the asynch callback to copy a given
* address. But this is an ipv6 build and then we don't copy the address, we
* just return the same pointer!
*/
Curl_addrinfo *Curl_addrinfo_copy(const void *orig, int port)
{
(void) port;
return (Curl_addrinfo*)orig;
}
#endif /* CURLRES_ASYNCH */
#endif /* CURLRES_ARES */
#if defined(CURLDEBUG) && defined(HAVE_GETNAMEINFO)
/* These are strictly for memory tracing and are using the same style as the
@@ -112,17 +98,13 @@ int curl_dogetnameinfo(GETNAMEINFO_QUAL_ARG1 GETNAMEINFO_TYPE_ARG1 sa,
host, hostlen,
serv, servlen,
flags);
if(0 == res) {
if(0 == res)
/* success */
if(logfile)
fprintf(logfile, "GETNAME %s:%d getnameinfo()\n",
source, line);
}
else {
if(logfile)
fprintf(logfile, "GETNAME %s:%d getnameinfo() failed = %d\n",
source, line, res);
}
curl_memlog("GETNAME %s:%d getnameinfo()\n",
source, line);
else
curl_memlog("GETNAME %s:%d getnameinfo() failed = %d\n",
source, line, res);
return res;
}
#endif /* defined(CURLDEBUG) && defined(HAVE_GETNAMEINFO) */
@@ -144,7 +126,7 @@ bool Curl_ipvalid(struct SessionHandle *data)
return TRUE;
}
#if !defined(USE_THREADING_GETADDRINFO) && !defined(CURLRES_ARES)
#if defined(CURLRES_SYNCH)
#ifdef DEBUG_ADDRINFO
static void dump_addrinfo(struct connectdata *conn, const Curl_addrinfo *ai)
@@ -188,7 +170,7 @@ Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
int pf;
struct SessionHandle *data = conn->data;
*waitp=0; /* don't wait, we have the response now */
*waitp = 0; /* synchronous response only */
/*
* Check if a limited name resolve has been requested.
@@ -252,6 +234,6 @@ Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
return res;
}
#endif /* !USE_THREADING_GETADDRINFO && !CURLRES_ARES */
#endif /* ipv6 */
#endif /* CURLRES_SYNCH */
#endif /* CURLRES_IPV6 */

View File

@@ -43,7 +43,7 @@
#ifdef HAVE_UNISTD_H
#include <unistd.h> /* for the close() proto */
#endif
#ifdef VMS
#ifdef __VMS
#include <in.h>
#include <inet.h>
#include <stdlib.h>

View File

@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2009, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2010, 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
@@ -44,14 +44,20 @@
#ifdef HAVE_UNISTD_H
#include <unistd.h> /* for the close() proto */
#endif
#ifdef VMS
#ifdef __VMS
#include <in.h>
#include <inet.h>
#include <stdlib.h>
#endif
#ifdef HAVE_PROCESS_H
#include <process.h>
#if defined(USE_THREADS_POSIX)
# ifdef HAVE_PTHREAD_H
# include <pthread.h>
# endif
#elif defined(USE_THREADS_WIN32)
# ifdef HAVE_PROCESS_H
# include <process.h>
# endif
#endif
#if (defined(NETWARE) && defined(__NOVELL_LIBC__))
@@ -68,22 +74,18 @@
#include "url.h"
#include "multiif.h"
#include "inet_pton.h"
#include "inet_ntop.h"
#include "curl_threads.h"
#define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h>
#include "inet_ntop.h"
#include "curl_memory.h"
/* The last #include file should be: */
#include "memdebug.h"
#if defined(_MSC_VER) && defined(CURL_NO__BEGINTHREADEX)
#pragma message ("No _beginthreadex() available in this RTL")
#endif
/***********************************************************************
* Only for Windows threaded name resolves builds
* Only for threaded name resolves builds
**********************************************************************/
#ifdef CURLRES_THREADED
@@ -92,249 +94,162 @@ static bool init_resolve_thread(struct connectdata *conn,
const char *hostname, int port,
const struct addrinfo *hints);
#ifdef CURLRES_IPV4
#define THREAD_FUNC gethostbyname_thread
#define THREAD_NAME "gethostbyname_thread"
#else
#define THREAD_FUNC getaddrinfo_thread
#define THREAD_NAME "getaddrinfo_thread"
#endif
struct thread_data {
HANDLE thread_hnd;
unsigned thread_id;
DWORD thread_status;
curl_socket_t dummy_sock; /* dummy for Curl_resolv_fdset() */
HANDLE mutex_waiting; /* marks that we are still waiting for a resolve */
HANDLE event_resolved; /* marks that the thread obtained the information */
HANDLE event_thread_started; /* marks that the thread has initialized and
started */
HANDLE mutex_terminate; /* serializes access to flag_terminate */
HANDLE event_terminate; /* flag for thread to terminate instead of calling
callbacks */
#ifdef CURLRES_IPV6
/* Data for synchronization between resolver thread and its parent */
struct thread_sync_data {
curl_mutex_t * mtx;
int done;
char * hostname; /* hostname to resolve, Curl_async.hostname
duplicate */
int port;
int sock_error;
Curl_addrinfo *res;
#ifdef HAVE_GETADDRINFO
struct addrinfo hints;
#endif
};
/* Data for synchronization between resolver thread and its parent */
struct thread_sync_data {
HANDLE mutex_waiting; /* thread_data.mutex_waiting duplicate */
HANDLE mutex_terminate; /* thread_data.mutex_terminate duplicate */
HANDLE event_terminate; /* thread_data.event_terminate duplicate */
char * hostname; /* hostname to resolve, Curl_async.hostname
duplicate */
struct thread_data {
curl_thread_t thread_hnd;
curl_socket_t dummy_sock;
unsigned int poll_interval;
int interval_end;
struct thread_sync_data tsd;
};
static struct thread_sync_data * conn_thread_sync_data(struct connectdata *conn)
{
return &(((struct thread_data *)conn->async.os_specific)->tsd);
}
#define CONN_THREAD_SYNC_DATA(conn) &(((conn)->async.os_specific)->tsd);
/* Destroy resolver thread synchronization data */
static
void destroy_thread_sync_data(struct thread_sync_data * tsd)
{
if (tsd->mtx) {
Curl_mutex_destroy(tsd->mtx);
free(tsd->mtx);
}
if(tsd->hostname)
free(tsd->hostname);
if(tsd->event_terminate)
CloseHandle(tsd->event_terminate);
if(tsd->mutex_terminate)
CloseHandle(tsd->mutex_terminate);
if(tsd->mutex_waiting)
CloseHandle(tsd->mutex_waiting);
if (tsd->res)
Curl_freeaddrinfo(tsd->res);
memset(tsd,0,sizeof(*tsd));
}
/* Initialize resolver thread synchronization data */
static
BOOL init_thread_sync_data(struct thread_data * td,
int init_thread_sync_data(struct thread_sync_data * tsd,
const char * hostname,
struct thread_sync_data * tsd)
int port,
const struct addrinfo *hints)
{
HANDLE curr_proc = GetCurrentProcess();
memset(tsd, 0, sizeof(*tsd));
if(!DuplicateHandle(curr_proc, td->mutex_waiting,
curr_proc, &tsd->mutex_waiting, 0, FALSE,
DUPLICATE_SAME_ACCESS)) {
/* failed to duplicate the mutex, no point in continuing */
destroy_thread_sync_data(tsd);
return FALSE;
}
if(!DuplicateHandle(curr_proc, td->mutex_terminate,
curr_proc, &tsd->mutex_terminate, 0, FALSE,
DUPLICATE_SAME_ACCESS)) {
/* failed to duplicate the mutex, no point in continuing */
destroy_thread_sync_data(tsd);
return FALSE;
}
if(!DuplicateHandle(curr_proc, td->event_terminate,
curr_proc, &tsd->event_terminate, 0, FALSE,
DUPLICATE_SAME_ACCESS)) {
/* failed to duplicate the event, no point in continuing */
destroy_thread_sync_data(tsd);
return FALSE;
}
tsd->port = port;
#ifdef CURLRES_IPV6
DEBUGASSERT(hints);
tsd->hints = *hints;
#else
(void) hints;
#endif
tsd->mtx = malloc(sizeof(curl_mutex_t));
if (tsd->mtx == NULL) goto err_exit;
Curl_mutex_init(tsd->mtx);
tsd->sock_error = CURL_ASYNC_SUCCESS;
/* Copying hostname string because original can be destroyed by parent
* thread during gethostbyname execution.
*/
tsd->hostname = strdup(hostname);
if(!tsd->hostname) {
/* Memory allocation failed */
destroy_thread_sync_data(tsd);
return FALSE;
}
return TRUE;
if (!tsd->hostname) goto err_exit;
return 1;
err_exit:
/* Memory allocation failed */
destroy_thread_sync_data(tsd);
return 0;
}
/* acquire resolver thread synchronization */
static
BOOL acquire_thread_sync(struct thread_sync_data * tsd)
{
/* is the thread initiator still waiting for us ? */
if(WaitForSingleObject(tsd->mutex_waiting, 0) == WAIT_TIMEOUT) {
/* yes, it is */
/* Waiting access to event_terminate */
if(WaitForSingleObject(tsd->mutex_terminate, INFINITE) != WAIT_OBJECT_0) {
/* Something went wrong - now just ignoring */
}
else {
if(WaitForSingleObject(tsd->event_terminate, 0) != WAIT_TIMEOUT) {
/* Parent thread signaled us to terminate.
* This means that all data in conn->async is now destroyed
* and we cannot use it.
*/
}
else {
return TRUE;
}
}
}
return FALSE;
}
/* release resolver thread synchronization */
static
void release_thread_sync(struct thread_sync_data * tsd)
{
ReleaseMutex(tsd->mutex_terminate);
}
#if defined(CURLRES_IPV4)
/*
* gethostbyname_thread() resolves a name, calls the Curl_addrinfo4_callback
* and then exits.
*
* For builds without ARES/ENABLE_IPV6, create a resolver thread and wait on
* it.
* gethostbyname_thread() resolves a name and then exits.
*/
static unsigned __stdcall gethostbyname_thread (void *arg)
static unsigned int CURL_STDCALL gethostbyname_thread (void *arg)
{
struct connectdata *conn = (struct connectdata*) arg;
struct thread_data *td = (struct thread_data*) conn->async.os_specific;
struct hostent *he;
int rc = 0;
struct thread_sync_data *tsd = (struct thread_sync_data *)arg;
/* Duplicate the passed mutex and event handles.
* This allows us to use it even after the container gets destroyed
* due to a resolver timeout.
*/
struct thread_sync_data tsd = { 0,0,0,NULL };
tsd->res = Curl_ipv4_resolve_r(tsd->hostname, tsd->port);
if(!init_thread_sync_data(td, conn->async.hostname, &tsd)) {
/* thread synchronization data initialization failed */
return (unsigned)-1;
}
if (!tsd->res) {
tsd->sock_error = SOCKERRNO;
if (tsd->sock_error == 0)
tsd->sock_error = ENOMEM;
}
conn->async.status = NO_DATA; /* pending status */
SET_SOCKERRNO(conn->async.status);
Curl_mutex_acquire(tsd->mtx);
tsd->done = 1;
Curl_mutex_release(tsd->mtx);
/* Signaling that we have initialized all copies of data and handles we
need */
SetEvent(td->event_thread_started);
he = gethostbyname (tsd.hostname);
/* is parent thread waiting for us and are we able to access conn members? */
if(acquire_thread_sync(&tsd)) {
/* Mark that we have obtained the information, and that we are calling
* back with it. */
SetEvent(td->event_resolved);
if(he) {
rc = Curl_addrinfo4_callback(conn, CURL_ASYNC_SUCCESS, he);
}
else {
rc = Curl_addrinfo4_callback(conn, SOCKERRNO, NULL);
}
release_thread_sync(&tsd);
}
/* clean up */
destroy_thread_sync_data(&tsd);
return (rc);
/* An implicit _endthreadex() here */
return 0;
}
#elif defined(CURLRES_IPV6)
static int getaddrinfo_complete(struct connectdata *conn)
{
struct thread_sync_data *tsd = conn_thread_sync_data(conn);
int rc;
rc = Curl_addrinfo_callback(conn, tsd->sock_error, tsd->res);
/* The tsd->res structure has been copied to async.dns and perhaps the DNS cache.
Set our copy to NULL so destroy_thread_sync_data doesn't free it.
*/
tsd->res = NULL;
return rc;
}
#if defined(HAVE_GETADDRINFO)
/*
* getaddrinfo_thread() resolves a name, calls Curl_addrinfo6_callback and then
* exits.
* getaddrinfo_thread() resolves a name and then exits.
*
* For builds without ARES, but with ENABLE_IPV6, create a resolver thread
* and wait on it.
*/
static unsigned __stdcall getaddrinfo_thread (void *arg)
static unsigned int CURL_STDCALL getaddrinfo_thread (void *arg)
{
struct connectdata *conn = (struct connectdata*) arg;
struct thread_data *td = (struct thread_data*) conn->async.os_specific;
Curl_addrinfo *res;
struct thread_sync_data *tsd = (struct thread_sync_data*)arg;
char service [NI_MAXSERV];
int rc;
struct addrinfo hints = td->hints;
int rc;
/* Duplicate the passed mutex handle.
* This allows us to use it even after the container gets destroyed
* due to a resolver timeout.
*/
struct thread_sync_data tsd = { 0,0,0,NULL };
snprintf(service, sizeof(service), "%d", tsd->port);
if(!init_thread_sync_data(td, conn->async.hostname, &tsd)) {
/* thread synchronization data initialization failed */
return -1;
rc = Curl_getaddrinfo_ex(tsd->hostname, service, &tsd->hints, &tsd->res);
if (rc != 0) {
tsd->sock_error = SOCKERRNO;
if (tsd->sock_error == 0)
tsd->sock_error = ENOMEM;
}
itoa(conn->async.port, service, 10);
Curl_mutex_acquire(tsd->mtx);
tsd->done = 1;
Curl_mutex_release(tsd->mtx);
conn->async.status = NO_DATA; /* pending status */
SET_SOCKERRNO(conn->async.status);
/* Signaling that we have initialized all copies of data and handles we
need */
SetEvent(td->event_thread_started);
rc = Curl_getaddrinfo_ex(tsd.hostname, service, &hints, &res);
/* is parent thread waiting for us and are we able to access conn members? */
if(acquire_thread_sync(&tsd)) {
/* Mark that we have obtained the information, and that we are calling
back with it. */
SetEvent(td->event_resolved);
if(rc == 0) {
rc = Curl_addrinfo6_callback(conn, CURL_ASYNC_SUCCESS, res);
}
else {
rc = Curl_addrinfo6_callback(conn, SOCKERRNO, NULL);
}
release_thread_sync(&tsd);
}
/* clean up */
destroy_thread_sync_data(&tsd);
return (rc);
/* An implicit _endthreadex() here */
return 0;
}
#endif
#endif /* HAVE_GETADDRINFO */
/*
* Curl_destroy_thread_data() cleans up async resolver data and thread handle.
@@ -347,39 +262,15 @@ void Curl_destroy_thread_data (struct Curl_async *async)
if(async->os_specific) {
struct thread_data *td = (struct thread_data*) async->os_specific;
curl_socket_t sock = td->dummy_sock;
if(td->mutex_terminate && td->event_terminate) {
/* Signaling resolver thread to terminate */
if(WaitForSingleObject(td->mutex_terminate, INFINITE) == WAIT_OBJECT_0) {
SetEvent(td->event_terminate);
ReleaseMutex(td->mutex_terminate);
}
else {
/* Something went wrong - just ignoring it */
}
}
if(td->mutex_terminate)
CloseHandle(td->mutex_terminate);
if(td->event_terminate)
CloseHandle(td->event_terminate);
if(td->event_thread_started)
CloseHandle(td->event_thread_started);
if(sock != CURL_SOCKET_BAD)
sclose(sock);
/* destroy the synchronization objects */
if(td->mutex_waiting)
CloseHandle(td->mutex_waiting);
td->mutex_waiting = NULL;
if(td->event_resolved)
CloseHandle(td->event_resolved);
if(td->thread_hnd)
CloseHandle(td->thread_hnd);
if (td->dummy_sock != CURL_SOCKET_BAD)
sclose(td->dummy_sock);
if (td->thread_hnd != curl_thread_t_null)
Curl_thread_join(&td->thread_hnd);
destroy_thread_sync_data(&td->tsd);
free(async->os_specific);
}
async->hostname = NULL;
@@ -397,114 +288,58 @@ static bool init_resolve_thread (struct connectdata *conn,
const struct addrinfo *hints)
{
struct thread_data *td = calloc(1, sizeof(struct thread_data));
HANDLE thread_and_event[2] = {0};
int err = ENOMEM;
if(!td) {
SET_ERRNO(ENOMEM);
return FALSE;
}
Curl_safefree(conn->async.hostname);
conn->async.hostname = strdup(hostname);
if(!conn->async.hostname) {
free(td);
SET_ERRNO(ENOMEM);
return FALSE;
}
conn->async.os_specific = (void*) td;
if(!td)
goto err_exit;
conn->async.port = port;
conn->async.done = FALSE;
conn->async.status = 0;
conn->async.dns = NULL;
conn->async.os_specific = (void*) td;
td->dummy_sock = CURL_SOCKET_BAD;
td->thread_hnd = curl_thread_t_null;
/* Create the mutex used to inform the resolver thread that we're
* still waiting, and take initial ownership.
*/
td->mutex_waiting = CreateMutex(NULL, TRUE, NULL);
if(td->mutex_waiting == NULL) {
Curl_destroy_thread_data(&conn->async);
SET_ERRNO(EAGAIN);
return FALSE;
}
if (!init_thread_sync_data(&td->tsd, hostname, port, hints))
goto err_exit;
/* Create the event that the thread uses to inform us that it's
* done resolving. Do not signal it.
*/
td->event_resolved = CreateEvent(NULL, TRUE, FALSE, NULL);
if(td->event_resolved == NULL) {
Curl_destroy_thread_data(&conn->async);
SET_ERRNO(EAGAIN);
return FALSE;
}
/* Create the mutex used to serialize access to event_terminated
* between us and resolver thread.
*/
td->mutex_terminate = CreateMutex(NULL, FALSE, NULL);
if(td->mutex_terminate == NULL) {
Curl_destroy_thread_data(&conn->async);
SET_ERRNO(EAGAIN);
return FALSE;
}
/* Create the event used to signal thread that it should terminate.
*/
td->event_terminate = CreateEvent(NULL, TRUE, FALSE, NULL);
if(td->event_terminate == NULL) {
Curl_destroy_thread_data(&conn->async);
SET_ERRNO(EAGAIN);
return FALSE;
}
/* Create the event used by thread to inform it has initialized its own data.
*/
td->event_thread_started = CreateEvent(NULL, TRUE, FALSE, NULL);
if(td->event_thread_started == NULL) {
Curl_destroy_thread_data(&conn->async);
SET_ERRNO(EAGAIN);
return FALSE;
}
Curl_safefree(conn->async.hostname);
conn->async.hostname = strdup(hostname);
if(!conn->async.hostname)
goto err_exit;
#ifdef _WIN32_WCE
td->thread_hnd = (HANDLE) CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE) THREAD_FUNC,
conn, 0, &td->thread_id);
#else
td->thread_hnd = (HANDLE) _beginthreadex(NULL, 0, THREAD_FUNC,
conn, 0, &td->thread_id);
#ifdef WIN32
/* This socket is only to keep Curl_resolv_fdset() and select() happy;
* should never become signalled for read since it's unbound but
* Windows needs at least 1 socket in select().
*/
td->dummy_sock = socket(AF_INET, SOCK_DGRAM, 0);
if (td->dummy_sock == CURL_SOCKET_BAD)
goto err_exit;
#endif
#ifdef CURLRES_IPV6
DEBUGASSERT(hints);
td->hints = *hints;
#ifdef HAVE_GETADDRINFO
td->thread_hnd = Curl_thread_create(getaddrinfo_thread, &td->tsd);
#else
(void) hints;
td->thread_hnd = Curl_thread_create(gethostbyname_thread, &td->tsd);
#endif
if(!td->thread_hnd) {
#ifndef _WIN32_WCE
SET_ERRNO(errno);
err = errno;
#endif
Curl_destroy_thread_data(&conn->async);
return FALSE;
goto err_exit;
}
/* Waiting until the thread will initialize its data or it will exit due errors.
*/
thread_and_event[0] = td->thread_hnd;
thread_and_event[1] = td->event_thread_started;
if(WaitForMultipleObjects(sizeof(thread_and_event) /
sizeof(thread_and_event[0]),
(const HANDLE*)thread_and_event, FALSE,
INFINITE) == WAIT_FAILED) {
/* The resolver thread has been created,
* most probably it works now - ignoring this "minor" error
*/
}
/* This socket is only to keep Curl_resolv_fdset() and select() happy;
* should never become signalled for read/write since it's unbound but
* Windows needs atleast 1 socket in select().
*/
td->dummy_sock = socket(AF_INET, SOCK_DGRAM, 0);
return TRUE;
err_exit:
Curl_destroy_thread_data(&conn->async);
SET_ERRNO(err);
return FALSE;
}
@@ -521,84 +356,33 @@ CURLcode Curl_wait_for_resolv(struct connectdata *conn,
{
struct thread_data *td = (struct thread_data*) conn->async.os_specific;
struct SessionHandle *data = conn->data;
long timeout;
DWORD status;
CURLcode rc;
CURLcode rc = CURLE_OK;
DEBUGASSERT(conn && td);
/* now, see if there's a connect timeout or a regular timeout to
use instead of the default one */
timeout =
conn->data->set.connecttimeout ? conn->data->set.connecttimeout :
conn->data->set.timeout ? conn->data->set.timeout :
CURL_TIMEOUT_RESOLVE * 1000; /* default name resolve timeout */
/* wait for the thread to resolve the name */
status = WaitForSingleObject(td->event_resolved, timeout);
/* mark that we are now done waiting */
ReleaseMutex(td->mutex_waiting);
/* close our handle to the mutex, no point in hanging on to it */
CloseHandle(td->mutex_waiting);
td->mutex_waiting = NULL;
/* close the event handle, it's useless now */
CloseHandle(td->event_resolved);
td->event_resolved = NULL;
/* has the resolver thread succeeded in resolving our query ? */
if(status == WAIT_OBJECT_0) {
/* wait for the thread to exit, it's in the callback sequence */
if(WaitForSingleObject(td->thread_hnd, 5000) == WAIT_TIMEOUT) {
TerminateThread(td->thread_hnd, 0);
conn->async.done = TRUE;
td->thread_status = (DWORD)-1;
}
else {
/* Thread finished before timeout; propagate Winsock error to this
* thread. 'conn->async.done = TRUE' is set in
* Curl_addrinfo4/6_callback().
*/
SET_SOCKERRNO(conn->async.status);
GetExitCodeThread(td->thread_hnd, &td->thread_status);
}
}
else {
conn->async.done = TRUE;
td->thread_status = (DWORD)-1;
if (Curl_thread_join(&td->thread_hnd)) {
rc = getaddrinfo_complete(conn);
} else {
DEBUGASSERT(0);
}
conn->async.done = TRUE;
if(entry)
*entry = conn->async.dns;
rc = CURLE_OK;
if(!conn->async.dns) {
/* a name was not resolved */
if(td->thread_status == CURLE_OUT_OF_MEMORY) {
rc = CURLE_OUT_OF_MEMORY;
failf(data, "Could not resolve host: %s", curl_easy_strerror(rc));
if (conn->bits.httpproxy) {
failf(data, "Could not resolve proxy: %s; %s",
conn->async.hostname, Curl_strerror(conn, conn->async.status));
rc = CURLE_COULDNT_RESOLVE_PROXY;
} else {
failf(data, "Could not resolve host: %s; %s",
conn->async.hostname, Curl_strerror(conn, conn->async.status));
rc = CURLE_COULDNT_RESOLVE_HOST;
}
else if(conn->async.done) {
if(conn->bits.httpproxy) {
failf(data, "Could not resolve proxy: %s; %s",
conn->proxy.dispname, Curl_strerror(conn, conn->async.status));
rc = CURLE_COULDNT_RESOLVE_PROXY;
}
else {
failf(data, "Could not resolve host: %s; %s",
conn->host.name, Curl_strerror(conn, conn->async.status));
rc = CURLE_COULDNT_RESOLVE_HOST;
}
}
else if(td->thread_status == (DWORD)-1 || conn->async.status == NO_DATA) {
failf(data, "Resolving host timed out: %s", conn->host.name);
rc = CURLE_OPERATION_TIMEDOUT;
}
else
rc = CURLE_OPERATION_TIMEDOUT;
}
Curl_destroy_thread_data(&conn->async);
@@ -618,19 +402,57 @@ CURLcode Curl_is_resolved(struct connectdata *conn,
struct Curl_dns_entry **entry)
{
struct SessionHandle *data = conn->data;
struct thread_data *td = (struct thread_data*) conn->async.os_specific;
int done = 0;
*entry = NULL;
if(conn->async.done) {
/* we're done */
if (!td) {
DEBUGASSERT(td);
return CURLE_COULDNT_RESOLVE_HOST;
}
Curl_mutex_acquire(td->tsd.mtx);
done = td->tsd.done;
Curl_mutex_release(td->tsd.mtx);
if (done) {
getaddrinfo_complete(conn);
if (td->poll_interval != 0)
Curl_expire(conn->data, 0);
Curl_destroy_thread_data(&conn->async);
if(!conn->async.dns) {
failf(data, "Could not resolve host: %s; %s",
conn->host.name, Curl_strerror(conn, conn->async.status));
return CURLE_COULDNT_RESOLVE_HOST;
}
*entry = conn->async.dns;
} else {
/* poll for name lookup done with exponential backoff up to 250ms */
int elapsed;
elapsed = Curl_tvdiff(Curl_tvnow(), data->progress.t_startsingle);
if (elapsed < 0) {
elapsed = 0;
}
if (td->poll_interval == 0) {
/* Start at 1ms poll interval */
td->poll_interval = 1;
} else if (elapsed >= td->interval_end) {
/* Back-off exponentially if last interval expired */
td->poll_interval *= 2;
}
if (td->poll_interval > 250)
td->poll_interval = 250;
td->interval_end = elapsed + td->poll_interval;
Curl_expire(conn->data, td->poll_interval);
}
return CURLE_OK;
}
@@ -643,18 +465,18 @@ int Curl_resolv_getsock(struct connectdata *conn,
if(td && td->dummy_sock != CURL_SOCKET_BAD) {
if(numsocks) {
/* return one socket waiting for writable, even though this is just
/* return one socket waiting for readable, even though this is just
a dummy */
socks[0] = td->dummy_sock;
return GETSOCK_WRITESOCK(0);
return GETSOCK_READSOCK(0);
}
}
return 0;
}
#ifdef CURLRES_IPV4
#if !defined(HAVE_GETADDRINFO)
/*
* Curl_getaddrinfo() - for Windows threading without ENABLE_IPV6.
* Curl_getaddrinfo() - for platforms without getaddrinfo
*/
Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
const char *hostname,
@@ -665,7 +487,7 @@ Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
struct SessionHandle *data = conn->data;
struct in_addr in;
*waitp = 0; /* don't wait, we act synchronously */
*waitp = 0; /* default to synchronous response */
if(Curl_inet_pton(AF_INET, hostname, &in) > 0)
/* This is a dotted IP address 123.123.123.123-style */
@@ -673,27 +495,18 @@ Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
/* fire up a new resolver thread! */
if(init_resolve_thread(conn, hostname, port, NULL)) {
*waitp = TRUE; /* please wait for the response */
*waitp = 1; /* expect asynchronous response */
return NULL;
}
/* fall-back to blocking version */
infof(data, "init_resolve_thread() failed for %s; %s\n",
hostname, Curl_strerror(conn, ERRNO));
h = gethostbyname(hostname);
if(!h) {
infof(data, "gethostbyname(2) failed for %s:%d; %s\n",
hostname, port, Curl_strerror(conn, SOCKERRNO));
return NULL;
}
return Curl_he2ai(h, port);
return Curl_ipv4_resolve_r(hostname, port);
}
#endif /* CURLRES_IPV4 */
#ifdef CURLRES_IPV6
#else /* HAVE_GETADDRINFO */
/*
* Curl_getaddrinfo() - for Windows threading IPv6 enabled
* Curl_getaddrinfo() - for getaddrinfo
*/
Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
const char *hostname,
@@ -704,11 +517,12 @@ Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
Curl_addrinfo *res;
int error;
char sbuf[NI_MAXSERV];
int pf;
int pf = PF_INET;
struct SessionHandle *data = conn->data;
*waitp = FALSE; /* default to synch response */
*waitp = 0; /* default to synchronous response */
#if !defined(CURLRES_IPV4)
/*
* Check if a limited name resolve has been requested.
*/
@@ -741,6 +555,7 @@ Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
sclose(s);
}
}
#endif /* !CURLRES_IPV4 */
memset(&hints, 0, sizeof(hints));
hints.ai_family = pf;
@@ -748,11 +563,11 @@ Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
#if 0 /* removed nov 8 2005 before 7.15.1 */
hints.ai_flags = AI_CANONNAME;
#endif
itoa(port, sbuf, 10);
snprintf(sbuf, sizeof(sbuf), "%d", port);
/* fire up a new resolver thread! */
if(init_resolve_thread(conn, hostname, port, &hints)) {
*waitp = TRUE; /* please wait for the response */
*waitp = 1; /* expect asynchronous response */
return NULL;
}
@@ -768,5 +583,7 @@ Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
}
return res;
}
#endif /* CURLRES_IPV6 */
#endif /* HAVE_GETADDRINFO */
#endif /* CURLRES_THREADED */

1161
lib/http.c

File diff suppressed because it is too large Load Diff

View File

@@ -8,7 +8,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2008, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2010, 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
@@ -35,8 +35,40 @@ bool Curl_compareheader(const char *headerline, /* line to check */
const char *header, /* header keyword _with_ colon */
const char *content); /* content string to find */
char *Curl_checkheaders(struct SessionHandle *data, const char *thisheader);
char *Curl_copy_header_value(const char *h);
/* ------------------------------------------------------------------------- */
/*
* The add_buffer series of functions are used to build one large memory chunk
* from repeated function invokes. Used so that the entire HTTP request can
* be sent in one go.
*/
struct Curl_send_buffer {
char *buffer;
size_t size_max;
size_t size_used;
};
typedef struct Curl_send_buffer Curl_send_buffer;
Curl_send_buffer *Curl_add_buffer_init(void);
CURLcode Curl_add_bufferf(Curl_send_buffer *in, const char *fmt, ...);
CURLcode Curl_add_buffer(Curl_send_buffer *in, const void *inptr, size_t size);
CURLcode Curl_add_buffer_send(Curl_send_buffer *in,
struct connectdata *conn,
long *bytes_written,
size_t included_body_bytes,
int socketindex);
CURLcode Curl_add_timecondition(struct SessionHandle *data,
Curl_send_buffer *buf);
CURLcode Curl_add_custom_headers(struct connectdata *conn,
Curl_send_buffer *req_buffer);
/* ftp can use this as well */
CURLcode Curl_proxyCONNECT(struct connectdata *conn,
int tunnelsocket,
@@ -87,5 +119,45 @@ int Curl_http_should_fail(struct connectdata *conn);
#define TINY_INITIAL_POST_SIZE 1024
#endif
#endif
#endif /* CURL_DISABLE_HTTP */
/****************************************************************************
* HTTP unique setup
***************************************************************************/
struct HTTP {
struct FormData *sendit;
curl_off_t postsize; /* off_t to handle large file sizes */
const char *postdata;
const char *p_pragma; /* Pragma: string */
const char *p_accept; /* Accept: string */
curl_off_t readbytecount;
curl_off_t writebytecount;
/* For FORM posting */
struct Form form;
struct back {
curl_read_callback fread_func; /* backup storage for fread pointer */
void *fread_in; /* backup storage for fread_in pointer */
const char *postdata;
curl_off_t postsize;
} backup;
enum {
HTTPSEND_NADA, /* init */
HTTPSEND_REQUEST, /* sending a request */
HTTPSEND_BODY, /* sending body */
HTTPSEND_LAST /* never use this */
} sending;
void *send_buffer; /* used if the request couldn't be sent in one chunk,
points to an allocated send_buffer struct */
};
CURLcode Curl_http_readwrite_headers(struct SessionHandle *data,
struct connectdata *conn,
ssize_t *nread,
bool *stop_reading);
#endif

View File

@@ -386,7 +386,7 @@ static void lm_resp(const unsigned char *keys,
setup_des_key(keys+14, DESKEY(ks));
DES_ecb_encrypt((DES_cblock*) plaintext, (DES_cblock*) (results+16),
DESKEY(ks), DES_ENCRYPT);
#elif USE_GNUTLS
#elif defined(USE_GNUTLS)
gcry_cipher_hd_t des;
gcry_cipher_open(&des, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0);
@@ -447,7 +447,7 @@ static void mk_lm_hash(struct SessionHandle *data,
setup_des_key(pw+7, DESKEY(ks));
DES_ecb_encrypt((DES_cblock *)magic, (DES_cblock *)(lmbuffer+8),
DESKEY(ks), DES_ENCRYPT);
#elif USE_GNUTLS
#elif defined(USE_GNUTLS)
gcry_cipher_hd_t des;
gcry_cipher_open(&des, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0);
@@ -508,7 +508,7 @@ static CURLcode mk_nt_hash(struct SessionHandle *data,
MD4_Init(&MD4pw);
MD4_Update(&MD4pw, pw, 2*len);
MD4_Final(ntbuffer, &MD4pw);
#elif USE_GNUTLS
#elif defined(USE_GNUTLS)
gcry_md_hd_t MD4pw;
gcry_md_open(&MD4pw, GCRY_MD_MD4, 0);
gcry_md_write(MD4pw, pw, 2*len);
@@ -911,7 +911,7 @@ CURLcode Curl_output_ntlm(struct connectdata *conn,
MD5_CTX MD5pw;
Curl_ossl_seed(conn->data); /* Initiate the seed if not already done */
RAND_bytes(entropy,8);
#elif USE_GNUTLS
#elif defined(USE_GNUTLS)
gcry_md_hd_t MD5pw;
Curl_gtls_seed(conn->data); /* Initiate the seed if not already done */
gcry_randomize(entropy, 8, GCRY_STRONG_RANDOM);
@@ -930,7 +930,7 @@ CURLcode Curl_output_ntlm(struct connectdata *conn,
MD5_Init(&MD5pw);
MD5_Update(&MD5pw, tmp, 16);
MD5_Final(md5sum, &MD5pw);
#elif USE_GNUTLS
#elif defined(USE_GNUTLS)
gcry_md_open(&MD5pw, GCRY_MD_MD5, 0);
gcry_md_write(MD5pw, tmp, MD5_DIGEST_LENGTH);
memcpy(md5sum, gcry_md_read (MD5pw, 0), MD5_DIGEST_LENGTH);

View File

@@ -53,7 +53,7 @@
#ifdef HAVE_STROPTS_H
# include <stropts.h>
#endif
#ifdef VMS
#ifdef __VMS
# include <inet.h>
#endif

1028
lib/imap.c Normal file

File diff suppressed because it is too large Load Diff

56
lib/imap.h Normal file
View File

@@ -0,0 +1,56 @@
#ifndef __IMAP_H
#define __IMAP_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 2009, 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$
***************************************************************************/
#include "pingpong.h"
/****************************************************************************
* IMAP unique setup
***************************************************************************/
typedef enum {
IMAP_STOP, /* do nothing state, stops the state machine */
IMAP_SERVERGREET, /* waiting for the initial greeting immediately after
a connect */
IMAP_LOGIN,
IMAP_STARTTLS,
IMAP_SELECT,
IMAP_FETCH,
IMAP_LOGOUT,
IMAP_LAST /* never used */
} imapstate;
/* imap_conn is used for struct connection-oriented data in the connectdata
struct */
struct imap_conn {
struct pingpong pp;
char *mailbox; /* what to FETCH */
imapstate state; /* always use imap.c:state() to change state! */
int cmdid; /* id number/index */
const char *idstr; /* pointer to a string for which to wait for as id */
};
extern const struct Curl_handler Curl_handler_imap;
extern const struct Curl_handler Curl_handler_imaps;
#endif /* __IMAP_H */

View File

@@ -200,7 +200,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
}
/* Get the URL scheme ( either ldap or ldaps ) */
if(Curl_raw_equal(conn->protostr, "LDAPS"))
if(conn->protocol & PROT_SSL)
ldap_ssl = 1;
infof(data, "LDAP local: trying to establish %s connection\n",
ldap_ssl ? "encrypted" : "cleartext");
@@ -262,7 +262,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
}
server = ldapssl_init(conn->host.name, (int)conn->port, 1);
if(server == NULL) {
failf(data, "LDAP local: Cannot connect to %s:%d",
failf(data, "LDAP local: Cannot connect to %s:%hu",
conn->host.name, conn->port);
status = CURLE_COULDNT_CONNECT;
goto quit;
@@ -302,7 +302,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
}
server = ldap_init(conn->host.name, (int)conn->port);
if(server == NULL) {
failf(data, "LDAP local: Cannot connect to %s:%d",
failf(data, "LDAP local: Cannot connect to %s:%hu",
conn->host.name, conn->port);
status = CURLE_COULDNT_CONNECT;
goto quit;
@@ -337,7 +337,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
} else {
server = ldap_init(conn->host.name, (int)conn->port);
if(server == NULL) {
failf(data, "LDAP local: Cannot connect to %s:%d",
failf(data, "LDAP local: Cannot connect to %s:%hu",
conn->host.name, conn->port);
status = CURLE_COULDNT_CONNECT;
goto quit;
@@ -488,15 +488,15 @@ static void _ldap_trace (const char *fmt, ...)
*/
static int str2scope (const char *p)
{
if(!stricmp(p, "one"))
if(strequal(p, "one"))
return LDAP_SCOPE_ONELEVEL;
if(!stricmp(p, "onetree"))
if(strequal(p, "onetree"))
return LDAP_SCOPE_ONELEVEL;
if(!stricmp(p, "base"))
if(strequal(p, "base"))
return LDAP_SCOPE_BASE;
if(!stricmp(p, "sub"))
if(strequal(p, "sub"))
return LDAP_SCOPE_SUBTREE;
if(!stricmp( p, "subtree"))
if(strequal( p, "subtree"))
return LDAP_SCOPE_SUBTREE;
return (-1);
}
@@ -582,7 +582,7 @@ static int _ldap_url_parse2 (const struct connectdata *conn, LDAPURLDesc *ludp)
if(!conn->data ||
!conn->data->state.path ||
conn->data->state.path[0] != '/' ||
!checkprefix(conn->protostr, conn->data->change.url))
!checkprefix("LDAP", conn->data->change.url))
return LDAP_INVALID_SYNTAX;
ludp->lud_scope = LDAP_SCOPE_BASE;

View File

@@ -10,17 +10,19 @@ ATCPSDKI= /GG/netinclude
CC = m68k-amigaos-gcc
CFLAGS = -I$(ATCPSDKI) -m68020-60 -O2 -msoft-float -noixemul -g -I. -I../include -W -Wall
OBJS = amigaos.c base64.c connect.c content_encoding.c cookie.c dict.c easy.c \
escape.c file.c formdata.c ftp.c getenv.c getinfo.c hash.c hostip.c \
hostip4.c hostsyn.c http.c http_chunks.c http_digest.c \
http_negotiate.c http_ntlm.c if2ip.c inet_ntop.c inet_pton.c krb4.c \
ldap.c llist.c md5.c memdebug.c mprintf.c multi.c netrc.c parsedate.c \
progress.c security.c select.c sendf.c share.c speedcheck.c ssluse.c \
strequal.c strtok.c telnet.c timeval.c transfer.c url.c version.c \
sslgen.c gtls.c strerror.c rawstr.c curl_addrinfo.c curl_rand.c \
socks_gssapi.c socks_sspi.c curl_sspi.c slist.c nonblock.c \
curl_memrchr.c
OBJS = amigaos.c \
file.c timeval.c base64.c hostip.c progress.c formdata.c \
cookie.c http.c sendf.c ftp.c url.c dict.c if2ip.c speedcheck.c \
ldap.c ssluse.c version.c getenv.c escape.c mprintf.c telnet.c \
netrc.c getinfo.c transfer.c strequal.c easy.c security.c krb4.c \
krb5.c memdebug.c http_chunks.c strtok.c connect.c llist.c hash.c \
multi.c content_encoding.c share.c http_digest.c md5.c curl_rand.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 splay.c \
strdup.c socks.c ssh.c nss.c qssl.c rawstr.c curl_addrinfo.c \
socks_gssapi.c socks_sspi.c curl_sspi.c slist.c nonblock.c \
curl_memrchr.c imap.c pop3.c smtp.c pingpong.c rtsp.c curl_threads.c
all: $(OBJS:.c=.o)
ar cru libcurl.a $(OBJS:.c=.o)

View File

@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2009, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2010, 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
@@ -36,6 +36,7 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
@@ -104,12 +105,14 @@ static bool countcheck(const char *func, int line, const char *source)
should not be made */
if(memlimit && source) {
if(!memsize) {
if(logfile && source)
fprintf(logfile, "LIMIT %s:%d %s reached memlimit\n",
source, line, func);
if(source)
if(source) {
/* log to file */
curl_memlog("LIMIT %s:%d %s reached memlimit\n",
source, line, func);
/* log to stderr also */
fprintf(stderr, "LIMIT %s:%d %s reached memlimit\n",
source, line, func);
}
SET_ERRNO(ENOMEM);
return TRUE; /* RETURN ERROR! */
}
@@ -117,9 +120,9 @@ static bool countcheck(const char *func, int line, const char *source)
memsize--; /* countdown */
/* log the countdown */
if(logfile && source)
fprintf(logfile, "LIMIT %s:%d %ld ALLOCS left\n",
source, line, memsize);
if(source)
curl_memlog("LIMIT %s:%d %ld ALLOCS left\n",
source, line, memsize);
}
@@ -146,9 +149,9 @@ void *curl_domalloc(size_t wantedsize, int line, const char *source)
mem->size = wantedsize;
}
if(logfile && source)
fprintf(logfile, "MEM %s:%d malloc(%zd) = %p\n",
source, line, wantedsize, mem ? mem->mem : 0);
if(source)
curl_memlog("MEM %s:%d malloc(%zd) = %p\n",
source, line, wantedsize, mem ? mem->mem : 0);
return (mem ? mem->mem : NULL);
}
@@ -175,9 +178,9 @@ void *curl_docalloc(size_t wanted_elements, size_t wanted_size,
mem->size = user_size;
}
if(logfile && source)
fprintf(logfile, "MEM %s:%d calloc(%zu,%zu) = %p\n",
source, line, wanted_elements, wanted_size, mem ? mem->mem : 0);
if(source)
curl_memlog("MEM %s:%d calloc(%zu,%zu) = %p\n",
source, line, wanted_elements, wanted_size, mem?mem->mem:0);
return (mem ? mem->mem : NULL);
}
@@ -197,9 +200,9 @@ char *curl_dostrdup(const char *str, int line, const char *source)
if(mem)
memcpy(mem, str, len);
if(logfile)
fprintf(logfile, "MEM %s:%d strdup(%p) (%zu) = %p\n",
source, line, str, len, mem);
if(source)
curl_memlog("MEM %s:%d strdup(%p) (%zu) = %p\n",
source, line, str, len, mem);
return mem;
}
@@ -222,9 +225,9 @@ void *curl_dorealloc(void *ptr, size_t wantedsize,
mem = (struct memdebug *)((char *)ptr - offsetof(struct memdebug, mem));
mem = (Curl_crealloc)(mem, size);
if(logfile)
fprintf(logfile, "MEM %s:%d realloc(%p, %zu) = %p\n",
source, line, ptr, wantedsize, mem?mem->mem:NULL);
if(source)
curl_memlog("MEM %s:%d realloc(%p, %zu) = %p\n",
source, line, ptr, wantedsize, mem?mem->mem:NULL);
if(mem) {
mem->size = wantedsize;
@@ -248,17 +251,17 @@ void curl_dofree(void *ptr, int line, const char *source)
/* free for real */
(Curl_cfree)(mem);
if(logfile)
fprintf(logfile, "MEM %s:%d free(%p)\n", source, line, ptr);
if(source)
curl_memlog("MEM %s:%d free(%p)\n", source, line, ptr);
}
int curl_socket(int domain, int type, int protocol, int line,
const char *source)
{
int sockfd=socket(domain, type, protocol);
if(logfile && (sockfd!=-1))
fprintf(logfile, "FD %s:%d socket() = %d\n",
source, line, sockfd);
if(source && (sockfd!=-1))
curl_memlog("FD %s:%d socket() = %d\n",
source, line, sockfd);
return sockfd;
}
@@ -268,18 +271,18 @@ int curl_accept(int s, void *saddr, void *saddrlen,
struct sockaddr *addr = (struct sockaddr *)saddr;
curl_socklen_t *addrlen = (curl_socklen_t *)saddrlen;
int sockfd=accept(s, addr, addrlen);
if(logfile)
fprintf(logfile, "FD %s:%d accept() = %d\n",
source, line, sockfd);
if(source)
curl_memlog("FD %s:%d accept() = %d\n",
source, line, sockfd);
return sockfd;
}
/* separate function to allow libcurl to mark a "faked" close */
void curl_mark_sclose(int sockfd, int line, const char *source)
{
if(logfile)
fprintf(logfile, "FD %s:%d sclose(%d)\n",
source, line, sockfd);
if(source)
curl_memlog("FD %s:%d sclose(%d)\n",
source, line, sockfd);
}
/* this is our own defined way to close sockets on *ALL* platforms */
@@ -294,9 +297,9 @@ FILE *curl_fopen(const char *file, const char *mode,
int line, const char *source)
{
FILE *res=fopen(file, mode);
if(logfile)
fprintf(logfile, "FILE %s:%d fopen(\"%s\",\"%s\") = %p\n",
source, line, file, mode, res);
if(source)
curl_memlog("FILE %s:%d fopen(\"%s\",\"%s\") = %p\n",
source, line, file, mode, res);
return res;
}
@@ -305,9 +308,9 @@ FILE *curl_fdopen(int filedes, const char *mode,
int line, const char *source)
{
FILE *res=fdopen(filedes, mode);
if(logfile)
fprintf(logfile, "FILE %s:%d fdopen(\"%d\",\"%s\") = %p\n",
source, line, filedes, mode, res);
if(source)
curl_memlog("FILE %s:%d fdopen(\"%d\",\"%s\") = %p\n",
source, line, filedes, mode, res);
return res;
}
#endif
@@ -319,9 +322,39 @@ int curl_fclose(FILE *file, int line, const char *source)
assert(file != NULL);
res=fclose(file);
if(logfile)
fprintf(logfile, "FILE %s:%d fclose(%p)\n",
source, line, file);
if(source)
curl_memlog("FILE %s:%d fclose(%p)\n",
source, line, file);
return res;
}
#define LOGLINE_BUFSIZE 1024
/* this does the writting to the memory tracking log file */
void curl_memlog(const char *format, ...)
{
char *buf;
int nchars;
va_list ap;
if(!logfile)
return;
buf = (Curl_cmalloc)(LOGLINE_BUFSIZE);
if(!buf)
return;
va_start(ap, format);
nchars = vsnprintf(buf, LOGLINE_BUFSIZE, format, ap);
va_end(ap);
if(nchars > LOGLINE_BUFSIZE - 1)
nchars = LOGLINE_BUFSIZE - 1;
if(nchars > 0)
fwrite(buf, 1, nchars, logfile);
(Curl_cfree)(buf);
}
#endif /* CURLDEBUG */

View File

@@ -8,7 +8,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2009, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2010, 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
@@ -54,6 +54,7 @@ CURL_EXTERN void curl_dofree(void *ptr, int line, const char *source);
CURL_EXTERN char *curl_dostrdup(const char *str, int line, const char *source);
CURL_EXTERN void curl_memdebug(const char *logname);
CURL_EXTERN void curl_memlimit(long limit);
CURL_EXTERN void curl_memlog(const char *format, ...);
/* file descriptor manipulators */
CURL_EXTERN int curl_socket(int domain, int type, int protocol, int line , const char *);

View File

@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1999 - 2009, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1999 - 2010, 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
@@ -1219,7 +1219,7 @@ int main()
curl_mprintf("%3d %5d\n", 10, 1998);
ptr=curl_maprintf("test this then baby %s%s%s%s%s%s %d %d %d loser baby get a hit in yer face now!", "", "pretty long string pretty long string pretty long string pretty long string pretty long string", "/", "/", "/", "pretty long string", 1998, 1999, 2001);
ptr=curl_maprintf("test this then baby %s%s%s%s%s%s %d %d %d loser baby get a kiss in yer face now!", "", "pretty long string pretty long string pretty long string pretty long string pretty long string", "/", "/", "/", "pretty long string", 1998, 1999, 2001);
puts(ptr);

View File

@@ -1,11 +1,11 @@
# Begin Group "Resource Files"
# PROP Default_Filter ""
# Begin Source File
SOURCE=.\libcurl.rc
# End Source File
# End Group
# End Target
# End Project
# Begin Group "Resource Files"
# PROP Default_Filter ""
# Begin Source File
SOURCE=.\libcurl.rc
# End Source File
# End Group
# End Target
# End Project

View File

@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2009, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2010, 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
@@ -181,8 +181,8 @@ struct Curl_multi {
previous callback */
};
static bool multi_conn_using(struct Curl_multi *multi,
struct SessionHandle *data);
static struct connectdata *conn_using(struct Curl_multi *multi,
struct SessionHandle *data);
static void singlesocket(struct Curl_multi *multi,
struct Curl_one_easy *easy);
static void add_closure(struct Curl_multi *multi,
@@ -258,7 +258,6 @@ static void multistate(struct Curl_one_easy *easy, CURLMstate state)
struct Curl_sh_entry {
struct SessionHandle *easy;
time_t timestamp;
long inuse;
int action; /* what action READ/WRITE this socket waits for */
curl_socket_t socket; /* mainly to ease debugging */
void *socketp; /* settable by users with curl_multi_assign() */
@@ -568,7 +567,7 @@ static void debug_print_sock_hash(void *p)
struct Curl_sh_entry *sh = (struct Curl_sh_entry *)p;
fprintf(stderr, " [easy %p/magic %x/socket %d]",
(void *)sh->easy, sh->easy->magic, sh->socket);
(void *)sh->easy, sh->easy->magic, (int)sh->socket);
}
#endif
@@ -577,6 +576,7 @@ CURLMcode curl_multi_remove_handle(CURLM *multi_handle,
{
struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
struct Curl_one_easy *easy;
struct connectdata *conn;
/* First, make some basic checks that the CURLM handle is a good handle */
if(!GOOD_MULTI_HANDLE(multi))
@@ -649,6 +649,9 @@ CURLMcode curl_multi_remove_handle(CURLM *multi_handle,
Curl_getoff_all_pipelines(easy->easy_handle, easy->easy_conn);
}
/* figure out if the easy handle is used by a connection in the cache */
conn = conn_using(multi, easy->easy_handle);
/* If this easy_handle was the last one in charge for one or more
connections in the shared connection cache, we might need to keep this
handle around until either A) the connection is closed and killed
@@ -665,16 +668,22 @@ CURLMcode curl_multi_remove_handle(CURLM *multi_handle,
we need to add this handle to the list of "easy handles kept around for
nice connection closures".
*/
if(multi_conn_using(multi, easy->easy_handle)) {
/* There's at least one connection using this handle so we must keep
this handle around. We also keep the connection cache pointer
pointing to the shared one since that will be used on close as
well. */
easy->easy_handle->state.shared_conn = multi;
if(conn) {
if(conn->protocol & PROT_CLOSEACTION) {
/* There's at least one CLOSEACTION connection using this handle so we
must keep this handle around. We also keep the connection cache
pointer pointing to the shared one since that will be used on close
as well. */
easy->easy_handle->state.shared_conn = multi;
/* this handle is still being used by a shared connection cache and
thus we leave it around for now */
add_closure(multi, easy->easy_handle);
/* this handle is still being used by a shared connection cache and
thus we leave it around for now */
add_closure(multi, easy->easy_handle);
}
else
/* disconect the easy handle from the connection since the connection
will now remain but this easy handle is going */
conn->data = NULL;
}
if(easy->easy_handle->state.connc->type == CONNCACHE_MULTI) {
@@ -914,7 +923,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
/* Handle the case when the pipe breaks, i.e., the connection
we're using gets cleaned up and we're left with nothing. */
if(easy->easy_handle->state.pipe_broke) {
infof(easy->easy_handle, "Pipe broke: handle 0x%x, url = %s\n",
infof(easy->easy_handle, "Pipe broke: handle 0x%p, url = %s\n",
easy, easy->easy_handle->state.path);
if(easy->state != CURLM_STATE_COMPLETED) {
@@ -1090,14 +1099,14 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
else
#endif
multistate(easy, CURLM_STATE_PROTOCONNECT);
}
else {
else
/* after the connect has completed, go WAITDO or DO */
multistate(easy, multi->pipelining_enabled?
CURLM_STATE_WAITDO:CURLM_STATE_DO);
result = CURLM_CALL_MULTI_PERFORM;
}
result = CURLM_CALL_MULTI_PERFORM;
}
break;
@@ -1122,12 +1131,12 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
case CURLM_STATE_WAITDO:
/* Wait for our turn to DO when we're pipelining requests */
#ifdef DEBUGBUILD
infof(easy->easy_handle, "Conn %d send pipe %d inuse %d athead %d\n",
infof(easy->easy_handle, "Conn %ld send pipe %zu inuse %d athead %d\n",
easy->easy_conn->connectindex,
easy->easy_conn->send_pipe->size,
easy->easy_conn->writechannel_inuse,
easy->easy_conn->writechannel_inuse?1:0,
isHandleAtHead(easy->easy_handle,
easy->easy_conn->send_pipe));
easy->easy_conn->send_pipe)?1:0);
#endif
if(!easy->easy_conn->writechannel_inuse &&
isHandleAtHead(easy->easy_handle,
@@ -1192,7 +1201,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
disconnect_conn = TRUE;
}
else
retry = newurl?TRUE:FALSE;
retry = (bool)(newurl?TRUE:FALSE);
Curl_posttransfer(easy->easy_handle);
drc = Curl_done(&easy->easy_conn, easy->result, FALSE);
@@ -1310,12 +1319,12 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
}
#ifdef DEBUGBUILD
else {
infof(easy->easy_handle, "Conn %d recv pipe %d inuse %d athead %d\n",
infof(easy->easy_handle, "Conn %ld recv pipe %zu inuse %d athead %d\n",
easy->easy_conn->connectindex,
easy->easy_conn->recv_pipe->size,
easy->easy_conn->readchannel_inuse,
easy->easy_conn->readchannel_inuse?1:0,
isHandleAtHead(easy->easy_handle,
easy->easy_conn->recv_pipe));
easy->easy_conn->recv_pipe)?1:0);
}
#endif
break;
@@ -1384,7 +1393,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
easy->result = Curl_retry_request(easy->easy_conn, &newurl);
if(!easy->result)
retry = newurl?TRUE:FALSE;
retry = (bool)(newurl?TRUE:FALSE);
/* call this even if the readwrite function returned error */
Curl_posttransfer(easy->easy_handle);
@@ -1559,17 +1568,6 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
multi->num_msgs++; /* increase message counter */
}
if(CURLM_CALL_MULTI_PERFORM == result)
/* Set the timeout for this handle to expire really soon so that it will
be taken care of even when this handle is added in the midst of
operation when only the curl_multi_socket() API is used. During that
flow, only sockets that time-out or have actions will be dealt
with. Since this handle has no action yet, we make sure it times out to
get things to happen. Also, this makes it less important for callers of
the curl_multi_* functions to bother about the CURLM_CALL_MULTI_PERFORM
return code, as long as they deal with the timeouts properly. */
Curl_expire(easy->easy_handle, 1);
return result;
}
@@ -1588,7 +1586,10 @@ CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles)
while(easy != &multi->easy) {
CURLMcode result;
result = multi_runsingle(multi, easy);
do
result = multi_runsingle(multi, easy);
while (CURLM_CALL_MULTI_PERFORM == result);
if(result)
returncode = result;
@@ -1750,7 +1751,6 @@ static void singlesocket(struct Curl_multi *multi,
struct Curl_one_easy *easy_by_hash;
bool remove_sock_from_hash;
memset(&socks, 0, sizeof(socks));
for(i=0; i< MAX_SOCKSPEREASYHANDLE; i++)
socks[i] = CURL_SOCKET_BAD;
@@ -1948,7 +1948,9 @@ static CURLMcode multi_socket(struct Curl_multi *multi,
if(data->set.one_easy->easy_conn) /* set socket event bitmask */
data->set.one_easy->easy_conn->cselect_bits = ev_bitmask;
result = multi_runsingle(multi, data->set.one_easy);
do
result = multi_runsingle(multi, data->set.one_easy);
while (CURLM_CALL_MULTI_PERFORM == result);
if(data->set.one_easy->easy_conn)
data->set.one_easy->easy_conn->cselect_bits = 0;
@@ -1977,7 +1979,9 @@ static CURLMcode multi_socket(struct Curl_multi *multi,
/* the first loop lap 'data' can be NULL */
if(data) {
result = multi_runsingle(multi, data->set.one_easy);
do
result = multi_runsingle(multi, data->set.one_easy);
while (CURLM_CALL_MULTI_PERFORM == result);
if(CURLM_OK >= result)
/* get the socket(s) and check if the state has been changed since
@@ -2369,20 +2373,19 @@ CURLMcode curl_multi_assign(CURLM *multi_handle,
return CURLM_OK;
}
static bool multi_conn_using(struct Curl_multi *multi,
struct SessionHandle *data)
static struct connectdata *conn_using(struct Curl_multi *multi,
struct SessionHandle *data)
{
/* any live CLOSEACTION-connections pointing to the give 'data' ? */
/* a connection in the connection cache pointing to the given 'data' ? */
int i;
for(i=0; i< multi->connc->num; i++) {
if(multi->connc->connects[i] &&
(multi->connc->connects[i]->data == data) &&
multi->connc->connects[i]->protocol & PROT_CLOSEACTION)
return TRUE;
(multi->connc->connects[i]->data == data))
return multi->connc->connects[i];
}
return FALSE;
return NULL;
}
/* Add the given data pointer to the list of 'closure handles' that are kept

View File

@@ -33,7 +33,7 @@
#ifdef HAVE_PWD_H
#include <pwd.h>
#endif
#ifdef VMS
#ifdef __VMS
#include <unixlib.h>
#endif
@@ -117,7 +117,7 @@ int Curl_parsenetrc(const char *host,
struct passwd *pw;
pw= getpwuid(geteuid());
if(pw) {
#ifdef VMS
#ifdef __VMS
home = decc_translate_vms(pw->pw_dir);
#else
home = pw->pw_dir;

View File

@@ -42,7 +42,7 @@
#if (defined(HAVE_IOCTL_FIONBIO) && defined(NETWARE))
#include <sys/filio.h>
#endif
#ifdef VMS
#ifdef __VMS
#include <in.h>
#include <inet.h>
#endif

View File

@@ -990,7 +990,9 @@ CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex)
{
PRInt32 err;
PRFileDesc *model = NULL;
PRBool ssl2, ssl3, tlsv1;
PRBool ssl2 = PR_FALSE;
PRBool ssl3 = PR_FALSE;
PRBool tlsv1 = PR_FALSE;
struct SessionHandle *data = conn->data;
curl_socket_t sockfd = conn->sock[sockindex];
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
@@ -1106,8 +1108,6 @@ CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex)
if(SSL_OptionSet(model, SSL_HANDSHAKE_AS_CLIENT, PR_TRUE) != SECSuccess)
goto error;
ssl2 = ssl3 = tlsv1 = PR_FALSE;
switch (data->set.ssl.version) {
default:
case CURL_SSLVERSION_DEFAULT:

536
lib/pingpong.c Normal file
View File

@@ -0,0 +1,536 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2009, 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.
*
* 'pingpong' is for generic back-and-forth support functions used by FTP,
* IMAP, POP3, SMTP and whatever more that likes them.
*
* $Id$
***************************************************************************/
#include "setup.h"
#include "urldata.h"
#include "sendf.h"
#include "select.h"
#include "progress.h"
#include "speedcheck.h"
#include "pingpong.h"
#include "multiif.h"
#define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h>
#include "curl_memory.h"
/* The last #include file should be: */
#include "memdebug.h"
#ifdef USE_PINGPONG
/* Returns timeout in ms. 0 or negative number means the timeout has already
triggered */
long Curl_pp_state_timeout(struct pingpong *pp)
{
struct connectdata *conn = pp->conn;
struct SessionHandle *data=conn->data;
long timeout_ms=360000; /* in milliseconds */
if(data->set.server_response_timeout )
/* if CURLOPT_SERVER_RESPONSE_TIMEOUT is set, use that to determine
remaining time. Also, use pp->response because SERVER_RESPONSE_TIMEOUT
is supposed to govern the response for any given server response, not
for the time from connect to the given server response. */
timeout_ms = data->set.server_response_timeout - /* timeout time */
Curl_tvdiff(Curl_tvnow(), pp->response); /* spent time */
else if(data->set.timeout)
/* if timeout is requested, find out how much remaining time we have */
timeout_ms = data->set.timeout - /* timeout time */
Curl_tvdiff(Curl_tvnow(), conn->now); /* spent time */
else
/* Without a requested timeout, we only wait 'response_time' seconds for
the full response to arrive before we bail out */
timeout_ms = pp->response_time -
Curl_tvdiff(Curl_tvnow(), pp->response); /* spent time */
return timeout_ms;
}
/*
* Curl_pp_multi_statemach()
*
* called repeatedly until done when the multi interface is used.
*/
CURLcode Curl_pp_multi_statemach(struct pingpong *pp)
{
struct connectdata *conn = pp->conn;
curl_socket_t sock = conn->sock[FIRSTSOCKET];
int rc;
struct SessionHandle *data=conn->data;
CURLcode result = CURLE_OK;
long timeout_ms = Curl_pp_state_timeout(pp);
if(timeout_ms <= 0) {
failf(data, "server response timeout");
return CURLE_OPERATION_TIMEDOUT;
}
rc = Curl_socket_ready(pp->sendleft?CURL_SOCKET_BAD:sock, /* reading */
pp->sendleft?sock:CURL_SOCKET_BAD, /* writing */
0);
if(rc == -1) {
failf(data, "select/poll error");
return CURLE_OUT_OF_MEMORY;
}
else if(rc != 0)
result = pp->statemach_act(conn);
/* if rc == 0, then select() timed out */
return result;
}
/*
* Curl_pp_easy_statemach()
*
* called repeatedly until done when the easy interface is used.
*/
CURLcode Curl_pp_easy_statemach(struct pingpong *pp)
{
struct connectdata *conn = pp->conn;
curl_socket_t sock = conn->sock[FIRSTSOCKET];
int rc;
long interval_ms;
long timeout_ms = Curl_pp_state_timeout(pp);
struct SessionHandle *data=conn->data;
CURLcode result;
if(timeout_ms <=0 ) {
failf(data, "server response timeout");
return CURLE_OPERATION_TIMEDOUT; /* already too little time */
}
interval_ms = 1000; /* use 1 second timeout intervals */
if(timeout_ms < interval_ms)
interval_ms = timeout_ms;
rc = Curl_socket_ready(pp->sendleft?CURL_SOCKET_BAD:sock, /* reading */
pp->sendleft?sock:CURL_SOCKET_BAD, /* writing */
(int)interval_ms);
if(Curl_pgrsUpdate(conn))
result = CURLE_ABORTED_BY_CALLBACK;
else
result = Curl_speedcheck(data, Curl_tvnow());
if(result)
;
else if(rc == -1) {
failf(data, "select/poll error");
result = CURLE_OUT_OF_MEMORY;
}
else if(rc)
result = pp->statemach_act(conn);
return result;
}
/* initialize stuff to prepare for reading a fresh new response */
void Curl_pp_init(struct pingpong *pp)
{
struct connectdata *conn = pp->conn;
pp->nread_resp = 0;
pp->linestart_resp = conn->data->state.buffer;
pp->pending_resp = TRUE;
pp->response = Curl_tvnow(); /* start response time-out now! */
}
/***********************************************************************
*
* Curl_pp_sendfv()
*
* Send the formated string as a command to a pingpong server. Note that
* the string should not have any CRLF appended, as this function will
* append the necessary things itself.
*
* NOTE: we build the command in a fixed-length buffer, which sets length
* restrictions on the command!
*
* made to never block
*/
CURLcode Curl_pp_vsendf(struct pingpong *pp,
const char *fmt,
va_list args)
{
ssize_t bytes_written;
/* may still not be big enough for some krb5 tokens */
#define SBUF_SIZE 1024
char s[SBUF_SIZE];
size_t write_len;
char *sptr=s;
CURLcode res = CURLE_OK;
struct connectdata *conn = pp->conn;
struct SessionHandle *data = conn->data;
#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI)
enum protection_level data_sec = conn->data_prot;
#endif
vsnprintf(s, SBUF_SIZE-3, fmt, args);
strcat(s, "\r\n"); /* append a trailing CRLF */
bytes_written=0;
write_len = strlen(s);
Curl_pp_init(pp);
#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 */
#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI)
conn->data_prot = prot_cmd;
#endif
res = Curl_write(conn, conn->sock[FIRSTSOCKET], sptr, write_len,
&bytes_written);
#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI)
conn->data_prot = data_sec;
#endif
if(CURLE_OK != res)
return res;
if(conn->data->set.verbose)
Curl_debug(conn->data, CURLINFO_HEADER_OUT,
sptr, (size_t)bytes_written, conn);
if(bytes_written != (ssize_t)write_len) {
/* the whole chunk was not sent, store the rest of the data */
write_len -= bytes_written;
sptr += bytes_written;
pp->sendthis = malloc(write_len);
if(pp->sendthis) {
memcpy(pp->sendthis, sptr, write_len);
pp->sendsize = pp->sendleft = write_len;
}
else {
failf(data, "out of memory");
res = CURLE_OUT_OF_MEMORY;
}
}
else
pp->response = Curl_tvnow();
return res;
}
/***********************************************************************
*
* Curl_pp_sendf()
*
* Send the formated string as a command to a pingpong server. Note that
* the string should not have any CRLF appended, as this function will
* append the necessary things itself.
*
* NOTE: we build the command in a fixed-length buffer, which sets length
* restrictions on the command!
*
* made to never block
*/
CURLcode Curl_pp_sendf(struct pingpong *pp,
const char *fmt, ...)
{
CURLcode res;
va_list ap;
va_start(ap, fmt);
res = Curl_pp_vsendf(pp, fmt, ap);
va_end(ap);
return res;
}
/*
* Curl_pp_readresp()
*
* Reads a piece of a server response.
*/
CURLcode Curl_pp_readresp(curl_socket_t sockfd,
struct pingpong *pp,
int *code, /* return the server code if done */
size_t *size) /* size of the response */
{
ssize_t perline; /* count bytes per line */
bool keepon=TRUE;
ssize_t gotbytes;
char *ptr;
struct connectdata *conn = pp->conn;
struct SessionHandle *data = conn->data;
char * const buf = data->state.buffer;
CURLcode result = CURLE_OK;
*code = 0; /* 0 for errors or not done */
*size = 0;
ptr=buf + pp->nread_resp;
/* number of bytes in the current line, so far */
perline = (ssize_t)(ptr-pp->linestart_resp);
keepon=TRUE;
while((pp->nread_resp<BUFSIZE) && (keepon && !result)) {
if(pp->cache) {
/* we had data in the "cache", copy that instead of doing an actual
* read
*
* ftp->cache_size is cast to int here. This should be safe,
* because it would have been populated with something of size
* int to begin with, even though its datatype may be larger
* than an int.
*/
DEBUGASSERT((ptr+pp->cache_size) <= (buf+BUFSIZE+1));
memcpy(ptr, pp->cache, pp->cache_size);
gotbytes = pp->cache_size;
free(pp->cache); /* free the cache */
pp->cache = NULL; /* clear the pointer */
pp->cache_size = 0; /* zero the size just in case */
}
else {
int res;
#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI)
enum protection_level prot = conn->data_prot;
conn->data_prot = 0;
#endif
DEBUGASSERT((ptr+BUFSIZE-pp->nread_resp) <= (buf+BUFSIZE+1));
res = Curl_read(conn, sockfd, ptr, BUFSIZE-pp->nread_resp,
&gotbytes);
#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI)
conn->data_prot = prot;
#endif
if(res < 0)
/* EWOULDBLOCK */
return CURLE_OK; /* return */
#ifdef CURL_DOES_CONVERSIONS
if((res == CURLE_OK) && (gotbytes > 0)) {
/* convert from the network encoding */
res = Curl_convert_from_network(data, ptr, gotbytes);
/* Curl_convert_from_network calls failf if unsuccessful */
}
#endif /* CURL_DOES_CONVERSIONS */
if(CURLE_OK != res) {
result = (CURLcode)res; /* Set outer result variable to this error. */
keepon = FALSE;
}
}
if(!keepon)
;
else if(gotbytes <= 0) {
keepon = FALSE;
result = CURLE_RECV_ERROR;
failf(data, "FTP response reading failed");
}
else {
/* we got a whole chunk of data, which can be anything from one
* byte to a set of lines and possible just a piece of the last
* line */
ssize_t i;
ssize_t clipamount = 0;
bool restart = FALSE;
data->req.headerbytecount += (long)gotbytes;
pp->nread_resp += gotbytes;
for(i = 0; i < gotbytes; ptr++, i++) {
perline++;
if(*ptr=='\n') {
/* a newline is CRLF in ftp-talk, so the CR is ignored as
the line isn't really terminated until the LF comes */
/* output debug output if that is requested */
#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI)
if(!conn->sec_complete)
#endif
if(data->set.verbose)
Curl_debug(data, CURLINFO_HEADER_IN,
pp->linestart_resp, (size_t)perline, conn);
/*
* We pass all response-lines to the callback function registered
* for "headers". The response lines can be seen as a kind of
* headers.
*/
result = Curl_client_write(conn, CLIENTWRITE_HEADER,
pp->linestart_resp, perline);
if(result)
return result;
if(pp->endofresp(pp, code)) {
/* This is the end of the last line, copy the last line to the
start of the buffer and zero terminate, for old times sake (and
krb4)! */
char *meow;
int n;
for(meow=pp->linestart_resp, n=0; meow<ptr; meow++, n++)
buf[n] = *meow;
*meow=0; /* zero terminate */
keepon=FALSE;
pp->linestart_resp = ptr+1; /* advance pointer */
i++; /* skip this before getting out */
*size = pp->nread_resp; /* size of the response */
pp->nread_resp = 0; /* restart */
break;
}
perline=0; /* line starts over here */
pp->linestart_resp = ptr+1;
}
}
if(!keepon && (i != gotbytes)) {
/* We found the end of the response lines, but we didn't parse the
full chunk of data we have read from the server. We therefore need
to store the rest of the data to be checked on the next invoke as
it may actually contain another end of response already! */
clipamount = gotbytes - i;
restart = TRUE;
}
else if(keepon) {
if((perline == gotbytes) && (gotbytes > BUFSIZE/2)) {
/* We got an excessive line without newlines and we need to deal
with it. We keep the first bytes of the line then we throw
away the rest. */
infof(data, "Excessive server response line length received, %zd bytes."
" Stripping\n", gotbytes);
restart = TRUE;
/* we keep 40 bytes since all our pingpong protocols are only
interested in the first piece */
clipamount = 40;
}
else if(pp->nread_resp > BUFSIZE/2) {
/* We got a large chunk of data and there's potentially still trailing
data to take care of, so we put any such part in the "cache", clear
the buffer to make space and restart. */
clipamount = perline;
restart = TRUE;
}
}
else if(i == gotbytes)
restart = TRUE;
if(clipamount) {
pp->cache_size = clipamount;
pp->cache = malloc(pp->cache_size);
if(pp->cache)
memcpy(pp->cache, pp->linestart_resp, pp->cache_size);
else
return CURLE_OUT_OF_MEMORY;
}
if(restart) {
/* now reset a few variables to start over nicely from the start of
the big buffer */
pp->nread_resp = 0; /* start over from scratch in the buffer */
ptr = pp->linestart_resp = buf;
perline = 0;
}
} /* there was data */
} /* while there's buffer left and loop is requested */
pp->pending_resp = FALSE;
return result;
}
int Curl_pp_getsock(struct pingpong *pp,
curl_socket_t *socks,
int numsocks)
{
struct connectdata *conn = pp->conn;
if(!numsocks)
return GETSOCK_BLANK;
socks[0] = conn->sock[FIRSTSOCKET];
if(pp->sendleft) {
/* write mode */
return GETSOCK_WRITESOCK(0);
}
/* read mode */
return GETSOCK_READSOCK(0);
}
CURLcode Curl_pp_flushsend(struct pingpong *pp)
{
/* we have a piece of a command still left to send */
struct connectdata *conn = pp->conn;
ssize_t written;
CURLcode result = CURLE_OK;
curl_socket_t sock = conn->sock[FIRSTSOCKET];
result = Curl_write(conn, sock, pp->sendthis + pp->sendsize -
pp->sendleft, pp->sendleft, &written);
if(result)
return result;
if(written != (ssize_t)pp->sendleft) {
/* only a fraction was sent */
pp->sendleft -= written;
}
else {
free(pp->sendthis);
pp->sendthis=NULL;
pp->sendleft = pp->sendsize = 0;
pp->response = Curl_tvnow();
}
return CURLE_OK;
}
CURLcode Curl_pp_disconnect(struct pingpong *pp)
{
if(pp->cache) {
free(pp->cache);
pp->cache = NULL;
}
return CURLE_OK;
}
#endif

148
lib/pingpong.h Normal file
View File

@@ -0,0 +1,148 @@
#ifndef __PINGPONG_H
#define __PINGPONG_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2007, 2009, 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$
***************************************************************************/
#include <stdarg.h>
#include "setup.h"
#if !defined(CURL_DISABLE_IMAP) || !defined(CURL_DISABLE_FTP) || \
!defined(CURL_DISABLE_POP3) || !defined(CURL_DISABLE_SMTP)
#define USE_PINGPONG
#endif
/* forward-declaration, this is defined in urldata.h */
struct connectdata;
/*
* 'pingpong' is the generic struct used for protocols doing server<->client
* conversations in a back-and-forth style such as FTP, IMAP, POP3, SMTP etc.
*
* It holds response cache and non-blocking sending data.
*/
struct pingpong {
char *cache; /* data cache between getresponse()-calls */
size_t cache_size; /* size of cache in bytes */
size_t nread_resp; /* number of bytes currently read of a server response */
char *linestart_resp; /* line start pointer for the server response
reader function */
bool pending_resp; /* set TRUE when a server response is pending or in
progress, and is cleared once the last response is
read */
char *sendthis; /* allocated pointer to a buffer that is to be sent to the
server */
size_t sendleft; /* number of bytes left to send from the sendthis buffer */
size_t sendsize; /* total size of the sendthis buffer */
struct timeval response; /* set to Curl_tvnow() when a command has been sent
off, used to time-out response reading */
long response_time; /* When no timeout is given, this is the amount of
seconds we await for a server response. */
struct connectdata *conn; /* points to the connectdata struct that this
belongs to */
/* Function pointers the protocols MUST implement and provide for the
pingpong layer to function */
CURLcode (*statemach_act)(struct connectdata *conn);
int (*endofresp)(struct pingpong *pp, int *code);
};
/*
* Curl_pp_multi_statemach()
*
* called repeatedly until done when the multi interface is used.
*/
CURLcode Curl_pp_multi_statemach(struct pingpong *pp);
/*
* Curl_pp_easy_statemach()
*
* called repeatedly until done when the easy interface is used.
*/
CURLcode Curl_pp_easy_statemach(struct pingpong *pp);
/* initialize stuff to prepare for reading a fresh new response */
void Curl_pp_init(struct pingpong *pp);
/* Returns timeout in ms. 0 or negative number means the timeout has already
triggered */
long Curl_pp_state_timeout(struct pingpong *pp);
/***********************************************************************
*
* Curl_pp_sendf()
*
* Send the formated string as a command to a pingpong server. Note that
* the string should not have any CRLF appended, as this function will
* append the necessary things itself.
*
* NOTE: we build the command in a fixed-length buffer, which sets length
* restrictions on the command!
*
* made to never block
*/
CURLcode Curl_pp_sendf(struct pingpong *pp,
const char *fmt, ...);
/***********************************************************************
*
* Curl_pp_vsendf()
*
* Send the formated string as a command to a pingpong server. Note that
* the string should not have any CRLF appended, as this function will
* append the necessary things itself.
*
* NOTE: we build the command in a fixed-length buffer, which sets length
* restrictions on the command!
*
* made to never block
*/
CURLcode Curl_pp_vsendf(struct pingpong *pp,
const char *fmt,
va_list args);
/*
* Curl_pp_readresp()
*
* Reads a piece of a server response.
*/
CURLcode Curl_pp_readresp(curl_socket_t sockfd,
struct pingpong *pp,
int *code, /* return the server code if done */
size_t *size); /* size of the response */
CURLcode Curl_pp_flushsend(struct pingpong *pp);
/* call this when a pingpong connection is disconnected */
CURLcode Curl_pp_disconnect(struct pingpong *pp);
int Curl_pp_getsock(struct pingpong *pp, curl_socket_t *socks,
int numsocks);
#endif /* __PINGPONG_H */

960
lib/pop3.c Normal file
View File

@@ -0,0 +1,960 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2010, 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.
*
* RFC1939 POP3 protocol
* RFC2384 POP URL Scheme
* RFC2595 Using TLS with IMAP, POP3 and ACAP
*
* $Id$
***************************************************************************/
#include "setup.h"
#ifndef CURL_DISABLE_POP3
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
#include <ctype.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
#endif
#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
#ifdef HAVE_UTSNAME_H
#include <sys/utsname.h>
#endif
#ifdef HAVE_NETDB_H
#include <netdb.h>
#endif
#ifdef __VMS
#include <in.h>
#include <inet.h>
#endif
#if (defined(NETWARE) && defined(__NOVELL_LIBC__))
#undef in_addr_t
#define in_addr_t unsigned long
#endif
#include <curl/curl.h>
#include "urldata.h"
#include "sendf.h"
#include "easyif.h" /* for Curl_convert_... prototypes */
#include "if2ip.h"
#include "hostip.h"
#include "progress.h"
#include "transfer.h"
#include "escape.h"
#include "http.h" /* for HTTP proxy tunnel stuff */
#include "socks.h"
#include "pop3.h"
#include "strtoofft.h"
#include "strequal.h"
#include "sslgen.h"
#include "connect.h"
#include "strerror.h"
#include "select.h"
#include "multiif.h"
#include "url.h"
#include "rawstr.h"
#include "strtoofft.h"
#define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h>
#include "curl_memory.h"
/* The last #include file should be: */
#include "memdebug.h"
/* Local API functions */
static CURLcode pop3_parse_url_path(struct connectdata *conn);
static CURLcode pop3_regular_transfer(struct connectdata *conn, bool *done);
static CURLcode pop3_do(struct connectdata *conn, bool *done);
static CURLcode pop3_done(struct connectdata *conn,
CURLcode, bool premature);
static CURLcode pop3_connect(struct connectdata *conn, bool *done);
static CURLcode pop3_disconnect(struct connectdata *conn);
static CURLcode pop3_multi_statemach(struct connectdata *conn, bool *done);
static int pop3_getsock(struct connectdata *conn,
curl_socket_t *socks,
int numsocks);
static CURLcode pop3_doing(struct connectdata *conn,
bool *dophase_done);
static CURLcode pop3_setup_connection(struct connectdata * conn);
/*
* POP3 protocol handler.
*/
const struct Curl_handler Curl_handler_pop3 = {
"POP3", /* scheme */
pop3_setup_connection, /* setup_connection */
pop3_do, /* do_it */
pop3_done, /* done */
ZERO_NULL, /* do_more */
pop3_connect, /* connect_it */
pop3_multi_statemach, /* connecting */
pop3_doing, /* doing */
pop3_getsock, /* proto_getsock */
pop3_getsock, /* doing_getsock */
ZERO_NULL, /* perform_getsock */
pop3_disconnect, /* disconnect */
PORT_POP3, /* defport */
PROT_POP3 /* protocol */
};
#ifdef USE_SSL
/*
* POP3S protocol handler.
*/
const struct Curl_handler Curl_handler_pop3s = {
"POP3S", /* scheme */
pop3_setup_connection, /* setup_connection */
pop3_do, /* do_it */
pop3_done, /* done */
ZERO_NULL, /* do_more */
pop3_connect, /* connect_it */
pop3_multi_statemach, /* connecting */
pop3_doing, /* doing */
pop3_getsock, /* proto_getsock */
pop3_getsock, /* doing_getsock */
ZERO_NULL, /* perform_getsock */
pop3_disconnect, /* disconnect */
PORT_POP3S, /* defport */
PROT_POP3 | PROT_POP3S | PROT_SSL /* protocol */
};
#endif
#ifndef CURL_DISABLE_HTTP
/*
* HTTP-proxyed POP3 protocol handler.
*/
static const struct Curl_handler Curl_handler_pop3_proxy = {
"POP3", /* scheme */
ZERO_NULL, /* setup_connection */
Curl_http, /* do_it */
Curl_http_done, /* done */
ZERO_NULL, /* do_more */
ZERO_NULL, /* connect_it */
ZERO_NULL, /* connecting */
ZERO_NULL, /* doing */
ZERO_NULL, /* proto_getsock */
ZERO_NULL, /* doing_getsock */
ZERO_NULL, /* perform_getsock */
ZERO_NULL, /* disconnect */
PORT_POP3, /* defport */
PROT_HTTP /* protocol */
};
#ifdef USE_SSL
/*
* HTTP-proxyed POP3S protocol handler.
*/
static const struct Curl_handler Curl_handler_pop3s_proxy = {
"POP3S", /* scheme */
ZERO_NULL, /* setup_connection */
Curl_http, /* do_it */
Curl_http_done, /* done */
ZERO_NULL, /* do_more */
ZERO_NULL, /* connect_it */
ZERO_NULL, /* connecting */
ZERO_NULL, /* doing */
ZERO_NULL, /* proto_getsock */
ZERO_NULL, /* doing_getsock */
ZERO_NULL, /* perform_getsock */
ZERO_NULL, /* disconnect */
PORT_POP3S, /* defport */
PROT_HTTP /* protocol */
};
#endif
#endif
/* function that checks for a pop3 status code at the start of the given
string */
static int pop3_endofresp(struct pingpong *pp,
int *resp)
{
char *line = pp->linestart_resp;
size_t len = pp->nread_resp;
if( ((len >= 3) && !memcmp("+OK", line, 3)) ||
((len >= 4) && !memcmp("-ERR", line, 4)) ) {
*resp=line[1]; /* O or E */
return TRUE;
}
return FALSE; /* nothing for us */
}
/* This is the ONLY way to change POP3 state! */
static void state(struct connectdata *conn,
pop3state newstate)
{
#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
/* for debug purposes */
static const char * const names[]={
"STOP",
"SERVERGREET",
"USER",
"PASS",
"STARTTLS",
"RETR",
"QUIT",
/* LAST */
};
#endif
struct pop3_conn *pop3c = &conn->proto.pop3c;
#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
if(pop3c->state != newstate)
infof(conn->data, "POP3 %p state change from %s to %s\n",
pop3c, names[pop3c->state], names[newstate]);
#endif
pop3c->state = newstate;
}
static CURLcode pop3_state_user(struct connectdata *conn)
{
CURLcode result;
struct FTP *pop3 = conn->data->state.proto.pop3;
/* send USER */
result = Curl_pp_sendf(&conn->proto.pop3c.pp, "USER %s",
pop3->user?pop3->user:"");
if(result)
return result;
state(conn, POP3_USER);
return CURLE_OK;
}
/* For the POP3 "protocol connect" and "doing" phases only */
static int pop3_getsock(struct connectdata *conn,
curl_socket_t *socks,
int numsocks)
{
return Curl_pp_getsock(&conn->proto.pop3c.pp, socks, numsocks);
}
/* for STARTTLS responses */
static CURLcode pop3_state_starttls_resp(struct connectdata *conn,
int pop3code,
pop3state instate)
{
CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data;
(void)instate; /* no use for this yet */
if(pop3code != 'O') {
failf(data, "STARTTLS denied. %c", pop3code);
result = CURLE_LOGIN_DENIED;
}
else {
/* Curl_ssl_connect is BLOCKING */
result = Curl_ssl_connect(conn, FIRSTSOCKET);
if(CURLE_OK == result) {
conn->protocol |= PROT_POP3S;
result = pop3_state_user(conn);
}
}
state(conn, POP3_STOP);
return result;
}
/* for USER responses */
static CURLcode pop3_state_user_resp(struct connectdata *conn,
int pop3code,
pop3state instate)
{
CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data;
struct FTP *pop3 = data->state.proto.pop3;
(void)instate; /* no use for this yet */
if(pop3code != 'O') {
failf(data, "Access denied. %c", pop3code);
result = CURLE_LOGIN_DENIED;
}
/* send PASS */
result = Curl_pp_sendf(&conn->proto.pop3c.pp, "PASS %s",
pop3->passwd?pop3->passwd:"");
if(result)
return result;
state(conn, POP3_PASS);
return result;
}
/* for PASS responses */
static CURLcode pop3_state_pass_resp(struct connectdata *conn,
int pop3code,
pop3state instate)
{
CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data;
(void)instate; /* no use for this yet */
if(pop3code != 'O') {
failf(data, "Access denied. %c", pop3code);
result = CURLE_LOGIN_DENIED;
}
state(conn, POP3_STOP);
return result;
}
/* for the retr response */
static CURLcode pop3_state_retr_resp(struct connectdata *conn,
int pop3code,
pop3state instate)
{
CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data;
struct FTP *pop3 = data->state.proto.pop3;
struct pop3_conn *pop3c = &conn->proto.pop3c;
struct pingpong *pp = &pop3c->pp;
(void)instate; /* no use for this yet */
if('O' != pop3code) {
state(conn, POP3_STOP);
return CURLE_RECV_ERROR;
}
/* POP3 download */
result=Curl_setup_transfer(conn, FIRSTSOCKET, -1, FALSE,
pop3->bytecountp,
-1, NULL); /* no upload here */
if(pp->cache) {
/* At this point there is a bunch of data in the header "cache" that is
actually body content, send it as body and then skip it. Do note
that there may even be additional "headers" after the body. */
/* we may get the EOB already here! */
result = Curl_pop3_write(conn, pp->cache, pp->cache_size);
if(result)
return result;
/* cache is drained */
free(pp->cache);
pp->cache = NULL;
pp->cache_size = 0;
}
state(conn, POP3_STOP);
return result;
}
/* start the DO phase */
static CURLcode pop3_retr(struct connectdata *conn)
{
CURLcode result = CURLE_OK;
struct pop3_conn *pop3c = &conn->proto.pop3c;
result = Curl_pp_sendf(&conn->proto.pop3c.pp, "RETR %s", pop3c->mailbox);
if(result)
return result;
state(conn, POP3_RETR);
return result;
}
static CURLcode pop3_statemach_act(struct connectdata *conn)
{
CURLcode result;
curl_socket_t sock = conn->sock[FIRSTSOCKET];
struct SessionHandle *data=conn->data;
int pop3code;
struct pop3_conn *pop3c = &conn->proto.pop3c;
struct pingpong *pp = &pop3c->pp;
size_t nread = 0;
if(pp->sendleft)
return Curl_pp_flushsend(pp);
/* we read a piece of response */
result = Curl_pp_readresp(sock, pp, &pop3code, &nread);
if(result)
return result;
if(pop3code) {
/* we have now received a full POP3 server response */
switch(pop3c->state) {
case POP3_SERVERGREET:
if(pop3code != 'O') {
failf(data, "Got unexpected pop3-server response");
return CURLE_FTP_WEIRD_SERVER_REPLY;
}
if(data->set.ftp_ssl && !conn->ssl[FIRSTSOCKET].use) {
/* We don't have a SSL/TLS connection yet, but SSL is requested. Switch
to TLS connection now */
result = Curl_pp_sendf(&pop3c->pp, "STARTTLS", NULL);
state(conn, POP3_STARTTLS);
}
else
result = pop3_state_user(conn);
if(result)
return result;
break;
case POP3_USER:
result = pop3_state_user_resp(conn, pop3code, pop3c->state);
break;
case POP3_PASS:
result = pop3_state_pass_resp(conn, pop3code, pop3c->state);
break;
case POP3_STARTTLS:
result = pop3_state_starttls_resp(conn, pop3code, pop3c->state);
break;
case POP3_RETR:
result = pop3_state_retr_resp(conn, pop3code, pop3c->state);
break;
case POP3_QUIT:
/* fallthrough, just stop! */
default:
/* internal error */
state(conn, POP3_STOP);
break;
}
}
return result;
}
/* called repeatedly until done from multi.c */
static CURLcode pop3_multi_statemach(struct connectdata *conn, bool *done)
{
struct pop3_conn *pop3c = &conn->proto.pop3c;
CURLcode result = Curl_pp_multi_statemach(&pop3c->pp);
*done = (bool)(pop3c->state == POP3_STOP);
return result;
}
static CURLcode pop3_easy_statemach(struct connectdata *conn)
{
struct pop3_conn *pop3c = &conn->proto.pop3c;
struct pingpong *pp = &pop3c->pp;
CURLcode result = CURLE_OK;
while(pop3c->state != POP3_STOP) {
result = Curl_pp_easy_statemach(pp);
if(result)
break;
}
return result;
}
/*
* Allocate and initialize the struct POP3 for the current SessionHandle. If
* need be.
*/
static CURLcode pop3_init(struct connectdata *conn)
{
struct SessionHandle *data = conn->data;
struct FTP *pop3 = data->state.proto.pop3;
if(!pop3) {
pop3 = data->state.proto.pop3 = calloc(sizeof(struct FTP), 1);
if(!pop3)
return CURLE_OUT_OF_MEMORY;
}
/* get some initial data into the pop3 struct */
pop3->bytecountp = &data->req.bytecount;
/* No need to duplicate user+password, the connectdata struct won't change
during a session, but we re-init them here since on subsequent inits
since the conn struct may have changed or been replaced.
*/
pop3->user = conn->user;
pop3->passwd = conn->passwd;
return CURLE_OK;
}
/*
* pop3_connect() should do everything that is to be considered a part of
* the connection phase.
*
* The variable 'done' points to will be TRUE if the protocol-layer connect
* phase is done when this function returns, or FALSE is not. When called as
* a part of the easy interface, it will always be TRUE.
*/
static CURLcode pop3_connect(struct connectdata *conn,
bool *done) /* see description above */
{
CURLcode result;
struct pop3_conn *pop3c = &conn->proto.pop3c;
struct SessionHandle *data=conn->data;
struct pingpong *pp = &pop3c->pp;
*done = FALSE; /* default to not done yet */
/* If there already is a protocol-specific struct allocated for this
sessionhandle, deal with it */
Curl_reset_reqproto(conn);
result = pop3_init(conn);
if(CURLE_OK != result)
return result;
/* We always support persistant connections on pop3 */
conn->bits.close = FALSE;
pp->response_time = RESP_TIMEOUT; /* set default response time-out */
pp->statemach_act = pop3_statemach_act;
pp->endofresp = pop3_endofresp;
pp->conn = conn;
#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_PROXY)
if(conn->bits.tunnel_proxy && conn->bits.httpproxy) {
/* for POP3 over HTTP proxy */
struct HTTP http_proxy;
struct FTP *pop3_save;
/* BLOCKING */
/* We want "seamless" POP3 operations through HTTP proxy tunnel */
/* Curl_proxyCONNECT is based on a pointer to a struct HTTP at the member
* conn->proto.http; we want POP3 through HTTP and we have to change the
* member temporarily for connecting to the HTTP proxy. After
* Curl_proxyCONNECT we have to set back the member to the original struct
* POP3 pointer
*/
pop3_save = data->state.proto.pop3;
memset(&http_proxy, 0, sizeof(http_proxy));
data->state.proto.http = &http_proxy;
result = Curl_proxyCONNECT(conn, FIRSTSOCKET,
conn->host.name, conn->remote_port);
data->state.proto.pop3 = pop3_save;
if(CURLE_OK != result)
return result;
}
#endif /* !CURL_DISABLE_HTTP && !CURL_DISABLE_PROXY */
if(conn->protocol & PROT_POP3S) {
/* BLOCKING */
/* POP3S is simply pop3 with SSL for the control channel */
/* now, perform the SSL initialization for this socket */
result = Curl_ssl_connect(conn, FIRSTSOCKET);
if(result)
return result;
}
Curl_pp_init(pp); /* init the response reader stuff */
/* When we connect, we start in the state where we await the server greet
response */
state(conn, POP3_SERVERGREET);
if(data->state.used_interface == Curl_if_multi)
result = pop3_multi_statemach(conn, done);
else {
result = pop3_easy_statemach(conn);
if(!result)
*done = TRUE;
}
return result;
}
/***********************************************************************
*
* pop3_done()
*
* The DONE function. This does what needs to be done after a single DO has
* performed.
*
* Input argument is already checked for validity.
*/
static CURLcode pop3_done(struct connectdata *conn, CURLcode status,
bool premature)
{
struct SessionHandle *data = conn->data;
struct FTP *pop3 = data->state.proto.pop3;
CURLcode result=CURLE_OK;
(void)premature;
if(!pop3)
/* When the easy handle is removed from the multi while libcurl is still
* trying to resolve the host name, it seems that the pop3 struct is not
* yet initialized, but the removal action calls Curl_done() which calls
* this function. So we simply return success if no pop3 pointer is set.
*/
return CURLE_OK;
if(status) {
conn->bits.close = TRUE; /* marked for closure */
result = status; /* use the already set error code */
}
/* clear these for next connection */
pop3->transfer = FTPTRANSFER_BODY;
return result;
}
/***********************************************************************
*
* pop3_perform()
*
* This is the actual DO function for POP3. Get a file/directory according to
* the options previously setup.
*/
static
CURLcode pop3_perform(struct connectdata *conn,
bool *connected, /* connect status after PASV / PORT */
bool *dophase_done)
{
/* this is POP3 and no proxy */
CURLcode result=CURLE_OK;
DEBUGF(infof(conn->data, "DO phase starts\n"));
if(conn->data->set.opt_no_body) {
/* requested no body means no transfer... */
struct FTP *pop3 = conn->data->state.proto.pop3;
pop3->transfer = FTPTRANSFER_INFO;
}
*dophase_done = FALSE; /* not done yet */
/* start the first command in the DO phase */
result = pop3_retr(conn);
if(result)
return result;
/* run the state-machine */
if(conn->data->state.used_interface == Curl_if_multi)
result = pop3_multi_statemach(conn, dophase_done);
else {
result = pop3_easy_statemach(conn);
*dophase_done = TRUE; /* with the easy interface we are done here */
}
*connected = conn->bits.tcpconnect;
if(*dophase_done)
DEBUGF(infof(conn->data, "DO phase is complete\n"));
return result;
}
/***********************************************************************
*
* pop3_do()
*
* This function is registered as 'curl_do' function. It decodes the path
* parts etc as a wrapper to the actual DO function (pop3_perform).
*
* The input argument is already checked for validity.
*/
static CURLcode pop3_do(struct connectdata *conn, bool *done)
{
CURLcode retcode = CURLE_OK;
*done = FALSE; /* default to false */
/*
Since connections can be re-used between SessionHandles, this might be a
connection already existing but on a fresh SessionHandle struct so we must
make sure we have a good 'struct POP3' to play with. For new connections,
the struct POP3 is allocated and setup in the pop3_connect() function.
*/
Curl_reset_reqproto(conn);
retcode = pop3_init(conn);
if(retcode)
return retcode;
retcode = pop3_parse_url_path(conn);
if(retcode)
return retcode;
retcode = pop3_regular_transfer(conn, done);
return retcode;
}
/***********************************************************************
*
* pop3_quit()
*
* This should be called before calling sclose(). We should then wait for the
* response from the server before returning. The calling code should then try
* to close the connection.
*
*/
static CURLcode pop3_quit(struct connectdata *conn)
{
CURLcode result = CURLE_OK;
result = Curl_pp_sendf(&conn->proto.pop3c.pp, "QUIT", NULL);
if(result)
return result;
state(conn, POP3_QUIT);
result = pop3_easy_statemach(conn);
return result;
}
/***********************************************************************
*
* pop3_disconnect()
*
* Disconnect from an POP3 server. Cleanup protocol-specific per-connection
* resources. BLOCKING.
*/
static CURLcode pop3_disconnect(struct connectdata *conn)
{
struct pop3_conn *pop3c= &conn->proto.pop3c;
/* We cannot send quit unconditionally. If this connection is stale or
bad in any way, sending quit and waiting around here will make the
disconnect wait in vain and cause more problems than we need to.
*/
/* The POP3 session may or may not have been allocated/setup at this
point! */
(void)pop3_quit(conn); /* ignore errors on the LOGOUT */
Curl_pp_disconnect(&pop3c->pp);
return CURLE_OK;
}
/***********************************************************************
*
* pop3_parse_url_path()
*
* Parse the URL path into separate path components.
*
*/
static CURLcode pop3_parse_url_path(struct connectdata *conn)
{
/* the pop3 struct is already inited in pop3_connect() */
struct pop3_conn *pop3c = &conn->proto.pop3c;
struct SessionHandle *data = conn->data;
const char *path = data->state.path;
int len;
if(!*path)
path = "INBOX";
/* url decode the path and use this mailbox */
pop3c->mailbox = curl_easy_unescape(data, path, 0, &len);
return CURLE_OK;
}
/* call this when the DO phase has completed */
static CURLcode pop3_dophase_done(struct connectdata *conn,
bool connected)
{
CURLcode result = CURLE_OK;
struct FTP *pop3 = conn->data->state.proto.pop3;
struct pop3_conn *pop3c = &conn->proto.pop3c;
(void)connected;
if(pop3->transfer != FTPTRANSFER_BODY)
/* no data to transfer */
result=Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
free(pop3c->mailbox);
return result;
}
/* called from multi.c while DOing */
static CURLcode pop3_doing(struct connectdata *conn,
bool *dophase_done)
{
CURLcode result;
result = pop3_multi_statemach(conn, dophase_done);
if(*dophase_done) {
result = pop3_dophase_done(conn, FALSE /* not connected */);
DEBUGF(infof(conn->data, "DO phase is complete\n"));
}
return result;
}
/***********************************************************************
*
* pop3_regular_transfer()
*
* The input argument is already checked for validity.
*
* Performs all commands done before a regular transfer between a local and a
* remote host.
*
*/
static
CURLcode pop3_regular_transfer(struct connectdata *conn,
bool *dophase_done)
{
CURLcode result=CURLE_OK;
bool connected=FALSE;
struct SessionHandle *data = conn->data;
data->req.size = -1; /* make sure this is unknown at this point */
Curl_pgrsSetUploadCounter(data, 0);
Curl_pgrsSetDownloadCounter(data, 0);
Curl_pgrsSetUploadSize(data, 0);
Curl_pgrsSetDownloadSize(data, 0);
result = pop3_perform(conn,
&connected, /* have we connected after PASV/PORT */
dophase_done); /* all commands in the DO-phase done? */
if(CURLE_OK == result) {
if(!*dophase_done)
/* the DO phase has not completed yet */
return CURLE_OK;
result = pop3_dophase_done(conn, connected);
if(result)
return result;
}
return result;
}
static CURLcode pop3_setup_connection(struct connectdata * conn)
{
struct SessionHandle *data = conn->data;
if(conn->bits.httpproxy && !data->set.tunnel_thru_httpproxy) {
/* Unless we have asked to tunnel pop3 operations through the proxy, we
switch and use HTTP operations only */
#ifndef CURL_DISABLE_HTTP
if(conn->handler == &Curl_handler_pop3)
conn->handler = &Curl_handler_pop3_proxy;
else {
#ifdef USE_SSL
conn->handler = &Curl_handler_pop3s_proxy;
#else
failf(data, "POP3S not supported!");
return CURLE_UNSUPPORTED_PROTOCOL;
#endif
}
/*
* We explicitly mark this connection as persistent here as we're doing
* POP3 over HTTP and thus we accidentally avoid setting this value
* otherwise.
*/
conn->bits.close = FALSE;
#else
failf(data, "POP3 over http proxy requires HTTP support built-in!");
return CURLE_UNSUPPORTED_PROTOCOL;
#endif
}
data->state.path++; /* don't include the initial slash */
return CURLE_OK;
}
/* this is the 5-bytes End-Of-Body marker for POP3 */
#define POP3_EOB "\x0d\x0a\x2e\x0d\x0a"
#define POP3_EOB_LEN 5
/*
* This function scans the body after the end-of-body and writes everything
* until the end is found.
*/
CURLcode Curl_pop3_write(struct connectdata *conn,
char *str,
size_t nread)
{
/* This code could be made into a special function in the handler struct. */
CURLcode result;
struct SessionHandle *data = conn->data;
struct SingleRequest *k = &data->req;
/* Detect the end-of-body marker, which is 5 bytes:
0d 0a 2e 0d 0a. This marker can of course be spread out
over up to 5 different data chunks. Deal with it! */
struct pop3_conn *pop3c = &conn->proto.pop3c;
int checkmax = (nread >= POP3_EOB_LEN?POP3_EOB_LEN:nread);
int checkleft = POP3_EOB_LEN-pop3c->eob;
int check = (checkmax >= checkleft?checkleft:checkmax);
if(!memcmp(POP3_EOB, &str[nread - check], check)) {
/* substring match */
pop3c->eob += check;
if(pop3c->eob == POP3_EOB_LEN) {
/* full match, the transfer is done! */
str[nread - check] = '\0';
nread -= check;
k->keepon &= ~KEEP_RECV;
pop3c->eob = 0;
}
}
else if(pop3c->eob) {
/* not a match, but we matched a piece before so we must now
send that part as body first, before we move on and send
this buffer */
result = Curl_client_write(conn, CLIENTWRITE_BODY,
(char *)POP3_EOB, pop3c->eob);
if(result)
return result;
pop3c->eob = 0;
}
result = Curl_client_write(conn, CLIENTWRITE_BODY, str, nread);
return result;
}
#endif /* CURL_DISABLE_POP3 */

62
lib/pop3.h Normal file
View File

@@ -0,0 +1,62 @@
#ifndef __POP3_H
#define __POP3_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 2009, 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$
***************************************************************************/
/****************************************************************************
* POP3 unique setup
***************************************************************************/
typedef enum {
POP3_STOP, /* do nothing state, stops the state machine */
POP3_SERVERGREET, /* waiting for the initial greeting immediately after
a connect */
POP3_USER,
POP3_PASS,
POP3_STARTTLS,
POP3_RETR,
POP3_QUIT,
POP3_LAST /* never used */
} pop3state;
/* pop3_conn is used for struct connection-oriented data in the connectdata
struct */
struct pop3_conn {
struct pingpong pp;
char *mailbox; /* what to RETR */
int eob; /* number of bytes of the EOB (End Of Body) that has been
received thus far */
pop3state state; /* always use pop3.c:state() to change state! */
};
extern const struct Curl_handler Curl_handler_pop3;
extern const struct Curl_handler Curl_handler_pop3s;
/*
* This function scans the body after the end-of-body and writes everything
* until the end is found.
*/
CURLcode Curl_pop3_write(struct connectdata *conn,
char *str,
size_t nread);
#endif /* __POP3_H */

View File

@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2009, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2010, 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
@@ -289,7 +289,7 @@ static int Curl_qsossl_close_one(struct ssl_connect_data * conn,
}
/* An SSL error. */
failf(data, "SSL_Destroy() returned error %d", SSL_Strerror(rc, NULL));
failf(data, "SSL_Destroy() returned error %s", SSL_Strerror(rc, NULL));
return -1;
}
@@ -406,7 +406,7 @@ ssize_t Curl_qsossl_send(struct connectdata * conn, int sockindex,
}
/* An SSL error. */
failf(conn->data, "SSL_Write() returned error %d",
failf(conn->data, "SSL_Write() returned error %s",
SSL_Strerror(rc, NULL));
return -1;
}

755
lib/rtsp.c Normal file
View File

@@ -0,0 +1,755 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2010, 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$
***************************************************************************/
#include "setup.h"
#ifndef CURL_DISABLE_RTSP
#include "urldata.h"
#include <curl/curl.h>
#include "transfer.h"
#include "sendf.h"
#include "easyif.h" /* for Curl_convert_... prototypes */
#include "multiif.h"
#include "http.h"
#include "url.h"
#include "progress.h"
#include "rtsp.h"
#include "rawstr.h"
#include "curl_memory.h"
#define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h>
/* The last #include file should be: */
#include "memdebug.h"
/*
* TODO (general)
* -incoming server requests
* -server CSeq counter
* -digest authentication
* -connect thru proxy
* -pipelining?
*/
#define RTP_PKT_CHANNEL(p) ((int)((unsigned char)((p)[1])))
#define RTP_PKT_LENGTH(p) ((((int)((unsigned char)((p)[2]))) << 8) | \
((int)((unsigned char)((p)[3]))))
static int rtsp_getsock_do(struct connectdata *conn,
curl_socket_t *socks,
int numsocks);
/* this returns the socket to wait for in the DO and DOING state for the multi
interface and then we're always _sending_ a request and thus we wait for
the single socket to become writable only */
static int rtsp_getsock_do(struct connectdata *conn,
curl_socket_t *socks,
int numsocks)
{
/* write mode */
(void)numsocks; /* unused, we trust it to be at least 1 */
socks[0] = conn->sock[FIRSTSOCKET];
return GETSOCK_WRITESOCK(0);
}
static
CURLcode rtp_client_write(struct connectdata *conn, char *ptr, size_t len);
/*
* RTSP handler interface.
*/
const struct Curl_handler Curl_handler_rtsp = {
"RTSP", /* scheme */
ZERO_NULL, /* setup_connection */
Curl_rtsp, /* do_it */
Curl_rtsp_done, /* done */
ZERO_NULL, /* do_more */
Curl_rtsp_connect, /* connect_it */
ZERO_NULL, /* connecting */
ZERO_NULL, /* doing */
ZERO_NULL, /* proto_getsock */
rtsp_getsock_do, /* doing_getsock */
ZERO_NULL, /* perform_getsock */
Curl_rtsp_disconnect, /* disconnect */
PORT_RTSP, /* defport */
PROT_RTSP, /* protocol */
};
CURLcode Curl_rtsp_connect(struct connectdata *conn, bool *done)
{
CURLcode httpStatus;
struct SessionHandle *data = conn->data;
httpStatus = Curl_http_connect(conn, done);
/* Initialize the CSeq if not already done */
if(data->state.rtsp_next_client_CSeq == 0)
data->state.rtsp_next_client_CSeq = 1;
if(data->state.rtsp_next_server_CSeq == 0)
data->state.rtsp_next_server_CSeq = 1;
conn->proto.rtspc.rtp_channel = -1;
return httpStatus;
}
CURLcode Curl_rtsp_disconnect(struct connectdata *conn) {
Curl_safefree(conn->proto.rtspc.rtp_buf);
return CURLE_OK;
}
CURLcode Curl_rtsp_done(struct connectdata *conn,
CURLcode status, bool premature)
{
struct SessionHandle *data = conn->data;
struct RTSP *rtsp = data->state.proto.rtsp;
CURLcode httpStatus;
long CSeq_sent;
long CSeq_recv;
/* Bypass HTTP empty-reply checks on receive */
if(data->set.rtspreq == RTSPREQ_RECEIVE)
premature = TRUE;
httpStatus = Curl_http_done(conn, status, premature);
if(rtsp) {
/* Check the sequence numbers */
CSeq_sent = rtsp->CSeq_sent;
CSeq_recv = rtsp->CSeq_recv;
if((data->set.rtspreq != RTSPREQ_RECEIVE) && (CSeq_sent != CSeq_recv)) {
failf(data, "The CSeq of this request %ld did not match the response %ld",
CSeq_sent, CSeq_recv);
return CURLE_RTSP_CSEQ_ERROR;
}
else if(data->set.rtspreq == RTSPREQ_RECEIVE &&
(conn->proto.rtspc.rtp_channel == -1)) {
infof(data, "Got an RTP Receive with a CSeq of %ld\n", CSeq_recv);
/* TODO CPC: Server -> Client logic here */
}
}
return httpStatus;
}
CURLcode Curl_rtsp(struct connectdata *conn, bool *done)
{
struct SessionHandle *data = conn->data;
CURLcode result=CURLE_OK;
Curl_RtspReq rtspreq = data->set.rtspreq;
struct RTSP *rtsp;
struct HTTP *http;
Curl_send_buffer *req_buffer;
curl_off_t postsize = 0; /* for ANNOUNCE and SET_PARAMETER */
curl_off_t putsize = 0; /* for ANNOUNCE and SET_PARAMETER */
const char *p_request = NULL;
const char *p_session_id = NULL;
const char *p_accept = NULL;
const char *p_accept_encoding = NULL;
const char *p_range = NULL;
const char *p_referrer = NULL;
const char *p_stream_uri = NULL;
const char *p_transport = NULL;
const char *p_uagent = NULL;
*done = TRUE;
Curl_reset_reqproto(conn);
if(!data->state.proto.rtsp) {
/* Only allocate this struct if we don't already have it! */
rtsp = calloc(1, sizeof(struct RTSP));
if(!rtsp)
return CURLE_OUT_OF_MEMORY;
data->state.proto.rtsp = rtsp;
}
else {
rtsp = data->state.proto.rtsp;
}
http = &(rtsp->http_wrapper);
/* Assert that no one has changed the RTSP struct in an evil way */
DEBUGASSERT((void *)http == (void *)rtsp);
rtsp->CSeq_sent = data->state.rtsp_next_client_CSeq;
rtsp->CSeq_recv = 0;
/* Setup the 'p_request' pointer to the proper p_request string
* Since all RTSP requests are included here, there is no need to
* support custom requests like HTTP.
**/
DEBUGASSERT((rtspreq > RTSPREQ_NONE && rtspreq < RTSPREQ_LAST));
data->set.opt_no_body = TRUE; /* most requests don't contain a body */
switch(rtspreq) {
case RTSPREQ_NONE:
failf(data, "Got invalid RTSP request: RTSPREQ_NONE");
return CURLE_BAD_FUNCTION_ARGUMENT;
case RTSPREQ_OPTIONS:
p_request = "OPTIONS";
break;
case RTSPREQ_DESCRIBE:
p_request = "DESCRIBE";
data->set.opt_no_body = FALSE;
break;
case RTSPREQ_ANNOUNCE:
p_request = "ANNOUNCE";
break;
case RTSPREQ_SETUP:
p_request = "SETUP";
break;
case RTSPREQ_PLAY:
p_request = "PLAY";
break;
case RTSPREQ_PAUSE:
p_request = "PAUSE";
break;
case RTSPREQ_TEARDOWN:
p_request = "TEARDOWN";
break;
case RTSPREQ_GET_PARAMETER:
p_request = "GET_PARAMETER";
data->set.opt_no_body = FALSE;
break;
case RTSPREQ_SET_PARAMETER:
p_request = "SET_PARAMETER";
break;
case RTSPREQ_RECORD:
p_request = "RECORD";
break;
case RTSPREQ_RECEIVE:
p_request = "";
/* Treat interleaved RTP as body*/
data->set.opt_no_body = FALSE;
break;
case RTSPREQ_LAST:
failf(data, "Got invalid RTSP request: RTSPREQ_LAST");
return CURLE_BAD_FUNCTION_ARGUMENT;
}
if(rtspreq == RTSPREQ_RECEIVE) {
result = Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE,
&http->readbytecount, -1, NULL);
return result;
}
p_session_id = data->set.str[STRING_RTSP_SESSION_ID];
if(!p_session_id &&
(rtspreq & ~(RTSPREQ_OPTIONS | RTSPREQ_DESCRIBE | RTSPREQ_SETUP))) {
failf(data, "Refusing to issue an RTSP request [%s] without a session ID.",
p_request ? p_request : "");
return CURLE_BAD_FUNCTION_ARGUMENT;
}
/* TODO: auth? */
/* TODO: proxy? */
/* Stream URI. Default to server '*' if not specified */
if(data->set.str[STRING_RTSP_STREAM_URI]) {
p_stream_uri = data->set.str[STRING_RTSP_STREAM_URI];
}
else {
p_stream_uri = "*";
}
/* Transport Header for SETUP requests */
p_transport = Curl_checkheaders(data, "Transport:");
if(rtspreq == RTSPREQ_SETUP && !p_transport) {
/* New Transport: setting? */
if(data->set.str[STRING_RTSP_TRANSPORT]) {
Curl_safefree(conn->allocptr.rtsp_transport);
conn->allocptr.rtsp_transport =
aprintf("Transport: %s\r\n",
data->set.str[STRING_RTSP_TRANSPORT]);
if(!conn->allocptr.rtsp_transport)
return CURLE_OUT_OF_MEMORY;
}
else {
failf(data,
"Refusing to issue an RTSP SETUP without a Transport: header.");
return CURLE_BAD_FUNCTION_ARGUMENT;
}
p_transport = conn->allocptr.rtsp_transport;
}
/* Accept Headers for DESCRIBE requests */
if(rtspreq == RTSPREQ_DESCRIBE) {
/* Accept Header */
p_accept = Curl_checkheaders(data, "Accept:")?
NULL:"Accept: application/sdp\r\n";
/* Accept-Encoding header */
if(!Curl_checkheaders(data, "Accept-Encoding:") &&
data->set.str[STRING_ENCODING]) {
Curl_safefree(conn->allocptr.accept_encoding);
conn->allocptr.accept_encoding =
aprintf("Accept-Encoding: %s\r\n", data->set.str[STRING_ENCODING]);
if(!conn->allocptr.accept_encoding)
return CURLE_OUT_OF_MEMORY;
p_accept_encoding = conn->allocptr.accept_encoding;
}
}
/* Default to text/parameters for GET_PARAMETER */
if(rtspreq == RTSPREQ_GET_PARAMETER) {
p_accept = Curl_checkheaders(data, "Accept:")?
NULL:"Accept: text/parameters\r\n";
}
/* The User-Agent string might have been allocated in url.c already, because
it might have been used in the proxy connect, but if we have got a header
with the user-agent string specified, we erase the previously made string
here. */
if(Curl_checkheaders(data, "User-Agent:") && conn->allocptr.uagent) {
Curl_safefree(conn->allocptr.uagent);
conn->allocptr.uagent = NULL;
}
else if(!Curl_checkheaders(data, "User-Agent:") &&
data->set.str[STRING_USERAGENT]) {
p_uagent = conn->allocptr.uagent;
}
/* Referrer */
Curl_safefree(conn->allocptr.ref);
if(data->change.referer && !Curl_checkheaders(data, "Referer:"))
conn->allocptr.ref = aprintf("Referer: %s\r\n", data->change.referer);
else
conn->allocptr.ref = NULL;
p_referrer = conn->allocptr.ref;
/*
* Range Header
* Only applies to PLAY, PAUSE, RECORD
*
* Go ahead and use the Range stuff supplied for HTTP
*/
if(data->state.use_range &&
(rtspreq & (RTSPREQ_PLAY | RTSPREQ_PAUSE | RTSPREQ_RECORD))) {
/* Check to see if there is a range set in the custom headers */
if(!Curl_checkheaders(data, "Range:") && data->state.range) {
Curl_safefree(conn->allocptr.rangeline);
conn->allocptr.rangeline = aprintf("Range: %s\r\n", data->state.range);
p_range = conn->allocptr.rangeline;
}
}
/*
* Sanity check the custom headers
*/
if(Curl_checkheaders(data, "CSeq:")) {
failf(data, "CSeq cannot be set as a custom header.");
return CURLE_RTSP_CSEQ_ERROR;
}
if(Curl_checkheaders(data, "Session:")) {
failf(data, "Session ID cannot be set as a custom header.");
return CURLE_BAD_FUNCTION_ARGUMENT;
}
/* Initialize a dynamic send buffer */
req_buffer = Curl_add_buffer_init();
if(!req_buffer)
return CURLE_OUT_OF_MEMORY;
result =
Curl_add_bufferf(req_buffer,
"%s %s RTSP/1.0\r\n" /* Request Stream-URI RTSP/1.0 */
"CSeq: %ld\r\n", /* CSeq */
(p_request ? p_request : ""), p_stream_uri,
rtsp->CSeq_sent);
if(result)
return result;
/*
* Rather than do a normal alloc line, keep the session_id unformatted
* to make comparison easier
*/
if(p_session_id) {
result = Curl_add_bufferf(req_buffer, "Session: %s\r\n", p_session_id);
if(result)
return result;
}
/*
* Shared HTTP-like options
*/
result = Curl_add_bufferf(req_buffer,
"%s" /* transport */
"%s" /* accept */
"%s" /* accept-encoding */
"%s" /* range */
"%s" /* referrer */
"%s" /* user-agent */
,
p_transport ? p_transport : "",
p_accept ? p_accept : "",
p_accept_encoding ? p_accept_encoding : "",
p_range ? p_range : "",
p_referrer ? p_referrer : "",
p_uagent ? p_uagent : "");
if(result)
return result;
if((rtspreq == RTSPREQ_SETUP) || (rtspreq == RTSPREQ_DESCRIBE)) {
result = Curl_add_timecondition(data, req_buffer);
if(result)
return result;
}
result = Curl_add_custom_headers(conn, req_buffer);
if(result)
return result;
if(rtspreq == RTSPREQ_ANNOUNCE || rtspreq == RTSPREQ_SET_PARAMETER) {
if(data->set.upload) {
putsize = data->set.infilesize;
data->set.httpreq = HTTPREQ_PUT;
}
else {
postsize = (data->set.postfieldsize != -1)?
data->set.postfieldsize:
(data->set.postfields? (curl_off_t)strlen(data->set.postfields):0);
data->set.httpreq = HTTPREQ_POST;
}
/* As stated in the http comments, it is probably not wise to
* actually set a custom Content-Length in the headers */
if(!Curl_checkheaders(data, "Content-Length:")) {
result = Curl_add_bufferf(req_buffer,
"Content-Length: %" FORMAT_OFF_T"\r\n",
(data->set.upload ? putsize : postsize));
if(result)
return result;
}
if(rtspreq == RTSPREQ_SET_PARAMETER) {
if(!Curl_checkheaders(data, "Content-Type:")) {
result = Curl_add_bufferf(req_buffer,
"Content-Type: text/parameters\r\n");
if(result)
return result;
}
}
if(rtspreq == RTSPREQ_ANNOUNCE) {
if(!Curl_checkheaders(data, "Content-Type:")) {
result = Curl_add_bufferf(req_buffer,
"Content-Type: application/sdp\r\n");
if(result)
return result;
}
}
data->state.expect100header = FALSE; /* RTSP posts are simple/small */
}
/* RTSP never allows chunked transfer */
data->req.forbidchunk = TRUE;
/* Finish the request buffer */
result = Curl_add_buffer(req_buffer, "\r\n", 2);
if(result)
return result;
if(postsize > 0) {
result = Curl_add_buffer(req_buffer, data->set.postfields,
(size_t)postsize);
if(result)
return result;
}
/* issue the request */
result = Curl_add_buffer_send(req_buffer, conn,
&data->info.request_size, 0, FIRSTSOCKET);
if(result) {
failf(data, "Failed sending RTSP request");
return result;
}
result = Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE,
&http->readbytecount,
putsize?FIRSTSOCKET:-1,
putsize?&http->writebytecount:NULL);
if(result) {
failf(data, "Failed RTSP transfer");
return result;
}
/* Increment the CSeq on success */
data->state.rtsp_next_client_CSeq++;
if(http->writebytecount) {
/* if a request-body has been sent off, we make sure this progress is
noted properly */
Curl_pgrsSetUploadCounter(data, http->writebytecount);
if(Curl_pgrsUpdate(conn))
result = CURLE_ABORTED_BY_CALLBACK;
}
return result;
}
CURLcode Curl_rtsp_rtp_readwrite(struct SessionHandle *data,
struct connectdata *conn,
ssize_t *nread,
bool *readmore) {
struct SingleRequest *k = &data->req;
struct rtsp_conn *rtspc = &(conn->proto.rtspc);
char *rtp; /* moving pointer to rtp data */
ssize_t rtp_dataleft; /* how much data left to parse in this round */
char *scratch;
CURLcode result;
if(rtspc->rtp_buf) {
/* There was some leftover data the last time. Merge buffers */
char *newptr = realloc(rtspc->rtp_buf, rtspc->rtp_bufsize + *nread);
if(!newptr) {
Curl_safefree(rtspc->rtp_buf);
rtspc->rtp_buf = NULL;
rtspc->rtp_bufsize = 0;
return CURLE_OUT_OF_MEMORY;
}
rtspc->rtp_buf = newptr;
memcpy(rtspc->rtp_buf + rtspc->rtp_bufsize, k->str, *nread);
rtspc->rtp_bufsize += *nread;
rtp = rtspc->rtp_buf;
rtp_dataleft = rtspc->rtp_bufsize;
}
else {
/* Just parse the request buffer directly */
rtp = k->str;
rtp_dataleft = *nread;
}
while((rtp_dataleft > 0) &&
(rtp[0] == '$')) {
if(rtp_dataleft > 4) {
int rtp_length;
/* Parse the header */
/* The channel identifier immediately follows and is 1 byte */
rtspc->rtp_channel = RTP_PKT_CHANNEL(rtp);
/* The length is two bytes */
rtp_length = RTP_PKT_LENGTH(rtp);
if(rtp_dataleft < rtp_length + 4) {
/* Need more - incomplete payload*/
*readmore = TRUE;
break;
}
else {
/* We have the full RTP interleaved packet
* Write out the header including the leading '$' */
DEBUGF(infof(data, "RTP write channel %d rtp_length %d\n",
rtspc->rtp_channel, rtp_length));
result = rtp_client_write(conn, &rtp[0], rtp_length + 4);
if(result) {
failf(data, "Got an error writing an RTP packet");
*readmore = FALSE;
Curl_safefree(rtspc->rtp_buf);
rtspc->rtp_buf = NULL;
rtspc->rtp_bufsize = 0;
return result;
}
/* Move forward in the buffer */
rtp_dataleft -= rtp_length + 4;
rtp += rtp_length + 4;
if(data->set.rtspreq == RTSPREQ_RECEIVE) {
/* If we are in a passive receive, give control back
* to the app as often as we can.
*/
k->keepon &= ~KEEP_RECV;
}
}
}
else {
/* Need more - incomplete header */
*readmore = TRUE;
break;
}
}
if(rtp_dataleft != 0 && rtp[0] == '$') {
DEBUGF(infof(data, "RTP Rewinding %zu %s\n", rtp_dataleft,
*readmore ? "(READMORE)" : ""));
/* Store the incomplete RTP packet for a "rewind" */
scratch = malloc(rtp_dataleft);
if(!scratch) {
Curl_safefree(rtspc->rtp_buf);
rtspc->rtp_buf = NULL;
rtspc->rtp_bufsize = 0;
return CURLE_OUT_OF_MEMORY;
}
memcpy(scratch, rtp, rtp_dataleft);
Curl_safefree(rtspc->rtp_buf);
rtspc->rtp_buf = scratch;
rtspc->rtp_bufsize = rtp_dataleft;
/* As far as the transfer is concerned, this data is consumed */
*nread = 0;
return CURLE_OK;
}
else {
/* Fix up k->str to point just after the last RTP packet */
k->str += *nread - rtp_dataleft;
/* either all of the data has been read or...
* rtp now points at the next byte to parse
*/
if(rtp_dataleft > 0)
DEBUGASSERT(k->str[0] == rtp[0]);
DEBUGASSERT(rtp_dataleft <= *nread); /* sanity check */
*nread = rtp_dataleft;
}
/* If we get here, we have finished with the leftover/merge buffer */
Curl_safefree(rtspc->rtp_buf);
rtspc->rtp_buf = NULL;
rtspc->rtp_bufsize = 0;
return CURLE_OK;
}
static
CURLcode rtp_client_write(struct connectdata *conn, char *ptr, size_t len)
{
struct SessionHandle *data = conn->data;
size_t wrote;
curl_write_callback writeit;
if(len == 0) {
failf (data, "Cannot write a 0 size RTP packet.");
return CURLE_WRITE_ERROR;
}
writeit = data->set.fwrite_rtp?data->set.fwrite_rtp:data->set.fwrite_func;
wrote = writeit(ptr, 1, len, data->set.rtp_out);
if(CURL_WRITEFUNC_PAUSE == wrote) {
failf (data, "Cannot pause RTP");
return CURLE_WRITE_ERROR;
}
if(wrote != len) {
failf (data, "Failed writing RTP data");
return CURLE_WRITE_ERROR;
}
return CURLE_OK;
}
CURLcode Curl_rtsp_parseheader(struct connectdata *conn,
char *header)
{
struct SessionHandle *data = conn->data;
long CSeq = 0;
if(checkprefix("CSeq:", header)) {
/* Store the received CSeq. Match is verified in rtsp_done */
int nc;
char *temp = strdup(header);
if(!temp)
return CURLE_OUT_OF_MEMORY;
Curl_strntoupper(temp, temp, sizeof(temp));
nc = sscanf(temp, "CSEQ: %ld", &CSeq);
free(temp);
if(nc == 1) {
data->state.proto.rtsp->CSeq_recv = CSeq; /* mark the request */
data->state.rtsp_CSeq_recv = CSeq; /* update the handle */
}
else {
failf(data, "Unable to read the CSeq header: [%s]", header);
return CURLE_RTSP_CSEQ_ERROR;
}
}
else if(checkprefix("Session:", header)) {
char *start;
/* Find the first non-space letter */
start = header + 9;
while(*start && ISSPACE(*start))
start++;
if(!start) {
failf(data, "Got a blank Session ID");
}
else if(data->set.str[STRING_RTSP_SESSION_ID]) {
/* If the Session ID is set, then compare */
if(strncmp(start, data->set.str[STRING_RTSP_SESSION_ID],
strlen(data->set.str[STRING_RTSP_SESSION_ID])) != 0) {
failf(data, "Got RTSP Session ID Line [%s], but wanted ID [%s]",
start, data->set.str[STRING_RTSP_SESSION_ID]);
return CURLE_RTSP_SESSION_ERROR;
}
}
else {
/* If the Session ID is not set, and we find it in a response, then
set it */
/* The session ID can be an alphanumeric or a 'safe' character
*
* RFC 2326 15.1 Base Syntax:
* safe = "\$" | "-" | "_" | "." | "+"
* */
char *end = start;
while(*end &&
(ISALNUM(*end) || *end == '-' || *end == '_' || *end == '.' ||
*end == '+' ||
(*end == '\\' && *(end + 1) && *(end + 1) == '$' && (++end, 1))))
end++;
/* Copy the id substring into a new buffer */
data->set.str[STRING_RTSP_SESSION_ID] = malloc(end - start + 1);
if(data->set.str[STRING_RTSP_SESSION_ID] == NULL)
return CURLE_OUT_OF_MEMORY;
memcpy(data->set.str[STRING_RTSP_SESSION_ID], start, end - start);
(data->set.str[STRING_RTSP_SESSION_ID])[end - start] = '\0';
}
}
return CURLE_OK;
}
#endif /* CURL_DISABLE_RTSP */

83
lib/rtsp.h Normal file
View File

@@ -0,0 +1,83 @@
#ifndef __RTSP_H_
#define __RTSP_H_
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2010, 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$
***************************************************************************/
#ifndef CURL_DISABLE_RTSP
extern const struct Curl_handler Curl_handler_rtsp;
/*
* Parse and write out any available RTP data.
*
* nread: amount of data left after k->str. will be modified if RTP
* data is parsed and k->str is moved up
* readmore: whether or not the RTP parser needs more data right away
*/
CURLcode Curl_rtsp_rtp_readwrite(struct SessionHandle *data,
struct connectdata *conn,
ssize_t *nread,
bool *readmore);
/* protocol-specific functions set up to be called by the main engine */
CURLcode Curl_rtsp(struct connectdata *conn, bool *done);
CURLcode Curl_rtsp_done(struct connectdata *conn, CURLcode, bool premature);
CURLcode Curl_rtsp_connect(struct connectdata *conn, bool *done);
CURLcode Curl_rtsp_disconnect(struct connectdata *conn);
CURLcode Curl_rtsp_parseheader(struct connectdata *conn, char *header);
#endif /* CURL_DISABLE_RTSP */
/*
* RTSP Connection data
*
* Currently, only used for tracking incomplete RTP data reads
*/
struct rtsp_conn {
char *rtp_buf;
ssize_t rtp_bufsize;
int rtp_channel;
};
/****************************************************************************
* RTSP unique setup
***************************************************************************/
struct RTSP {
/*
* http_wrapper MUST be the first element of this structure for the wrap
* logic to work. In this way, we get a cheap polymorphism because
* &(data->state.proto.rtsp) == &(data->state.proto.http) per the C spec
*
* HTTP functions can safely treat this as an HTTP struct, but RTSP aware
* functions can also index into the later elements.
*/
struct HTTP http_wrapper; /*wrap HTTP to do the heavy lifting */
long CSeq_sent; /* CSeq of this request */
long CSeq_recv; /* CSeq received */
};
#endif /* __RTSP_H_ */

View File

@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2009, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2010, 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
@@ -43,6 +43,7 @@
#include "sslgen.h"
#include "ssh.h"
#include "multiif.h"
#include "rtsp.h"
#define _MPRINTF_REPLACE /* use the internal *printf() functions */
#include <curl/mprintf.h>
@@ -209,7 +210,7 @@ CURLcode Curl_sendf(curl_socket_t sockfd, struct connectdata *conn,
write_len = strlen(s);
sptr = s;
while(1) {
for(;;) {
/* Write the buffer to the socket */
res = Curl_write(conn, sockfd, sptr, write_len, &bytes_written);
@@ -342,8 +343,8 @@ static CURLcode pausewrite(struct SessionHandle *data,
/* mark the connection as RECV paused */
k->keepon |= KEEP_RECV_PAUSE;
DEBUGF(infof(data, "Pausing with %d bytes in buffer for type %02x\n",
(int)len, type));
DEBUGF(infof(data, "Pausing with %zu bytes in buffer for type %02x\n",
len, type));
return CURLE_OK;
}
@@ -425,7 +426,7 @@ CURLcode Curl_client_write(struct connectdata *conn,
return pausewrite(data, type, ptr, len);
if(wrote != len) {
failf(data, "Failed writing body (%d != %d)", (int)wrote, (int)len);
failf(data, "Failed writing body (%zu != %zu)", wrote, len);
return CURLE_WRITE_ERROR;
}
}
@@ -510,7 +511,8 @@ int Curl_read(struct connectdata *conn, /* connection data */
/* If session can pipeline, check connection buffer */
if(pipelining) {
size_t bytestocopy = CURLMIN(conn->buf_len - conn->read_pos, sizerequested);
size_t bytestocopy = CURLMIN(conn->buf_len - conn->read_pos,
sizerequested);
/* Copy from our master buffer first if we have some unread data there*/
if(bytestocopy > 0) {
@@ -527,8 +529,9 @@ int Curl_read(struct connectdata *conn, /* connection data */
buffertofill = conn->master_buffer;
}
else {
bytesfromsocket = CURLMIN((long)sizerequested, conn->data->set.buffer_size ?
conn->data->set.buffer_size : BUFSIZE);
bytesfromsocket = CURLMIN((long)sizerequested,
conn->data->set.buffer_size ?
conn->data->set.buffer_size : BUFSIZE);
buffertofill = buf;
}

View File

@@ -1,5 +1,5 @@
#ifndef __SENDF_H
#define __SENDF_H
#ifndef HEADER_CURL_SENDF_H
#define HEADER_CURL_SENDF_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2008, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2010, 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
@@ -48,16 +48,13 @@ void Curl_failf(struct SessionHandle *, const char *fmt, ...);
#define failf Curl_failf
#define CLIENTWRITE_BODY 1
#define CLIENTWRITE_HEADER 2
#define CLIENTWRITE_BODY (1<<0)
#define CLIENTWRITE_HEADER (1<<1)
#define CLIENTWRITE_BOTH (CLIENTWRITE_BODY|CLIENTWRITE_HEADER)
CURLcode Curl_client_write(struct connectdata *conn, int type, char *ptr,
size_t len);
void Curl_read_rewind(struct connectdata *conn,
size_t extraBytesRead);
/* internal read-function, does plain socket only */
int Curl_read_plain(curl_socket_t sockfd,
char *buf,
@@ -86,4 +83,4 @@ int Curl_debug(struct SessionHandle *handle, curl_infotype type,
struct connectdata *conn);
#endif /* __SENDF_H */
#endif /* HEADER_CURL_SENDF_H */

View File

@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2009, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2010, 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
@@ -169,6 +169,15 @@
# define CURL_DISABLE_TELNET
# define CURL_DISABLE_DICT
# define CURL_DISABLE_FILE
# define CURL_DISABLE_RTSP
#endif
/*
* When http is disabled rtsp is not supported.
*/
#if defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_RTSP)
# define CURL_DISABLE_RTSP
#endif
/* ================================================================ */
@@ -326,7 +335,7 @@
*/
#ifndef SIZEOF_OFF_T
# if defined(__VMS) && (defined(__alpha) || defined(__ia64))
# if defined(__VMS) && !defined(__VAX)
# if defined(_LARGEFILE)
# define SIZEOF_OFF_T 8
# endif
@@ -398,23 +407,68 @@
#endif /* WIN32 */
#if defined(WIN32) && !defined(__CYGWIN__) && !defined(USE_ARES) && \
!defined(__LCC__) /* lcc-win32 doesn't have _beginthreadex() */
#ifdef ENABLE_IPV6
#define USE_THREADING_GETADDRINFO
#else
#define USE_THREADING_GETHOSTBYNAME /* Cygwin uses alarm() function */
#endif
/*
* msvc 6.0 requires PSDK in order to have INET6_ADDRSTRLEN
* defined in ws2tcpip.h as well as to provide IPv6 support.
*/
#if defined(_MSC_VER) && !defined(__POCC__)
# if !defined(HAVE_WS2TCPIP_H) || \
((_MSC_VER < 1300) && !defined(INET6_ADDRSTRLEN))
# undef HAVE_GETADDRINFO_THREADSAFE
# undef HAVE_FREEADDRINFO
# undef HAVE_GETADDRINFO
# undef HAVE_GETNAMEINFO
# undef ENABLE_IPV6
# endif
#endif
/* "cl -ML" or "cl -MLd" implies a single-threaded runtime library where
_beginthreadex() is not available */
#if (defined(_MSC_VER) && !defined(__POCC__)) && !defined(_MT) && !defined(USE_ARES)
#undef USE_THREADING_GETADDRINFO
#undef USE_THREADING_GETHOSTBYNAME
#define CURL_NO__BEGINTHREADEX
/* ---------------------------------------------------------------- */
/* resolver specialty compile-time defines */
/* CURLRES_* defines to use in the host*.c sources */
/* ---------------------------------------------------------------- */
/*
* lcc-win32 doesn't have _beginthreadex(), lacks threads support.
*/
#if defined(__LCC__) && defined(WIN32)
# undef USE_THREADS_POSIX
# undef USE_THREADS_WIN32
#endif
/*
* MSVC threads support requires a multi-threaded runtime library.
* _beginthreadex() is not available in single-threaded ones.
*/
#if defined(_MSC_VER) && !defined(__POCC__) && !defined(_MT)
# undef USE_THREADS_POSIX
# undef USE_THREADS_WIN32
#endif
/*
* Mutually exclusive CURLRES_* definitions.
*/
#ifdef USE_ARES
# define CURLRES_ASYNCH
# define CURLRES_ARES
#elif defined(USE_THREADS_POSIX) || defined(USE_THREADS_WIN32)
# define CURLRES_ASYNCH
# define CURLRES_THREADED
#else
# define CURLRES_SYNCH
#endif
#ifdef ENABLE_IPV6
# define CURLRES_IPV6
#else
# define CURLRES_IPV4
#endif
/* ---------------------------------------------------------------- */
/*
* When using WINSOCK, TELNET protocol requires WINSOCK2 API.
*/
@@ -435,20 +489,6 @@
# endif
#endif
/*
* msvc 6.0 requires PSDK in order to have INET6_ADDRSTRLEN
* defined in ws2tcpip.h as well as to provide IPv6 support.
*/
#if defined(_MSC_VER) && !defined(__POCC__)
# if !defined(HAVE_WS2TCPIP_H) || ((_MSC_VER < 1300) && !defined(INET6_ADDRSTRLEN))
# undef HAVE_FREEADDRINFO
# undef HAVE_GETADDRINFO
# undef HAVE_GETNAMEINFO
# undef ENABLE_IPV6
# endif
#endif
/*
* Intentionally fail to build when using msvc 6.0 without PSDK installed.
* The brave of heart can circumvent this, defining ALLOW_MSVC6_WITHOUT_PSDK

View File

@@ -422,7 +422,7 @@ typedef int sig_atomic_t;
* Actually use __32_getpwuid() on 64-bit VMS builds for getpwuid()
*/
#if defined(VMS) && \
#if defined(__VMS) && \
defined(__INITIAL_POINTER_SIZE) && (__INITIAL_POINTER_SIZE == 64)
#define getpwuid __32_getpwuid
#endif
@@ -432,7 +432,7 @@ typedef int sig_atomic_t;
* Macro argv_item_t hides platform details to code using it.
*/
#ifdef VMS
#ifdef __VMS
#define argv_item_t __char_ptr32
#else
#define argv_item_t char *

992
lib/smtp.c Normal file
View File

@@ -0,0 +1,992 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2010, 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.
*
* RFC2821 SMTP protocol
*
* $Id$
***************************************************************************/
#include "setup.h"
#ifndef CURL_DISABLE_SMTP
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
#include <ctype.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
#endif
#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
#ifdef HAVE_UTSNAME_H
#include <sys/utsname.h>
#endif
#ifdef HAVE_NETDB_H
#include <netdb.h>
#endif
#ifdef __VMS
#include <in.h>
#include <inet.h>
#endif
#if (defined(NETWARE) && defined(__NOVELL_LIBC__))
#undef in_addr_t
#define in_addr_t unsigned long
#endif
#include <curl/curl.h>
#include "urldata.h"
#include "sendf.h"
#include "easyif.h" /* for Curl_convert_... prototypes */
#include "if2ip.h"
#include "hostip.h"
#include "progress.h"
#include "transfer.h"
#include "escape.h"
#include "http.h" /* for HTTP proxy tunnel stuff */
#include "socks.h"
#include "smtp.h"
#include "strtoofft.h"
#include "strequal.h"
#include "sslgen.h"
#include "connect.h"
#include "strerror.h"
#include "select.h"
#include "multiif.h"
#include "url.h"
#include "rawstr.h"
#include "strtoofft.h"
#define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h>
#include "curl_memory.h"
/* The last #include file should be: */
#include "memdebug.h"
/* Local API functions */
static CURLcode smtp_regular_transfer(struct connectdata *conn, bool *done);
static CURLcode smtp_do(struct connectdata *conn, bool *done);
static CURLcode smtp_done(struct connectdata *conn,
CURLcode, bool premature);
static CURLcode smtp_connect(struct connectdata *conn, bool *done);
static CURLcode smtp_disconnect(struct connectdata *conn);
static CURLcode smtp_multi_statemach(struct connectdata *conn, bool *done);
static int smtp_getsock(struct connectdata *conn,
curl_socket_t *socks,
int numsocks);
static CURLcode smtp_doing(struct connectdata *conn,
bool *dophase_done);
static CURLcode smtp_setup_connection(struct connectdata * conn);
/*
* SMTP protocol handler.
*/
const struct Curl_handler Curl_handler_smtp = {
"SMTP", /* scheme */
smtp_setup_connection, /* setup_connection */
smtp_do, /* do_it */
smtp_done, /* done */
ZERO_NULL, /* do_more */
smtp_connect, /* connect_it */
smtp_multi_statemach, /* connecting */
smtp_doing, /* doing */
smtp_getsock, /* proto_getsock */
smtp_getsock, /* doing_getsock */
ZERO_NULL, /* perform_getsock */
smtp_disconnect, /* disconnect */
PORT_SMTP, /* defport */
PROT_SMTP /* protocol */
};
#ifdef USE_SSL
/*
* SMTPS protocol handler.
*/
const struct Curl_handler Curl_handler_smtps = {
"SMTPS", /* scheme */
smtp_setup_connection, /* setup_connection */
smtp_do, /* do_it */
smtp_done, /* done */
ZERO_NULL, /* do_more */
smtp_connect, /* connect_it */
smtp_multi_statemach, /* connecting */
smtp_doing, /* doing */
smtp_getsock, /* proto_getsock */
smtp_getsock, /* doing_getsock */
ZERO_NULL, /* perform_getsock */
smtp_disconnect, /* disconnect */
PORT_SMTPS, /* defport */
PROT_SMTP | PROT_SMTPS | PROT_SSL /* protocol */
};
#endif
#ifndef CURL_DISABLE_HTTP
/*
* HTTP-proxyed SMTP protocol handler.
*/
static const struct Curl_handler Curl_handler_smtp_proxy = {
"SMTP", /* scheme */
ZERO_NULL, /* setup_connection */
Curl_http, /* do_it */
Curl_http_done, /* done */
ZERO_NULL, /* do_more */
ZERO_NULL, /* connect_it */
ZERO_NULL, /* connecting */
ZERO_NULL, /* doing */
ZERO_NULL, /* proto_getsock */
ZERO_NULL, /* doing_getsock */
ZERO_NULL, /* perform_getsock */
ZERO_NULL, /* disconnect */
PORT_SMTP, /* defport */
PROT_HTTP /* protocol */
};
#ifdef USE_SSL
/*
* HTTP-proxyed SMTPS protocol handler.
*/
static const struct Curl_handler Curl_handler_smtps_proxy = {
"SMTPS", /* scheme */
ZERO_NULL, /* setup_connection */
Curl_http, /* do_it */
Curl_http_done, /* done */
ZERO_NULL, /* do_more */
ZERO_NULL, /* connect_it */
ZERO_NULL, /* connecting */
ZERO_NULL, /* doing */
ZERO_NULL, /* proto_getsock */
ZERO_NULL, /* doing_getsock */
ZERO_NULL, /* perform_getsock */
ZERO_NULL, /* disconnect */
PORT_SMTPS, /* defport */
PROT_HTTP /* protocol */
};
#endif
#endif
/* fucntion that checks for an ending smtp status code at the start of the
given string */
static int smtp_endofresp(struct pingpong *pp, int *resp)
{
char *line = pp->linestart_resp;
size_t len = pp->nread_resp;
if( (len >= 4) && (' ' == line[3]) &&
ISDIGIT(line[0]) && ISDIGIT(line[1]) && ISDIGIT(line[2])) {
*resp=atoi(line);
return TRUE;
}
return FALSE; /* nothing for us */
}
/* This is the ONLY way to change SMTP state! */
static void state(struct connectdata *conn,
smtpstate newstate)
{
#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
/* for debug purposes */
static const char * const names[]={
"STOP",
"SERVERGREET",
"EHLO",
"STARTTLS",
"MAIL",
"RCPT",
"DATA",
"QUIT",
/* LAST */
};
#endif
struct smtp_conn *smtpc = &conn->proto.smtpc;
#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
if(smtpc->state != newstate)
infof(conn->data, "SMTP %p state change from %s to %s\n",
smtpc, names[smtpc->state], names[newstate]);
#endif
smtpc->state = newstate;
}
static CURLcode smtp_state_ehlo(struct connectdata *conn)
{
CURLcode result;
struct smtp_conn *smtpc = &conn->proto.smtpc;
/* send EHLO */
result = Curl_pp_sendf(&conn->proto.smtpc.pp, "EHLO %s", smtpc->domain);
if(result)
return result;
state(conn, SMTP_EHLO);
return CURLE_OK;
}
/* For the SMTP "protocol connect" and "doing" phases only */
static int smtp_getsock(struct connectdata *conn,
curl_socket_t *socks,
int numsocks)
{
return Curl_pp_getsock(&conn->proto.smtpc.pp, socks, numsocks);
}
/* for STARTTLS responses */
static CURLcode smtp_state_starttls_resp(struct connectdata *conn,
int smtpcode,
smtpstate instate)
{
CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data;
(void)instate; /* no use for this yet */
if(smtpcode != 'O') {
failf(data, "STARTTLS denied. %c", smtpcode);
result = CURLE_LOGIN_DENIED;
}
else {
/* Curl_ssl_connect is BLOCKING */
result = Curl_ssl_connect(conn, FIRSTSOCKET);
if(CURLE_OK == result) {
conn->protocol |= PROT_SMTPS;
result = smtp_state_ehlo(conn);
}
}
state(conn, SMTP_STOP);
return result;
}
/* for EHLO responses */
static CURLcode smtp_state_ehlo_resp(struct connectdata *conn,
int smtpcode,
smtpstate instate)
{
CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data;
(void)instate; /* no use for this yet */
if(smtpcode/100 != 2) {
failf(data, "Access denied: %d", smtpcode);
result = CURLE_LOGIN_DENIED;
}
/* end the connect phase */
state(conn, SMTP_STOP);
return result;
}
/* start the DO phase */
static CURLcode smtp_mail(struct connectdata *conn)
{
CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data;
/* send MAIL */
result = Curl_pp_sendf(&conn->proto.smtpc.pp, "MAIL FROM:%s",
data->set.str[STRING_MAIL_FROM]);
if(result)
return result;
state(conn, SMTP_MAIL);
return result;
}
/* for MAIL responses */
static CURLcode smtp_state_mail_resp(struct connectdata *conn,
int smtpcode,
smtpstate instate)
{
CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data;
(void)instate; /* no use for this yet */
if(smtpcode/100 != 2) {
failf(data, "Access denied: %d", smtpcode);
result = CURLE_LOGIN_DENIED;
state(conn, SMTP_STOP);
}
else {
/* send RCPT TO */
struct curl_slist *rcpt;
char *buffer = NULL;
for(rcpt = data->set.mail_rcpt; rcpt; rcpt=rcpt->next) {
char *add = aprintf("%s%s%s", buffer?buffer:"", buffer?", ":"",
rcpt->data);
if(!add) {
free(buffer);
return CURLE_OUT_OF_MEMORY;
}
buffer = add;
}
result = Curl_pp_sendf(&conn->proto.smtpc.pp, "RCPT TO:%s", buffer);
free(buffer);
if(result)
return result;
state(conn, SMTP_RCPT);
}
return result;
}
/* for RCPT responses */
static CURLcode smtp_state_rcpt_resp(struct connectdata *conn,
int smtpcode,
smtpstate instate)
{
CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data;
(void)instate; /* no use for this yet */
if(smtpcode/100 != 2) {
failf(data, "Access denied: %d", smtpcode);
result = CURLE_LOGIN_DENIED;
state(conn, SMTP_STOP);
}
else {
/* send DATA */
result = Curl_pp_sendf(&conn->proto.smtpc.pp, "DATA", "");
if(result)
return result;
state(conn, SMTP_DATA);
}
return result;
}
/* for the DATA response */
static CURLcode smtp_state_data_resp(struct connectdata *conn,
int smtpcode,
smtpstate instate)
{
CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data;
struct FTP *smtp = data->state.proto.smtp;
(void)instate; /* no use for this yet */
if(smtpcode != 354) {
state(conn, SMTP_STOP);
return CURLE_RECV_ERROR;
}
/* SMTP upload */
result = Curl_setup_transfer(conn, -1, -1, FALSE, NULL, /* no download */
FIRSTSOCKET, smtp->bytecountp);
state(conn, SMTP_STOP);
return result;
}
static CURLcode smtp_statemach_act(struct connectdata *conn)
{
CURLcode result;
curl_socket_t sock = conn->sock[FIRSTSOCKET];
struct SessionHandle *data=conn->data;
int smtpcode;
struct smtp_conn *smtpc = &conn->proto.smtpc;
struct pingpong *pp = &smtpc->pp;
size_t nread = 0;
if(pp->sendleft)
/* we have a piece of a command still left to send */
return Curl_pp_flushsend(pp);
/* we read a piece of response */
result = Curl_pp_readresp(sock, pp, &smtpcode, &nread);
if(result)
return result;
if(smtpcode) {
/* we have now received a full SMTP server response */
switch(smtpc->state) {
case SMTP_SERVERGREET:
if(smtpcode/100 != 2) {
failf(data, "Got unexpected smtp-server response: %d", smtpcode);
return CURLE_FTP_WEIRD_SERVER_REPLY;
}
if(data->set.ftp_ssl && !conn->ssl[FIRSTSOCKET].use) {
/* We don't have a SSL/TLS connection yet, but SSL is requested. Switch
to TLS connection now */
result = Curl_pp_sendf(&smtpc->pp, "STARTTLS", NULL);
state(conn, SMTP_STARTTLS);
}
else
result = smtp_state_ehlo(conn);
if(result)
return result;
break;
case SMTP_EHLO:
result = smtp_state_ehlo_resp(conn, smtpcode, smtpc->state);
break;
case SMTP_MAIL:
result = smtp_state_mail_resp(conn, smtpcode, smtpc->state);
break;
case SMTP_RCPT:
result = smtp_state_rcpt_resp(conn, smtpcode, smtpc->state);
break;
case SMTP_STARTTLS:
result = smtp_state_starttls_resp(conn, smtpcode, smtpc->state);
break;
case SMTP_DATA:
result = smtp_state_data_resp(conn, smtpcode, smtpc->state);
break;
case SMTP_QUIT:
/* fallthrough, just stop! */
default:
/* internal error */
state(conn, SMTP_STOP);
break;
}
}
return result;
}
/* called repeatedly until done from multi.c */
static CURLcode smtp_multi_statemach(struct connectdata *conn,
bool *done)
{
struct smtp_conn *smtpc = &conn->proto.smtpc;
CURLcode result = Curl_pp_multi_statemach(&smtpc->pp);
*done = (bool)(smtpc->state == SMTP_STOP);
return result;
}
static CURLcode smtp_easy_statemach(struct connectdata *conn)
{
struct smtp_conn *smtpc = &conn->proto.smtpc;
struct pingpong *pp = &smtpc->pp;
CURLcode result = CURLE_OK;
while(smtpc->state != SMTP_STOP) {
result = Curl_pp_easy_statemach(pp);
if(result)
break;
}
return result;
}
/*
* Allocate and initialize the struct SMTP for the current SessionHandle. If
* need be.
*/
static CURLcode smtp_init(struct connectdata *conn)
{
struct SessionHandle *data = conn->data;
struct FTP *smtp = data->state.proto.smtp;
if(!smtp) {
smtp = data->state.proto.smtp = calloc(sizeof(struct FTP), 1);
if(!smtp)
return CURLE_OUT_OF_MEMORY;
}
/* get some initial data into the smtp struct */
smtp->bytecountp = &data->req.bytecount;
/* No need to duplicate user+password, the connectdata struct won't change
during a session, but we re-init them here since on subsequent inits
since the conn struct may have changed or been replaced.
*/
smtp->user = conn->user;
smtp->passwd = conn->passwd;
return CURLE_OK;
}
/*
* smtp_connect() should do everything that is to be considered a part of
* the connection phase.
*
* The variable 'done' points to will be TRUE if the protocol-layer connect
* phase is done when this function returns, or FALSE is not. When called as
* a part of the easy interface, it will always be TRUE.
*/
static CURLcode smtp_connect(struct connectdata *conn,
bool *done) /* see description above */
{
CURLcode result;
struct smtp_conn *smtpc = &conn->proto.smtpc;
struct SessionHandle *data=conn->data;
struct pingpong *pp=&smtpc->pp;
const char *path = conn->data->state.path;
int len;
*done = FALSE; /* default to not done yet */
/* If there already is a protocol-specific struct allocated for this
sessionhandle, deal with it */
Curl_reset_reqproto(conn);
result = smtp_init(conn);
if(CURLE_OK != result)
return result;
/* We always support persistant connections on smtp */
conn->bits.close = FALSE;
pp->response_time = RESP_TIMEOUT; /* set default response time-out */
pp->statemach_act = smtp_statemach_act;
pp->endofresp = smtp_endofresp;
pp->conn = conn;
#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_PROXY)
if(conn->bits.tunnel_proxy && conn->bits.httpproxy) {
/* for SMTP over HTTP proxy */
struct HTTP http_proxy;
struct FTP *smtp_save;
/* BLOCKING */
/* We want "seamless" SMTP operations through HTTP proxy tunnel */
/* Curl_proxyCONNECT is based on a pointer to a struct HTTP at the member
* conn->proto.http; we want SMTP through HTTP and we have to change the
* member temporarily for connecting to the HTTP proxy. After
* Curl_proxyCONNECT we have to set back the member to the original struct
* SMTP pointer
*/
smtp_save = data->state.proto.smtp;
memset(&http_proxy, 0, sizeof(http_proxy));
data->state.proto.http = &http_proxy;
result = Curl_proxyCONNECT(conn, FIRSTSOCKET,
conn->host.name, conn->remote_port);
data->state.proto.smtp = smtp_save;
if(CURLE_OK != result)
return result;
}
#endif /* !CURL_DISABLE_HTTP && !CURL_DISABLE_PROXY */
if(conn->protocol & PROT_SMTPS) {
/* BLOCKING */
/* SMTPS is simply smtp with SSL for the control channel */
/* now, perform the SSL initialization for this socket */
result = Curl_ssl_connect(conn, FIRSTSOCKET);
if(result)
return result;
}
Curl_pp_init(pp); /* init the response reader stuff */
pp->response_time = RESP_TIMEOUT; /* set default response time-out */
pp->statemach_act = smtp_statemach_act;
pp->endofresp = smtp_endofresp;
pp->conn = conn;
if(!*path)
path = "localhost";
/* url decode the path and use it as domain with EHLO */
smtpc->domain = curl_easy_unescape(conn->data, path, 0, &len);
/* When we connect, we start in the state where we await the server greeting
*/
state(conn, SMTP_SERVERGREET);
if(data->state.used_interface == Curl_if_multi)
result = smtp_multi_statemach(conn, done);
else {
result = smtp_easy_statemach(conn);
if(!result)
*done = TRUE;
}
return result;
}
/***********************************************************************
*
* smtp_done()
*
* The DONE function. This does what needs to be done after a single DO has
* performed.
*
* Input argument is already checked for validity.
*/
static CURLcode smtp_done(struct connectdata *conn, CURLcode status,
bool premature)
{
struct SessionHandle *data = conn->data;
struct FTP *smtp = data->state.proto.smtp;
CURLcode result=CURLE_OK;
ssize_t bytes_written;
(void)premature;
if(!smtp)
/* When the easy handle is removed from the multi while libcurl is still
* trying to resolve the host name, it seems that the smtp struct is not
* yet initialized, but the removal action calls Curl_done() which calls
* this function. So we simply return success if no smtp pointer is set.
*/
return CURLE_OK;
if(status) {
conn->bits.close = TRUE; /* marked for closure */
result = status; /* use the already set error code */
}
else
/* TODO: make this work even when the socket is EWOULDBLOCK in this call! */
/* write to socket (send away data) */
result = Curl_write(conn,
conn->writesockfd, /* socket to send to */
SMTP_EOB, /* buffer pointer */
SMTP_EOB_LEN, /* buffer size */
&bytes_written); /* actually sent away */
/* clear these for next connection */
smtp->transfer = FTPTRANSFER_BODY;
return result;
}
/***********************************************************************
*
* smtp_perform()
*
* This is the actual DO function for SMTP. Get a file/directory according to
* the options previously setup.
*/
static
CURLcode smtp_perform(struct connectdata *conn,
bool *connected, /* connect status after PASV / PORT */
bool *dophase_done)
{
/* this is SMTP and no proxy */
CURLcode result=CURLE_OK;
DEBUGF(infof(conn->data, "DO phase starts\n"));
if(conn->data->set.opt_no_body) {
/* requested no body means no transfer... */
struct FTP *smtp = conn->data->state.proto.smtp;
smtp->transfer = FTPTRANSFER_INFO;
}
*dophase_done = FALSE; /* not done yet */
/* start the first command in the DO phase */
result = smtp_mail(conn);
if(result)
return result;
/* run the state-machine */
if(conn->data->state.used_interface == Curl_if_multi)
result = smtp_multi_statemach(conn, dophase_done);
else {
result = smtp_easy_statemach(conn);
*dophase_done = TRUE; /* with the easy interface we are done here */
}
*connected = conn->bits.tcpconnect;
if(*dophase_done)
DEBUGF(infof(conn->data, "DO phase is complete\n"));
return result;
}
/***********************************************************************
*
* smtp_do()
*
* This function is registered as 'curl_do' function. It decodes the path
* parts etc as a wrapper to the actual DO function (smtp_perform).
*
* The input argument is already checked for validity.
*/
static CURLcode smtp_do(struct connectdata *conn, bool *done)
{
CURLcode retcode = CURLE_OK;
*done = FALSE; /* default to false */
/*
Since connections can be re-used between SessionHandles, this might be a
connection already existing but on a fresh SessionHandle struct so we must
make sure we have a good 'struct SMTP' to play with. For new connections,
the struct SMTP is allocated and setup in the smtp_connect() function.
*/
Curl_reset_reqproto(conn);
retcode = smtp_init(conn);
if(retcode)
return retcode;
retcode = smtp_regular_transfer(conn, done);
return retcode;
}
/***********************************************************************
*
* smtp_quit()
*
* This should be called before calling sclose(). We should then wait for the
* response from the server before returning. The calling code should then try
* to close the connection.
*
*/
static CURLcode smtp_quit(struct connectdata *conn)
{
CURLcode result = CURLE_OK;
result = Curl_pp_sendf(&conn->proto.smtpc.pp, "QUIT", NULL);
if(result)
return result;
state(conn, SMTP_QUIT);
result = smtp_easy_statemach(conn);
return result;
}
/***********************************************************************
*
* smtp_disconnect()
*
* Disconnect from an SMTP server. Cleanup protocol-specific per-connection
* resources. BLOCKING.
*/
static CURLcode smtp_disconnect(struct connectdata *conn)
{
struct smtp_conn *smtpc= &conn->proto.smtpc;
/* We cannot send quit unconditionally. If this connection is stale or
bad in any way, sending quit and waiting around here will make the
disconnect wait in vain and cause more problems than we need to.
*/
/* The SMTP session may or may not have been allocated/setup at this
point! */
(void)smtp_quit(conn); /* ignore errors on the LOGOUT */
Curl_pp_disconnect(&smtpc->pp);
return CURLE_OK;
}
/* call this when the DO phase has completed */
static CURLcode smtp_dophase_done(struct connectdata *conn,
bool connected)
{
CURLcode result = CURLE_OK;
struct FTP *smtp = conn->data->state.proto.smtp;
struct smtp_conn *smtpc= &conn->proto.smtpc;
(void)connected;
if(smtp->transfer != FTPTRANSFER_BODY)
/* no data to transfer */
result=Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
free(smtpc->domain);
return result;
}
/* called from multi.c while DOing */
static CURLcode smtp_doing(struct connectdata *conn,
bool *dophase_done)
{
CURLcode result;
result = smtp_multi_statemach(conn, dophase_done);
if(*dophase_done) {
result = smtp_dophase_done(conn, FALSE /* not connected */);
DEBUGF(infof(conn->data, "DO phase is complete\n"));
}
return result;
}
/***********************************************************************
*
* smtp_regular_transfer()
*
* The input argument is already checked for validity.
*
* Performs all commands done before a regular transfer between a local and a
* remote host.
*/
static
CURLcode smtp_regular_transfer(struct connectdata *conn,
bool *dophase_done)
{
CURLcode result=CURLE_OK;
bool connected=FALSE;
struct SessionHandle *data = conn->data;
data->req.size = -1; /* make sure this is unknown at this point */
Curl_pgrsSetUploadCounter(data, 0);
Curl_pgrsSetDownloadCounter(data, 0);
Curl_pgrsSetUploadSize(data, 0);
Curl_pgrsSetDownloadSize(data, 0);
result = smtp_perform(conn,
&connected, /* have we connected after PASV/PORT */
dophase_done); /* all commands in the DO-phase done? */
if(CURLE_OK == result) {
if(!*dophase_done)
/* the DO phase has not completed yet */
return CURLE_OK;
result = smtp_dophase_done(conn, connected);
if(result)
return result;
}
return result;
}
static CURLcode smtp_setup_connection(struct connectdata * conn)
{
struct SessionHandle *data = conn->data;
if(conn->bits.httpproxy && !data->set.tunnel_thru_httpproxy) {
/* Unless we have asked to tunnel smtp operations through the proxy, we
switch and use HTTP operations only */
#ifndef CURL_DISABLE_HTTP
if(conn->handler == &Curl_handler_smtp)
conn->handler = &Curl_handler_smtp_proxy;
else {
#ifdef USE_SSL
conn->handler = &Curl_handler_smtps_proxy;
#else
failf(data, "SMTPS not supported!");
return CURLE_UNSUPPORTED_PROTOCOL;
#endif
}
/*
* We explicitly mark this connection as persistent here as we're doing
* SMTP over HTTP and thus we accidentally avoid setting this value
* otherwise.
*/
conn->bits.close = FALSE;
#else
failf(data, "SMTP over http proxy requires HTTP support built-in!");
return CURLE_UNSUPPORTED_PROTOCOL;
#endif
}
data->state.path++; /* don't include the initial slash */
return CURLE_OK;
}
CURLcode Curl_smtp_escape_eob(struct connectdata *conn, int nread)
{
/* When sending SMTP payload, we must detect CRLF.CRLF sequences in
* the data and make sure it is sent as CRLF..CRLF instead, as
* otherwise it will wrongly be detected as end of data by the server.
*/
int i;
int si;
struct smtp_conn *smtpc = &conn->proto.smtpc;
struct SessionHandle *data = conn->data;
if(data->state.scratch == NULL)
data->state.scratch = malloc(2*BUFSIZE);
if(data->state.scratch == NULL) {
failf (data, "Failed to alloc scratch buffer!");
return CURLE_OUT_OF_MEMORY;
}
/* This loop can be improved by some kind of Boyer-Moore style of
approach but that is saved for later... */
for(i = 0, si = 0; i < nread; i++, si++) {
int left = nread - i;
if(left>= (SMTP_EOB_LEN-smtpc->eob)) {
if(!memcmp(SMTP_EOB+smtpc->eob, &data->req.upload_fromhere[i],
SMTP_EOB_LEN-smtpc->eob)) {
/* It matched, copy the replacement data to the target buffer
instead. Note that the replacement does not contain the
trailing CRLF but we instead continue to match on that one
to deal with repeated sequences. Like CRLF.CRLF.CRLF etc
*/
memcpy(&data->state.scratch[si], SMTP_EOB_REPL,
SMTP_EOB_REPL_LEN);
si+=SMTP_EOB_REPL_LEN-1; /* minus one since the for() increments
it */
i+=SMTP_EOB_LEN-smtpc->eob-1-2;
smtpc->eob = 0; /* start over */
continue;
}
}
else if(!memcmp(SMTP_EOB+smtpc->eob, &data->req.upload_fromhere[i],
left)) {
/* the last piece of the data matches the EOB so we can't send that
until we know the rest of it */
smtpc->eob += left;
break;
}
data->state.scratch[si] = data->req.upload_fromhere[i];
} /* for() */
if(si != nread) {
/* only use the new buffer if we replaced something */
nread = si;
/* upload from the new (replaced) buffer instead */
data->req.upload_fromhere = data->state.scratch;
/* set the new amount too */
data->req.upload_present = nread;
}
return CURLE_OK;
}
#endif /* CURL_DISABLE_SMTP */

67
lib/smtp.h Normal file
View File

@@ -0,0 +1,67 @@
#ifndef __SMTP_H
#define __SMTP_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 2009, 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$
***************************************************************************/
#include "pingpong.h"
/****************************************************************************
* SMTP unique setup
***************************************************************************/
typedef enum {
SMTP_STOP, /* do nothing state, stops the state machine */
SMTP_SERVERGREET, /* waiting for the initial greeting immediately after
a connect */
SMTP_EHLO,
SMTP_STARTTLS,
SMTP_MAIL, /* MAIL FROM */
SMTP_RCPT, /* RCPT TO */
SMTP_DATA,
SMTP_QUIT,
SMTP_LAST /* never used */
} smtpstate;
/* smtp_conn is used for struct connection-oriented data in the connectdata
struct */
struct smtp_conn {
struct pingpong pp;
char *domain; /* what to send in the EHLO */
int eob; /* number of bytes of the EOB (End Of Body) that has been
received thus far */
smtpstate state; /* always use smtp.c:state() to change state! */
};
extern const struct Curl_handler Curl_handler_smtp;
extern const struct Curl_handler Curl_handler_smtps;
/* this is the 5-bytes End-Of-Body marker for SMTP */
#define SMTP_EOB "\x0d\x0a\x2e\x0d\x0a"
#define SMTP_EOB_LEN 5
/* if found in data, replace it with this string instead */
#define SMTP_EOB_REPL "\x0d\x0a\x2e\x2e"
#define SMTP_EOB_REPL_LEN 4
CURLcode Curl_smtp_escape_eob(struct connectdata *conn, int nread);
#endif /* __SMTP_H */

View File

@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2009, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2010, 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
@@ -72,7 +72,7 @@ int Curl_blockread_all(struct connectdata *conn, /* connection data */
struct timeval tvnow;
long conntime;
*n = 0;
do {
for(;;) {
tvnow = Curl_tvnow();
/* calculating how long connection is establishing */
conntime = Curl_tvdiff(tvnow, conn->created);
@@ -104,7 +104,7 @@ int Curl_blockread_all(struct connectdata *conn, /* connection data */
buffersize -= nread;
buf += nread;
allread += nread;
} while(1);
}
return result;
}
@@ -393,7 +393,7 @@ CURLcode Curl_SOCKS5(const char *proxy_name,
if(!socks5_resolve_local && hostname_len > 255)
{
infof(conn->data,"SOCKS5: server resolving disabled for hostnames of "
"length > 255 [actual len=%d]\n", hostname_len);
"length > 255 [actual len=%zu]\n", hostname_len);
socks5_resolve_local = TRUE;
}

View File

@@ -49,6 +49,7 @@ static gss_ctx_id_t gss_context = GSS_C_NO_CONTEXT;
#define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h>
#include "curl_memory.h"
/* The last #include file should be: */
#include "memdebug.h"

View File

@@ -42,6 +42,7 @@
#define _MPRINTF_REPLACE /* use the internal *printf() functions */
#include <curl/mprintf.h>
#include "curl_memory.h"
/* The last #include file should be: */
#include "memdebug.h"

View File

@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2006, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2010, 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
@@ -54,7 +54,7 @@ CURLcode Curl_speedcheck(struct SessionHandle *data,
/* we have been this slow for long enough, now die */
failf(data,
"Operation too slow. "
"Less than %d bytes/sec transfered the last %d seconds",
"Less than %ld bytes/sec transfered the last %ld seconds",
data->set.low_speed_limit,
data->set.low_speed_time);
return CURLE_OPERATION_TIMEDOUT;

3306
lib/ssh.c

File diff suppressed because it is too large Load Diff

122
lib/ssh.h
View File

@@ -23,6 +23,128 @@
* $Id$
***************************************************************************/
#include "setup.h"
#ifdef HAVE_LIBSSH2_H
#include <libssh2.h>
#include <libssh2_sftp.h>
#endif /* HAVE_LIBSSH2_H */
/****************************************************************************
* SSH unique setup
***************************************************************************/
typedef enum {
SSH_NO_STATE = -1, /* Used for "nextState" so say there is none */
SSH_STOP = 0, /* do nothing state, stops the state machine */
SSH_S_STARTUP, /* Session startup, First state in SSH-CONNECT */
SSH_HOSTKEY, /* verify hostkey */
SSH_AUTHLIST,
SSH_AUTH_PKEY_INIT,
SSH_AUTH_PKEY,
SSH_AUTH_PASS_INIT,
SSH_AUTH_PASS,
SSH_AUTH_HOST_INIT,
SSH_AUTH_HOST,
SSH_AUTH_KEY_INIT,
SSH_AUTH_KEY,
SSH_AUTH_DONE,
SSH_SFTP_INIT,
SSH_SFTP_REALPATH, /* Last state in SSH-CONNECT */
SSH_SFTP_QUOTE_INIT, /* First state in SFTP-DO */
SSH_SFTP_POSTQUOTE_INIT, /* (Possibly) First state in SFTP-DONE */
SSH_SFTP_QUOTE,
SSH_SFTP_NEXT_QUOTE,
SSH_SFTP_QUOTE_STAT,
SSH_SFTP_QUOTE_SETSTAT,
SSH_SFTP_QUOTE_SYMLINK,
SSH_SFTP_QUOTE_MKDIR,
SSH_SFTP_QUOTE_RENAME,
SSH_SFTP_QUOTE_RMDIR,
SSH_SFTP_QUOTE_UNLINK,
SSH_SFTP_TRANS_INIT,
SSH_SFTP_UPLOAD_INIT,
SSH_SFTP_CREATE_DIRS_INIT,
SSH_SFTP_CREATE_DIRS,
SSH_SFTP_CREATE_DIRS_MKDIR,
SSH_SFTP_READDIR_INIT,
SSH_SFTP_READDIR,
SSH_SFTP_READDIR_LINK,
SSH_SFTP_READDIR_BOTTOM,
SSH_SFTP_READDIR_DONE,
SSH_SFTP_DOWNLOAD_INIT,
SSH_SFTP_DOWNLOAD_STAT, /* Last state in SFTP-DO */
SSH_SFTP_CLOSE, /* Last state in SFTP-DONE */
SSH_SFTP_SHUTDOWN, /* First state in SFTP-DISCONNECT */
SSH_SCP_TRANS_INIT, /* First state in SCP-DO */
SSH_SCP_UPLOAD_INIT,
SSH_SCP_DOWNLOAD_INIT,
SSH_SCP_DONE,
SSH_SCP_SEND_EOF,
SSH_SCP_WAIT_EOF,
SSH_SCP_WAIT_CLOSE,
SSH_SCP_CHANNEL_FREE, /* Last state in SCP-DONE */
SSH_SESSION_DISCONNECT, /* First state in SCP-DISCONNECT */
SSH_SESSION_FREE, /* Last state in SCP/SFTP-DISCONNECT */
SSH_QUIT,
SSH_LAST /* never used */
} sshstate;
/* this struct is used in the HandleData struct which is part of the
SessionHandle, which means this is used on a per-easy handle basis.
Everything that is strictly related to a connection is banned from this
struct. */
struct SSHPROTO {
char *path; /* the path we operate on */
};
/* ssh_conn is used for struct connection-oriented data in the connectdata
struct */
struct ssh_conn {
const char *authlist; /* List of auth. methods, managed by libssh2 */
#ifdef USE_LIBSSH2
const char *passphrase; /* pass-phrase to use */
char *rsa_pub; /* path name */
char *rsa; /* path name */
bool authed; /* the connection has been authenticated fine */
sshstate state; /* always use ssh.c:state() to change state! */
sshstate nextstate; /* the state to goto after stopping */
CURLcode actualcode; /* the actual error code */
struct curl_slist *quote_item; /* for the quote option */
char *quote_path1; /* two generic pointers for the QUOTE stuff */
char *quote_path2;
LIBSSH2_SFTP_ATTRIBUTES quote_attrs; /* used by the SFTP_QUOTE state */
char *homedir; /* when doing SFTP we figure out home dir in the
connect phase */
/* Here's a set of struct members used by the SFTP_READDIR state */
LIBSSH2_SFTP_ATTRIBUTES readdir_attrs;
char *readdir_filename;
char *readdir_longentry;
int readdir_len, readdir_totalLen, readdir_currLen;
char *readdir_line;
char *readdir_linkPath;
/* end of READDIR stuff */
int secondCreateDirs; /* counter use by the code to see if the
second attempt has been made to change
to/create a directory */
char *slash_pos; /* used by the SFTP_CREATE_DIRS state */
LIBSSH2_SESSION *ssh_session; /* Secure Shell session */
LIBSSH2_CHANNEL *ssh_channel; /* Secure Shell channel handle */
LIBSSH2_SFTP *sftp_session; /* SFTP handle */
LIBSSH2_SFTP_HANDLE *sftp_handle;
int orig_waitfor; /* default READ/WRITE bits wait for */
/* note that HAVE_LIBSSH2_KNOWNHOST_API is a define set in the libssh2.h
header */
#ifdef HAVE_LIBSSH2_KNOWNHOST_API
LIBSSH2_KNOWNHOSTS *kh;
#endif
#endif /* USE_LIBSSH2 */
};
#ifdef USE_LIBSSH2
#if !defined(LIBSSH2_VERSION_NUM) || (LIBSSH2_VERSION_NUM < 0x001000)

View File

@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2009, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2010, 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
@@ -483,8 +483,7 @@ int cert_stuff(struct connectdata *conn,
return 0;
}
if (!SSL_CTX_add_client_CA(ctx, sk_X509_value(ca, i))) {
failf(data, "cannot add certificate to client CA list",
cert_file);
failf(data, "cannot add certificate to client CA list");
EVP_PKEY_free(pri);
X509_free(x509);
return 0;
@@ -595,14 +594,14 @@ int cert_stuff(struct connectdata *conn,
* the SSL context */
if(!SSL_CTX_check_private_key(ctx)) {
failf(data, "Private key does not match the certificate public key");
return(0);
return 0;
}
#ifndef HAVE_USERDATA_IN_PWD_CALLBACK
/* erase it now */
memset(global_passwd, 0, sizeof(global_passwd));
#endif
}
return(1);
return 1;
}
/* returns non-zero on failure */
@@ -659,7 +658,7 @@ static char *SSL_strerror(unsigned long error, char *buf, size_t size)
(void) size;
ERR_error_string(error, buf);
#endif
return (buf);
return buf;
}
#endif /* USE_SSLEAY */
@@ -709,7 +708,7 @@ void Curl_ossl_cleanup(void)
/* EVP_cleanup() removes all ciphers and digests from the table. */
EVP_cleanup();
#ifdef HAVE_ENGINE_cleanup
#ifdef HAVE_ENGINE_CLEANUP
ENGINE_cleanup();
#endif
@@ -748,11 +747,22 @@ int Curl_ossl_check_cxn(struct connectdata *conn)
CURLcode Curl_ossl_set_engine(struct SessionHandle *data, const char *engine)
{
#if defined(USE_SSLEAY) && defined(HAVE_OPENSSL_ENGINE_H)
ENGINE *e = ENGINE_by_id(engine);
ENGINE *e;
#if OPENSSL_VERSION_NUMBER >= 0x00909000L
e = ENGINE_by_id(engine);
#else
/* avoid memory leak */
for(e = ENGINE_get_first(); e; e = ENGINE_get_next(e)) {
const char *e_id = ENGINE_get_id(e);
if(!strcmp(engine, e_id))
break;
}
#endif
if(!e) {
failf(data, "SSL Engine '%s' not found", engine);
return (CURLE_SSL_ENGINE_NOTFOUND);
return CURLE_SSL_ENGINE_NOTFOUND;
}
if(data->state.engine) {
@@ -766,14 +776,14 @@ CURLcode Curl_ossl_set_engine(struct SessionHandle *data, const char *engine)
ENGINE_free(e);
failf(data, "Failed to initialise SSL Engine '%s':\n%s",
engine, SSL_strerror(ERR_get_error(), buf, sizeof(buf)));
return (CURLE_SSL_ENGINE_INITFAILED);
return CURLE_SSL_ENGINE_INITFAILED;
}
data->state.engine = e;
return (CURLE_OK);
return CURLE_OK;
#else
(void)engine;
failf(data, "SSL Engine not supported");
return (CURLE_SSL_ENGINE_NOTFOUND);
return CURLE_SSL_ENGINE_NOTFOUND;
#endif
}
@@ -818,7 +828,7 @@ struct curl_slist *Curl_ossl_engines_list(struct SessionHandle *data)
}
#endif
(void) data;
return (list);
return list;
}
@@ -1365,7 +1375,7 @@ static void ssl_tls_trace(int direction, int ssl_ver, int content_type,
int ver, msg_type, txt_len;
if(!conn || !conn->data || !conn->data->set.fdebug ||
(direction != 0 && direction != 1))
(direction != 0 && direction != 1))
return;
data = conn->data;
@@ -1470,7 +1480,7 @@ ossl_connect_step1(struct connectdata *conn,
infof(data, "SSL: couldn't set callback!\n");
}
else if(!SSL_CTX_ctrl(connssl->ctx, SSL_CTRL_SET_MSG_CALLBACK_ARG, 0,
conn)) {
conn)) {
infof(data, "SSL: couldn't set callback argument!\n");
}
}
@@ -1735,7 +1745,7 @@ ossl_connect_step2(struct connectdata *conn, int sockindex)
* the SO_ERROR is also lost.
*/
if(CURLE_SSL_CONNECT_ERROR == rc && errdetail == 0) {
failf(data, "Unknown SSL protocol error in connection to %s:%d ",
failf(data, "Unknown SSL protocol error in connection to %s:%ld ",
conn->host.name, conn->port);
return rc;
}
@@ -2315,7 +2325,15 @@ ossl_connect_step3(struct connectdata *conn,
return retcode;
}
}
#ifdef HAVE_SSL_GET1_SESSION
else {
/* Session was incache, so refcount already incremented earlier.
* Avoid further increments with each SSL_get1_session() call.
* This does not free the session as refcount remains > 0
*/
SSL_SESSION_free(our_ssl_sessionid);
}
#endif
/*
* We check certificates to authenticate the server; otherwise we risk

View File

@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 2004 - 2009, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 2004 - 2010, 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
@@ -81,6 +81,9 @@ curl_easy_strerror(CURLcode error)
case CURLE_REMOTE_ACCESS_DENIED:
return "Access denied to remote resource";
case CURLE_FTP_PRET_FAILED:
return "FTP: The server did not accept the PRET command.";
case CURLE_FTP_WEIRD_PASS_REPLY:
return "FTP: unknown PASS reply";
@@ -267,6 +270,12 @@ curl_easy_strerror(CURLcode error)
case CURLE_AGAIN:
return "Socket not ready for send/recv";
case CURLE_RTSP_CSEQ_ERROR:
return "RTSP CSeq mismatch or invalid CSeq";
case CURLE_RTSP_SESSION_ERROR:
return "RTSP session error";
/* error codes not used by current libcurl */
case CURLE_OBSOLETE4:
case CURLE_OBSOLETE10:

View File

@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2009, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2010, 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
@@ -729,7 +729,7 @@ static void printsub(struct SessionHandle *data,
else if(CURL_TELCMD_OK(i))
infof(data, "%s ", CURL_TELCMD(i));
else
infof(data, "%d ", i);
infof(data, "%u ", i);
if(CURL_TELOPT_OK(j))
infof(data, "%s", CURL_TELOPT(j));
else if(CURL_TELCMD_OK(j))
@@ -1325,7 +1325,7 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done)
switch(waitret) {
case WAIT_TIMEOUT:
{
while(1) {
for(;;) {
if(!PeekNamedPipe(stdin_handle, NULL, 0, NULL, &readfile_read, NULL)) {
keepon = FALSE;
code = CURLE_READ_ERROR;

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