Skip to content

Commit db5a13d

Browse files
committed
fix: end a listing whose peer stopped reading
The idle deadline covered RETR and the command stage only, so a LIST, NLST or MLSD that stopped being read had nothing to end it: the server retried its failing writes until the client gave up, and the session stayed open holding the queued send buffer. Observed on an ESP32-S3 with internal DRAM exhausted, 415 rounds before the run was stopped by hand. Listings refresh the deadline whenever the peer takes bytes, so covering them ends only the ones that stopped moving. STOR refreshes nothing yet and stays out.
1 parent 20744d8 commit db5a13d

1 file changed

Lines changed: 7 additions & 5 deletions

File tree

FtpServer.cpp

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -448,13 +448,15 @@ uint8_t FtpServer::handleFTP() {
448448

449449
// Out of the chain above, whose tail this was: a running transfer always took its own
450450
// branch, so the deadline was never reached — and doRetrieve() now waits a stalled peer
451-
// out instead of aborting, leaving nothing else to end it. RETR refreshes this deadline
452-
// as it sends; the other types never do, so bounding them would kill them mid-progress.
453-
const bool in_retrieve = (transferStage == FTP_Retrieve);
454-
if (cmdStage > FTP_Client && (transferStage == FTP_Close || in_retrieve)
451+
// out instead of aborting, leaving nothing else to end it. RETR and the listings both
452+
// refresh this deadline as they send, so it ends only what stopped sending; STOR does
453+
// not refresh it and stays out of scope rather than die mid-progress.
454+
const bool in_transfer = (transferStage == FTP_Retrieve || transferStage == FTP_List
455+
|| transferStage == FTP_Nlst || transferStage == FTP_Mlsd);
456+
if (cmdStage > FTP_Client && (transferStage == FTP_Close || in_transfer)
455457
&& !((int32_t) (millisEndConnection - millis()) > 0)) {
456458
DEBUG_PRINTLN(F("Timeout"));
457-
if (in_retrieve) {
459+
if (in_transfer) {
458460
// NOT closeTransfer(): that answers 226. abortTransfer() replies 426 and fires
459461
// FTP_TRANSFER_ERROR, which releases what the app took.
460462
abortTransfer();

0 commit comments

Comments
 (0)