From 49bde8258108057cff01dcef0c36d640373e2e79 Mon Sep 17 00:00:00 2001 From: Daniel Plasa Date: Tue, 26 May 2020 18:30:45 +0200 Subject: use ESP.getMaxFreeBlockSize() / 2 as transfer buffer size for RETR use 2048 bytes for STOR --- espFtpServer.cpp | 77 ++++++++++++++---------------- espFtpServer.h | 20 ++++---- examples/LittleFSSample/LittleFSSample.ino | 7 ++- examples/SPIFFSSample/SPIFFSSample.ino | 4 +- library.properties | 2 +- 5 files changed, 52 insertions(+), 58 deletions(-) diff --git a/espFtpServer.cpp b/espFtpServer.cpp index aa67fe3..5158243 100644 --- a/espFtpServer.cpp +++ b/espFtpServer.cpp @@ -103,9 +103,6 @@ void FtpServer::iniVariables() void FtpServer::handleFTP() { - // if ((int32_t)(millisDelay - millis()) > 0) - // return; - // // control connection state sequence is // cInit @@ -130,6 +127,10 @@ void FtpServer::handleFTP() // V // cProcess // + + // if ((int32_t)(millisDelay - millis()) > 0) + // return; + if (cmdState == cInit) { if (control.connected()) @@ -766,15 +767,16 @@ int8_t FtpServer::processCommand() transferState = tRetrieve; millisBeginTrans = millis(); bytesTransfered = 0; - if (allocateBuffer(file.size()) <= 0) + uint32_t fs = file.size(); + if (allocateBuffer(fs > 32768 ? 32768 : fs)) { - closeTransfer(); - FTP_SEND_MSG(451, "Internal error. Not enough memory."); + FTP_DEBUG_MSG("Sending file '%s'", path.c_str()); + FTP_SEND_MSG(150, "%lu bytes to download", fs); } else { - FTP_DEBUG_MSG("Sending file '%s'", path.c_str()); - FTP_SEND_MSG(150, "%lu bytes to download", (uint32_t)file.size()); + closeTransfer(); + FTP_SEND_MSG(451, "Internal error. Not enough memory."); } } } @@ -813,15 +815,15 @@ int8_t FtpServer::processCommand() transferState = tStore; millisBeginTrans = millis(); bytesTransfered = 0; - if (allocateBuffer(2048) <= 0) + if (allocateBuffer(2048)) { - closeTransfer(); - FTP_SEND_MSG(451, "Internal error. Not enough memory."); + FTP_DEBUG_MSG("Receiving file '%s' => %s", parameters.c_str(), path.c_str()); + FTP_SEND_MSG(150, "Connected to port %d", dataPort); } else { - FTP_DEBUG_MSG("Receiving file '%s' => %s", parameters.c_str(), path.c_str()); - FTP_SEND_MSG(150, "Connected to port %d", dataPort); + closeTransfer(); + FTP_SEND_MSG(451, "Internal error. Not enough memory."); } } } @@ -1022,28 +1024,22 @@ int8_t FtpServer::dataConnect() return rc; } -int32_t FtpServer::allocateBuffer(int32_t desiredBytes) +uint16_t FtpServer::allocateBuffer(uint16_t desiredBytes) { - // allocate a large buffer for file transfers - int32_t maxBlock = ESP.getMaxFreeBlockSize(); - int32_t maxHeap = ESP.getFreeHeap(); - if (maxBlock - desiredBytes < 0) - desiredBytes = maxBlock; + // allocate a big buffer for file transfers + uint16_t maxBlock = ESP.getMaxFreeBlockSize() / 2; - // leave at least (20% of heap) as reserve - if (maxHeap - desiredBytes < (maxHeap / 5)) - desiredBytes -= (maxHeap / 5); + if (desiredBytes > maxBlock) + desiredBytes = maxBlock; - // round down on 4byte bound - desiredBytes &= ~3; while (fileBuffer == NULL && desiredBytes > 0) { fileBuffer = (uint8_t *)malloc(desiredBytes); if (NULL == fileBuffer) { FTP_DEBUG_MSG("Cannot allocate buffer for file transfer, re-trying"); - // try less - desiredBytes -= 16; + // try with less bytes + desiredBytes--; } else { @@ -1061,18 +1057,19 @@ void FtpServer::freeBuffer() bool FtpServer::doRetrieve() { - // how many bytes to transfer - int32_t nb = (file.size() - bytesTransfered); - if (nb > fileBufferSize) - nb = fileBufferSize; - // data connection lost or no more bytes to transfer? - if (!data.connected() || (nb <= 0)) + if (!data.connected() || (bytesTransfered >= file.size())) { return false; } + // how many bytes to transfer left? + uint32_t nb = (file.size() - bytesTransfered); + if (nb > fileBufferSize) + nb = fileBufferSize; + // transfer the file + FTP_DEBUG_MSG("Transfer %d bytes fs->client", nb); nb = file.readBytes((char *)fileBuffer, nb); if (nb > 0) { @@ -1086,27 +1083,25 @@ bool FtpServer::doRetrieve() bool FtpServer::doStore() { // Avoid blocking by never reading more bytes than are available - int32_t navail = data.available(); + int16_t navail = data.available(); if (navail > 0) { if (navail > fileBufferSize) navail = fileBufferSize; - - int16_t nb = data.read(fileBuffer, navail); - FTP_DEBUG_MSG("Transfer %d bytes at one batch (buf %d bytes)", nb, nsavail); - if (nb > 0) - { - file.write(fileBuffer, nb); - bytesTransfered += nb; - } + FTP_DEBUG_MSG("Transfer %d bytes client->fs", navail); + navail = data.read(fileBuffer, navail); + file.write(fileBuffer, navail); } + if (!data.connected() && (navail <= 0)) { + // connection closed or no more bytes to read return false; } else { + // inidcate, we need to be called again return true; } } diff --git a/espFtpServer.h b/espFtpServer.h index a9f8d56..d4b3f44 100644 --- a/espFtpServer.h +++ b/espFtpServer.h @@ -51,7 +51,7 @@ #define FTP_DEBUG_MSG(...) #endif -#define FTP_SERVER_VERSION "0.9.2-20200526" +#define FTP_SERVER_VERSION "0.9.3-20200526" #define FTP_CTRL_PORT 21 // Command port on wich server is listening #define FTP_DATA_PORT_PASV 50009 // Data port in passive mode @@ -105,10 +105,10 @@ private: bool doStore(); void closeTransfer(); void abortTransfer(); - int32_t allocateBuffer(int32_t desiredBytes); + uint16_t allocateBuffer(uint16_t desiredBytes); void freeBuffer(); - String getPathName(const String& param, bool includeLast = false); + String getPathName(const String ¶m, bool includeLast = false); String getFileName(const String ¶m, bool fullFilePath = false); String makeDateTimeStr(time_t fileTime); int8_t readChar(); @@ -124,12 +124,12 @@ private: uint16_t dataPort = // holds our PASV port number or the port number provided by PORT FTP_DATA_PORT_PASV; - uint32_t command; // numeric command code of command sent by the client - String cmdLine; // command line as read from client - String cmdString; // command as textual representation - String parameters; // parameters sent by client - String cwd; // the current directory - String rnFrom; // previous command was RNFR, this is the source file name + uint32_t command; // numeric command code of command sent by the client + String cmdLine; // command line as read from client + String cmdString; // command as textual representation + String parameters; // parameters sent by client + String cwd; // the current directory + String rnFrom; // previous command was RNFR, this is the source file name internalState cmdState, // state of ftp control connection transferState; // state of ftp data connection @@ -139,7 +139,7 @@ private: millisBeginTrans, // store time of beginning of a transaction bytesTransfered; // uint8_t *fileBuffer = NULL; // pointer to buffer for file transfer (by allocateBuffer) - int32_t fileBufferSize; // size of buffer + uint16_t fileBufferSize; // size of buffer String _FTP_USER; // usename String _FTP_PASS; // password }; diff --git a/examples/LittleFSSample/LittleFSSample.ino b/examples/LittleFSSample/LittleFSSample.ino index b6bfdd6..b5dc797 100644 --- a/examples/LittleFSSample/LittleFSSample.ino +++ b/examples/LittleFSSample/LittleFSSample.ino @@ -16,17 +16,16 @@ */ #ifdef ESP8266 -#include #include #elif defined ESP32 #include -#include #endif +#include #include -const char *ssid PROGMEM = ""; -const char *password PROGMEM = ""; +const char *ssid PROGMEM = "YOUR_SSID"; +const char *password PROGMEM = "YOUR_PASS"; // tell the FtpServer to use LittleFS FtpServer ftpSrv(LittleFS); diff --git a/examples/SPIFFSSample/SPIFFSSample.ino b/examples/SPIFFSSample/SPIFFSSample.ino index 6438afe..dce703c 100644 --- a/examples/SPIFFSSample/SPIFFSSample.ino +++ b/examples/SPIFFSSample/SPIFFSSample.ino @@ -25,8 +25,8 @@ #include -const char *ssid PROGMEM = ""; -const char *password PROGMEM = ""; +const char *ssid PROGMEM = "YOUR_SSID"; +const char *password PROGMEM = "YOUR_PASS"; // Since SPIFFS is becoming deprecated but might still be in // use in your Projects, tell the FtpServer to use SPIFFS diff --git a/library.properties b/library.properties index 335af06..8817300 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=espFtpServer -version=0.9.2 +version=0.9.3 author=Daniel Plasa maintainer=dplasa@gmail.com sentence=Simple FTP server for SPIFFS and LittleFS on esp8266/esp32 -- cgit v1.2.3