Commit 32e8467a authored by Daniel Stenberg's avatar Daniel Stenberg
Browse files

Curl_perfom: removed

Curl_perfom is no longer used anywhere since the always-multi commit
c4312741, and some related functions were used only from within
Curl_perfom.
parent e243d80d
Loading
Loading
Loading
Loading
+0 −372
Original line number Diff line number Diff line
@@ -1245,156 +1245,6 @@ long Curl_sleep_time(curl_off_t rate_bps, curl_off_t cur_rate_bps,
  return (long)rv;
}


/*
 * Transfer()
 *
 * This function is what performs the actual transfer. It is capable of doing
 * both ways simultaneously.  The transfer must already have been setup by a
 * call to Curl_setup_transfer().
 *
 * Note that headers are created in a preallocated buffer of a default size.
 * That buffer can be enlarged on demand, but it is never shrunken again.
 *
 */

static CURLcode
Transfer(struct connectdata *conn)
{
  CURLcode result;
  struct SessionHandle *data = conn->data;
  struct SingleRequest *k = &data->req;
  bool done=FALSE;
  bool first=TRUE;
  long timeout_ms;
  int buffersize;
  long totmp;

  if((conn->sockfd == CURL_SOCKET_BAD) &&
     (conn->writesockfd == CURL_SOCKET_BAD))
    /* nothing to read, nothing to write, we're already OK! */
    return CURLE_OK;

  /* we want header and/or body, if neither then don't do this! */
  if(!k->getheader && data->set.opt_no_body)
    return CURLE_OK;

  while(!done) {
    curl_socket_t fd_read = conn->sockfd;
    curl_socket_t fd_write = conn->writesockfd;
    int keepon = k->keepon;
    timeout_ms = 1000;

    if(conn->waitfor) {
      /* if waitfor is set, get the RECV and SEND bits from that but keep the
         other bits */
      keepon &= ~ (KEEP_RECV|KEEP_SEND);
      keepon |= conn->waitfor & (KEEP_RECV|KEEP_SEND);
    }

    /* limit-rate logic: if speed exceeds threshold, then do not include fd in
       select set. The current speed is recalculated in each Curl_readwrite()
       call */
    if((keepon & KEEP_SEND) &&
        (!data->set.max_send_speed ||
         (data->progress.ulspeed < data->set.max_send_speed) )) {
      k->keepon &= ~KEEP_SEND_HOLD;
    }
    else {
      if(data->set.upload && data->set.max_send_speed &&
         (data->progress.ulspeed > data->set.max_send_speed) ) {
        /* calculate upload rate-limitation timeout. */
        buffersize = (int)(data->set.buffer_size ?
                           data->set.buffer_size : BUFSIZE);
        totmp = Curl_sleep_time(data->set.max_send_speed,
                                data->progress.ulspeed, buffersize);
        if(totmp < timeout_ms)
          timeout_ms = totmp;
      }
      fd_write = CURL_SOCKET_BAD;
      if(keepon & KEEP_SEND)
        k->keepon |= KEEP_SEND_HOLD; /* hold it */
    }

    if((keepon & KEEP_RECV) &&
        (!data->set.max_recv_speed ||
         (data->progress.dlspeed < data->set.max_recv_speed)) ) {
      k->keepon &= ~KEEP_RECV_HOLD;
    }
    else {
      if((!data->set.upload) && data->set.max_recv_speed &&
         (data->progress.dlspeed > data->set.max_recv_speed)) {
        /* Calculate download rate-limitation timeout. */
        buffersize = (int)(data->set.buffer_size ?
                           data->set.buffer_size : BUFSIZE);
        totmp = Curl_sleep_time(data->set.max_recv_speed,
                                data->progress.dlspeed, buffersize);
        if(totmp < timeout_ms)
          timeout_ms = totmp;
      }
      fd_read = CURL_SOCKET_BAD;
      if(keepon & KEEP_RECV)
        k->keepon |= KEEP_RECV_HOLD; /* hold it */
    }

    /* pause logic. Don't check descriptors for paused connections */
    if(k->keepon & KEEP_RECV_PAUSE)
      fd_read = CURL_SOCKET_BAD;
    if(k->keepon & KEEP_SEND_PAUSE)
      fd_write = CURL_SOCKET_BAD;

    /* The *_HOLD and *_PAUSE logic is necessary since even though there might
       be no traffic during the select interval, we still call
       Curl_readwrite() for the timeout case and if we limit transfer speed we
       must make sure that this function doesn't transfer anything while in
       HOLD status.

       The no timeout for the first round is for the protocols for which data
       has already been slurped off the socket and thus waiting for action
       won't work since it'll wait even though there is already data present
       to work with. */
    if(first &&
       ((fd_read != CURL_SOCKET_BAD) || (fd_write != CURL_SOCKET_BAD)))
      /* if this is the first lap and one of the file descriptors is fine
         to work with, skip the timeout */
      timeout_ms = 0;
    else {
      totmp = Curl_timeleft(data, &k->now, FALSE);
      if(totmp < 0)
        return CURLE_OPERATION_TIMEDOUT;
      else if(!totmp)
        totmp = 1000;

      if(totmp < timeout_ms)
        timeout_ms = totmp;
    }

    switch (Curl_socket_ready(fd_read, fd_write, timeout_ms)) {
    case -1: /* select() error, stop reading */
#ifdef EINTR
      /* The EINTR is not serious, and it seems you might get this more
         often when using the lib in a multi-threaded environment! */
      if(SOCKERRNO == EINTR)
        continue;
#endif
      return CURLE_RECV_ERROR;  /* indicate a network problem */
    case 0:  /* timeout */
    default: /* readable descriptors */

      result = Curl_readwrite(conn, &done);
      /* "done" signals to us if the transfer(s) are ready */
      break;
    }
    if(result)
      return result;

    first = FALSE; /* not the first lap anymore */
  }

  return CURLE_OK;
}


