From 057c058ca360e19896636f0bd4859121fd1a2e71 Mon Sep 17 00:00:00 2001 From: Th3maz1ng Date: Sat, 23 Apr 2022 22:39:46 +0200 Subject: [PATCH] Renamed FtpMsgCode to FTPMsgCode, Added new state in the FileTransferStatus enum : MALLOC_ERROR, reworked the way the send and receive buffer is allocated, this is not done on the stack anymore which led to a silent stack overflow :-(. Changed the way the IP address is retrieved to open the passive connection --- src/app/FTPServer.h | 89 +++++++++++++++++++++++++++++---------------- 1 file changed, 58 insertions(+), 31 deletions(-) diff --git a/src/app/FTPServer.h b/src/app/FTPServer.h index 0e23015..630845a 100644 --- a/src/app/FTPServer.h +++ b/src/app/FTPServer.h @@ -6,7 +6,7 @@ #include "utilities.h" #include "Dictionary.h" //#define DEBUG_FTPS -#define READ_BUFFER_SIZE 2048 //2048 is max to read sd card, more will crash +#define SEND_RECV_BUFFER_SIZE 5000 template class FTPServer : public TCPServer @@ -14,9 +14,9 @@ class FTPServer : public TCPServer public: enum FTPClientState {INIT, WAITING_FOR_COMMANDS}; enum FTPClientDataTransfer {NONE = 0, LIST_DF, NLST_DF, RETR_DF, STOR_DF, APPE_DF}; - enum FileTransferStatus {OK, NOT_FOUND, NO_FILE_NAME}; + enum FileTransferStatus {OK, NOT_FOUND, NO_FILE_NAME, MALLOC_ERROR}; enum BinaryFlag {OFF = 0, ON}; - enum FtpMsgCode {_150, _200, _215, _220, _221, _230, _226, _227, _250, _257, _331, _350, _451, _5_502, _504, _530, _550 }; + enum FTPMsgCode {_150, _200, _215, _220, _221, _230, _226, _227, _250, _257, _331, _350, _451, _5_502, _504, _530, _550 }; FTPServer(uint16_t port = 21, SDClass *sdClass = NULL, const char *login = NULL, const char *password = NULL, uint8_t maxClient = MAX_CLIENT, uint16_t clientCommandDataBufferSize = 255) : TCPServer(port, maxClient, clientCommandDataBufferSize), _login(NULL), @@ -140,7 +140,7 @@ class FTPServer : public TCPServer client->_client.println("150 File status okay."); FileTransferStatus fts; - if(!sendFile(client,&fts))//File was sent or error occured + if(!sendFile(client,&fts))//Whole file was sent or error an occured { //we check the return code if(fts == OK) @@ -155,6 +155,12 @@ class FTPServer : public TCPServer client->closeDataConnection(); client->_dataTransferPending = NONE; } + else if(fts == MALLOC_ERROR) + { + client->_client.println("451 Insufficient RAM space."); + client->closeDataConnection(); + client->_dataTransferPending = NONE; + } } } else if(client->_fileSentBytes != 0) @@ -181,6 +187,14 @@ class FTPServer : public TCPServer { client->_client.println("501 No file name given."); } + else if(fts == NOT_FOUND) + { + client->_client.println("451 File not found."); + } + else if(fts == MALLOC_ERROR) + { + client->_client.println("451 Insufficient RAM space."); + } else { client->_client.println("451 Requested action aborted: local error in processing."); @@ -238,6 +252,14 @@ class FTPServer : public TCPServer { client->_client.println("501 No file name given."); } + else if(fts == NOT_FOUND) + { + client->_client.println("451 File not found."); + } + else if(fts == MALLOC_ERROR) + { + client->_client.println("451 Insufficient RAM space."); + } else { client->_client.println("451 Requested action aborted: local error in processing."); @@ -397,23 +419,7 @@ class FTPServer : public TCPServer return; } - //We need to test if we are in softAP or STA to chose the right IP - uint8_t addr[4] = {0}; - if(WiFi.status() == WL_CONNECTED) - { - addr[0] = WiFi.localIP()[0]; - addr[1] = WiFi.localIP()[1]; - addr[2] = WiFi.localIP()[2]; - addr[3] = WiFi.localIP()[3]; - }else - { - addr[0] = WiFi.softAPIP()[0]; - addr[1] = WiFi.softAPIP()[1]; - addr[2] = WiFi.softAPIP()[2]; - addr[3] = WiFi.softAPIP()[3]; - } - - client->_client.printf("227 Entering Passive Mode (%u,%u,%u,%u,%d,%d).\r\n", addr[0], addr[1], addr[2], addr[3], _dataPort / 256, _dataPort % 256); + client->_client.printf("227 Entering Passive Mode (%u,%u,%u,%u,%d,%d).\r\n", client->_client.localIP()[0], client->_client.localIP()[1], client->_client.localIP()[2], client->_client.localIP()[3], _dataPort / 256, _dataPort % 256); #ifdef DEBUG_FTPS Serial.println("Opening data server for new data client"); #endif @@ -803,13 +809,22 @@ class FTPServer : public TCPServer if(fileBeeingReceived) { - uint8_t recvBuffer[2048]; + size_t mallocAcceptedSize(0); + uint8_t *recvBuffer = (uint8_t*)mallocWithFallback(SEND_RECV_BUFFER_SIZE * sizeof(uint8_t), &mallocAcceptedSize); + + if(!recvBuffer) + { + *fts = MALLOC_ERROR; + fileBeeingReceived.close(); + return false; + } /*fileBeeingReceived.seek(client->_fileRecvBytes);*/ - uint16_t size = client->_dataClient.read(recvBuffer, 2048); - + size_t size = client->_dataClient.read(recvBuffer, mallocAcceptedSize); fileBeeingReceived.write(recvBuffer, size); + free(recvBuffer); + client->_fileRecvBytes += size; fileBeeingReceived.close(); #ifdef DEBUG_FTPS @@ -818,6 +833,7 @@ class FTPServer : public TCPServer } else { + *fts = NOT_FOUND; return false; } } @@ -840,7 +856,7 @@ class FTPServer : public TCPServer File currentDirectory = _sdClass->open(client->_currentDirectory); if (currentDirectory) { - currentDirectory.rewindDirectory(); + //currentDirectory.rewindDirectory(); while (true) //May be removed in the future to improve responsiveness { File fileOrDir = currentDirectory.openNextFile(); @@ -890,26 +906,37 @@ class FTPServer : public TCPServer //The binary flag needs to be taken into consideration IRAM_ATTR inline boolean sendFile(T *client, FileTransferStatus *fts) { - if (client->_currentFile != NULL) + if (client->_currentFile != nullptr) { - uint8_t sendBuffer[READ_BUFFER_SIZE]; File fileToSend = _sdClass->open(client->_currentFile); if (fileToSend) { *fts = OK; - unsigned int readBytes(0); + size_t readBytes(0); fileToSend.seek(client->_fileSentBytes); if(fileToSend.available()) { - readBytes = fileToSend.read(sendBuffer, READ_BUFFER_SIZE); + size_t mallocAcceptedSize(0); + uint8_t *sendBuffer = (uint8_t*)mallocWithFallback(SEND_RECV_BUFFER_SIZE * sizeof(uint8_t), &mallocAcceptedSize); + + if(!sendBuffer) + { + *fts = MALLOC_ERROR; + fileToSend.close(); + return false; + } + + readBytes = fileToSend.read(sendBuffer, mallocAcceptedSize); client->_dataClient.write(sendBuffer, readBytes); + free(sendBuffer); + client->_fileSentBytes += readBytes; #ifdef DEBUG_FTPS - Serial.printf("File : bytes sent : %u\n",readBytes); + Serial.printf("File : bytes sent : %u - free stack : %u\n", readBytes, ESP.getFreeContStack()); #endif } else //The whole file has been sent @@ -978,7 +1005,7 @@ class FTPServer : public TCPServer } //Error code functions - void sendInfoResponse(FtpMsgCode code, T *client, const char *msg = "") + void sendInfoResponse(FTPMsgCode code, T *client, const char *msg = "") { switch(code) {