Rearranged code and changed Curl_readwrite_init() and Curl_pre_readwrite() into

do_init() and do_complete() which now are called first and last in the DO
function. It simplified the flow in multi.c and the functions got more
sensible names!
This commit is contained in:
Daniel Stenberg 2007-11-15 21:45:45 +00:00
parent ca95f58ac0
commit 50feea3eef
8 changed files with 139 additions and 148 deletions

View File

@ -378,7 +378,6 @@ static CURLcode Curl_file(struct connectdata *conn, bool *done)
*done = TRUE; /* unconditionally */
Curl_readwrite_init(conn);
Curl_initinfo(data);
Curl_pgrsStartNow(data);

View File

@ -178,7 +178,7 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
if(*datap == 0x0a) {
/* we're now expecting data to come, unless size was zero! */
if(0 == ch->datasize) {
if(conn->bits.trailerHdrPresent!=TRUE) {
if(conn->bits.trailerhdrpresent!=TRUE) {
/* No Trailer: header found - revert to original Curl processing */
ch->state = CHUNK_STOPCR;

View File

@ -1121,11 +1121,8 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
}
else {
/* we're done with the DO, now DO_DONE */
easy->result = Curl_readwrite_init(easy->easy_conn);
if(CURLE_OK == easy->result) {
multistate(easy, CURLM_STATE_DO_DONE);
result = CURLM_CALL_MULTI_PERFORM;
}
multistate(easy, CURLM_STATE_DO_DONE);
result = CURLM_CALL_MULTI_PERFORM;
}
}
else {
@ -1152,11 +1149,8 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
}
else {
/* we're done with the DO, now DO_DONE */
easy->result = Curl_readwrite_init(easy->easy_conn);
if(CURLE_OK == easy->result) {
multistate(easy, CURLM_STATE_DO_DONE);
result = CURLM_CALL_MULTI_PERFORM;
}
multistate(easy, CURLM_STATE_DO_DONE);
result = CURLM_CALL_MULTI_PERFORM;
}
} /* dophase_done */
}
@ -1179,9 +1173,6 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
*/
easy->result = Curl_do_more(easy->easy_conn);
if(CURLE_OK == easy->result)
easy->result = Curl_readwrite_init(easy->easy_conn);
/* No need to remove ourselves from the send pipeline here since that
is done for us in Curl_done() */
@ -1207,9 +1198,6 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
easy->easy_conn->recv_pipe);
multistate(easy, CURLM_STATE_WAITPERFORM);
result = CURLM_CALL_MULTI_PERFORM;
Curl_pre_readwrite(easy->easy_conn);
break;
case CURLM_STATE_WAITPERFORM:

View File