/*
 * Curl_pretransfer() is called immediately before a transfer starts.
 */
@@ -1925,38 +1775,6 @@ CURLcode Curl_follow(struct SessionHandle *data,
#endif /* CURL_DISABLE_HTTP */
}

static CURLcode
connect_host(struct SessionHandle *data,
             struct connectdata **conn)
{
  CURLcode res = CURLE_OK;

  bool async;
  bool protocol_done=TRUE; /* will be TRUE always since this is only used
                                within the easy interface */
  Curl_pgrsTime(data, TIMER_STARTSINGLE);
  res = Curl_connect(data, conn, &async, &protocol_done);

  if((CURLE_OK == res) && async) {
    /* Now, if async is TRUE here, we need to wait for the name
       to resolve */
    res = Curl_resolver_wait_resolv(*conn, NULL);
    if(CURLE_OK == res) {
      /* Resolved, continue with the connection */
      res = Curl_async_resolved(*conn, &protocol_done);
      if(res)
        *conn = NULL;
    }
    else {
      /* if we can't resolve, we kill this "connection" now */
      (void)Curl_disconnect(*conn, /* dead_connection */ FALSE);
      *conn = NULL;
    }
  }

  return res;
}

CURLcode
Curl_reconnect_request(struct connectdata **connp)
{
@@ -2060,196 +1878,6 @@ CURLcode Curl_retry_request(struct connectdata *conn,
  return CURLE_OK;
}

static CURLcode Curl_do_perform(struct SessionHandle *data)
{
  CURLcode res;
  CURLcode res2;
  struct connectdata *conn=NULL;
  char *newurl = NULL; /* possibly a new URL to follow to! */
  followtype follow = FOLLOW_NONE;

  res = Curl_pretransfer(data);
  if(res)
    return res;

  /*
   * It is important that there is NO 'return' from this function at any other
   * place than falling down to the end of the function! This is because we
   * have cleanup stuff that must be done before we get back, and that is only
   * performed after this do-while loop.
   */

  for(;;) {
    res = connect_host(data, &conn);   /* primary connection */

    if(res == CURLE_OK) {
      bool do_done;
      if(data->set.connect_only) {
        /* keep connection open for application to use the socket */
        conn->bits.close = FALSE;
        res = Curl_done(&conn, CURLE_OK, FALSE);
        break;
      }
      res = Curl_do(&conn, &do_done);

      if(res == CURLE_OK) {
        if(conn->data->set.wildcardmatch) {
          if(conn->data->wildcard.state == CURLWC_DONE ||
             conn->data->wildcard.state == CURLWC_SKIP) {
            /* keep connection open for application to use the socket */
            conn->bits.close = FALSE;
            res = Curl_done(&conn, CURLE_OK, FALSE);
            break;
          }
        }
        res = Transfer(conn); /* now fetch that URL please */
        if((res == CURLE_OK) || (res == CURLE_RECV_ERROR)) {
          bool retry = FALSE;
          CURLcode rc = Curl_retry_request(conn, &newurl);
          if(rc)
            res = rc;
          else
            retry = (newurl?TRUE:FALSE);

          if(retry) {
            /* we know (newurl != NULL) at this point */
            res = CURLE_OK;
            follow = FOLLOW_RETRY;
          }
          else if(res == CURLE_OK) {
            /*
             * We must duplicate the new URL here as the connection data may
             * be free()ed in the Curl_done() function. We prefer the newurl
             * one since that's used for redirects or just further requests
             * for retries or multi-stage HTTP auth methods etc.
             */
            if(data->req.newurl) {
              follow = FOLLOW_REDIR;
              newurl = strdup(data->req.newurl);
              if(!newurl)
                res = CURLE_OUT_OF_MEMORY;
            }
            else if(data->req.location) {
              follow = FOLLOW_FAKE;
              newurl = strdup(data->req.location);
              if(!newurl)
                res = CURLE_OUT_OF_MEMORY;
            }
          }

          /* in the above cases where 'newurl' gets assigned, we have a fresh
           * allocated memory pointed to */
        }
        if(res != CURLE_OK) {
          /* The transfer phase returned error, we mark the connection to get
           * closed to prevent being re-used. This is because we can't
           * possibly know if the connection is in a good shape or not now. */
          conn->bits.close = TRUE;

          if(CURL_SOCKET_BAD != conn->sock[SECONDARYSOCKET]) {
            /* if we failed anywhere, we must clean up the secondary socket if
               it was used */
            Curl_closesocket(conn, conn->sock[SECONDARYSOCKET]);
            conn->sock[SECONDARYSOCKET] = CURL_SOCKET_BAD;
          }
        }

        /* Always run Curl_done(), even if some of the previous calls
           failed, but return the previous (original) error code */
        res2 = Curl_done(&conn, res, FALSE);

        if(CURLE_OK == res)
          res = res2;
      }
      else if(conn)
        /* Curl_do() failed, clean up left-overs in the done-call, but note
           that at some cases the conn pointer is NULL when Curl_do() failed
           and the connection cache is very small so only call Curl_done() if
           conn is still "alive". */
        /* ignore return code since we already have an error to return */
        (void)Curl_done(&conn, res, FALSE);

      /*
       * Important: 'conn' cannot be used here, since it may have been closed
       * in 'Curl_done' or other functions.
       */

      if((res == CURLE_OK) && follow) {
        res = Curl_follow(data, newurl, follow);
        if(CURLE_OK == res) {
          /* if things went fine, Curl_follow() freed or otherwise took
             responsibility for the newurl pointer */
          newurl = NULL;
          if(follow >= FOLLOW_RETRY) {
            follow = FOLLOW_NONE;
            continue;
          }
          /* else we break out of the loop below */
        }
      }
    }
    break; /* it only reaches here when this shouldn't loop */

  } /* loop if Location: */

  if(newurl)
    free(newurl);

  if(res && !data->state.errorbuf) {
    /*
     * As an extra precaution: if no error string has been set and there was
     * an error, use the strerror() string or if things are so bad that not
     * even that is good, set a bad string that mentions the error code.
     */
    const char *str = curl_easy_strerror(res);
    if(!str)
      failf(data, "unspecified error %d", (int)res);
    else
      failf(data, "%s", str);
  }

  /* run post-transfer unconditionally, 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_perform() is the internal high-level function that gets called by the
 * external curl_easy_perform() function. It inits, performs and cleans up a
 * single file transfer.
 */
CURLcode Curl_perform(struct SessionHandle *data)
{
  CURLcode res;
  if(!data->set.wildcardmatch)
    return Curl_do_perform(data);

  /* init main wildcard structures */
  res = Curl_wildcard_init(&data->wildcard);
  if(res)
    return res;

  res = Curl_do_perform(data);
  if(res) {
    Curl_wildcard_dtor(&data->wildcard);
    return res;
  }

  /* wildcard loop */
  while(!res && data->wildcard.state != CURLWC_DONE)
    res = Curl_do_perform(data);

  Curl_wildcard_dtor(&data->wildcard);

  /* wildcard download finished or failed */
  data->wildcard.state = CURLWC_INIT;
  return res;
}

/*
 * Curl_setup_transfer() is called to setup some basic properties for the
 * upcoming transfer.
+2 −2
Original line number Diff line number Diff line
@@ -7,7 +7,7 @@
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
 * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
 *
 * This software is licensed as described in the file COPYING, which
 * you should have received as part of this distribution. The terms
@@ -21,7 +21,7 @@
 * KIND, either express or implied.
 *
 ***************************************************************************/
CURLcode Curl_perform(struct SessionHandle *data);

CURLcode Curl_pretransfer(struct SessionHandle *data);
CURLcode Curl_second_connect(struct connectdata *conn);
CURLcode Curl_posttransfer(struct SessionHandle *data);
+3 −3
Original line number Diff line number Diff line
@@ -7,7 +7,7 @@
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 2010, Daniel Stenberg, <daniel@haxx.se>, et al.
 * Copyright (C) 2010 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
 *
 * This software is licensed as described in the file COPYING, which
 * you should have received as part of this distribution. The terms
@@ -33,8 +33,8 @@ typedef enum {
  CURLWC_CLEAN, /* deallocate resources and reset settings */
  CURLWC_SKIP,  /* skip over concrete file */
  CURLWC_ERROR, /* error cases */
  CURLWC_DONE   /* if is wildcard->state == CURLWC_DONE wildcard loop in
                   Curl_perform() will end */
  CURLWC_DONE   /* if is wildcard->state == CURLWC_DONE wildcard loop
                   will end */
} curl_wildcard_states;

typedef void (*curl_wildcard_tmp_dtor)(void *ptr);