Newer
Older
res = Curl_connect_host(data, &conn); /* primary connection */
if(res == CURLE_OK) {
if (data->set.source_host) /* 3rd party transfer */
res = Curl_pretransfersec(conn);
else
conn->sec_conn = NULL;
}
if(res == CURLE_OK) {
res = Curl_do(&conn);
/* for non 3rd party transfer only */
if(res == CURLE_OK && !data->set.source_host) {
res = Transfer(conn); /* now fetch that URL please */
if(res == CURLE_OK) {
Daniel Stenberg
committed
if((conn->keep.bytecount+conn->headerbytecount == 0) &&
conn->bits.reuse) {
Daniel Stenberg
committed
/* We got no data and we attempted to re-use a connection. This
might happen if the connection was left alive when we were done
using it before, but that was closed when we wanted to read
from it again. Bad luck. Retry the same request on a fresh
connect! */
infof(data, "Connection died, retrying a fresh connect\n");
newurl = strdup(conn->data->change.url);
conn->bits.close = TRUE; /* close this connection */
conn->bits.retry = TRUE; /* mark this as a connection we're about
to retry. Marking it this way should
prevent i.e HTTP transfers to return
error just because nothing has been
transfered! */
}
else
/*
* We must duplicate the new URL here as the connection data
* may be free()ed in the Curl_done() function.
*/
newurl = conn->newurl?strdup(conn->newurl):NULL;
}
Daniel Stenberg
committed
else {
/* The transfer phase returned error, we mark the connection to get
* closed to prevent being re-used. This is becasue we can't
* possibly know if the connection is in a good shape or not now. */
conn->bits.close = TRUE;
Daniel Stenberg
committed
Daniel Stenberg
committed
if(CURL_SOCKET_BAD != conn->sock[SECONDARYSOCKET]) {
Daniel Stenberg
committed
/* if we failed anywhere, we must clean up the secondary socket if
it was used */
Daniel Stenberg
committed
sclose(conn->sock[SECONDARYSOCKET]);
Daniel Stenberg
committed
conn->sock[SECONDARYSOCKET] = CURL_SOCKET_BAD;
Daniel Stenberg
committed
}
}
Daniel Stenberg
committed
/* Always run Curl_done(), even if some of the previous calls
failed, but return the previous (original) error code */
Daniel Stenberg
committed
res2 = Curl_done(&conn, res);
Daniel Stenberg
committed
if(CURLE_OK == res)
res = res2;
Daniel Stenberg
committed
else
/* Curl_do() failed, clean up left-overs in the done-call */
Daniel Stenberg
committed
res2 = Curl_done(&conn, res);
Daniel Stenberg
committed
/*
* Important: 'conn' cannot be used here, since it may have been closed
* in 'Curl_done' or other functions.
*/
if((res == CURLE_OK) && newurl) {
res = Curl_follow(data, newurl);
if(CURLE_OK == res) {
newurl = NULL;
continue;
}
}
break; /* it only reaches here when this shouldn't loop */
} while(1); /* loop if Location: */
Daniel Stenberg
committed
if(newurl)
free(newurl);
/* run post-transfer uncondionally, 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_Transfer() is called to setup some basic properties for the upcoming
* transfer.
*/
Curl_Transfer(struct connectdata *c_conn, /* connection data */
int sockindex, /* socket index to read from or -1 */
curl_off_t size, /* -1 if unknown at this point */
bool getheader, /* TRUE if header parsing is wanted */
curl_off_t *bytecountp, /* return number of bytes read or NULL */
Daniel Stenberg
committed
int writesockindex, /* socket index to write to, it may very
well be the same we read from. -1
disables */
curl_off_t *writecountp /* return number of bytes written or
NULL */
)
{
struct connectdata *conn = (struct connectdata *)c_conn;
if(!conn)
return CURLE_BAD_FUNCTION_ARGUMENT;
curlassert((sockindex <= 1) && (sockindex >= -1));
/* now copy all input parameters */
conn->sockfd = sockindex==-1?
CURL_SOCKET_BAD:conn->sock[sockindex];
conn->bits.getheader = getheader;
conn->bytecountp = bytecountp;
conn->writesockfd = writesockindex==-1?
CURL_SOCKET_BAD:conn->sock[writesockindex];
conn->writebytecountp = writecountp;
return CURLE_OK;
}
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
/*
* Curl_pretransfersec() prepares the secondary connection (used for 3rd party
* FTP transfers).
*/
CURLcode Curl_pretransfersec(struct connectdata *conn)
{
CURLcode status = CURLE_OK;
struct SessionHandle *data = conn->data;
struct connectdata *sec_conn = NULL; /* secondary connection */
/* update data with source host options */
char *url = aprintf( "%s://%s/", conn->protostr, data->set.source_host);
if(!url)
return CURLE_OUT_OF_MEMORY;
if(data->change.url_alloc)
free(data->change.url);
data->change.url_alloc = TRUE;
data->change.url = url;
data->set.ftpport = data->set.source_port;
data->set.userpwd = data->set.source_userpwd;
/* secondary connection */
status = Curl_connect_host(data, &sec_conn);
if(CURLE_OK == status) {
sec_conn->data = data;
conn->sec_conn = sec_conn;
}
return status;
}