@ -725,10 +725,6 @@ static CURLcode Curl_tftp(struct connectdata *conn, bool *done)
}
state = (tftp_state_data_t *)data->reqdata.proto.tftp;
code = Curl_readwrite_init(conn);
if(code)
return code;
/* Run the TFTP State Machine */
for(code=tftp_state_machine(state, TFTP_EVENT_INIT);
(state->state != TFTP_STATE_FIN) && (code == CURLE_OK);

View File

@ -992,7 +992,7 @@ CURLcode Curl_readwrite(struct connectdata *conn,
*
* It seems both Trailer: and Trailers: occur in the wild.
*/
conn->bits.trailerHdrPresent = TRUE;
conn->bits.trailerhdrpresent = TRUE;
}
else if(checkprefix("Content-Encoding:", k->p) &&
@ -1640,102 +1640,6 @@ CURLcode Curl_readwrite(struct connectdata *conn,
return CURLE_OK;
}
/*
* Curl_readwrite_init() inits the readwrite session. This is inited each time
* for a transfer, sometimes multiple times on the same SessionHandle
*/
CURLcode Curl_readwrite_init(struct connectdata *conn)
{
struct SessionHandle *data = conn->data;
struct Curl_transfer_keeper *k = &data->reqdata.keep;
/* NB: the content encoding software depends on this initialization of
Curl_transfer_keeper.*/
memset(k, 0, sizeof(struct Curl_transfer_keeper));
k->start = Curl_tvnow(); /* start time */
k->now = k->start; /* current time is now */
k->header = TRUE; /* assume header */
k->httpversion = -1; /* unknown at this point */
k->size = data->reqdata.size;
k->maxdownload = data->reqdata.maxdownload;
k->bytecountp = data->reqdata.bytecountp;
k->writebytecountp = data->reqdata.writebytecountp;
k->bytecount = 0;
k->buf = data->state.buffer;
k->uploadbuf = data->state.uploadbuffer;
k->maxfd = (conn->sockfd>conn->writesockfd?
conn->sockfd:conn->writesockfd)+1;
k->hbufp = data->state.headerbuff;
k->ignorebody=FALSE;
Curl_pgrsTime(data, TIMER_PRETRANSFER);
Curl_speedinit(data);
Curl_pgrsSetUploadCounter(data, 0);
Curl_pgrsSetDownloadCounter(data, 0);
if(!conn->bits.getheader) {
k->header = FALSE;
if(k->size > 0)
Curl_pgrsSetDownloadSize(data, k->size);
}
/* we want header and/or body, if neither then don't do this! */
if(conn->bits.getheader || !conn->bits.no_body) {
if(conn->sockfd != CURL_SOCKET_BAD) {
k->keepon |= KEEP_READ;
}
if(conn->writesockfd != CURL_SOCKET_BAD) {
/* HTTP 1.1 magic:
Even if we require a 100-return code before uploading data, we might
need to write data before that since the REQUEST may not have been
finished sent off just yet.
Thus, we must check if the request has been sent before we set the
state info where we wait for the 100-return code
*/
if(data->state.expect100header &&
(data->reqdata.proto.http->sending == HTTPSEND_BODY)) {
/* wait with write until we either got 100-continue or a timeout */
k->write_after_100_header = TRUE;
k->start100 = k->start;
}
else {
if(data->state.expect100header)
/* when we've sent off the rest of the headers, we must await a
100-continue */
k->wait100_after_headers = TRUE;
k->keepon |= KEEP_WRITE;
}
}
}
return CURLE_OK;
}
/*
* Curl_readwrite may get called multiple times. This function is called
* immediately before the first Curl_readwrite. Note that this can't be moved
* to Curl_readwrite_init since that function can get called while another
* pipeline request is in the middle of receiving data.
*
* We init chunking and trailer bits to their default values here immediately
* before receiving any header data for the current request in the pipeline.
*/
void Curl_pre_readwrite(struct connectdata *conn)
{
conn->bits.chunk=FALSE;
conn->bits.trailerHdrPresent=FALSE;
}
/*
* Curl_single_getsock() gets called by the multi interface code when the app
* has requested to get the sockets for the current connection. This function
@ -1757,6 +1661,9 @@ int Curl_single_getsock(const struct connectdata *conn,
return GETSOCK_BLANK;
if(data->reqdata.keep.keepon & KEEP_READ) {
DEBUGASSERT(conn->sockfd != CURL_SOCKET_BAD);
bitmap |= GETSOCK_READSOCK(sockindex);
sock[sockindex] = conn->sockfd;
}
@ -1769,6 +1676,9 @@ int Curl_single_getsock(const struct connectdata *conn,
one, we increase index */
if(data->reqdata.keep.keepon & KEEP_READ)
sockindex++; /* increase index if we need two entries */
DEBUGASSERT(conn->writesockfd != CURL_SOCKET_BAD);
sock[sockindex] = conn->writesockfd;
}
@ -1810,15 +1720,6 @@ Transfer(struct connectdata *conn)
if(!conn->bits.getheader && conn->bits.no_body)
return CURLE_OK;
if(!(conn->protocol & (PROT_FILE|PROT_TFTP))) {
/* Only do this if we are not transferring FILE or TFTP, since those
transfers are treated differently. They do their entire transfers in
the DO function and just returns from this. That is ugly indeed.
*/
Curl_readwrite_init(conn);
Curl_pre_readwrite(conn);
}
while(!done) {
curl_socket_t fd_read;
curl_socket_t fd_write;
@ -2523,25 +2424,23 @@ CURLcode Curl_perform(struct SessionHandle *data)
*/
CURLcode
Curl_setup_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 */
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, /* 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 */
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;
struct SessionHandle *data;
struct Curl_transfer_keeper *k;
if(!conn)
return CURLE_BAD_FUNCTION_ARGUMENT;
DEBUGASSERT(conn != NULL);
data = conn->data;
k = &data->reqdata.keep;
DEBUGASSERT((sockindex <= 1) && (sockindex >= -1));
@ -2556,5 +2455,47 @@ Curl_setup_transfer(
data->reqdata.bytecountp = bytecountp;
data->reqdata.writebytecountp = writecountp;
/* The code sequence below is placed in this function just because all
necessary input is not always known in do_complete() as this function may
be called after that */
if(!conn->bits.getheader) {
k->header = FALSE;
if(k->size > 0)
Curl_pgrsSetDownloadSize(data, k->size);
}
/* we want header and/or body, if neither then don't do this! */
if(conn->bits.getheader || !conn->bits.no_body) {
if(conn->sockfd != CURL_SOCKET_BAD) {
k->keepon |= KEEP_READ;
}
if(conn->writesockfd != CURL_SOCKET_BAD) {
/* HTTP 1.1 magic:
Even if we require a 100-return code before uploading data, we might
need to write data before that since the REQUEST may not have been
finished sent off just yet.
Thus, we must check if the request has been sent before we set the
state info where we wait for the 100-return code
*/
if(data->state.expect100header &&
(data->reqdata.proto.http->sending == HTTPSEND_BODY)) {
/* wait with write until we either got 100-continue or a timeout */
k->write_after_100_header = TRUE;
k->start100 = k->start;
}
else {
if(data->state.expect100header)
/* when we've sent off the rest of the headers, we must await a
100-continue */
k->wait100_after_headers = TRUE;
k->keepon |= KEEP_WRITE;
}
}
}
return CURLE_OK;
}

View File

@ -31,8 +31,6 @@ CURLcode Curl_readwrite(struct connectdata *conn, bool *done);
int Curl_single_getsock(const struct connectdata *conn,
curl_socket_t *socks,
int numsocks);
CURLcode Curl_readwrite_init(struct connectdata *conn);
void Curl_pre_readwrite(struct connectdata *conn);
CURLcode Curl_readrewind(struct connectdata *conn);
CURLcode Curl_fillreadbuffer(struct connectdata *conn, int bytes, int *nreadp);
bool Curl_retry_request(struct connectdata *conn, char **url);

View File

@ -121,6 +121,7 @@ void idn_free (void *ptr); /* prototype from idn-free.h, not provided by
#include "select.h"
#include "multiif.h"
#include "easyif.h"
#include "speedcheck.h"
/* And now for the protocols */
#include "ftp.h"
@ -164,6 +165,8 @@ static void conn_free(struct connectdata *conn);
static void signalPipeClose(struct curl_llist *pipeline);
static struct SessionHandle* gethandleathead(struct curl_llist *pipeline);
static CURLcode do_init(struct connectdata *conn);
static void do_complete(struct connectdata *conn);
#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
static void flush_cookies(struct SessionHandle *data, int cleanup);
@ -4449,21 +4452,83 @@ CURLcode Curl_done(struct connectdata **connp,
return result;
}
/*
* do_init() inits the readwrite session. This is inited each time (in the DO
* function before the protocol-specific DO functions are invoked) for a
* transfer, sometimes multiple times on the same SessionHandle. Make sure
* nothing in here depends on stuff that are setup dynamicly for the transfer.
*/
static CURLcode do_init(struct connectdata *conn)
{
struct SessionHandle *data = conn->data;
struct Curl_transfer_keeper *k = &data->reqdata.keep;
conn->bits.done = FALSE; /* Curl_done() is not called yet */
conn->bits.do_more = FALSE; /* by default there's no curl_do_more() to use */
/* NB: the content encoding software depends on this initialization of
Curl_transfer_keeper.*/
memset(k, 0, sizeof(struct Curl_transfer_keeper));
k->start = Curl_tvnow(); /* start time */
k->now = k->start; /* current time is now */
k->header = TRUE; /* assume header */
k->httpversion = -1; /* unknown at this point */
k->bytecount = 0;
k->buf = data->state.buffer;
k->uploadbuf = data->state.uploadbuffer;
k->hbufp = data->state.headerbuff;
k->ignorebody=FALSE;
Curl_pgrsTime(data, TIMER_PRETRANSFER);
Curl_speedinit(data);
Curl_pgrsSetUploadCounter(data, 0);
Curl_pgrsSetDownloadCounter(data, 0);
return CURLE_OK;
}
/*
* do_complete is called when the DO actions are complete.
*
* We init chunking and trailer bits to their default values here immediately
* before receiving any header data for the current request in the pipeline.
*/
static void do_complete(struct connectdata *conn)
{
struct SessionHandle *data = conn->data;
struct Curl_transfer_keeper *k = &data->reqdata.keep;
conn->bits.chunk=FALSE;
conn->bits.trailerhdrpresent=FALSE;
k->maxfd = (conn->sockfd>conn->writesockfd?
conn->sockfd:conn->writesockfd)+1;
k->size = data->reqdata.size;
k->maxdownload = data->reqdata.maxdownload;
k->bytecountp = data->reqdata.bytecountp;
k->writebytecountp = data->reqdata.writebytecountp;
}
CURLcode Curl_do(struct connectdata **connp, bool *done)
{
CURLcode result=CURLE_OK;
struct connectdata *conn = *connp;
struct SessionHandle *data = conn->data;
conn->bits.done = FALSE; /* Curl_done() is not called yet */
conn->bits.do_more = FALSE; /* by default there's no curl_do_more() to use */
/* setup and init stuff before DO starts, in preparing for the transfer */
do_init(conn);
if(conn->handler->do_it) {
/* generic protocol-specific function pointer set in curl_connect() */
result = conn->handler->do_it(conn, done);
/* This was formerly done in transfer.c, but we better do it here */
if((CURLE_SEND_ERROR == result) && conn->bits.reuse) {
/* This was a re-use of a connection and we got a write error in the
* DO-phase. Then we DISCONNECT this connection and have another attempt
@ -4513,6 +4578,10 @@ CURLcode Curl_do(struct connectdata **connp, bool *done)
}
}
}
if(result == CURLE_OK)
/* pre readwrite must be called after the protocol-specific DO function */
do_complete(conn);
}
return result;
}

View File

@ -600,7 +600,7 @@ struct ConnectBits {
requests */
bool netrc; /* name+password provided by netrc */
bool trailerHdrPresent; /* Set when Trailer: header found in HTTP response.
bool trailerhdrpresent; /* Set when Trailer: header found in HTTP response.
Required to determine whether to look for trailers
in case of Transfer-Encoding: chunking */
bool done; /* set to FALSE when Curl_do() is called and set to TRUE