1
0
mirror of https://github.com/moparisthebest/curl synced 2024-12-23 08:38:49 -05:00

connection: never reuse CONNECT_ONLY conections

and make CONNECT_ONLY conections never reuse any existing ones either.

Reported-by: Pavel Löbl
Bug: https://curl.haxx.se/mail/lib-2019-02/0064.html
Closes #3586
This commit is contained in:
Daniel Stenberg 2019-02-18 16:33:36 +01:00
parent e49e5eaa10
commit b08898fb29
No known key found for this signature in database
GPG Key ID: 5CC908FDB71E12C2
5 changed files with 65 additions and 77 deletions

View File

@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
.\" * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
.\" * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@ -37,6 +37,9 @@ useful when used with the \fICURLINFO_ACTIVESOCKET(3)\fP option to
\fIcurl_easy_getinfo(3)\fP as the library can set up the connection and then
the application can obtain the most recently used socket for special data
transfers.
Transfers marked connect only will not reuse any existing connections and
connections marked connect only will not be allowed to get reused.
.SH DEFAULT
0
.SH PROTOCOLS

View File

@ -1133,6 +1133,10 @@ ConnectionExists(struct Curl_easy *data,
check = curr->ptr;
curr = curr->next;
if(check->bits.connect_only)
/* connect-only connections will not be reused */
continue;
if(extract_if_dead(check, data)) {
/* disconnect it */
(void)Curl_disconnect(data, check, /* dead_connection */TRUE);
@ -1893,8 +1897,8 @@ static struct connectdata *allocate_conn(struct Curl_easy *data)
data->set.proxy_ssl.primary.verifystatus;
conn->proxy_ssl_config.verifypeer = data->set.proxy_ssl.primary.verifypeer;
conn->proxy_ssl_config.verifyhost = data->set.proxy_ssl.primary.verifyhost;
conn->ip_version = data->set.ipver;
conn->bits.connect_only = data->set.connect_only;
#if !defined(CURL_DISABLE_HTTP) && defined(USE_NTLM) && \
defined(NTLM_WB_ENABLED)
@ -3871,8 +3875,9 @@ static CURLcode create_conn(struct Curl_easy *data,
/* reuse_fresh is TRUE if we are told to use a new connection by force, but
we only acknowledge this option if this is not a re-used connection
already (which happens due to follow-location or during a HTTP
authentication phase). */
if(data->set.reuse_fresh && !data->state.this_is_a_follow)
authentication phase). CONNECT_ONLY transfers also refuse reuse. */
if((data->set.reuse_fresh && !data->state.this_is_a_follow) ||
data->set.connect_only)
reuse = FALSE;
else
reuse = ConnectionExists(data, conn, &conn_temp, &force_reuse, &waitpipe);

View File

@ -452,6 +452,7 @@ struct ConnectBits {
bool proxy_ssl_connected[2]; /* TRUE when SSL initialization for HTTPS proxy
is complete */
bool socksproxy_connecting; /* connecting through a socks proxy */
bool connect_only;
};
struct hostname {

View File

@ -31,7 +31,6 @@ ftp://%HOSTIP:%FTPPORT
USER anonymous
PASS ftp@example.com
PWD
QUIT
</protocol>
</verify>
</testcase>

View File

@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@ -32,20 +32,12 @@
/*
* Test case for below scenario:
* - Connect to an FTP server using CONNECT_ONLY option
* - transfer some files with re-using the connection (omitted in test case)
* - Disconnect from FTP server with sending QUIT command
*
* The test case originated for verifying CONNECT_ONLY option shall not
* block after protocol connect is done, but it returns the message
* with function curl_multi_info_read().
*/
enum {
CONNECT_ONLY_PHASE = 0,
QUIT_PHASE,
LAST_PHASE
};
int test(char *URL)
{
CURL *easy = NULL;
@ -53,7 +45,6 @@ int test(char *URL)
int res = 0;
int running;
int msgs_left;
int phase;
CURLMsg *msg;
start_test_timing();
@ -64,76 +55,65 @@ int test(char *URL)
multi_init(multi);
for(phase = CONNECT_ONLY_PHASE; phase < LAST_PHASE; ++phase) {
/* go verbose */
easy_setopt(easy, CURLOPT_VERBOSE, 1L);
/* go verbose */
easy_setopt(easy, CURLOPT_VERBOSE, 1L);
/* specify target */
easy_setopt(easy, CURLOPT_URL, URL);
/* specify target */
easy_setopt(easy, CURLOPT_URL, URL);
/* enable 'CONNECT_ONLY' option when in connect phase */
if(phase == CONNECT_ONLY_PHASE)
easy_setopt(easy, CURLOPT_CONNECT_ONLY, 1L);
easy_setopt(easy, CURLOPT_CONNECT_ONLY, 1L);
/* enable 'NOBODY' option to send 'QUIT' command in quit phase */
if(phase == QUIT_PHASE) {
easy_setopt(easy, CURLOPT_CONNECT_ONLY, 0L);
easy_setopt(easy, CURLOPT_NOBODY, 1L);
easy_setopt(easy, CURLOPT_FORBID_REUSE, 1L);
multi_add_handle(multi, easy);
for(;;) {
struct timeval interval;
fd_set fdread;
fd_set fdwrite;
fd_set fdexcep;
long timeout = -99;
int maxfd = -99;
multi_perform(multi, &running);
abort_on_test_timeout();
if(!running)
break; /* done */
FD_ZERO(&fdread);
FD_ZERO(&fdwrite);
FD_ZERO(&fdexcep);
multi_fdset(multi, &fdread, &fdwrite, &fdexcep, &maxfd);
/* At this point, maxfd is guaranteed to be greater or equal than -1. */
multi_timeout(multi, &timeout);
/* At this point, timeout is guaranteed to be greater or equal than
-1. */
if(timeout != -1L) {
int itimeout = (timeout > (long)INT_MAX) ? INT_MAX : (int)timeout;
interval.tv_sec = itimeout/1000;
interval.tv_usec = (itimeout%1000)*1000;
}
else {
interval.tv_sec = TEST_HANG_TIMEOUT/1000 + 1;
interval.tv_usec = 0;
}
multi_add_handle(multi, easy);
select_test(maxfd + 1, &fdread, &fdwrite, &fdexcep, &interval);
for(;;) {
struct timeval interval;
fd_set fdread;
fd_set fdwrite;
fd_set fdexcep;
long timeout = -99;
int maxfd = -99;
multi_perform(multi, &running);
abort_on_test_timeout();
if(!running)
break; /* done */
FD_ZERO(&fdread);
FD_ZERO(&fdwrite);
FD_ZERO(&fdexcep);
multi_fdset(multi, &fdread, &fdwrite, &fdexcep, &maxfd);
/* At this point, maxfd is guaranteed to be greater or equal than -1. */
multi_timeout(multi, &timeout);
/* At this point, timeout is guaranteed to be greater or equal than
-1. */
if(timeout != -1L) {
int itimeout = (timeout > (long)INT_MAX) ? INT_MAX : (int)timeout;
interval.tv_sec = itimeout/1000;
interval.tv_usec = (itimeout%1000)*1000;
}
else {
interval.tv_sec = TEST_HANG_TIMEOUT/1000 + 1;
interval.tv_usec = 0;
}
select_test(maxfd + 1, &fdread, &fdwrite, &fdexcep, &interval);
abort_on_test_timeout();
}
msg = curl_multi_info_read(multi, &msgs_left);
if(msg)
res = msg->data.result;
multi_remove_handle(multi, easy);
abort_on_test_timeout();
}
msg = curl_multi_info_read(multi, &msgs_left);
if(msg)
res = msg->data.result;
multi_remove_handle(multi, easy);
test_cleanup:
/* undocumented cleanup sequence - type UA */