Added the FTPServer and improved functionalities (not done yet)
This commit is contained in:
parent
c777e23a52
commit
99e0f7d82c
88
src/app/FTPClient.cpp
Normal file
88
src/app/FTPClient.cpp
Normal file
@ -0,0 +1,88 @@
|
||||
#include "FTPClient.h"
|
||||
|
||||
FTPClient::FTPClient(WiFiClient client, uint8_t id, uint16_t clientCommandDataBufferSize) : TCPClient(client, id, clientCommandDataBufferSize),
|
||||
_ftpCommand({'\0'}),
|
||||
_cmdParameters(NULL),
|
||||
_loggedIn(false),
|
||||
_username(NULL),
|
||||
_currentDirectory(NULL),
|
||||
_currentFile(NULL),
|
||||
_fileSentBytes(0),
|
||||
_waitingForDataConnection(false),
|
||||
_fileIsBeeingReceived(false),
|
||||
_ftpClientState(FTPServer<FTPClient>::FTPClientState::INIT),
|
||||
_binaryFlag(FTPServer<FTPClient>::BinaryFlag::OFF),
|
||||
_dataTransferPending(FTPServer<FTPClient>::FTPClientDataTransfer::NONE)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
FTPClient::~FTPClient()
|
||||
{
|
||||
delete _cmdParameters;
|
||||
free(_username);
|
||||
free(_currentDirectory);
|
||||
free(_currentFile);
|
||||
_dataClient.stop();
|
||||
}
|
||||
|
||||
void FTPClient::setDataClient(WiFiClient dataClient)
|
||||
{
|
||||
_dataClient = dataClient;
|
||||
}
|
||||
|
||||
boolean FTPClient::parseCommandAndParameters()
|
||||
{
|
||||
//We remove the cr lf at the end
|
||||
char *cr = strchr((char *)_data,'\r'); *cr = '\0';
|
||||
char *cmdDelimiter = strchr((char *)_data,' ');
|
||||
|
||||
if(cmdDelimiter == NULL) //It means that we do not have any parameters
|
||||
{
|
||||
cmdDelimiter = (char *)_data + strlen((char *)_data) - 1;
|
||||
strcpy(_ftpCommand, (char *)_data);
|
||||
}
|
||||
else //we do
|
||||
{
|
||||
strncpy(_ftpCommand, (char *)_data, cmdDelimiter - (char *)_data);
|
||||
_ftpCommand[cmdDelimiter - (char *)_data] = '\0'; // /!\ strncpy does not append the terminating string character
|
||||
}
|
||||
|
||||
//We get the parameters :
|
||||
DictionaryHelper::StringEntity params(cmdDelimiter+1); //+1 to skip the first space
|
||||
delete _cmdParameters;
|
||||
_cmdParameters = params.split(' ');
|
||||
|
||||
//At the end, we flush the buffer:
|
||||
freeDataBuffer(_dataSize);
|
||||
}
|
||||
|
||||
void FTPClient::setUsername(const char *username)
|
||||
{
|
||||
free(_username);_username = NULL;
|
||||
if(username != NULL)
|
||||
{
|
||||
_username = (char *) malloc((sizeof(char) * strlen(username)) + 1);
|
||||
strcpy(_username, username);
|
||||
}
|
||||
}
|
||||
|
||||
void FTPClient::setCurrentDirectory(const char *dir)
|
||||
{
|
||||
free(_currentDirectory);_currentDirectory = NULL;
|
||||
if(dir != NULL)
|
||||
{
|
||||
_currentDirectory = (char *) malloc((sizeof(char) * strlen(dir)) + 1);
|
||||
strcpy(_currentDirectory, dir);
|
||||
}
|
||||
}
|
||||
|
||||
void FTPClient::setCurrentFile(const char *file)
|
||||
{
|
||||
free(_currentFile);_currentFile = NULL;
|
||||
if(file != NULL)
|
||||
{
|
||||
_currentFile = (char *) malloc((sizeof(char) * strlen(file)) + 1);
|
||||
strcpy(_currentFile, file);
|
||||
}
|
||||
}
|
40
src/app/FTPClient.h
Normal file
40
src/app/FTPClient.h
Normal file
@ -0,0 +1,40 @@
|
||||
#ifndef FTPCLIENT_H
|
||||
#define FTPCLIENT_H
|
||||
|
||||
#include "TCPClient.h"
|
||||
#include "FTPServer.h"
|
||||
#include "Dictionary.h"
|
||||
|
||||
class FTPClient : public TCPClient
|
||||
{
|
||||
template<typename T>
|
||||
friend class FTPServer;
|
||||
public:
|
||||
FTPClient(WiFiClient client, uint8_t id, uint16_t clientCommandDataBufferSize = 255);
|
||||
virtual ~FTPClient();
|
||||
protected:
|
||||
private:
|
||||
FTPClient(const FTPClient &Object) : TCPClient(Object){}
|
||||
void setDataClient(WiFiClient dataClient); //Also known as the data socket
|
||||
boolean parseCommandAndParameters(void);
|
||||
void setUsername(const char *username);
|
||||
void setCurrentDirectory(const char *dir);
|
||||
void setCurrentFile(const char *file);
|
||||
|
||||
char _ftpCommand[5];
|
||||
Dictionary<DictionaryHelper::StringEntity> *_cmdParameters;
|
||||
boolean _loggedIn;
|
||||
char *_username;
|
||||
char *_currentDirectory;
|
||||
char *_currentFile;
|
||||
uint64_t _fileSentBytes;
|
||||
boolean _waitingForDataConnection;
|
||||
boolean _fileIsBeeingReceived;
|
||||
|
||||
FTPServer<FTPClient>::FTPClientState _ftpClientState;
|
||||
FTPServer<FTPClient>::BinaryFlag _binaryFlag;
|
||||
FTPServer<FTPClient>::FTPClientDataTransfer _dataTransferPending;
|
||||
WiFiClient _dataClient; //data socket
|
||||
};
|
||||
|
||||
#endif //FTPCLIENT_H
|
578
src/app/FTPServer.h
Normal file
578
src/app/FTPServer.h
Normal file
@ -0,0 +1,578 @@
|
||||
#ifndef FTPSERVER_H
|
||||
#define FTPSERVER_H
|
||||
|
||||
#include "TCPServer.h"
|
||||
#include "SDCardManager.h"
|
||||
#include "definition.h"
|
||||
#define DEBUG_FTPS
|
||||
#define READ_WRITE_BUFFER_SIZE 2048
|
||||
|
||||
template <typename T>
|
||||
class FTPServer : public TCPServer<T>
|
||||
{
|
||||
public:
|
||||
enum FTPClientState {INIT, WAITING_FOR_COMMANDS};
|
||||
enum FTPClientDataTransfer {NONE, LIST_DF, NLST_DF, RETR_DF, STOR_DF};
|
||||
enum FileTransferStatus {OK, NOT_FOUND};
|
||||
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),
|
||||
_login(NULL),
|
||||
_password(NULL),
|
||||
_dataPort(1024),
|
||||
_dataServer(_dataPort),
|
||||
_sdCardManager(sdCardManager)
|
||||
{
|
||||
if (login != NULL)
|
||||
{
|
||||
if (strlen(login) > 0)
|
||||
{
|
||||
_login = (char *)malloc((sizeof(char) * strlen(login)) + 1);
|
||||
strcpy(_login, login);
|
||||
}
|
||||
}
|
||||
|
||||
if (password != NULL)
|
||||
{
|
||||
if (strlen(password) > 0)
|
||||
{
|
||||
_password = (char *)malloc((sizeof(char) * strlen(password)) + 1);
|
||||
strcpy(_password, password);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void setCustomDataPort(unsigned int port)
|
||||
{
|
||||
_dataPort = port;
|
||||
}
|
||||
|
||||
virtual ~FTPServer()
|
||||
{
|
||||
free(_login); free(_password);
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual T* createNewClient(WiFiClient wc)
|
||||
{
|
||||
return new T(wc, TCPServer<T>::freeClientId(), TCPServer<T>::_clientDataBufferSize);
|
||||
}
|
||||
|
||||
virtual void greetClient(T *client)
|
||||
{
|
||||
//The first time the client connects, we send the server's information
|
||||
client->_client.println("220 Welcome to the ESP8266SwissArmyBoard embedded FTP server.");
|
||||
client->_clientState = TCPClient::HANDLED;
|
||||
}
|
||||
|
||||
virtual void processClientData(T *client)
|
||||
{
|
||||
if (client->_waitingForDataConnection)
|
||||
{
|
||||
/*#ifdef DEBUG_FTPS
|
||||
Serial.println("Listening for new data client");
|
||||
#endif*/
|
||||
WiFiClient dataClient = _dataServer.available();
|
||||
|
||||
if (dataClient)
|
||||
{
|
||||
if (dataClient.connected())
|
||||
{
|
||||
client->_waitingForDataConnection = false;
|
||||
client->setDataClient(dataClient);
|
||||
#ifdef DEBUG_FTPS
|
||||
Serial.println("Data client accepted successfully");
|
||||
#endif
|
||||
}
|
||||
else
|
||||
dataClient.stop();
|
||||
}
|
||||
}
|
||||
|
||||
switch(client->_dataTransferPending)
|
||||
{
|
||||
case LIST_DF: //We list the files of the current directory
|
||||
//We check if the dataConnection is established:
|
||||
if (client->_dataClient.connected())
|
||||
{
|
||||
client->_client.println("150 File status okay;");
|
||||
sendFSTree(client);
|
||||
|
||||
client->_client.println("226 Closing data connection.");
|
||||
client->_dataClient.stop();
|
||||
client->_dataTransferPending = NONE;
|
||||
}
|
||||
//A timeout should be added
|
||||
/*else
|
||||
{
|
||||
client->_client.println("425 Can't open data connection.");
|
||||
}*/
|
||||
break;
|
||||
case RETR_DF:
|
||||
if (client->_dataClient.connected())
|
||||
{
|
||||
if(client->_fileSentBytes == 0)
|
||||
client->_client.println("150 File status okay;");
|
||||
|
||||
FileTransferStatus fts;
|
||||
if(!sendFile(client,&fts))//File was sent or error occured
|
||||
{
|
||||
//we check the return code
|
||||
switch(fts)
|
||||
{
|
||||
case OK:
|
||||
client->_client.println("226 Closing data connection.");
|
||||
client->_dataClient.stop();
|
||||
client->_dataTransferPending = NONE;
|
||||
break;
|
||||
case NOT_FOUND:
|
||||
client->_client.println("451 File not found.");
|
||||
client->_dataClient.stop();
|
||||
client->_dataTransferPending = NONE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
//A timeout should be added
|
||||
/*else
|
||||
{
|
||||
client->_client.println("425 Can't open data connection.");
|
||||
}*/
|
||||
break;
|
||||
case STOR_DF :
|
||||
if (client->_dataClient.connected())
|
||||
{
|
||||
char recvBuffer[READ_WRITE_BUFFER_SIZE];
|
||||
if(client->_dataClient.available())
|
||||
{
|
||||
uint16_t size = client->_dataClient.read((uint8_t *)recvBuffer, READ_WRITE_BUFFER_SIZE-1);
|
||||
recvBuffer[size] = '\0';
|
||||
Serial.printf("Data : %s\n", recvBuffer);
|
||||
}
|
||||
|
||||
/*client->_dataClient.stop();
|
||||
client->_dataTransferPending = NONE;*/
|
||||
client->_fileIsBeeingReceived = true;
|
||||
}
|
||||
else if(client->_fileIsBeeingReceived)
|
||||
{
|
||||
#ifdef DEBUG_FTPS
|
||||
Serial.println("Whole file received");
|
||||
#endif
|
||||
|
||||
client->_fileIsBeeingReceived = false;
|
||||
client->_dataClient.stop();
|
||||
client->_dataTransferPending = NONE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_FTPS
|
||||
if (client->_newDataAvailable)
|
||||
{
|
||||
Serial.print("Client --> "); Serial.print(client->_id); Serial.print(" : "); Serial.print((char *)client->_data); Serial.println("#");
|
||||
}
|
||||
#endif
|
||||
|
||||
if (client->_dataSize > 0)
|
||||
{
|
||||
switch (client->_ftpClientState)
|
||||
{
|
||||
case INIT:
|
||||
client->setCurrentDirectory(FTP_DIR);
|
||||
client->_ftpClientState = WAITING_FOR_COMMANDS;
|
||||
break;
|
||||
case WAITING_FOR_COMMANDS:
|
||||
processCommands(client);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
void processCommands(T *client)
|
||||
{
|
||||
if (!client->parseCommandAndParameters()) //Failed to retrieve command and parameters
|
||||
{
|
||||
//We can close the connection or do other things
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_FTPS
|
||||
Serial.printf("Issued command : '%s'\n", client->_ftpCommand);
|
||||
Serial.println("Get params :");
|
||||
for (int i = 0; i < client->_cmdParameters->count(); i++)
|
||||
{
|
||||
Serial.print(client->_cmdParameters->getParameter(i)); Serial.print(" : "); Serial.printf("'%s'\n", client->_cmdParameters->getAt(i)->getString());
|
||||
}
|
||||
#endif
|
||||
|
||||
if (strcmp(client->_ftpCommand, "USER") == 0)
|
||||
{
|
||||
//We check if we set a login and a password :
|
||||
if (_login != NULL && _password != NULL)
|
||||
{
|
||||
if (client->_cmdParameters->count() > 0)
|
||||
{
|
||||
client->_client.println("331 User name okay, need password.");
|
||||
client->setUsername(client->_cmdParameters->getAt(0)->getString());
|
||||
}
|
||||
else
|
||||
client->_client.println("530 Username required.");
|
||||
}
|
||||
else //The ftp access is open
|
||||
{
|
||||
client->_client.println("230 User logged in, proceed.");
|
||||
}
|
||||
}
|
||||
else if (strcmp(client->_ftpCommand, "PASS") == 0)
|
||||
{
|
||||
//We now check if the username and password correspond
|
||||
if (client->_cmdParameters->count() > 0)
|
||||
{
|
||||
if (strcmp(_login, client->_username) == 0 && strcmp(_password, client->_cmdParameters->getAt(0)->getString()) == 0)
|
||||
{
|
||||
client->_loggedIn = true;
|
||||
client->_client.println("230 User logged in, proceed.");
|
||||
}
|
||||
else
|
||||
{
|
||||
client->_client.println("530 Wrong username or password !.");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
client->_client.println("530 Password required.");
|
||||
}
|
||||
}
|
||||
else if (strcmp(client->_ftpCommand, "PWD") == 0) //We set the default directory
|
||||
{
|
||||
client->_client.printf("257 \"%s\"\r\n", client->_currentDirectory);
|
||||
}
|
||||
else if (strcmp(client->_ftpCommand, "TYPE") == 0)
|
||||
{
|
||||
if (client->_cmdParameters->count() > 0)
|
||||
{
|
||||
switch (client->_cmdParameters->getAt(0)->getString()[0])
|
||||
{
|
||||
case 'I':
|
||||
client->_binaryFlag = ON;
|
||||
client->_client.println("200 Command okay.");
|
||||
break;
|
||||
case 'L':
|
||||
client->_binaryFlag = ON;
|
||||
client->_client.println("200 Command okay.");
|
||||
break;
|
||||
case 'A':
|
||||
client->_binaryFlag = OFF;
|
||||
client->_client.println("200 Command okay.");
|
||||
break;
|
||||
default:
|
||||
client->_client.println("504 Command not implemented for TYPE.");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
client->_client.println("504 Command not implemented for TYPE.");
|
||||
}
|
||||
}
|
||||
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->_waitingForDataConnection = true;
|
||||
}
|
||||
else if (strcmp(client->_ftpCommand, "LIST") == 0)
|
||||
{
|
||||
//We inform that a data transfer is pending
|
||||
client->_dataTransferPending = LIST_DF;
|
||||
}
|
||||
else if (strcmp(client->_ftpCommand, "CWD") == 0)
|
||||
{
|
||||
if (client->_cmdParameters->count() > 0)
|
||||
{
|
||||
//Go back one level
|
||||
if (strcmp(client->_cmdParameters->getAt(0)->getString(), "..") == 0)
|
||||
{
|
||||
char *dirCopy = (char *)malloc((sizeof(char) * strlen(client->_currentDirectory)) + 1);
|
||||
strcpy(dirCopy, client->_currentDirectory);
|
||||
|
||||
char *p = lastIndexOf(dirCopy, '/');
|
||||
if (dirCopy == p)
|
||||
{
|
||||
*(p + 1) = '\0';
|
||||
}
|
||||
else
|
||||
*(p) = '\0';
|
||||
|
||||
#ifdef DEBUG_FTPS
|
||||
Serial.printf("Final dir : %s\n", dirCopy);
|
||||
#endif
|
||||
|
||||
client->setCurrentDirectory(dirCopy);
|
||||
free(dirCopy);
|
||||
}
|
||||
else if (strcmp(client->_cmdParameters->getAt(0)->getString(), "/") == 0)
|
||||
{
|
||||
client->setCurrentDirectory("/");
|
||||
}
|
||||
else
|
||||
{
|
||||
if(client->_cmdParameters->getAt(0)->getString()[0] == '/')//Then this is a name prefix
|
||||
{
|
||||
client->setCurrentDirectory(client->_cmdParameters->getAt(0)->getString());
|
||||
}
|
||||
else
|
||||
{
|
||||
char *temp = (char *)malloc((sizeof(char) * strlen(client->_currentDirectory)) + (sizeof(char) * strlen(client->_cmdParameters->getAt(0)->getString())) + 2);
|
||||
strcpy(temp,client->_currentDirectory);
|
||||
if(strcmp(temp, "/") != 0)strcat(temp,"/");
|
||||
strcat(temp,client->_cmdParameters->getAt(0)->getString());
|
||||
#ifdef DEBUG_FTPS
|
||||
Serial.printf("Final dir : %s\n",temp);
|
||||
#endif
|
||||
client->setCurrentDirectory(temp);
|
||||
free(temp);
|
||||
}
|
||||
}
|
||||
|
||||
client->_client.println("250 Requested file action okay, completed.");
|
||||
#ifdef DEBUG_FTPS
|
||||
Serial.printf("CWD new dir : %s\n", client->_currentDirectory);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else if(strcmp(client->_ftpCommand, "RETR") == 0)
|
||||
{
|
||||
if (client->_cmdParameters->count() > 0)
|
||||
{
|
||||
//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);
|
||||
strcpy(temp, client->_currentDirectory);
|
||||
if(strcmp(client->_currentDirectory,"/") != 0 )strcat(temp, "/");
|
||||
strcat(temp, client->_cmdParameters->getAt(0)->getString());
|
||||
|
||||
client->setCurrentFile(temp);
|
||||
#ifdef DEBUG_FTPS
|
||||
Serial.printf("File to donwload : %s\n", temp);
|
||||
#endif
|
||||
free(temp);
|
||||
client->_dataTransferPending = RETR_DF;
|
||||
}
|
||||
}
|
||||
else if(strcmp(client->_ftpCommand, "MKD") == 0)
|
||||
{
|
||||
if (client->_cmdParameters->count() > 0)
|
||||
{
|
||||
uint16_t dirNameSize(0), paramCount(client->_cmdParameters->count());
|
||||
char *dirName(NULL);
|
||||
for(int i(0); i < paramCount; i++)
|
||||
{
|
||||
dirNameSize += strlen(client->_cmdParameters->getAt(i)->getString());
|
||||
|
||||
if(i != paramCount-1)
|
||||
dirNameSize++;
|
||||
}
|
||||
|
||||
dirName = (char *)malloc((sizeof(char)*dirNameSize) + 1);
|
||||
if(dirName != NULL)
|
||||
{
|
||||
dirName[0] = '\0';
|
||||
|
||||
for(int i(0); i < paramCount; i++)
|
||||
{
|
||||
strcat(dirName,client->_cmdParameters->getAt(i)->getString());
|
||||
|
||||
if(i != paramCount-1)
|
||||
strcat(dirName," ");
|
||||
}
|
||||
|
||||
#ifdef DEBUG_FTPS
|
||||
Serial.printf("dirName size : %d, dirName #%s#\n",dirNameSize,dirName);
|
||||
#endif
|
||||
|
||||
if(strlen(dirName) > 8)
|
||||
dirName[8] = '\0';
|
||||
|
||||
//We have the dir name, we need to append the current directory...
|
||||
uint16_t pathDirNameLength = strlen(dirName) + 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 ? "" : "/", dirName);
|
||||
|
||||
#ifdef DEBUG_FTPS
|
||||
Serial.printf("Final dirName and path #%s# #%s# size %d\n",dirName, pathWithDirName, pathDirNameLength);
|
||||
#endif
|
||||
|
||||
if(_sdCardManager->mkdir(strupr(pathWithDirName)))
|
||||
{
|
||||
client->_client.printf("257 \"%s\"\r\n", pathWithDirName);
|
||||
}
|
||||
else
|
||||
client->_client.println("550 Failed to mkdir (no spaces allowed in dir name).");
|
||||
free(pathWithDirName);
|
||||
free(dirName);
|
||||
}
|
||||
else
|
||||
{
|
||||
client->_client.println("550 Requested action not taken.");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
client->_client.println("550 Requested action not taken.");
|
||||
}
|
||||
}
|
||||
else if(strcmp(client->_ftpCommand, "RMD") == 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("pathDirName to delete : #%s#\n",pathWithDirName);
|
||||
#endif
|
||||
|
||||
if(_sdCardManager->rmdir(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 if(strcmp(client->_ftpCommand, "STOR") == 0)
|
||||
{
|
||||
if (client->_cmdParameters->count() > 0)
|
||||
{
|
||||
//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);
|
||||
strcpy(temp, client->_currentDirectory);
|
||||
if(strcmp(client->_currentDirectory,"/") != 0 )strcat(temp, "/");
|
||||
strcat(temp, client->_cmdParameters->getAt(0)->getString());
|
||||
|
||||
client->setCurrentFile(temp);
|
||||
#ifdef DEBUG_FTPS
|
||||
Serial.printf("File to store : %s\n", temp);
|
||||
#endif
|
||||
free(temp);
|
||||
client->_dataTransferPending = STOR_DF;
|
||||
}
|
||||
}
|
||||
else if(strcmp(client->_ftpCommand, "SYST") == 0)
|
||||
{
|
||||
client->_client.println("215 UNIX Type: L8");
|
||||
}
|
||||
else
|
||||
client->_client.println("502 Command not implemented.");
|
||||
}
|
||||
|
||||
//Here we send the fs tree to the ftp client
|
||||
void sendFSTree(T *client)
|
||||
{
|
||||
if (client->_currentDirectory != NULL)
|
||||
{
|
||||
#ifdef DEBUG_FTPS
|
||||
Serial.printf("Directory : %s\n",client->_currentDirectory);
|
||||
#endif
|
||||
File currentDirectory = _sdCardManager->open(client->_currentDirectory);
|
||||
currentDirectory.rewindDirectory();
|
||||
if (currentDirectory)
|
||||
{
|
||||
while (true) //Maybe be remove in the future to improve responsiveness
|
||||
{
|
||||
File fileOrDir = currentDirectory.openNextFile();
|
||||
|
||||
if (!fileOrDir) //No more files in the directory
|
||||
break;
|
||||
|
||||
#ifdef DEBUG_FTPS
|
||||
Serial.printf("Filename : %s\n", fileOrDir.name());
|
||||
#endif
|
||||
|
||||
client->_dataClient.printf("%crwxrwxrwx 1 owner esp8266 %d Aug 26 16:31 %s\r\n", fileOrDir.isDirectory() ? 'd' : '-', fileOrDir.isDirectory() ? 0 : fileOrDir.size(), fileOrDir.name());
|
||||
|
||||
fileOrDir.close();
|
||||
}
|
||||
|
||||
currentDirectory.close();
|
||||
}
|
||||
else //Failed to open directory
|
||||
{
|
||||
#ifdef DEBUG_FTPS
|
||||
Serial.println("Failed to open directory");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//The binary flag needs to be taken into consideration
|
||||
boolean sendFile(T *client, FileTransferStatus *fts)
|
||||
{
|
||||
if (client->_currentFile != NULL)
|
||||
{
|
||||
char sendBuffer[READ_WRITE_BUFFER_SIZE];
|
||||
File fileToSend = _sdCardManager->open(client->_currentFile);
|
||||
|
||||
if (fileToSend)
|
||||
{
|
||||
*fts = OK;
|
||||
unsigned int readBytes(0);
|
||||
fileToSend.seek(client->_fileSentBytes);
|
||||
|
||||
if(fileToSend.available())
|
||||
{
|
||||
readBytes = fileToSend.read(sendBuffer, READ_WRITE_BUFFER_SIZE);
|
||||
client->_dataClient.write(sendBuffer, readBytes);
|
||||
|
||||
client->_fileSentBytes += readBytes;
|
||||
|
||||
#ifdef DEBUG_FTPS
|
||||
Serial.printf("File : bytes sent : %u\n",readBytes);
|
||||
#endif
|
||||
}
|
||||
else //The whole file has been sent
|
||||
{
|
||||
fileToSend.close();
|
||||
client->_fileSentBytes = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
fileToSend.close();
|
||||
}
|
||||
else //Failed to open file maybe not found
|
||||
{
|
||||
#ifdef DEBUG_FTPS
|
||||
Serial.println("Failed to open file");
|
||||
#endif
|
||||
*fts = NOT_FOUND;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;//Still things to send
|
||||
}
|
||||
|
||||
*fts = NOT_FOUND;
|
||||
return false;
|
||||
}
|
||||
|
||||
char *_login;
|
||||
char *_password;
|
||||
unsigned int _dataPort;
|
||||
|
||||
WiFiServer _dataServer; //In passive mode, the FTP server opens two different ports (one for the commands and the other for the data stream)
|
||||
SDCardManager *_sdCardManager;
|
||||
};
|
||||
|
||||
#endif //FTPSERVER_H
|
@ -9,6 +9,7 @@ _rtcManager(_rtc), _sdCardManager(),
|
||||
_connectivityManager(NULL),
|
||||
//_webServerManager(80, &_sdCardManager),
|
||||
_webServer(80, &_sdCardManager),
|
||||
_ftpServer(21, &_sdCardManager, "ESP8266", "12345678"),
|
||||
_pcf(0x27, Wire),
|
||||
_ioManager(_pcf),
|
||||
_taskSchedulerManager(_rtcManager),
|
||||
@ -40,6 +41,7 @@ _sdCardManager(),
|
||||
_connectivityManager(NULL),
|
||||
//_webServerManager(webServerPort, &_sdCardManager),
|
||||
_webServer(webServerPort, &_sdCardManager),
|
||||
_ftpServer(21, &_sdCardManager, "ESP8266", "12345678"),
|
||||
_pcf(0x27, Wire),
|
||||
_ioManager(_pcf),
|
||||
_taskSchedulerManager(_rtcManager),
|
||||
@ -94,6 +96,11 @@ WEBServer<WEBClient>& SAB::getWebServer()
|
||||
return _webServer;
|
||||
}
|
||||
|
||||
FTPServer<FTPClient>& SAB::getFtpServer()
|
||||
{
|
||||
return _ftpServer;
|
||||
}
|
||||
|
||||
IOManager& SAB::getIoManager()
|
||||
{
|
||||
return _ioManager;
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include "ConnectivityManager.h"
|
||||
//#include "WEBServerManager.h"
|
||||
#include "WEBClient.h" //includes WEBServer internally
|
||||
#include "FTPClient.h" //includes FTPServer internally
|
||||
#include "IOManager.h"
|
||||
#include "TaskSchedulerManager.h"
|
||||
#include "PowerManager.h"
|
||||
@ -35,6 +36,7 @@ class SAB
|
||||
ConnectivityManager& getConnectivityManager();
|
||||
//WEBServerManager& getWebServerManager();
|
||||
WEBServer<WEBClient>& getWebServer();
|
||||
FTPServer<FTPClient>& getFtpServer();
|
||||
IOManager& getIoManager();
|
||||
TaskSchedulerManager& getTaskSchedulerManager();
|
||||
PowerManager& getPowerManager();
|
||||
@ -57,6 +59,7 @@ class SAB
|
||||
ConnectivityManager *_connectivityManager;
|
||||
//WEBServerManager _webServerManager;
|
||||
WEBServer<WEBClient> _webServer;
|
||||
FTPServer<FTPClient> _ftpServer;
|
||||
PCF8574 _pcf;
|
||||
IOManager _ioManager;
|
||||
TaskSchedulerManager _taskSchedulerManager;
|
||||
|
@ -120,6 +120,7 @@ void loop()
|
||||
|
||||
//Run the webServer
|
||||
sab.getWebServer().runServer();
|
||||
sab.getFtpServer().runServer();
|
||||
sab.getTaskSchedulerManager().runTaskScheduler();
|
||||
}
|
||||
|
||||
|
@ -18,5 +18,6 @@
|
||||
#define SOFT_VERSION "1.3.0" //Implemented multi-client non blocking webserver
|
||||
#define SOFT_VERSION "1.3.1" //Fixed sdCardUnmount api call
|
||||
#define SOFT_VERSION "1.3.2" //Modified TCPServer and WEBServer core logic
|
||||
#define SOFT_VERSION "1.4.0" //Added the new FTPServer
|
||||
|
||||
#endif //VERSIONS_H
|
||||
|
Loading…
Reference in New Issue
Block a user