Developped new multi client tcp server as well as web server
This commit is contained in:
parent
cc8e517920
commit
4a98c5ebc6
@ -99,6 +99,7 @@ public:
|
|||||||
|
|
||||||
return cursor->_value;
|
return cursor->_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
T getLast()
|
T getLast()
|
||||||
{
|
{
|
||||||
T* p = getLastRef();
|
T* p = getLastRef();
|
||||||
|
82
src/software_test/tcpServer_test/TCPClient.cpp
Normal file
82
src/software_test/tcpServer_test/TCPClient.cpp
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
#include "TCPClient.h"
|
||||||
|
|
||||||
|
#define DEBUG_CL
|
||||||
|
|
||||||
|
TCPClient::TCPClient(WiFiClient client, uint8_t id, uint16_t dataBufferSize) : _client(client),
|
||||||
|
_clientState(NEW),
|
||||||
|
_error(OK),
|
||||||
|
_data(NULL),
|
||||||
|
_dataSize(0),
|
||||||
|
_dataBufferSize(dataBufferSize+1),
|
||||||
|
_newDataAvailable(false),
|
||||||
|
_id(id)
|
||||||
|
{
|
||||||
|
#ifdef DEBUG_CL
|
||||||
|
Serial.println("TCPClient : Standard constructor called");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
uint8_t *p = (uint8_t *) malloc(sizeof(uint8_t) * _dataBufferSize);
|
||||||
|
if(p != NULL)
|
||||||
|
_data = p;
|
||||||
|
else
|
||||||
|
_error = MALLOC_ERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
TCPClient::TCPClient(const TCPClient &Object) : _client(Object._client),
|
||||||
|
_clientState(Object._clientState),
|
||||||
|
_error(Object._error),
|
||||||
|
_data(NULL),
|
||||||
|
_dataSize(Object._dataSize),
|
||||||
|
_dataBufferSize(Object._dataBufferSize),
|
||||||
|
_newDataAvailable(Object._newDataAvailable),
|
||||||
|
_id(Object._id)
|
||||||
|
{
|
||||||
|
#ifdef DEBUG_CL
|
||||||
|
Serial.println("TCPClient : Copy constructor called");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
uint8_t *p = (uint8_t *) malloc(sizeof(uint8_t) * _dataBufferSize);
|
||||||
|
if(p != NULL)
|
||||||
|
{
|
||||||
|
_data = p;
|
||||||
|
memcpy(_data,Object._data,_dataSize);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
_error = MALLOC_ERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
TCPClient::~TCPClient()
|
||||||
|
{
|
||||||
|
#ifdef DEBUG_CL
|
||||||
|
Serial.println("TCPClient : Destructor called");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
free(_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TCPClient::operator==(TCPClient& Object)
|
||||||
|
{
|
||||||
|
return this->_client == Object._client;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TCPClient::closeConnection()
|
||||||
|
{
|
||||||
|
_client.stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TCPClient::freeDataBuffer(uint16_t size)
|
||||||
|
{
|
||||||
|
if(size > _dataBufferSize-1) size = _dataBufferSize - 1;
|
||||||
|
|
||||||
|
uint16_t secureSize = size > _dataSize ? _dataSize : size;
|
||||||
|
|
||||||
|
if(*(_data + secureSize) == '\0')
|
||||||
|
{
|
||||||
|
#ifdef DEBUG_CL
|
||||||
|
Serial.println("Its the terminating string");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
strcpy((char *)_data, (char *)_data + secureSize);
|
||||||
|
_dataSize -= secureSize;
|
||||||
|
}
|
34
src/software_test/tcpServer_test/TCPClient.h
Normal file
34
src/software_test/tcpServer_test/TCPClient.h
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
#ifndef TCPCLIENT_H
|
||||||
|
#define TCPCLIENT_H
|
||||||
|
|
||||||
|
#include <ESP8266WiFi.h>
|
||||||
|
|
||||||
|
//Forward class declaration
|
||||||
|
template <typename T> class TCPServer;
|
||||||
|
|
||||||
|
class TCPClient
|
||||||
|
{
|
||||||
|
template<typename T>
|
||||||
|
friend class TCPServer;
|
||||||
|
public:
|
||||||
|
TCPClient(WiFiClient client, uint8_t id, uint16_t dataBufferSize = 255);
|
||||||
|
TCPClient(const TCPClient &Object);
|
||||||
|
virtual ~TCPClient();
|
||||||
|
bool operator==(TCPClient& Object);
|
||||||
|
bool closeConnection();
|
||||||
|
protected:
|
||||||
|
enum ClientState {NEW, HANDLED, DISCARDED} _clientState;
|
||||||
|
enum Error {OK = 0, MALLOC_ERR = 1} _error;
|
||||||
|
|
||||||
|
WiFiClient _client;
|
||||||
|
uint8_t *_data; //The actual data
|
||||||
|
uint16_t _dataSize; //The logic size of the data contained
|
||||||
|
uint16_t _dataBufferSize; //The physic size of the buffer
|
||||||
|
boolean _newDataAvailable;
|
||||||
|
uint8_t _id;
|
||||||
|
|
||||||
|
void freeDataBuffer(uint16_t size);
|
||||||
|
private:
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //TCPCLIENT_H
|
@ -1,117 +0,0 @@
|
|||||||
#include "TCPServer.h"
|
|
||||||
#define DEBUG
|
|
||||||
|
|
||||||
TCPServer::TCPServer(unsigned int port, uint8_t maxClient) : _wifiServer(port), _port(port), _serverStarted(true), _maxClient(maxClient), _currentClient(NULL)
|
|
||||||
{
|
|
||||||
_wifiServer.begin();
|
|
||||||
}
|
|
||||||
|
|
||||||
TCPServer::~TCPServer()
|
|
||||||
{
|
|
||||||
_clientList.dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
void TCPServer::runServer()
|
|
||||||
{
|
|
||||||
handleNewClients();
|
|
||||||
getClientData();
|
|
||||||
}
|
|
||||||
|
|
||||||
void TCPServer::handleNewClients()
|
|
||||||
{
|
|
||||||
WiFiClient wc;
|
|
||||||
|
|
||||||
if(_maxClient == -1 || _maxClient > _clientList.count())
|
|
||||||
{
|
|
||||||
wc = _wifiServer.available();
|
|
||||||
}
|
|
||||||
|
|
||||||
if(wc && wc.connected())
|
|
||||||
{
|
|
||||||
_clientList.addFirst(new TCPServerHelper::TCPServerClient({wc, TCPServerHelper::TCPServerClient::NEW,{'/0'},0,false,_clientList.count(),{TCPServerHelper::UNDEFINED, TCPServerHelper::UNKNOWN, TCPServerHelper::UNKNOWN_MIME, Dictionary<DictionaryHelper::StringEntity>(), Dictionary<DictionaryHelper::StringEntity>(), NULL,NULL},TCPServerHelper::HTTP_VERB}));
|
|
||||||
#ifdef DEBUG
|
|
||||||
Serial.print("New client accepted : ");Serial.println(_clientList.count()-1);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
_currentClient = _clientList.removeLastRef();//We pick a client in the list to process it's request
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void TCPServer::getClientData()
|
|
||||||
{
|
|
||||||
if(_currentClient == NULL)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t bytesAvailable((_currentClient->client).available());
|
|
||||||
|
|
||||||
if(bytesAvailable)
|
|
||||||
{
|
|
||||||
if(_currentClient->dataSize < 255)
|
|
||||||
{
|
|
||||||
int freeSpace = (255-1/*for \0*/ - _currentClient->dataSize);
|
|
||||||
int amountToBeRead = bytesAvailable < freeSpace ? bytesAvailable : freeSpace;//;bytesAvailable < 254 ? bytesAvailable : 254;
|
|
||||||
|
|
||||||
_currentClient->client.read(_currentClient->data + _currentClient->dataSize, amountToBeRead);
|
|
||||||
_currentClient->dataSize+=amountToBeRead;
|
|
||||||
_currentClient->data[_currentClient->dataSize] = '\0';
|
|
||||||
_currentClient->newDataAvailable = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if(!(_currentClient->client).connected())
|
|
||||||
{
|
|
||||||
#ifdef DEBUG
|
|
||||||
Serial.print("Client can be discarded : ");Serial.println(_currentClient->id);
|
|
||||||
#endif
|
|
||||||
_currentClient->clientState = TCPServerHelper::TCPServerClient::DISCARDED;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if(_currentClient->dataSize > 0)
|
|
||||||
{
|
|
||||||
processClientData(_currentClient);//We process the actual data
|
|
||||||
_currentClient->newDataAvailable = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(_currentClient->clientState == TCPServerHelper::TCPServerClient::DISCARDED)
|
|
||||||
{
|
|
||||||
_currentClient->client.stop();
|
|
||||||
#ifdef DEBUG
|
|
||||||
Serial.print("Client was discarded : ");Serial.println(_currentClient->id);
|
|
||||||
#endif
|
|
||||||
delete _currentClient;
|
|
||||||
_currentClient = NULL;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_clientList.addFirst(_currentClient);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void TCPServer::processClientData(TCPServerHelper::TCPServerClient *client)
|
|
||||||
{
|
|
||||||
Serial.print("Client --> ");Serial.print(client->id);Serial.print(" : ");Serial.println((char *)client->data);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t TCPServer::getMaxClient()
|
|
||||||
{
|
|
||||||
return _maxClient;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t TCPServer::getClientsCount()
|
|
||||||
{
|
|
||||||
return _clientList.count();
|
|
||||||
}
|
|
||||||
|
|
||||||
void TCPServer::startServer()
|
|
||||||
{
|
|
||||||
_serverStarted = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void TCPServer::stopServer()
|
|
||||||
{
|
|
||||||
_serverStarted = false;
|
|
||||||
_clientList.dispose();
|
|
||||||
}
|
|
@ -1,86 +1,194 @@
|
|||||||
#ifndef TCPSERVER_H
|
#ifndef TCPSERVER_H
|
||||||
#define TCPSERVER_H
|
#define TCPSERVER_H
|
||||||
#include <Arduino.h>
|
|
||||||
#include <ESP8266WiFi.h>
|
#include <ESP8266WiFi.h>
|
||||||
#include "List.h"
|
#include "List.h"
|
||||||
#include "Dictionary.h"
|
#include "TCPClient.h"
|
||||||
|
|
||||||
#define MAX_CLIENT -1
|
#define MAX_CLIENT -1
|
||||||
|
#define DEBUG
|
||||||
|
|
||||||
namespace TCPServerHelper
|
|
||||||
{
|
|
||||||
enum HttpRequestMethod {UNDEFINED, GET, HEAD, POST, PUT, DELETE, CONNECT, OPTIONS, TRACE, PATCH};
|
|
||||||
enum HttpVersion {UNKNOWN, HTTP_0_9, HTTP_1_1, HTTP_1_0, HTTP_2_0};
|
|
||||||
enum HttpMIMEType{UNKNOWN_MIME, TEXT_PLAIN, TEXT_CSS, TEXT_HTML, TEXT_JAVASCRIPT, APPLICATION_JSON, APPLICATION_X_WWW_FORM_URLENCODED, IMAGE_PNG, IMAGE_JPEG, AUDIO_MPEG, APPLICATION_OCTET_STREAM};
|
|
||||||
enum HttpParserStatus {HTTP_VERB, HTTP_RESSOURCE, HTTP_VERSION, HTTP_PARAMS, POST_DATA};
|
|
||||||
|
|
||||||
struct HttpRequestData
|
|
||||||
{
|
|
||||||
HttpRequestMethod HRM;
|
|
||||||
HttpVersion HV;
|
|
||||||
HttpMIMEType HMT;
|
|
||||||
Dictionary<DictionaryHelper::StringEntity> getParams;
|
|
||||||
Dictionary<DictionaryHelper::StringEntity> postParams;
|
|
||||||
char *httpResource;
|
|
||||||
char *httpBody;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct TCPServerClient
|
|
||||||
{
|
|
||||||
WiFiClient client;
|
|
||||||
enum ClientState {NEW, HANDLED, QUERY_PARSED, RESPONSE_SENT, DISCARDED} clientState;
|
|
||||||
uint8_t data[255];
|
|
||||||
uint16_t dataSize;
|
|
||||||
boolean newDataAvailable;
|
|
||||||
uint8_t id;
|
|
||||||
HttpRequestData httpRequestData;
|
|
||||||
HttpParserStatus httpParserState;
|
|
||||||
|
|
||||||
bool operator==(TCPServerClient& Object){return this->client == Object.client;}
|
|
||||||
void clearHttpRequestData(TCPServerHelper::HttpRequestData *httpRequestData)
|
|
||||||
{
|
|
||||||
free(httpRequestData->httpResource);free(httpRequestData->httpBody);
|
|
||||||
httpRequestData->getParams.dispose();
|
|
||||||
httpRequestData->postParams.dispose();
|
|
||||||
}
|
|
||||||
~TCPServerClient()
|
|
||||||
{
|
|
||||||
client.stop();
|
|
||||||
clearHttpRequestData(&httpRequestData);
|
|
||||||
}
|
|
||||||
void freeDataBuffer(uint16_t size)
|
|
||||||
{
|
|
||||||
if(size > 254) size = 254;
|
|
||||||
|
|
||||||
uint16_t secureSize = size > dataSize ? dataSize : size;
|
|
||||||
strcpy((char *)data, (char *)data + secureSize);
|
|
||||||
dataSize -= secureSize;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
class TCPServer
|
class TCPServer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
TCPServer(unsigned int port = 80, uint8_t maxClient = MAX_CLIENT);
|
TCPServer(unsigned int port = 80, uint8_t maxClient = MAX_CLIENT, uint16_t clientDataBufferSize = 255) : _wifiServer(port), _port(port), _serverStarted(true), _maxClient(maxClient), _clientDataBufferSize(clientDataBufferSize), _currentClient(NULL)
|
||||||
~TCPServer();
|
{
|
||||||
uint8_t getMaxClient();
|
_wifiServer.begin();
|
||||||
uint8_t getClientsCount();
|
}
|
||||||
virtual void runServer();
|
|
||||||
virtual void startServer();
|
virtual ~TCPServer()
|
||||||
virtual void stopServer();
|
{
|
||||||
|
_clientList.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t getMaxClient()
|
||||||
|
{
|
||||||
|
return _maxClient;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t getConnectedClientsCount()
|
||||||
|
{
|
||||||
|
return _clientList.count();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void runServer()
|
||||||
|
{
|
||||||
|
handleNewClients();
|
||||||
|
getClientData();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void startServer()
|
||||||
|
{
|
||||||
|
if(!_serverStarted)
|
||||||
|
{
|
||||||
|
_wifiServer.begin();
|
||||||
|
_serverStarted = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void stopServer()
|
||||||
|
{
|
||||||
|
if(_serverStarted)
|
||||||
|
{
|
||||||
|
_wifiServer.stop();
|
||||||
|
_clientList.dispose();
|
||||||
|
_serverStarted = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
private:
|
virtual T* createNewClient(WiFiClient wc)
|
||||||
virtual void handleNewClients();
|
{
|
||||||
virtual void getClientData();
|
return new T(wc, freeClientId(), _clientDataBufferSize);
|
||||||
virtual void processClientData(TCPServerHelper::TCPServerClient *client);
|
}
|
||||||
|
|
||||||
|
virtual void handleNewClients()
|
||||||
|
{
|
||||||
|
WiFiClient wc;
|
||||||
|
|
||||||
|
if(_maxClient == -1 || _maxClient > _clientList.count())
|
||||||
|
{
|
||||||
|
wc = _wifiServer.available();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(wc && wc.connected())
|
||||||
|
{
|
||||||
|
T *clientPointer = createNewClient(wc);
|
||||||
|
_clientList.addFirst(clientPointer);
|
||||||
|
#ifdef DEBUG
|
||||||
|
Serial.print("TCPServer : New client accepted : ");Serial.println(clientPointer->_id);
|
||||||
|
#endif
|
||||||
|
greetClient(clientPointer);
|
||||||
|
}
|
||||||
|
|
||||||
|
_currentClient = _clientList.removeLastRef();//We pick a client in the list to process it's request
|
||||||
|
|
||||||
|
if(_currentClient != NULL)
|
||||||
|
{
|
||||||
|
if(_currentClient->_error != TCPClient::OK)
|
||||||
|
{
|
||||||
|
_currentClient->closeConnection();
|
||||||
|
delete _currentClient; _currentClient = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void greetClient(T *client)
|
||||||
|
{
|
||||||
|
client->_client.println(F("Successfully connected !"));
|
||||||
|
client->_client.print(F("Your are client with id : "));
|
||||||
|
client->_client.println(client->_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void getClientData()
|
||||||
|
{
|
||||||
|
if(_currentClient == NULL)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t bytesAvailable((_currentClient->_client).available());
|
||||||
|
|
||||||
|
if(bytesAvailable)
|
||||||
|
{
|
||||||
|
uint16_t freeSpace = (_currentClient->_dataBufferSize-1/*for \0*/ - _currentClient->_dataSize);
|
||||||
|
|
||||||
|
if(freeSpace != 0)
|
||||||
|
{
|
||||||
|
int amountToBeRead = bytesAvailable < freeSpace ? bytesAvailable : freeSpace;
|
||||||
|
|
||||||
|
(_currentClient->_client).read(_currentClient->_data + _currentClient->_dataSize, amountToBeRead);
|
||||||
|
_currentClient->_dataSize += amountToBeRead;
|
||||||
|
_currentClient->_data[_currentClient->_dataSize] = '\0';
|
||||||
|
_currentClient->_newDataAvailable = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(!(_currentClient->_client).connected())
|
||||||
|
{
|
||||||
|
#ifdef DEBUG
|
||||||
|
Serial.print("TCPServer : Client disconnected and can be discarded : ");Serial.println(_currentClient->_id);
|
||||||
|
#endif
|
||||||
|
_currentClient->_clientState = TCPClient::DISCARDED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(_currentClient->_dataSize > 0)
|
||||||
|
{
|
||||||
|
processClientData(_currentClient);//We process the actual data
|
||||||
|
_currentClient->_newDataAvailable = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(_currentClient->_clientState == TCPClient::ClientState::DISCARDED)
|
||||||
|
{
|
||||||
|
_currentClient->closeConnection();
|
||||||
|
#ifdef DEBUG
|
||||||
|
Serial.print("TCPServer : Client was discarded : ");Serial.println(_currentClient->_id);
|
||||||
|
#endif
|
||||||
|
delete _currentClient;
|
||||||
|
_currentClient = NULL;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_clientList.addFirst(_currentClient);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void processClientData(T *client)
|
||||||
|
{
|
||||||
|
if(client->_dataSize > 0 && ((char) client->_data[0] != '\r' && (char) client->_data[0] != '\n'))
|
||||||
|
{
|
||||||
|
Serial.print("Client --> ");Serial.print(client->_id);Serial.print(" : ");Serial.print((char *)client->_data);Serial.println("#");
|
||||||
|
}
|
||||||
|
|
||||||
|
client->freeDataBuffer(client->_dataSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t freeClientId()
|
||||||
|
{
|
||||||
|
int listCounter(_clientList.count());
|
||||||
|
int freeId(0);
|
||||||
|
|
||||||
|
for(int i(0); i < listCounter; i++)
|
||||||
|
{
|
||||||
|
if(_clientList.getRef(i)->_id == freeId)
|
||||||
|
{
|
||||||
|
freeId++;
|
||||||
|
i = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return freeId;
|
||||||
|
}
|
||||||
|
|
||||||
boolean _serverStarted;
|
boolean _serverStarted;
|
||||||
uint8_t _maxClient;
|
uint8_t _maxClient;
|
||||||
unsigned int _port;
|
unsigned int _port;
|
||||||
|
uint16_t _clientDataBufferSize;
|
||||||
WiFiServer _wifiServer;
|
WiFiServer _wifiServer;
|
||||||
TCPServerHelper::TCPServerClient *_currentClient; //current client to be processed
|
T *_currentClient; //current client to be processed
|
||||||
List<TCPServerHelper::TCPServerClient> _clientList;
|
List<T> _clientList;
|
||||||
|
private:
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //TCPSERVER_H
|
#endif //TCPSERVER_H
|
||||||
|
@ -1,143 +0,0 @@
|
|||||||
#include "TCPWebServer.h"
|
|
||||||
#define DEBUG
|
|
||||||
|
|
||||||
TCPWebServer::TCPWebServer(unsigned int port, uint8_t maxClient) : TCPServer(port, maxClient)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void debugInfo()
|
|
||||||
{
|
|
||||||
uint32_t freeMem;
|
|
||||||
uint16_t biggestContigMemBlock;
|
|
||||||
uint8_t frag;
|
|
||||||
ESP.getHeapStats(&freeMem, &biggestContigMemBlock, &frag);
|
|
||||||
Serial.print("Free MEM : ");Serial.println(freeMem);
|
|
||||||
Serial.print("Heap Frag : ");Serial.println(frag);
|
|
||||||
}
|
|
||||||
|
|
||||||
void TCPWebServer::processClientData(TCPServerHelper::TCPServerClient *client)
|
|
||||||
{
|
|
||||||
if(client->newDataAvailable)
|
|
||||||
{
|
|
||||||
switch(client->httpParserState)
|
|
||||||
{
|
|
||||||
case TCPServerHelper::HTTP_VERB:
|
|
||||||
{
|
|
||||||
char *pVerb = strstr((char *)client->data, " ");
|
|
||||||
|
|
||||||
if(pVerb != NULL)
|
|
||||||
{
|
|
||||||
*pVerb = '\0';
|
|
||||||
client->httpRequestData.HRM = getHttpVerbEnumValue((char *)client->data);
|
|
||||||
client->freeDataBuffer((pVerb - (char *)client->data) +1);
|
|
||||||
#ifdef DEBUG
|
|
||||||
Serial.print("Verb : ");Serial.println(client->httpRequestData.HRM);
|
|
||||||
#endif
|
|
||||||
client->httpParserState = TCPServerHelper::HttpParserStatus::HTTP_RESSOURCE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case TCPServerHelper::HTTP_RESSOURCE:
|
|
||||||
{
|
|
||||||
char *pRsrc = strstr((char *)client->data, " ");
|
|
||||||
|
|
||||||
if(pRsrc != NULL)
|
|
||||||
{
|
|
||||||
*pRsrc = '\0';
|
|
||||||
uint16_t length = pRsrc - (char *)client->data;
|
|
||||||
client->httpRequestData.httpResource = (char *) malloc(sizeof(char) * length + 1 ); //for \0
|
|
||||||
if(client->httpRequestData.httpResource != NULL)
|
|
||||||
strcpy(client->httpRequestData.httpResource, (char *)client->data);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
client->clientState = TCPServerHelper::TCPServerClient::ClientState::DISCARDED;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
Serial.print("Resrc : ");Serial.println(client->httpRequestData.httpResource);
|
|
||||||
#endif
|
|
||||||
client->freeDataBuffer(length + 1);
|
|
||||||
|
|
||||||
client->httpParserState = TCPServerHelper::HttpParserStatus::HTTP_VERSION;
|
|
||||||
}
|
|
||||||
else if(client->dataSize == 254)
|
|
||||||
{
|
|
||||||
client->httpRequestData.httpResource = (char *) malloc(sizeof(char) * client->dataSize + 1 ); //for \0
|
|
||||||
if(client->httpRequestData.httpResource != NULL)
|
|
||||||
strcpy(client->httpRequestData.httpResource, (char *)client->data);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
client->clientState = TCPServerHelper::TCPServerClient::ClientState::DISCARDED;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
Serial.print("Resrc : ");Serial.println(client->httpRequestData.httpResource);
|
|
||||||
#endif
|
|
||||||
client->freeDataBuffer(client->dataSize);
|
|
||||||
client->httpParserState = TCPServerHelper::HttpParserStatus::HTTP_VERSION;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case TCPServerHelper::HTTP_VERSION:
|
|
||||||
{
|
|
||||||
char *pEndline = strstr((char *)client->data, "\r\n");
|
|
||||||
char *pVers = strstr((char *)client->data, "HTTP/");
|
|
||||||
|
|
||||||
if(pEndline != NULL && pVers!= NULL)
|
|
||||||
{
|
|
||||||
*pEndline = '\0';
|
|
||||||
client->httpRequestData.HV = getHttpVersionEnumValue(pVers+5);
|
|
||||||
#ifdef DEBUG
|
|
||||||
Serial.print("Vers : ");Serial.println(pVers+5);
|
|
||||||
Serial.print("Vers : ");Serial.println(client->httpRequestData.HV);
|
|
||||||
#endif
|
|
||||||
client->freeDataBuffer((pEndline - (char *)client->data)+2);
|
|
||||||
client->clientState = TCPServerHelper::TCPServerClient::ClientState::DISCARDED;
|
|
||||||
}
|
|
||||||
else //If we do not find it, it's probably split at the end of the buffer, so we ignore some of the resource left over
|
|
||||||
{
|
|
||||||
client->freeDataBuffer(100);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
/*case TCPServerHelper::HTTP_PARAMS:
|
|
||||||
break;
|
|
||||||
case TCPServerHelper::POST_DATA:
|
|
||||||
break;
|
|
||||||
default :*/
|
|
||||||
}
|
|
||||||
/*Serial.print("WEB Client --> ");Serial.print(client->id);Serial.print(" : ");Serial.println((char *)client->data);
|
|
||||||
client->freeDataBuffer(client->dataSize);*/
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
TCPServerHelper::HttpRequestMethod TCPWebServer::getHttpVerbEnumValue(const char *parseBuffer)
|
|
||||||
{
|
|
||||||
//UNDEFINED, GET, HEAD, POST, PUT, DELETE, CONNECT, OPTIONS, TRACE, PATCH
|
|
||||||
if(strcmp(parseBuffer,"GET") == 0){return TCPServerHelper::HttpRequestMethod::GET;}
|
|
||||||
else if(strcmp(parseBuffer,"POST") == 0){return TCPServerHelper::HttpRequestMethod::POST;}
|
|
||||||
else if(strcmp(parseBuffer,"HEAD") == 0){return TCPServerHelper::HttpRequestMethod::HEAD;}
|
|
||||||
else if(strcmp(parseBuffer,"PUT") == 0){return TCPServerHelper::HttpRequestMethod::PUT;}
|
|
||||||
else if(strcmp(parseBuffer,"DELETE") == 0){return TCPServerHelper::HttpRequestMethod::DELETE;}
|
|
||||||
else if(strcmp(parseBuffer,"CONNECT") == 0){return TCPServerHelper::HttpRequestMethod::CONNECT;}
|
|
||||||
else if(strcmp(parseBuffer,"TRACE") == 0){return TCPServerHelper::HttpRequestMethod::TRACE;}
|
|
||||||
else if(strcmp(parseBuffer,"PATCH") == 0){return TCPServerHelper::HttpRequestMethod::PATCH;}
|
|
||||||
else if(strcmp(parseBuffer,"OPTIONS") == 0){return TCPServerHelper::HttpRequestMethod::OPTIONS;}
|
|
||||||
else
|
|
||||||
return TCPServerHelper::HttpRequestMethod::UNDEFINED;
|
|
||||||
}
|
|
||||||
|
|
||||||
TCPServerHelper::HttpVersion TCPWebServer::getHttpVersionEnumValue(const char *parseBuffer)
|
|
||||||
{
|
|
||||||
//HTTP_0_9, HTTP_1_1, HTTP_1_0, HTTP_2_0
|
|
||||||
if(strcmp(parseBuffer,"1.1") == 0){return TCPServerHelper::HttpVersion::HTTP_1_1;}
|
|
||||||
else if(strcmp(parseBuffer,"2.0") == 0){return TCPServerHelper::HttpVersion::HTTP_2_0;}
|
|
||||||
else if(strcmp(parseBuffer,"1.0") == 0){return TCPServerHelper::HttpVersion::HTTP_1_0;}
|
|
||||||
else if(strcmp(parseBuffer,"0.9") == 0){return TCPServerHelper::HttpVersion::HTTP_0_9;}
|
|
||||||
else
|
|
||||||
return TCPServerHelper::HttpVersion::UNKNOWN;
|
|
||||||
}
|
|
@ -1,17 +0,0 @@
|
|||||||
#ifndef TCPWEBSERVER_H
|
|
||||||
#define TCPWEBSERVER_H
|
|
||||||
|
|
||||||
#include "TCPServer.h"
|
|
||||||
|
|
||||||
class TCPWebServer : public TCPServer
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
TCPWebServer(unsigned int port = 80, uint8_t maxClient = MAX_CLIENT);
|
|
||||||
protected:
|
|
||||||
private:
|
|
||||||
virtual void processClientData(TCPServerHelper::TCPServerClient *client);
|
|
||||||
TCPServerHelper::HttpRequestMethod getHttpVerbEnumValue(const char *parseBuffer);
|
|
||||||
TCPServerHelper::HttpVersion getHttpVersionEnumValue(const char *parseBuffer);
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif //TCPWEBSERVER_H
|
|
37
src/software_test/tcpServer_test/WEBClient.cpp
Normal file
37
src/software_test/tcpServer_test/WEBClient.cpp
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
#include "WEBClient.h"
|
||||||
|
|
||||||
|
#define DEBUG_WEBCL
|
||||||
|
|
||||||
|
WEBClient::WEBClient(WiFiClient client, uint8_t id, uint16_t maxResourceBuffer, uint16_t maxBodyBuffer, uint16_t dataBufferSize) : TCPClient(client, id, dataBufferSize), _WEBClientState(WEBServer<WEBClient>::WEBClientState::ACCEPTED), _httpParserState(WEBServer<WEBClient>::HttpParserStatus::HTTP_VERB)
|
||||||
|
{
|
||||||
|
#ifdef DEBUG_WEBCL
|
||||||
|
Serial.println("WEBClient : Standard constructor called");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
_httpRequestData.HRM = WEBServer<WEBClient>::HttpRequestMethod::UNDEFINED;
|
||||||
|
_httpRequestData.HV = WEBServer<WEBClient>::HttpVersion::UNKNOWN;
|
||||||
|
_httpRequestData.HMT = WEBServer<WEBClient>::HttpMIMEType::UNKNOWN_MIME;
|
||||||
|
|
||||||
|
_httpRequestData.getParamsDataPointer = NULL;
|
||||||
|
_httpRequestData.postParamsDataPointer = NULL;
|
||||||
|
|
||||||
|
_httpRequestData.httpResource = NULL;
|
||||||
|
_httpRequestData.maxResourceBuffer = maxResourceBuffer;
|
||||||
|
_httpRequestData.httpBody = NULL;
|
||||||
|
_httpRequestData.maxBodyBuffer = maxBodyBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
WEBClient::~WEBClient()
|
||||||
|
{
|
||||||
|
#ifdef DEBUG_WEBCL
|
||||||
|
Serial.println("WEBClient : Destructor called");
|
||||||
|
#endif
|
||||||
|
clearHttpRequestData();
|
||||||
|
}
|
||||||
|
|
||||||
|
void WEBClient::clearHttpRequestData()
|
||||||
|
{
|
||||||
|
free(_httpRequestData.httpResource);free(_httpRequestData.httpBody);
|
||||||
|
_httpRequestData.getParams.dispose();
|
||||||
|
_httpRequestData.postParams.dispose();
|
||||||
|
}
|
40
src/software_test/tcpServer_test/WEBClient.h
Normal file
40
src/software_test/tcpServer_test/WEBClient.h
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
#ifndef WEBCLIENT_H
|
||||||
|
#define WEBCLIENT_H
|
||||||
|
|
||||||
|
#include "WEBServer.h"
|
||||||
|
#include "TCPClient.h"
|
||||||
|
#include "Dictionary.h"
|
||||||
|
|
||||||
|
class WEBClient : public TCPClient
|
||||||
|
{
|
||||||
|
template <typename T>
|
||||||
|
friend class WEBServer;
|
||||||
|
public:
|
||||||
|
WEBClient(WiFiClient client, uint8_t id, uint16_t maxResourceBuffer = 255, uint16_t maxBodyBuffer = 255, uint16_t dataBufferSize = 511);
|
||||||
|
virtual ~WEBClient();
|
||||||
|
protected:
|
||||||
|
WEBServer<WEBClient>::WEBClientState _WEBClientState;
|
||||||
|
private:
|
||||||
|
struct HttpRequestData
|
||||||
|
{
|
||||||
|
WEBServer<WEBClient>::HttpRequestMethod HRM;
|
||||||
|
WEBServer<WEBClient>::HttpVersion HV;
|
||||||
|
WEBServer<WEBClient>::HttpMIMEType HMT;
|
||||||
|
|
||||||
|
Dictionary<DictionaryHelper::StringEntity> getParams;
|
||||||
|
char *getParamsDataPointer; //Used in the getParams algorithm
|
||||||
|
Dictionary<DictionaryHelper::StringEntity> postParams;
|
||||||
|
char *postParamsDataPointer; //Used in the postParams algorithm
|
||||||
|
|
||||||
|
char *httpResource;
|
||||||
|
uint16_t maxResourceBuffer;
|
||||||
|
char *httpBody;
|
||||||
|
uint16_t maxBodyBuffer;
|
||||||
|
} _httpRequestData;
|
||||||
|
|
||||||
|
WEBServer<WEBClient>::HttpParserStatus _httpParserState;
|
||||||
|
|
||||||
|
void clearHttpRequestData();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //WEBCLIENT_H
|
305
src/software_test/tcpServer_test/WEBServer.h
Normal file
305
src/software_test/tcpServer_test/WEBServer.h
Normal file
@ -0,0 +1,305 @@
|
|||||||
|
#ifndef WEBSERVER_H
|
||||||
|
#define WEBSERVER_H
|
||||||
|
|
||||||
|
#include "TCPServer.h"
|
||||||
|
#include "Dictionary.h"
|
||||||
|
#define DEBUG_WEBS
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
class WEBServer : public TCPServer<T>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum HttpRequestMethod {UNDEFINED, GET, HEAD, POST, PUT, DELETE, CONNECT, OPTIONS, TRACE, PATCH};
|
||||||
|
enum HttpVersion {UNKNOWN, HTTP_0_9, HTTP_1_1, HTTP_1_0, HTTP_2_0};
|
||||||
|
enum HttpMIMEType{UNKNOWN_MIME, TEXT_PLAIN, TEXT_CSS, TEXT_HTML, TEXT_JAVASCRIPT, APPLICATION_JSON, APPLICATION_X_WWW_FORM_URLENCODED, IMAGE_PNG, IMAGE_JPEG, AUDIO_MPEG, APPLICATION_OCTET_STREAM};
|
||||||
|
enum HttpParserStatus {HTTP_VERB, HTTP_RESSOURCE, HTTP_VERSION, HTTP_PARAMS, POST_DATA};
|
||||||
|
enum WEBClientState {ACCEPTED, QUERY_PARSED, RESPONSE_SENT, DONE};
|
||||||
|
enum HTTP_CODE {_400, _401, _403, _404, _500, _501};
|
||||||
|
|
||||||
|
WEBServer(unsigned int port = 80, uint8_t maxClient = MAX_CLIENT, uint16_t clientDataBufferSize = 512) : TCPServer<T>(port, maxClient, clientDataBufferSize) {}
|
||||||
|
protected:
|
||||||
|
private:
|
||||||
|
virtual T* createNewClient(WiFiClient wc)
|
||||||
|
{
|
||||||
|
return new T(wc, TCPServer<T>::freeClientId());
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void greetClient(T *client)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void processClientData(T *client)
|
||||||
|
{
|
||||||
|
switch(client->_WEBClientState)
|
||||||
|
{
|
||||||
|
case ACCEPTED:
|
||||||
|
queryParser(client);
|
||||||
|
break;
|
||||||
|
case QUERY_PARSED:
|
||||||
|
sendDataToClient(client);
|
||||||
|
break;
|
||||||
|
case RESPONSE_SENT:
|
||||||
|
break;
|
||||||
|
case DONE:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void queryParser(T *client)
|
||||||
|
{
|
||||||
|
switch(client->_httpParserState)
|
||||||
|
{
|
||||||
|
case HttpParserStatus::HTTP_VERB:
|
||||||
|
{
|
||||||
|
#ifdef DEBUG_WEBS
|
||||||
|
Serial.println((char *)client->_data);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
char *pVerb = strstr((char *)client->_data, " ");
|
||||||
|
|
||||||
|
if(pVerb != NULL)
|
||||||
|
{
|
||||||
|
*pVerb = '\0';
|
||||||
|
client->_httpRequestData.HRM = getHttpVerbEnumValue((char *)client->_data);
|
||||||
|
client->freeDataBuffer((pVerb - (char *)client->_data) +1);
|
||||||
|
|
||||||
|
if(client->_httpRequestData.HRM == HttpRequestMethod::UNDEFINED) //Error 400
|
||||||
|
{
|
||||||
|
sendInfoResponse(HTTP_CODE::_400, client, "The server could not understand the request due to invalid syntax");
|
||||||
|
client->_clientState = TCPClient::ClientState::DISCARDED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG_WEBS
|
||||||
|
Serial.print("Verb : ");Serial.println(client->_httpRequestData.HRM);
|
||||||
|
Serial.println((char *)client->_data);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
client->_httpParserState = HttpParserStatus::HTTP_RESSOURCE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sendInfoResponse(HTTP_CODE::_400, client, "The server could not understand the request due to invalid syntax");
|
||||||
|
client->_clientState = TCPClient::ClientState::DISCARDED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case HttpParserStatus::HTTP_RESSOURCE:
|
||||||
|
{
|
||||||
|
char *pRsrc = strstr((char *)client->_data, " ");
|
||||||
|
|
||||||
|
if(pRsrc != NULL)
|
||||||
|
{
|
||||||
|
*pRsrc = '\0';
|
||||||
|
uint16_t safeLength = pRsrc - (char *)client->_data <= client->_httpRequestData.maxResourceBuffer ? pRsrc - (char *)client->_data : client->_httpRequestData.maxResourceBuffer;
|
||||||
|
|
||||||
|
#ifdef DEBUG_WEBS
|
||||||
|
Serial.print("Resrc length : ");Serial.println(safeLength);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
client->_httpRequestData.httpResource = (char *) malloc(sizeof(char) * (safeLength+1) ); //for \0
|
||||||
|
if(client->_httpRequestData.httpResource != NULL)
|
||||||
|
{
|
||||||
|
strncpy(client->_httpRequestData.httpResource, (char *)client->_data, safeLength);
|
||||||
|
client->_httpRequestData.httpResource[safeLength] = '\0';
|
||||||
|
}
|
||||||
|
else //Error 500
|
||||||
|
{
|
||||||
|
sendInfoResponse(HTTP_CODE::_500, client, "Failed to allocate memory for resources");
|
||||||
|
client->_clientState = TCPClient::ClientState::DISCARDED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
client->freeDataBuffer(safeLength + 1);
|
||||||
|
|
||||||
|
#ifdef DEBUG_WEBS
|
||||||
|
Serial.print("Resrc : ");Serial.println(client->_httpRequestData.httpResource);
|
||||||
|
Serial.println((char *)client->_data);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else //Resource is probably too long, so we truncate it
|
||||||
|
{
|
||||||
|
client->_httpRequestData.httpResource = (char *) malloc(sizeof(char) * (client->_httpRequestData.maxResourceBuffer+1) ); //for \0
|
||||||
|
if(client->_httpRequestData.httpResource != NULL)
|
||||||
|
{
|
||||||
|
strncpy(client->_httpRequestData.httpResource, (char *)client->_data, client->_httpRequestData.maxResourceBuffer);
|
||||||
|
client->_httpRequestData.httpResource[client->_httpRequestData.maxResourceBuffer] = '\0';
|
||||||
|
}
|
||||||
|
else //Error 500
|
||||||
|
{
|
||||||
|
sendInfoResponse(HTTP_CODE::_500, client, "Failed to allocate memory for resources");
|
||||||
|
client->_clientState = TCPClient::ClientState::DISCARDED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
client->freeDataBuffer(client->_httpRequestData.maxResourceBuffer + 1);
|
||||||
|
}
|
||||||
|
client->_httpParserState = HttpParserStatus::HTTP_PARAMS;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case HttpParserStatus::HTTP_VERSION:
|
||||||
|
{
|
||||||
|
char *pEndline = strstr((char *)client->_data, "\r\n");
|
||||||
|
char *pVers = strstr((char *)client->_data, "HTTP/");
|
||||||
|
|
||||||
|
if(pEndline != NULL && pVers!= NULL)
|
||||||
|
{
|
||||||
|
*pEndline = '\0';
|
||||||
|
client->_httpRequestData.HV = getHttpVersionEnumValue(pVers+5);
|
||||||
|
|
||||||
|
#ifdef DEBUG_WEBS
|
||||||
|
Serial.print("Vers : ");Serial.println(pVers+5);
|
||||||
|
Serial.print("Vers : ");Serial.println(client->_httpRequestData.HV);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
client->freeDataBuffer((pEndline - (char *)client->_data)+2);
|
||||||
|
|
||||||
|
#ifdef DEBUG_WEBS
|
||||||
|
Serial.println((char *)client->_data);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
client->_httpParserState = HttpParserStatus::POST_DATA;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case HttpParserStatus::HTTP_PARAMS: //index.htm?var1=1&var2=2...
|
||||||
|
if(!httpParamParser(client))
|
||||||
|
{
|
||||||
|
#ifdef DEBUG_WEBS
|
||||||
|
Serial.print("Resrc : ");Serial.println(client->_httpRequestData.httpResource);
|
||||||
|
Serial.println("Get params :");
|
||||||
|
for(int i = 0; i < client->_httpRequestData.getParams.count(); i++)
|
||||||
|
{
|
||||||
|
Serial.print(client->_httpRequestData.getParams.getParameter(i));Serial.print(" : ");Serial.println(client->_httpRequestData.getParams.getAt(i)->getString());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
client->_httpParserState = HttpParserStatus::HTTP_VERSION;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case HttpParserStatus::POST_DATA:
|
||||||
|
|
||||||
|
client->_WEBClientState = WEBClientState::QUERY_PARSED;
|
||||||
|
break;
|
||||||
|
default :
|
||||||
|
sendInfoResponse(HTTP_CODE::_500, client, "WEB server error");
|
||||||
|
client->_clientState = TCPClient::ClientState::DISCARDED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean httpParamParser(T *client)
|
||||||
|
{
|
||||||
|
char *pGetParam = strchr((char *)client->_httpRequestData.httpResource, '?');
|
||||||
|
|
||||||
|
|
||||||
|
if(pGetParam != NULL) //There are some params to be parsed
|
||||||
|
{
|
||||||
|
if(client->_httpRequestData.getParamsDataPointer == NULL)
|
||||||
|
{
|
||||||
|
client->_httpRequestData.getParamsDataPointer = pGetParam +1;//We save the starting position of the string to parse
|
||||||
|
}
|
||||||
|
|
||||||
|
char *key = strchr(client->_httpRequestData.getParamsDataPointer, '=');
|
||||||
|
char *value = strchr(client->_httpRequestData.getParamsDataPointer, '&');
|
||||||
|
|
||||||
|
if(key == NULL && value == NULL) //Only the key is present
|
||||||
|
{
|
||||||
|
client->_httpRequestData.getParams.add(client->_httpRequestData.getParamsDataPointer, new DictionaryHelper::StringEntity(NULL));
|
||||||
|
*pGetParam = '\0';
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else if(key != NULL && value != NULL)
|
||||||
|
{
|
||||||
|
if(key < value)*key = '\0';
|
||||||
|
*value = '\0';
|
||||||
|
|
||||||
|
client->_httpRequestData.getParams.add(client->_httpRequestData.getParamsDataPointer, new DictionaryHelper::StringEntity(key > value ? NULL : key + 1));
|
||||||
|
strcpy(client->_httpRequestData.getParamsDataPointer,value+1);
|
||||||
|
|
||||||
|
#ifdef DEBUG_WEBS
|
||||||
|
Serial.print("Params pointer : ");Serial.println(client->_httpRequestData.getParamsDataPointer);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else if(key != NULL && value == NULL) //Only one key/value pair present
|
||||||
|
{
|
||||||
|
*key = '\0';
|
||||||
|
|
||||||
|
client->_httpRequestData.getParams.add(client->_httpRequestData.getParamsDataPointer, new DictionaryHelper::StringEntity(key+1));
|
||||||
|
*pGetParam = '\0';
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else if(key == NULL && value != NULL)
|
||||||
|
{
|
||||||
|
*value = '\0';
|
||||||
|
|
||||||
|
client->_httpRequestData.getParams.add(client->_httpRequestData.getParamsDataPointer, new DictionaryHelper::StringEntity(NULL));
|
||||||
|
strcpy(client->_httpRequestData.getParamsDataPointer,value+1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else //nothing to parse or done
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void sendDataToClient(T *client)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void sendInfoResponse(HTTP_CODE http_code, T *client, const char *message)
|
||||||
|
{
|
||||||
|
switch(http_code)
|
||||||
|
{
|
||||||
|
case _500:
|
||||||
|
client->_client.print(F("HTTP/1.1 500 Internal Server Error\r\nContent-Type: text/html\r\nContent-Length: "));
|
||||||
|
client->_client.print(strlen(message) + 59);
|
||||||
|
client->_client.print(F("\r\n\r\n<!DOCTYPE HTML>\r\n<html>\r\n<h1>Error 500</h1><p>"));
|
||||||
|
client->_client.print(message);
|
||||||
|
client->_client.print(F("</p>\r\n</html>"));
|
||||||
|
break;
|
||||||
|
case _400:
|
||||||
|
client->_client.print(F("HTTP/1.1 400 Bad Request\r\nContent-Type: text/html\r\nContent-Length: "));
|
||||||
|
client->_client.print(strlen(message) + 59);
|
||||||
|
client->_client.print(F("\r\n\r\n<!DOCTYPE HTML>\r\n<html>\r\n<h1>Error 400</h1><p>"));
|
||||||
|
client->_client.print(message);
|
||||||
|
client->_client.print(F("</p>\r\n</html>"));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*Static helper methods*/
|
||||||
|
|
||||||
|
static HttpRequestMethod getHttpVerbEnumValue(const char *parseBuffer)
|
||||||
|
{
|
||||||
|
//UNDEFINED, GET, HEAD, POST, PUT, DELETE, CONNECT, OPTIONS, TRACE, PATCH
|
||||||
|
if(strcmp(parseBuffer,"GET") == 0){return HttpRequestMethod::GET;}
|
||||||
|
else if(strcmp(parseBuffer,"POST") == 0){return HttpRequestMethod::POST;}
|
||||||
|
else if(strcmp(parseBuffer,"HEAD") == 0){return HttpRequestMethod::HEAD;}
|
||||||
|
else if(strcmp(parseBuffer,"PUT") == 0){return HttpRequestMethod::PUT;}
|
||||||
|
else if(strcmp(parseBuffer,"DELETE") == 0){return HttpRequestMethod::DELETE;}
|
||||||
|
else if(strcmp(parseBuffer,"CONNECT") == 0){return HttpRequestMethod::CONNECT;}
|
||||||
|
else if(strcmp(parseBuffer,"TRACE") == 0){return HttpRequestMethod::TRACE;}
|
||||||
|
else if(strcmp(parseBuffer,"PATCH") == 0){return HttpRequestMethod::PATCH;}
|
||||||
|
else if(strcmp(parseBuffer,"OPTIONS") == 0){return HttpRequestMethod::OPTIONS;}
|
||||||
|
else
|
||||||
|
return HttpRequestMethod::UNDEFINED;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HttpVersion getHttpVersionEnumValue(const char *parseBuffer)
|
||||||
|
{
|
||||||
|
//HTTP_0_9, HTTP_1_1, HTTP_1_0, HTTP_2_0
|
||||||
|
if(strcmp(parseBuffer,"1.1") == 0){return HttpVersion::HTTP_1_1;}
|
||||||
|
else if(strcmp(parseBuffer,"2.0") == 0){return HttpVersion::HTTP_2_0;}
|
||||||
|
else if(strcmp(parseBuffer,"1.0") == 0){return HttpVersion::HTTP_1_0;}
|
||||||
|
else if(strcmp(parseBuffer,"0.9") == 0){return HttpVersion::HTTP_0_9;}
|
||||||
|
else
|
||||||
|
return HttpVersion::UNKNOWN;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //WEBSERVER_H
|
@ -1,12 +1,20 @@
|
|||||||
/**
|
/**
|
||||||
* This sketch was written in order to developp and test the multi client tcp server which will be used in my project
|
* This sketch was written in order to developp and test the multi-client tcp server which will later be used in my project
|
||||||
* Anatole SCHRAMM-HENRY 08/05/2019
|
* Anatole SCHRAMM-HENRY 08/05/2019
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "TCPWebServer.h"
|
#include "TCPClient.h"
|
||||||
|
#include "TCPServer.h"
|
||||||
|
#include "WEBServer.h"
|
||||||
|
#include "WEBClient.h"
|
||||||
|
|
||||||
|
uint32_t lastFreeMem(0);
|
||||||
|
uint16_t lastClientCount(0);
|
||||||
|
|
||||||
|
TCPServer<TCPClient> server(80, MAX_CLIENT, 5);
|
||||||
|
WEBServer<WEBClient> webServer(8080);
|
||||||
|
|
||||||
WiFiEventHandler gotIpEventHandler, disconnectedEventHandler;
|
WiFiEventHandler gotIpEventHandler, disconnectedEventHandler;
|
||||||
TCPWebServer tws(80,2);
|
|
||||||
|
|
||||||
void setup() {
|
void setup() {
|
||||||
// put your setup code here, to run once:
|
// put your setup code here, to run once:
|
||||||
@ -19,9 +27,30 @@ void setup() {
|
|||||||
WiFi.begin("freebox_Henry","eustache1930");
|
WiFi.begin("freebox_Henry","eustache1930");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void debugInfo()
|
||||||
|
{
|
||||||
|
uint32_t freeMem;
|
||||||
|
uint16_t biggestContigMemBlock;
|
||||||
|
uint8_t frag;
|
||||||
|
ESP.getHeapStats(&freeMem, &biggestContigMemBlock, &frag);
|
||||||
|
if(lastFreeMem != freeMem)
|
||||||
|
{
|
||||||
|
Serial.print("Free MEM : ");Serial.println(freeMem);
|
||||||
|
Serial.print("Heap Frag : ");Serial.println(frag);
|
||||||
|
lastFreeMem = freeMem;
|
||||||
|
}
|
||||||
|
if(lastClientCount != server.getConnectedClientsCount())
|
||||||
|
{
|
||||||
|
lastClientCount = server.getConnectedClientsCount();
|
||||||
|
Serial.print("Connected client(s) : ");Serial.println(lastClientCount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void loop() {
|
void loop() {
|
||||||
// put your main code here, to run repeatedly:
|
// put your main code here, to run repeatedly:
|
||||||
tws.runServer();
|
server.runServer();
|
||||||
|
webServer.runServer();
|
||||||
|
debugInfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user