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
This commit is contained in:
parent
4297df4acb
commit
057c058ca3
@ -6,7 +6,7 @@
|
|||||||
#include "utilities.h"
|
#include "utilities.h"
|
||||||
#include "Dictionary.h"
|
#include "Dictionary.h"
|
||||||
//#define DEBUG_FTPS
|
//#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 <typename T>
|
template <typename T>
|
||||||
class FTPServer : public TCPServer<T>
|
class FTPServer : public TCPServer<T>
|
||||||
@ -14,9 +14,9 @@ class FTPServer : public TCPServer<T>
|
|||||||
public:
|
public:
|
||||||
enum FTPClientState {INIT, WAITING_FOR_COMMANDS};
|
enum FTPClientState {INIT, WAITING_FOR_COMMANDS};
|
||||||
enum FTPClientDataTransfer {NONE = 0, LIST_DF, NLST_DF, RETR_DF, STOR_DF, APPE_DF};
|
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 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<T>(port, maxClient, clientCommandDataBufferSize),
|
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<T>(port, maxClient, clientCommandDataBufferSize),
|
||||||
_login(NULL),
|
_login(NULL),
|
||||||
@ -140,7 +140,7 @@ class FTPServer : public TCPServer<T>
|
|||||||
client->_client.println("150 File status okay.");
|
client->_client.println("150 File status okay.");
|
||||||
|
|
||||||
FileTransferStatus fts;
|
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
|
//we check the return code
|
||||||
if(fts == OK)
|
if(fts == OK)
|
||||||
@ -155,6 +155,12 @@ class FTPServer : public TCPServer<T>
|
|||||||
client->closeDataConnection();
|
client->closeDataConnection();
|
||||||
client->_dataTransferPending = NONE;
|
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)
|
else if(client->_fileSentBytes != 0)
|
||||||
@ -181,6 +187,14 @@ class FTPServer : public TCPServer<T>
|
|||||||
{
|
{
|
||||||
client->_client.println("501 No file name given.");
|
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
|
else
|
||||||
{
|
{
|
||||||
client->_client.println("451 Requested action aborted: local error in processing.");
|
client->_client.println("451 Requested action aborted: local error in processing.");
|
||||||
@ -238,6 +252,14 @@ class FTPServer : public TCPServer<T>
|
|||||||
{
|
{
|
||||||
client->_client.println("501 No file name given.");
|
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
|
else
|
||||||
{
|
{
|
||||||
client->_client.println("451 Requested action aborted: local error in processing.");
|
client->_client.println("451 Requested action aborted: local error in processing.");
|
||||||
@ -397,23 +419,7 @@ class FTPServer : public TCPServer<T>
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//We need to test if we are in softAP or STA to chose the right IP
|
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);
|
||||||
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);
|
|
||||||
#ifdef DEBUG_FTPS
|
#ifdef DEBUG_FTPS
|
||||||
Serial.println("Opening data server for new data client");
|
Serial.println("Opening data server for new data client");
|
||||||
#endif
|
#endif
|
||||||
@ -803,13 +809,22 @@ class FTPServer : public TCPServer<T>
|
|||||||
|
|
||||||
if(fileBeeingReceived)
|
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);*/
|
/*fileBeeingReceived.seek(client->_fileRecvBytes);*/
|
||||||
uint16_t size = client->_dataClient.read(recvBuffer, 2048);
|
size_t size = client->_dataClient.read(recvBuffer, mallocAcceptedSize);
|
||||||
|
|
||||||
fileBeeingReceived.write(recvBuffer, size);
|
fileBeeingReceived.write(recvBuffer, size);
|
||||||
|
|
||||||
|
free(recvBuffer);
|
||||||
|
|
||||||
client->_fileRecvBytes += size;
|
client->_fileRecvBytes += size;
|
||||||
fileBeeingReceived.close();
|
fileBeeingReceived.close();
|
||||||
#ifdef DEBUG_FTPS
|
#ifdef DEBUG_FTPS
|
||||||
@ -818,6 +833,7 @@ class FTPServer : public TCPServer<T>
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
*fts = NOT_FOUND;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -840,7 +856,7 @@ class FTPServer : public TCPServer<T>
|
|||||||
File currentDirectory = _sdClass->open(client->_currentDirectory);
|
File currentDirectory = _sdClass->open(client->_currentDirectory);
|
||||||
if (currentDirectory)
|
if (currentDirectory)
|
||||||
{
|
{
|
||||||
currentDirectory.rewindDirectory();
|
//currentDirectory.rewindDirectory();
|
||||||
while (true) //May be removed in the future to improve responsiveness
|
while (true) //May be removed in the future to improve responsiveness
|
||||||
{
|
{
|
||||||
File fileOrDir = currentDirectory.openNextFile();
|
File fileOrDir = currentDirectory.openNextFile();
|
||||||
@ -890,26 +906,37 @@ class FTPServer : public TCPServer<T>
|
|||||||
//The binary flag needs to be taken into consideration
|
//The binary flag needs to be taken into consideration
|
||||||
IRAM_ATTR inline boolean sendFile(T *client, FileTransferStatus *fts)
|
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);
|
File fileToSend = _sdClass->open(client->_currentFile);
|
||||||
|
|
||||||
if (fileToSend)
|
if (fileToSend)
|
||||||
{
|
{
|
||||||
*fts = OK;
|
*fts = OK;
|
||||||
unsigned int readBytes(0);
|
size_t readBytes(0);
|
||||||
fileToSend.seek(client->_fileSentBytes);
|
fileToSend.seek(client->_fileSentBytes);
|
||||||
|
|
||||||
if(fileToSend.available())
|
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);
|
client->_dataClient.write(sendBuffer, readBytes);
|
||||||
|
|
||||||
|
free(sendBuffer);
|
||||||
|
|
||||||
client->_fileSentBytes += readBytes;
|
client->_fileSentBytes += readBytes;
|
||||||
|
|
||||||
#ifdef DEBUG_FTPS
|
#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
|
#endif
|
||||||
}
|
}
|
||||||
else //The whole file has been sent
|
else //The whole file has been sent
|
||||||
@ -978,7 +1005,7 @@ class FTPServer : public TCPServer<T>
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Error code functions
|
//Error code functions
|
||||||
void sendInfoResponse(FtpMsgCode code, T *client, const char *msg = "")
|
void sendInfoResponse(FTPMsgCode code, T *client, const char *msg = "")
|
||||||
{
|
{
|
||||||
switch(code)
|
switch(code)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user