aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Stenberg <daniel@haxx.se>2006-02-11 22:35:16 +0000
committerDaniel Stenberg <daniel@haxx.se>2006-02-11 22:35:16 +0000
commit87bcb6f3775a437579c7526d0972c714c2e5d31d (patch)
treee3b1729ce92ff0ab994b7e904f0bca5bd018a060
parentb0bc2f00d2ef005b6322123799af78528f66b713 (diff)
Karl M added the CURLOPT_CONNECT_ONLY and CURLINFO_LASTSOCKET options that
an app can use to let libcurl only connect to a remote host and then extract the socket from libcurl. libcurl will then not attempt to do any transfer at all after the connect is done.
-rw-r--r--CHANGES5
-rw-r--r--RELEASE-NOTES15
-rw-r--r--docs/libcurl/curl_easy_getinfo.36
-rw-r--r--docs/libcurl/curl_easy_setopt.38
-rw-r--r--include/curl/curl.h7
-rw-r--r--lib/easy.c2
-rw-r--r--lib/ftp.c4
-rw-r--r--lib/getinfo.c10
-rw-r--r--lib/http.c2
-rw-r--r--lib/multi.c67
-rw-r--r--lib/transfer.c6
-rw-r--r--lib/url.c25
-rw-r--r--lib/urldata.h2
13 files changed, 115 insertions, 44 deletions
diff --git a/CHANGES b/CHANGES
index 88961d32d..826b02100 100644
--- a/CHANGES
+++ b/CHANGES
@@ -7,6 +7,11 @@
Changelog
Daniel (11 February 2006)
+- Karl M added the CURLOPT_CONNECT_ONLY and CURLINFO_LASTSOCKET options that
+ an app can use to let libcurl only connect to a remote host and then extract
+ the socket from libcurl. libcurl will then not attempt to do any transfer at
+ all after the connect is done.
+
- Kent Boortz improved the configure check for GnuTLS to properly set LIBS
instead of LDFLAGS.
diff --git a/RELEASE-NOTES b/RELEASE-NOTES
index d7babaab2..5cd89a464 100644
--- a/RELEASE-NOTES
+++ b/RELEASE-NOTES
@@ -2,21 +2,22 @@ Curl and libcurl 7.15.2
Public curl release number: 92
Releases counted from the very beginning: 119
- Available command line options: 109
- Available curl_easy_setopt() options: 125
+ Available command line options: 111
+ Available curl_easy_setopt() options: 129
Number of public functions in libcurl: 46
- Amount of public web site mirrors: 30
+ Amount of public web site mirrors: 31
Number of known libcurl bindings: 32
Number of contributors: 474
This release includes the following changes:
+ o CURLOPT_CONNECT_ONLY and CURLINFO_LASTSOCKET added
o CURLOPT_LOCALPORT and CURLOPT_LOCALPORTRANGE (--local-port) added
o Dropped support for the LPRT ftp command
- o Gopher is now officially abandoned as a protocol (lib)curl tries to support.
+ o Gopher is now officially abandoned as a protocol (lib)curl tries to support
o curl_global_init() and curl_global_cleanup() are now using a refcount so
that it is now legal to call them multiple times. See updated info for
- details.
+ details
This release includes the following bugfixes:
@@ -60,7 +61,7 @@ advice from friends like these:
Dov Murik, Jean Jacques Drouin, Andres Garcia, Yang Tse, Gisle Vanem, Dan
Fandrich, Alexander Lazic, Michael Jahn, Andrew Benham, Bryan Henderson,
- David Shaw, Jon Turner, Duane Cathey, Michal Marek, Philippe Vaucher,
- Kent Boortz
+ David Shaw, Jon Turner, Duane Cathey, Michal Marek, Philippe Vaucher, Kent
+ Boortz, Karl M
Thanks! (and sorry if I forgot to mention someone)
diff --git a/docs/libcurl/curl_easy_getinfo.3 b/docs/libcurl/curl_easy_getinfo.3
index bc4f2063b..2119ea211 100644
--- a/docs/libcurl/curl_easy_getinfo.3
+++ b/docs/libcurl/curl_easy_getinfo.3
@@ -141,6 +141,12 @@ cookies cURL knows (expired ones, too). Don't forget to
cookies (cookies for the handle have not been enabled or simply none have been
received) 'struct curl_slist *' will be set to point to NULL. (Added in
7.14.1)
+.IP CURLINFO_LASTSOCKET
+Pass a pointer to a long to receive the last socket used by this curl
+session. If the socket is no longer valid, -1 is returned. When you finish
+working with the socket, you must call curl_easy_cleanup() as usual and let
+libcurl close the socket and cleanup other resources associated with the
+handle. (Added in 7.15.2)
.SH TIMES
.NF
An overview of the six time values available from curl_easy_getinfo()
diff --git a/docs/libcurl/curl_easy_setopt.3 b/docs/libcurl/curl_easy_setopt.3
index 25e7e7707..8a152947c 100644
--- a/docs/libcurl/curl_easy_setopt.3
+++ b/docs/libcurl/curl_easy_setopt.3
@@ -1044,6 +1044,14 @@ Resolve to ipv4 addresses.
.IP CURL_IPRESOLVE_V6
Resolve to ipv6 addresses.
.RE
+.SH CURLOPT_CONNECT_ONLY
+Pass a long. A non-zero parameter tells the library to perform any required
+proxy authentication and connection setup, but no data transfer.
+
+This option is useful with the \fICURLINFO_LASTSOCKET\fP option to
+\fIcurl_easy_getinfo(3)\fP. The library can set up the connection and then the
+application can obtain the most recently used socket for special data
+transfers. (Added in 7.15.2)
.SH SSL and SECURITY OPTIONS
.IP CURLOPT_SSLCERT
Pass a pointer to a zero terminated string as parameter. The string should be
diff --git a/include/curl/curl.h b/include/curl/curl.h
index 95c478a07..1ad282df8 100644
--- a/include/curl/curl.h
+++ b/include/curl/curl.h
@@ -923,6 +923,10 @@ typedef enum {
*/
CINIT(LOCALPORTRANGE, LONG, 140),
+ /* no transfer, set up connection and let application use the socket by
+ extracting it with CURLINFO_LASTSOCKET */
+ CINIT(CONNECT_ONLY, LONG, 141),
+
CURLOPT_LASTENTRY /* the last unused */
} CURLoption;
@@ -1277,9 +1281,10 @@ typedef enum {
CURLINFO_NUM_CONNECTS = CURLINFO_LONG + 26,
CURLINFO_SSL_ENGINES = CURLINFO_SLIST + 27,
CURLINFO_COOKIELIST = CURLINFO_SLIST + 28,
+ CURLINFO_LASTSOCKET = CURLINFO_LONG + 29,
/* Fill in new entries below here! */
- CURLINFO_LASTONE = 28
+ CURLINFO_LASTONE = 29
} CURLINFO;
/* CURLINFO_RESPONSE_CODE is the new name for the option previously known as
diff --git a/lib/easy.c b/lib/easy.c
index 2de18037f..d86b755fb 100644
--- a/lib/easy.c
+++ b/lib/easy.c
@@ -527,6 +527,8 @@ CURL *curl_easy_duphandle(CURL *incurl)
memset(outcurl->state.connects, 0,
sizeof(struct connectdata *)*outcurl->state.numconnects);
+ outcurl->state.lastconnect = -1;
+
outcurl->progress.flags = data->progress.flags;
outcurl->progress.callback = data->progress.callback;
diff --git a/lib/ftp.c b/lib/ftp.c
index ecb717696..02732f452 100644
--- a/lib/ftp.c
+++ b/lib/ftp.c
@@ -1689,7 +1689,7 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
ftp_pasv_verbose(conn, conninfo, newhost, connectport);
#ifndef CURL_DISABLE_HTTP
- if(conn->bits.tunnel_proxy) {
+ if(conn->bits.tunnel_proxy && conn->bits.httpproxy) {
/* FIX: this MUST wait for a proper connect first if 'connected' is
* FALSE */
@@ -2786,7 +2786,7 @@ CURLcode Curl_ftp_connect(struct connectdata *conn,
ftp->response_time = 3600; /* set default response time-out */
#ifndef CURL_DISABLE_HTTP
- if (conn->bits.tunnel_proxy) {
+ if (conn->bits.tunnel_proxy && conn->bits.httpproxy) {
/* BLOCKING */
/* We want "seamless" FTP operations through HTTP proxy tunnel */
diff --git a/lib/getinfo.c b/lib/getinfo.c
index 47828212b..2a4c3aac4 100644
--- a/lib/getinfo.c
+++ b/lib/getinfo.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2005, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2006, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -187,6 +187,14 @@ CURLcode Curl_getinfo(struct SessionHandle *data, CURLINFO info, ...)
case CURLINFO_COOKIELIST:
*param_slistp = Curl_cookie_list(data);
break;
+ case CURLINFO_LASTSOCKET:
+ if((data->state.lastconnect != -1) &&
+ (data->state.connects[data->state.lastconnect] != NULL))
+ *param_longp = data->state.connects[data->state.lastconnect]->
+ sock[FIRSTSOCKET];
+ else
+ *param_longp = -1;
+ break;
default:
return CURLE_BAD_FUNCTION_ARGUMENT;
}
diff --git a/lib/http.c b/lib/http.c
index 39e2940ff..e15054f57 100644
--- a/lib/http.c
+++ b/lib/http.c
@@ -1361,7 +1361,7 @@ CURLcode Curl_http_connect(struct connectdata *conn, bool *done)
* after the connect has occured, can we start talking SSL
*/
- if(conn->bits.tunnel_proxy) {
+ if(conn->bits.tunnel_proxy && conn->bits.httpproxy) {
/* either SSL over proxy, or explicitly asked for */
result = Curl_proxyCONNECT(conn, FIRSTSOCKET,
diff --git a/lib/multi.c b/lib/multi.c
index a60e1f5a9..a7d1988d6 100644
--- a/lib/multi.c
+++ b/lib/multi.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2005, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2006, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -522,41 +522,50 @@ CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles)
break;
case CURLM_STATE_DO:
- /* Perform the protocol's DO action */
- easy->result = Curl_do(&easy->easy_conn, &dophase_done);
+ if(easy->easy_handle->set.connect_only) {
+ /* keep connection open for application to use the socket */
+ easy->easy_conn->bits.close = FALSE;
+ multistate(easy, CURLM_STATE_DONE);
+ easy->result = CURLE_OK;
+ result = CURLM_OK;
+ }
+ else {
+ /* Perform the protocol's DO action */
+ easy->result = Curl_do(&easy->easy_conn, &dophase_done);
- if(CURLE_OK == easy->result) {
+ if(CURLE_OK == easy->result) {
- if(!dophase_done) {
- /* DO was not completed in one function call, we must continue
- DOING... */
- multistate(easy, CURLM_STATE_DOING);
- result = CURLM_OK;
- }
+ if(!dophase_done) {
+ /* DO was not completed in one function call, we must continue
+ DOING... */
+ multistate(easy, CURLM_STATE_DOING);
+ result = CURLM_OK;
+ }
- /* after DO, go PERFORM... or DO_MORE */
- else if(easy->easy_conn->bits.do_more) {
- /* we're supposed to do more, but we need to sit down, relax
- and wait a little while first */
- multistate(easy, CURLM_STATE_DO_MORE);
- result = CURLM_OK;
+ /* after DO, go PERFORM... or DO_MORE */
+ else if(easy->easy_conn->bits.do_more) {
+ /* we're supposed to do more, but we need to sit down, relax
+ and wait a little while first */
+ multistate(easy, CURLM_STATE_DO_MORE);
+ result = CURLM_OK;
+ }
+ else {
+ /* we're done with the DO, now PERFORM */
+ easy->result = Curl_readwrite_init(easy->easy_conn);
+ if(CURLE_OK == easy->result) {
+ multistate(easy, CURLM_STATE_PERFORM);
+ result = CURLM_CALL_MULTI_PERFORM;
+ }
+ }
}
else {
- /* we're done with the DO, now PERFORM */
- easy->result = Curl_readwrite_init(easy->easy_conn);
- if(CURLE_OK == easy->result) {
- multistate(easy, CURLM_STATE_PERFORM);
- result = CURLM_CALL_MULTI_PERFORM;
- }
+ /* failure detected */
+ Curl_posttransfer(easy->easy_handle);
+ Curl_done(&easy->easy_conn, easy->result);
+ Curl_disconnect(easy->easy_conn); /* close the connection */
+ easy->easy_conn = NULL; /* no more connection */
}
}
- else {
- /* failure detected */
- Curl_posttransfer(easy->easy_handle);
- Curl_done(&easy->easy_conn, easy->result);
- Curl_disconnect(easy->easy_conn); /* close the connection */
- easy->easy_conn = NULL; /* no more connection */
- }
break;
case CURLM_STATE_DOING:
diff --git a/lib/transfer.c b/lib/transfer.c
index 50a8bae98..2fbc2c615 100644
--- a/lib/transfer.c
+++ b/lib/transfer.c
@@ -2159,6 +2159,12 @@ CURLcode Curl_perform(struct SessionHandle *data)
if(res == CURLE_OK) {
bool do_done;
+ if(data->set.connect_only) {
+ /* keep connection open for application to use the socket */
+ conn->bits.close = FALSE;
+ res = Curl_done(&conn, CURLE_OK);
+ break;
+ }
res = Curl_do(&conn, &do_done);
/* for non 3rd party transfer only */
diff --git a/lib/url.c b/lib/url.c
index f17213f79..49e7c1cbf 100644
--- a/lib/url.c
+++ b/lib/url.c
@@ -352,6 +352,9 @@ CURLcode Curl_open(struct SessionHandle **curl)
memset(data->state.connects, 0,
sizeof(struct connectdata *)*data->state.numconnects);
+ /* most recent connection is not yet defined */
+ data->state.lastconnect = -1;
+
/*
* libcurl 7.10 introduced SSL verification *by default*! This needs to be
* switched off unless wanted.
@@ -432,6 +435,10 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
are being removed! */
for(i=newconnects; i< data->state.numconnects; i++)
Curl_disconnect(data->state.connects[i]);
+
+ /* If the most recent connection is no longer valid, mark it invalid. */
+ if(data->state.lastconnect <= newconnects)
+ data->state.lastconnect = -1;
}
if(newconnects) {
newptr= (struct connectdata **)
@@ -453,8 +460,9 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
/* zero makes NO cache at all */
if(data->state.connects)
free(data->state.connects);
- data->state.connects=NULL;
- data->state.numconnects=0;
+ data->state.connects = NULL;
+ data->state.numconnects = 0;
+ data->state.lastconnect = -1;
}
}
break;
@@ -1471,6 +1479,13 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
data->set.ignorecl = va_arg(param, long)?TRUE:FALSE;
break;
+ case CURLOPT_CONNECT_ONLY:
+ /*
+ * No data transfer, set up connection and let application use the socket
+ */
+ data->set.connect_only = va_arg(param, long)?TRUE:FALSE;
+ break;
+
default:
/* unknown tag and its companion, just ignore: */
result = CURLE_FAILED_INIT; /* correct this */
@@ -3811,10 +3826,14 @@ CURLcode Curl_done(struct connectdata **connp,
if(!result && res2)
result = res2;
}
- else
+ else {
+ /* remember the most recently used connection */
+ data->state.lastconnect = conn->connectindex;
+
infof(data, "Connection #%ld to host %s left intact\n",
conn->connectindex,
conn->bits.httpproxy?conn->proxy.dispname:conn->host.dispname);
+ }
return result;
}
diff --git a/lib/urldata.h b/lib/urldata.h
index 96494a7ce..a3802b7c3 100644
--- a/lib/urldata.h
+++ b/lib/urldata.h
@@ -856,6 +856,7 @@ struct UrlState {
set, it holds an allocated connection. */
struct connectdata **connects;
long numconnects; /* size of the 'connects' array */
+ int lastconnect; /* index of most recent connect or -1 if undefined */
char *headerbuff; /* allocated buffer to store headers in */
size_t headersize; /* size of the allocation */
@@ -1083,6 +1084,7 @@ struct UserDefined {
bool ignorecl; /* ignore content length */
bool ftp_skip_ip; /* skip the IP address the FTP server passes on to
us */
+ bool connect_only; /* make connection, let application use the socket */
};
/*