mirror of
https://github.com/moparisthebest/curl
synced 2024-12-21 23:58:49 -05:00
multi: use timeouts properly for MAX_RECV/SEND_SPEED
When detecting that the send or recv speed, the multi interface changes state to TOOFAST and previously there was no timeout set that would force a recheck but it would rely on the application to somehow call libcurl anyway. This now sets a timeout for a suitable future time to check again if the average transfer speed is then below the threshold again.
This commit is contained in:
parent
232ad6549a
commit
9124bfba45
163
lib/multi.c
163
lib/multi.c
@ -934,10 +934,13 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
|||||||
bool done = FALSE;
|
bool done = FALSE;
|
||||||
CURLMcode result = CURLM_OK;
|
CURLMcode result = CURLM_OK;
|
||||||
struct SingleRequest *k;
|
struct SingleRequest *k;
|
||||||
|
struct SessionHandle *data;
|
||||||
|
|
||||||
if(!GOOD_EASY_HANDLE(easy->easy_handle))
|
if(!GOOD_EASY_HANDLE(easy->easy_handle))
|
||||||
return CURLM_BAD_EASY_HANDLE;
|
return CURLM_BAD_EASY_HANDLE;
|
||||||
|
|
||||||
|
data = easy->easy_handle;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
/* this is a do-while loop just to allow a break to skip to the end
|
/* this is a do-while loop just to allow a break to skip to the end
|
||||||
of it */
|
of it */
|
||||||
@ -945,9 +948,9 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
|||||||
|
|
||||||
/* Handle the case when the pipe breaks, i.e., the connection
|
/* Handle the case when the pipe breaks, i.e., the connection
|
||||||
we're using gets cleaned up and we're left with nothing. */
|
we're using gets cleaned up and we're left with nothing. */
|
||||||
if(easy->easy_handle->state.pipe_broke) {
|
if(data->state.pipe_broke) {
|
||||||
infof(easy->easy_handle, "Pipe broke: handle 0x%p, url = %s\n",
|
infof(data, "Pipe broke: handle 0x%p, url = %s\n",
|
||||||
easy, easy->easy_handle->state.path);
|
easy, data->state.path);
|
||||||
|
|
||||||
if(easy->state != CURLM_STATE_COMPLETED) {
|
if(easy->state != CURLM_STATE_COMPLETED) {
|
||||||
/* Head back to the CONNECT state */
|
/* Head back to the CONNECT state */
|
||||||
@ -956,7 +959,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
|||||||
easy->result = CURLE_OK;
|
easy->result = CURLE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
easy->easy_handle->state.pipe_broke = FALSE;
|
data->state.pipe_broke = FALSE;
|
||||||
easy->easy_conn = NULL;
|
easy->easy_conn = NULL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -964,31 +967,31 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
|||||||
if(easy->easy_conn && easy->state > CURLM_STATE_CONNECT &&
|
if(easy->easy_conn && easy->state > CURLM_STATE_CONNECT &&
|
||||||
easy->state < CURLM_STATE_COMPLETED)
|
easy->state < CURLM_STATE_COMPLETED)
|
||||||
/* Make sure we set the connection's current owner */
|
/* Make sure we set the connection's current owner */
|
||||||
easy->easy_conn->data = easy->easy_handle;
|
easy->easy_conn->data = data;
|
||||||
|
|
||||||
switch(easy->state) {
|
switch(easy->state) {
|
||||||
case CURLM_STATE_INIT:
|
case CURLM_STATE_INIT:
|
||||||
/* init this transfer. */
|
/* init this transfer. */
|
||||||
easy->result=Curl_pretransfer(easy->easy_handle);
|
easy->result=Curl_pretransfer(data);
|
||||||
|
|
||||||
if(CURLE_OK == easy->result) {
|
if(CURLE_OK == easy->result) {
|
||||||
/* after init, go CONNECT */
|
/* after init, go CONNECT */
|
||||||
multistate(easy, CURLM_STATE_CONNECT);
|
multistate(easy, CURLM_STATE_CONNECT);
|
||||||
result = CURLM_CALL_MULTI_PERFORM;
|
result = CURLM_CALL_MULTI_PERFORM;
|
||||||
|
|
||||||
easy->easy_handle->state.used_interface = Curl_if_multi;
|
data->state.used_interface = Curl_if_multi;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CURLM_STATE_CONNECT:
|
case CURLM_STATE_CONNECT:
|
||||||
/* Connect. We get a connection identifier filled in. */
|
/* Connect. We get a connection identifier filled in. */
|
||||||
Curl_pgrsTime(easy->easy_handle, TIMER_STARTSINGLE);
|
Curl_pgrsTime(data, TIMER_STARTSINGLE);
|
||||||
easy->result = Curl_connect(easy->easy_handle, &easy->easy_conn,
|
easy->result = Curl_connect(data, &easy->easy_conn,
|
||||||
&async, &protocol_connect);
|
&async, &protocol_connect);
|
||||||
|
|
||||||
if(CURLE_OK == easy->result) {
|
if(CURLE_OK == easy->result) {
|
||||||
/* Add this handle to the send or pend pipeline */
|
/* Add this handle to the send or pend pipeline */
|
||||||
easy->result = addHandleToSendOrPendPipeline(easy->easy_handle,
|
easy->result = addHandleToSendOrPendPipeline(data,
|
||||||
easy->easy_conn);
|
easy->easy_conn);
|
||||||
if(CURLE_OK == easy->result) {
|
if(CURLE_OK == easy->result) {
|
||||||
if(async)
|
if(async)
|
||||||
@ -1071,9 +1074,9 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
|||||||
|
|
||||||
if(easy->easy_conn->bits.proxy_connect_closed) {
|
if(easy->easy_conn->bits.proxy_connect_closed) {
|
||||||
/* reset the error buffer */
|
/* reset the error buffer */
|
||||||
if(easy->easy_handle->set.errorbuffer)
|
if(data->set.errorbuffer)
|
||||||
easy->easy_handle->set.errorbuffer[0] = '\0';
|
data->set.errorbuffer[0] = '\0';
|
||||||
easy->easy_handle->state.errorbuf = FALSE;
|
data->state.errorbuf = FALSE;
|
||||||
|
|
||||||
easy->result = CURLE_OK;
|
easy->result = CURLE_OK;
|
||||||
result = CURLM_CALL_MULTI_PERFORM;
|
result = CURLM_CALL_MULTI_PERFORM;
|
||||||
@ -1145,7 +1148,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
|||||||
}
|
}
|
||||||
else if(easy->result) {
|
else if(easy->result) {
|
||||||
/* failure detected */
|
/* failure detected */
|
||||||
Curl_posttransfer(easy->easy_handle);
|
Curl_posttransfer(data);
|
||||||
Curl_done(&easy->easy_conn, easy->result, FALSE);
|
Curl_done(&easy->easy_conn, easy->result, FALSE);
|
||||||
disconnect_conn = TRUE;
|
disconnect_conn = TRUE;
|
||||||
}
|
}
|
||||||
@ -1154,15 +1157,15 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
|||||||
case CURLM_STATE_WAITDO:
|
case CURLM_STATE_WAITDO:
|
||||||
/* Wait for our turn to DO when we're pipelining requests */
|
/* Wait for our turn to DO when we're pipelining requests */
|
||||||
#ifdef DEBUGBUILD
|
#ifdef DEBUGBUILD
|
||||||
infof(easy->easy_handle, "Conn %ld send pipe %zu inuse %d athead %d\n",
|
infof(data, "Conn %ld send pipe %zu inuse %d athead %d\n",
|
||||||
easy->easy_conn->connectindex,
|
easy->easy_conn->connectindex,
|
||||||
easy->easy_conn->send_pipe->size,
|
easy->easy_conn->send_pipe->size,
|
||||||
easy->easy_conn->writechannel_inuse?1:0,
|
easy->easy_conn->writechannel_inuse?1:0,
|
||||||
isHandleAtHead(easy->easy_handle,
|
isHandleAtHead(data,
|
||||||
easy->easy_conn->send_pipe)?1:0);
|
easy->easy_conn->send_pipe)?1:0);
|
||||||
#endif
|
#endif
|
||||||
if(!easy->easy_conn->writechannel_inuse &&
|
if(!easy->easy_conn->writechannel_inuse &&
|
||||||
isHandleAtHead(easy->easy_handle,
|
isHandleAtHead(data,
|
||||||
easy->easy_conn->send_pipe)) {
|
easy->easy_conn->send_pipe)) {
|
||||||
/* Grab the channel */
|
/* Grab the channel */
|
||||||
easy->easy_conn->writechannel_inuse = TRUE;
|
easy->easy_conn->writechannel_inuse = TRUE;
|
||||||
@ -1172,7 +1175,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case CURLM_STATE_DO:
|
case CURLM_STATE_DO:
|
||||||
if(easy->easy_handle->set.connect_only) {
|
if(data->set.connect_only) {
|
||||||
/* keep connection open for application to use the socket */
|
/* keep connection open for application to use the socket */
|
||||||
easy->easy_conn->bits.close = FALSE;
|
easy->easy_conn->bits.close = FALSE;
|
||||||
multistate(easy, CURLM_STATE_DONE);
|
multistate(easy, CURLM_STATE_DONE);
|
||||||
@ -1187,8 +1190,8 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
|||||||
if(CURLE_OK == easy->result) {
|
if(CURLE_OK == easy->result) {
|
||||||
if(!dophase_done) {
|
if(!dophase_done) {
|
||||||
/* some steps needed for wildcard matching */
|
/* some steps needed for wildcard matching */
|
||||||
if(easy->easy_handle->set.wildcardmatch) {
|
if(data->set.wildcardmatch) {
|
||||||
struct WildcardData *wc = &easy->easy_handle->wildcard;
|
struct WildcardData *wc = &data->wildcard;
|
||||||
if(wc->state == CURLWC_DONE || wc->state == CURLWC_SKIP) {
|
if(wc->state == CURLWC_DONE || wc->state == CURLWC_SKIP) {
|
||||||
/* skip some states if it is important */
|
/* skip some states if it is important */
|
||||||
Curl_done(&easy->easy_conn, CURLE_OK, FALSE);
|
Curl_done(&easy->easy_conn, CURLE_OK, FALSE);
|
||||||
@ -1237,7 +1240,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
|||||||
else
|
else
|
||||||
retry = (bool)(newurl?TRUE:FALSE);
|
retry = (bool)(newurl?TRUE:FALSE);
|
||||||
|
|
||||||
Curl_posttransfer(easy->easy_handle);
|
Curl_posttransfer(data);
|
||||||
drc = Curl_done(&easy->easy_conn, easy->result, FALSE);
|
drc = Curl_done(&easy->easy_conn, easy->result, FALSE);
|
||||||
|
|
||||||
/* When set to retry the connection, we must to go back to
|
/* When set to retry the connection, we must to go back to
|
||||||
@ -1245,7 +1248,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
|||||||
if(retry) {
|
if(retry) {
|
||||||
if ((drc == CURLE_OK) || (drc == CURLE_SEND_ERROR)) {
|
if ((drc == CURLE_OK) || (drc == CURLE_SEND_ERROR)) {
|
||||||
follow = FOLLOW_RETRY;
|
follow = FOLLOW_RETRY;
|
||||||
drc = Curl_follow(easy->easy_handle, newurl, follow);
|
drc = Curl_follow(data, newurl, follow);
|
||||||
if(drc == CURLE_OK) {
|
if(drc == CURLE_OK) {
|
||||||
multistate(easy, CURLM_STATE_CONNECT);
|
multistate(easy, CURLM_STATE_CONNECT);
|
||||||
result = CURLM_CALL_MULTI_PERFORM;
|
result = CURLM_CALL_MULTI_PERFORM;
|
||||||
@ -1270,7 +1273,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* failure detected */
|
/* failure detected */
|
||||||
Curl_posttransfer(easy->easy_handle);
|
Curl_posttransfer(data);
|
||||||
Curl_done(&easy->easy_conn, easy->result, FALSE);
|
Curl_done(&easy->easy_conn, easy->result, FALSE);
|
||||||
disconnect_conn = TRUE;
|
disconnect_conn = TRUE;
|
||||||
}
|
}
|
||||||
@ -1299,7 +1302,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* failure detected */
|
/* failure detected */
|
||||||
Curl_posttransfer(easy->easy_handle);
|
Curl_posttransfer(data);
|
||||||
Curl_done(&easy->easy_conn, easy->result, FALSE);
|
Curl_done(&easy->easy_conn, easy->result, FALSE);
|
||||||
disconnect_conn = TRUE;
|
disconnect_conn = TRUE;
|
||||||
}
|
}
|
||||||
@ -1325,7 +1328,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* failure detected */
|
/* failure detected */
|
||||||
Curl_posttransfer(easy->easy_handle);
|
Curl_posttransfer(data);
|
||||||
Curl_done(&easy->easy_conn, easy->result, FALSE);
|
Curl_done(&easy->easy_conn, easy->result, FALSE);
|
||||||
disconnect_conn = TRUE;
|
disconnect_conn = TRUE;
|
||||||
}
|
}
|
||||||
@ -1334,7 +1337,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
|||||||
|
|
||||||
case CURLM_STATE_DO_DONE:
|
case CURLM_STATE_DO_DONE:
|
||||||
/* Move ourselves from the send to recv pipeline */
|
/* Move ourselves from the send to recv pipeline */
|
||||||
moveHandleFromSendToRecvPipeline(easy->easy_handle, easy->easy_conn);
|
moveHandleFromSendToRecvPipeline(data, easy->easy_conn);
|
||||||
/* Check if we can move pending requests to send pipe */
|
/* Check if we can move pending requests to send pipe */
|
||||||
checkPendPipeline(easy->easy_conn);
|
checkPendPipeline(easy->easy_conn);
|
||||||
multistate(easy, CURLM_STATE_WAITPERFORM);
|
multistate(easy, CURLM_STATE_WAITPERFORM);
|
||||||
@ -1344,7 +1347,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
|||||||
case CURLM_STATE_WAITPERFORM:
|
case CURLM_STATE_WAITPERFORM:
|
||||||
/* Wait for our turn to PERFORM */
|
/* Wait for our turn to PERFORM */
|
||||||
if(!easy->easy_conn->readchannel_inuse &&
|
if(!easy->easy_conn->readchannel_inuse &&
|
||||||
isHandleAtHead(easy->easy_handle,
|
isHandleAtHead(data,
|
||||||
easy->easy_conn->recv_pipe)) {
|
easy->easy_conn->recv_pipe)) {
|
||||||
/* Grab the channel */
|
/* Grab the channel */
|
||||||
easy->easy_conn->readchannel_inuse = TRUE;
|
easy->easy_conn->readchannel_inuse = TRUE;
|
||||||
@ -1353,11 +1356,11 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
|||||||
}
|
}
|
||||||
#ifdef DEBUGBUILD
|
#ifdef DEBUGBUILD
|
||||||
else {
|
else {
|
||||||
infof(easy->easy_handle, "Conn %ld recv pipe %zu inuse %d athead %d\n",
|
infof(data, "Conn %ld recv pipe %zu inuse %d athead %d\n",
|
||||||
easy->easy_conn->connectindex,
|
easy->easy_conn->connectindex,
|
||||||
easy->easy_conn->recv_pipe->size,
|
easy->easy_conn->recv_pipe->size,
|
||||||
easy->easy_conn->readchannel_inuse?1:0,
|
easy->easy_conn->readchannel_inuse?1:0,
|
||||||
isHandleAtHead(easy->easy_handle,
|
isHandleAtHead(data,
|
||||||
easy->easy_conn->recv_pipe)?1:0);
|
easy->easy_conn->recv_pipe)?1:0);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -1365,36 +1368,52 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
|||||||
|
|
||||||
case CURLM_STATE_TOOFAST: /* limit-rate exceeded in either direction */
|
case CURLM_STATE_TOOFAST: /* limit-rate exceeded in either direction */
|
||||||
/* if both rates are within spec, resume transfer */
|
/* if both rates are within spec, resume transfer */
|
||||||
if( ( ( easy->easy_handle->set.max_send_speed == 0 ) ||
|
if( ( (data->set.max_send_speed == 0) ||
|
||||||
( easy->easy_handle->progress.ulspeed <
|
(data->progress.ulspeed < data->set.max_send_speed )) &&
|
||||||
easy->easy_handle->set.max_send_speed ) ) &&
|
( (data->set.max_recv_speed == 0) ||
|
||||||
( ( easy->easy_handle->set.max_recv_speed == 0 ) ||
|
(data->progress.dlspeed < data->set.max_recv_speed) ) )
|
||||||
( easy->easy_handle->progress.dlspeed <
|
|
||||||
easy->easy_handle->set.max_recv_speed ) )
|
|
||||||
)
|
|
||||||
multistate(easy, CURLM_STATE_PERFORM);
|
multistate(easy, CURLM_STATE_PERFORM);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CURLM_STATE_PERFORM:
|
case CURLM_STATE_PERFORM:
|
||||||
/* check if over speed */
|
/* check if over send speed */
|
||||||
if( ( ( easy->easy_handle->set.max_send_speed > 0 ) &&
|
if( (data->set.max_send_speed > 0) &&
|
||||||
( easy->easy_handle->progress.ulspeed >
|
(data->progress.ulspeed > data->set.max_send_speed) ) {
|
||||||
easy->easy_handle->set.max_send_speed ) ) ||
|
int buffersize;
|
||||||
( ( easy->easy_handle->set.max_recv_speed > 0 ) &&
|
long timeout_ms;
|
||||||
( easy->easy_handle->progress.dlspeed >
|
|
||||||
easy->easy_handle->set.max_recv_speed ) )
|
multistate(easy, CURLM_STATE_TOOFAST);
|
||||||
) {
|
|
||||||
/* Transfer is over the speed limit. Change state. TODO: Call
|
/* calculate upload rate-limitation timeout. */
|
||||||
* Curl_expire() with the time left until we're targeted to be below
|
buffersize = (int)(data->set.buffer_size ?
|
||||||
* the speed limit again. */
|
data->set.buffer_size : BUFSIZE);
|
||||||
multistate(easy, CURLM_STATE_TOOFAST );
|
timeout_ms = Curl_sleep_time(data->set.max_send_speed,
|
||||||
|
data->progress.ulspeed, buffersize);
|
||||||
|
Curl_expire(data, timeout_ms);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check if over recv speed */
|
||||||
|
if( (data->set.max_recv_speed > 0) &&
|
||||||
|
(data->progress.dlspeed > data->set.max_recv_speed) ) {
|
||||||
|
int buffersize;
|
||||||
|
long timeout_ms;
|
||||||
|
|
||||||
|
multistate(easy, CURLM_STATE_TOOFAST);
|
||||||
|
|
||||||
|
/* Calculate download rate-limitation timeout. */
|
||||||
|
buffersize = (int)(data->set.buffer_size ?
|
||||||
|
data->set.buffer_size : BUFSIZE);
|
||||||
|
timeout_ms = Curl_sleep_time(data->set.max_recv_speed,
|
||||||
|
data->progress.dlspeed, buffersize);
|
||||||
|
Curl_expire(data, timeout_ms);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* read/write data if it is ready to do so */
|
/* read/write data if it is ready to do so */
|
||||||
easy->result = Curl_readwrite(easy->easy_conn, &done);
|
easy->result = Curl_readwrite(easy->easy_conn, &done);
|
||||||
|
|
||||||
k = &easy->easy_handle->req;
|
k = &data->req;
|
||||||
|
|
||||||
if(!(k->keepon & KEEP_RECV)) {
|
if(!(k->keepon & KEEP_RECV)) {
|
||||||
/* We're done receiving */
|
/* We're done receiving */
|
||||||
@ -1416,7 +1435,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
|||||||
if(!(easy->easy_conn->protocol & PROT_DUALCHANNEL))
|
if(!(easy->easy_conn->protocol & PROT_DUALCHANNEL))
|
||||||
easy->easy_conn->bits.close = TRUE;
|
easy->easy_conn->bits.close = TRUE;
|
||||||
|
|
||||||
Curl_posttransfer(easy->easy_handle);
|
Curl_posttransfer(data);
|
||||||
Curl_done(&easy->easy_conn, easy->result, FALSE);
|
Curl_done(&easy->easy_conn, easy->result, FALSE);
|
||||||
}
|
}
|
||||||
else if(TRUE == done) {
|
else if(TRUE == done) {
|
||||||
@ -1429,10 +1448,10 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
|||||||
retry = (bool)(newurl?TRUE:FALSE);
|
retry = (bool)(newurl?TRUE:FALSE);
|
||||||
|
|
||||||
/* call this even if the readwrite function returned error */
|
/* call this even if the readwrite function returned error */
|
||||||
Curl_posttransfer(easy->easy_handle);
|
Curl_posttransfer(data);
|
||||||
|
|
||||||
/* we're no longer receving */
|
/* we're no longer receving */
|
||||||
moveHandleFromRecvToDonePipeline(easy->easy_handle,
|
moveHandleFromRecvToDonePipeline(data,
|
||||||
easy->easy_conn);
|
easy->easy_conn);
|
||||||
|
|
||||||
/* expire the new receiving pipeline head */
|
/* expire the new receiving pipeline head */
|
||||||
@ -1444,19 +1463,19 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
|||||||
|
|
||||||
/* When we follow redirects or is set to retry the connection, we must
|
/* When we follow redirects or is set to retry the connection, we must
|
||||||
to go back to the CONNECT state */
|
to go back to the CONNECT state */
|
||||||
if(easy->easy_handle->req.newurl || retry) {
|
if(data->req.newurl || retry) {
|
||||||
if(!retry) {
|
if(!retry) {
|
||||||
/* if the URL is a follow-location and not just a retried request
|
/* if the URL is a follow-location and not just a retried request
|
||||||
then figure out the URL here */
|
then figure out the URL here */
|
||||||
newurl = easy->easy_handle->req.newurl;
|
newurl = data->req.newurl;
|
||||||
easy->easy_handle->req.newurl = NULL;
|
data->req.newurl = NULL;
|
||||||
follow = FOLLOW_REDIR;
|
follow = FOLLOW_REDIR;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
follow = FOLLOW_RETRY;
|
follow = FOLLOW_RETRY;
|
||||||
easy->result = Curl_done(&easy->easy_conn, CURLE_OK, FALSE);
|
easy->result = Curl_done(&easy->easy_conn, CURLE_OK, FALSE);
|
||||||
if(easy->result == CURLE_OK)
|
if(easy->result == CURLE_OK)
|
||||||
easy->result = Curl_follow(easy->easy_handle, newurl, follow);
|
easy->result = Curl_follow(data, newurl, follow);
|
||||||
if(CURLE_OK == easy->result) {
|
if(CURLE_OK == easy->result) {
|
||||||
multistate(easy, CURLM_STATE_CONNECT);
|
multistate(easy, CURLM_STATE_CONNECT);
|
||||||
result = CURLM_CALL_MULTI_PERFORM;
|
result = CURLM_CALL_MULTI_PERFORM;
|
||||||
@ -1471,10 +1490,10 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
|||||||
|
|
||||||
/* but first check to see if we got a location info even though we're
|
/* but first check to see if we got a location info even though we're
|
||||||
not following redirects */
|
not following redirects */
|
||||||
if (easy->easy_handle->req.location) {
|
if (data->req.location) {
|
||||||
newurl = easy->easy_handle->req.location;
|
newurl = data->req.location;
|
||||||
easy->easy_handle->req.location = NULL;
|
data->req.location = NULL;
|
||||||
easy->result = Curl_follow(easy->easy_handle, newurl, FOLLOW_FAKE);
|
easy->result = Curl_follow(data, newurl, FOLLOW_FAKE);
|
||||||
if (easy->result)
|
if (easy->result)
|
||||||
free(newurl);
|
free(newurl);
|
||||||
}
|
}
|
||||||
@ -1491,9 +1510,9 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
|||||||
if(easy->easy_conn) {
|
if(easy->easy_conn) {
|
||||||
/* Remove ourselves from the receive and done pipelines. Handle
|
/* Remove ourselves from the receive and done pipelines. Handle
|
||||||
should be on one of these lists, depending upon how we got here. */
|
should be on one of these lists, depending upon how we got here. */
|
||||||
Curl_removeHandleFromPipeline(easy->easy_handle,
|
Curl_removeHandleFromPipeline(data,
|
||||||
easy->easy_conn->recv_pipe);
|
easy->easy_conn->recv_pipe);
|
||||||
Curl_removeHandleFromPipeline(easy->easy_handle,
|
Curl_removeHandleFromPipeline(data,
|
||||||
easy->easy_conn->done_pipe);
|
easy->easy_conn->done_pipe);
|
||||||
/* Check if we can move pending requests to send pipe */
|
/* Check if we can move pending requests to send pipe */
|
||||||
checkPendPipeline(easy->easy_conn);
|
checkPendPipeline(easy->easy_conn);
|
||||||
@ -1517,8 +1536,8 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
|||||||
easy->easy_conn = NULL;
|
easy->easy_conn = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(easy->easy_handle->set.wildcardmatch) {
|
if(data->set.wildcardmatch) {
|
||||||
if(easy->easy_handle->wildcard.state != CURLWC_DONE) {
|
if(data->wildcard.state != CURLWC_DONE) {
|
||||||
/* if a wildcard is set and we are not ending -> lets start again
|
/* if a wildcard is set and we are not ending -> lets start again
|
||||||
with CURLM_STATE_INIT */
|
with CURLM_STATE_INIT */
|
||||||
result = CURLM_CALL_MULTI_PERFORM;
|
result = CURLM_CALL_MULTI_PERFORM;
|
||||||
@ -1558,17 +1577,17 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
|||||||
/* NOTE: no attempt to disconnect connections must be made
|
/* NOTE: no attempt to disconnect connections must be made
|
||||||
in the case blocks above - cleanup happens only here */
|
in the case blocks above - cleanup happens only here */
|
||||||
|
|
||||||
easy->easy_handle->state.pipe_broke = FALSE;
|
data->state.pipe_broke = FALSE;
|
||||||
|
|
||||||
if(easy->easy_conn) {
|
if(easy->easy_conn) {
|
||||||
/* if this has a connection, unsubscribe from the pipelines */
|
/* if this has a connection, unsubscribe from the pipelines */
|
||||||
easy->easy_conn->writechannel_inuse = FALSE;
|
easy->easy_conn->writechannel_inuse = FALSE;
|
||||||
easy->easy_conn->readchannel_inuse = FALSE;
|
easy->easy_conn->readchannel_inuse = FALSE;
|
||||||
Curl_removeHandleFromPipeline(easy->easy_handle,
|
Curl_removeHandleFromPipeline(data,
|
||||||
easy->easy_conn->send_pipe);
|
easy->easy_conn->send_pipe);
|
||||||
Curl_removeHandleFromPipeline(easy->easy_handle,
|
Curl_removeHandleFromPipeline(data,
|
||||||
easy->easy_conn->recv_pipe);
|
easy->easy_conn->recv_pipe);
|
||||||
Curl_removeHandleFromPipeline(easy->easy_handle,
|
Curl_removeHandleFromPipeline(data,
|
||||||
easy->easy_conn->done_pipe);
|
easy->easy_conn->done_pipe);
|
||||||
/* Check if we can move pending requests to send pipe */
|
/* Check if we can move pending requests to send pipe */
|
||||||
checkPendPipeline(easy->easy_conn);
|
checkPendPipeline(easy->easy_conn);
|
||||||
@ -1592,17 +1611,17 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
|||||||
} while(0);
|
} while(0);
|
||||||
|
|
||||||
if(CURLM_STATE_COMPLETED == easy->state) {
|
if(CURLM_STATE_COMPLETED == easy->state) {
|
||||||
if(easy->easy_handle->dns.hostcachetype == HCACHE_MULTI) {
|
if(data->dns.hostcachetype == HCACHE_MULTI) {
|
||||||
/* clear out the usage of the shared DNS cache */
|
/* clear out the usage of the shared DNS cache */
|
||||||
easy->easy_handle->dns.hostcache = NULL;
|
data->dns.hostcache = NULL;
|
||||||
easy->easy_handle->dns.hostcachetype = HCACHE_NONE;
|
data->dns.hostcachetype = HCACHE_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* now fill in the Curl_message with this info */
|
/* now fill in the Curl_message with this info */
|
||||||
msg = &easy->msg;
|
msg = &easy->msg;
|
||||||
|
|
||||||
msg->extmsg.msg = CURLMSG_DONE;
|
msg->extmsg.msg = CURLMSG_DONE;
|
||||||
msg->extmsg.easy_handle = easy->easy_handle;
|
msg->extmsg.easy_handle = data;
|
||||||
msg->extmsg.data.result = easy->result;
|
msg->extmsg.data.result = easy->result;
|
||||||
|
|
||||||
result = multi_addmsg(multi, msg);
|
result = multi_addmsg(multi, msg);
|
||||||
|
Loading…
Reference in New Issue
Block a user