From 30f49006094eb710de4f92bf2c097d67d83b9a9a Mon Sep 17 00:00:00 2001 From: anschrammh Date: Sun, 31 Mar 2019 11:01:55 +0200 Subject: [PATCH] Added the WEBServerManager class --- src/app/WEBServerManager.cpp | 232 +++++++++++++++++++++++++++++++++++ src/app/WEBServerManager.h | 46 +++++++ 2 files changed, 278 insertions(+) create mode 100644 src/app/WEBServerManager.cpp create mode 100644 src/app/WEBServerManager.h diff --git a/src/app/WEBServerManager.cpp b/src/app/WEBServerManager.cpp new file mode 100644 index 0000000..9058a28 --- /dev/null +++ b/src/app/WEBServerManager.cpp @@ -0,0 +1,232 @@ +#include "WEBServerManager.h" + +#define DEBUG + +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) +{ + _wifiServer.begin(); +} + +boolean WEBServerManager::runServer() +{ + switch(_clientState) + { + case WAITING_FOR_CLIENT: + _wifiClient.stopAll(); + _wifiClient = _wifiServer.available(); + if(_wifiClient) + { + _clientState = NEW; + _clientTimeout = millis(); + #ifdef DEBUG + Serial.println("Client connected !!!"); + #endif + } + break; + case NEW: + _clientState = NOT_HANDLED; + break; + case NOT_HANDLED: + if(millis()-_clientTimeout > 500) + { + _clientState = HANDLED; + #ifdef DEBUG + Serial.println("Client timed out !!!"); + #endif + } + parseQuery(&_wifiClient); + break; + case QUERY_PARSED: + _clientState = RESPONSE_SENT; + break; + case RESPONSE_SENT: + #ifdef DEBUG + Serial.println("Client handled !!!"); + #endif + _wifiClient.print(F("HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n\r\n\r\n

Response !!!

")); + + _clientState = HANDLED; + break; + case HANDLED: + _wifiClient.stopAll(); + _clientState = WAITING_FOR_CLIENT; + #ifdef DEBUG + Serial.println("Client discarded !!!"); + #endif + break; + default: + break; + } + return true; +} + +boolean WEBServerManager::parseQuery(WiFiClient *wifiClient) +{ + char readChar(0), *parseBuffer(NULL); + _httpParserState = INIT; + + while(wifiClient->available()) + { + 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) + { + case INIT: + if(readChar >= 65 && readChar <= 90) + { + 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; + } + + _clientState = QUERY_PARSED; + } + return true; +} + +unsigned int WEBServerManager::getPort() const +{ + return _port; +} + +char *WEBServerManager::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; +} + +WEBServerManager::HttpRequestMethod WEBServerManager::getHttpVerbEnumValue(const char *parseBuffer) +{ + //UNDEFINED, GET, HEAD, POST, PUT, DELETE, CONNECT, OPTIONS, TRACE, PATCH + if(strcmp(parseBuffer,"GET") == 0){return GET;} + else if(strcmp(parseBuffer,"POST") == 0){return POST;} + else if(strcmp(parseBuffer,"HEAD") == 0){return HEAD;} + else if(strcmp(parseBuffer,"PUT") == 0){return PUT;} + else if(strcmp(parseBuffer,"DELETE") == 0){return DELETE;} + else if(strcmp(parseBuffer,"CONNECT") == 0){return CONNECT;} + else if(strcmp(parseBuffer,"TRACE") == 0){return TRACE;} + else if(strcmp(parseBuffer,"PATCH") == 0){return PATCH;} + else if(strcmp(parseBuffer,"OPTIONS") == 0){return OPTIONS;} + else + return UNDEFINED; +} + +WEBServerManager::HttpVersion WEBServerManager::getHttpVersionEnumValue(const char *parseBuffer) +{ + //HTTP_0_9, HTTP_1_1, HTTP_1_0, HTTP_2_0 + if(strcmp(parseBuffer,"1.1") == 0){return HTTP_1_1;} + else if(strcmp(parseBuffer,"2.0") == 0){return HTTP_2_0;} + else if(strcmp(parseBuffer,"1.0") == 0){return HTTP_1_0;} + else if(strcmp(parseBuffer,"0.9") == 0){return HTTP_0_9;} + else + return UNKNOWN; +} + diff --git a/src/app/WEBServerManager.h b/src/app/WEBServerManager.h new file mode 100644 index 0000000..eb15056 --- /dev/null +++ b/src/app/WEBServerManager.h @@ -0,0 +1,46 @@ +#ifndef WEBSERVERMANAGER_H +#define WEBSERVERMANAGER_H + +#include +#include +#include "SDCardManager.h" +#include "definition.h" + +class WEBServerManager +{ + public: + WEBServerManager(unsigned int port = 80, SDCardManager *sdCardManager = NULL); + + boolean runServer(); + unsigned int getPort() const; + protected: + private: + 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}; + + struct HttpRequestData{ + HttpRequestMethod HRM; + HttpVersion HV; + char *httpResource; + char *httpBody; + }; + boolean parseQuery(WiFiClient *wifiClient); + char *addChar(char *pointer, const char character); + HttpRequestMethod getHttpVerbEnumValue(const char *parseBuffer); + HttpVersion getHttpVersionEnumValue(const char *parseBuffer); + + WiFiServer _wifiServer; + WiFiClient _wifiClient;//One client only, maybe replaced with a fifo in the future + SDCardManager *_sdCardManager; + + HttpRequestData _httpRequestData; + + ClientStatus _clientState; + HttpParserStatus _httpParserState; + unsigned long _clientTimeout; + unsigned int _port; +}; + +#endif //WEBSERVERMANAGER_H