diff options
-rw-r--r-- | FTPClient.cpp | 15 | ||||
-rw-r--r-- | FTPClient.h | 2 | ||||
-rw-r--r-- | FTPCommon.cpp | 7 | ||||
-rw-r--r-- | FTPCommon.h | 15 | ||||
-rw-r--r-- | FTPServer.cpp | 46 | ||||
-rw-r--r-- | FTPServer.h | 8 | ||||
-rw-r--r-- | library.properties | 2 |
7 files changed, 44 insertions, 51 deletions
diff --git a/FTPClient.cpp b/FTPClient.cpp index e32af21..84c4fdb 100644 --- a/FTPClient.cpp +++ b/FTPClient.cpp @@ -10,6 +10,8 @@ FTPClient::FTPClient(FS &_FSImplementation) : FTPCommon(_FSImplementation) { + // set aTimeout to never expire, will be used later by ::waitFor(...) + aTimeout.resetToNeverExpires(); } void FTPClient::begin(const ServerInfo &theServer) @@ -216,20 +218,20 @@ int8_t FTPClient::controlConnect() return -1; } -bool FTPClient::waitFor(const uint16_t respCode, const __FlashStringHelper *errorString, uint16_t timeOut) +bool FTPClient::waitFor(const int16_t respCode, const __FlashStringHelper *errorString, uint16_t timeOutMs) { // initalize waiting - if (0 == waitUntil) + if (!aTimeout.canExpire()) { - waitUntil = millis(); - waitUntil += timeOut; + aTimeout.reset(timeOutMs); _serverStatus.desc.clear(); } else { // timeout - if ((int32_t)(millis() - waitUntil) >= 0) + if (aTimeout.expired()) { + aTimeout.resetToNeverExpires(); FTP_DEBUG_MSG("Waiting for code %u - timeout!", respCode); _serverStatus.code = errorTimeout; if (errorString) @@ -241,7 +243,6 @@ bool FTPClient::waitFor(const uint16_t respCode, const __FlashStringHelper *erro _serverStatus.desc = F("timeout"); } ftpState = cTimeout; - waitUntil = 0; return false; } @@ -269,7 +270,7 @@ bool FTPClient::waitFor(const uint16_t respCode, const __FlashStringHelper *erro FTP_DEBUG_MSG("Waiting for code %u success, SMTP server replies: %s", respCode, _serverStatus.desc.c_str()); } - waitUntil = 0; + aTimeout.resetToNeverExpires(); return (respCode == _serverStatus.code); } else diff --git a/FTPClient.h b/FTPClient.h index 1d3d6b4..9f3fd06 100644 --- a/FTPClient.h +++ b/FTPClient.h @@ -108,7 +108,7 @@ protected: int8_t controlConnect(); // connects to ServerInfo, returns -1: no connection possible, +1: connection established - bool waitFor(const uint16_t respCode, const __FlashStringHelper *errorString = nullptr, uint16_t timeOut = 10000); + bool waitFor(const int16_t respCode, const __FlashStringHelper *errorString = nullptr, uint16_t timeOut = 10000); }; // basically just the same as FTPClient but has a different connect() method to account for SSL/TLS diff --git a/FTPCommon.cpp b/FTPCommon.cpp index 66211a8..4b8af4c 100644 --- a/FTPCommon.cpp +++ b/FTPCommon.cpp @@ -1,6 +1,7 @@ #include "FTPCommon.h" -FTPCommon::FTPCommon(FS &_FSImplementation) : THEFS(_FSImplementation) +FTPCommon::FTPCommon(FS &_FSImplementation) : + THEFS(_FSImplementation), sTimeOutMs(FTP_TIME_OUT*60*1000), aTimeout(FTP_TIME_OUT*60*1000) { } @@ -17,9 +18,9 @@ void FTPCommon::stop() freeBuffer(); } -void FTPCommon::setTimeout(uint16_t timeout) +void FTPCommon::setTimeout(uint32_t timeoutMs) { - sTimeOut = timeout; + sTimeOutMs = timeoutMs; } uint16_t FTPCommon::allocateBuffer(uint16_t desiredBytes) diff --git a/FTPCommon.h b/FTPCommon.h index 55844f7..9b3fb29 100644 --- a/FTPCommon.h +++ b/FTPCommon.h @@ -5,8 +5,9 @@ #include <FS.h> #include <WiFiClient.h> #include <WString.h> +#include <PolledTimeout.h> -#define FTP_CTRL_PORT 21 // Command port on wich server is listening +#define FTP_CTRL_PORT 21 // Command port on which server is listening #define FTP_DATA_PORT_PASV 50009 // Data port in passive mode #define FTP_TIME_OUT 5 // Disconnect client after 5 minutes of inactivity #define FTP_CMD_SIZE 127 // allow max. 127 chars in a received command @@ -81,6 +82,8 @@ #define FTP_CMD_LE_SYST 0x54535953 // "SYST" as uint32_t (little endian) #define FTP_CMD_BE_SYST 0x53595354 // "SYST" as uint32_t (big endian) +using esp8266::polledTimeout::oneShotMs; // import the type to the local namespace + class FTPCommon { public: @@ -89,11 +92,11 @@ public: FTPCommon(FS &_FSImplementation); virtual ~FTPCommon(); - // stops the FTP Server or Client + // stops the FTP Server or Client, i.e. stops control and data connections virtual void stop(); - // set a timeout in seconds - void setTimeout(uint16_t timeout = FTP_TIME_OUT * 60); + // set disconnect timeout in millisecords + void setTimeout(uint32_t timeoutMs = FTP_TIME_OUT * 60 * 1000); // needs to be called frequently (e.g. in loop() ) // to process ftp requests @@ -112,8 +115,8 @@ protected: virtual int8_t dataConnect(); // connects to dataIP:dataPort, returns -1: no data connection possible, +1: data connection established bool parseDataIpPort(const char *p); - uint16_t sTimeOut = // disconnect after 5 min of inactivity - FTP_TIME_OUT * 60; + uint32_t sTimeOutMs; // disconnect timeout + oneShotMs aTimeout; // timeout from esp8266 core library bool doFiletoNetwork(); bool doNetworkToFile(); diff --git a/FTPServer.cpp b/FTPServer.cpp index 4a03712..e153649 100644 --- a/FTPServer.cpp +++ b/FTPServer.cpp @@ -56,7 +56,10 @@ static const char aSpace[] PROGMEM = " "; static const char aSlash[] PROGMEM = "/"; // constructor -FTPServer::FTPServer(FS &_FSImplementation) : FTPCommon(_FSImplementation) {} +FTPServer::FTPServer(FS &_FSImplementation) : FTPCommon(_FSImplementation) +{ + aTimeout.resetToNeverExpires(); +} void FTPServer::begin(const String &uname, const String &pword) { @@ -151,7 +154,7 @@ void FTPServer::handleFTP() control = controlServer.available(); // wait 10s for login command - updateTimeout(10); + aTimeout.reset(10 * 1000); cmdState = cCheck; } } @@ -185,7 +188,7 @@ void FTPServer::handleFTP() else if (cmdState == cLoginOk) // tell client "Login ok!" { FTP_SEND_MSG(230, "Login successful."); - updateTimeout(sTimeOut); + aTimeout.reset(sTimeOutMs); cmdState = cProcess; } @@ -194,12 +197,13 @@ void FTPServer::handleFTP() // else if (readChar() > 0) { - // enforce USER than PASS commands before anything else - if (((cmdState == cUserId) && (FTP_CMD(USER) != command)) || - ((cmdState == cPassword) && (FTP_CMD(PASS) != command))) + // enforce USER than PASS commands before anything else except the FEAT command + // that should be supported to indicate server features even before login + if ((FTP_CMD(FEAT) != command) && (((cmdState == cUserId) && (FTP_CMD(USER) != command)) || + ((cmdState == cPassword) && (FTP_CMD(PASS) != command)))) { FTP_SEND_MSG(530, "Please login with USER and PASS."); - FTP_DEBUG_MSG("ignoring before login: cwd=%s cmd[%x]=%s, params='%s'", cwd.c_str(), command, cmdString.c_str(), parameters.c_str()); + FTP_DEBUG_MSG("ignoring before login: command %s [%x], params='%s'", cmdString.c_str(), command, parameters.c_str()); command = 0; return; } @@ -225,7 +229,7 @@ void FTPServer::handleFTP() if (_FTP_PASS.length()) { // wait 10s for PASS command - updateTimeout(10); + aTimeout.reset(10 * 1000); FTP_SEND_MSG(331, "Please specify the password."); cmdState = cPassword; } @@ -240,7 +244,7 @@ void FTPServer::handleFTP() } else { - updateTimeout(sTimeOut); + aTimeout.reset(sTimeOutMs); } } } @@ -259,7 +263,7 @@ void FTPServer::handleFTP() } // check for timeout - if (!((int32_t)(millisEndConnection - millis()) > 0)) + if (aTimeout.expired()) { FTP_SEND_MSG(530, "Timeout."); FTP_DEBUG_MSG("client connection timed out"); @@ -308,7 +312,7 @@ int8_t FTPServer::processCommand() // make the full path of parameters (even if this makes no sense for all commands) String path = getFileName(parameters, true); - FTP_DEBUG_MSG("processing: cmd=%s[%x], params='%s' (cwd='%s')", cmdString.c_str(), command, parameters.c_str()); + FTP_DEBUG_MSG("processing: command %s [%x], params='%s' (cwd='%s')", cmdString.c_str(), command, parameters.c_str(), cwd.c_str()); /////////////////////////////////////// // // @@ -472,7 +476,7 @@ int8_t FTPServer::processCommand() else { FTP_SEND_MSG(501, "Can't interpret parameters"); - } + } } // @@ -596,10 +600,6 @@ int8_t FTPServer::processCommand() { data.println(fn); } - else - { - FTP_DEBUG_MSG("Implemetation of %s [%x] command - internal BUG", cmdString.c_str(), command); - } } if (FTP_CMD(MLSD) == command) @@ -910,6 +910,8 @@ int8_t FTPServer::processCommand() else if (FTP_CMD(FEAT) == command) { FTP_SEND_DASHMSG(211, "Features:\r\n MLSD\r\n MDTM\r\n SIZE\r\n211 End."); + command = 0; // clear command code and + rc = 0; // return 0 to prevent progression of state machine in case FEAT was a command before login } // @@ -967,7 +969,7 @@ int8_t FTPServer::processCommand() // else { - FTP_DEBUG_MSG("Unknown command: %s [%#x], param: '%s')", cmdString.c_str(), command, parameters.c_str()); + FTP_DEBUG_MSG("Unknown command: %s, params: '%s')", cmdString.c_str(), parameters.c_str()); FTP_SEND_MSG(500, "unknown command \"%s\"", cmdString.c_str()); } @@ -1006,7 +1008,6 @@ int8_t FTPServer::dataConnect() return rc; } - void FTPServer::closeTransfer() { uint32_t deltaT = (int32_t)(millis() - millisBeginTrans); @@ -1085,7 +1086,7 @@ int8_t FTPServer::readChar() // clear cmdline cmdLine.clear(); - FTP_DEBUG_MSG("readChar() success, command=%x, cmdString='%s', params='%s'", command, cmdString.c_str(), parameters.c_str()); + // FTP_DEBUG_MSG("readChar() success, cmdString='%s' [%x], params='%s'", cmdString.c_str(), command, parameters.c_str()); return 1; } else @@ -1196,10 +1197,3 @@ String FTPServer::makeDateTimeStr(time_t ft) strftime((char *)tmp.c_str(), 17, "%Y%m%d%H%M%S", _tm); return tmp; } - -void FTPServer::updateTimeout(uint16_t s) -{ - millisEndConnection = s; - millisEndConnection *= 60000UL; - millisEndConnection += millis(); -} diff --git a/FTPServer.h b/FTPServer.h index f5f1448..84e20a7 100644 --- a/FTPServer.h +++ b/FTPServer.h @@ -30,7 +30,7 @@ ** ** *******************************************************************************/ #include "FTPCommon.h" -#define FTP_SERVER_VERSION "0.9.6-20200526" +#define FTP_SERVER_VERSION "0.9.7-20200529" class FTPServer : public FTPCommon { @@ -46,9 +46,6 @@ public: // stops the FTP server void stop(); - // set the FTP server's timeout in seconds - void setTimeout(uint16_t timeout = FTP_TIME_OUT * 60); - // needs to be called frequently (e.g. in loop() ) // to process ftp requests void handleFTP(); @@ -81,7 +78,6 @@ private: String getFileName(const String ¶m, bool fullFilePath = false); String makeDateTimeStr(time_t fileTime); int8_t readChar(); - void updateTimeout(uint16_t timeout); // server specific bool dataPassiveConn = true; // PASV (passive) mode is our default @@ -96,8 +92,6 @@ private: internalState cmdState, // state of ftp control connection transferState; // state of ftp data connection - - uint32_t millisEndConnection; }; #endif // FTP_SERVER_H diff --git a/library.properties b/library.properties index cfaf8cf..0bf7adb 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=FtpClientServer -version=0.9.6 +version=0.9.7 author=Daniel Plasa maintainer=dplasa@gmail.com sentence=Simple FTP server for SPIFFS and LittleFS on esp8266/esp32 |