mirror of
https://github.com/moparisthebest/curl
synced 2024-12-21 15:48:49 -05:00
multi: turn Curl_done into file local multi_done
... as it now is used by multi.c only.
This commit is contained in:
parent
93935c08c1
commit
575e885db0
@ -3242,7 +3242,7 @@ static CURLcode ftp_connect(struct connectdata *conn,
|
||||
* Input argument is already checked for validity.
|
||||
*/
|
||||
static CURLcode ftp_done(struct connectdata *conn, CURLcode status,
|
||||
bool premature)
|
||||
bool premature)
|
||||
{
|
||||
struct SessionHandle *data = conn->data;
|
||||
struct FTP *ftp = data->req.protop;
|
||||
@ -3256,11 +3256,6 @@ static CURLcode ftp_done(struct connectdata *conn, CURLcode status,
|
||||
const char *path_to_use = data->state.path;
|
||||
|
||||
if(!ftp)
|
||||
/* When the easy handle is removed from the multi while libcurl is still
|
||||
* trying to resolve the host name, it seems that the ftp struct is not
|
||||
* yet initialized, but the removal action calls Curl_done() which calls
|
||||
* this function. So we simply return success if no ftp pointer is set.
|
||||
*/
|
||||
return CURLE_OK;
|
||||
|
||||
switch(status) {
|
||||
|
@ -1434,8 +1434,8 @@ static int https_getsock(struct connectdata *conn,
|
||||
#endif /* USE_OPENSSL || USE_GNUTLS || USE_SCHANNEL */
|
||||
|
||||
/*
|
||||
* Curl_http_done() gets called from Curl_done() after a single HTTP request
|
||||
* has been performed.
|
||||
* Curl_http_done() gets called after a single HTTP request has been
|
||||
* performed.
|
||||
*/
|
||||
|
||||
CURLcode Curl_http_done(struct connectdata *conn,
|
||||
|
@ -1486,10 +1486,6 @@ static CURLcode imap_done(struct connectdata *conn, CURLcode status,
|
||||
(void)premature;
|
||||
|
||||
if(!imap)
|
||||
/* When the easy handle is removed from the multi interface while libcurl
|
||||
is still trying to resolve the host name, the IMAP struct is not yet
|
||||
initialized. However, the removal action calls Curl_done() which in
|
||||
turn calls this function, so we simply return success. */
|
||||
return CURLE_OK;
|
||||
|
||||
if(status) {
|
||||
@ -1512,8 +1508,7 @@ static CURLcode imap_done(struct connectdata *conn, CURLcode status,
|
||||
|
||||
TODO: when the multi interface is used, this _really_ should be using
|
||||
the imap_multi_statemach function but we have no general support for
|
||||
non-blocking DONE operations, not in the multi state machine and with
|
||||
Curl_done() invokes on several places in the code!
|
||||
non-blocking DONE operations!
|
||||
*/
|
||||
if(!result)
|
||||
result = imap_block_statemach(conn);
|
||||
|
217
lib/multi.c
217
lib/multi.c
@ -484,6 +484,167 @@ static void debug_print_sock_hash(void *p)
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Mark the connection as 'idle', or close it if the cache is full.
|
||||
Returns TRUE if the connection is kept, or FALSE if it was closed. */
|
||||
static bool
|
||||
ConnectionDone(struct SessionHandle *data, struct connectdata *conn)
|
||||
{
|
||||
/* data->multi->maxconnects can be negative, deal with it. */
|
||||
size_t maxconnects =
|
||||
(data->multi->maxconnects < 0) ? data->multi->num_easy * 4:
|
||||
data->multi->maxconnects;
|
||||
struct connectdata *conn_candidate = NULL;
|
||||
|
||||
/* Mark the current connection as 'unused' */
|
||||
conn->inuse = FALSE;
|
||||
|
||||
if(maxconnects > 0 &&
|
||||
data->state.conn_cache->num_connections > maxconnects) {
|
||||
infof(data, "Connection cache is full, closing the oldest one.\n");
|
||||
|
||||
conn_candidate = Curl_oldest_idle_connection(data);
|
||||
|
||||
if(conn_candidate) {
|
||||
/* Set the connection's owner correctly */
|
||||
conn_candidate->data = data;
|
||||
|
||||
/* the winner gets the honour of being disconnected */
|
||||
(void)Curl_disconnect(conn_candidate, /* dead_connection */ FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
return (conn_candidate == conn) ? FALSE : TRUE;
|
||||
}
|
||||
|
||||
static CURLcode multi_done(struct connectdata **connp,
|
||||
CURLcode status, /* an error if this is called
|
||||
after an error was detected */
|
||||
bool premature)
|
||||
{
|
||||
CURLcode result;
|
||||
struct connectdata *conn;
|
||||
struct SessionHandle *data;
|
||||
|
||||
DEBUGASSERT(*connp);
|
||||
|
||||
conn = *connp;
|
||||
data = conn->data;
|
||||
|
||||
DEBUGF(infof(data, "multi_done\n"));
|
||||
|
||||
if(data->state.done)
|
||||
/* Stop if multi_done() has already been called */
|
||||
return CURLE_OK;
|
||||
|
||||
Curl_getoff_all_pipelines(data, conn);
|
||||
|
||||
/* Cleanup possible redirect junk */
|
||||
free(data->req.newurl);
|
||||
data->req.newurl = NULL;
|
||||
free(data->req.location);
|
||||
data->req.location = NULL;
|
||||
|
||||
switch(status) {
|
||||
case CURLE_ABORTED_BY_CALLBACK:
|
||||
case CURLE_READ_ERROR:
|
||||
case CURLE_WRITE_ERROR:
|
||||
/* When we're aborted due to a callback return code it basically have to
|
||||
be counted as premature as there is trouble ahead if we don't. We have
|
||||
many callbacks and protocols work differently, we could potentially do
|
||||
this more fine-grained in the future. */
|
||||
premature = TRUE;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* this calls the protocol-specific function pointer previously set */
|
||||
if(conn->handler->done)
|
||||
result = conn->handler->done(conn, status, premature);
|
||||
else
|
||||
result = status;
|
||||
|
||||
if(CURLE_ABORTED_BY_CALLBACK != result) {
|
||||
/* avoid this if we already aborted by callback to avoid this calling
|
||||
another callback */
|
||||
CURLcode rc = Curl_pgrsDone(conn);
|
||||
if(!result && rc)
|
||||
result = CURLE_ABORTED_BY_CALLBACK;
|
||||
}
|
||||
|
||||
if((!premature &&
|
||||
conn->send_pipe->size + conn->recv_pipe->size != 0 &&
|
||||
!data->set.reuse_forbid &&
|
||||
!conn->bits.close)) {
|
||||
/* Stop if pipeline is not empty and we do not have to close
|
||||
connection. */
|
||||
DEBUGF(infof(data, "Connection still in use, no more multi_done now!\n"));
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
data->state.done = TRUE; /* called just now! */
|
||||
Curl_resolver_cancel(conn);
|
||||
|
||||
if(conn->dns_entry) {
|
||||
Curl_resolv_unlock(data, conn->dns_entry); /* done with this */
|
||||
conn->dns_entry = NULL;
|
||||
}
|
||||
|
||||
/* if the transfer was completed in a paused state there can be buffered
|
||||
data left to write and then kill */
|
||||
free(data->state.tempwrite);
|
||||
data->state.tempwrite = NULL;
|
||||
|
||||
/* if data->set.reuse_forbid is TRUE, it means the libcurl client has
|
||||
forced us to close this connection. This is ignored for requests taking
|
||||
place in a NTLM authentication handshake
|
||||
|
||||
if conn->bits.close is TRUE, it means that the connection should be
|
||||
closed in spite of all our efforts to be nice, due to protocol
|
||||
restrictions in our or the server's end
|
||||
|
||||
if premature is TRUE, it means this connection was said to be DONE before
|
||||
the entire request operation is complete and thus we can't know in what
|
||||
state it is for re-using, so we're forced to close it. In a perfect world
|
||||
we can add code that keep track of if we really must close it here or not,
|
||||
but currently we have no such detail knowledge.
|
||||
*/
|
||||
|
||||
if((data->set.reuse_forbid
|
||||
#if defined(USE_NTLM)
|
||||
&& !(conn->ntlm.state == NTLMSTATE_TYPE2 ||
|
||||
conn->proxyntlm.state == NTLMSTATE_TYPE2)
|
||||
#endif
|
||||
) || conn->bits.close || premature) {
|
||||
CURLcode res2 = Curl_disconnect(conn, premature); /* close connection */
|
||||
|
||||
/* If we had an error already, make sure we return that one. But
|
||||
if we got a new error, return that. */
|
||||
if(!result && res2)
|
||||
result = res2;
|
||||
}
|
||||
else {
|
||||
/* the connection is no longer in use */
|
||||
if(ConnectionDone(data, conn)) {
|
||||
/* remember the most recently used connection */
|
||||
data->state.lastconnect = conn;
|
||||
|
||||
infof(data, "Connection #%ld to host %s left intact\n",
|
||||
conn->connection_id,
|
||||
conn->bits.httpproxy?conn->proxy.dispname:conn->host.dispname);
|
||||
}
|
||||
else
|
||||
data->state.lastconnect = NULL;
|
||||
}
|
||||
|
||||
*connp = NULL; /* to make the caller of this function better detect that
|
||||
this was either closed or handed over to the connection
|
||||
cache here, and therefore cannot be used from this point on
|
||||
*/
|
||||
Curl_free_request_state(data);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
CURLMcode curl_multi_remove_handle(CURLM *multi_handle,
|
||||
CURL *curl_handle)
|
||||
{
|
||||
@ -529,8 +690,8 @@ CURLMcode curl_multi_remove_handle(CURLM *multi_handle,
|
||||
request but not received its response yet, we need to close
|
||||
connection. */
|
||||
connclose(data->easy_conn, "Removed with partial response");
|
||||
/* Set connection owner so that Curl_done() closes it.
|
||||
We can safely do this here since connection is killed. */
|
||||
/* Set connection owner so that the DONE function closes it. We can
|
||||
safely do this here since connection is killed. */
|
||||
data->easy_conn->data = easy;
|
||||
easy_owns_conn = TRUE;
|
||||
}
|
||||
@ -548,26 +709,26 @@ CURLMcode curl_multi_remove_handle(CURLM *multi_handle,
|
||||
|
||||
if(data->easy_conn) {
|
||||
|
||||
/* we must call Curl_done() here (if we still "own it") so that we don't
|
||||
leave a half-baked one around */
|
||||
/* we must call multi_done() here (if we still own the connection) so that
|
||||
we don't leave a half-baked one around */
|
||||
if(easy_owns_conn) {
|
||||
|
||||
/* Curl_done() clears the conn->data field to lose the association
|
||||
/* multi_done() clears the conn->data field to lose the association
|
||||
between the easy handle and the connection
|
||||
|
||||
Note that this ignores the return code simply because there's
|
||||
nothing really useful to do with it anyway! */
|
||||
(void)Curl_done(&data->easy_conn, data->result, premature);
|
||||
(void)multi_done(&data->easy_conn, data->result, premature);
|
||||
}
|
||||
else
|
||||
/* Clear connection pipelines, if Curl_done above was not called */
|
||||
/* Clear connection pipelines, if multi_done above was not called */
|
||||
Curl_getoff_all_pipelines(data, data->easy_conn);
|
||||
}
|
||||
|
||||
Curl_wildcard_dtor(&data->wildcard);
|
||||
|
||||
/* destroy the timeout list that is held in the easy handle, do this *after*
|
||||
Curl_done() as that may actuall call Curl_expire that uses this */
|
||||
multi_done() as that may actually call Curl_expire that uses this */
|
||||
if(data->state.timeoutlist) {
|
||||
Curl_llist_destroy(data->state.timeoutlist, NULL);
|
||||
data->state.timeoutlist = NULL;
|
||||
@ -1005,18 +1166,16 @@ static CURLcode multi_reconnect_request(struct connectdata **connp)
|
||||
infof(data, "Re-used connection seems dead, get a new one\n");
|
||||
|
||||
connclose(conn, "Reconnect dead connection"); /* enforce close */
|
||||
result = Curl_done(&conn, result, FALSE); /* we are so done with this */
|
||||
result = multi_done(&conn, result, FALSE); /* we are so done with this */
|
||||
|
||||
/* conn may no longer be a good pointer, clear it to avoid mistakes by
|
||||
parent functions */
|
||||
*connp = NULL;
|
||||
|
||||
/*
|
||||
* According to bug report #1330310. We need to check for CURLE_SEND_ERROR
|
||||
* here as well. I figure this could happen when the request failed on a FTP
|
||||
* connection and thus Curl_done() itself tried to use the connection
|
||||
* (again). Slight Lack of feedback in the report, but I don't think this
|
||||
* extra check can do much harm.
|
||||
* We need to check for CURLE_SEND_ERROR here as well. This could happen
|
||||
* when the request failed on a FTP connection and thus multi_done() itself
|
||||
* tried to use the connection (again).
|
||||
*/
|
||||
if(!result || (CURLE_SEND_ERROR == result)) {
|
||||
bool async;
|
||||
@ -1227,7 +1386,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
||||
disconnect_conn = TRUE;
|
||||
}
|
||||
result = CURLE_OPERATION_TIMEDOUT;
|
||||
(void)Curl_done(&data->easy_conn, result, TRUE);
|
||||
(void)multi_done(&data->easy_conn, result, TRUE);
|
||||
/* Skip the statemachine and go directly to error handling section. */
|
||||
goto statemachine_end;
|
||||
}
|
||||
@ -1372,7 +1531,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
||||
rc = CURLM_CALL_MULTI_PERFORM;
|
||||
/* connect back to proxy again */
|
||||
result = CURLE_OK;
|
||||
Curl_done(&data->easy_conn, CURLE_OK, FALSE);
|
||||
multi_done(&data->easy_conn, CURLE_OK, FALSE);
|
||||
multistate(data, CURLM_STATE_CONNECT);
|
||||
}
|
||||
else if(!result) {
|
||||
@ -1416,7 +1575,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
||||
else if(result) {
|
||||
/* failure detected */
|
||||
Curl_posttransfer(data);
|
||||
Curl_done(&data->easy_conn, result, TRUE);
|
||||
multi_done(&data->easy_conn, result, TRUE);
|
||||
disconnect_conn = TRUE;
|
||||
}
|
||||
break;
|
||||
@ -1433,7 +1592,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
||||
else if(result) {
|
||||
/* failure detected */
|
||||
Curl_posttransfer(data);
|
||||
Curl_done(&data->easy_conn, result, TRUE);
|
||||
multi_done(&data->easy_conn, result, TRUE);
|
||||
disconnect_conn = TRUE;
|
||||
}
|
||||
break;
|
||||
@ -1468,7 +1627,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
||||
struct WildcardData *wc = &data->wildcard;
|
||||
if(wc->state == CURLWC_DONE || wc->state == CURLWC_SKIP) {
|
||||
/* skip some states if it is important */
|
||||
Curl_done(&data->easy_conn, CURLE_OK, FALSE);
|
||||
multi_done(&data->easy_conn, CURLE_OK, FALSE);
|
||||
multistate(data, CURLM_STATE_DONE);
|
||||
rc = CURLM_CALL_MULTI_PERFORM;
|
||||
break;
|
||||
@ -1515,7 +1674,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
||||
retry = (newurl)?TRUE:FALSE;
|
||||
|
||||
Curl_posttransfer(data);
|
||||
drc = Curl_done(&data->easy_conn, result, FALSE);
|
||||
drc = multi_done(&data->easy_conn, result, FALSE);
|
||||
|
||||
/* When set to retry the connection, we must to go back to
|
||||
* the CONNECT state */
|
||||
@ -1550,7 +1709,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
||||
/* failure detected */
|
||||
Curl_posttransfer(data);
|
||||
if(data->easy_conn)
|
||||
Curl_done(&data->easy_conn, result, FALSE);
|
||||
multi_done(&data->easy_conn, result, FALSE);
|
||||
disconnect_conn = TRUE;
|
||||
}
|
||||
}
|
||||
@ -1572,7 +1731,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
||||
else {
|
||||
/* failure detected */
|
||||
Curl_posttransfer(data);
|
||||
Curl_done(&data->easy_conn, result, FALSE);
|
||||
multi_done(&data->easy_conn, result, FALSE);
|
||||
disconnect_conn = TRUE;
|
||||
}
|
||||
break;
|
||||
@ -1584,7 +1743,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
||||
result = multi_do_more(data->easy_conn, &control);
|
||||
|
||||
/* No need to remove this handle from the send pipeline here since that
|
||||
is done in Curl_done() */
|
||||
is done in multi_done() */
|
||||
if(!result) {
|
||||
if(control) {
|
||||
/* if positive, advance to DO_DONE
|
||||
@ -1601,7 +1760,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
||||
else {
|
||||
/* failure detected */
|
||||
Curl_posttransfer(data);
|
||||
Curl_done(&data->easy_conn, result, FALSE);
|
||||
multi_done(&data->easy_conn, result, FALSE);
|
||||
disconnect_conn = TRUE;
|
||||
}
|
||||
break;
|
||||
@ -1725,7 +1884,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
||||
connclose(data->easy_conn, "Transfer returned error");
|
||||
|
||||
Curl_posttransfer(data);
|
||||
Curl_done(&data->easy_conn, result, FALSE);
|
||||
multi_done(&data->easy_conn, result, FALSE);
|
||||
}
|
||||
else if(done) {
|
||||
followtype follow=FOLLOW_NONE;
|
||||
@ -1756,7 +1915,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
||||
}
|
||||
else
|
||||
follow = FOLLOW_RETRY;
|
||||
result = Curl_done(&data->easy_conn, CURLE_OK, FALSE);
|
||||
result = multi_done(&data->easy_conn, CURLE_OK, FALSE);
|
||||
if(!result) {
|
||||
result = Curl_follow(data, newurl, follow);
|
||||
if(!result) {
|
||||
@ -1806,14 +1965,14 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
||||
Curl_multi_process_pending_handles(multi);
|
||||
|
||||
/* post-transfer command */
|
||||
res = Curl_done(&data->easy_conn, result, FALSE);
|
||||
res = multi_done(&data->easy_conn, result, FALSE);
|
||||
|
||||
/* allow a previously set error code take precedence */
|
||||
if(!result)
|
||||
result = res;
|
||||
|
||||
/*
|
||||
* If there are other handles on the pipeline, Curl_done won't set
|
||||
* If there are other handles on the pipeline, multi_done won't set
|
||||
* easy_conn to NULL. In such a case, curl_multi_remove_handle() can
|
||||
* access free'd data, if the connection is free'd and the handle
|
||||
* removed before we perform the processing in CURLM_STATE_COMPLETED
|
||||
@ -1832,7 +1991,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
||||
}
|
||||
|
||||
/* after we have DONE what we're supposed to do, go COMPLETED, and
|
||||
it doesn't matter what the Curl_done() returned! */
|
||||
it doesn't matter what the multi_done() returned! */
|
||||
multistate(data, CURLM_STATE_COMPLETED);
|
||||
break;
|
||||
|
||||
|
@ -1166,10 +1166,6 @@ static CURLcode pop3_done(struct connectdata *conn, CURLcode status,
|
||||
(void)premature;
|
||||
|
||||
if(!pop3)
|
||||
/* When the easy handle is removed from the multi interface while libcurl
|
||||
is still trying to resolve the host name, the POP3 struct is not yet
|
||||
initialized. However, the removal action calls Curl_done() which in
|
||||
turn calls this function, so we simply return success. */
|
||||
return CURLE_OK;
|
||||
|
||||
if(status) {
|
||||
|
@ -1204,10 +1204,6 @@ static CURLcode smtp_done(struct connectdata *conn, CURLcode status,
|
||||
(void)premature;
|
||||
|
||||
if(!smtp || !pp->conn)
|
||||
/* When the easy handle is removed from the multi interface while libcurl
|
||||
is still trying to resolve the host name, the SMTP struct is not yet
|
||||
initialized. However, the removal action calls Curl_done() which in
|
||||
turn calls this function, so we simply return success. */
|
||||
return CURLE_OK;
|
||||
|
||||
if(status) {
|
||||
@ -1262,8 +1258,7 @@ static CURLcode smtp_done(struct connectdata *conn, CURLcode status,
|
||||
|
||||
TODO: when the multi interface is used, this _really_ should be using
|
||||
the smtp_multi_statemach function but we have no general support for
|
||||
non-blocking DONE operations, not in the multi state machine and with
|
||||
Curl_done() invokes on several places in the code!
|
||||
non-blocking DONE operations!
|
||||
*/
|
||||
result = smtp_block_statemach(conn);
|
||||
}
|
||||
|
@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2016, 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
|
||||
@ -3068,8 +3068,7 @@ static CURLcode ssh_done(struct connectdata *conn, CURLcode status)
|
||||
|
||||
TODO: when the multi interface is used, this _really_ should be using
|
||||
the ssh_multi_statemach function but we have no general support for
|
||||
non-blocking DONE operations, not in the multi state machine and with
|
||||
Curl_done() invokes on several places in the code!
|
||||
non-blocking DONE operations!
|
||||
*/
|
||||
result = ssh_block_statemach(conn, FALSE);
|
||||
}
|
||||
|
171
lib/url.c
171
lib/url.c
@ -137,8 +137,6 @@ bool curl_win32_idn_to_ascii(const char *in, char **out);
|
||||
|
||||
/* Local static prototypes */
|
||||
static struct connectdata *
|
||||
find_oldest_idle_connection(struct SessionHandle *data);
|
||||
static struct connectdata *
|
||||
find_oldest_idle_connection_in_bundle(struct SessionHandle *data,
|
||||
struct connectbundle *bundle);
|
||||
static void conn_free(struct connectdata *conn);
|
||||
@ -2960,8 +2958,8 @@ static void signalPipeClose(struct curl_llist *pipeline, bool pipe_broke)
|
||||
* Returns the pointer to the oldest idle connection, or NULL if none was
|
||||
* found.
|
||||
*/
|
||||
static struct connectdata *
|
||||
find_oldest_idle_connection(struct SessionHandle *data)
|
||||
struct connectdata *
|
||||
Curl_oldest_idle_connection(struct SessionHandle *data)
|
||||
{
|
||||
struct conncache *bc = data->state.conn_cache;
|
||||
struct curl_hash_iterator iter;
|
||||
@ -3493,38 +3491,6 @@ ConnectionExists(struct SessionHandle *data,
|
||||
return FALSE; /* no matching connecting exists */
|
||||
}
|
||||
|
||||
/* Mark the connection as 'idle', or close it if the cache is full.
|
||||
Returns TRUE if the connection is kept, or FALSE if it was closed. */
|
||||
static bool
|
||||
ConnectionDone(struct SessionHandle *data, struct connectdata *conn)
|
||||
{
|
||||
/* data->multi->maxconnects can be negative, deal with it. */
|
||||
size_t maxconnects =
|
||||
(data->multi->maxconnects < 0) ? data->multi->num_easy * 4:
|
||||
data->multi->maxconnects;
|
||||
struct connectdata *conn_candidate = NULL;
|
||||
|
||||
/* Mark the current connection as 'unused' */
|
||||
conn->inuse = FALSE;
|
||||
|
||||
if(maxconnects > 0 &&
|
||||
data->state.conn_cache->num_connections > maxconnects) {
|
||||
infof(data, "Connection cache is full, closing the oldest one.\n");
|
||||
|
||||
conn_candidate = find_oldest_idle_connection(data);
|
||||
|
||||
if(conn_candidate) {
|
||||
/* Set the connection's owner correctly */
|
||||
conn_candidate->data = data;
|
||||
|
||||
/* the winner gets the honour of being disconnected */
|
||||
(void)Curl_disconnect(conn_candidate, /* dead_connection */ FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
return (conn_candidate == conn) ? FALSE : TRUE;
|
||||
}
|
||||
|
||||
/* after a TCP connection to the proxy has been verified, this function does
|
||||
the next magic step.
|
||||
|
||||
@ -5891,7 +5857,7 @@ static CURLcode create_conn(struct SessionHandle *data,
|
||||
struct connectdata *conn_candidate;
|
||||
|
||||
/* The cache is full. Let's see if we can kill a connection. */
|
||||
conn_candidate = find_oldest_idle_connection(data);
|
||||
conn_candidate = Curl_oldest_idle_connection(data);
|
||||
|
||||
if(conn_candidate) {
|
||||
/* Set the connection's owner correctly, then kill it */
|
||||
@ -6103,135 +6069,6 @@ CURLcode Curl_connect(struct SessionHandle *data,
|
||||
return result;
|
||||
}
|
||||
|
||||
CURLcode Curl_done(struct connectdata **connp,
|
||||
CURLcode status, /* an error if this is called after an
|
||||
error was detected */
|
||||
bool premature)
|
||||
{
|
||||
CURLcode result;
|
||||
struct connectdata *conn;
|
||||
struct SessionHandle *data;
|
||||
|
||||
DEBUGASSERT(*connp);
|
||||
|
||||
conn = *connp;
|
||||
data = conn->data;
|
||||
|
||||
DEBUGF(infof(data, "Curl_done\n"));
|
||||
|
||||
if(data->state.done)
|
||||
/* Stop if Curl_done() has already been called */
|
||||
return CURLE_OK;
|
||||
|
||||
Curl_getoff_all_pipelines(data, conn);
|
||||
|
||||
/* Cleanup possible redirect junk */
|
||||
free(data->req.newurl);
|
||||
data->req.newurl = NULL;
|
||||
free(data->req.location);
|
||||
data->req.location = NULL;
|
||||
|
||||
switch(status) {
|
||||
case CURLE_ABORTED_BY_CALLBACK:
|
||||
case CURLE_READ_ERROR:
|
||||
case CURLE_WRITE_ERROR:
|
||||
/* When we're aborted due to a callback return code it basically have to
|
||||
be counted as premature as there is trouble ahead if we don't. We have
|
||||
many callbacks and protocols work differently, we could potentially do
|
||||
this more fine-grained in the future. */
|
||||
premature = TRUE;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* this calls the protocol-specific function pointer previously set */
|
||||
if(conn->handler->done)
|
||||
result = conn->handler->done(conn, status, premature);
|
||||
else
|
||||
result = status;
|
||||
|
||||
if(CURLE_ABORTED_BY_CALLBACK != result) {
|
||||
/* avoid this if we already aborted by callback to avoid this calling
|
||||
another callback */
|
||||
CURLcode rc = Curl_pgrsDone(conn);
|
||||
if(!result && rc)
|
||||
result = CURLE_ABORTED_BY_CALLBACK;
|
||||
}
|
||||
|
||||
if((!premature &&
|
||||
conn->send_pipe->size + conn->recv_pipe->size != 0 &&
|
||||
!data->set.reuse_forbid &&
|
||||
!conn->bits.close)) {
|
||||
/* Stop if pipeline is not empty and we do not have to close
|
||||
connection. */
|
||||
DEBUGF(infof(data, "Connection still in use, no more Curl_done now!\n"));
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
data->state.done = TRUE; /* called just now! */
|
||||
Curl_resolver_cancel(conn);
|
||||
|
||||
if(conn->dns_entry) {
|
||||
Curl_resolv_unlock(data, conn->dns_entry); /* done with this */
|
||||
conn->dns_entry = NULL;
|
||||
}
|
||||
|
||||
/* if the transfer was completed in a paused state there can be buffered
|
||||
data left to write and then kill */
|
||||
free(data->state.tempwrite);
|
||||
data->state.tempwrite = NULL;
|
||||
|
||||
/* if data->set.reuse_forbid is TRUE, it means the libcurl client has
|
||||
forced us to close this connection. This is ignored for requests taking
|
||||
place in a NTLM authentication handshake
|
||||
|
||||
if conn->bits.close is TRUE, it means that the connection should be
|
||||
closed in spite of all our efforts to be nice, due to protocol
|
||||
restrictions in our or the server's end
|
||||
|
||||
if premature is TRUE, it means this connection was said to be DONE before
|
||||
the entire request operation is complete and thus we can't know in what
|
||||
state it is for re-using, so we're forced to close it. In a perfect world
|
||||
we can add code that keep track of if we really must close it here or not,
|
||||
but currently we have no such detail knowledge.
|
||||
*/
|
||||
|
||||
if((data->set.reuse_forbid
|
||||
#if defined(USE_NTLM)
|
||||
&& !(conn->ntlm.state == NTLMSTATE_TYPE2 ||
|
||||
conn->proxyntlm.state == NTLMSTATE_TYPE2)
|
||||
#endif
|
||||
) || conn->bits.close || premature) {
|
||||
CURLcode res2 = Curl_disconnect(conn, premature); /* close connection */
|
||||
|
||||
/* If we had an error already, make sure we return that one. But
|
||||
if we got a new error, return that. */
|
||||
if(!result && res2)
|
||||
result = res2;
|
||||
}
|
||||
else {
|
||||
/* the connection is no longer in use */
|
||||
if(ConnectionDone(data, conn)) {
|
||||
/* remember the most recently used connection */
|
||||
data->state.lastconnect = conn;
|
||||
|
||||
infof(data, "Connection #%ld to host %s left intact\n",
|
||||
conn->connection_id,
|
||||
conn->bits.httpproxy?conn->proxy.dispname:conn->host.dispname);
|
||||
}
|
||||
else
|
||||
data->state.lastconnect = NULL;
|
||||
}
|
||||
|
||||
*connp = NULL; /* to make the caller of this function better detect that
|
||||
this was either closed or handed over to the connection
|
||||
cache here, and therefore cannot be used from this point on
|
||||
*/
|
||||
Curl_free_request_state(data);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Curl_init_do() inits the readwrite session. This is inited each time (in
|
||||
* the DO function before the protocol-specific DO functions are invoked) for
|
||||
@ -6250,7 +6087,7 @@ CURLcode Curl_init_do(struct SessionHandle *data, struct connectdata *conn)
|
||||
conn->bits.do_more = FALSE; /* by default there's no curl_do_more() to
|
||||
* use */
|
||||
|
||||
data->state.done = FALSE; /* Curl_done() is not called yet */
|
||||
data->state.done = FALSE; /* *_done() is not called yet */
|
||||
data->state.expect100header = FALSE;
|
||||
|
||||
if(data->set.opt_no_body)
|
||||
|
@ -37,7 +37,6 @@ void Curl_freeset(struct SessionHandle * data);
|
||||
CURLcode Curl_close(struct SessionHandle *data); /* opposite of curl_open() */
|
||||
CURLcode Curl_connect(struct SessionHandle *, struct connectdata **,
|
||||
bool *async, bool *protocol_connect);
|
||||
CURLcode Curl_done(struct connectdata **, CURLcode, bool premature);
|
||||
CURLcode Curl_disconnect(struct connectdata *, bool dead_connection);
|
||||
CURLcode Curl_protocol_connect(struct connectdata *conn, bool *done);
|
||||
CURLcode Curl_protocol_connecting(struct connectdata *conn, bool *done);
|
||||
@ -58,6 +57,8 @@ CURLcode Curl_addHandleToPipeline(struct SessionHandle *handle,
|
||||
struct curl_llist *pipeline);
|
||||
int Curl_removeHandleFromPipeline(struct SessionHandle *handle,
|
||||
struct curl_llist *pipeline);
|
||||
struct connectdata *
|
||||
Curl_oldest_idle_connection(struct SessionHandle *data);
|
||||
/* remove the specified connection from all (possible) pipelines and related
|
||||
queues */
|
||||
void Curl_getoff_all_pipelines(struct SessionHandle *data,
|
||||
|
Loading…
Reference in New Issue
Block a user