aboutsummaryrefslogtreecommitdiff
path: root/lib/ftp.c
diff options
context:
space:
mode:
authorDaniel Stenberg <daniel@haxx.se>2007-09-05 21:41:07 +0000
committerDaniel Stenberg <daniel@haxx.se>2007-09-05 21:41:07 +0000
commit73e91ce20cb76df8b617c8e97974d7c15a0fa590 (patch)
treec1983ac7362143fc56f3b7ca57d17404a5419384 /lib/ftp.c
parent8780ff879c1dea904902c43bfabff34325391949 (diff)
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...
Diffstat (limited to 'lib/ftp.c')
-rw-r--r--lib/ftp.c63
1 files changed, 48 insertions, 15 deletions
diff --git a/lib/ftp.c b/lib/ftp.c
index 36fe4686b..a282282aa 100644
--- a/lib/ftp.c
+++ b/lib/ftp.c
@@ -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,27 +573,59 @@ CURLcode Curl_GetFTPResponse(ssize_t *nreadp, /* return number of bytes read */
if(timeout < interval_ms)
interval_ms = timeout;
- 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",
- SOCKERRNO);
- return CURLE_RECV_ERROR;
-
- case 0: /* timeout */
- if(Curl_pgrsUpdate(conn))
- return CURLE_ABORTED_BY_CALLBACK;
- continue; /* just continue in our loop for the timeout duration */
-
- default: /* for clarity */
- break;
- }
+ /*
+ * 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",
+ SOCKERRNO);
+ return CURLE_RECV_ERROR;
+
+ case 0: /* timeout */
+ if(Curl_pgrsUpdate(conn))
+ return CURLE_ABORTED_BY_CALLBACK;
+ continue; /* just continue in our loop for the timeout duration */
+
+ 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 */
return result;