mirror of
https://github.com/curl/curl.git
synced 2024-11-27 05:50:21 +08:00
ftp: flush pingpong before response
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 #14452
This commit is contained in:
parent
badbd4eb46
commit
a0ea955f80
24
lib/ftp.c
24
lib/ftp.c
@ -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
|
||||
@ -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 */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
@ -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;
|
||||
}
|
||||
|
@ -395,6 +395,13 @@ 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)
|
||||
{
|
||||
@ -402,6 +409,9 @@ CURLcode Curl_pp_flushsend(struct Curl_easy *data,
|
||||
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);
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user