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...
This commit is contained in:
6
CHANGES
6
CHANGES
@@ -6,6 +6,12 @@
|
|||||||
|
|
||||||
Changelog
|
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)
|
Dan F (5 September 2007)
|
||||||
- Minix doesn't support getsockopt on UDP sockets or send/recv on TCP
|
- Minix doesn't support getsockopt on UDP sockets or send/recv on TCP
|
||||||
sockets.
|
sockets.
|
||||||
|
|||||||
35
lib/ftp.c
35
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 ftp_conn *ftpc = &conn->proto.ftpc;
|
||||||
struct timeval now = Curl_tvnow();
|
struct timeval now = Curl_tvnow();
|
||||||
size_t nread;
|
size_t nread;
|
||||||
|
int cache_skip=0;
|
||||||
|
|
||||||
if (ftpcode)
|
if (ftpcode)
|
||||||
*ftpcode = 0; /* 0 for errors */
|
*ftpcode = 0; /* 0 for errors */
|
||||||
@@ -572,6 +573,29 @@ CURLcode Curl_GetFTPResponse(ssize_t *nreadp, /* return number of bytes read */
|
|||||||
if(timeout < interval_ms)
|
if(timeout < interval_ms)
|
||||||
interval_ms = timeout;
|
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)) {
|
switch (Curl_socket_ready(sockfd, CURL_SOCKET_BAD, (int)interval_ms)) {
|
||||||
case -1: /* select() error, stop reading */
|
case -1: /* select() error, stop reading */
|
||||||
failf(data, "FTP response aborted due to select/poll error: %d",
|
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 */
|
default: /* for clarity */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
result = ftp_readresp(sockfd, conn, ftpcode, &nread);
|
result = ftp_readresp(sockfd, conn, ftpcode, &nread);
|
||||||
if(result)
|
if(result)
|
||||||
break;
|
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;
|
*nreadp += nread;
|
||||||
|
|
||||||
} /* while there's buffer left and loop is requested */
|
} /* while there's buffer left and loop is requested */
|
||||||
|
|||||||
Reference in New Issue
Block a user