Commit 73e91ce2 authored by Daniel Stenberg's avatar Daniel Stenberg
Browse files

Curl_GetFTPResponse() now checks and properly deals with the fact that the

underlying ftp_readresp() function has a separate "cache" where there might
in fact be leftover data...
parent 8780ff87
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -6,6 +6,12 @@

                                  Changelog

Daniel S (5 September 2007)
- Continued the work on a fix for #1779054
  (http://curl.haxx.se/bug/view.cgi?id=1779054). My previous fix from August
  24 was not complete (either) but could accidentally "forget" parts of a
  server response which led to faulty server response time-out errors.

Dan F (5 September 2007)
- Minix doesn't support getsockopt on UDP sockets or send/recv on TCP
  sockets.
+48 −15
Original line number Diff line number Diff line
@@ -537,6 +537,7 @@ CURLcode Curl_GetFTPResponse(ssize_t *nreadp, /* return number of bytes read */
  struct ftp_conn *ftpc = &conn->proto.ftpc;
  struct timeval now = Curl_tvnow();
  size_t nread;
  int cache_skip=0;

  if (ftpcode)
    *ftpcode = 0; /* 0 for errors */
@@ -572,6 +573,29 @@ CURLcode Curl_GetFTPResponse(ssize_t *nreadp, /* return number of bytes read */
    if(timeout < interval_ms)
      interval_ms = timeout;

    /*
     * Since this function is blocking, we need to wait here for input on the
     * connection and only then we call the response reading function. We do
     * timeout at least every second to make the timeout check run.
     *
     * A caution here is that the ftp_readresp() function has a cache that may
     * contain pieces of a response from the previous invoke and we need to
     * make sure we don't just wait for input while there is unhandled data in
     * that cache. But also, if the cache is there, we call ftp_readresp() and
     * the cache wasn't good enough to continue we must not just busy-loop
     * around this function.
     *
     */

    if(ftpc->cache && (cache_skip < 2)) {
      /*
       * There's a cache left since before. We then skipping the wait for
       * socket action, unless this is the same cache like the previous round
       * as then the cache was deemed not enough to act on and we then need to
       * wait for more data anyway.
       */
    }
    else {
      switch (Curl_socket_ready(sockfd, CURL_SOCKET_BAD, (int)interval_ms)) {
      case -1: /* select() error, stop reading */
        failf(data, "FTP response aborted due to select/poll error: %d",
@@ -586,11 +610,20 @@ CURLcode Curl_GetFTPResponse(ssize_t *nreadp, /* return number of bytes read */
      default: /* for clarity */
        break;
      }

    }
    result = ftp_readresp(sockfd, conn, ftpcode, &nread);
    if(result)
      break;

    if(!nread && ftpc->cache)
      /* bump cache skip counter as on repeated skips we must wait for more
         data */
      cache_skip++;
    else
      /* when we got data or there is no cache left, we reset the cache skip
         counter */
      cache_skip=0;

    *nreadp += nread;

  } /* while there's buffer left and loop is requested */