From ef07903a5151aeb80aae070bdbe847be45205211 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 26 Apr 2001 10:29:24 +0000 Subject: [PATCH] Curl_GetFTPResponse() is rewritten to read all incoming data in large chunks, which makes it a lot faster and will make ftps work better... --- lib/ftp.c | 172 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 167 insertions(+), 5 deletions(-) diff --git a/lib/ftp.c b/lib/ftp.c index 43c53a859..e634fa6ab 100644 --- a/lib/ftp.c +++ b/lib/ftp.c @@ -147,6 +147,165 @@ static CURLcode AllowServerConnect(struct UrlData *data, #define lastline(line) (isdigit((int)line[0]) && isdigit((int)line[1]) && \ isdigit((int)line[2]) && (' ' == line[3])) + +int Curl_GetFTPResponse(int sockfd, + char *buf, + struct connectdata *conn, + int *ftpcode) +{ + /* Brand new implementation. + * We cannot read just one byte per read() and then go back to select() + * as it seems that the OpenSSL read() stuff doesn't grok that properly. + * + * Alas, read as much as possible, split up into lines, use the ending + * line in a response or continue reading. + */ + + int nread; /* total size read */ + int perline; /* count bytes per line */ + bool keepon=TRUE; + ssize_t gotbytes; + char *ptr; + int timeout = 3600; /* default timeout in seconds */ + struct timeval interval; + fd_set rkeepfd; + fd_set readfd; + struct UrlData *data = conn->data; + char *line_start; + int code; + +#define SELECT_OK 0 +#define SELECT_ERROR 1 +#define SELECT_TIMEOUT 2 + int error = SELECT_OK; + + if(ftpcode) + *ftpcode=0; /* 0 for errors */ + + if(data->timeout) { + /* if timeout is requested, find out how much remaining time we have */ + timeout = data->timeout - /* timeout time */ + (Curl_tvlong(Curl_tvnow()) - Curl_tvlong(conn->now)); /* spent time */ + if(timeout <=0 ) { + failf(data, "Transfer aborted due to timeout"); + return -SELECT_TIMEOUT; /* already too little time */ + } + } + + FD_ZERO (&readfd); /* clear it */ + FD_SET (sockfd, &readfd); /* read socket */ + + /* get this in a backup variable to be able to restore it on each lap in the + select() loop */ + rkeepfd = readfd; + + ptr=buf; + line_start = buf; + + nread=0; + perline=0; + keepon=TRUE; + + while((nreadbits.verbose) { + fputs("< ", data->err); + fwrite(line_start, 1, perline, data->err); + /* no need to output LF here, it is part of the data */ + } + + if(perline>3 && lastline(line_start)) { + /* This is the end of the last line, copy the last + * line to the start of the buffer and zero terminate, + * for old times sake (and krb4)! */ + char *moo; + int i; + for(moo=line_start, i=0; moofirstsocket, conn, "%s |%d|%s|%s|", *modep, eprtaf, portmsgbuf, tmp); - } else if (strcmp(*modep, "LPRT") == 0 || strcmp(*modep, "PORT") == 0) { + } else if (strcmp(*modep, "LPRT") == 0 || + strcmp(*modep, "PORT") == 0) { int i; if (strcmp(*modep, "LPRT") == 0 && lprtaf < 0) @@ -849,7 +1011,7 @@ CURLcode _ftp(struct connectdata *conn) if (strcmp(*modep, "LPRT") == 0) { snprintf(tmp, sizeof(tmp), "%d,%d", lprtaf, alen); if (strlcat(portmsgbuf, tmp, sizeof(portmsgbuf)) >= sizeof(portmsgbuf)) { - goto again; + continue; } } for (i = 0; i < alen; i++) { @@ -858,18 +1020,18 @@ CURLcode _ftp(struct connectdata *conn) else snprintf(tmp, sizeof(tmp), "%u", ap[i]); if (strlcat(portmsgbuf, tmp, sizeof(portmsgbuf)) >= sizeof(portmsgbuf)) { - goto again; + continue; } } if (strcmp(*modep, "LPRT") == 0) { snprintf(tmp, sizeof(tmp), ",%d", plen); if (strlcat(portmsgbuf, tmp, sizeof(portmsgbuf)) >= sizeof(portmsgbuf)) - goto again; + continue; } for (i = 0; i < plen; i++) { snprintf(tmp, sizeof(tmp), ",%u", pp[i]); if (strlcat(portmsgbuf, tmp, sizeof(portmsgbuf)) >= sizeof(portmsgbuf)) { - goto again; + continue; } } ftpsendf(conn->firstsocket, conn, "%s %s", *modep, portmsgbuf);