Skip to content

Commit

Permalink
ftp: flush pingpong before response
Browse files Browse the repository at this point in the history
Fix FTP protocol to flush the pingpong's send buffer before receiving a
response from the server, as it may never come otherwise.

Fixes FTP/FTPS tests with `CURL_DBG_SOCK_WBLOCK=90` set.

Closes curl#14452
  • Loading branch information
icing authored and bagder committed Aug 8, 2024
1 parent badbd4e commit a0ea955
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 6 deletions.
22 changes: 16 additions & 6 deletions lib/ftp.c
Original file line number Diff line number Diff line change
Expand Up @@ -819,6 +819,8 @@ CURLcode Curl_GetFTPResponse(struct Curl_easy *data,
int cache_skip = 0;
int value_to_be_ignored = 0;

CURL_TRC_FTP(data, "getFTPResponse start");

if(ftpcode)
*ftpcode = 0; /* 0 for errors */
else
Expand Down Expand Up @@ -864,21 +866,27 @@ CURLcode Curl_GetFTPResponse(struct Curl_easy *data,
*/
}
else if(!Curl_conn_data_pending(data, FIRSTSOCKET)) {
switch(SOCKET_READABLE(sockfd, interval_ms)) {
case -1: /* select() error, stop reading */
curl_socket_t wsock = Curl_pp_needs_flush(data, pp)?
sockfd : CURL_SOCKET_BAD;
int ev = Curl_socket_check(sockfd, CURL_SOCKET_BAD, wsock, interval_ms);
if(ev < 0) {
failf(data, "FTP response aborted due to select/poll error: %d",
SOCKERRNO);
return CURLE_RECV_ERROR;

case 0: /* timeout */
}
else if(ev == 0) {
if(Curl_pgrsUpdate(data))
return CURLE_ABORTED_BY_CALLBACK;
continue; /* just continue in our loop for the timeout duration */
}
}

default: /* for clarity */
if(Curl_pp_needs_flush(data, pp)) {
result = Curl_pp_flushsend(data, pp);
if(result)
break;
}
}

result = ftp_readresp(data, FIRSTSOCKET, pp, ftpcode, &nread);
if(result)
break;
Expand All @@ -897,6 +905,8 @@ CURLcode Curl_GetFTPResponse(struct Curl_easy *data,
} /* while there is buffer left and loop is requested */

pp->pending_resp = FALSE;
CURL_TRC_FTP(data, "getFTPResponse -> result=%d, nread=%zd, ftpcode=%d",
result, *nreadp, *ftpcode);

return result;
}
Expand Down
10 changes: 10 additions & 0 deletions lib/pingpong.c
Original file line number Diff line number Diff line change
Expand Up @@ -395,13 +395,23 @@ int Curl_pp_getsock(struct Curl_easy *data,
return GETSOCK_READSOCK(0);
}

bool Curl_pp_needs_flush(struct Curl_easy *data,
struct pingpong *pp)
{
(void)data;
return pp->sendleft > 0;
}

CURLcode Curl_pp_flushsend(struct Curl_easy *data,
struct pingpong *pp)
{
/* we have a piece of a command still left to send */
size_t written;
CURLcode result;

if(!Curl_pp_needs_flush(data, pp))
return CURLE_OK;

result = Curl_conn_send(data, FIRSTSOCKET,
pp->sendthis + pp->sendsize - pp->sendleft,
pp->sendleft, FALSE, &written);
Expand Down
2 changes: 2 additions & 0 deletions lib/pingpong.h
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,8 @@ CURLcode Curl_pp_readresp(struct Curl_easy *data,
int *code, /* return the server code if done */
size_t *size); /* size of the response */

bool Curl_pp_needs_flush(struct Curl_easy *data,
struct pingpong *pp);

CURLcode Curl_pp_flushsend(struct Curl_easy *data,
struct pingpong *pp);
Expand Down

0 comments on commit a0ea955

Please sign in to comment.