aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Stenberg <daniel@haxx.se>2007-11-15 21:45:45 +0000
committerDaniel Stenberg <daniel@haxx.se>2007-11-15 21:45:45 +0000
commit50feea3eef87f1c07b954ad3020fdb836c7f279f (patch)
tree1458929eb07b01267e57bf3d32a066c96e68d0c5
parentca95f58ac0d5c9cc8f56517917af8b83248777f7 (diff)
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!
-rw-r--r--lib/file.c1
-rw-r--r--lib/http_chunks.c2
-rw-r--r--lib/multi.c20
-rw-r--r--lib/tftp.c4
-rw-r--r--lib/transfer.c181
-rw-r--r--lib/transfer.h2
-rw-r--r--lib/url.c75
-rw-r--r--lib/urldata.h2
8 files changed, 139 insertions, 148 deletions
diff --git a/lib/file.c b/lib/file.c
index 3b68eb229..1461de224 100644
--- a/lib/file.c
+++ b/lib/file.c
@@ -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);
diff --git a/lib/http_chunks.c b/lib/http_chunks.c
index 71b9b9791..305a8a97a 100644
--- a/lib/http_chunks.c
+++ b/lib/http_chunks.c
@@ -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;
diff --git a/lib/multi.c b/lib/multi.c
index 1b5dd1869..061e7b5e4 100644
--- a/lib/multi.c
+++ b/lib/multi.c
@@ -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:
diff --git a/lib/tftp.c b/lib/tftp.c
index c4603934c..d315aadde 100644
--- a/lib/tftp.c
+++ b/lib/tftp.c
@@ -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);
diff --git a/lib/transfer.c b/lib/transfer.c
index 64513e003..01a5ee33b 100644
--- a/lib/transfer.c
+++ b/lib/transfer.c
@@ -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;
}
diff --git a/lib/transfer.h b/lib/transfer.h
index a2fcd11e2..c368c4682 100644
--- a/lib/transfer.h
+++ b/lib/transfer.h
@@ -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);
diff --git a/lib/url.c b/lib/url.c
index 4ecfeee3e..5d8d042ed 100644
--- a/lib/url.c
+++ b/lib/url.c
@@ -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;
}
diff --git a/lib/urldata.h b/lib/urldata.h
index d28108d34..2ca78e256 100644
--- a/lib/urldata.h
+++ b/lib/urldata.h
@@ -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