ESP8266_swiss_army_board/src/app/TCPServer.h
2020-02-02 20:57:53 +01:00

197 lines
5.0 KiB
C++

#ifndef TCPSERVER_H
#define TCPSERVER_H
#include <ESP8266WiFi.h>
#include "List.h"
#include "TCPClient.h"
#define MAX_CLIENT -1
//#define DEBUG_TCPS
template <typename T>
class TCPServer
{
public:
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)
{
_wifiServer.begin();
}
virtual ~TCPServer()
{
_clientList.dispose();
}
uint8_t getMaxClient()
{
return _maxClient;
}
unsigned int getPort() const
{
return _port;
}
uint8_t getConnectedClientsCount()
{
return _clientList.count();
}
virtual void run()
{
handleNewClients();
getClientData();
}
virtual void start()
{
if(!_serverStarted)
{
_wifiServer.begin();
_serverStarted = true;
}
}
virtual void stop()
{
if(_serverStarted)
{
_wifiServer.stop();
_clientList.dispose();
_serverStarted = false;
}
}
protected:
virtual T* createNewClient(WiFiClient wc)
{
return new T(wc, freeClientId(), _clientDataBufferSize);
}
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_TCPS
Serial.printf("TCPServer : New client accepted. Id : %u , Number of clients : %u, local port : %u, remote port : %u\n",clientPointer->_id, _clientList.count(),clientPointer->_client.localPort(),clientPointer->_client.remotePort());
#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_TCPS
Serial.print("TCPServer : Client disconnected and can be discarded : ");Serial.println(_currentClient->_id);
#endif
_currentClient->_clientState = TCPClient::DISCARDED;
}
processClientData(_currentClient);//We process the actual data
_currentClient->_newDataAvailable = false;
if(_currentClient->_clientState == TCPClient::ClientState::DISCARDED)
{
_currentClient->closeConnection();
#ifdef DEBUG_TCPS
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;
uint8_t _maxClient;
unsigned int _port;
uint16_t _clientDataBufferSize;
WiFiServer _wifiServer;
T *_currentClient; //current client to be processed
List<T> _clientList;
private:
};
#endif //TCPSERVER_H