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.
This commit is contained in:
Daniel Stenberg 2006-02-11 22:35:16 +00:00
parent b0bc2f00d2
commit 87bcb6f377
13 changed files with 119 additions and 48 deletions

View File

@ -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.

View File

@ -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)

View File

@ -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()

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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 */

View File

@ -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;
}

View File

@ -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,

View File

@ -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,40 +522,49 @@ 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(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;
}
/* 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;
}
}
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 {
/* 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 */
/* Perform the protocol's DO action */
easy->result = Curl_do(&easy->easy_conn, &dophase_done);
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;
}
/* 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 {
/* 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;

View File

@ -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 */

View File

@ -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;
}

View File

@ -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 */
};
/*