mirror of
https://github.com/moparisthebest/curl
synced 2024-12-21 23:58:49 -05:00
Curl_perfom: removed
Curl_perfom is no longer used anywhere since the always-multi commit
c43127414d
, and some related functions were used only from within
Curl_perfom.
This commit is contained in:
parent
e243d80dea
commit
32e8467a66
372
lib/transfer.c
372
lib/transfer.c
@ -1245,156 +1245,6 @@ long Curl_sleep_time(curl_off_t rate_bps, curl_off_t cur_rate_bps,
|
|||||||
return (long)rv;
|
return (long)rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Transfer()
|
|
||||||
*
|
|
||||||
* This function is what performs the actual transfer. It is capable of doing
|
|
||||||
* both ways simultaneously. The transfer must already have been setup by a
|
|
||||||
* call to Curl_setup_transfer().
|
|
||||||
*
|
|
||||||
* Note that headers are created in a preallocated buffer of a default size.
|
|
||||||
* That buffer can be enlarged on demand, but it is never shrunken again.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
static CURLcode
|
|
||||||
Transfer(struct connectdata *conn)
|
|
||||||
{
|
|
||||||
CURLcode result;
|
|
||||||
struct SessionHandle *data = conn->data;
|
|
||||||
struct SingleRequest *k = &data->req;
|
|
||||||
bool done=FALSE;
|
|
||||||
bool first=TRUE;
|
|
||||||
long timeout_ms;
|
|
||||||
int buffersize;
|
|
||||||
long totmp;
|
|
||||||
|
|
||||||
if((conn->sockfd == CURL_SOCKET_BAD) &&
|
|
||||||
(conn->writesockfd == CURL_SOCKET_BAD))
|
|
||||||
/* nothing to read, nothing to write, we're already OK! */
|
|
||||||
return CURLE_OK;
|
|
||||||
|
|
||||||
/* we want header and/or body, if neither then don't do this! */
|
|
||||||
if(!k->getheader && data->set.opt_no_body)
|
|
||||||
return CURLE_OK;
|
|
||||||
|
|
||||||
while(!done) {
|
|
||||||
curl_socket_t fd_read = conn->sockfd;
|
|
||||||
curl_socket_t fd_write = conn->writesockfd;
|
|
||||||
int keepon = k->keepon;
|
|
||||||
timeout_ms = 1000;
|
|
||||||
|
|
||||||
if(conn->waitfor) {
|
|
||||||
/* if waitfor is set, get the RECV and SEND bits from that but keep the
|
|
||||||
other bits */
|
|
||||||
keepon &= ~ (KEEP_RECV|KEEP_SEND);
|
|
||||||
keepon |= conn->waitfor & (KEEP_RECV|KEEP_SEND);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* limit-rate logic: if speed exceeds threshold, then do not include fd in
|
|
||||||
select set. The current speed is recalculated in each Curl_readwrite()
|
|
||||||
call */
|
|
||||||
if((keepon & KEEP_SEND) &&
|
|
||||||
(!data->set.max_send_speed ||
|
|
||||||
(data->progress.ulspeed < data->set.max_send_speed) )) {
|
|
||||||
k->keepon &= ~KEEP_SEND_HOLD;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if(data->set.upload && data->set.max_send_speed &&
|
|
||||||
(data->progress.ulspeed > data->set.max_send_speed) ) {
|
|
||||||
/* calculate upload rate-limitation timeout. */
|
|
||||||
buffersize = (int)(data->set.buffer_size ?
|
|
||||||
data->set.buffer_size : BUFSIZE);
|
|
||||||
totmp = Curl_sleep_time(data->set.max_send_speed,
|
|
||||||
data->progress.ulspeed, buffersize);
|
|
||||||
if(totmp < timeout_ms)
|
|
||||||
timeout_ms = totmp;
|
|
||||||
}
|
|
||||||
fd_write = CURL_SOCKET_BAD;
|
|
||||||
if(keepon & KEEP_SEND)
|
|
||||||
k->keepon |= KEEP_SEND_HOLD; /* hold it */
|
|
||||||
}
|
|
||||||
|
|
||||||
if((keepon & KEEP_RECV) &&
|
|
||||||
(!data->set.max_recv_speed ||
|
|
||||||
(data->progress.dlspeed < data->set.max_recv_speed)) ) {
|
|
||||||
k->keepon &= ~KEEP_RECV_HOLD;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if((!data->set.upload) && data->set.max_recv_speed &&
|
|
||||||
(data->progress.dlspeed > data->set.max_recv_speed)) {
|
|
||||||
/* Calculate download rate-limitation timeout. */
|
|
||||||
buffersize = (int)(data->set.buffer_size ?
|
|
||||||
data->set.buffer_size : BUFSIZE);
|
|
||||||
totmp = Curl_sleep_time(data->set.max_recv_speed,
|
|
||||||
data->progress.dlspeed, buffersize);
|
|
||||||
if(totmp < timeout_ms)
|
|
||||||
timeout_ms = totmp;
|
|
||||||
}
|
|
||||||
fd_read = CURL_SOCKET_BAD;
|
|
||||||
if(keepon & KEEP_RECV)
|
|
||||||
k->keepon |= KEEP_RECV_HOLD; /* hold it */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* pause logic. Don't check descriptors for paused connections */
|
|
||||||
if(k->keepon & KEEP_RECV_PAUSE)
|
|
||||||
fd_read = CURL_SOCKET_BAD;
|
|
||||||
if(k->keepon & KEEP_SEND_PAUSE)
|
|
||||||
fd_write = CURL_SOCKET_BAD;
|
|
||||||
|
|
||||||
/* The *_HOLD and *_PAUSE logic is necessary since even though there might
|
|
||||||
be no traffic during the select interval, we still call
|
|
||||||
Curl_readwrite() for the timeout case and if we limit transfer speed we
|
|
||||||
must make sure that this function doesn't transfer anything while in
|
|
||||||
HOLD status.
|
|
||||||
|
|
||||||
The no timeout for the first round is for the protocols for which data
|
|
||||||
has already been slurped off the socket and thus waiting for action
|
|
||||||
won't work since it'll wait even though there is already data present
|
|
||||||
to work with. */
|
|
||||||
if(first &&
|
|
||||||
((fd_read != CURL_SOCKET_BAD) || (fd_write != CURL_SOCKET_BAD)))
|
|
||||||
/* if this is the first lap and one of the file descriptors is fine
|
|
||||||
to work with, skip the timeout */
|
|
||||||
timeout_ms = 0;
|
|
||||||
else {
|
|
||||||
totmp = Curl_timeleft(data, &k->now, FALSE);
|
|
||||||
if(totmp < 0)
|
|
||||||
return CURLE_OPERATION_TIMEDOUT;
|
|
||||||
else if(!totmp)
|
|
||||||
totmp = 1000;
|
|
||||||
|
|
||||||
if(totmp < timeout_ms)
|
|
||||||
timeout_ms = totmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (Curl_socket_ready(fd_read, fd_write, timeout_ms)) {
|
|
||||||
case -1: /* select() error, stop reading */
|
|
||||||
#ifdef EINTR
|
|
||||||
/* The EINTR is not serious, and it seems you might get this more
|
|
||||||
often when using the lib in a multi-threaded environment! */
|
|
||||||
if(SOCKERRNO == EINTR)
|
|
||||||
continue;
|
|
||||||
#endif
|
|
||||||
return CURLE_RECV_ERROR; /* indicate a network problem */
|
|
||||||
case 0: /* timeout */
|
|
||||||
default: /* readable descriptors */
|
|
||||||
|
|
||||||
result = Curl_readwrite(conn, &done);
|
|
||||||
/* "done" signals to us if the transfer(s) are ready */
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if(result)
|
|
||||||
return result;
|
|
||||||
|
|
||||||
first = FALSE; /* not the first lap anymore */
|
|
||||||
}
|
|
||||||
|
|
||||||
return CURLE_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Curl_pretransfer() is called immediately before a transfer starts.
|
* Curl_pretransfer() is called immediately before a transfer starts.
|
||||||
*/
|
*/
|
||||||
@ -1925,38 +1775,6 @@ CURLcode Curl_follow(struct SessionHandle *data,
|
|||||||
#endif /* CURL_DISABLE_HTTP */
|
#endif /* CURL_DISABLE_HTTP */
|
||||||
}
|
}
|
||||||
|
|
||||||
static CURLcode
|
|
||||||
connect_host(struct SessionHandle *data,
|
|
||||||
struct connectdata **conn)
|
|
||||||
{
|
|
||||||
CURLcode res = CURLE_OK;
|
|
||||||
|
|
||||||
bool async;
|
|
||||||
bool protocol_done=TRUE; /* will be TRUE always since this is only used
|
|
||||||
within the easy interface */
|
|
||||||
Curl_pgrsTime(data, TIMER_STARTSINGLE);
|
|
||||||
res = Curl_connect(data, conn, &async, &protocol_done);
|
|
||||||
|
|
||||||
if((CURLE_OK == res) && async) {
|
|
||||||
/* Now, if async is TRUE here, we need to wait for the name
|
|
||||||
to resolve */
|
|
||||||
res = Curl_resolver_wait_resolv(*conn, NULL);
|
|
||||||
if(CURLE_OK == res) {
|
|
||||||
/* Resolved, continue with the connection */
|
|
||||||
res = Curl_async_resolved(*conn, &protocol_done);
|
|
||||||
if(res)
|
|
||||||
*conn = NULL;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
/* if we can't resolve, we kill this "connection" now */
|
|
||||||
(void)Curl_disconnect(*conn, /* dead_connection */ FALSE);
|
|
||||||
*conn = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
CURLcode
|
CURLcode
|
||||||
Curl_reconnect_request(struct connectdata **connp)
|
Curl_reconnect_request(struct connectdata **connp)
|
||||||
{
|
{
|
||||||
@ -2060,196 +1878,6 @@ CURLcode Curl_retry_request(struct connectdata *conn,
|
|||||||
return CURLE_OK;
|
return CURLE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static CURLcode Curl_do_perform(struct SessionHandle *data)
|
|
||||||
{
|
|
||||||
CURLcode res;
|
|
||||||
CURLcode res2;
|
|
||||||
struct connectdata *conn=NULL;
|
|
||||||
char *newurl = NULL; /* possibly a new URL to follow to! */
|
|
||||||
followtype follow = FOLLOW_NONE;
|
|
||||||
|
|
||||||
res = Curl_pretransfer(data);
|
|
||||||
if(res)
|
|
||||||
return res;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* It is important that there is NO 'return' from this function at any other
|
|
||||||
* place than falling down to the end of the function! This is because we
|
|
||||||
* have cleanup stuff that must be done before we get back, and that is only
|
|
||||||
* performed after this do-while loop.
|
|
||||||
*/
|
|
||||||
|
|
||||||
for(;;) {
|
|
||||||
res = connect_host(data, &conn); /* primary connection */
|
|
||||||
|
|
||||||
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, FALSE);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
res = Curl_do(&conn, &do_done);
|
|
||||||
|
|
||||||
if(res == CURLE_OK) {
|
|
||||||
if(conn->data->set.wildcardmatch) {
|
|
||||||
if(conn->data->wildcard.state == CURLWC_DONE ||
|
|
||||||
conn->data->wildcard.state == CURLWC_SKIP) {
|
|
||||||
/* keep connection open for application to use the socket */
|
|
||||||
conn->bits.close = FALSE;
|
|
||||||
res = Curl_done(&conn, CURLE_OK, FALSE);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
res = Transfer(conn); /* now fetch that URL please */
|
|
||||||
if((res == CURLE_OK) || (res == CURLE_RECV_ERROR)) {
|
|
||||||
bool retry = FALSE;
|
|
||||||
CURLcode rc = Curl_retry_request(conn, &newurl);
|
|
||||||
if(rc)
|
|
||||||
res = rc;
|
|
||||||
else
|
|
||||||
retry = (newurl?TRUE:FALSE);
|
|
||||||
|
|
||||||
if(retry) {
|
|
||||||
/* we know (newurl != NULL) at this point */
|
|
||||||
res = CURLE_OK;
|
|
||||||
follow = FOLLOW_RETRY;
|
|
||||||
}
|
|
||||||
else if(res == CURLE_OK) {
|
|
||||||
/*
|
|
||||||
* We must duplicate the new URL here as the connection data may
|
|
||||||
* be free()ed in the Curl_done() function. We prefer the newurl
|
|
||||||
* one since that's used for redirects or just further requests
|
|
||||||
* for retries or multi-stage HTTP auth methods etc.
|
|
||||||
*/
|
|
||||||
if(data->req.newurl) {
|
|
||||||
follow = FOLLOW_REDIR;
|
|
||||||
newurl = strdup(data->req.newurl);
|
|
||||||
if(!newurl)
|
|
||||||
res = CURLE_OUT_OF_MEMORY;
|
|
||||||
}
|
|
||||||
else if(data->req.location) {
|
|
||||||
follow = FOLLOW_FAKE;
|
|
||||||
newurl = strdup(data->req.location);
|
|
||||||
if(!newurl)
|
|
||||||
res = CURLE_OUT_OF_MEMORY;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* in the above cases where 'newurl' gets assigned, we have a fresh
|
|
||||||
* allocated memory pointed to */
|
|
||||||
}
|
|
||||||
if(res != CURLE_OK) {
|
|
||||||
/* The transfer phase returned error, we mark the connection to get
|
|
||||||
* closed to prevent being re-used. This is because we can't
|
|
||||||
* possibly know if the connection is in a good shape or not now. */
|
|
||||||
conn->bits.close = TRUE;
|
|
||||||
|
|
||||||
if(CURL_SOCKET_BAD != conn->sock[SECONDARYSOCKET]) {
|
|
||||||
/* if we failed anywhere, we must clean up the secondary socket if
|
|
||||||
it was used */
|
|
||||||
Curl_closesocket(conn, conn->sock[SECONDARYSOCKET]);
|
|
||||||
conn->sock[SECONDARYSOCKET] = CURL_SOCKET_BAD;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Always run Curl_done(), even if some of the previous calls
|
|
||||||
failed, but return the previous (original) error code */
|
|
||||||
res2 = Curl_done(&conn, res, FALSE);
|
|
||||||
|
|
||||||
if(CURLE_OK == res)
|
|
||||||
res = res2;
|
|
||||||
}
|
|
||||||
else if(conn)
|
|
||||||
/* Curl_do() failed, clean up left-overs in the done-call, but note
|
|
||||||
that at some cases the conn pointer is NULL when Curl_do() failed
|
|
||||||
and the connection cache is very small so only call Curl_done() if
|
|
||||||
conn is still "alive". */
|
|
||||||
/* ignore return code since we already have an error to return */
|
|
||||||
(void)Curl_done(&conn, res, FALSE);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Important: 'conn' cannot be used here, since it may have been closed
|
|
||||||
* in 'Curl_done' or other functions.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if((res == CURLE_OK) && follow) {
|
|
||||||
res = Curl_follow(data, newurl, follow);
|
|
||||||
if(CURLE_OK == res) {
|
|
||||||
/* if things went fine, Curl_follow() freed or otherwise took
|
|
||||||
responsibility for the newurl pointer */
|
|
||||||
newurl = NULL;
|
|
||||||
if(follow >= FOLLOW_RETRY) {
|
|
||||||
follow = FOLLOW_NONE;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
/* else we break out of the loop below */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break; /* it only reaches here when this shouldn't loop */
|
|
||||||
|
|
||||||
} /* loop if Location: */
|
|
||||||
|
|
||||||
if(newurl)
|
|
||||||
free(newurl);
|
|
||||||
|
|
||||||
if(res && !data->state.errorbuf) {
|
|
||||||
/*
|
|
||||||
* As an extra precaution: if no error string has been set and there was
|
|
||||||
* an error, use the strerror() string or if things are so bad that not
|
|
||||||
* even that is good, set a bad string that mentions the error code.
|
|
||||||
*/
|
|
||||||
const char *str = curl_easy_strerror(res);
|
|
||||||
if(!str)
|
|
||||||
failf(data, "unspecified error %d", (int)res);
|
|
||||||
else
|
|
||||||
failf(data, "%s", str);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* run post-transfer unconditionally, but don't clobber the return code if
|
|
||||||
we already have an error code recorder */
|
|
||||||
res2 = Curl_posttransfer(data);
|
|
||||||
if(!res && res2)
|
|
||||||
res = res2;
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Curl_perform() is the internal high-level function that gets called by the
|
|
||||||
* external curl_easy_perform() function. It inits, performs and cleans up a
|
|
||||||
* single file transfer.
|
|
||||||
*/
|
|
||||||
CURLcode Curl_perform(struct SessionHandle *data)
|
|
||||||
{
|
|
||||||
CURLcode res;
|
|
||||||
if(!data->set.wildcardmatch)
|
|
||||||
return Curl_do_perform(data);
|
|
||||||
|
|
||||||
/* init main wildcard structures */
|
|
||||||
res = Curl_wildcard_init(&data->wildcard);
|
|
||||||
if(res)
|
|
||||||
return res;
|
|
||||||
|
|
||||||
res = Curl_do_perform(data);
|
|
||||||
if(res) {
|
|
||||||
Curl_wildcard_dtor(&data->wildcard);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* wildcard loop */
|
|
||||||
while(!res && data->wildcard.state != CURLWC_DONE)
|
|
||||||
res = Curl_do_perform(data);
|
|
||||||
|
|
||||||
Curl_wildcard_dtor(&data->wildcard);
|
|
||||||
|
|
||||||
/* wildcard download finished or failed */
|
|
||||||
data->wildcard.state = CURLWC_INIT;
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Curl_setup_transfer() is called to setup some basic properties for the
|
* Curl_setup_transfer() is called to setup some basic properties for the
|
||||||
* upcoming transfer.
|
* upcoming transfer.
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* | (__| |_| | _ <| |___
|
* | (__| |_| | _ <| |___
|
||||||
* \___|\___/|_| \_\_____|
|
* \___|\___/|_| \_\_____|
|
||||||
*
|
*
|
||||||
* Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
|
* Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||||
*
|
*
|
||||||
* This software is licensed as described in the file COPYING, which
|
* This software is licensed as described in the file COPYING, which
|
||||||
* you should have received as part of this distribution. The terms
|
* you should have received as part of this distribution. The terms
|
||||||
@ -21,7 +21,7 @@
|
|||||||
* KIND, either express or implied.
|
* KIND, either express or implied.
|
||||||
*
|
*
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
CURLcode Curl_perform(struct SessionHandle *data);
|
|
||||||
CURLcode Curl_pretransfer(struct SessionHandle *data);
|
CURLcode Curl_pretransfer(struct SessionHandle *data);
|
||||||
CURLcode Curl_second_connect(struct connectdata *conn);
|
CURLcode Curl_second_connect(struct connectdata *conn);
|
||||||
CURLcode Curl_posttransfer(struct SessionHandle *data);
|
CURLcode Curl_posttransfer(struct SessionHandle *data);
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* | (__| |_| | _ <| |___
|
* | (__| |_| | _ <| |___
|
||||||
* \___|\___/|_| \_\_____|
|
* \___|\___/|_| \_\_____|
|
||||||
*
|
*
|
||||||
* Copyright (C) 2010, Daniel Stenberg, <daniel@haxx.se>, et al.
|
* Copyright (C) 2010 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||||
*
|
*
|
||||||
* This software is licensed as described in the file COPYING, which
|
* This software is licensed as described in the file COPYING, which
|
||||||
* you should have received as part of this distribution. The terms
|
* you should have received as part of this distribution. The terms
|
||||||
@ -33,8 +33,8 @@ typedef enum {
|
|||||||
CURLWC_CLEAN, /* deallocate resources and reset settings */
|
CURLWC_CLEAN, /* deallocate resources and reset settings */
|
||||||
CURLWC_SKIP, /* skip over concrete file */
|
CURLWC_SKIP, /* skip over concrete file */
|
||||||
CURLWC_ERROR, /* error cases */
|
CURLWC_ERROR, /* error cases */
|
||||||
CURLWC_DONE /* if is wildcard->state == CURLWC_DONE wildcard loop in
|
CURLWC_DONE /* if is wildcard->state == CURLWC_DONE wildcard loop
|
||||||
Curl_perform() will end */
|
will end */
|
||||||
} curl_wildcard_states;
|
} curl_wildcard_states;
|
||||||
|
|
||||||
typedef void (*curl_wildcard_tmp_dtor)(void *ptr);
|
typedef void (*curl_wildcard_tmp_dtor)(void *ptr);
|
||||||
|
Loading…
Reference in New Issue
Block a user