Skip to content

Commit

Permalink
pingpong: stop using the download buffer
Browse files Browse the repository at this point in the history
The pinglong logic now uses its own dynbuf for receiving command
response data.
  • Loading branch information
bagder committed Jan 22, 2024
1 parent f81a335 commit a0d4c18
Show file tree
Hide file tree
Showing 6 changed files with 152 additions and 249 deletions.
39 changes: 21 additions & 18 deletions lib/ftp.c
Expand Up @@ -379,7 +379,7 @@ static CURLcode ReceivedServerConnect(struct Curl_easy *data, bool *received)
}

/* First check whether there is a cached response from server */
if(pp->cache_size && pp->cache && pp->cache[0] > '3') {
if(Curl_dyn_len(&pp->recvbuf) && (*Curl_dyn_ptr(&pp->recvbuf) > '3')) {
/* Data connection could not be established, let's return */
infof(data, "There is negative response in cache while serv connect");
(void)Curl_GetFTPResponse(data, &nread, &ftpcode);
Expand Down Expand Up @@ -554,7 +554,7 @@ static CURLcode ftp_readresp(struct Curl_easy *data,
#ifdef HAVE_GSSAPI
{
struct connectdata *conn = data->conn;
char * const buf = data->state.buffer;
char * const buf = Curl_dyn_ptr(&data->conn->proto.ftpc.pp.recvbuf);

/* handle the security-oriented responses 6xx ***/
switch(code) {
Expand Down Expand Up @@ -660,7 +660,7 @@ CURLcode Curl_GetFTPResponse(struct Curl_easy *data,
*
*/

if(pp->cache && (cache_skip < 2)) {
if(Curl_dyn_len(&pp->recvbuf) && (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
Expand Down Expand Up @@ -688,7 +688,7 @@ CURLcode Curl_GetFTPResponse(struct Curl_easy *data,
if(result)
break;

if(!nread && pp->cache)
if(!nread && Curl_dyn_len(&pp->recvbuf))
/* bump cache skip counter as on repeated skips we must wait for more
data */
cache_skip++;
Expand Down Expand Up @@ -1821,7 +1821,9 @@ static CURLcode ftp_state_pasv_resp(struct Curl_easy *data,
struct Curl_dns_entry *addr = NULL;
enum resolve_t rc;
unsigned short connectport; /* the local port connect() should use! */
char *str = &data->state.buffer[4]; /* start on the first letter */
struct pingpong *pp = &ftpc->pp;
char *str =
Curl_dyn_ptr(&pp->recvbuf) + 4; /* start on the first letter */

/* if we come here again, make sure the former name is cleared */
Curl_safefree(ftpc->newhost);
Expand Down Expand Up @@ -2099,8 +2101,9 @@ static CURLcode ftp_state_mdtm_resp(struct Curl_easy *data,
/* we got a time. Format should be: "YYYYMMDDHHMMSS[.sss]" where the
last .sss part is optional and means fractions of a second */
int year, month, day, hour, minute, second;
if(ftp_213_date(&data->state.buffer[4],
&year, &month, &day, &hour, &minute, &second)) {
struct pingpong *pp = &ftpc->pp;
char *resp = Curl_dyn_ptr(&pp->recvbuf) + 4;
if(ftp_213_date(resp, &year, &month, &day, &hour, &minute, &second)) {
/* we have a time, reformat it */
char timebuf[24];
msnprintf(timebuf, sizeof(timebuf),
Expand Down Expand Up @@ -2311,15 +2314,16 @@ static CURLcode ftp_state_size_resp(struct Curl_easy *data,
{
CURLcode result = CURLE_OK;
curl_off_t filesize = -1;
char *buf = data->state.buffer;
char *buf = Curl_dyn_ptr(&data->conn->proto.ftpc.pp.recvbuf);
size_t len = Curl_dyn_len(&data->conn->proto.ftpc.pp.recvbuf);

/* get the size from the ascii string: */
if(ftpcode == 213) {
/* To allow servers to prepend "rubbish" in the response string, we scan
for all the digits at the end of the response and parse only those as a
number. */
char *start = &buf[4];
char *fdigit = strchr(start, '\r');
char *fdigit = memchr(start, '\r', len);
if(fdigit) {
do
fdigit--;
Expand Down Expand Up @@ -2494,7 +2498,7 @@ static CURLcode ftp_state_get_resp(struct Curl_easy *data,
*
* Example D above makes this parsing a little tricky */
char *bytes;
char *buf = data->state.buffer;
char *buf = Curl_dyn_ptr(&conn->proto.ftpc.pp.recvbuf);
bytes = strstr(buf, " bytes");
if(bytes) {
long in = (long)(--bytes-buf);
Expand Down Expand Up @@ -2763,7 +2767,7 @@ static CURLcode ftp_statemachine(struct Curl_easy *data,
case FTP_AUTH:
/* we have gotten the response to a previous AUTH command */

if(pp->cache_size)
if(Curl_dyn_len(&pp->recvbuf))
return CURLE_WEIRD_SERVER_REPLY; /* Forbid pipelining in response. */

/* RFC2228 (page 5) says:
Expand Down Expand Up @@ -2861,8 +2865,8 @@ static CURLcode ftp_statemachine(struct Curl_easy *data,

case FTP_PWD:
if(ftpcode == 257) {
char *ptr = &data->state.buffer[4]; /* start on the first letter */
const size_t buf_size = data->set.buffer_size;
char *ptr = Curl_dyn_ptr(&pp->recvbuf) + 4; /* start on the first
letter */
bool entry_extracted = FALSE;
struct dynbuf out;
Curl_dyn_init(&out, 1000);
Expand All @@ -2877,8 +2881,7 @@ static CURLcode ftp_statemachine(struct Curl_easy *data,
*/

/* scan for the first double-quote for non-standard responses */
while(ptr < &data->state.buffer[buf_size]
&& *ptr != '\n' && *ptr != '\0' && *ptr != '"')
while(*ptr != '\n' && *ptr != '\0' && *ptr != '"')
ptr++;

if('\"' == *ptr) {
Expand Down Expand Up @@ -2950,7 +2953,8 @@ static CURLcode ftp_statemachine(struct Curl_easy *data,

case FTP_SYST:
if(ftpcode == 215) {
char *ptr = &data->state.buffer[4]; /* start on the first letter */
char *ptr = Curl_dyn_ptr(&pp->recvbuf) + 4; /* start on the first
letter */
char *os;
char *start;

Expand Down Expand Up @@ -3191,8 +3195,7 @@ static CURLcode ftp_connect(struct Curl_easy *data,
conn->bits.ftp_use_control_ssl = TRUE;
}

Curl_pp_setup(pp); /* once per transfer */
Curl_pp_init(data, pp); /* init the generic pingpong data */
Curl_pp_init(data, pp); /* once per transfer */

/* When we connect, we start in the state where we await the 220
response */
Expand Down
47 changes: 20 additions & 27 deletions lib/imap.c
Expand Up @@ -355,8 +355,8 @@ static bool imap_endofresp(struct Curl_easy *data, struct connectdata *conn,
*/
static CURLcode imap_get_message(struct Curl_easy *data, struct bufref *out)
{
char *message = data->state.buffer;
size_t len = strlen(message);
char *message = Curl_dyn_ptr(&data->conn->proto.imapc.pp.recvbuf);
size_t len = Curl_dyn_len(&data->conn->proto.imapc.pp.recvbuf);

if(len > 2) {
/* Find the start of the message */
Expand Down Expand Up @@ -896,7 +896,7 @@ static CURLcode imap_state_capability_resp(struct Curl_easy *data,
CURLcode result = CURLE_OK;
struct connectdata *conn = data->conn;
struct imap_conn *imapc = &conn->proto.imapc;
const char *line = data->state.buffer;
const char *line = Curl_dyn_ptr(&imapc->pp.recvbuf);

(void)instate; /* no use for this yet */

Expand Down Expand Up @@ -982,7 +982,7 @@ static CURLcode imap_state_starttls_resp(struct Curl_easy *data,
(void)instate; /* no use for this yet */

/* Pipelining in response is forbidden. */
if(data->conn->proto.imapc.pp.cache_size)
if(data->conn->proto.imapc.pp.overflow)
return CURLE_WEIRD_SERVER_REPLY;

if(imapcode != IMAP_RESP_OK) {
Expand Down Expand Up @@ -1058,8 +1058,8 @@ static CURLcode imap_state_listsearch_resp(struct Curl_easy *data,
imapstate instate)
{
CURLcode result = CURLE_OK;
char *line = data->state.buffer;
size_t len = strlen(line);
char *line = Curl_dyn_ptr(&data->conn->proto.imapc.pp.recvbuf);
size_t len = Curl_dyn_len(&data->conn->proto.imapc.pp.recvbuf);

(void)instate; /* No use for this yet */

Expand All @@ -1086,7 +1086,7 @@ static CURLcode imap_state_select_resp(struct Curl_easy *data, int imapcode,
struct connectdata *conn = data->conn;
struct IMAP *imap = data->req.p.imap;
struct imap_conn *imapc = &conn->proto.imapc;
const char *line = data->state.buffer;
const char *line = Curl_dyn_ptr(&data->conn->proto.imapc.pp.recvbuf);

(void)instate; /* no use for this yet */

Expand Down Expand Up @@ -1145,7 +1145,7 @@ static CURLcode imap_state_fetch_resp(struct Curl_easy *data,
CURLcode result = CURLE_OK;
struct imap_conn *imapc = &conn->proto.imapc;
struct pingpong *pp = &imapc->pp;
const char *ptr = data->state.buffer;
const char *ptr = Curl_dyn_ptr(&data->conn->proto.imapc.pp.recvbuf);
bool parsed = FALSE;
curl_off_t size = 0;

Expand Down Expand Up @@ -1176,11 +1176,11 @@ static CURLcode imap_state_fetch_resp(struct Curl_easy *data,
size);
Curl_pgrsSetDownloadSize(data, size);

if(pp->cache) {
/* At this point there is a bunch of data in the header "cache" that is
actually body content, send it as body and then skip it. Do note
that there may even be additional "headers" after the body. */
size_t chunk = pp->cache_size;
if(Curl_dyn_len(&pp->recvbuf)) {
/* At this point there is a data in the header buffer that is actually
body content, send it as body and then skip it. Do note that there
may even be additional "headers" after the body. */
size_t chunk = Curl_dyn_len(&pp->recvbuf);

if(chunk > (size_t)size)
/* The conversion from curl_off_t to size_t is always fine here */
Expand All @@ -1191,26 +1191,21 @@ static CURLcode imap_state_fetch_resp(struct Curl_easy *data,
imap_state(data, IMAP_STOP);
return CURLE_OK;
}
result = Curl_client_write(data, CLIENTWRITE_BODY, pp->cache, chunk);
result = Curl_client_write(data, CLIENTWRITE_BODY,
Curl_dyn_ptr(&pp->recvbuf), chunk);
if(result)
return result;

infof(data, "Written %zu bytes, %" CURL_FORMAT_CURL_OFF_TU
" bytes are left for transfer", chunk, size - chunk);

/* Have we used the entire cache or just part of it?*/
if(pp->cache_size > chunk) {
/* Only part of it so shrink the cache to fit the trailing data */
memmove(pp->cache, pp->cache + chunk, pp->cache_size - chunk);
pp->cache_size -= chunk;
}
else {
if(Curl_dyn_len(&pp->recvbuf) > chunk)
/* keep the trailing data */
Curl_dyn_tail(&pp->recvbuf, Curl_dyn_len(&pp->recvbuf) - chunk);
else
/* Free the cache */
Curl_safefree(pp->cache);

/* Reset the cache size */
pp->cache_size = 0;
}
Curl_dyn_reset(&pp->recvbuf);
}

if(data->req.bytecount == size)
Expand Down Expand Up @@ -1472,8 +1467,6 @@ static CURLcode imap_connect(struct Curl_easy *data, bool *done)
Curl_sasl_init(&imapc->sasl, data, &saslimap);

Curl_dyn_init(&imapc->dyn, DYN_IMAP_CMD);
/* Initialise the pingpong layer */
Curl_pp_setup(pp);
Curl_pp_init(data, pp);

/* Parse the URL options */
Expand Down

0 comments on commit a0d4c18

Please sign in to comment.