mirror of
https://github.com/moparisthebest/curl
synced 2024-12-22 08:08:50 -05:00
Curl_GetFTPResponse() is rewritten to read all incoming data in large
chunks, which makes it a lot faster and will make ftps work better...
This commit is contained in:
parent
a7dc45997f
commit
ef07903a51
172
lib/ftp.c
172
lib/ftp.c
@ -147,6 +147,165 @@ static CURLcode AllowServerConnect(struct UrlData *data,
|
|||||||
#define lastline(line) (isdigit((int)line[0]) && isdigit((int)line[1]) && \
|
#define lastline(line) (isdigit((int)line[0]) && isdigit((int)line[1]) && \
|
||||||
isdigit((int)line[2]) && (' ' == line[3]))
|
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((nread<BUFSIZE) && (keepon && !error)) {
|
||||||
|
readfd = rkeepfd; /* set every lap */
|
||||||
|
interval.tv_sec = timeout;
|
||||||
|
interval.tv_usec = 0;
|
||||||
|
|
||||||
|
switch (select (sockfd+1, &readfd, NULL, NULL, &interval)) {
|
||||||
|
case -1: /* select() error, stop reading */
|
||||||
|
error = SELECT_ERROR;
|
||||||
|
failf(data, "Transfer aborted due to select() error");
|
||||||
|
break;
|
||||||
|
case 0: /* timeout */
|
||||||
|
error = SELECT_TIMEOUT;
|
||||||
|
failf(data, "Transfer aborted due to timeout");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/*
|
||||||
|
* This code previously didn't use the kerberos sec_read() code
|
||||||
|
* to read, but when we use Curl_read() it may do so. Do confirm
|
||||||
|
* that this is still ok and then remove this comment!
|
||||||
|
*/
|
||||||
|
if(CURLE_OK != Curl_read(conn, sockfd, ptr, BUFSIZE-nread, &gotbytes))
|
||||||
|
keepon = FALSE;
|
||||||
|
else if(gotbytes <= 0) {
|
||||||
|
keepon = FALSE;
|
||||||
|
error = SELECT_ERROR;
|
||||||
|
failf(data, "Connection aborted");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* we got a whole chunk of data, which can be anything from one
|
||||||
|
* byte to a set of lines and possible just a piece of the last
|
||||||
|
* line */
|
||||||
|
int i;
|
||||||
|
|
||||||
|
nread += gotbytes;
|
||||||
|
for(i=0; i< gotbytes; ptr++, i++) {
|
||||||
|
perline++;
|
||||||
|
if(*ptr=='\n') {
|
||||||
|
/* a newline is CRLF in ftp-talk, so the CR is ignored as
|
||||||
|
the line isn't really terminated until the LF comes */
|
||||||
|
|
||||||
|
/* output debug output if that is requested */
|
||||||
|
if(data->bits.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; moo<ptr; moo++, i++)
|
||||||
|
buf[i] = *moo;
|
||||||
|
moo[i]=0; /* zero terminate */
|
||||||
|
keepon=FALSE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
perline=0; /* line starts over here */
|
||||||
|
line_start = ptr+1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
} /* switch */
|
||||||
|
} /* while there's buffer left and loop is requested */
|
||||||
|
|
||||||
|
if(!error)
|
||||||
|
code = atoi(buf);
|
||||||
|
|
||||||
|
#if KRB4
|
||||||
|
/* handle the security-oriented responses 6xx ***/
|
||||||
|
/* FIXME: some errorchecking perhaps... ***/
|
||||||
|
switch(code) {
|
||||||
|
case 631:
|
||||||
|
sec_read_msg(conn, buf, prot_safe);
|
||||||
|
break;
|
||||||
|
case 632:
|
||||||
|
sec_read_msg(conn, buf, prot_private);
|
||||||
|
break;
|
||||||
|
case 633:
|
||||||
|
sec_read_msg(conn, buf, prot_confidential);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* normal ftp stuff we pass through! */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if(error)
|
||||||
|
return -error;
|
||||||
|
|
||||||
|
if(ftpcode)
|
||||||
|
*ftpcode=code; /* return the initial number like this */
|
||||||
|
|
||||||
|
return nread; /* total amount of bytes read */
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
/*
|
/*
|
||||||
* We allow the ftpcode pointer to be NULL if no reply integer is wanted
|
* We allow the ftpcode pointer to be NULL if no reply integer is wanted
|
||||||
*/
|
*/
|
||||||
@ -157,6 +316,7 @@ int Curl_GetFTPResponse(int sockfd, char *buf,
|
|||||||
{
|
{
|
||||||
int nread;
|
int nread;
|
||||||
ssize_t keepon=TRUE;
|
ssize_t keepon=TRUE;
|
||||||
|
size_t got;
|
||||||
char *ptr;
|
char *ptr;
|
||||||
int timeout = 3600; /* in seconds */
|
int timeout = 3600; /* in seconds */
|
||||||
struct timeval interval;
|
struct timeval interval;
|
||||||
@ -260,6 +420,7 @@ int Curl_GetFTPResponse(int sockfd, char *buf,
|
|||||||
|
|
||||||
return nread;
|
return nread;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* -- who are we? -- */
|
/* -- who are we? -- */
|
||||||
char *Curl_getmyhost(char *buf, int buf_size)
|
char *Curl_getmyhost(char *buf, int buf_size)
|
||||||
@ -837,7 +998,8 @@ CURLcode _ftp(struct connectdata *conn)
|
|||||||
}
|
}
|
||||||
ftpsendf(conn->firstsocket, conn, "%s |%d|%s|%s|", *modep, eprtaf,
|
ftpsendf(conn->firstsocket, conn, "%s |%d|%s|%s|", *modep, eprtaf,
|
||||||
portmsgbuf, tmp);
|
portmsgbuf, tmp);
|
||||||
} else if (strcmp(*modep, "LPRT") == 0 || strcmp(*modep, "PORT") == 0) {
|
} else if (strcmp(*modep, "LPRT") == 0 ||
|
||||||
|
strcmp(*modep, "PORT") == 0) {
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (strcmp(*modep, "LPRT") == 0 && lprtaf < 0)
|
if (strcmp(*modep, "LPRT") == 0 && lprtaf < 0)
|
||||||
@ -849,7 +1011,7 @@ CURLcode _ftp(struct connectdata *conn)
|
|||||||
if (strcmp(*modep, "LPRT") == 0) {
|
if (strcmp(*modep, "LPRT") == 0) {
|
||||||
snprintf(tmp, sizeof(tmp), "%d,%d", lprtaf, alen);
|
snprintf(tmp, sizeof(tmp), "%d,%d", lprtaf, alen);
|
||||||
if (strlcat(portmsgbuf, tmp, sizeof(portmsgbuf)) >= sizeof(portmsgbuf)) {
|
if (strlcat(portmsgbuf, tmp, sizeof(portmsgbuf)) >= sizeof(portmsgbuf)) {
|
||||||
goto again;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (i = 0; i < alen; i++) {
|
for (i = 0; i < alen; i++) {
|
||||||
@ -858,18 +1020,18 @@ CURLcode _ftp(struct connectdata *conn)
|
|||||||
else
|
else
|
||||||
snprintf(tmp, sizeof(tmp), "%u", ap[i]);
|
snprintf(tmp, sizeof(tmp), "%u", ap[i]);
|
||||||
if (strlcat(portmsgbuf, tmp, sizeof(portmsgbuf)) >= sizeof(portmsgbuf)) {
|
if (strlcat(portmsgbuf, tmp, sizeof(portmsgbuf)) >= sizeof(portmsgbuf)) {
|
||||||
goto again;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (strcmp(*modep, "LPRT") == 0) {
|
if (strcmp(*modep, "LPRT") == 0) {
|
||||||
snprintf(tmp, sizeof(tmp), ",%d", plen);
|
snprintf(tmp, sizeof(tmp), ",%d", plen);
|
||||||
if (strlcat(portmsgbuf, tmp, sizeof(portmsgbuf)) >= sizeof(portmsgbuf))
|
if (strlcat(portmsgbuf, tmp, sizeof(portmsgbuf)) >= sizeof(portmsgbuf))
|
||||||
goto again;
|
continue;
|
||||||
}
|
}
|
||||||
for (i = 0; i < plen; i++) {
|
for (i = 0; i < plen; i++) {
|
||||||
snprintf(tmp, sizeof(tmp), ",%u", pp[i]);
|
snprintf(tmp, sizeof(tmp), ",%u", pp[i]);
|
||||||
if (strlcat(portmsgbuf, tmp, sizeof(portmsgbuf)) >= sizeof(portmsgbuf)) {
|
if (strlcat(portmsgbuf, tmp, sizeof(portmsgbuf)) >= sizeof(portmsgbuf)) {
|
||||||
goto again;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ftpsendf(conn->firstsocket, conn, "%s %s", *modep, portmsgbuf);
|
ftpsendf(conn->firstsocket, conn, "%s %s", *modep, portmsgbuf);
|
||||||
|
Loading…
Reference in New Issue
Block a user