]> granicus.if.org Git - curl/commitdiff
Rearranged code and changed Curl_readwrite_init() and Curl_pre_readwrite() into
authorDaniel Stenberg <daniel@haxx.se>
Thu, 15 Nov 2007 21:45:45 +0000 (21:45 +0000)
committerDaniel Stenberg <daniel@haxx.se>
Thu, 15 Nov 2007 21:45:45 +0000 (21:45 +0000)
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!

lib/file.c
lib/http_chunks.c
lib/multi.c
lib/tftp.c
lib/transfer.c
lib/transfer.h
lib/url.c
lib/urldata.h

index 3b68eb2291c98770830af833fdc63692f69de3c5..1461de2249f060c50596bc13980abbcaf6f9e7c1 100644 (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);
 
index 71b9b979182395cf58294a31fab49d6e815877dc..305a8a97a9af28df2392e15dd27d0093a469b711 100644 (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;
 
index 1b5dd18691a4b7e1069d4605fd8d9f54ec4ff57c..061e7b5e4f3c718f30ed4fa90e53252b4500194b 100644 (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:
index c4603934c8d9c7748da2575950314f7803418fa0..d315aadde42128fe5855da3e45a6989c5f901f9e 100644 (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);
index 64513e00331cd741d14c5cdd4c92ca2a783ffddb..01a5ee33b17034f6ac6f95f60726c4250ab7bea3 100644 (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;
 }
index a2fcd11e20e40b6fdc00189f144b55d5de4655fb..c368c4682ec52b74d12aa1fa914b25339d406786 100644 (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);
index 4ecfeee3ec2b27541567f9d84b47d324472a9e1a..5d8d042ed91154930cc66dbdf6f1ba031e4ce0d2 100644 (file)
--- 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;
 }
index d28108d349619f4b7a1fc4e654a437903d65c97a..2ca78e2567bbcf90bb25360f8e1c3a55798d3ba0 100644 (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