Implementing FTP server
This commit is contained in:
parent
e77e879027
commit
31eb8eb589
@ -19,8 +19,8 @@ namespace DictionaryHelper
|
||||
{
|
||||
if(string == NULL)
|
||||
{
|
||||
_string = (char *) malloc((sizeof(char)) * 2); //+1 for the string terminating character
|
||||
strcpy(_string, "");
|
||||
_string = (char *) malloc((sizeof(char)));
|
||||
_string[0] = '\0';
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1 +1,58 @@
|
||||
#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),
|
||||
_ftpClientState(FTPServer<FTPClient>::FTPClientState::WAITING_FOR_COMMANDS),
|
||||
_binaryFlag(FTPServer<FTPClient>::BinaryFlag::OFF)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
FTPClient::~FTPClient()
|
||||
{
|
||||
delete _cmdParameters;
|
||||
free(_username);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
if(username != NULL)
|
||||
{
|
||||
_username = (char *) malloc((sizeof(char) * strlen(username)) + 1);
|
||||
strcpy(_username, username);
|
||||
}
|
||||
}
|
||||
|
@ -2,12 +2,31 @@
|
||||
#define FTPCLIENT_H
|
||||
|
||||
#include "TCPClient.h"
|
||||
#include "FTPServer.h"
|
||||
#include "Dictionary.h"
|
||||
|
||||
class FTPClient
|
||||
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);
|
||||
|
||||
char _ftpCommand[5];
|
||||
Dictionary<DictionaryHelper::StringEntity> *_cmdParameters;
|
||||
boolean _loggedIn;
|
||||
char *_username;
|
||||
|
||||
FTPServer<FTPClient>::FTPClientState _ftpClientState;
|
||||
FTPServer<FTPClient>::BinaryFlag _binaryFlag;
|
||||
WiFiClient _dataClient; //data socket
|
||||
};
|
||||
|
||||
#endif //FTPCLIENT_H
|
||||
|
@ -2,20 +2,31 @@
|
||||
#define FTPSERVER_H
|
||||
|
||||
#include "TCPServer.h"
|
||||
#define DEBUG_FTPS
|
||||
|
||||
template <typename T>
|
||||
class FTPServer : public TCPServer<T>
|
||||
{
|
||||
public:
|
||||
FTPServer(unsigned int port = 22, const char login = "", const char password = "", uint8_t maxClient = MAX_CLIENT, uint16_t clientCommandDataBufferSize = 255) : TCPServer<T>(port, maxClient, clientCommandDataBufferSize), _login(NULL), _password(NULL)
|
||||
enum FTPClientState {WAITING_FOR_COMMANDS};
|
||||
enum BinaryFlag {OFF = 0, ON};
|
||||
|
||||
FTPServer(unsigned int port = 21, 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),
|
||||
_dataServer(1024)
|
||||
{
|
||||
_login = (char *)malloc((sizeof(char) * strlen(login)) + 1);
|
||||
if(_login != NULL)
|
||||
if(login != NULL)
|
||||
{
|
||||
_login = (char *)malloc((sizeof(char) * strlen(login)) + 1);
|
||||
strcpy(_login, login);
|
||||
}
|
||||
|
||||
_password = (char *)malloc((sizeof(char) * strlen(password)) + 1);
|
||||
if(_password != NULL)
|
||||
if(password != NULL)
|
||||
{
|
||||
_password = (char *)malloc((sizeof(char) * strlen(password)) + 1);
|
||||
strcpy(_password, password);
|
||||
}
|
||||
}
|
||||
|
||||
virtual ~FTPServer()
|
||||
@ -24,9 +35,136 @@ class FTPServer : public TCPServer<T>
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
|
||||
#ifdef DEBUG_FTPS
|
||||
if(client->_newDataAvailable)
|
||||
{
|
||||
Serial.print("Client --> ");Serial.print(client->_id);Serial.print(" : ");Serial.print((char *)client->_data);Serial.println("#");
|
||||
}
|
||||
#endif
|
||||
|
||||
switch(client->_ftpClientState)
|
||||
{
|
||||
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)
|
||||
{
|
||||
client->_client.println("257 \"/FTP\"");
|
||||
}
|
||||
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();
|
||||
client->_client.printf("227 Entering Passive Mode (%d,%d,%d,%d,%d,%d).\r\n", 192,168,0,29,1024/256, 1024%256);
|
||||
}
|
||||
else
|
||||
client->_client.println("502 Command not implemented.");
|
||||
}
|
||||
|
||||
char *_login;
|
||||
char *_password;
|
||||
|
||||
WiFiServer _dataServer; //In passive mode, the FTP server opens two different ports (one for the commands and the other for the data stream)
|
||||
};
|
||||
|
||||
#endif //FTPSERVER_H
|
||||
|
33
src/software_test/tcpServer_test/StringEntity.cpp
Normal file
33
src/software_test/tcpServer_test/StringEntity.cpp
Normal file
@ -0,0 +1,33 @@
|
||||
#include "Dictionary.h"
|
||||
#include "definition.h"
|
||||
|
||||
Dictionary<DictionaryHelper::StringEntity> *DictionaryHelper::StringEntity::split(char character)
|
||||
{
|
||||
Dictionary<DictionaryHelper::StringEntity> *ref = NULL;
|
||||
unsigned int i(0), counter(0);
|
||||
char *parseBuffer(NULL);
|
||||
|
||||
if(_string == NULL)return NULL;
|
||||
|
||||
ref = new Dictionary<StringEntity>();
|
||||
|
||||
while(_string[i] != '\0')
|
||||
{
|
||||
if(_string[i] == character)
|
||||
{
|
||||
ref->add(counter++, parseBuffer);
|
||||
free(parseBuffer);parseBuffer = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
parseBuffer = addChar(parseBuffer, _string[i]);
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
ref->add(counter++,parseBuffer);
|
||||
free(parseBuffer);parseBuffer = NULL;
|
||||
|
||||
return ref;
|
||||
}
|
@ -36,7 +36,7 @@ class WEBServer : public TCPServer<T>
|
||||
uint16_t maxBodyBuffer;
|
||||
};
|
||||
|
||||
WEBServer(unsigned int port = 80, uint8_t maxClient = MAX_CLIENT, uint16_t clientDataBufferSize = 512) : TCPServer<T>(port, maxClient, clientDataBufferSize) {}
|
||||
WEBServer(unsigned int port = 80, uint8_t maxClient = MAX_CLIENT, uint16_t clientDataBufferSize = 255) : TCPServer<T>(port, maxClient, clientDataBufferSize) {}
|
||||
|
||||
boolean addApiRoutine(const char *uri, boolean (*apiRoutine)(HttpRequestData&, WiFiClient*, void*), void *pData, HttpRequestMethod HRM = UNDEFINED)
|
||||
{
|
||||
@ -53,7 +53,7 @@ class WEBServer : public TCPServer<T>
|
||||
private:
|
||||
virtual T* createNewClient(WiFiClient wc)
|
||||
{
|
||||
return new T(wc, TCPServer<T>::freeClientId());
|
||||
return new T(wc, TCPServer<T>::freeClientId(), TCPServer<T>::_clientDataBufferSize);
|
||||
}
|
||||
|
||||
virtual void greetClient(T *client)
|
||||
|
51
src/software_test/tcpServer_test/definition.cpp
Normal file
51
src/software_test/tcpServer_test/definition.cpp
Normal file
@ -0,0 +1,51 @@
|
||||
#include "definition.h"
|
||||
|
||||
char *addChar(char *pointer, const char character)
|
||||
{
|
||||
char *tempAddr = NULL;
|
||||
if(pointer == NULL)
|
||||
{
|
||||
tempAddr = (char *) realloc(pointer, 2*sizeof(char));
|
||||
if(tempAddr == NULL)
|
||||
return NULL;
|
||||
else
|
||||
{
|
||||
pointer = tempAddr;
|
||||
pointer[0] = character;
|
||||
pointer[1] = '\0';
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
tempAddr = (char *) realloc(pointer, (strlen(pointer)+2)*sizeof(char));
|
||||
if(tempAddr == NULL)
|
||||
{
|
||||
free(pointer);
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
pointer = tempAddr;
|
||||
pointer[strlen(pointer)+1] = '\0';
|
||||
pointer[strlen(pointer)] = character;
|
||||
}
|
||||
}
|
||||
|
||||
return pointer;
|
||||
}
|
||||
|
||||
char *dateTimeFormater(char *pointer, const uint8_t value, const char character)
|
||||
{
|
||||
if(pointer == NULL)
|
||||
return pointer;
|
||||
|
||||
if(value < 10)
|
||||
{
|
||||
sprintf(pointer,"%d", value);
|
||||
*(pointer+1) = *(pointer);*(pointer) = character;*(pointer+2) = '\0';
|
||||
}
|
||||
else
|
||||
sprintf(pointer,"%d", value);
|
||||
|
||||
return pointer;
|
||||
}
|
60
src/software_test/tcpServer_test/definition.h
Normal file
60
src/software_test/tcpServer_test/definition.h
Normal file
@ -0,0 +1,60 @@
|
||||
#ifndef DEFINITION_H
|
||||
#define DEFINITION_H
|
||||
|
||||
#include <Adafruit_SSD1306.h>
|
||||
#include <Arduino.h>
|
||||
|
||||
typedef enum { GPIO_0 = 0,
|
||||
GPIO_1_TX = 1,
|
||||
GPIO_2 = 2,
|
||||
GPIO_3_RX = 3,
|
||||
GPIO_4_SDA = 4,
|
||||
GPIO_5_SCL = 5,
|
||||
GPIO_10 = 10,
|
||||
GPIO_12_MISO = 12,
|
||||
GPIO_13_MOSI = 13,
|
||||
GPIO_14_CLK = 14,
|
||||
GPIO_15 = 15,
|
||||
GPIO_16 = 16,
|
||||
ADC = A0,
|
||||
DEFAULT_PIN = -1 } Pin;
|
||||
|
||||
#define AP_AND_STA_ENABLED_ERR B00000001
|
||||
#define AP_SETUP_ERR B00000010
|
||||
#define STA_SETUP_ERR B00000100
|
||||
|
||||
#define NO_ERROR 0
|
||||
|
||||
#define NO_CURRENT_VIEW NULL
|
||||
#define LAST_VIEW -1
|
||||
#define RESERVED_VIEW_UID -2
|
||||
|
||||
#define BATT_FULL 870 //8.4v
|
||||
#define BATT_EMPTY 775 //7.4v
|
||||
#define BATT_DIFF 95
|
||||
#define USB_THRESHOLD 600
|
||||
|
||||
//SD card file structure :
|
||||
#define AP_CFG_FILE "/CONFIG/AP.CFG"
|
||||
#define STA_CFG_FILE "/CONFIG/STA.CFG"
|
||||
#define WWW_DIR "/WWW"
|
||||
#define LOG_DIR "/LOGS"
|
||||
#define FTP_DIR "/FTP"
|
||||
|
||||
typedef enum { OR_0 = 2, OR_90 = 3, OR_180 = 0, OR_270 = 1 } Orientation;
|
||||
|
||||
typedef enum { BIT = 0, BYTE, KBIT, KBYTE, MBIT, MBYTE, GBIT, GBYTE } SizeUnit;
|
||||
|
||||
//Data structure for the view handling
|
||||
typedef struct viewLink{
|
||||
boolean (*viewLogicFunction)(Adafruit_SSD1306&, void*);
|
||||
void *pData;
|
||||
const int UID;
|
||||
struct viewLink *next;
|
||||
} ViewLink, *ViewLinkedList;
|
||||
|
||||
char *addChar(char *pointer, const char character);
|
||||
|
||||
char *dateTimeFormater(char *pointer, const uint8_t value, const char character);
|
||||
|
||||
#endif //DEFINITION_H
|
@ -15,6 +15,7 @@ uint16_t lastClientCount(0);
|
||||
|
||||
//TCPServer<TCPClient> server(80, MAX_CLIENT, 5);
|
||||
//WEBServer<WEBClient> webServer(8080);
|
||||
FTPServer<FTPClient> ftpServer;
|
||||
|
||||
WiFiEventHandler gotIpEventHandler, disconnectedEventHandler;
|
||||
|
||||
@ -53,6 +54,7 @@ void loop() {
|
||||
//server.runServer();
|
||||
//webServer.runServer();
|
||||
debugInfo();
|
||||
ftpServer.runServer();
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user