Improved WEBServerManager class

This commit is contained in:
anschrammh 2019-03-31 23:34:15 +02:00
parent 92b648fa67
commit d302ce7e45
2 changed files with 127 additions and 105 deletions

View File

@ -1,8 +1,9 @@
#include "WEBServerManager.h"
#define DEBUG
#define DEBUG_RAW
WEBServerManager::WEBServerManager(unsigned int port, SDCardManager *sdCardManager) : _wifiServer(port), _sdCardManager(sdCardManager), _httpRequestData({UNDEFINED, UNKNOWN, NULL,NULL}), _httpParserState(INIT), _clientState(WAITING_FOR_CLIENT), _port(port), _clientTimeout(0)
WEBServerManager::WEBServerManager(unsigned int port, SDCardManager *sdCardManager) : _wifiServer(port), _sdCardManager(sdCardManager), _httpRequestData({UNDEFINED, UNKNOWN, UNKNOWN_MIME, NULL,NULL}), _httpParserState(INIT), _clientState(WAITING_FOR_CLIENT), _port(port), _clientTimeout(0)
{
_wifiServer.begin();
}
@ -13,6 +14,7 @@ boolean WEBServerManager::runServer()
{
case WAITING_FOR_CLIENT:
_wifiClient.stopAll();
_wifiClient = _wifiServer.available();
if(_wifiClient)
{
@ -23,20 +25,15 @@ boolean WEBServerManager::runServer()
}
break;
case NEW:
_clientTimeout = millis();
_clientState = NOT_HANDLED;
break;
case NOT_HANDLED:
if(millis()-_clientTimeout > 500)
{
_clientState = HANDLED;
#ifdef DEBUG
Serial.println("Client timed out !!!");
#endif
}
clearHttpRequestData();
parseQuery(&_wifiClient);
#ifdef DEBUG
Serial.println("Nothing more from client !!!");
#endif
_clientState = QUERY_PARSED;
break;
case QUERY_PARSED:
#ifdef DEBUG
@ -67,104 +64,117 @@ boolean WEBServerManager::runServer()
boolean WEBServerManager::parseQuery(WiFiClient *wifiClient)
{
char readChar(0), *parseBuffer(NULL);
_httpParserState = INIT;
while(wifiClient->available())
_httpParserState = INIT;
_clientTimeout = millis();
while(wifiClient->available() || millis() - _clientTimeout < 150)
{
readChar = (char)wifiClient->read();
#ifdef DEBUG
//Serial.print(readChar);
#endif
//INIT, LINE_BREAK, HTTP_VERB_SECTION, HTTP_RESOURCE_SECTION, HTTP_VER_SECTION, BODY_SECTION, IGNORED, ERROR
switch(_httpParserState)
if(wifiClient->available())
{
case INIT:
if(readChar >= 65 && readChar <= 90)
{
readChar = (char)wifiClient->read();
#ifdef DEBUG_RAW
Serial.print(readChar);
#endif
//INIT, LINE_BREAK, HTTP_VERB_SECTION, HTTP_RESOURCE_SECTION, HTTP_VER_SECTION, BODY_SECTION, IGNORED, ERROR
switch(_httpParserState)
{
case INIT:
if(readChar >= 65 && readChar <= 90)
{
parseBuffer = addChar(parseBuffer, readChar);
_httpParserState = HTTP_VERB_SECTION;
}
else
_httpParserState = ERROR;
break;
case LINE_BREAK:
if(readChar == '\n')
_httpParserState = BODY_SECTION;
else if(readChar != '\r')
_httpParserState = PARAMETER_SECTION;
break;
case HTTP_VERB_SECTION:
if(readChar >= 65 && readChar <= 90)
{
parseBuffer = addChar(parseBuffer, readChar);
_httpParserState = HTTP_VERB_SECTION;
}
else if (readChar == ' ')
{
//This is the end of the section
_httpRequestData.HRM = getHttpVerbEnumValue(parseBuffer);
free(parseBuffer);parseBuffer = NULL;
_httpParserState = HTTP_RESOURCE_SECTION;
}
else
_httpParserState = ERROR;
break;
case HTTP_RESOURCE_SECTION:
if(readChar != ' ')
{
parseBuffer = addChar(parseBuffer, readChar);
_httpParserState = HTTP_RESOURCE_SECTION;
}
else
{
free(_httpRequestData.httpResource);_httpRequestData.httpResource = NULL;
_httpRequestData.httpResource = parseBuffer;parseBuffer = NULL;
_httpParserState = HTTP_VER_SECTION;
}
break;
case HTTP_VER_SECTION:
if((readChar >= 48 && readChar <= 57) || readChar == '.')
{
parseBuffer = addChar(parseBuffer, readChar);
_httpParserState = HTTP_VER_SECTION;
}
else if(readChar == '\n')
{
_httpRequestData.HV = getHttpVersionEnumValue(parseBuffer);
free(parseBuffer);parseBuffer = NULL;
_httpParserState = LINE_BREAK;
}
break;
case BODY_SECTION:
parseBuffer = addChar(parseBuffer, readChar);
_httpParserState = HTTP_VERB_SECTION;
}
else
_httpParserState = ERROR;
break;
case LINE_BREAK:
_httpParserState = IGNORED;
break;
case HTTP_VERB_SECTION:
if(readChar >= 65 && readChar <= 90)
{
parseBuffer = addChar(parseBuffer, readChar);
_httpParserState = HTTP_VERB_SECTION;
}
else if (readChar == ' ')
{
//This is the end of the section
#ifdef DEBUG
Serial.print("HTTP VERB : ");
Serial.println(parseBuffer);
#endif
_httpRequestData.HRM = getHttpVerbEnumValue(parseBuffer);
#ifdef DEBUG
Serial.print("ENUM VALUE :");
Serial.println(_httpRequestData.HRM);
#endif
free(parseBuffer);parseBuffer = NULL;
_httpParserState = HTTP_RESOURCE_SECTION;
}
else
_httpParserState = ERROR;
break;
case HTTP_RESOURCE_SECTION:
if(readChar != ' ')
{
parseBuffer = addChar(parseBuffer, readChar);
_httpParserState = HTTP_RESOURCE_SECTION;
}
else
{
#ifdef DEBUG
Serial.print("HTTP RESOURCE : ");
Serial.println(parseBuffer);
#endif
free(_httpRequestData.httpResource);_httpRequestData.httpResource = NULL;
_httpRequestData.httpResource = parseBuffer;parseBuffer = NULL;
_httpParserState = HTTP_VER_SECTION;
}
break;
case HTTP_VER_SECTION:
if((readChar >= 48 && readChar <= 57) || readChar == '.')
{
parseBuffer = addChar(parseBuffer, readChar);
_httpParserState = HTTP_VER_SECTION;
}
else if(readChar == '\r' || readChar == '\n')
{
#ifdef DEBUG
Serial.print("HTTP VERSION : ");
Serial.println(parseBuffer);
#endif
_httpRequestData.HV = getHttpVersionEnumValue(parseBuffer);
#ifdef DEBUG
Serial.print("HTTP VERSION ENUM : ");
Serial.println(_httpRequestData.HV);
#endif
free(parseBuffer);parseBuffer = NULL;
_httpParserState = LINE_BREAK;
}
break;
case BODY_SECTION:
break;
case IGNORED:
break;
case ERROR:
return false;
break; //Not necessary
default :
break;
break;
case PARAMETER_SECTION:
if(readChar == '\n')
{
_httpParserState = LINE_BREAK;
}
break;
case IGNORED:
break;
case ERROR:
return false;
break; //Not necessary
default :
break;
}
_clientTimeout = millis();
}
_clientState = QUERY_PARSED;
}
if(parseBuffer != NULL)
if(strlen(parseBuffer) > 0)
{
_httpRequestData.httpBody = parseBuffer;
parseBuffer = NULL;
}
#ifdef DEBUG
Serial.print("HTTP VERB : ");
Serial.println(_httpRequestData.HRM);
Serial.print("HTTP RESOURCE : ");
Serial.println(_httpRequestData.httpResource);
Serial.print("HTTP VERSION : ");
Serial.println(_httpRequestData.HV);
Serial.print("BODY CONTENT : ");
Serial.println(_httpRequestData.httpBody);
#endif
return true;
}
@ -379,3 +389,13 @@ WEBServerManager::HttpVersion WEBServerManager::getHttpVersionEnumValue(const ch
return UNKNOWN;
}
void WEBServerManager::clearHttpRequestData()
{
_httpRequestData.HRM = UNDEFINED;
_httpRequestData.HV = UNKNOWN;
_httpRequestData.HMT = UNKNOWN_MIME;
free(_httpRequestData.httpResource);free(_httpRequestData.httpBody);
_httpRequestData.httpResource = NULL;_httpRequestData.httpBody = NULL;
}

View File

@ -18,12 +18,13 @@ class WEBServerManager
enum ClientStatus {NOT_HANDLED, HANDLED, NEW, WAITING_FOR_CLIENT, QUERY_PARSED, RESPONSE_SENT};
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 HttpParserStatus {INIT, LINE_BREAK, HTTP_VERB_SECTION, HTTP_RESOURCE_SECTION, HTTP_VER_SECTION, BODY_SECTION, IGNORED, ERROR};
enum HttpMIMEType{TEXT_PLAIN, TEXT_CSS, TEXT_HTML, TEXT_JAVASCRIPT};
enum HttpParserStatus {INIT, LINE_BREAK, HTTP_VERB_SECTION, HTTP_RESOURCE_SECTION, HTTP_VER_SECTION, PARAMETER_SECTION, BODY_SECTION, IGNORED, ERROR};
enum HttpMIMEType{UNKNOWN_MIME, TEXT_PLAIN, TEXT_CSS, TEXT_HTML, TEXT_JAVASCRIPT, APPLICATION_JSON, APPLICATION_X_WWW_FORM_URLENCODED};
struct HttpRequestData{
HttpRequestMethod HRM;
HttpVersion HV;
HttpMIMEType HMT;
char *httpResource;
char *httpBody;
};
@ -36,6 +37,7 @@ class WEBServerManager
char *getFileExtension(char *name);
HttpMIMEType getMIMETypeByExtension(const char *extension);
char *getHTTPHeader(HttpMIMEType httpMIMEType, unsigned long size);
void clearHttpRequestData();
WiFiServer _wifiServer;
WiFiClient _wifiClient;//One client only, maybe replaced with a fifo in the future