FTPServer implemented, small bugs to fix...
This commit is contained in:
parent
f0398b717b
commit
7d60a8d9d0
@ -8,6 +8,7 @@ _username(NULL),
|
|||||||
_currentDirectory(NULL),
|
_currentDirectory(NULL),
|
||||||
_currentFile(NULL),
|
_currentFile(NULL),
|
||||||
_fileSentBytes(0),
|
_fileSentBytes(0),
|
||||||
|
_fileRecvBytes(0),
|
||||||
_waitingForDataConnection(false),
|
_waitingForDataConnection(false),
|
||||||
_fileIsBeeingReceived(false),
|
_fileIsBeeingReceived(false),
|
||||||
_ftpClientState(FTPServer<FTPClient>::FTPClientState::INIT),
|
_ftpClientState(FTPServer<FTPClient>::FTPClientState::INIT),
|
||||||
|
@ -28,6 +28,7 @@ class FTPClient : public TCPClient
|
|||||||
char *_currentDirectory;
|
char *_currentDirectory;
|
||||||
char *_currentFile;
|
char *_currentFile;
|
||||||
uint64_t _fileSentBytes;
|
uint64_t _fileSentBytes;
|
||||||
|
uint64_t _fileRecvBytes;
|
||||||
boolean _waitingForDataConnection;
|
boolean _waitingForDataConnection;
|
||||||
boolean _fileIsBeeingReceived;
|
boolean _fileIsBeeingReceived;
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@ class FTPServer : public TCPServer<T>
|
|||||||
public:
|
public:
|
||||||
enum FTPClientState {INIT, WAITING_FOR_COMMANDS};
|
enum FTPClientState {INIT, WAITING_FOR_COMMANDS};
|
||||||
enum FTPClientDataTransfer {NONE, LIST_DF, NLST_DF, RETR_DF, STOR_DF};
|
enum FTPClientDataTransfer {NONE, LIST_DF, NLST_DF, RETR_DF, STOR_DF};
|
||||||
enum FileTransferStatus {OK, NOT_FOUND};
|
enum FileTransferStatus {OK, NOT_FOUND, NO_FILE_NAME};
|
||||||
enum BinaryFlag {OFF = 0, ON};
|
enum BinaryFlag {OFF = 0, ON};
|
||||||
|
|
||||||
FTPServer(unsigned int port = 21, SDCardManager *sdCardManager = NULL, const char *login = NULL, const char *password = NULL, uint8_t maxClient = MAX_CLIENT, uint16_t clientCommandDataBufferSize = 255) : TCPServer<T>(port, maxClient, clientCommandDataBufferSize),
|
FTPServer(unsigned int port = 21, SDCardManager *sdCardManager = NULL, const char *login = NULL, const char *password = NULL, uint8_t maxClient = MAX_CLIENT, uint16_t clientCommandDataBufferSize = 255) : TCPServer<T>(port, maxClient, clientCommandDataBufferSize),
|
||||||
@ -40,6 +40,8 @@ class FTPServer : public TCPServer<T>
|
|||||||
strcpy(_password, password);
|
strcpy(_password, password);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_dataServer.begin(_dataPort);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setCustomDataPort(unsigned int port)
|
void setCustomDataPort(unsigned int port)
|
||||||
@ -69,9 +71,9 @@ class FTPServer : public TCPServer<T>
|
|||||||
{
|
{
|
||||||
if (client->_waitingForDataConnection)
|
if (client->_waitingForDataConnection)
|
||||||
{
|
{
|
||||||
/*#ifdef DEBUG_FTPS
|
//#ifdef DEBUG_FTPS
|
||||||
Serial.println("Listening for new data client");
|
//Serial.println("Listening for new data client");
|
||||||
#endif*/
|
//#endif
|
||||||
WiFiClient dataClient = _dataServer.available();
|
WiFiClient dataClient = _dataServer.available();
|
||||||
|
|
||||||
if (dataClient)
|
if (dataClient)
|
||||||
@ -140,19 +142,32 @@ class FTPServer : public TCPServer<T>
|
|||||||
}*/
|
}*/
|
||||||
break;
|
break;
|
||||||
case STOR_DF :
|
case STOR_DF :
|
||||||
if (client->_dataClient.connected())
|
if (client->_dataClient.connected() || client->_dataClient.available())
|
||||||
{
|
{
|
||||||
char recvBuffer[READ_WRITE_BUFFER_SIZE];
|
|
||||||
if(client->_dataClient.available())
|
if(client->_dataClient.available())
|
||||||
{
|
{
|
||||||
uint16_t size = client->_dataClient.read((uint8_t *)recvBuffer, READ_WRITE_BUFFER_SIZE-1);
|
#ifdef DEBUG_FTPS
|
||||||
recvBuffer[size] = '\0';
|
Serial.printf("receiving file %s\n", client->_currentFile);
|
||||||
Serial.printf("Data : %s\n", recvBuffer);
|
#endif
|
||||||
|
FileTransferStatus fts = OK;
|
||||||
|
|
||||||
|
if(!writeToSdCard(client, &fts)) //An error occured
|
||||||
|
{
|
||||||
|
if(fts == NO_FILE_NAME)
|
||||||
|
{
|
||||||
|
client->_client.println("501 No file name given.");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
client->_client.println("451 Requested action aborted: local error in processing.");
|
||||||
|
}
|
||||||
|
client->_dataClient.stop();
|
||||||
|
client->_fileIsBeeingReceived = false;
|
||||||
|
client->_dataTransferPending = NONE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
client->_fileIsBeeingReceived = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*client->_dataClient.stop();
|
|
||||||
client->_dataTransferPending = NONE;*/
|
|
||||||
client->_fileIsBeeingReceived = true;
|
|
||||||
}
|
}
|
||||||
else if(client->_fileIsBeeingReceived)
|
else if(client->_fileIsBeeingReceived)
|
||||||
{
|
{
|
||||||
@ -160,9 +175,12 @@ class FTPServer : public TCPServer<T>
|
|||||||
Serial.println("Whole file received");
|
Serial.println("Whole file received");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
client->_client.println("226 Closing data connection.");
|
||||||
|
|
||||||
client->_fileIsBeeingReceived = false;
|
client->_fileIsBeeingReceived = false;
|
||||||
client->_dataClient.stop();
|
client->_dataClient.stop();
|
||||||
client->_dataTransferPending = NONE;
|
client->_dataTransferPending = NONE;
|
||||||
|
client->_fileRecvBytes = 0;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -278,9 +296,11 @@ class FTPServer : public TCPServer<T>
|
|||||||
}
|
}
|
||||||
else if (strcmp(client->_ftpCommand, "PASV") == 0)
|
else if (strcmp(client->_ftpCommand, "PASV") == 0)
|
||||||
{
|
{
|
||||||
_dataServer.begin(_dataPort);
|
|
||||||
client->_client.printf("227 Entering Passive Mode (%u,%u,%u,%u,%d,%d).\r\n", WiFi.localIP()[0], WiFi.localIP()[1], WiFi.localIP()[2], WiFi.localIP()[3], _dataPort / 256, _dataPort % 256);
|
client->_client.printf("227 Entering Passive Mode (%u,%u,%u,%u,%d,%d).\r\n", WiFi.localIP()[0], WiFi.localIP()[1], WiFi.localIP()[2], WiFi.localIP()[3], _dataPort / 256, _dataPort % 256);
|
||||||
client->_waitingForDataConnection = true;
|
client->_waitingForDataConnection = true;
|
||||||
|
#ifdef DEBUG_FTPS
|
||||||
|
Serial.println("Opening data server for new data client");
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
else if (strcmp(client->_ftpCommand, "LIST") == 0)
|
else if (strcmp(client->_ftpCommand, "LIST") == 0)
|
||||||
{
|
{
|
||||||
@ -457,14 +477,16 @@ class FTPServer : public TCPServer<T>
|
|||||||
if (client->_cmdParameters->count() > 0)
|
if (client->_cmdParameters->count() > 0)
|
||||||
{
|
{
|
||||||
//We save the file path to be sent
|
//We save the file path to be sent
|
||||||
char *temp = (char *)malloc((sizeof(char) * strlen(client->_currentDirectory)) + (sizeof(char) * strlen(client->_cmdParameters->getAt(0)->getString())) + (strcmp(client->_currentDirectory,"/") == 0 ? 0 : 1) + 1);
|
client->_client.println("150 File status okay; about to open data connection.");
|
||||||
|
|
||||||
|
char *temp = (char *)malloc((sizeof(char) * strlen(client->_currentDirectory)) + (sizeof(char) * strlen(_83FileNameFormat(client->_cmdParameters->getAt(0)->getString()))) + (strcmp(client->_currentDirectory,"/") == 0 ? 0 : 1) + 1);
|
||||||
strcpy(temp, client->_currentDirectory);
|
strcpy(temp, client->_currentDirectory);
|
||||||
if(strcmp(client->_currentDirectory,"/") != 0 )strcat(temp, "/");
|
if(strcmp(client->_currentDirectory,"/") != 0 )strcat(temp, "/");
|
||||||
strcat(temp, client->_cmdParameters->getAt(0)->getString());
|
strcat(temp, client->_cmdParameters->getAt(0)->getString());
|
||||||
|
|
||||||
client->setCurrentFile(temp);
|
client->setCurrentFile(temp);
|
||||||
#ifdef DEBUG_FTPS
|
#ifdef DEBUG_FTPS
|
||||||
Serial.printf("File to store : %s\n", temp);
|
Serial.printf("File to store : %s\n", client->_currentFile);
|
||||||
#endif
|
#endif
|
||||||
free(temp);
|
free(temp);
|
||||||
client->_dataTransferPending = STOR_DF;
|
client->_dataTransferPending = STOR_DF;
|
||||||
@ -474,12 +496,79 @@ class FTPServer : public TCPServer<T>
|
|||||||
{
|
{
|
||||||
client->_client.println("215 UNIX Type: L8");
|
client->_client.println("215 UNIX Type: L8");
|
||||||
}
|
}
|
||||||
|
else if(strcmp(client->_ftpCommand, "DELE") == 0)
|
||||||
|
{
|
||||||
|
if (client->_cmdParameters->count() > 0)
|
||||||
|
{
|
||||||
|
//We have the dir name, we need to append the current directory...
|
||||||
|
uint16_t pathDirNameLength = strlen(client->_cmdParameters->getAt(0)->getString()) + strlen(client->_currentDirectory) + /*If we need to add a /*/ (strcmp(client->_currentDirectory,"/") == 0 ? 0 : 1) + 1; //for \0
|
||||||
|
char *pathWithDirName = (char *)malloc(sizeof(char) * pathDirNameLength);
|
||||||
|
sprintf(pathWithDirName,"%s%s%s",client->_currentDirectory, strcmp(client->_currentDirectory,"/") == 0 ? "" : "/", client->_cmdParameters->getAt(0)->getString());
|
||||||
|
|
||||||
|
#ifdef DEBUG_FTPS
|
||||||
|
Serial.printf("file to delete : #%s#\n",pathWithDirName);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if(_sdCardManager->remove(pathWithDirName))
|
||||||
|
{
|
||||||
|
client->_client.println("250 Requested file action okay.");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
client->_client.println("550 Requested action not taken.");
|
||||||
|
}
|
||||||
|
|
||||||
|
free(pathWithDirName);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
client->_client.println("550 Requested action not taken.");
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
client->_client.println("502 Command not implemented.");
|
client->_client.println("502 Command not implemented.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Here we write the received file to the sd card
|
||||||
|
boolean writeToSdCard(T *client, FileTransferStatus *fts)
|
||||||
|
{
|
||||||
|
if (client->_currentFile != NULL)
|
||||||
|
{
|
||||||
|
if(_sdCardManager->exists(client->_currentFile) && client->_fileRecvBytes == 0)
|
||||||
|
_sdCardManager->remove(client->_currentFile);
|
||||||
|
|
||||||
|
File fileBeeingReceived = _sdCardManager->open(client->_currentFile, FILE_WRITE);
|
||||||
|
|
||||||
|
if(fileBeeingReceived)
|
||||||
|
{
|
||||||
|
char recvBuffer[1024];
|
||||||
|
|
||||||
|
/*fileBeeingReceived.seek(client->_fileRecvBytes);*/
|
||||||
|
uint16_t size = client->_dataClient.read((uint8_t *)recvBuffer, 1024);
|
||||||
|
|
||||||
|
fileBeeingReceived.write(recvBuffer, size);
|
||||||
|
|
||||||
|
client->_fileRecvBytes += size;
|
||||||
|
fileBeeingReceived.close();
|
||||||
|
#ifdef DEBUG_FTPS
|
||||||
|
Serial.println("File beeing written");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*fts = NO_FILE_NAME;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
//Here we send the fs tree to the ftp client
|
//Here we send the fs tree to the ftp client
|
||||||
void sendFSTree(T *client)
|
boolean sendFSTree(T *client)
|
||||||
{
|
{
|
||||||
if (client->_currentDirectory != NULL)
|
if (client->_currentDirectory != NULL)
|
||||||
{
|
{
|
||||||
@ -513,8 +602,13 @@ class FTPServer : public TCPServer<T>
|
|||||||
#ifdef DEBUG_FTPS
|
#ifdef DEBUG_FTPS
|
||||||
Serial.println("Failed to open directory");
|
Serial.println("Failed to open directory");
|
||||||
#endif
|
#endif
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//The binary flag needs to be taken into consideration
|
//The binary flag needs to be taken into consideration
|
||||||
@ -567,6 +661,38 @@ class FTPServer : public TCPServer<T>
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char *_83FileNameFormat(char *filename)
|
||||||
|
{
|
||||||
|
char *buffer = (char *)malloc((sizeof(char) * strlen(filename)) + 1);
|
||||||
|
strcpy(buffer, filename);
|
||||||
|
char *delimiter = strchr(buffer, '.');
|
||||||
|
if(delimiter != NULL)
|
||||||
|
{
|
||||||
|
*delimiter = '\0';
|
||||||
|
|
||||||
|
if(strlen(buffer) > 8)
|
||||||
|
buffer[8] = '\0';
|
||||||
|
|
||||||
|
strcpy(filename, buffer);
|
||||||
|
|
||||||
|
if(strlen(delimiter + 1) > 3)
|
||||||
|
*(delimiter + 1 + 3) = '\0';
|
||||||
|
|
||||||
|
strcat(filename, ".");
|
||||||
|
strcat(filename, delimiter + 1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(strlen(buffer) > 8)
|
||||||
|
{
|
||||||
|
buffer[8] = '\0';
|
||||||
|
}
|
||||||
|
strcpy(filename, buffer);
|
||||||
|
}
|
||||||
|
free(buffer);
|
||||||
|
return filename;
|
||||||
|
}
|
||||||
|
|
||||||
char *_login;
|
char *_login;
|
||||||
char *_password;
|
char *_password;
|
||||||
unsigned int _dataPort;
|
unsigned int _dataPort;
|
||||||
|
Loading…
Reference in New Issue
Block a user