aboutsummaryrefslogtreecommitdiff
path: root/lib/ftp.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/ftp.c')
-rw-r--r--lib/ftp.c595
1 files changed, 100 insertions, 495 deletions
diff --git a/lib/ftp.c b/lib/ftp.c
index 000670fb4..331d17e9d 100644
--- a/lib/ftp.c
+++ b/lib/ftp.c
@@ -106,14 +106,6 @@
#define INET_ADDRSTRLEN 16
#endif
-#ifdef __SYMBIAN32__
-/* Symbian OS panics when given a timeout much greater than 1/2 hour */
-#define RESP_TIMEOUT (1800*1000)
-#else
-/* Default response timeout in milliseconds */
-#define RESP_TIMEOUT (3600*1000)
-#endif
-
#ifdef CURL_DISABLE_VERBOSE_STRINGS
#define ftp_pasv_verbose(a,b,c,d) do { } while(0)
#endif
@@ -155,7 +147,7 @@ static CURLcode ftp_setup_connection(struct connectdata * conn);
/* easy-to-use macro: */
#define FTPSENDF(x,y,z) if((result = Curl_ftpsendf(x,y,z)) != CURLE_OK) \
return result
-#define NBFTPSENDF(x,y,z) if((result = Curl_nbftpsendf(x,y,z)) != CURLE_OK) \
+#define PPSENDF(x,y,z) if((result = Curl_pp_sendf(x,y,z)) != CURLE_OK) \
return result
@@ -164,7 +156,7 @@ static CURLcode ftp_setup_connection(struct connectdata * conn);
*/
const struct Curl_handler Curl_handler_ftp = {
- "FTP", /* scheme */
+ "FTP", /* scheme */
ftp_setup_connection, /* setup_connection */
ftp_do, /* do_it */
ftp_done, /* done */
@@ -187,7 +179,7 @@ const struct Curl_handler Curl_handler_ftp = {
*/
const struct Curl_handler Curl_handler_ftps = {
- "FTPS", /* scheme */
+ "FTPS", /* scheme */
ftp_setup_connection, /* setup_connection */
ftp_do, /* do_it */
ftp_done, /* done */
@@ -362,217 +354,39 @@ static CURLcode AllowServerConnect(struct connectdata *conn)
/* never reaches this point */
}
-/* initialize stuff to prepare for reading a fresh new response */
-static void ftp_respinit(struct connectdata *conn)
-{
- struct ftp_conn *ftpc = &conn->proto.ftpc;
- ftpc->nread_resp = 0;
- ftpc->linestart_resp = conn->data->state.buffer;
- ftpc->pending_resp = TRUE;
-}
-
/* macro to check for a three-digit ftp status code at the start of the
given string */
-#define STATUSCODE(line) (ISDIGIT(line[0]) && ISDIGIT(line[1]) && \
- ISDIGIT(line[2]))
+#define STATUSCODE(line) (ISDIGIT(line[0]) && ISDIGIT(line[1]) && \
+ ISDIGIT(line[2]))
/* macro to check for the last line in an FTP server response */
#define LASTLINE(line) (STATUSCODE(line) && (' ' == line[3]))
+static int ftp_endofresp(struct pingpong *pp,
+ int *code)
+{
+ char *line = pp->linestart_resp;
+ size_t len = pp->nread_resp;
+
+ if((len > 3) && LASTLINE(line)) {
+ *code = atoi(line);
+ return 1;
+ }
+ return 0;
+}
+
static CURLcode ftp_readresp(curl_socket_t sockfd,
- struct connectdata *conn,
+ struct pingpong *pp,
int *ftpcode, /* return the ftp-code if done */
size_t *size) /* size of the response */
{
- ssize_t perline; /* count bytes per line */
- bool keepon=TRUE;
- ssize_t gotbytes;
- char *ptr;
+ struct connectdata *conn = pp->conn;
struct SessionHandle *data = conn->data;
char * const buf = data->state.buffer;
CURLcode result = CURLE_OK;
- struct ftp_conn *ftpc = &conn->proto.ftpc;
- int code = 0;
-
- *ftpcode = 0; /* 0 for errors or not done */
- *size = 0;
-
- ptr=buf + ftpc->nread_resp;
-
- /* number of bytes in the current line, so far */
- perline = (ssize_t)(ptr-ftpc->linestart_resp);
-
- keepon=TRUE;
-
- while((ftpc->nread_resp<BUFSIZE) && (keepon && !result)) {
-
- if(ftpc->cache) {
- /* we had data in the "cache", copy that instead of doing an actual
- * read
- *
- * ftp->cache_size is cast to int here. This should be safe,
- * because it would have been populated with something of size
- * int to begin with, even though its datatype may be larger
- * than an int.
- */
- DEBUGASSERT((ptr+ftpc->cache_size) <= (buf+BUFSIZE+1));
- memcpy(ptr, ftpc->cache, (int)ftpc->cache_size);
- gotbytes = (int)ftpc->cache_size;
- free(ftpc->cache); /* free the cache */
- ftpc->cache = NULL; /* clear the pointer */
- ftpc->cache_size = 0; /* zero the size just in case */
- }
- else {
- int res;
-#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI)
- enum protection_level prot = conn->data_prot;
-
- conn->data_prot = 0;
-#endif
- DEBUGASSERT((ptr+BUFSIZE-ftpc->nread_resp) <= (buf+BUFSIZE+1));
- res = Curl_read(conn, sockfd, ptr, BUFSIZE-ftpc->nread_resp,
- &gotbytes);
-#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI)
- conn->data_prot = prot;
-#endif
- if(res < 0)
- /* EWOULDBLOCK */
- return CURLE_OK; /* return */
-
-#ifdef CURL_DOES_CONVERSIONS
- if((res == CURLE_OK) && (gotbytes > 0)) {
- /* convert from the network encoding */
- res = Curl_convert_from_network(data, ptr, gotbytes);
- /* Curl_convert_from_network calls failf if unsuccessful */
- }
-#endif /* CURL_DOES_CONVERSIONS */
-
- if(CURLE_OK != res) {
- result = (CURLcode)res; /* Set outer result variable to this error. */
- keepon = FALSE;
- }
- }
-
- if(!keepon)
- ;
- else if(gotbytes <= 0) {
- keepon = FALSE;
- result = CURLE_RECV_ERROR;
- failf(data, "FTP response reading failed");
- }
- 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 */
- ssize_t i;
- ssize_t clipamount = 0;
- bool restart = FALSE;
-
- data->req.headerbytecount += gotbytes;
-
- ftpc->nread_resp += 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 defined(HAVE_KRB4) || defined(HAVE_GSSAPI)
- if(!conn->sec_complete)
-#endif
- if(data->set.verbose)
- Curl_debug(data, CURLINFO_HEADER_IN,
- ftpc->linestart_resp, (size_t)perline, conn);
-
- /*
- * We pass all response-lines to the callback function registered
- * for "headers". The response lines can be seen as a kind of
- * headers.
- */
- result = Curl_client_write(conn, CLIENTWRITE_HEADER,
- ftpc->linestart_resp, perline);
- if(result)
- return result;
+ int code;
- if(perline>3 && LASTLINE(ftpc->linestart_resp)) {
- /* 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 *meow;
- int n;
- for(meow=ftpc->linestart_resp, n=0; meow<ptr; meow++, n++)
- buf[n] = *meow;
- *meow=0; /* zero terminate */
- keepon=FALSE;
- ftpc->linestart_resp = ptr+1; /* advance pointer */
- i++; /* skip this before getting out */
-
- *size = ftpc->nread_resp; /* size of the response */
- ftpc->nread_resp = 0; /* restart */
- break;
- }
- perline=0; /* line starts over here */
- ftpc->linestart_resp = ptr+1;
- }
- }
-
- if(!keepon && (i != gotbytes)) {
- /* We found the end of the response lines, but we didn't parse the
- full chunk of data we have read from the server. We therefore need
- to store the rest of the data to be checked on the next invoke as
- it may actually contain another end of response already! */
- clipamount = gotbytes - i;
- restart = TRUE;
- }
- else if(keepon) {
-
- if((perline == gotbytes) && (gotbytes > BUFSIZE/2)) {
- /* We got an excessive line without newlines and we need to deal
- with it. First, check if it seems to start with a valid status
- code and then we keep just that in the line cache. Then throw
- away the rest. */
- infof(data, "Excessive FTP response line length received, %zd bytes."
- " Stripping\n", gotbytes);
- restart = TRUE;
- if(STATUSCODE(ftpc->linestart_resp))
- /* we copy 4 bytes since after the three-digit number there is a
- dash or a space and it is significant */
- clipamount = 4;
- }
- else if(ftpc->nread_resp > BUFSIZE/2) {
- /* We got a large chunk of data and there's potentially still trailing
- data to take care of, so we put any such part in the "cache", clear
- the buffer to make space and restart. */
- clipamount = perline;
- restart = TRUE;
- }
- }
- else if(i == gotbytes)
- restart = TRUE;
-
- if(clipamount) {
- ftpc->cache_size = clipamount;
- ftpc->cache = malloc((int)ftpc->cache_size);
- if(ftpc->cache)
- memcpy(ftpc->cache, ftpc->linestart_resp, (int)ftpc->cache_size);
- else
- return CURLE_OUT_OF_MEMORY;
- }
- if(restart) {
- /* now reset a few variables to start over nicely from the start of
- the big buffer */
- ftpc->nread_resp = 0; /* start over from scratch in the buffer */
- ptr = ftpc->linestart_resp = buf;
- perline = 0;
- }
-
- } /* there was data */
-
- } /* while there's buffer left and loop is requested */
-
- if(!result)
- code = atoi(buf);
+ result = Curl_pp_readresp(sockfd, pp, &code, size);
#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI)
/* handle the security-oriented responses 6xx ***/
@@ -593,12 +407,11 @@ static CURLcode ftp_readresp(curl_socket_t sockfd,
}
#endif
- *ftpcode=code; /* return the initial number like this */
-
/* store the latest code for later retrieval */
conn->data->info.httpcode=code;
- ftpc->pending_resp = FALSE;
+ if(ftpcode)
+ *ftpcode = code;
return result;
}
@@ -628,7 +441,7 @@ CURLcode Curl_GetFTPResponse(ssize_t *nreadp, /* return number of bytes read */
struct SessionHandle *data = conn->data;
CURLcode result = CURLE_OK;
struct ftp_conn *ftpc = &conn->proto.ftpc;
- struct timeval now = Curl_tvnow();
+ struct pingpong *pp = &ftpc->pp;
size_t nread;
int cache_skip=0;
int value_to_be_ignored=0;
@@ -643,23 +456,7 @@ CURLcode Curl_GetFTPResponse(ssize_t *nreadp, /* return number of bytes read */
while(!*ftpcode && !result) {
/* check and reset timeout value every lap */
- if(data->set.ftp_response_timeout )
- /* if CURLOPT_FTP_RESPONSE_TIMEOUT is set, use that to determine
- remaining time. Also, use "now" as opposed to "conn->now"
- because ftp_response_timeout is only supposed to govern
- the response for any given ftp response, not for the time
- from connect to the given ftp response. */
- timeout = data->set.ftp_response_timeout - /* timeout time */
- Curl_tvdiff(Curl_tvnow(), now); /* spent time */
- else if(data->set.timeout)
- /* if timeout is requested, find out how much remaining time we have */
- timeout = data->set.timeout - /* timeout time */
- Curl_tvdiff(Curl_tvnow(), conn->now); /* spent time */
- else
- /* Even without a requested timeout, we only wait response_time
- seconds for the full response to arrive before we bail out */
- timeout = ftpc->response_time -
- Curl_tvdiff(Curl_tvnow(), now); /* spent time */
+ timeout = Curl_pp_state_timeout(pp);
if(timeout <=0 ) {
failf(data, "FTP response timeout");
@@ -684,7 +481,7 @@ CURLcode Curl_GetFTPResponse(ssize_t *nreadp, /* return number of bytes read */
*
*/
- if(ftpc->cache && (cache_skip < 2)) {
+ if(pp->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
@@ -708,11 +505,11 @@ CURLcode Curl_GetFTPResponse(ssize_t *nreadp, /* return number of bytes read */
break;
}
}
- result = ftp_readresp(sockfd, conn, ftpcode, &nread);
+ result = ftp_readresp(sockfd, pp, ftpcode, &nread);
if(result)
break;
- if(!nread && ftpc->cache)
+ if(!nread && pp->cache)
/* bump cache skip counter as on repeated skips we must wait for more
data */
cache_skip++;
@@ -725,7 +522,7 @@ CURLcode Curl_GetFTPResponse(ssize_t *nreadp, /* return number of bytes read */
} /* while there's buffer left and loop is requested */
- ftpc->pending_resp = FALSE;
+ pp->pending_resp = FALSE;
return result;
}
@@ -787,7 +584,7 @@ static CURLcode ftp_state_user(struct connectdata *conn)
CURLcode result;
struct FTP *ftp = conn->data->state.proto.ftp;
/* send USER */
- NBFTPSENDF(conn, "USER %s", ftp->user?ftp->user:"");
+ PPSENDF(&conn->proto.ftpc.pp, "USER %s", ftp->user?ftp->user:"");
state(conn, FTP_USER);
conn->data->state.ftp_trying_alternative = FALSE;
@@ -800,7 +597,7 @@ static CURLcode ftp_state_pwd(struct connectdata *conn)
CURLcode result;
/* send PWD to discover our entry point */
- NBFTPSENDF(conn, "PWD", NULL);
+ PPSENDF(&conn->proto.ftpc.pp, "PWD", NULL);
state(conn, FTP_PWD);
return CURLE_OK;
@@ -808,23 +605,10 @@ static CURLcode ftp_state_pwd(struct connectdata *conn)
/* For the FTP "protocol connect" and "doing" phases only */
static int ftp_getsock(struct connectdata *conn,
- curl_socket_t *socks,
- int numsocks)
+ curl_socket_t *socks,
+ int numsocks)
{
- struct ftp_conn *ftpc = &conn->proto.ftpc;
-
- if(!numsocks)
- return GETSOCK_BLANK;
-
- socks[0] = conn->sock[FIRSTSOCKET];
-
- if(ftpc->sendleft) {
- /* write mode */
- return GETSOCK_WRITESOCK(0);
- }
-
- /* read mode */
- return GETSOCK_READSOCK(0);
+ return Curl_pp_getsock(&conn->proto.ftpc.pp, socks, numsocks);
}
/* This is called after the FTP_QUOTE state is passed.
@@ -855,7 +639,7 @@ static CURLcode ftp_state_cwd(struct connectdata *conn)
where we ended up after login: */
ftpc->count1 = 0; /* we count this as the first path, then we add one
for all upcoming ones in the ftp->dirs[] array */
- NBFTPSENDF(conn, "CWD %s", ftpc->entrypath);
+ PPSENDF(&conn->proto.ftpc.pp, "CWD %s", ftpc->entrypath);
state(conn, FTP_CWD);
}
else {
@@ -863,7 +647,7 @@ static CURLcode ftp_state_cwd(struct connectdata *conn)
ftpc->count1 = 1;
/* issue the first CWD, the rest is sent when the CWD responses are
received... */
- NBFTPSENDF(conn, "CWD %s", ftpc->dirs[ftpc->count1 -1]);
+ PPSENDF(&conn->proto.ftpc.pp, "CWD %s", ftpc->dirs[ftpc->count1 -1]);
state(conn, FTP_CWD);
}
else {
@@ -1190,9 +974,9 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
* EPRT |2|1080::8:800:200C:417A|5282|
*/
- result = Curl_nbftpsendf(conn, "%s |%d|%s|%d|", mode[fcmd],
- sa->sa_family == AF_INET?1:2,
- myhost, port);
+ result = Curl_pp_sendf(&ftpc->pp, "%s |%d|%s|%d|", mode[fcmd],
+ sa->sa_family == AF_INET?1:2,
+ myhost, port);
if(result)
return result;
break;
@@ -1213,7 +997,7 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
*dest = 0;
snprintf(dest, 20, ",%d,%d", port>>8, port&0xff);
- result = Curl_nbftpsendf(conn, "%s %s", mode[fcmd], tmp);
+ result = Curl_pp_sendf(&ftpc->pp, "%s %s", mode[fcmd], tmp);
if(result)
return result;
break;
@@ -1273,9 +1057,7 @@ static CURLcode ftp_state_use_pasv(struct connectdata *conn)
modeoff = conn->bits.ftp_use_epsv?0:1;
- result = Curl_nbftpsendf(conn, "%s", mode[modeoff]);
- if(result)
- return result;
+ PPSENDF(&ftpc->pp, "%s", mode[modeoff]);
ftpc->count1 = modeoff;
state(conn, FTP_PASV);
@@ -1322,7 +1104,7 @@ static CURLcode ftp_state_post_size(struct connectdata *conn)
/* Determine if server can respond to REST command and therefore
whether it supports range */
- NBFTPSENDF(conn, "REST %d", 0);
+ PPSENDF(&conn->proto.ftpc.pp, "REST %d", 0);
state(conn, FTP_REST);
}
@@ -1342,7 +1124,7 @@ static CURLcode ftp_state_post_type(struct connectdata *conn)
/* if a "head"-like request is being made (on a file) */
/* we know ftpc->file is a valid pointer to a file name */
- NBFTPSENDF(conn, "SIZE %s", ftpc->file);
+ PPSENDF(&ftpc->pp, "SIZE %s", ftpc->file);
state(conn, FTP_SIZE);
}
@@ -1406,7 +1188,7 @@ static CURLcode ftp_state_post_listtype(struct connectdata *conn)
return CURLE_OUT_OF_MEMORY;
}
- NBFTPSENDF(conn, "%s",cmd);
+ PPSENDF(&conn->proto.ftpc.pp, "%s",cmd);
if(lstArg)
free(lstArg);
@@ -1484,7 +1266,7 @@ static CURLcode ftp_state_post_cwd(struct connectdata *conn)
/* we have requested to get the modified-time of the file, this is a white
spot as the MDTM is not mentioned in RFC959 */
- NBFTPSENDF(conn, "MDTM %s", ftpc->file);
+ PPSENDF(&ftpc->pp, "MDTM %s", ftpc->file);
state(conn, FTP_MDTM);
}
@@ -1522,7 +1304,7 @@ static CURLcode ftp_state_ul_setup(struct connectdata *conn,
if(data->state.resume_from < 0 ) {
/* Got no given size to start from, figure it out */
- NBFTPSENDF(conn, "SIZE %s", ftpc->file);
+ PPSENDF(&ftpc->pp, "SIZE %s", ftpc->file);
state(conn, FTP_STOR_SIZE);
return result;
}
@@ -1586,8 +1368,8 @@ static CURLcode ftp_state_ul_setup(struct connectdata *conn,
/* we've passed, proceed as normal */
} /* resume_from */
- NBFTPSENDF(conn, data->set.ftp_append?"APPE %s":"STOR %s",
- ftpc->file);
+ PPSENDF(&ftpc->pp, data->set.ftp_append?"APPE %s":"STOR %s",
+ ftpc->file);
state(conn, FTP_STOR);
@@ -1633,7 +1415,7 @@ static CURLcode ftp_state_quote(struct connectdata *conn,
i++;
}
if(item) {
- NBFTPSENDF(conn, "%s", item->data);
+ PPSENDF(&ftpc->pp, "%s", item->data);
state(conn, instate);
quote = TRUE;
}
@@ -1650,7 +1432,7 @@ static CURLcode ftp_state_quote(struct connectdata *conn,
if(ftp->transfer != FTPTRANSFER_BODY)
state(conn, FTP_STOP);
else {
- NBFTPSENDF(conn, "SIZE %s", ftpc->file);
+ PPSENDF(&ftpc->pp, "SIZE %s", ftpc->file);
state(conn, FTP_RETR_SIZE);
}
break;
@@ -1791,7 +1573,7 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
conn->bits.ftp_use_epsv = FALSE;
infof(data, "disabling EPSV usage\n");
- NBFTPSENDF(conn, "PASV", NULL);
+ PPSENDF(&ftpc->pp, "PASV", NULL);
ftpc->count1++;
/* remain in the FTP_PASV state */
return result;
@@ -1852,7 +1634,7 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
/* disable it for next transfer */
conn->bits.ftp_use_epsv = FALSE;
data->state.errorbuf = FALSE; /* allow error message to get rewritten */
- NBFTPSENDF(conn, "PASV", NULL);
+ PPSENDF(&ftpc->pp, "PASV", NULL);
ftpc->count1++;
/* remain in the FTP_PASV state */
return result;
@@ -2168,14 +1950,14 @@ static CURLcode ftp_state_post_retr_size(struct connectdata *conn,
infof(data, "Instructs server to resume from offset %" FORMAT_OFF_T
"\n", data->state.resume_from);
- NBFTPSENDF(conn, "REST %" FORMAT_OFF_T, data->state.resume_from);
+ PPSENDF(&ftpc->pp, "REST %" FORMAT_OFF_T, data->state.resume_from);
state(conn, FTP_RETR_REST);
}
else {
/* no resume */
- NBFTPSENDF(conn, "RETR %s", ftpc->file);
+ PPSENDF(&ftpc->pp, "RETR %s", ftpc->file);
state(conn, FTP_RETR);
}
@@ -2246,7 +2028,7 @@ static CURLcode ftp_state_rest_resp(struct connectdata *conn,
result = CURLE_FTP_COULDNT_USE_REST;
}
else {
- NBFTPSENDF(conn, "RETR %s", ftpc->file);
+ PPSENDF(&ftpc->pp, "RETR %s", ftpc->file);
state(conn, FTP_RETR);
}
break;
@@ -2300,7 +2082,7 @@ static CURLcode ftp_state_stor_resp(struct connectdata *conn,
SECONDARYSOCKET, ftp->bytecountp);
state(conn, FTP_STOP);
- conn->proto.ftpc.pending_resp = TRUE; /* we expect a server response more */
+ conn->proto.ftpc.pp.pending_resp = TRUE; /* expect a server response */
return result;
}
@@ -2414,7 +2196,7 @@ static CURLcode ftp_state_get_resp(struct connectdata *conn,
if(result)
return result;
- conn->proto.ftpc.pending_resp = TRUE; /* we expect a server response more */
+ conn->proto.ftpc.pp.pending_resp = TRUE; /* expect server response */
state(conn, FTP_STOP);
}
else {
@@ -2466,7 +2248,7 @@ static CURLcode ftp_state_loggedin(struct connectdata *conn)
parameter of '0' to indicate that no buffering is taking place
and the data connection should not be encapsulated.
*/
- NBFTPSENDF(conn, "PBSZ %d", 0);
+ PPSENDF(&conn->proto.ftpc.pp, "PBSZ %d", 0);
state(conn, FTP_PBSZ);
}
else {
@@ -2490,7 +2272,7 @@ static CURLcode ftp_state_user_resp(struct connectdata *conn,
if((ftpcode == 331) && (ftpc->state == FTP_USER)) {
/* 331 Password required for ...
(the server requires to send the user's password too) */
- NBFTPSENDF(conn, "PASS %s", ftp->passwd?ftp->passwd:"");
+ PPSENDF(&ftpc->pp, "PASS %s", ftp->passwd?ftp->passwd:"");
state(conn, FTP_PASS);
}
else if(ftpcode/100 == 2) {
@@ -2500,7 +2282,7 @@ static CURLcode ftp_state_user_resp(struct connectdata *conn,
}
else if(ftpcode == 332) {
if(data->set.str[STRING_FTP_ACCOUNT]) {
- NBFTPSENDF(conn, "ACCT %s", data->set.str[STRING_FTP_ACCOUNT]);
+ PPSENDF(&ftpc->pp, "ACCT %s", data->set.str[STRING_FTP_ACCOUNT]);
state(conn, FTP_ACCT);
}
else {
@@ -2517,8 +2299,8 @@ static CURLcode ftp_state_user_resp(struct connectdata *conn,
if(conn->data->set.str[STRING_FTP_ALTERNATIVE_TO_USER] &&
!conn->data->state.ftp_trying_alternative) {
/* Ok, USER failed. Let's try the supplied command. */
- NBFTPSENDF(conn, "%s",
- conn->data->set.str[STRING_FTP_ALTERNATIVE_TO_USER]);
+ PPSENDF(&conn->proto.ftpc.pp, "%s",
+ conn->data->set.str[STRING_FTP_ALTERNATIVE_TO_USER]);
conn->data->state.ftp_trying_alternative = TRUE;
state(conn, FTP_USER);
result = CURLE_OK;
@@ -2555,32 +2337,15 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
struct SessionHandle *data=conn->data;
int ftpcode;
struct ftp_conn *ftpc = &conn->proto.ftpc;
+ struct pingpong *pp = &ftpc->pp;
static const char ftpauth[][4] = { "SSL", "TLS" };
size_t nread = 0;
- if(ftpc->sendleft) {
- /* we have a piece of a command still left to send */
- ssize_t written;
- result = Curl_write(conn, sock, ftpc->sendthis + ftpc->sendsize -
- ftpc->sendleft, ftpc->sendleft, &written);
- if(result)
- return result;
-
- if(written != (ssize_t)ftpc->sendleft) {
- /* only a fraction was sent */
- ftpc->sendleft -= written;
- }
- else {
- free(ftpc->sendthis);
- ftpc->sendthis=NULL;
- ftpc->sendleft = ftpc->sendsize = 0;
- ftpc->response = Curl_tvnow();
- }
- return CURLE_OK;
- }
+ if(pp->sendleft)
+ return Curl_pp_flushsend(pp);
/* we read a piece of response */
- result = ftp_readresp(sock, conn, &ftpcode, &nread);
+ result = ftp_readresp(sock, pp, &ftpcode, &nread);
if(result)
return result;
@@ -2632,7 +2397,7 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
data->set.ftpsslauth);
return CURLE_FAILED_INIT; /* we don't know what to do */
}
- NBFTPSENDF(conn, "AUTH %s", ftpauth[ftpc->count1]);
+ PPSENDF(&ftpc->pp, "AUTH %s", ftpauth[ftpc->count1]);
state(conn, FTP_AUTH);
}
else {
@@ -2665,7 +2430,7 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
else if(ftpc->count3 < 1) {
ftpc->count3++;
ftpc->count1 += ftpc->count2; /* get next attempt */
- result = Curl_nbftpsendf(conn, "AUTH %s", ftpauth[ftpc->count1]);
+ result = Curl_pp_sendf(&ftpc->pp, "AUTH %s", ftpauth[ftpc->count1]);
/* remain in this same state */
}
else {
@@ -2691,8 +2456,8 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
break;
case FTP_PBSZ:
- NBFTPSENDF(conn, "PROT %c",
- data->set.ftp_ssl == CURLUSESSL_CONTROL ? 'C' : 'P');
+ PPSENDF(&ftpc->pp, "PROT %c",
+ data->set.ftp_ssl == CURLUSESSL_CONTROL ? 'C' : 'P');
state(conn, FTP_PROT);
break;
@@ -2711,7 +2476,7 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
if(data->set.ftp_ccc) {
/* CCC - Clear Command Channel
*/
- NBFTPSENDF(conn, "CCC", NULL);
+ PPSENDF(&ftpc->pp, "CCC", NULL);
state(conn, FTP_CCC);
}
else {
@@ -2797,7 +2562,7 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
systems. */
if(!ftpc->server_os && ftpc->entrypath[0] != '/') {
- NBFTPSENDF(conn, "SYST", NULL);
+ PPSENDF(&ftpc->pp, "SYST", NULL);
state(conn, FTP_SYST);
break;
}
@@ -2836,7 +2601,7 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
if(strequal(ftpc->server_os, "OS/400")) {
/* Force OS400 name format 1. */
- NBFTPSENDF(conn, "SITE NAMEFMT 1", NULL);
+ PPSENDF(&ftpc->pp, "SITE NAMEFMT 1", NULL);
state(conn, FTP_NAMEFMT);
break;
}
@@ -2884,7 +2649,7 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
ftpc->count1 && !ftpc->count2) {
/* try making it */
ftpc->count2++; /* counter to prevent CWD-MKD loops */
- NBFTPSENDF(conn, "MKD %s", ftpc->dirs[ftpc->count1 - 1]);
+ PPSENDF(&ftpc->pp, "MKD %s", ftpc->dirs[ftpc->count1 - 1]);
state(conn, FTP_MKD);
}
else {
@@ -2900,7 +2665,7 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
ftpc->count2=0;
if(++ftpc->count1 <= ftpc->dirdepth) {
/* send next CWD */
- NBFTPSENDF(conn, "CWD %s", ftpc->dirs[ftpc->count1 - 1]);
+ PPSENDF(&ftpc->pp, "CWD %s", ftpc->dirs[ftpc->count1 - 1]);
}
else {
result = ftp_state_post_cwd(conn);
@@ -2918,7 +2683,7 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
}
state(conn, FTP_CWD);
/* send CWD */
- NBFTPSENDF(conn, "CWD %s", ftpc->dirs[ftpc->count1 - 1]);
+ PPSENDF(&ftpc->pp, "CWD %s", ftpc->dirs[ftpc->count1 - 1]);
break;
case FTP_MDTM:
@@ -2972,65 +2737,13 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
return result;
}
-/* Returns timeout in ms. 0 or negative number means the timeout has already
- triggered */
-static long ftp_state_timeout(struct connectdata *conn)
-{
- struct SessionHandle *data=conn->data;
- struct ftp_conn *ftpc = &conn->proto.ftpc;
- long timeout_ms=360000; /* in milliseconds */
-
- if(data->set.ftp_response_timeout )
- /* if CURLOPT_FTP_RESPONSE_TIMEOUT is set, use that to determine remaining
- time. Also, use ftp->response because FTP_RESPONSE_TIMEOUT is supposed
- to govern the response for any given ftp response, not for the time
- from connect to the given ftp response. */
- timeout_ms = data->set.ftp_response_timeout - /* timeout time */
- Curl_tvdiff(Curl_tvnow(), ftpc->response); /* spent time */
- else if(data->set.timeout)
- /* if timeout is requested, find out how much remaining time we have */
- timeout_ms = data->set.timeout - /* timeout time */
- Curl_tvdiff(Curl_tvnow(), conn->now); /* spent time */
- else
- /* Without a requested timeout, we only wait 'response_time' seconds for
- the full response to arrive before we bail out */
- timeout_ms = ftpc->response_time -
- Curl_tvdiff(Curl_tvnow(), ftpc->response); /* spent time */
-
- return timeout_ms;
-}
-
/* called repeatedly until done from multi.c */
static CURLcode ftp_multi_statemach(struct connectdata *conn,
- bool *done)
+ bool *done)
{
- curl_socket_t sock = conn->sock[FIRSTSOCKET];
- int rc;
- struct SessionHandle *data=conn->data;
struct ftp_conn *ftpc = &conn->proto.ftpc;
- CURLcode result = CURLE_OK;
- long timeout_ms = ftp_state_timeout(conn);
-
- *done = FALSE; /* default to not done yet */
-
- if(timeout_ms <= 0) {
- failf(data, "FTP response timeout");
- return CURLE_OPERATION_TIMEDOUT;
- }
-
- rc = Curl_socket_ready(ftpc->sendleft?CURL_SOCKET_BAD:sock, /* reading */
- ftpc->sendleft?sock:CURL_SOCKET_BAD, /* writing */
- 0);
-
- if(rc == -1) {
- failf(data, "select/poll error");
- return CURLE_OUT_OF_MEMORY;
- }
- else if(rc != 0) {
- result = ftp_statemach_act(conn);
- }
- /* if rc == 0, then select() timed out */
+ CURLcode result = Curl_pp_multi_statemach(&ftpc->pp);
/* Check for the state outside of the Curl_socket_ready() return code checks
since at times we are in fact already in this state when this function
@@ -3042,44 +2755,12 @@ static CURLcode ftp_multi_statemach(struct connectdata *conn,
static CURLcode ftp_easy_statemach(struct connectdata *conn)
{
- curl_socket_t sock = conn->sock[FIRSTSOCKET];
- int rc;
- struct SessionHandle *data=conn->data;
struct ftp_conn *ftpc = &conn->proto.ftpc;
+ struct pingpong *pp = &ftpc->pp;
CURLcode result = CURLE_OK;
while(ftpc->state != FTP_STOP) {
- long interval_ms;
- long timeout_ms = ftp_state_timeout(conn);
-
- if(timeout_ms <=0 ) {
- failf(data, "FTP response timeout");
- return CURLE_OPERATION_TIMEDOUT; /* already too little time */
- }
-
- interval_ms = 1000; /* use 1 second timeout intervals */
- if(timeout_ms < interval_ms)
- interval_ms = timeout_ms;
-
- rc = Curl_socket_ready(ftpc->sendleft?CURL_SOCKET_BAD:sock, /* reading */
- ftpc->sendleft?sock:CURL_SOCKET_BAD, /* writing */
- (int)interval_ms);
-
- if(Curl_pgrsUpdate(conn))
- result = CURLE_ABORTED_BY_CALLBACK;
- else
- result = Curl_speedcheck(data, Curl_tvnow());
-
- if(result)
- break;
-
- if(rc == -1) {
- failf(data, "select/poll error");
- result = CURLE_OUT_OF_MEMORY;
- }
- else if(rc)
- result = ftp_statemach_act(conn);
-
+ result = Curl_pp_easy_statemach(pp);
if(result)
break;
}
@@ -3136,6 +2817,7 @@ static CURLcode ftp_connect(struct connectdata *conn,
CURLcode result;
struct ftp_conn *ftpc = &conn->proto.ftpc;
struct SessionHandle *data=conn->data;
+ struct pingpong *pp = &ftpc->pp;
*done = FALSE; /* default to not done yet */
@@ -3150,7 +2832,10 @@ static CURLcode ftp_connect(struct connectdata *conn,
/* We always support persistant connections on ftp */
conn->bits.close = FALSE;
- ftpc->response_time = RESP_TIMEOUT; /* set default response time-out */
+ pp->response_time = RESP_TIMEOUT; /* set default response time-out */
+ pp->statemach_act = ftp_statemach_act;
+ pp->endofresp = ftp_endofresp;
+ pp->conn = conn;
#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_PROXY)
if(conn->bits.tunnel_proxy && conn->bits.httpproxy) {
@@ -3190,11 +2875,11 @@ static CURLcode ftp_connect(struct connectdata *conn,
return result;
}
+ Curl_pp_init(pp); /* init the generic pingpong data */
+
/* When we connect, we start in the state where we await the 220
response */
- ftp_respinit(conn); /* init the response reader stuff */
state(conn, FTP_WAIT220);
- ftpc->response = Curl_tvnow(); /* start response time-out now! */
if(data->state.used_interface == Curl_if_multi)
result = ftp_multi_statemach(conn, done);
@@ -3222,6 +2907,7 @@ static CURLcode ftp_done(struct connectdata *conn, CURLcode status,
struct SessionHandle *data = conn->data;
struct FTP *ftp = data->state.proto.ftp;
struct ftp_conn *ftpc = &conn->proto.ftpc;
+ struct pingpong *pp = &ftpc->pp;
ssize_t nread;
int ftpcode;
CURLcode result=CURLE_OK;
@@ -3330,20 +3016,20 @@ static CURLcode ftp_done(struct connectdata *conn, CURLcode status,
}
if((ftp->transfer == FTPTRANSFER_BODY) && ftpc->ctl_valid &&
- ftpc->pending_resp && !premature) {
+ pp->pending_resp && !premature) {
/*
* Let's see what the server says about the transfer we just performed,
* but lower the timeout as sometimes this connection has died while the
* data has been transfered. This happens when doing through NATs etc that
* abandon old silent connections.
*/
- long old_time = ftpc->response_time;
+ long old_time = pp->response_time;
- ftpc->response_time = 60*1000; /* give it only a minute for now */
+ pp->response_time = 60*1000; /* give it only a minute for now */
result = Curl_GetFTPResponse(&nread, conn, &ftpcode);
- ftpc->response_time = old_time; /* set this back to previous value */
+ pp->response_time = old_time; /* set this back to previous value */
if(!nread && (CURLE_OPERATION_TIMEDOUT == result)) {
failf(data, "control connection looks dead");
@@ -3497,7 +3183,7 @@ static CURLcode ftp_nb_type(struct connectdata *conn,
return ftp_state_type_resp(conn, 200, newstate);
}
- NBFTPSENDF(conn, "TYPE %c", want);
+ PPSENDF(&ftpc->pp, "TYPE %c", want);
state(conn, newstate);
/* keep track of our current transfer type */
@@ -3735,93 +3421,12 @@ static CURLcode ftp_do(struct connectdata *conn, bool *done)
return retcode;
}
-/***********************************************************************
- *
- * Curl_(nb)ftpsendf()
- *
- * Sends the formated string as a ftp command to a ftp server
- *
- * NOTE: we build the command in a fixed-length buffer, which sets length
- * restrictions on the command!
- *
- * The "nb" version is made to Never Block.
- */
-CURLcode Curl_nbftpsendf(struct connectdata *conn,
- const char *fmt, ...)
-{
- ssize_t bytes_written;
-/* may still not be big enough for some krb5 tokens */
-#define SBUF_SIZE 1024
- char s[SBUF_SIZE];
- size_t write_len;
- char *sptr=s;
- CURLcode res = CURLE_OK;
- struct SessionHandle *data = conn->data;
- struct ftp_conn *ftpc = &conn->proto.ftpc;
-#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI)
- enum protection_level data_sec = conn->data_prot;
-#endif
-
- va_list ap;
- va_start(ap, fmt);
- vsnprintf(s, SBUF_SIZE-3, fmt, ap);
- va_end(ap);
-
- strcat(s, "\r\n"); /* append a trailing CRLF */
-
- bytes_written=0;
- write_len = strlen(s);
-
- ftp_respinit(conn);
-
-#ifdef CURL_DOES_CONVERSIONS
- res = Curl_convert_to_network(data, s, write_len);
- /* Curl_convert_to_network calls failf if unsuccessful */
- if(res != CURLE_OK) {
- return res;
- }
-#endif /* CURL_DOES_CONVERSIONS */
-
-#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI)
- conn->data_prot = prot_cmd;
-#endif
- res = Curl_write(conn, conn->sock[FIRSTSOCKET], sptr, write_len,
- &bytes_written);
-#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI)
- conn->data_prot = data_sec;
-#endif
-
- if(CURLE_OK != res)
- return res;
-
- if(conn->data->set.verbose)
- Curl_debug(conn->data, CURLINFO_HEADER_OUT,
- sptr, (size_t)bytes_written, conn);
-
- if(bytes_written != (ssize_t)write_len) {
- /* the whole chunk was not sent, store the rest of the data */
- write_len -= bytes_written;
- sptr += bytes_written;
- ftpc->sendthis = malloc(write_len);
- if(ftpc->sendthis) {
- memcpy(ftpc->sendthis, sptr, write_len);
- ftpc->sendsize = ftpc->sendleft = write_len;
- }
- else {
- failf(data, "out of memory");
- res = CURLE_OUT_OF_MEMORY;
- }
- }
- else
- ftpc->response = Curl_tvnow();
-
- return res;
-}
CURLcode Curl_ftpsendf(struct connectdata *conn,
const char *fmt, ...)
{
ssize_t bytes_written;
+#define SBUF_SIZE 1024
char s[SBUF_SIZE];
size_t write_len;
char *sptr=s;
@@ -3891,7 +3496,7 @@ static CURLcode ftp_quit(struct connectdata *conn)
CURLcode result = CURLE_OK;
if(conn->proto.ftpc.ctl_valid) {
- NBFTPSENDF(conn, "QUIT", NULL);
+ PPSENDF(&conn->proto.ftpc.pp, "QUIT", NULL);
state(conn, FTP_QUIT);
result = ftp_easy_statemach(conn);
@@ -3910,6 +3515,7 @@ static CURLcode ftp_quit(struct connectdata *conn)
static CURLcode ftp_disconnect(struct connectdata *conn)
{
struct ftp_conn *ftpc= &conn->proto.ftpc;
+ struct pingpong *pp = &ftpc->pp;
/* We cannot send quit unconditionally. If this connection is stale or
bad in any way, sending quit and waiting around here will make the
@@ -3930,10 +3536,7 @@ static CURLcode ftp_disconnect(struct connectdata *conn)
free(ftpc->entrypath);
ftpc->entrypath = NULL;
}
- if(ftpc->cache) {
- free(ftpc->cache);
- ftpc->cache = NULL;
- }
+
freedirs(ftpc);
if(ftpc->prevpath) {
free(ftpc->prevpath);
@@ -3944,6 +3547,8 @@ static CURLcode ftp_disconnect(struct connectdata *conn)
ftpc->server_os = NULL;
}
+ Curl_pp_disconnect(pp);
+
return CURLE_OK;
}