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" #include "WEBServerManager.h"
#define DEBUG #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(); _wifiServer.begin();
} }
@ -13,6 +14,7 @@ boolean WEBServerManager::runServer()
{ {
case WAITING_FOR_CLIENT: case WAITING_FOR_CLIENT:
_wifiClient.stopAll(); _wifiClient.stopAll();
_wifiClient = _wifiServer.available(); _wifiClient = _wifiServer.available();
if(_wifiClient) if(_wifiClient)
{ {
@ -23,20 +25,15 @@ boolean WEBServerManager::runServer()
} }
break; break;
case NEW: case NEW:
_clientTimeout = millis();
_clientState = NOT_HANDLED; _clientState = NOT_HANDLED;
break; break;
case NOT_HANDLED: case NOT_HANDLED:
if(millis()-_clientTimeout > 500) clearHttpRequestData();
{
_clientState = HANDLED;
#ifdef DEBUG
Serial.println("Client timed out !!!");
#endif
}
parseQuery(&_wifiClient); parseQuery(&_wifiClient);
#ifdef DEBUG
Serial.println("Nothing more from client !!!");
#endif
_clientState = QUERY_PARSED;
break; break;
case QUERY_PARSED: case QUERY_PARSED:
#ifdef DEBUG #ifdef DEBUG
@ -67,104 +64,117 @@ boolean WEBServerManager::runServer()
boolean WEBServerManager::parseQuery(WiFiClient *wifiClient) boolean WEBServerManager::parseQuery(WiFiClient *wifiClient)
{ {
char readChar(0), *parseBuffer(NULL); char readChar(0), *parseBuffer(NULL);
_httpParserState = INIT;
while(wifiClient->available()) _httpParserState = INIT;
_clientTimeout = millis();
while(wifiClient->available() || millis() - _clientTimeout < 150)
{ {
readChar = (char)wifiClient->read(); if(wifiClient->available())
#ifdef DEBUG
//Serial.print(readChar);
#endif
//INIT, LINE_BREAK, HTTP_VERB_SECTION, HTTP_RESOURCE_SECTION, HTTP_VER_SECTION, BODY_SECTION, IGNORED, ERROR
switch(_httpParserState)
{ {
case INIT: readChar = (char)wifiClient->read();
if(readChar >= 65 && readChar <= 90) #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); parseBuffer = addChar(parseBuffer, readChar);
_httpParserState = HTTP_VERB_SECTION; break;
} case PARAMETER_SECTION:
else if(readChar == '\n')
_httpParserState = ERROR; {
break; _httpParserState = LINE_BREAK;
case LINE_BREAK: }
_httpParserState = IGNORED; break;
break; case IGNORED:
case HTTP_VERB_SECTION: break;
if(readChar >= 65 && readChar <= 90) case ERROR:
{ return false;
parseBuffer = addChar(parseBuffer, readChar); break; //Not necessary
_httpParserState = HTTP_VERB_SECTION; default :
} break;
else if (readChar == ' ') }
{ _clientTimeout = millis();
//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;
} }
_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; return true;
} }
@ -379,3 +389,13 @@ WEBServerManager::HttpVersion WEBServerManager::getHttpVersionEnumValue(const ch
return UNKNOWN; 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 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 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 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 HttpParserStatus {INIT, LINE_BREAK, HTTP_VERB_SECTION, HTTP_RESOURCE_SECTION, HTTP_VER_SECTION, PARAMETER_SECTION, BODY_SECTION, IGNORED, ERROR};
enum HttpMIMEType{TEXT_PLAIN, TEXT_CSS, TEXT_HTML, TEXT_JAVASCRIPT}; enum HttpMIMEType{UNKNOWN_MIME, TEXT_PLAIN, TEXT_CSS, TEXT_HTML, TEXT_JAVASCRIPT, APPLICATION_JSON, APPLICATION_X_WWW_FORM_URLENCODED};
struct HttpRequestData{ struct HttpRequestData{
HttpRequestMethod HRM; HttpRequestMethod HRM;
HttpVersion HV; HttpVersion HV;
HttpMIMEType HMT;
char *httpResource; char *httpResource;
char *httpBody; char *httpBody;
}; };
@ -36,6 +37,7 @@ class WEBServerManager
char *getFileExtension(char *name); char *getFileExtension(char *name);
HttpMIMEType getMIMETypeByExtension(const char *extension); HttpMIMEType getMIMETypeByExtension(const char *extension);
char *getHTTPHeader(HttpMIMEType httpMIMEType, unsigned long size); char *getHTTPHeader(HttpMIMEType httpMIMEType, unsigned long size);
void clearHttpRequestData();
WiFiServer _wifiServer; WiFiServer _wifiServer;
WiFiClient _wifiClient;//One client only, maybe replaced with a fifo in the future WiFiClient _wifiClient;//One client only, maybe replaced with a fifo in the future