-#endif
-#include "ESPAsyncWebServer.h"
-
-DNSServer dnsServer;
-AsyncWebServer server(80);
-
-class CaptiveRequestHandler : public AsyncWebHandler {
-public:
- CaptiveRequestHandler() {}
- virtual ~CaptiveRequestHandler() {}
-
- bool canHandle(AsyncWebServerRequest *request){
- //request->addInterestingHeader("ANY");
- return true;
- }
-
- void handleRequest(AsyncWebServerRequest *request) {
- AsyncResponseStream *response = request->beginResponseStream("text/html");
- response->print("Captive Portal");
- response->print("This is out captive portal front page.
");
- response->printf("You were trying to reach: http://%s%s
", request->host().c_str(), request->url().c_str());
- response->printf("Try opening this link instead
", WiFi.softAPIP().toString().c_str());
- response->print("");
- request->send(response);
- }
-};
-
-
-void setup(){
- //your other setup stuff...
- WiFi.softAP("esp-captive");
- dnsServer.start(53, "*", WiFi.softAPIP());
- server.addHandler(new CaptiveRequestHandler()).setFilter(ON_AP_FILTER);//only when requested from AP
- //more handlers...
- server.begin();
-}
-
-void loop(){
- dnsServer.processNextRequest();
-}
diff --git a/ESP32/lib/ESPAsyncWebServer/examples/ESP_AsyncFSBrowser/ESP_AsyncFSBrowser.ino b/ESP32/lib/ESPAsyncWebServer/examples/ESP_AsyncFSBrowser/ESP_AsyncFSBrowser.ino
deleted file mode 100644
index bf42d00..0000000
--- a/ESP32/lib/ESPAsyncWebServer/examples/ESP_AsyncFSBrowser/ESP_AsyncFSBrowser.ino
+++ /dev/null
@@ -1,221 +0,0 @@
-#include
-#ifdef ESP32
-#include
-#include
-#include
-#include
-#include
-#elif defined(ESP8266)
-#include
-#include
-#include
-#endif
-#include
-#include
-
-// SKETCH BEGIN
-AsyncWebServer server(80);
-AsyncWebSocket ws("/ws");
-AsyncEventSource events("/events");
-
-void onWsEvent(AsyncWebSocket * server, AsyncWebSocketClient * client, AwsEventType type, void * arg, uint8_t *data, size_t len){
- if(type == WS_EVT_CONNECT){
- Serial.printf("ws[%s][%u] connect\n", server->url(), client->id());
- client->printf("Hello Client %u :)", client->id());
- client->ping();
- } else if(type == WS_EVT_DISCONNECT){
- Serial.printf("ws[%s][%u] disconnect\n", server->url(), client->id());
- } else if(type == WS_EVT_ERROR){
- Serial.printf("ws[%s][%u] error(%u): %s\n", server->url(), client->id(), *((uint16_t*)arg), (char*)data);
- } else if(type == WS_EVT_PONG){
- Serial.printf("ws[%s][%u] pong[%u]: %s\n", server->url(), client->id(), len, (len)?(char*)data:"");
- } else if(type == WS_EVT_DATA){
- AwsFrameInfo * info = (AwsFrameInfo*)arg;
- String msg = "";
- if(info->final && info->index == 0 && info->len == len){
- //the whole message is in a single frame and we got all of it's data
- Serial.printf("ws[%s][%u] %s-message[%llu]: ", server->url(), client->id(), (info->opcode == WS_TEXT)?"text":"binary", info->len);
-
- if(info->opcode == WS_TEXT){
- for(size_t i=0; i < info->len; i++) {
- msg += (char) data[i];
- }
- } else {
- char buff[3];
- for(size_t i=0; i < info->len; i++) {
- sprintf(buff, "%02x ", (uint8_t) data[i]);
- msg += buff ;
- }
- }
- Serial.printf("%s\n",msg.c_str());
-
- if(info->opcode == WS_TEXT)
- client->text("I got your text message");
- else
- client->binary("I got your binary message");
- } else {
- //message is comprised of multiple frames or the frame is split into multiple packets
- if(info->index == 0){
- if(info->num == 0)
- Serial.printf("ws[%s][%u] %s-message start\n", server->url(), client->id(), (info->message_opcode == WS_TEXT)?"text":"binary");
- Serial.printf("ws[%s][%u] frame[%u] start[%llu]\n", server->url(), client->id(), info->num, info->len);
- }
-
- Serial.printf("ws[%s][%u] frame[%u] %s[%llu - %llu]: ", server->url(), client->id(), info->num, (info->message_opcode == WS_TEXT)?"text":"binary", info->index, info->index + len);
-
- if(info->opcode == WS_TEXT){
- for(size_t i=0; i < len; i++) {
- msg += (char) data[i];
- }
- } else {
- char buff[3];
- for(size_t i=0; i < len; i++) {
- sprintf(buff, "%02x ", (uint8_t) data[i]);
- msg += buff ;
- }
- }
- Serial.printf("%s\n",msg.c_str());
-
- if((info->index + len) == info->len){
- Serial.printf("ws[%s][%u] frame[%u] end[%llu]\n", server->url(), client->id(), info->num, info->len);
- if(info->final){
- Serial.printf("ws[%s][%u] %s-message end\n", server->url(), client->id(), (info->message_opcode == WS_TEXT)?"text":"binary");
- if(info->message_opcode == WS_TEXT)
- client->text("I got your text message");
- else
- client->binary("I got your binary message");
- }
- }
- }
- }
-}
-
-
-const char* ssid = "*******";
-const char* password = "*******";
-const char * hostName = "esp-async";
-const char* http_username = "admin";
-const char* http_password = "admin";
-
-void setup(){
- Serial.begin(115200);
- Serial.setDebugOutput(true);
- WiFi.mode(WIFI_AP_STA);
- WiFi.softAP(hostName);
- WiFi.begin(ssid, password);
- if (WiFi.waitForConnectResult() != WL_CONNECTED) {
- Serial.printf("STA: Failed!\n");
- WiFi.disconnect(false);
- delay(1000);
- WiFi.begin(ssid, password);
- }
-
- //Send OTA events to the browser
- ArduinoOTA.onStart([]() { events.send("Update Start", "ota"); });
- ArduinoOTA.onEnd([]() { events.send("Update End", "ota"); });
- ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
- char p[32];
- sprintf(p, "Progress: %u%%\n", (progress/(total/100)));
- events.send(p, "ota");
- });
- ArduinoOTA.onError([](ota_error_t error) {
- if(error == OTA_AUTH_ERROR) events.send("Auth Failed", "ota");
- else if(error == OTA_BEGIN_ERROR) events.send("Begin Failed", "ota");
- else if(error == OTA_CONNECT_ERROR) events.send("Connect Failed", "ota");
- else if(error == OTA_RECEIVE_ERROR) events.send("Recieve Failed", "ota");
- else if(error == OTA_END_ERROR) events.send("End Failed", "ota");
- });
- ArduinoOTA.setHostname(hostName);
- ArduinoOTA.begin();
-
- MDNS.addService("http","tcp",80);
-
- SPIFFS.begin();
-
- ws.onEvent(onWsEvent);
- server.addHandler(&ws);
-
- events.onConnect([](AsyncEventSourceClient *client){
- client->send("hello!",NULL,millis(),1000);
- });
- server.addHandler(&events);
-
-#ifdef ESP32
- server.addHandler(new SPIFFSEditor(SPIFFS, http_username,http_password));
-#elif defined(ESP8266)
- server.addHandler(new SPIFFSEditor(http_username,http_password));
-#endif
-
- server.on("/heap", HTTP_GET, [](AsyncWebServerRequest *request){
- request->send(200, "text/plain", String(ESP.getFreeHeap()));
- });
-
- server.serveStatic("/", SPIFFS, "/").setDefaultFile("index.htm");
-
- server.onNotFound([](AsyncWebServerRequest *request){
- Serial.printf("NOT_FOUND: ");
- if(request->method() == HTTP_GET)
- Serial.printf("GET");
- else if(request->method() == HTTP_POST)
- Serial.printf("POST");
- else if(request->method() == HTTP_DELETE)
- Serial.printf("DELETE");
- else if(request->method() == HTTP_PUT)
- Serial.printf("PUT");
- else if(request->method() == HTTP_PATCH)
- Serial.printf("PATCH");
- else if(request->method() == HTTP_HEAD)
- Serial.printf("HEAD");
- else if(request->method() == HTTP_OPTIONS)
- Serial.printf("OPTIONS");
- else
- Serial.printf("UNKNOWN");
- Serial.printf(" http://%s%s\n", request->host().c_str(), request->url().c_str());
-
- if(request->contentLength()){
- Serial.printf("_CONTENT_TYPE: %s\n", request->contentType().c_str());
- Serial.printf("_CONTENT_LENGTH: %u\n", request->contentLength());
- }
-
- int headers = request->headers();
- int i;
- for(i=0;igetHeader(i);
- Serial.printf("_HEADER[%s]: %s\n", h->name().c_str(), h->value().c_str());
- }
-
- int params = request->params();
- for(i=0;igetParam(i);
- if(p->isFile()){
- Serial.printf("_FILE[%s]: %s, size: %u\n", p->name().c_str(), p->value().c_str(), p->size());
- } else if(p->isPost()){
- Serial.printf("_POST[%s]: %s\n", p->name().c_str(), p->value().c_str());
- } else {
- Serial.printf("_GET[%s]: %s\n", p->name().c_str(), p->value().c_str());
- }
- }
-
- request->send(404);
- });
- server.onFileUpload([](AsyncWebServerRequest *request, const String& filename, size_t index, uint8_t *data, size_t len, bool final){
- if(!index)
- Serial.printf("UploadStart: %s\n", filename.c_str());
- Serial.printf("%s", (const char*)data);
- if(final)
- Serial.printf("UploadEnd: %s (%u)\n", filename.c_str(), index+len);
- });
- server.onRequestBody([](AsyncWebServerRequest *request, uint8_t *data, size_t len, size_t index, size_t total){
- if(!index)
- Serial.printf("BodyStart: %u\n", total);
- Serial.printf("%s", (const char*)data);
- if(index + len == total)
- Serial.printf("BodyEnd: %u\n", total);
- });
- server.begin();
-}
-
-void loop(){
- ArduinoOTA.handle();
- ws.cleanupClients();
-}
diff --git a/ESP32/lib/ESPAsyncWebServer/examples/ESP_AsyncFSBrowser/data/.exclude.files b/ESP32/lib/ESPAsyncWebServer/examples/ESP_AsyncFSBrowser/data/.exclude.files
deleted file mode 100644
index 955397f..0000000
--- a/ESP32/lib/ESPAsyncWebServer/examples/ESP_AsyncFSBrowser/data/.exclude.files
+++ /dev/null
@@ -1,2 +0,0 @@
-/*.js.gz
-/.exclude.files
diff --git a/ESP32/lib/ESPAsyncWebServer/examples/ESP_AsyncFSBrowser/data/ace.js.gz b/ESP32/lib/ESPAsyncWebServer/examples/ESP_AsyncFSBrowser/data/ace.js.gz
deleted file mode 100644
index 7b175c1..0000000
Binary files a/ESP32/lib/ESPAsyncWebServer/examples/ESP_AsyncFSBrowser/data/ace.js.gz and /dev/null differ
diff --git a/ESP32/lib/ESPAsyncWebServer/examples/ESP_AsyncFSBrowser/data/ext-searchbox.js.gz b/ESP32/lib/ESPAsyncWebServer/examples/ESP_AsyncFSBrowser/data/ext-searchbox.js.gz
deleted file mode 100644
index cf5b49f..0000000
Binary files a/ESP32/lib/ESPAsyncWebServer/examples/ESP_AsyncFSBrowser/data/ext-searchbox.js.gz and /dev/null differ
diff --git a/ESP32/lib/ESPAsyncWebServer/examples/ESP_AsyncFSBrowser/data/favicon.ico b/ESP32/lib/ESPAsyncWebServer/examples/ESP_AsyncFSBrowser/data/favicon.ico
deleted file mode 100644
index 71b25fe..0000000
Binary files a/ESP32/lib/ESPAsyncWebServer/examples/ESP_AsyncFSBrowser/data/favicon.ico and /dev/null differ
diff --git a/ESP32/lib/ESPAsyncWebServer/examples/ESP_AsyncFSBrowser/data/index.htm b/ESP32/lib/ESPAsyncWebServer/examples/ESP_AsyncFSBrowser/data/index.htm
deleted file mode 100644
index 28f47e9..0000000
--- a/ESP32/lib/ESPAsyncWebServer/examples/ESP_AsyncFSBrowser/data/index.htm
+++ /dev/null
@@ -1,131 +0,0 @@
-
-
-
-
-
- WebSocketTester
-
-
-
-
-
-
- $
-
-
-
diff --git a/ESP32/lib/ESPAsyncWebServer/examples/ESP_AsyncFSBrowser/data/mode-css.js.gz b/ESP32/lib/ESPAsyncWebServer/examples/ESP_AsyncFSBrowser/data/mode-css.js.gz
deleted file mode 100644
index ebd6fe9..0000000
Binary files a/ESP32/lib/ESPAsyncWebServer/examples/ESP_AsyncFSBrowser/data/mode-css.js.gz and /dev/null differ
diff --git a/ESP32/lib/ESPAsyncWebServer/examples/ESP_AsyncFSBrowser/data/mode-html.js.gz b/ESP32/lib/ESPAsyncWebServer/examples/ESP_AsyncFSBrowser/data/mode-html.js.gz
deleted file mode 100644
index 26b5353..0000000
Binary files a/ESP32/lib/ESPAsyncWebServer/examples/ESP_AsyncFSBrowser/data/mode-html.js.gz and /dev/null differ
diff --git a/ESP32/lib/ESPAsyncWebServer/examples/ESP_AsyncFSBrowser/data/mode-javascript.js.gz b/ESP32/lib/ESPAsyncWebServer/examples/ESP_AsyncFSBrowser/data/mode-javascript.js.gz
deleted file mode 100644
index c0451c1..0000000
Binary files a/ESP32/lib/ESPAsyncWebServer/examples/ESP_AsyncFSBrowser/data/mode-javascript.js.gz and /dev/null differ
diff --git a/ESP32/lib/ESPAsyncWebServer/examples/ESP_AsyncFSBrowser/data/worker-html.js.gz b/ESP32/lib/ESPAsyncWebServer/examples/ESP_AsyncFSBrowser/data/worker-html.js.gz
deleted file mode 100644
index ec8aa87..0000000
Binary files a/ESP32/lib/ESPAsyncWebServer/examples/ESP_AsyncFSBrowser/data/worker-html.js.gz and /dev/null differ
diff --git a/ESP32/lib/ESPAsyncWebServer/examples/regex_patterns/.test.build_flags b/ESP32/lib/ESPAsyncWebServer/examples/regex_patterns/.test.build_flags
deleted file mode 100644
index 9ea3bb7..0000000
--- a/ESP32/lib/ESPAsyncWebServer/examples/regex_patterns/.test.build_flags
+++ /dev/null
@@ -1 +0,0 @@
--DASYNCWEBSERVER_REGEX=1
diff --git a/ESP32/lib/ESPAsyncWebServer/examples/regex_patterns/regex_patterns.ino b/ESP32/lib/ESPAsyncWebServer/examples/regex_patterns/regex_patterns.ino
deleted file mode 100644
index fb01306..0000000
--- a/ESP32/lib/ESPAsyncWebServer/examples/regex_patterns/regex_patterns.ino
+++ /dev/null
@@ -1,77 +0,0 @@
-//
-// A simple server implementation with regex routes:
-// * serve static messages
-// * read GET and POST parameters
-// * handle missing pages / 404s
-//
-
-// Add buildflag ASYNCWEBSERVER_REGEX to enable the regex support
-
-// For platformio: platformio.ini:
-// build_flags =
-// -DASYNCWEBSERVER_REGEX
-
-// For arduino IDE: create/update platform.local.txt
-// Windows: C:\Users\(username)\AppData\Local\Arduino15\packages\espxxxx\hardware\espxxxx\{version}\platform.local.txt
-// Linux: ~/.arduino15/packages/espxxxx/hardware/espxxxx/{version}/platform.local.txt
-//
-// compiler.cpp.extra_flags=-DASYNCWEBSERVER_REGEX=1
-
-#include
-#ifdef ESP32
-#include
-#include
-#elif defined(ESP8266)
-#include
-#include
-#endif
-#include
-
-AsyncWebServer server(80);
-
-const char* ssid = "YOUR_SSID";
-const char* password = "YOUR_PASSWORD";
-
-const char* PARAM_MESSAGE = "message";
-
-void notFound(AsyncWebServerRequest *request) {
- request->send(404, "text/plain", "Not found");
-}
-
-void setup() {
-
- Serial.begin(115200);
- WiFi.mode(WIFI_STA);
- WiFi.begin(ssid, password);
- if (WiFi.waitForConnectResult() != WL_CONNECTED) {
- Serial.printf("WiFi Failed!\n");
- return;
- }
-
- Serial.print("IP Address: ");
- Serial.println(WiFi.localIP());
-
- server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
- request->send(200, "text/plain", "Hello, world");
- });
-
- // Send a GET request to /sensor/
- server.on("^\\/sensor\\/([0-9]+)$", HTTP_GET, [] (AsyncWebServerRequest *request) {
- String sensorNumber = request->pathArg(0);
- request->send(200, "text/plain", "Hello, sensor: " + sensorNumber);
- });
-
- // Send a GET request to /sensor//action/
- server.on("^\\/sensor\\/([0-9]+)\\/action\\/([a-zA-Z0-9]+)$", HTTP_GET, [] (AsyncWebServerRequest *request) {
- String sensorNumber = request->pathArg(0);
- String action = request->pathArg(1);
- request->send(200, "text/plain", "Hello, sensor: " + sensorNumber + ", with action: " + action);
- });
-
- server.onNotFound(notFound);
-
- server.begin();
-}
-
-void loop() {
-}
diff --git a/ESP32/lib/ESPAsyncWebServer/examples/simple_server/simple_server.ino b/ESP32/lib/ESPAsyncWebServer/examples/simple_server/simple_server.ino
deleted file mode 100644
index bdbcf60..0000000
--- a/ESP32/lib/ESPAsyncWebServer/examples/simple_server/simple_server.ino
+++ /dev/null
@@ -1,74 +0,0 @@
-//
-// A simple server implementation showing how to:
-// * serve static messages
-// * read GET and POST parameters
-// * handle missing pages / 404s
-//
-
-#include
-#ifdef ESP32
-#include
-#include
-#elif defined(ESP8266)
-#include
-#include
-#endif
-#include
-
-AsyncWebServer server(80);
-
-const char* ssid = "YOUR_SSID";
-const char* password = "YOUR_PASSWORD";
-
-const char* PARAM_MESSAGE = "message";
-
-void notFound(AsyncWebServerRequest *request) {
- request->send(404, "text/plain", "Not found");
-}
-
-void setup() {
-
- Serial.begin(115200);
- WiFi.mode(WIFI_STA);
- WiFi.begin(ssid, password);
- if (WiFi.waitForConnectResult() != WL_CONNECTED) {
- Serial.printf("WiFi Failed!\n");
- return;
- }
-
- Serial.print("IP Address: ");
- Serial.println(WiFi.localIP());
-
- server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
- request->send(200, "text/plain", "Hello, world");
- });
-
- // Send a GET request to /get?message=
- server.on("/get", HTTP_GET, [] (AsyncWebServerRequest *request) {
- String message;
- if (request->hasParam(PARAM_MESSAGE)) {
- message = request->getParam(PARAM_MESSAGE)->value();
- } else {
- message = "No message sent";
- }
- request->send(200, "text/plain", "Hello, GET: " + message);
- });
-
- // Send a POST request to /post with a form field message set to
- server.on("/post", HTTP_POST, [](AsyncWebServerRequest *request){
- String message;
- if (request->hasParam(PARAM_MESSAGE, true)) {
- message = request->getParam(PARAM_MESSAGE, true)->value();
- } else {
- message = "No message sent";
- }
- request->send(200, "text/plain", "Hello, POST: " + message);
- });
-
- server.onNotFound(notFound);
-
- server.begin();
-}
-
-void loop() {
-}
\ No newline at end of file
diff --git a/ESP32/lib/ESPAsyncWebServer/keywords.txt b/ESP32/lib/ESPAsyncWebServer/keywords.txt
deleted file mode 100755
index c391e6c..0000000
--- a/ESP32/lib/ESPAsyncWebServer/keywords.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-JsonArray KEYWORD1
-add KEYWORD2
-createArray KEYWORD3
diff --git a/ESP32/lib/ESPAsyncWebServer/library.json b/ESP32/lib/ESPAsyncWebServer/library.json
deleted file mode 100644
index 5565927..0000000
--- a/ESP32/lib/ESPAsyncWebServer/library.json
+++ /dev/null
@@ -1,33 +0,0 @@
-{
- "name":"ESP Async WebServer",
- "description":"Asynchronous HTTP and WebSocket Server Library for ESP8266 and ESP32",
- "keywords":"http,async,websocket,webserver",
- "authors":
- {
- "name": "Hristo Gochkov",
- "maintainer": true
- },
- "repository":
- {
- "type": "git",
- "url": "https://github.com/me-no-dev/ESPAsyncWebServer.git"
- },
- "version": "1.2.3",
- "license": "LGPL-3.0",
- "frameworks": "arduino",
- "platforms": ["espressif8266", "espressif32"],
- "dependencies": [
- {
- "name": "ESPAsyncTCP",
- "platforms": "espressif8266"
- },
- {
- "name": "AsyncTCP",
- "platforms": "espressif32"
- },
- {
- "name": "Hash",
- "platforms": "espressif8266"
- }
- ]
-}
diff --git a/ESP32/lib/ESPAsyncWebServer/library.properties b/ESP32/lib/ESPAsyncWebServer/library.properties
deleted file mode 100644
index 401b041..0000000
--- a/ESP32/lib/ESPAsyncWebServer/library.properties
+++ /dev/null
@@ -1,9 +0,0 @@
-name=ESP Async WebServer
-version=1.2.3
-author=Me-No-Dev
-maintainer=Me-No-Dev
-sentence=Async Web Server for ESP8266 and ESP31B
-paragraph=Async Web Server for ESP8266 and ESP31B
-category=Other
-url=https://github.com/me-no-dev/ESPAsyncWebServer
-architectures=*
diff --git a/ESP32/lib/ESPAsyncWebServer/src/AsyncEventSource.cpp b/ESP32/lib/ESPAsyncWebServer/src/AsyncEventSource.cpp
deleted file mode 100644
index f2914df..0000000
--- a/ESP32/lib/ESPAsyncWebServer/src/AsyncEventSource.cpp
+++ /dev/null
@@ -1,368 +0,0 @@
-/*
- Asynchronous WebServer library for Espressif MCUs
-
- Copyright (c) 2016 Hristo Gochkov. All rights reserved.
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-*/
-#include "Arduino.h"
-#include "AsyncEventSource.h"
-
-static String generateEventMessage(const char *message, const char *event, uint32_t id, uint32_t reconnect){
- String ev = "";
-
- if(reconnect){
- ev += "retry: ";
- ev += String(reconnect);
- ev += "\r\n";
- }
-
- if(id){
- ev += "id: ";
- ev += String(id);
- ev += "\r\n";
- }
-
- if(event != NULL){
- ev += "event: ";
- ev += String(event);
- ev += "\r\n";
- }
-
- if(message != NULL){
- size_t messageLen = strlen(message);
- char * lineStart = (char *)message;
- char * lineEnd;
- do {
- char * nextN = strchr(lineStart, '\n');
- char * nextR = strchr(lineStart, '\r');
- if(nextN == NULL && nextR == NULL){
- size_t llen = ((char *)message + messageLen) - lineStart;
- char * ldata = (char *)malloc(llen+1);
- if(ldata != NULL){
- memcpy(ldata, lineStart, llen);
- ldata[llen] = 0;
- ev += "data: ";
- ev += ldata;
- ev += "\r\n\r\n";
- free(ldata);
- }
- lineStart = (char *)message + messageLen;
- } else {
- char * nextLine = NULL;
- if(nextN != NULL && nextR != NULL){
- if(nextR < nextN){
- lineEnd = nextR;
- if(nextN == (nextR + 1))
- nextLine = nextN + 1;
- else
- nextLine = nextR + 1;
- } else {
- lineEnd = nextN;
- if(nextR == (nextN + 1))
- nextLine = nextR + 1;
- else
- nextLine = nextN + 1;
- }
- } else if(nextN != NULL){
- lineEnd = nextN;
- nextLine = nextN + 1;
- } else {
- lineEnd = nextR;
- nextLine = nextR + 1;
- }
-
- size_t llen = lineEnd - lineStart;
- char * ldata = (char *)malloc(llen+1);
- if(ldata != NULL){
- memcpy(ldata, lineStart, llen);
- ldata[llen] = 0;
- ev += "data: ";
- ev += ldata;
- ev += "\r\n";
- free(ldata);
- }
- lineStart = nextLine;
- if(lineStart == ((char *)message + messageLen))
- ev += "\r\n";
- }
- } while(lineStart < ((char *)message + messageLen));
- }
-
- return ev;
-}
-
-// Message
-
-AsyncEventSourceMessage::AsyncEventSourceMessage(const char * data, size_t len)
-: _data(nullptr), _len(len), _sent(0), _acked(0)
-{
- _data = (uint8_t*)malloc(_len+1);
- if(_data == nullptr){
- _len = 0;
- } else {
- memcpy(_data, data, len);
- _data[_len] = 0;
- }
-}
-
-AsyncEventSourceMessage::~AsyncEventSourceMessage() {
- if(_data != NULL)
- free(_data);
-}
-
-size_t AsyncEventSourceMessage::ack(size_t len, uint32_t time) {
- (void)time;
- // If the whole message is now acked...
- if(_acked + len > _len){
- // Return the number of extra bytes acked (they will be carried on to the next message)
- const size_t extra = _acked + len - _len;
- _acked = _len;
- return extra;
- }
- // Return that no extra bytes left.
- _acked += len;
- return 0;
-}
-
-size_t AsyncEventSourceMessage::send(AsyncClient *client) {
- const size_t len = _len - _sent;
- if(client->space() < len){
- return 0;
- }
- size_t sent = client->add((const char *)_data, len);
- if(client->canSend())
- client->send();
- _sent += sent;
- return sent;
-}
-
-// Client
-
-AsyncEventSourceClient::AsyncEventSourceClient(AsyncWebServerRequest *request, AsyncEventSource *server)
-: _messageQueue(LinkedList([](AsyncEventSourceMessage *m){ delete m; }))
-{
- _client = request->client();
- _server = server;
- _lastId = 0;
- if(request->hasHeader("Last-Event-ID"))
- _lastId = atoi(request->getHeader("Last-Event-ID")->value().c_str());
-
- _client->setRxTimeout(0);
- _client->onError(NULL, NULL);
- _client->onAck([](void *r, AsyncClient* c, size_t len, uint32_t time){ (void)c; ((AsyncEventSourceClient*)(r))->_onAck(len, time); }, this);
- _client->onPoll([](void *r, AsyncClient* c){ (void)c; ((AsyncEventSourceClient*)(r))->_onPoll(); }, this);
- _client->onData(NULL, NULL);
- _client->onTimeout([this](void *r, AsyncClient* c __attribute__((unused)), uint32_t time){ ((AsyncEventSourceClient*)(r))->_onTimeout(time); }, this);
- _client->onDisconnect([this](void *r, AsyncClient* c){ ((AsyncEventSourceClient*)(r))->_onDisconnect(); delete c; }, this);
-
- _server->_addClient(this);
- delete request;
-}
-
-AsyncEventSourceClient::~AsyncEventSourceClient(){
- _messageQueue.free();
- close();
-}
-
-void AsyncEventSourceClient::_queueMessage(AsyncEventSourceMessage *dataMessage){
- if(dataMessage == NULL)
- return;
- if(!connected()){
- delete dataMessage;
- return;
- }
- if(_messageQueue.length() >= SSE_MAX_QUEUED_MESSAGES){
- ets_printf("ERROR: Too many messages queued\n");
- delete dataMessage;
- } else {
- _messageQueue.add(dataMessage);
- }
- if(_client->canSend())
- _runQueue();
-}
-
-void AsyncEventSourceClient::_onAck(size_t len, uint32_t time){
- while(len && !_messageQueue.isEmpty()){
- len = _messageQueue.front()->ack(len, time);
- if(_messageQueue.front()->finished())
- _messageQueue.remove(_messageQueue.front());
- }
-
- _runQueue();
-}
-
-void AsyncEventSourceClient::_onPoll(){
- if(!_messageQueue.isEmpty()){
- _runQueue();
- }
-}
-
-
-void AsyncEventSourceClient::_onTimeout(uint32_t time __attribute__((unused))){
- _client->close(true);
-}
-
-void AsyncEventSourceClient::_onDisconnect(){
- _client = NULL;
- _server->_handleDisconnect(this);
-}
-
-void AsyncEventSourceClient::close(){
- if(_client != NULL)
- _client->close();
-}
-
-void AsyncEventSourceClient::write(const char * message, size_t len){
- _queueMessage(new AsyncEventSourceMessage(message, len));
-}
-
-void AsyncEventSourceClient::send(const char *message, const char *event, uint32_t id, uint32_t reconnect){
- String ev = generateEventMessage(message, event, id, reconnect);
- _queueMessage(new AsyncEventSourceMessage(ev.c_str(), ev.length()));
-}
-
-void AsyncEventSourceClient::_runQueue(){
- while(!_messageQueue.isEmpty() && _messageQueue.front()->finished()){
- _messageQueue.remove(_messageQueue.front());
- }
-
- for(auto i = _messageQueue.begin(); i != _messageQueue.end(); ++i)
- {
- if(!(*i)->sent())
- (*i)->send(_client);
- }
-}
-
-
-// Handler
-
-AsyncEventSource::AsyncEventSource(const String& url)
- : _url(url)
- , _clients(LinkedList([](AsyncEventSourceClient *c){ delete c; }))
- , _connectcb(NULL)
-{}
-
-AsyncEventSource::~AsyncEventSource(){
- close();
-}
-
-void AsyncEventSource::onConnect(ArEventHandlerFunction cb){
- _connectcb = cb;
-}
-
-void AsyncEventSource::_addClient(AsyncEventSourceClient * client){
- /*char * temp = (char *)malloc(2054);
- if(temp != NULL){
- memset(temp+1,' ',2048);
- temp[0] = ':';
- temp[2049] = '\r';
- temp[2050] = '\n';
- temp[2051] = '\r';
- temp[2052] = '\n';
- temp[2053] = 0;
- client->write((const char *)temp, 2053);
- free(temp);
- }*/
-
- _clients.add(client);
- if(_connectcb)
- _connectcb(client);
-}
-
-void AsyncEventSource::_handleDisconnect(AsyncEventSourceClient * client){
- _clients.remove(client);
-}
-
-void AsyncEventSource::close(){
- for(const auto &c: _clients){
- if(c->connected())
- c->close();
- }
-}
-
-// pmb fix
-size_t AsyncEventSource::avgPacketsWaiting() const {
- if(_clients.isEmpty())
- return 0;
-
- size_t aql=0;
- uint32_t nConnectedClients=0;
-
- for(const auto &c: _clients){
- if(c->connected()) {
- aql+=c->packetsWaiting();
- ++nConnectedClients;
- }
- }
-// return aql / nConnectedClients;
- return ((aql) + (nConnectedClients/2))/(nConnectedClients); // round up
-}
-
-void AsyncEventSource::send(const char *message, const char *event, uint32_t id, uint32_t reconnect){
-
-
- String ev = generateEventMessage(message, event, id, reconnect);
- for(const auto &c: _clients){
- if(c->connected()) {
- c->write(ev.c_str(), ev.length());
- }
- }
-}
-
-size_t AsyncEventSource::count() const {
- return _clients.count_if([](AsyncEventSourceClient *c){
- return c->connected();
- });
-}
-
-bool AsyncEventSource::canHandle(AsyncWebServerRequest *request){
- if(request->method() != HTTP_GET || !request->url().equals(_url)) {
- return false;
- }
- request->addInterestingHeader("Last-Event-ID");
- return true;
-}
-
-void AsyncEventSource::handleRequest(AsyncWebServerRequest *request){
- if((_username != "" && _password != "") && !request->authenticate(_username.c_str(), _password.c_str()))
- return request->requestAuthentication();
- request->send(new AsyncEventSourceResponse(this));
-}
-
-// Response
-
-AsyncEventSourceResponse::AsyncEventSourceResponse(AsyncEventSource *server){
- _server = server;
- _code = 200;
- _contentType = "text/event-stream";
- _sendContentLength = false;
- addHeader("Cache-Control", "no-cache");
- addHeader("Connection","keep-alive");
-}
-
-void AsyncEventSourceResponse::_respond(AsyncWebServerRequest *request){
- String out = _assembleHead(request->version());
- request->client()->write(out.c_str(), _headLength);
- _state = RESPONSE_WAIT_ACK;
-}
-
-size_t AsyncEventSourceResponse::_ack(AsyncWebServerRequest *request, size_t len, uint32_t time __attribute__((unused))){
- if(len){
- new AsyncEventSourceClient(request, _server);
- }
- return 0;
-}
-
diff --git a/ESP32/lib/ESPAsyncWebServer/src/AsyncEventSource.h b/ESP32/lib/ESPAsyncWebServer/src/AsyncEventSource.h
deleted file mode 100644
index b097fa6..0000000
--- a/ESP32/lib/ESPAsyncWebServer/src/AsyncEventSource.h
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- Asynchronous WebServer library for Espressif MCUs
-
- Copyright (c) 2016 Hristo Gochkov. All rights reserved.
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-*/
-#ifndef ASYNCEVENTSOURCE_H_
-#define ASYNCEVENTSOURCE_H_
-
-#include
-#ifdef ESP32
-#include
-#define SSE_MAX_QUEUED_MESSAGES 32
-#else
-#include
-#define SSE_MAX_QUEUED_MESSAGES 8
-#endif
-#include
-
-#include "AsyncWebSynchronization.h"
-
-#ifdef ESP8266
-#include
-#ifdef CRYPTO_HASH_h // include Hash.h from espressif framework if the first include was from the crypto library
-#include <../src/Hash.h>
-#endif
-#endif
-
-#ifdef ESP32
-#define DEFAULT_MAX_SSE_CLIENTS 8
-#else
-#define DEFAULT_MAX_SSE_CLIENTS 4
-#endif
-
-class AsyncEventSource;
-class AsyncEventSourceResponse;
-class AsyncEventSourceClient;
-typedef std::function ArEventHandlerFunction;
-
-class AsyncEventSourceMessage {
- private:
- uint8_t * _data;
- size_t _len;
- size_t _sent;
- //size_t _ack;
- size_t _acked;
- public:
- AsyncEventSourceMessage(const char * data, size_t len);
- ~AsyncEventSourceMessage();
- size_t ack(size_t len, uint32_t time __attribute__((unused)));
- size_t send(AsyncClient *client);
- bool finished(){ return _acked == _len; }
- bool sent() { return _sent == _len; }
-};
-
-class AsyncEventSourceClient {
- private:
- AsyncClient *_client;
- AsyncEventSource *_server;
- uint32_t _lastId;
- LinkedList _messageQueue;
- void _queueMessage(AsyncEventSourceMessage *dataMessage);
- void _runQueue();
-
- public:
-
- AsyncEventSourceClient(AsyncWebServerRequest *request, AsyncEventSource *server);
- ~AsyncEventSourceClient();
-
- AsyncClient* client(){ return _client; }
- void close();
- void write(const char * message, size_t len);
- void send(const char *message, const char *event=NULL, uint32_t id=0, uint32_t reconnect=0);
- bool connected() const { return (_client != NULL) && _client->connected(); }
- uint32_t lastId() const { return _lastId; }
- size_t packetsWaiting() const { return _messageQueue.length(); }
-
- //system callbacks (do not call)
- void _onAck(size_t len, uint32_t time);
- void _onPoll();
- void _onTimeout(uint32_t time);
- void _onDisconnect();
-};
-
-class AsyncEventSource: public AsyncWebHandler {
- private:
- String _url;
- LinkedList _clients;
- ArEventHandlerFunction _connectcb;
- public:
- AsyncEventSource(const String& url);
- ~AsyncEventSource();
-
- const char * url() const { return _url.c_str(); }
- void close();
- void onConnect(ArEventHandlerFunction cb);
- void send(const char *message, const char *event=NULL, uint32_t id=0, uint32_t reconnect=0);
- size_t count() const; //number clinets connected
- size_t avgPacketsWaiting() const;
-
- //system callbacks (do not call)
- void _addClient(AsyncEventSourceClient * client);
- void _handleDisconnect(AsyncEventSourceClient * client);
- virtual bool canHandle(AsyncWebServerRequest *request) override final;
- virtual void handleRequest(AsyncWebServerRequest *request) override final;
-};
-
-class AsyncEventSourceResponse: public AsyncWebServerResponse {
- private:
- String _content;
- AsyncEventSource *_server;
- public:
- AsyncEventSourceResponse(AsyncEventSource *server);
- void _respond(AsyncWebServerRequest *request);
- size_t _ack(AsyncWebServerRequest *request, size_t len, uint32_t time);
- bool _sourceValid() const { return true; }
-};
-
-
-#endif /* ASYNCEVENTSOURCE_H_ */
diff --git a/ESP32/lib/ESPAsyncWebServer/src/AsyncJson.h b/ESP32/lib/ESPAsyncWebServer/src/AsyncJson.h
deleted file mode 100644
index 2fa6a2d..0000000
--- a/ESP32/lib/ESPAsyncWebServer/src/AsyncJson.h
+++ /dev/null
@@ -1,254 +0,0 @@
-// AsyncJson.h
-/*
- Async Response to use with ArduinoJson and AsyncWebServer
- Written by Andrew Melvin (SticilFace) with help from me-no-dev and BBlanchon.
-
- Example of callback in use
-
- server.on("/json", HTTP_ANY, [](AsyncWebServerRequest * request) {
-
- AsyncJsonResponse * response = new AsyncJsonResponse();
- JsonObject& root = response->getRoot();
- root["key1"] = "key number one";
- JsonObject& nested = root.createNestedObject("nested");
- nested["key1"] = "key number one";
-
- response->setLength();
- request->send(response);
- });
-
- --------------------
-
- Async Request to use with ArduinoJson and AsyncWebServer
- Written by Arsène von Wyss (avonwyss)
-
- Example
-
- AsyncCallbackJsonWebHandler* handler = new AsyncCallbackJsonWebHandler("/rest/endpoint");
- handler->onRequest([](AsyncWebServerRequest *request, JsonVariant &json) {
- JsonObject& jsonObj = json.as();
- // ...
- });
- server.addHandler(handler);
-
-*/
-#ifndef ASYNC_JSON_H_
-#define ASYNC_JSON_H_
-#include
-#include
-#include
-
-#if ARDUINOJSON_VERSION_MAJOR == 5
- #define ARDUINOJSON_5_COMPATIBILITY
-#else
- #ifndef DYNAMIC_JSON_DOCUMENT_SIZE
- #define DYNAMIC_JSON_DOCUMENT_SIZE 1024
- #endif
-#endif
-
-constexpr const char* JSON_MIMETYPE = "application/json";
-
-/*
- * Json Response
- * */
-
-class ChunkPrint : public Print {
- private:
- uint8_t* _destination;
- size_t _to_skip;
- size_t _to_write;
- size_t _pos;
- public:
- ChunkPrint(uint8_t* destination, size_t from, size_t len)
- : _destination(destination), _to_skip(from), _to_write(len), _pos{0} {}
- virtual ~ChunkPrint(){}
- size_t write(uint8_t c){
- if (_to_skip > 0) {
- _to_skip--;
- return 1;
- } else if (_to_write > 0) {
- _to_write--;
- _destination[_pos++] = c;
- return 1;
- }
- return 0;
- }
- size_t write(const uint8_t *buffer, size_t size)
- {
- return this->Print::write(buffer, size);
- }
-};
-
-class AsyncJsonResponse: public AsyncAbstractResponse {
- protected:
-
-#ifdef ARDUINOJSON_5_COMPATIBILITY
- DynamicJsonBuffer _jsonBuffer;
-#else
- DynamicJsonDocument _jsonBuffer;
-#endif
-
- JsonVariant _root;
- bool _isValid;
-
- public:
-
-#ifdef ARDUINOJSON_5_COMPATIBILITY
- AsyncJsonResponse(bool isArray=false): _isValid{false} {
- _code = 200;
- _contentType = JSON_MIMETYPE;
- if(isArray)
- _root = _jsonBuffer.createArray();
- else
- _root = _jsonBuffer.createObject();
- }
-#else
- AsyncJsonResponse(bool isArray=false, size_t maxJsonBufferSize = DYNAMIC_JSON_DOCUMENT_SIZE) : _jsonBuffer(maxJsonBufferSize), _isValid{false} {
- _code = 200;
- _contentType = JSON_MIMETYPE;
- if(isArray)
- _root = _jsonBuffer.createNestedArray();
- else
- _root = _jsonBuffer.createNestedObject();
- }
-#endif
-
- ~AsyncJsonResponse() {}
- JsonVariant & getRoot() { return _root; }
- bool _sourceValid() const { return _isValid; }
- size_t setLength() {
-
-#ifdef ARDUINOJSON_5_COMPATIBILITY
- _contentLength = _root.measureLength();
-#else
- _contentLength = measureJson(_root);
-#endif
-
- if (_contentLength) { _isValid = true; }
- return _contentLength;
- }
-
- size_t getSize() { return _jsonBuffer.size(); }
-
- size_t _fillBuffer(uint8_t *data, size_t len){
- ChunkPrint dest(data, _sentLength, len);
-
-#ifdef ARDUINOJSON_5_COMPATIBILITY
- _root.printTo( dest ) ;
-#else
- serializeJson(_root, dest);
-#endif
- return len;
- }
-};
-
-class PrettyAsyncJsonResponse: public AsyncJsonResponse {
-public:
-#ifdef ARDUINOJSON_5_COMPATIBILITY
- PrettyAsyncJsonResponse (bool isArray=false) : AsyncJsonResponse{isArray} {}
-#else
- PrettyAsyncJsonResponse (bool isArray=false, size_t maxJsonBufferSize = DYNAMIC_JSON_DOCUMENT_SIZE) : AsyncJsonResponse{isArray, maxJsonBufferSize} {}
-#endif
- size_t setLength () {
-#ifdef ARDUINOJSON_5_COMPATIBILITY
- _contentLength = _root.measurePrettyLength ();
-#else
- _contentLength = measureJsonPretty(_root);
-#endif
- if (_contentLength) {_isValid = true;}
- return _contentLength;
- }
- size_t _fillBuffer (uint8_t *data, size_t len) {
- ChunkPrint dest (data, _sentLength, len);
-#ifdef ARDUINOJSON_5_COMPATIBILITY
- _root.prettyPrintTo (dest);
-#else
- serializeJsonPretty(_root, dest);
-#endif
- return len;
- }
-};
-
-typedef std::function ArJsonRequestHandlerFunction;
-
-class AsyncCallbackJsonWebHandler: public AsyncWebHandler {
-private:
-protected:
- const String _uri;
- WebRequestMethodComposite _method;
- ArJsonRequestHandlerFunction _onRequest;
- size_t _contentLength;
-#ifndef ARDUINOJSON_5_COMPATIBILITY
- const size_t maxJsonBufferSize;
-#endif
- size_t _maxContentLength;
-public:
-#ifdef ARDUINOJSON_5_COMPATIBILITY
- AsyncCallbackJsonWebHandler(const String& uri, ArJsonRequestHandlerFunction onRequest)
- : _uri(uri), _method(HTTP_POST|HTTP_PUT|HTTP_PATCH), _onRequest(onRequest), _maxContentLength(16384) {}
-#else
- AsyncCallbackJsonWebHandler(const String& uri, ArJsonRequestHandlerFunction onRequest, size_t maxJsonBufferSize=DYNAMIC_JSON_DOCUMENT_SIZE)
- : _uri(uri), _method(HTTP_POST|HTTP_PUT|HTTP_PATCH), _onRequest(onRequest), maxJsonBufferSize(maxJsonBufferSize), _maxContentLength(16384) {}
-#endif
-
- void setMethod(WebRequestMethodComposite method){ _method = method; }
- void setMaxContentLength(int maxContentLength){ _maxContentLength = maxContentLength; }
- void onRequest(ArJsonRequestHandlerFunction fn){ _onRequest = fn; }
-
- virtual bool canHandle(AsyncWebServerRequest *request) override final{
- if(!_onRequest)
- return false;
-
- if(!(_method & request->method()))
- return false;
-
- if(_uri.length() && (_uri != request->url() && !request->url().startsWith(_uri+"/")))
- return false;
-
- if ( !request->contentType().equalsIgnoreCase(JSON_MIMETYPE) )
- return false;
-
- request->addInterestingHeader("ANY");
- return true;
- }
-
- virtual void handleRequest(AsyncWebServerRequest *request) override final {
- if(_onRequest) {
- if (request->_tempObject != NULL) {
-
-#ifdef ARDUINOJSON_5_COMPATIBILITY
- DynamicJsonBuffer jsonBuffer;
- JsonVariant json = jsonBuffer.parse((uint8_t*)(request->_tempObject));
- if (json.success()) {
-#else
- DynamicJsonDocument jsonBuffer(this->maxJsonBufferSize);
- DeserializationError error = deserializeJson(jsonBuffer, (uint8_t*)(request->_tempObject));
- if(!error) {
- JsonVariant json = jsonBuffer.as();
-#endif
-
- _onRequest(request, json);
- return;
- }
- }
- request->send(_contentLength > _maxContentLength ? 413 : 400);
- } else {
- request->send(500);
- }
- }
- virtual void handleUpload(AsyncWebServerRequest *request, const String& filename, size_t index, uint8_t *data, size_t len, bool final) override final {
- }
- virtual void handleBody(AsyncWebServerRequest *request, uint8_t *data, size_t len, size_t index, size_t total) override final {
- if (_onRequest) {
- _contentLength = total;
- if (total > 0 && request->_tempObject == NULL && total < _maxContentLength) {
- request->_tempObject = malloc(total);
- }
- if (request->_tempObject != NULL) {
- memcpy((uint8_t*)(request->_tempObject) + index, data, len);
- }
- }
- }
- virtual bool isRequestHandlerTrivial() override final {return _onRequest ? false : true;}
-};
-#endif
diff --git a/ESP32/lib/ESPAsyncWebServer/src/AsyncWebSocket.cpp b/ESP32/lib/ESPAsyncWebServer/src/AsyncWebSocket.cpp
deleted file mode 100644
index f76f2fc..0000000
--- a/ESP32/lib/ESPAsyncWebServer/src/AsyncWebSocket.cpp
+++ /dev/null
@@ -1,1294 +0,0 @@
-/*
- Asynchronous WebServer library for Espressif MCUs
-
- Copyright (c) 2016 Hristo Gochkov. All rights reserved.
- This file is part of the esp8266 core for Arduino environment.
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-*/
-#include "Arduino.h"
-#include "AsyncWebSocket.h"
-
-#include
-
-#ifndef ESP8266
-#include "mbedtls/sha1.h"
-#else
-#include
-#endif
-
-#define MAX_PRINTF_LEN 64
-
-size_t webSocketSendFrameWindow(AsyncClient *client){
- if(!client->canSend())
- return 0;
- size_t space = client->space();
- if(space < 9)
- return 0;
- return space - 8;
-}
-
-size_t webSocketSendFrame(AsyncClient *client, bool final, uint8_t opcode, bool mask, uint8_t *data, size_t len){
- if(!client->canSend())
- return 0;
- size_t space = client->space();
- if(space < 2)
- return 0;
- uint8_t mbuf[4] = {0,0,0,0};
- uint8_t headLen = 2;
- if(len && mask){
- headLen += 4;
- mbuf[0] = rand() % 0xFF;
- mbuf[1] = rand() % 0xFF;
- mbuf[2] = rand() % 0xFF;
- mbuf[3] = rand() % 0xFF;
- }
- if(len > 125)
- headLen += 2;
- if(space < headLen)
- return 0;
- space -= headLen;
-
- if(len > space) len = space;
-
- uint8_t *buf = (uint8_t*)malloc(headLen);
- if(buf == NULL){
- //os_printf("could not malloc %u bytes for frame header\n", headLen);
- return 0;
- }
-
- buf[0] = opcode & 0x0F;
- if(final)
- buf[0] |= 0x80;
- if(len < 126)
- buf[1] = len & 0x7F;
- else {
- buf[1] = 126;
- buf[2] = (uint8_t)((len >> 8) & 0xFF);
- buf[3] = (uint8_t)(len & 0xFF);
- }
- if(len && mask){
- buf[1] |= 0x80;
- memcpy(buf + (headLen - 4), mbuf, 4);
- }
- if(client->add((const char *)buf, headLen) != headLen){
- //os_printf("error adding %lu header bytes\n", headLen);
- free(buf);
- return 0;
- }
- free(buf);
-
- if(len){
- if(len && mask){
- size_t i;
- for(i=0;iadd((const char *)data, len) != len){
- //os_printf("error adding %lu data bytes\n", len);
- return 0;
- }
- }
- if(!client->send()){
- //os_printf("error sending frame: %lu\n", headLen+len);
- return 0;
- }
- return len;
-}
-
-
-/*
- * AsyncWebSocketMessageBuffer
- */
-
-
-
-AsyncWebSocketMessageBuffer::AsyncWebSocketMessageBuffer()
- :_data(nullptr)
- ,_len(0)
- ,_lock(false)
- ,_count(0)
-{
-
-}
-
-AsyncWebSocketMessageBuffer::AsyncWebSocketMessageBuffer(uint8_t * data, size_t size)
- :_data(nullptr)
- ,_len(size)
- ,_lock(false)
- ,_count(0)
-{
-
- if (!data) {
- return;
- }
-
- _data = new uint8_t[_len + 1];
-
- if (_data) {
- memcpy(_data, data, _len);
- _data[_len] = 0;
- }
-}
-
-
-AsyncWebSocketMessageBuffer::AsyncWebSocketMessageBuffer(size_t size)
- :_data(nullptr)
- ,_len(size)
- ,_lock(false)
- ,_count(0)
-{
- _data = new uint8_t[_len + 1];
-
- if (_data) {
- _data[_len] = 0;
- }
-
-}
-
-AsyncWebSocketMessageBuffer::AsyncWebSocketMessageBuffer(const AsyncWebSocketMessageBuffer & copy)
- :_data(nullptr)
- ,_len(0)
- ,_lock(false)
- ,_count(0)
-{
- _len = copy._len;
- _lock = copy._lock;
- _count = 0;
-
- if (_len) {
- _data = new uint8_t[_len + 1];
- _data[_len] = 0;
- }
-
- if (_data) {
- memcpy(_data, copy._data, _len);
- _data[_len] = 0;
- }
-
-}
-
-AsyncWebSocketMessageBuffer::AsyncWebSocketMessageBuffer(AsyncWebSocketMessageBuffer && copy)
- :_data(nullptr)
- ,_len(0)
- ,_lock(false)
- ,_count(0)
-{
- _len = copy._len;
- _lock = copy._lock;
- _count = 0;
-
- if (copy._data) {
- _data = copy._data;
- copy._data = nullptr;
- }
-
-}
-
-AsyncWebSocketMessageBuffer::~AsyncWebSocketMessageBuffer()
-{
- if (_data) {
- delete[] _data;
- }
-}
-
-bool AsyncWebSocketMessageBuffer::reserve(size_t size)
-{
- _len = size;
-
- if (_data) {
- delete[] _data;
- _data = nullptr;
- }
-
- _data = new uint8_t[_len + 1];
-
- if (_data) {
- _data[_len] = 0;
- return true;
- } else {
- return false;
- }
-
-}
-
-
-
-/*
- * Control Frame
- */
-
-class AsyncWebSocketControl {
- private:
- uint8_t _opcode;
- uint8_t *_data;
- size_t _len;
- bool _mask;
- bool _finished;
- public:
- AsyncWebSocketControl(uint8_t opcode, uint8_t *data=NULL, size_t len=0, bool mask=false)
- :_opcode(opcode)
- ,_len(len)
- ,_mask(len && mask)
- ,_finished(false)
- {
- if(data == NULL)
- _len = 0;
- if(_len){
- if(_len > 125)
- _len = 125;
- _data = (uint8_t*)malloc(_len);
- if(_data == NULL)
- _len = 0;
- else memcpy(_data, data, len);
- } else _data = NULL;
- }
- virtual ~AsyncWebSocketControl(){
- if(_data != NULL)
- free(_data);
- }
- virtual bool finished() const { return _finished; }
- uint8_t opcode(){ return _opcode; }
- uint8_t len(){ return _len + 2; }
- size_t send(AsyncClient *client){
- _finished = true;
- return webSocketSendFrame(client, true, _opcode & 0x0F, _mask, _data, _len);
- }
-};
-
-/*
- * Basic Buffered Message
- */
-
-
-AsyncWebSocketBasicMessage::AsyncWebSocketBasicMessage(const char * data, size_t len, uint8_t opcode, bool mask)
- :_len(len)
- ,_sent(0)
- ,_ack(0)
- ,_acked(0)
-{
- _opcode = opcode & 0x07;
- _mask = mask;
- _data = (uint8_t*)malloc(_len+1);
- if(_data == NULL){
- _len = 0;
- _status = WS_MSG_ERROR;
- } else {
- _status = WS_MSG_SENDING;
- memcpy(_data, data, _len);
- _data[_len] = 0;
- }
-}
-AsyncWebSocketBasicMessage::AsyncWebSocketBasicMessage(uint8_t opcode, bool mask)
- :_len(0)
- ,_sent(0)
- ,_ack(0)
- ,_acked(0)
- ,_data(NULL)
-{
- _opcode = opcode & 0x07;
- _mask = mask;
-
-}
-
-
-AsyncWebSocketBasicMessage::~AsyncWebSocketBasicMessage() {
- if(_data != NULL)
- free(_data);
-}
-
- void AsyncWebSocketBasicMessage::ack(size_t len, uint32_t time) {
- (void)time;
- _acked += len;
- if(_sent == _len && _acked == _ack){
- _status = WS_MSG_SENT;
- }
-}
- size_t AsyncWebSocketBasicMessage::send(AsyncClient *client) {
- if(_status != WS_MSG_SENDING)
- return 0;
- if(_acked < _ack){
- return 0;
- }
- if(_sent == _len){
- if(_acked == _ack)
- _status = WS_MSG_SENT;
- return 0;
- }
- if(_sent > _len){
- _status = WS_MSG_ERROR;
- return 0;
- }
-
- size_t toSend = _len - _sent;
- size_t window = webSocketSendFrameWindow(client);
-
- if(window < toSend) {
- toSend = window;
- }
-
- _sent += toSend;
- _ack += toSend + ((toSend < 126)?2:4) + (_mask * 4);
-
- bool final = (_sent == _len);
- uint8_t* dPtr = (uint8_t*)(_data + (_sent - toSend));
- uint8_t opCode = (toSend && _sent == toSend)?_opcode:(uint8_t)WS_CONTINUATION;
-
- size_t sent = webSocketSendFrame(client, final, opCode, _mask, dPtr, toSend);
- _status = WS_MSG_SENDING;
- if(toSend && sent != toSend){
- _sent -= (toSend - sent);
- _ack -= (toSend - sent);
- }
- return sent;
-}
-
-// bool AsyncWebSocketBasicMessage::reserve(size_t size) {
-// if (size) {
-// _data = (uint8_t*)malloc(size +1);
-// if (_data) {
-// memset(_data, 0, size);
-// _len = size;
-// _status = WS_MSG_SENDING;
-// return true;
-// }
-// }
-// return false;
-// }
-
-
-/*
- * AsyncWebSocketMultiMessage Message
- */
-
-
-AsyncWebSocketMultiMessage::AsyncWebSocketMultiMessage(AsyncWebSocketMessageBuffer * buffer, uint8_t opcode, bool mask)
- :_len(0)
- ,_sent(0)
- ,_ack(0)
- ,_acked(0)
- ,_WSbuffer(nullptr)
-{
-
- _opcode = opcode & 0x07;
- _mask = mask;
-
- if (buffer) {
- _WSbuffer = buffer;
- (*_WSbuffer)++;
- _data = buffer->get();
- _len = buffer->length();
- _status = WS_MSG_SENDING;
- //ets_printf("M: %u\n", _len);
- } else {
- _status = WS_MSG_ERROR;
- }
-
-}
-
-
-AsyncWebSocketMultiMessage::~AsyncWebSocketMultiMessage() {
- if (_WSbuffer) {
- (*_WSbuffer)--; // decreases the counter.
- }
-}
-
- void AsyncWebSocketMultiMessage::ack(size_t len, uint32_t time) {
- (void)time;
- _acked += len;
- if(_sent >= _len && _acked >= _ack){
- _status = WS_MSG_SENT;
- }
- //ets_printf("A: %u\n", len);
-}
- size_t AsyncWebSocketMultiMessage::send(AsyncClient *client) {
- if(_status != WS_MSG_SENDING)
- return 0;
- if(_acked < _ack){
- return 0;
- }
- if(_sent == _len){
- _status = WS_MSG_SENT;
- return 0;
- }
- if(_sent > _len){
- _status = WS_MSG_ERROR;
- //ets_printf("E: %u > %u\n", _sent, _len);
- return 0;
- }
-
- size_t toSend = _len - _sent;
- size_t window = webSocketSendFrameWindow(client);
-
- if(window < toSend) {
- toSend = window;
- }
-
- _sent += toSend;
- _ack += toSend + ((toSend < 126)?2:4) + (_mask * 4);
-
- //ets_printf("W: %u %u\n", _sent - toSend, toSend);
-
- bool final = (_sent == _len);
- uint8_t* dPtr = (uint8_t*)(_data + (_sent - toSend));
- uint8_t opCode = (toSend && _sent == toSend)?_opcode:(uint8_t)WS_CONTINUATION;
-
- size_t sent = webSocketSendFrame(client, final, opCode, _mask, dPtr, toSend);
- _status = WS_MSG_SENDING;
- if(toSend && sent != toSend){
- //ets_printf("E: %u != %u\n", toSend, sent);
- _sent -= (toSend - sent);
- _ack -= (toSend - sent);
- }
- //ets_printf("S: %u %u\n", _sent, sent);
- return sent;
-}
-
-
-/*
- * Async WebSocket Client
- */
- const char * AWSC_PING_PAYLOAD = "ESPAsyncWebServer-PING";
- const size_t AWSC_PING_PAYLOAD_LEN = 22;
-
-AsyncWebSocketClient::AsyncWebSocketClient(AsyncWebServerRequest *request, AsyncWebSocket *server)
- : _controlQueue(LinkedList([](AsyncWebSocketControl *c){ delete c; }))
- , _messageQueue(LinkedList([](AsyncWebSocketMessage *m){ delete m; }))
- , _tempObject(NULL)
-{
- _client = request->client();
- _server = server;
- _clientId = _server->_getNextId();
- _status = WS_CONNECTED;
- _pstate = 0;
- _lastMessageTime = millis();
- _keepAlivePeriod = 0;
- _client->setRxTimeout(0);
- _client->onError([](void *r, AsyncClient* c, int8_t error){ (void)c; ((AsyncWebSocketClient*)(r))->_onError(error); }, this);
- _client->onAck([](void *r, AsyncClient* c, size_t len, uint32_t time){ (void)c; ((AsyncWebSocketClient*)(r))->_onAck(len, time); }, this);
- _client->onDisconnect([](void *r, AsyncClient* c){ ((AsyncWebSocketClient*)(r))->_onDisconnect(); delete c; }, this);
- _client->onTimeout([](void *r, AsyncClient* c, uint32_t time){ (void)c; ((AsyncWebSocketClient*)(r))->_onTimeout(time); }, this);
- _client->onData([](void *r, AsyncClient* c, void *buf, size_t len){ (void)c; ((AsyncWebSocketClient*)(r))->_onData(buf, len); }, this);
- _client->onPoll([](void *r, AsyncClient* c){ (void)c; ((AsyncWebSocketClient*)(r))->_onPoll(); }, this);
- _server->_addClient(this);
- _server->_handleEvent(this, WS_EVT_CONNECT, request, NULL, 0);
- delete request;
-}
-
-AsyncWebSocketClient::~AsyncWebSocketClient(){
- _messageQueue.free();
- _controlQueue.free();
- _server->_handleEvent(this, WS_EVT_DISCONNECT, NULL, NULL, 0);
-}
-
-void AsyncWebSocketClient::_onAck(size_t len, uint32_t time){
- _lastMessageTime = millis();
- if(!_controlQueue.isEmpty()){
- auto head = _controlQueue.front();
- if(head->finished()){
- len -= head->len();
- if(_status == WS_DISCONNECTING && head->opcode() == WS_DISCONNECT){
- _controlQueue.remove(head);
- _status = WS_DISCONNECTED;
- _client->close(true);
- return;
- }
- _controlQueue.remove(head);
- }
- }
- if(len && !_messageQueue.isEmpty()){
- _messageQueue.front()->ack(len, time);
- }
- _server->_cleanBuffers();
- _runQueue();
-}
-
-void AsyncWebSocketClient::_onPoll(){
- if(_client->canSend() && (!_controlQueue.isEmpty() || !_messageQueue.isEmpty())){
- _runQueue();
- } else if(_keepAlivePeriod > 0 && _controlQueue.isEmpty() && _messageQueue.isEmpty() && (millis() - _lastMessageTime) >= _keepAlivePeriod){
- ping((uint8_t *)AWSC_PING_PAYLOAD, AWSC_PING_PAYLOAD_LEN);
- }
-}
-
-void AsyncWebSocketClient::_runQueue(){
- while(!_messageQueue.isEmpty() && _messageQueue.front()->finished()){
- _messageQueue.remove(_messageQueue.front());
- }
-
- if(!_controlQueue.isEmpty() && (_messageQueue.isEmpty() || _messageQueue.front()->betweenFrames()) && webSocketSendFrameWindow(_client) > (size_t)(_controlQueue.front()->len() - 1)){
- _controlQueue.front()->send(_client);
- } else if(!_messageQueue.isEmpty() && _messageQueue.front()->betweenFrames() && webSocketSendFrameWindow(_client)){
- _messageQueue.front()->send(_client);
- }
-}
-
-bool AsyncWebSocketClient::queueIsFull(){
- if((_messageQueue.length() >= WS_MAX_QUEUED_MESSAGES) || (_status != WS_CONNECTED) ) return true;
- return false;
-}
-
-void AsyncWebSocketClient::_queueMessage(AsyncWebSocketMessage *dataMessage){
- if(dataMessage == NULL)
- return;
- if(_status != WS_CONNECTED){
- delete dataMessage;
- return;
- }
- if(_messageQueue.length() >= WS_MAX_QUEUED_MESSAGES){
- ets_printf("ERROR: Too many messages queued\n");
- delete dataMessage;
- } else {
- _messageQueue.add(dataMessage);
- }
- if(_client->canSend())
- _runQueue();
-}
-
-void AsyncWebSocketClient::_queueControl(AsyncWebSocketControl *controlMessage){
- if(controlMessage == NULL)
- return;
- _controlQueue.add(controlMessage);
- if(_client->canSend())
- _runQueue();
-}
-
-void AsyncWebSocketClient::close(uint16_t code, const char * message){
- if(_status != WS_CONNECTED)
- return;
- if(code){
- uint8_t packetLen = 2;
- if(message != NULL){
- size_t mlen = strlen(message);
- if(mlen > 123) mlen = 123;
- packetLen += mlen;
- }
- char * buf = (char*)malloc(packetLen);
- if(buf != NULL){
- buf[0] = (uint8_t)(code >> 8);
- buf[1] = (uint8_t)(code & 0xFF);
- if(message != NULL){
- memcpy(buf+2, message, packetLen -2);
- }
- _queueControl(new AsyncWebSocketControl(WS_DISCONNECT,(uint8_t*)buf,packetLen));
- free(buf);
- return;
- }
- }
- _queueControl(new AsyncWebSocketControl(WS_DISCONNECT));
-}
-
-void AsyncWebSocketClient::ping(uint8_t *data, size_t len){
- if(_status == WS_CONNECTED)
- _queueControl(new AsyncWebSocketControl(WS_PING, data, len));
-}
-
-void AsyncWebSocketClient::_onError(int8_t){}
-
-void AsyncWebSocketClient::_onTimeout(uint32_t time){
- (void)time;
- _client->close(true);
-}
-
-void AsyncWebSocketClient::_onDisconnect(){
- _client = NULL;
- _server->_handleDisconnect(this);
-}
-
-void AsyncWebSocketClient::_onData(void *pbuf, size_t plen){
- _lastMessageTime = millis();
- uint8_t *data = (uint8_t*)pbuf;
- while(plen > 0){
- if(!_pstate){
- const uint8_t *fdata = data;
- _pinfo.index = 0;
- _pinfo.final = (fdata[0] & 0x80) != 0;
- _pinfo.opcode = fdata[0] & 0x0F;
- _pinfo.masked = (fdata[1] & 0x80) != 0;
- _pinfo.len = fdata[1] & 0x7F;
- data += 2;
- plen -= 2;
- if(_pinfo.len == 126){
- _pinfo.len = fdata[3] | (uint16_t)(fdata[2]) << 8;
- data += 2;
- plen -= 2;
- } else if(_pinfo.len == 127){
- _pinfo.len = fdata[9] | (uint16_t)(fdata[8]) << 8 | (uint32_t)(fdata[7]) << 16 | (uint32_t)(fdata[6]) << 24 | (uint64_t)(fdata[5]) << 32 | (uint64_t)(fdata[4]) << 40 | (uint64_t)(fdata[3]) << 48 | (uint64_t)(fdata[2]) << 56;
- data += 8;
- plen -= 8;
- }
-
- if(_pinfo.masked){
- memcpy(_pinfo.mask, data, 4);
- data += 4;
- plen -= 4;
- }
- }
-
- const size_t datalen = std::min((size_t)(_pinfo.len - _pinfo.index), plen);
- const auto datalast = data[datalen];
-
- if(_pinfo.masked){
- for(size_t i=0;i_handleEvent(this, WS_EVT_DATA, (void *)&_pinfo, (uint8_t*)data, datalen);
-
- _pinfo.index += datalen;
- } else if((datalen + _pinfo.index) == _pinfo.len){
- _pstate = 0;
- if(_pinfo.opcode == WS_DISCONNECT){
- if(datalen){
- uint16_t reasonCode = (uint16_t)(data[0] << 8) + data[1];
- char * reasonString = (char*)(data+2);
- if(reasonCode > 1001){
- _server->_handleEvent(this, WS_EVT_ERROR, (void *)&reasonCode, (uint8_t*)reasonString, strlen(reasonString));
- }
- }
- if(_status == WS_DISCONNECTING){
- _status = WS_DISCONNECTED;
- _client->close(true);
- } else {
- _status = WS_DISCONNECTING;
- _client->ackLater();
- _queueControl(new AsyncWebSocketControl(WS_DISCONNECT, data, datalen));
- }
- } else if(_pinfo.opcode == WS_PING){
- _queueControl(new AsyncWebSocketControl(WS_PONG, data, datalen));
- } else if(_pinfo.opcode == WS_PONG){
- if(datalen != AWSC_PING_PAYLOAD_LEN || memcmp(AWSC_PING_PAYLOAD, data, AWSC_PING_PAYLOAD_LEN) != 0)
- _server->_handleEvent(this, WS_EVT_PONG, NULL, data, datalen);
- } else if(_pinfo.opcode < 8){//continuation or text/binary frame
- _server->_handleEvent(this, WS_EVT_DATA, (void *)&_pinfo, data, datalen);
- }
- } else {
- //os_printf("frame error: len: %u, index: %llu, total: %llu\n", datalen, _pinfo.index, _pinfo.len);
- //what should we do?
- break;
- }
-
- // restore byte as _handleEvent may have added a null terminator i.e., data[len] = 0;
- if (datalen > 0)
- data[datalen] = datalast;
-
- data += datalen;
- plen -= datalen;
- }
-}
-
-size_t AsyncWebSocketClient::printf(const char *format, ...) {
- va_list arg;
- va_start(arg, format);
- char* temp = new char[MAX_PRINTF_LEN];
- if(!temp){
- va_end(arg);
- return 0;
- }
- char* buffer = temp;
- size_t len = vsnprintf(temp, MAX_PRINTF_LEN, format, arg);
- va_end(arg);
-
- if (len > (MAX_PRINTF_LEN - 1)) {
- buffer = new char[len + 1];
- if (!buffer) {
- delete[] temp;
- return 0;
- }
- va_start(arg, format);
- vsnprintf(buffer, len + 1, format, arg);
- va_end(arg);
- }
- text(buffer, len);
- if (buffer != temp) {
- delete[] buffer;
- }
- delete[] temp;
- return len;
-}
-
-#ifndef ESP32
-size_t AsyncWebSocketClient::printf_P(PGM_P formatP, ...) {
- va_list arg;
- va_start(arg, formatP);
- char* temp = new char[MAX_PRINTF_LEN];
- if(!temp){
- va_end(arg);
- return 0;
- }
- char* buffer = temp;
- size_t len = vsnprintf_P(temp, MAX_PRINTF_LEN, formatP, arg);
- va_end(arg);
-
- if (len > (MAX_PRINTF_LEN - 1)) {
- buffer = new char[len + 1];
- if (!buffer) {
- delete[] temp;
- return 0;
- }
- va_start(arg, formatP);
- vsnprintf_P(buffer, len + 1, formatP, arg);
- va_end(arg);
- }
- text(buffer, len);
- if (buffer != temp) {
- delete[] buffer;
- }
- delete[] temp;
- return len;
-}
-#endif
-
-void AsyncWebSocketClient::text(const char * message, size_t len){
- _queueMessage(new AsyncWebSocketBasicMessage(message, len));
-}
-void AsyncWebSocketClient::text(const char * message){
- text(message, strlen(message));
-}
-void AsyncWebSocketClient::text(uint8_t * message, size_t len){
- text((const char *)message, len);
-}
-void AsyncWebSocketClient::text(char * message){
- text(message, strlen(message));
-}
-void AsyncWebSocketClient::text(const String &message){
- text(message.c_str(), message.length());
-}
-void AsyncWebSocketClient::text(const __FlashStringHelper *data){
- PGM_P p = reinterpret_cast(data);
- size_t n = 0;
- while (1) {
- if (pgm_read_byte(p+n) == 0) break;
- n += 1;
- }
- char * message = (char*) malloc(n+1);
- if(message){
- for(size_t b=0; b(data);
- char * message = (char*) malloc(len);
- if(message){
- for(size_t b=0; bremoteIP();
-}
-
-uint16_t AsyncWebSocketClient::remotePort() {
- if(!_client) {
- return 0;
- }
- return _client->remotePort();
-}
-
-
-
-/*
- * Async Web Socket - Each separate socket location
- */
-
-AsyncWebSocket::AsyncWebSocket(const String& url)
- :_url(url)
- ,_clients(LinkedList([](AsyncWebSocketClient *c){ delete c; }))
- ,_cNextId(1)
- ,_enabled(true)
- ,_buffers(LinkedList([](AsyncWebSocketMessageBuffer *b){ delete b; }))
-{
- _eventHandler = NULL;
-}
-
-AsyncWebSocket::~AsyncWebSocket(){}
-
-void AsyncWebSocket::_handleEvent(AsyncWebSocketClient * client, AwsEventType type, void * arg, uint8_t *data, size_t len){
- if(_eventHandler != NULL){
- _eventHandler(this, client, type, arg, data, len);
- }
-}
-
-void AsyncWebSocket::_addClient(AsyncWebSocketClient * client){
- _clients.add(client);
-}
-
-void AsyncWebSocket::_handleDisconnect(AsyncWebSocketClient * client){
-
- _clients.remove_first([=](AsyncWebSocketClient * c){
- return c->id() == client->id();
- });
-}
-
-bool AsyncWebSocket::availableForWriteAll(){
- for(const auto& c: _clients){
- if(c->queueIsFull()) return false;
- }
- return true;
-}
-
-bool AsyncWebSocket::availableForWrite(uint32_t id){
- for(const auto& c: _clients){
- if(c->queueIsFull() && (c->id() == id )) return false;
- }
- return true;
-}
-
-size_t AsyncWebSocket::count() const {
- return _clients.count_if([](AsyncWebSocketClient * c){
- return c->status() == WS_CONNECTED;
- });
-}
-
-AsyncWebSocketClient * AsyncWebSocket::client(uint32_t id){
- for(const auto &c: _clients){
- if(c->id() == id && c->status() == WS_CONNECTED){
- return c;
- }
- }
- return nullptr;
-}
-
-
-void AsyncWebSocket::close(uint32_t id, uint16_t code, const char * message){
- AsyncWebSocketClient * c = client(id);
- if(c)
- c->close(code, message);
-}
-
-void AsyncWebSocket::closeAll(uint16_t code, const char * message){
- for(const auto& c: _clients){
- if(c->status() == WS_CONNECTED)
- c->close(code, message);
- }
-}
-
-void AsyncWebSocket::cleanupClients(uint16_t maxClients)
-{
- if (count() > maxClients){
- _clients.front()->close();
- }
-}
-
-void AsyncWebSocket::ping(uint32_t id, uint8_t *data, size_t len){
- AsyncWebSocketClient * c = client(id);
- if(c)
- c->ping(data, len);
-}
-
-void AsyncWebSocket::pingAll(uint8_t *data, size_t len){
- for(const auto& c: _clients){
- if(c->status() == WS_CONNECTED)
- c->ping(data, len);
- }
-}
-
-void AsyncWebSocket::text(uint32_t id, const char * message, size_t len){
- AsyncWebSocketClient * c = client(id);
- if(c)
- c->text(message, len);
-}
-
-void AsyncWebSocket::textAll(AsyncWebSocketMessageBuffer * buffer){
- if (!buffer) return;
- buffer->lock();
- for(const auto& c: _clients){
- if(c->status() == WS_CONNECTED){
- c->text(buffer);
- }
- }
- buffer->unlock();
- _cleanBuffers();
-}
-
-
-void AsyncWebSocket::textAll(const char * message, size_t len){
- AsyncWebSocketMessageBuffer * WSBuffer = makeBuffer((uint8_t *)message, len);
- textAll(WSBuffer);
-}
-
-void AsyncWebSocket::binary(uint32_t id, const char * message, size_t len){
- AsyncWebSocketClient * c = client(id);
- if(c)
- c->binary(message, len);
-}
-
-void AsyncWebSocket::binaryAll(const char * message, size_t len){
- AsyncWebSocketMessageBuffer * buffer = makeBuffer((uint8_t *)message, len);
- binaryAll(buffer);
-}
-
-void AsyncWebSocket::binaryAll(AsyncWebSocketMessageBuffer * buffer)
-{
- if (!buffer) return;
- buffer->lock();
- for(const auto& c: _clients){
- if(c->status() == WS_CONNECTED)
- c->binary(buffer);
- }
- buffer->unlock();
- _cleanBuffers();
-}
-
-void AsyncWebSocket::message(uint32_t id, AsyncWebSocketMessage *message){
- AsyncWebSocketClient * c = client(id);
- if(c)
- c->message(message);
-}
-
-void AsyncWebSocket::messageAll(AsyncWebSocketMultiMessage *message){
- for(const auto& c: _clients){
- if(c->status() == WS_CONNECTED)
- c->message(message);
- }
- _cleanBuffers();
-}
-
-size_t AsyncWebSocket::printf(uint32_t id, const char *format, ...){
- AsyncWebSocketClient * c = client(id);
- if(c){
- va_list arg;
- va_start(arg, format);
- size_t len = c->printf(format, arg);
- va_end(arg);
- return len;
- }
- return 0;
-}
-
-size_t AsyncWebSocket::printfAll(const char *format, ...) {
- va_list arg;
- char* temp = new char[MAX_PRINTF_LEN];
- if(!temp){
- return 0;
- }
- va_start(arg, format);
- size_t len = vsnprintf(temp, MAX_PRINTF_LEN, format, arg);
- va_end(arg);
- delete[] temp;
-
- AsyncWebSocketMessageBuffer * buffer = makeBuffer(len);
- if (!buffer) {
- return 0;
- }
-
- va_start(arg, format);
- vsnprintf( (char *)buffer->get(), len + 1, format, arg);
- va_end(arg);
-
- textAll(buffer);
- return len;
-}
-
-#ifndef ESP32
-size_t AsyncWebSocket::printf_P(uint32_t id, PGM_P formatP, ...){
- AsyncWebSocketClient * c = client(id);
- if(c != NULL){
- va_list arg;
- va_start(arg, formatP);
- size_t len = c->printf_P(formatP, arg);
- va_end(arg);
- return len;
- }
- return 0;
-}
-#endif
-
-size_t AsyncWebSocket::printfAll_P(PGM_P formatP, ...) {
- va_list arg;
- char* temp = new char[MAX_PRINTF_LEN];
- if(!temp){
- return 0;
- }
- va_start(arg, formatP);
- size_t len = vsnprintf_P(temp, MAX_PRINTF_LEN, formatP, arg);
- va_end(arg);
- delete[] temp;
-
- AsyncWebSocketMessageBuffer * buffer = makeBuffer(len + 1);
- if (!buffer) {
- return 0;
- }
-
- va_start(arg, formatP);
- vsnprintf_P((char *)buffer->get(), len + 1, formatP, arg);
- va_end(arg);
-
- textAll(buffer);
- return len;
-}
-
-void AsyncWebSocket::text(uint32_t id, const char * message){
- text(id, message, strlen(message));
-}
-void AsyncWebSocket::text(uint32_t id, uint8_t * message, size_t len){
- text(id, (const char *)message, len);
-}
-void AsyncWebSocket::text(uint32_t id, char * message){
- text(id, message, strlen(message));
-}
-void AsyncWebSocket::text(uint32_t id, const String &message){
- text(id, message.c_str(), message.length());
-}
-void AsyncWebSocket::text(uint32_t id, const __FlashStringHelper *message){
- AsyncWebSocketClient * c = client(id);
- if(c != NULL)
- c->text(message);
-}
-void AsyncWebSocket::textAll(const char * message){
- textAll(message, strlen(message));
-}
-void AsyncWebSocket::textAll(uint8_t * message, size_t len){
- textAll((const char *)message, len);
-}
-void AsyncWebSocket::textAll(char * message){
- textAll(message, strlen(message));
-}
-void AsyncWebSocket::textAll(const String &message){
- textAll(message.c_str(), message.length());
-}
-void AsyncWebSocket::textAll(const __FlashStringHelper *message){
- for(const auto& c: _clients){
- if(c->status() == WS_CONNECTED)
- c->text(message);
- }
-}
-void AsyncWebSocket::binary(uint32_t id, const char * message){
- binary(id, message, strlen(message));
-}
-void AsyncWebSocket::binary(uint32_t id, uint8_t * message, size_t len){
- binary(id, (const char *)message, len);
-}
-void AsyncWebSocket::binary(uint32_t id, char * message){
- binary(id, message, strlen(message));
-}
-void AsyncWebSocket::binary(uint32_t id, const String &message){
- binary(id, message.c_str(), message.length());
-}
-void AsyncWebSocket::binary(uint32_t id, const __FlashStringHelper *message, size_t len){
- AsyncWebSocketClient * c = client(id);
- if(c != NULL)
- c-> binary(message, len);
-}
-void AsyncWebSocket::binaryAll(const char * message){
- binaryAll(message, strlen(message));
-}
-void AsyncWebSocket::binaryAll(uint8_t * message, size_t len){
- binaryAll((const char *)message, len);
-}
-void AsyncWebSocket::binaryAll(char * message){
- binaryAll(message, strlen(message));
-}
-void AsyncWebSocket::binaryAll(const String &message){
- binaryAll(message.c_str(), message.length());
-}
-void AsyncWebSocket::binaryAll(const __FlashStringHelper *message, size_t len){
- for(const auto& c: _clients){
- if(c->status() == WS_CONNECTED)
- c-> binary(message, len);
- }
- }
-
-const char * WS_STR_CONNECTION = "Connection";
-const char * WS_STR_UPGRADE = "Upgrade";
-const char * WS_STR_ORIGIN = "Origin";
-const char * WS_STR_VERSION = "Sec-WebSocket-Version";
-const char * WS_STR_KEY = "Sec-WebSocket-Key";
-const char * WS_STR_PROTOCOL = "Sec-WebSocket-Protocol";
-const char * WS_STR_ACCEPT = "Sec-WebSocket-Accept";
-const char * WS_STR_UUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
-
-bool AsyncWebSocket::canHandle(AsyncWebServerRequest *request){
- if(!_enabled)
- return false;
-
- if(request->method() != HTTP_GET || !request->url().equals(_url) || !request->isExpectedRequestedConnType(RCT_WS))
- return false;
-
- request->addInterestingHeader(WS_STR_CONNECTION);
- request->addInterestingHeader(WS_STR_UPGRADE);
- request->addInterestingHeader(WS_STR_ORIGIN);
- request->addInterestingHeader(WS_STR_VERSION);
- request->addInterestingHeader(WS_STR_KEY);
- request->addInterestingHeader(WS_STR_PROTOCOL);
- return true;
-}
-
-void AsyncWebSocket::handleRequest(AsyncWebServerRequest *request){
- if(!request->hasHeader(WS_STR_VERSION) || !request->hasHeader(WS_STR_KEY)){
- request->send(400);
- return;
- }
- if((_username != "" && _password != "") && !request->authenticate(_username.c_str(), _password.c_str())){
- return request->requestAuthentication();
- }
- AsyncWebHeader* version = request->getHeader(WS_STR_VERSION);
- if(version->value().toInt() != 13){
- AsyncWebServerResponse *response = request->beginResponse(400);
- response->addHeader(WS_STR_VERSION,"13");
- request->send(response);
- return;
- }
- AsyncWebHeader* key = request->getHeader(WS_STR_KEY);
- AsyncWebServerResponse *response = new AsyncWebSocketResponse(key->value(), this);
- if(request->hasHeader(WS_STR_PROTOCOL)){
- AsyncWebHeader* protocol = request->getHeader(WS_STR_PROTOCOL);
- //ToDo: check protocol
- response->addHeader(WS_STR_PROTOCOL, protocol->value());
- }
- request->send(response);
-}
-
-AsyncWebSocketMessageBuffer * AsyncWebSocket::makeBuffer(size_t size)
-{
- AsyncWebSocketMessageBuffer * buffer = new AsyncWebSocketMessageBuffer(size);
- if (buffer) {
- AsyncWebLockGuard l(_lock);
- _buffers.add(buffer);
- }
- return buffer;
-}
-
-AsyncWebSocketMessageBuffer * AsyncWebSocket::makeBuffer(uint8_t * data, size_t size)
-{
- AsyncWebSocketMessageBuffer * buffer = new AsyncWebSocketMessageBuffer(data, size);
-
- if (buffer) {
- AsyncWebLockGuard l(_lock);
- _buffers.add(buffer);
- }
-
- return buffer;
-}
-
-void AsyncWebSocket::_cleanBuffers()
-{
- AsyncWebLockGuard l(_lock);
-
- for(AsyncWebSocketMessageBuffer * c: _buffers){
- if(c && c->canDelete()){
- _buffers.remove(c);
- }
- }
-}
-
-AsyncWebSocket::AsyncWebSocketClientLinkedList AsyncWebSocket::getClients() const {
- return _clients;
-}
-
-/*
- * Response to Web Socket request - sends the authorization and detaches the TCP Client from the web server
- * Authentication code from https://github.com/Links2004/arduinoWebSockets/blob/master/src/WebSockets.cpp#L480
- */
-
-AsyncWebSocketResponse::AsyncWebSocketResponse(const String& key, AsyncWebSocket *server){
- _server = server;
- _code = 101;
- _sendContentLength = false;
-
- uint8_t * hash = (uint8_t*)malloc(20);
- if(hash == NULL){
- _state = RESPONSE_FAILED;
- return;
- }
- char * buffer = (char *) malloc(33);
- if(buffer == NULL){
- free(hash);
- _state = RESPONSE_FAILED;
- return;
- }
-#ifdef ESP8266
- sha1(key + WS_STR_UUID, hash);
-#else
- (String&)key += WS_STR_UUID;
- mbedtls_sha1_context ctx;
- mbedtls_sha1_init(&ctx);
- mbedtls_sha1_starts_ret(&ctx);
- mbedtls_sha1_update_ret(&ctx, (const unsigned char*)key.c_str(), key.length());
- mbedtls_sha1_finish_ret(&ctx, hash);
- mbedtls_sha1_free(&ctx);
-#endif
- base64_encodestate _state;
- base64_init_encodestate(&_state);
- int len = base64_encode_block((const char *) hash, 20, buffer, &_state);
- len = base64_encode_blockend((buffer + len), &_state);
- addHeader(WS_STR_CONNECTION, WS_STR_UPGRADE);
- addHeader(WS_STR_UPGRADE, "websocket");
- addHeader(WS_STR_ACCEPT,buffer);
- free(buffer);
- free(hash);
-}
-
-void AsyncWebSocketResponse::_respond(AsyncWebServerRequest *request){
- if(_state == RESPONSE_FAILED){
- request->client()->close(true);
- return;
- }
- String out = _assembleHead(request->version());
- request->client()->write(out.c_str(), _headLength);
- _state = RESPONSE_WAIT_ACK;
-}
-
-size_t AsyncWebSocketResponse::_ack(AsyncWebServerRequest *request, size_t len, uint32_t time){
- (void)time;
- if(len){
- new AsyncWebSocketClient(request, _server);
- }
- return 0;
-}
diff --git a/ESP32/lib/ESPAsyncWebServer/src/AsyncWebSocket.h b/ESP32/lib/ESPAsyncWebServer/src/AsyncWebSocket.h
deleted file mode 100644
index 5b03ace..0000000
--- a/ESP32/lib/ESPAsyncWebServer/src/AsyncWebSocket.h
+++ /dev/null
@@ -1,350 +0,0 @@
-/*
- Asynchronous WebServer library for Espressif MCUs
-
- Copyright (c) 2016 Hristo Gochkov. All rights reserved.
- This file is part of the esp8266 core for Arduino environment.
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-*/
-#ifndef ASYNCWEBSOCKET_H_
-#define ASYNCWEBSOCKET_H_
-
-#include
-#ifdef ESP32
-#include
-#define WS_MAX_QUEUED_MESSAGES 32
-#else
-#include
-#define WS_MAX_QUEUED_MESSAGES 8
-#endif
-#include
-
-#include "AsyncWebSynchronization.h"
-
-#ifdef ESP8266
-#include
-#ifdef CRYPTO_HASH_h // include Hash.h from espressif framework if the first include was from the crypto library
-#include <../src/Hash.h>
-#endif
-#endif
-
-#ifdef ESP32
-#define DEFAULT_MAX_WS_CLIENTS 8
-#else
-#define DEFAULT_MAX_WS_CLIENTS 4
-#endif
-
-class AsyncWebSocket;
-class AsyncWebSocketResponse;
-class AsyncWebSocketClient;
-class AsyncWebSocketControl;
-
-typedef struct {
- /** Message type as defined by enum AwsFrameType.
- * Note: Applications will only see WS_TEXT and WS_BINARY.
- * All other types are handled by the library. */
- uint8_t message_opcode;
- /** Frame number of a fragmented message. */
- uint32_t num;
- /** Is this the last frame in a fragmented message ?*/
- uint8_t final;
- /** Is this frame masked? */
- uint8_t masked;
- /** Message type as defined by enum AwsFrameType.
- * This value is the same as message_opcode for non-fragmented
- * messages, but may also be WS_CONTINUATION in a fragmented message. */
- uint8_t opcode;
- /** Length of the current frame.
- * This equals the total length of the message if num == 0 && final == true */
- uint64_t len;
- /** Mask key */
- uint8_t mask[4];
- /** Offset of the data inside the current frame. */
- uint64_t index;
-} AwsFrameInfo;
-
-typedef enum { WS_DISCONNECTED, WS_CONNECTED, WS_DISCONNECTING } AwsClientStatus;
-typedef enum { WS_CONTINUATION, WS_TEXT, WS_BINARY, WS_DISCONNECT = 0x08, WS_PING, WS_PONG } AwsFrameType;
-typedef enum { WS_MSG_SENDING, WS_MSG_SENT, WS_MSG_ERROR } AwsMessageStatus;
-typedef enum { WS_EVT_CONNECT, WS_EVT_DISCONNECT, WS_EVT_PONG, WS_EVT_ERROR, WS_EVT_DATA } AwsEventType;
-
-class AsyncWebSocketMessageBuffer {
- private:
- uint8_t * _data;
- size_t _len;
- bool _lock;
- uint32_t _count;
-
- public:
- AsyncWebSocketMessageBuffer();
- AsyncWebSocketMessageBuffer(size_t size);
- AsyncWebSocketMessageBuffer(uint8_t * data, size_t size);
- AsyncWebSocketMessageBuffer(const AsyncWebSocketMessageBuffer &);
- AsyncWebSocketMessageBuffer(AsyncWebSocketMessageBuffer &&);
- ~AsyncWebSocketMessageBuffer();
- void operator ++(int i) { (void)i; _count++; }
- void operator --(int i) { (void)i; if (_count > 0) { _count--; } ; }
- bool reserve(size_t size);
- void lock() { _lock = true; }
- void unlock() { _lock = false; }
- uint8_t * get() { return _data; }
- size_t length() { return _len; }
- uint32_t count() { return _count; }
- bool canDelete() { return (!_count && !_lock); }
-
- friend AsyncWebSocket;
-
-};
-
-class AsyncWebSocketMessage {
- protected:
- uint8_t _opcode;
- bool _mask;
- AwsMessageStatus _status;
- public:
- AsyncWebSocketMessage():_opcode(WS_TEXT),_mask(false),_status(WS_MSG_ERROR){}
- virtual ~AsyncWebSocketMessage(){}
- virtual void ack(size_t len __attribute__((unused)), uint32_t time __attribute__((unused))){}
- virtual size_t send(AsyncClient *client __attribute__((unused))){ return 0; }
- virtual bool finished(){ return _status != WS_MSG_SENDING; }
- virtual bool betweenFrames() const { return false; }
-};
-
-class AsyncWebSocketBasicMessage: public AsyncWebSocketMessage {
- private:
- size_t _len;
- size_t _sent;
- size_t _ack;
- size_t _acked;
- uint8_t * _data;
-public:
- AsyncWebSocketBasicMessage(const char * data, size_t len, uint8_t opcode=WS_TEXT, bool mask=false);
- AsyncWebSocketBasicMessage(uint8_t opcode=WS_TEXT, bool mask=false);
- virtual ~AsyncWebSocketBasicMessage() override;
- virtual bool betweenFrames() const override { return _acked == _ack; }
- virtual void ack(size_t len, uint32_t time) override ;
- virtual size_t send(AsyncClient *client) override ;
-};
-
-class AsyncWebSocketMultiMessage: public AsyncWebSocketMessage {
- private:
- uint8_t * _data;
- size_t _len;
- size_t _sent;
- size_t _ack;
- size_t _acked;
- AsyncWebSocketMessageBuffer * _WSbuffer;
-public:
- AsyncWebSocketMultiMessage(AsyncWebSocketMessageBuffer * buffer, uint8_t opcode=WS_TEXT, bool mask=false);
- virtual ~AsyncWebSocketMultiMessage() override;
- virtual bool betweenFrames() const override { return _acked == _ack; }
- virtual void ack(size_t len, uint32_t time) override ;
- virtual size_t send(AsyncClient *client) override ;
-};
-
-class AsyncWebSocketClient {
- private:
- AsyncClient *_client;
- AsyncWebSocket *_server;
- uint32_t _clientId;
- AwsClientStatus _status;
-
- LinkedList _controlQueue;
- LinkedList _messageQueue;
-
- uint8_t _pstate;
- AwsFrameInfo _pinfo;
-
- uint32_t _lastMessageTime;
- uint32_t _keepAlivePeriod;
-
- void _queueMessage(AsyncWebSocketMessage *dataMessage);
- void _queueControl(AsyncWebSocketControl *controlMessage);
- void _runQueue();
-
- public:
- void *_tempObject;
-
- AsyncWebSocketClient(AsyncWebServerRequest *request, AsyncWebSocket *server);
- ~AsyncWebSocketClient();
-
- //client id increments for the given server
- uint32_t id(){ return _clientId; }
- AwsClientStatus status(){ return _status; }
- AsyncClient* client(){ return _client; }
- AsyncWebSocket *server(){ return _server; }
- AwsFrameInfo const &pinfo() const { return _pinfo; }
-
- IPAddress remoteIP();
- uint16_t remotePort();
-
- //control frames
- void close(uint16_t code=0, const char * message=NULL);
- void ping(uint8_t *data=NULL, size_t len=0);
-
- //set auto-ping period in seconds. disabled if zero (default)
- void keepAlivePeriod(uint16_t seconds){
- _keepAlivePeriod = seconds * 1000;
- }
- uint16_t keepAlivePeriod(){
- return (uint16_t)(_keepAlivePeriod / 1000);
- }
-
- //data packets
- void message(AsyncWebSocketMessage *message){ _queueMessage(message); }
- bool queueIsFull();
-
- size_t printf(const char *format, ...) __attribute__ ((format (printf, 2, 3)));
-#ifndef ESP32
- size_t printf_P(PGM_P formatP, ...) __attribute__ ((format (printf, 2, 3)));
-#endif
- void text(const char * message, size_t len);
- void text(const char * message);
- void text(uint8_t * message, size_t len);
- void text(char * message);
- void text(const String &message);
- void text(const __FlashStringHelper *data);
- void text(AsyncWebSocketMessageBuffer *buffer);
-
- void binary(const char * message, size_t len);
- void binary(const char * message);
- void binary(uint8_t * message, size_t len);
- void binary(char * message);
- void binary(const String &message);
- void binary(const __FlashStringHelper *data, size_t len);
- void binary(AsyncWebSocketMessageBuffer *buffer);
-
- bool canSend() { return _messageQueue.length() < WS_MAX_QUEUED_MESSAGES; }
-
- //system callbacks (do not call)
- void _onAck(size_t len, uint32_t time);
- void _onError(int8_t);
- void _onPoll();
- void _onTimeout(uint32_t time);
- void _onDisconnect();
- void _onData(void *pbuf, size_t plen);
-};
-
-typedef std::function AwsEventHandler;
-
-//WebServer Handler implementation that plays the role of a socket server
-class AsyncWebSocket: public AsyncWebHandler {
- public:
- typedef LinkedList AsyncWebSocketClientLinkedList;
- private:
- String _url;
- AsyncWebSocketClientLinkedList _clients;
- uint32_t _cNextId;
- AwsEventHandler _eventHandler;
- bool _enabled;
- AsyncWebLock _lock;
-
- public:
- AsyncWebSocket(const String& url);
- ~AsyncWebSocket();
- const char * url() const { return _url.c_str(); }
- void enable(bool e){ _enabled = e; }
- bool enabled() const { return _enabled; }
- bool availableForWriteAll();
- bool availableForWrite(uint32_t id);
-
- size_t count() const;
- AsyncWebSocketClient * client(uint32_t id);
- bool hasClient(uint32_t id){ return client(id) != NULL; }
-
- void close(uint32_t id, uint16_t code=0, const char * message=NULL);
- void closeAll(uint16_t code=0, const char * message=NULL);
- void cleanupClients(uint16_t maxClients = DEFAULT_MAX_WS_CLIENTS);
-
- void ping(uint32_t id, uint8_t *data=NULL, size_t len=0);
- void pingAll(uint8_t *data=NULL, size_t len=0); // done
-
- void text(uint32_t id, const char * message, size_t len);
- void text(uint32_t id, const char * message);
- void text(uint32_t id, uint8_t * message, size_t len);
- void text(uint32_t id, char * message);
- void text(uint32_t id, const String &message);
- void text(uint32_t id, const __FlashStringHelper *message);
-
- void textAll(const char * message, size_t len);
- void textAll(const char * message);
- void textAll(uint8_t * message, size_t len);
- void textAll(char * message);
- void textAll(const String &message);
- void textAll(const __FlashStringHelper *message); // need to convert
- void textAll(AsyncWebSocketMessageBuffer * buffer);
-
- void binary(uint32_t id, const char * message, size_t len);
- void binary(uint32_t id, const char * message);
- void binary(uint32_t id, uint8_t * message, size_t len);
- void binary(uint32_t id, char * message);
- void binary(uint32_t id, const String &message);
- void binary(uint32_t id, const __FlashStringHelper *message, size_t len);
-
- void binaryAll(const char * message, size_t len);
- void binaryAll(const char * message);
- void binaryAll(uint8_t * message, size_t len);
- void binaryAll(char * message);
- void binaryAll(const String &message);
- void binaryAll(const __FlashStringHelper *message, size_t len);
- void binaryAll(AsyncWebSocketMessageBuffer * buffer);
-
- void message(uint32_t id, AsyncWebSocketMessage *message);
- void messageAll(AsyncWebSocketMultiMessage *message);
-
- size_t printf(uint32_t id, const char *format, ...) __attribute__ ((format (printf, 3, 4)));
- size_t printfAll(const char *format, ...) __attribute__ ((format (printf, 2, 3)));
-#ifndef ESP32
- size_t printf_P(uint32_t id, PGM_P formatP, ...) __attribute__ ((format (printf, 3, 4)));
-#endif
- size_t printfAll_P(PGM_P formatP, ...) __attribute__ ((format (printf, 2, 3)));
-
- //event listener
- void onEvent(AwsEventHandler handler){
- _eventHandler = handler;
- }
-
- //system callbacks (do not call)
- uint32_t _getNextId(){ return _cNextId++; }
- void _addClient(AsyncWebSocketClient * client);
- void _handleDisconnect(AsyncWebSocketClient * client);
- void _handleEvent(AsyncWebSocketClient * client, AwsEventType type, void * arg, uint8_t *data, size_t len);
- virtual bool canHandle(AsyncWebServerRequest *request) override final;
- virtual void handleRequest(AsyncWebServerRequest *request) override final;
-
-
- // messagebuffer functions/objects.
- AsyncWebSocketMessageBuffer * makeBuffer(size_t size = 0);
- AsyncWebSocketMessageBuffer * makeBuffer(uint8_t * data, size_t size);
- LinkedList _buffers;
- void _cleanBuffers();
-
- AsyncWebSocketClientLinkedList getClients() const;
-};
-
-//WebServer response to authenticate the socket and detach the tcp client from the web server request
-class AsyncWebSocketResponse: public AsyncWebServerResponse {
- private:
- String _content;
- AsyncWebSocket *_server;
- public:
- AsyncWebSocketResponse(const String& key, AsyncWebSocket *server);
- void _respond(AsyncWebServerRequest *request);
- size_t _ack(AsyncWebServerRequest *request, size_t len, uint32_t time);
- bool _sourceValid() const { return true; }
-};
-
-
-#endif /* ASYNCWEBSOCKET_H_ */
diff --git a/ESP32/lib/ESPAsyncWebServer/src/AsyncWebSynchronization.h b/ESP32/lib/ESPAsyncWebServer/src/AsyncWebSynchronization.h
deleted file mode 100644
index f36c52d..0000000
--- a/ESP32/lib/ESPAsyncWebServer/src/AsyncWebSynchronization.h
+++ /dev/null
@@ -1,87 +0,0 @@
-#ifndef ASYNCWEBSYNCHRONIZATION_H_
-#define ASYNCWEBSYNCHRONIZATION_H_
-
-// Synchronisation is only available on ESP32, as the ESP8266 isn't using FreeRTOS by default
-
-#include
-
-#ifdef ESP32
-
-// This is the ESP32 version of the Sync Lock, using the FreeRTOS Semaphore
-class AsyncWebLock
-{
-private:
- SemaphoreHandle_t _lock;
- mutable void *_lockedBy;
-
-public:
- AsyncWebLock() {
- _lock = xSemaphoreCreateBinary();
- _lockedBy = NULL;
- xSemaphoreGive(_lock);
- }
-
- ~AsyncWebLock() {
- vSemaphoreDelete(_lock);
- }
-
- bool lock() const {
- extern void *pxCurrentTCB;
- if (_lockedBy != pxCurrentTCB) {
- xSemaphoreTake(_lock, portMAX_DELAY);
- _lockedBy = pxCurrentTCB;
- return true;
- }
- return false;
- }
-
- void unlock() const {
- _lockedBy = NULL;
- xSemaphoreGive(_lock);
- }
-};
-
-#else
-
-// This is the 8266 version of the Sync Lock which is currently unimplemented
-class AsyncWebLock
-{
-
-public:
- AsyncWebLock() {
- }
-
- ~AsyncWebLock() {
- }
-
- bool lock() const {
- return false;
- }
-
- void unlock() const {
- }
-};
-#endif
-
-class AsyncWebLockGuard
-{
-private:
- const AsyncWebLock *_lock;
-
-public:
- AsyncWebLockGuard(const AsyncWebLock &l) {
- if (l.lock()) {
- _lock = &l;
- } else {
- _lock = NULL;
- }
- }
-
- ~AsyncWebLockGuard() {
- if (_lock) {
- _lock->unlock();
- }
- }
-};
-
-#endif // ASYNCWEBSYNCHRONIZATION_H_
\ No newline at end of file
diff --git a/ESP32/lib/ESPAsyncWebServer/src/ESPAsyncWebServer.h b/ESP32/lib/ESPAsyncWebServer/src/ESPAsyncWebServer.h
deleted file mode 100644
index 7cd21aa..0000000
--- a/ESP32/lib/ESPAsyncWebServer/src/ESPAsyncWebServer.h
+++ /dev/null
@@ -1,471 +0,0 @@
-/*
- Asynchronous WebServer library for Espressif MCUs
-
- Copyright (c) 2016 Hristo Gochkov. All rights reserved.
- This file is part of the esp8266 core for Arduino environment.
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-*/
-#ifndef _ESPAsyncWebServer_H_
-#define _ESPAsyncWebServer_H_
-
-#include "Arduino.h"
-
-#include
-#include "FS.h"
-
-#include "StringArray.h"
-
-#ifdef ESP32
-#include
-#include
-#elif defined(ESP8266)
-#include
-#include
-#else
-#error Platform not supported
-#endif
-
-#ifdef ASYNCWEBSERVER_REGEX
-#define ASYNCWEBSERVER_REGEX_ATTRIBUTE
-#else
-#define ASYNCWEBSERVER_REGEX_ATTRIBUTE __attribute__((warning("ASYNCWEBSERVER_REGEX not defined")))
-#endif
-
-#define DEBUGF(...) //Serial.printf(__VA_ARGS__)
-
-class AsyncWebServer;
-class AsyncWebServerRequest;
-class AsyncWebServerResponse;
-class AsyncWebHeader;
-class AsyncWebParameter;
-class AsyncWebRewrite;
-class AsyncWebHandler;
-class AsyncStaticWebHandler;
-class AsyncCallbackWebHandler;
-class AsyncResponseStream;
-
-#ifndef WEBSERVER_H
-typedef enum {
- HTTP_GET = 0b00000001,
- HTTP_POST = 0b00000010,
- HTTP_DELETE = 0b00000100,
- HTTP_PUT = 0b00001000,
- HTTP_PATCH = 0b00010000,
- HTTP_HEAD = 0b00100000,
- HTTP_OPTIONS = 0b01000000,
- HTTP_ANY = 0b01111111,
-} WebRequestMethod;
-#endif
-
-//if this value is returned when asked for data, packet will not be sent and you will be asked for data again
-#define RESPONSE_TRY_AGAIN 0xFFFFFFFF
-
-typedef uint8_t WebRequestMethodComposite;
-typedef std::function ArDisconnectHandler;
-
-/*
- * PARAMETER :: Chainable object to hold GET/POST and FILE parameters
- * */
-
-class AsyncWebParameter {
- private:
- String _name;
- String _value;
- size_t _size;
- bool _isForm;
- bool _isFile;
-
- public:
-
- AsyncWebParameter(const String& name, const String& value, bool form=false, bool file=false, size_t size=0): _name(name), _value(value), _size(size), _isForm(form), _isFile(file){}
- const String& name() const { return _name; }
- const String& value() const { return _value; }
- size_t size() const { return _size; }
- bool isPost() const { return _isForm; }
- bool isFile() const { return _isFile; }
-};
-
-/*
- * HEADER :: Chainable object to hold the headers
- * */
-
-class AsyncWebHeader {
- private:
- String _name;
- String _value;
-
- public:
- AsyncWebHeader(const String& name, const String& value): _name(name), _value(value){}
- AsyncWebHeader(const String& data): _name(), _value(){
- if(!data) return;
- int index = data.indexOf(':');
- if (index < 0) return;
- _name = data.substring(0, index);
- _value = data.substring(index + 2);
- }
- ~AsyncWebHeader(){}
- const String& name() const { return _name; }
- const String& value() const { return _value; }
- String toString() const { return String(_name+": "+_value+"\r\n"); }
-};
-
-/*
- * REQUEST :: Each incoming Client is wrapped inside a Request and both live together until disconnect
- * */
-
-typedef enum { RCT_NOT_USED = -1, RCT_DEFAULT = 0, RCT_HTTP, RCT_WS, RCT_EVENT, RCT_MAX } RequestedConnectionType;
-
-typedef std::function AwsResponseFiller;
-typedef std::function AwsTemplateProcessor;
-
-class AsyncWebServerRequest {
- using File = fs::File;
- using FS = fs::FS;
- friend class AsyncWebServer;
- friend class AsyncCallbackWebHandler;
- private:
- AsyncClient* _client;
- AsyncWebServer* _server;
- AsyncWebHandler* _handler;
- AsyncWebServerResponse* _response;
- StringArray _interestingHeaders;
- ArDisconnectHandler _onDisconnectfn;
-
- String _temp;
- uint8_t _parseState;
-
- uint8_t _version;
- WebRequestMethodComposite _method;
- String _url;
- String _host;
- String _contentType;
- String _boundary;
- String _authorization;
- RequestedConnectionType _reqconntype;
- void _removeNotInterestingHeaders();
- bool _isDigest;
- bool _isMultipart;
- bool _isPlainPost;
- bool _expectingContinue;
- size_t _contentLength;
- size_t _parsedLength;
-
- LinkedList _headers;
- LinkedList _params;
- LinkedList _pathParams;
-
- uint8_t _multiParseState;
- uint8_t _boundaryPosition;
- size_t _itemStartIndex;
- size_t _itemSize;
- String _itemName;
- String _itemFilename;
- String _itemType;
- String _itemValue;
- uint8_t *_itemBuffer;
- size_t _itemBufferIndex;
- bool _itemIsFile;
-
- void _onPoll();
- void _onAck(size_t len, uint32_t time);
- void _onError(int8_t error);
- void _onTimeout(uint32_t time);
- void _onDisconnect();
- void _onData(void *buf, size_t len);
-
- void _addParam(AsyncWebParameter*);
- void _addPathParam(const char *param);
-
- bool _parseReqHead();
- bool _parseReqHeader();
- void _parseLine();
- void _parsePlainPostChar(uint8_t data);
- void _parseMultipartPostByte(uint8_t data, bool last);
- void _addGetParams(const String& params);
-
- void _handleUploadStart();
- void _handleUploadByte(uint8_t data, bool last);
- void _handleUploadEnd();
-
- public:
- File _tempFile;
- void *_tempObject;
-
- AsyncWebServerRequest(AsyncWebServer*, AsyncClient*);
- ~AsyncWebServerRequest();
-
- AsyncClient* client(){ return _client; }
- uint8_t version() const { return _version; }
- WebRequestMethodComposite method() const { return _method; }
- const String& url() const { return _url; }
- const String& host() const { return _host; }
- const String& contentType() const { return _contentType; }
- size_t contentLength() const { return _contentLength; }
- bool multipart() const { return _isMultipart; }
- const char * methodToString() const;
- const char * requestedConnTypeToString() const;
- RequestedConnectionType requestedConnType() const { return _reqconntype; }
- bool isExpectedRequestedConnType(RequestedConnectionType erct1, RequestedConnectionType erct2 = RCT_NOT_USED, RequestedConnectionType erct3 = RCT_NOT_USED);
- void onDisconnect (ArDisconnectHandler fn);
-
- //hash is the string representation of:
- // base64(user:pass) for basic or
- // user:realm:md5(user:realm:pass) for digest
- bool authenticate(const char * hash);
- bool authenticate(const char * username, const char * password, const char * realm = NULL, bool passwordIsHash = false);
- void requestAuthentication(const char * realm = NULL, bool isDigest = true);
-
- void setHandler(AsyncWebHandler *handler){ _handler = handler; }
- void addInterestingHeader(const String& name);
-
- void redirect(const String& url);
-
- void send(AsyncWebServerResponse *response);
- void send(int code, const String& contentType=String(), const String& content=String());
- void send(FS &fs, const String& path, const String& contentType=String(), bool download=false, AwsTemplateProcessor callback=nullptr);
- void send(File content, const String& path, const String& contentType=String(), bool download=false, AwsTemplateProcessor callback=nullptr);
- void send(Stream &stream, const String& contentType, size_t len, AwsTemplateProcessor callback=nullptr);
- void send(const String& contentType, size_t len, AwsResponseFiller callback, AwsTemplateProcessor templateCallback=nullptr);
- void sendChunked(const String& contentType, AwsResponseFiller callback, AwsTemplateProcessor templateCallback=nullptr);
- void send_P(int code, const String& contentType, const uint8_t * content, size_t len, AwsTemplateProcessor callback=nullptr);
- void send_P(int code, const String& contentType, PGM_P content, AwsTemplateProcessor callback=nullptr);
-
- AsyncWebServerResponse *beginResponse(int code, const String& contentType=String(), const String& content=String());
- AsyncWebServerResponse *beginResponse(FS &fs, const String& path, const String& contentType=String(), bool download=false, AwsTemplateProcessor callback=nullptr);
- AsyncWebServerResponse *beginResponse(File content, const String& path, const String& contentType=String(), bool download=false, AwsTemplateProcessor callback=nullptr);
- AsyncWebServerResponse *beginResponse(Stream &stream, const String& contentType, size_t len, AwsTemplateProcessor callback=nullptr);
- AsyncWebServerResponse *beginResponse(const String& contentType, size_t len, AwsResponseFiller callback, AwsTemplateProcessor templateCallback=nullptr);
- AsyncWebServerResponse *beginChunkedResponse(const String& contentType, AwsResponseFiller callback, AwsTemplateProcessor templateCallback=nullptr);
- AsyncResponseStream *beginResponseStream(const String& contentType, size_t bufferSize=1460);
- AsyncWebServerResponse *beginResponse_P(int code, const String& contentType, const uint8_t * content, size_t len, AwsTemplateProcessor callback=nullptr);
- AsyncWebServerResponse *beginResponse_P(int code, const String& contentType, PGM_P content, AwsTemplateProcessor callback=nullptr);
-
- size_t headers() const; // get header count
- bool hasHeader(const String& name) const; // check if header exists
- bool hasHeader(const __FlashStringHelper * data) const; // check if header exists
-
- AsyncWebHeader* getHeader(const String& name) const;
- AsyncWebHeader* getHeader(const __FlashStringHelper * data) const;
- AsyncWebHeader* getHeader(size_t num) const;
-
- size_t params() const; // get arguments count
- bool hasParam(const String& name, bool post=false, bool file=false) const;
- bool hasParam(const __FlashStringHelper * data, bool post=false, bool file=false) const;
-
- AsyncWebParameter* getParam(const String& name, bool post=false, bool file=false) const;
- AsyncWebParameter* getParam(const __FlashStringHelper * data, bool post, bool file) const;
- AsyncWebParameter* getParam(size_t num) const;
-
- size_t args() const { return params(); } // get arguments count
- const String& arg(const String& name) const; // get request argument value by name
- const String& arg(const __FlashStringHelper * data) const; // get request argument value by F(name)
- const String& arg(size_t i) const; // get request argument value by number
- const String& argName(size_t i) const; // get request argument name by number
- bool hasArg(const char* name) const; // check if argument exists
- bool hasArg(const __FlashStringHelper * data) const; // check if F(argument) exists
-
- const String& ASYNCWEBSERVER_REGEX_ATTRIBUTE pathArg(size_t i) const;
-
- const String& header(const char* name) const;// get request header value by name
- const String& header(const __FlashStringHelper * data) const;// get request header value by F(name)
- const String& header(size_t i) const; // get request header value by number
- const String& headerName(size_t i) const; // get request header name by number
- String urlDecode(const String& text) const;
-};
-
-/*
- * FILTER :: Callback to filter AsyncWebRewrite and AsyncWebHandler (done by the Server)
- * */
-
-typedef std::function ArRequestFilterFunction;
-
-bool ON_STA_FILTER(AsyncWebServerRequest *request);
-
-bool ON_AP_FILTER(AsyncWebServerRequest *request);
-
-/*
- * REWRITE :: One instance can be handle any Request (done by the Server)
- * */
-
-class AsyncWebRewrite {
- protected:
- String _from;
- String _toUrl;
- String _params;
- ArRequestFilterFunction _filter;
- public:
- AsyncWebRewrite(const char* from, const char* to): _from(from), _toUrl(to), _params(String()), _filter(NULL){
- int index = _toUrl.indexOf('?');
- if (index > 0) {
- _params = _toUrl.substring(index +1);
- _toUrl = _toUrl.substring(0, index);
- }
- }
- virtual ~AsyncWebRewrite(){}
- AsyncWebRewrite& setFilter(ArRequestFilterFunction fn) { _filter = fn; return *this; }
- bool filter(AsyncWebServerRequest *request) const { return _filter == NULL || _filter(request); }
- const String& from(void) const { return _from; }
- const String& toUrl(void) const { return _toUrl; }
- const String& params(void) const { return _params; }
- virtual bool match(AsyncWebServerRequest *request) { return from() == request->url() && filter(request); }
-};
-
-/*
- * HANDLER :: One instance can be attached to any Request (done by the Server)
- * */
-
-class AsyncWebHandler {
- protected:
- ArRequestFilterFunction _filter;
- String _username;
- String _password;
- public:
- AsyncWebHandler():_username(""), _password(""){}
- AsyncWebHandler& setFilter(ArRequestFilterFunction fn) { _filter = fn; return *this; }
- AsyncWebHandler& setAuthentication(const char *username, const char *password){ _username = String(username);_password = String(password); return *this; };
- bool filter(AsyncWebServerRequest *request){ return _filter == NULL || _filter(request); }
- virtual ~AsyncWebHandler(){}
- virtual bool canHandle(AsyncWebServerRequest *request __attribute__((unused))){
- return false;
- }
- virtual void handleRequest(AsyncWebServerRequest *request __attribute__((unused))){}
- virtual void handleUpload(AsyncWebServerRequest *request __attribute__((unused)), const String& filename __attribute__((unused)), size_t index __attribute__((unused)), uint8_t *data __attribute__((unused)), size_t len __attribute__((unused)), bool final __attribute__((unused))){}
- virtual void handleBody(AsyncWebServerRequest *request __attribute__((unused)), uint8_t *data __attribute__((unused)), size_t len __attribute__((unused)), size_t index __attribute__((unused)), size_t total __attribute__((unused))){}
- virtual bool isRequestHandlerTrivial(){return true;}
-};
-
-/*
- * RESPONSE :: One instance is created for each Request (attached by the Handler)
- * */
-
-typedef enum {
- RESPONSE_SETUP, RESPONSE_HEADERS, RESPONSE_CONTENT, RESPONSE_WAIT_ACK, RESPONSE_END, RESPONSE_FAILED
-} WebResponseState;
-
-class AsyncWebServerResponse {
- protected:
- int _code;
- LinkedList _headers;
- String _contentType;
- size_t _contentLength;
- bool _sendContentLength;
- bool _chunked;
- size_t _headLength;
- size_t _sentLength;
- size_t _ackedLength;
- size_t _writtenLength;
- WebResponseState _state;
- const char* _responseCodeToString(int code);
-
- public:
- AsyncWebServerResponse();
- virtual ~AsyncWebServerResponse();
- virtual void setCode(int code);
- virtual void setContentLength(size_t len);
- virtual void setContentType(const String& type);
- virtual void addHeader(const String& name, const String& value);
- virtual String _assembleHead(uint8_t version);
- virtual bool _started() const;
- virtual bool _finished() const;
- virtual bool _failed() const;
- virtual bool _sourceValid() const;
- virtual void _respond(AsyncWebServerRequest *request);
- virtual size_t _ack(AsyncWebServerRequest *request, size_t len, uint32_t time);
-};
-
-/*
- * SERVER :: One instance
- * */
-
-typedef std::function ArRequestHandlerFunction;
-typedef std::function ArUploadHandlerFunction;
-typedef std::function ArBodyHandlerFunction;
-
-class AsyncWebServer {
- protected:
- AsyncServer _server;
- LinkedList _rewrites;
- LinkedList _handlers;
- AsyncCallbackWebHandler* _catchAllHandler;
-
- public:
- AsyncWebServer(uint16_t port);
- ~AsyncWebServer();
-
- void begin();
- void end();
-
-#if ASYNC_TCP_SSL_ENABLED
- void onSslFileRequest(AcSSlFileHandler cb, void* arg);
- void beginSecure(const char *cert, const char *private_key_file, const char *password);
-#endif
-
- AsyncWebRewrite& addRewrite(AsyncWebRewrite* rewrite);
- bool removeRewrite(AsyncWebRewrite* rewrite);
- AsyncWebRewrite& rewrite(const char* from, const char* to);
-
- AsyncWebHandler& addHandler(AsyncWebHandler* handler);
- bool removeHandler(AsyncWebHandler* handler);
-
- AsyncCallbackWebHandler& on(const char* uri, ArRequestHandlerFunction onRequest);
- AsyncCallbackWebHandler& on(const char* uri, WebRequestMethodComposite method, ArRequestHandlerFunction onRequest);
- AsyncCallbackWebHandler& on(const char* uri, WebRequestMethodComposite method, ArRequestHandlerFunction onRequest, ArUploadHandlerFunction onUpload);
- AsyncCallbackWebHandler& on(const char* uri, WebRequestMethodComposite method, ArRequestHandlerFunction onRequest, ArUploadHandlerFunction onUpload, ArBodyHandlerFunction onBody);
-
- AsyncStaticWebHandler& serveStatic(const char* uri, fs::FS& fs, const char* path, const char* cache_control = NULL);
-
- void onNotFound(ArRequestHandlerFunction fn); //called when handler is not assigned
- void onFileUpload(ArUploadHandlerFunction fn); //handle file uploads
- void onRequestBody(ArBodyHandlerFunction fn); //handle posts with plain body content (JSON often transmitted this way as a request)
-
- void reset(); //remove all writers and handlers, with onNotFound/onFileUpload/onRequestBody
-
- void _handleDisconnect(AsyncWebServerRequest *request);
- void _attachHandler(AsyncWebServerRequest *request);
- void _rewriteRequest(AsyncWebServerRequest *request);
-};
-
-class DefaultHeaders {
- using headers_t = LinkedList;
- headers_t _headers;
-
- DefaultHeaders()
- :_headers(headers_t([](AsyncWebHeader *h){ delete h; }))
- {}
-public:
- using ConstIterator = headers_t::ConstIterator;
-
- void addHeader(const String& name, const String& value){
- _headers.add(new AsyncWebHeader(name, value));
- }
-
- ConstIterator begin() const { return _headers.begin(); }
- ConstIterator end() const { return _headers.end(); }
-
- DefaultHeaders(DefaultHeaders const &) = delete;
- DefaultHeaders &operator=(DefaultHeaders const &) = delete;
- static DefaultHeaders &Instance() {
- static DefaultHeaders instance;
- return instance;
- }
-};
-
-#include "WebResponseImpl.h"
-#include "WebHandlerImpl.h"
-#include "AsyncWebSocket.h"
-#include "AsyncEventSource.h"
-
-#endif /* _AsyncWebServer_H_ */
diff --git a/ESP32/lib/ESPAsyncWebServer/src/SPIFFSEditor.cpp b/ESP32/lib/ESPAsyncWebServer/src/SPIFFSEditor.cpp
deleted file mode 100644
index a84fa87..0000000
--- a/ESP32/lib/ESPAsyncWebServer/src/SPIFFSEditor.cpp
+++ /dev/null
@@ -1,544 +0,0 @@
-#include "SPIFFSEditor.h"
-#include
-
-//File: edit.htm.gz, Size: 4151
-#define edit_htm_gz_len 4151
-const uint8_t edit_htm_gz[] PROGMEM = {
- 0x1F, 0x8B, 0x08, 0x08, 0xB8, 0x94, 0xB1, 0x59, 0x00, 0x03, 0x65, 0x64, 0x69, 0x74, 0x2E, 0x68,
- 0x74, 0x6D, 0x00, 0xB5, 0x3A, 0x0B, 0x7B, 0xDA, 0xB8, 0xB2, 0x7F, 0xC5, 0x71, 0xCF, 0x66, 0xED,
- 0x83, 0x31, 0x90, 0xA4, 0xD9, 0xD6, 0xC4, 0xC9, 0x42, 0x92, 0x36, 0x6D, 0xF3, 0x6A, 0x80, 0xB6,
- 0x69, 0x4F, 0xEE, 0x7E, 0xC2, 0x16, 0xA0, 0xC6, 0x96, 0x5D, 0x5B, 0x0E, 0x49, 0x59, 0xFE, 0xFB,
- 0x9D, 0x91, 0x6C, 0xB0, 0x09, 0x69, 0x77, 0xCF, 0xBD, 0xBB, 0xDD, 0x2D, 0x92, 0x46, 0x33, 0x9A,
- 0x19, 0xCD, 0x53, 0xDE, 0xBD, 0x8D, 0xA3, 0x8B, 0xC3, 0xFE, 0xF5, 0xE5, 0xB1, 0x36, 0x11, 0x61,
- 0xB0, 0xBF, 0x87, 0x7F, 0x6B, 0x01, 0xE1, 0x63, 0x97, 0xF2, 0xFD, 0x3D, 0xC1, 0x44, 0x40, 0xF7,
- 0x8F, 0x7B, 0x97, 0xDA, 0xB1, 0xCF, 0x44, 0x94, 0xEC, 0x35, 0xD4, 0xCA, 0x5E, 0x2A, 0x1E, 0x02,
- 0xAA, 0x85, 0xD4, 0x67, 0xC4, 0x4D, 0xBD, 0x84, 0xC2, 0x66, 0xDB, 0x0B, 0x67, 0xDF, 0xEB, 0x8C,
- 0xFB, 0xF4, 0xDE, 0xD9, 0x6E, 0x36, 0xDB, 0x71, 0x94, 0x32, 0xC1, 0x22, 0xEE, 0x90, 0x61, 0x1A,
- 0x05, 0x99, 0xA0, 0xED, 0x80, 0x8E, 0x84, 0xF3, 0x3C, 0xBE, 0x6F, 0x0F, 0xA3, 0xC4, 0xA7, 0x89,
- 0xD3, 0x8A, 0xEF, 0x35, 0x00, 0x31, 0x5F, 0x7B, 0xB6, 0xB3, 0xB3, 0xD3, 0x1E, 0x12, 0xEF, 0x76,
- 0x9C, 0x44, 0x19, 0xF7, 0xEB, 0x5E, 0x14, 0x44, 0x89, 0xF3, 0x6C, 0xF4, 0x1C, 0xFF, 0xB4, 0x7D,
- 0x96, 0xC6, 0x01, 0x79, 0x70, 0x78, 0xC4, 0x29, 0xE0, 0xDE, 0xD7, 0xD3, 0x09, 0xF1, 0xA3, 0xA9,
- 0xD3, 0xD4, 0x9A, 0x5A, 0xAB, 0x09, 0x44, 0x92, 0xF1, 0x90, 0x18, 0x4D, 0x0B, 0xFF, 0xD8, 0x3B,
- 0x66, 0x7B, 0x14, 0x71, 0x51, 0x4F, 0xD9, 0x77, 0xEA, 0xB4, 0xB6, 0xE0, 0x34, 0x39, 0x1D, 0x91,
- 0x90, 0x05, 0x0F, 0x4E, 0x4A, 0x78, 0x5A, 0x4F, 0x69, 0xC2, 0x46, 0x6A, 0x79, 0x4A, 0xD9, 0x78,
- 0x22, 0x9C, 0xDF, 0x9A, 0xCD, 0x39, 0xF0, 0xAF, 0x65, 0xC1, 0x2C, 0x60, 0x29, 0x20, 0xA3, 0x78,
- 0xEA, 0x3C, 0x11, 0xC5, 0x4E, 0x53, 0xB1, 0xDE, 0x6C, 0x87, 0x24, 0x19, 0x33, 0x0E, 0x83, 0x98,
- 0xF8, 0x3E, 0xE3, 0x63, 0x47, 0xA1, 0x05, 0x6C, 0xB6, 0x90, 0x36, 0xA1, 0x01, 0x11, 0xEC, 0x8E,
- 0xB6, 0x43, 0xC6, 0xEB, 0x53, 0xE6, 0x8B, 0x89, 0xB3, 0x0B, 0x3C, 0xB6, 0xBD, 0x2C, 0x49, 0x41,
- 0xA6, 0x38, 0x62, 0x5C, 0xD0, 0x44, 0xA2, 0xA5, 0x31, 0xE1, 0xB3, 0x5C, 0x54, 0x54, 0x40, 0x21,
- 0x27, 0xE3, 0x01, 0xE3, 0xB4, 0x3E, 0x0C, 0x22, 0xEF, 0x76, 0x71, 0xD2, 0x6E, 0x7C, 0x9F, 0x9F,
- 0xE5, 0x4C, 0xA2, 0x3B, 0x9A, 0xCC, 0x96, 0xEA, 0x92, 0xD8, 0x15, 0x60, 0x85, 0x34, 0xA5, 0x74,
- 0x6E, 0x8B, 0xBB, 0x0C, 0xA0, 0x96, 0xFC, 0x05, 0x29, 0x17, 0xFC, 0x2F, 0x45, 0x5A, 0x11, 0x5C,
- 0xA1, 0x30, 0x1E, 0x67, 0x62, 0xF6, 0xF8, 0x2A, 0xA3, 0x98, 0x78, 0x4C, 0x3C, 0xA0, 0xFC, 0xB0,
- 0x6D, 0x86, 0xBA, 0x04, 0xAC, 0x24, 0x24, 0x81, 0x86, 0x3A, 0xD7, 0x3E, 0xD0, 0xC4, 0x27, 0x9C,
- 0x58, 0x9D, 0x84, 0x91, 0xC0, 0xEA, 0x2D, 0xB5, 0x5E, 0x0F, 0xA3, 0xEF, 0xF5, 0x0C, 0xC6, 0x30,
- 0x0F, 0xA8, 0x27, 0x94, 0x92, 0xE1, 0x1E, 0x86, 0xB7, 0x4C, 0x3C, 0x06, 0x3C, 0x5A, 0x28, 0xA9,
- 0x4B, 0x2A, 0x69, 0xA2, 0x2E, 0xB0, 0x25, 0xD5, 0x83, 0x1C, 0x4B, 0xC9, 0x95, 0x50, 0xF5, 0x61,
- 0x24, 0x44, 0x14, 0x4A, 0x93, 0x5B, 0x08, 0xAC, 0x49, 0xAB, 0x79, 0xF1, 0xE8, 0x46, 0xD6, 0x6B,
- 0xBF, 0x44, 0xBE, 0x0D, 0x7A, 0x15, 0xCC, 0x23, 0x41, 0x9D, 0x04, 0x6C, 0xCC, 0x9D, 0x90, 0xF9,
- 0x7E, 0x40, 0x4B, 0x56, 0xEB, 0x64, 0x49, 0x60, 0xF8, 0x44, 0x10, 0x87, 0x85, 0x64, 0x4C, 0x1B,
- 0x31, 0x1F, 0x03, 0x34, 0xA5, 0xBB, 0x3B, 0x16, 0xFB, 0xD0, 0xBD, 0xB8, 0x9A, 0x36, 0xDF, 0xBD,
- 0x1E, 0x47, 0x1D, 0xF8, 0xE7, 0xBC, 0x37, 0x98, 0x1C, 0x0F, 0xC6, 0x30, 0xEA, 0xE2, 0xB4, 0xF3,
- 0xFE, 0xB0, 0xF3, 0x1E, 0x7E, 0x0E, 0x5B, 0xB5, 0xAF, 0xA3, 0x6F, 0xB8, 0xD0, 0x7D, 0xED, 0x77,
- 0xFB, 0x83, 0xE3, 0x4E, 0xE7, 0x5D, 0xE3, 0xCD, 0xF9, 0xF4, 0xE3, 0xBB, 0x5D, 0x04, 0x77, 0x83,
- 0xE6, 0xD5, 0x87, 0x49, 0x73, 0xB0, 0xF5, 0x32, 0xF4, 0x4F, 0xFC, 0x89, 0x17, 0x0E, 0x3A, 0xEF,
- 0x3F, 0x5E, 0xDD, 0x5D, 0x87, 0x83, 0x71, 0xEF, 0x63, 0x6B, 0xF2, 0x79, 0xEB, 0x43, 0xEF, 0xF3,
- 0xC7, 0x57, 0xB7, 0xF4, 0xD3, 0xC9, 0xDB, 0xCF, 0xFD, 0x29, 0x20, 0x1C, 0x45, 0xBD, 0xC1, 0x55,
- 0xF7, 0x43, 0x77, 0xFC, 0xB9, 0xEB, 0x1D, 0xDF, 0x0F, 0x83, 0xF3, 0xEE, 0xEB, 0xCE, 0xB0, 0xB3,
- 0xE5, 0x51, 0x3A, 0xEE, 0x5F, 0x75, 0xB3, 0x37, 0xEF, 0x2E, 0xC6, 0x8C, 0x4D, 0x7A, 0x9F, 0xCF,
- 0xFB, 0xDE, 0xE1, 0xF3, 0xD3, 0xC1, 0x49, 0x87, 0x4D, 0xCE, 0xDF, 0x5E, 0x35, 0x6F, 0x5F, 0xBF,
- 0x3B, 0x3C, 0xF2, 0xAE, 0xDF, 0x5E, 0xEF, 0x1E, 0x6D, 0x37, 0x7E, 0xFB, 0xED, 0xCC, 0xBF, 0x60,
- 0xBC, 0x7F, 0xF7, 0xBD, 0x33, 0x3E, 0x9C, 0xBE, 0x78, 0x48, 0xFB, 0x93, 0x37, 0x77, 0xBC, 0xF1,
- 0x21, 0xFA, 0xFA, 0xE6, 0xE1, 0x0C, 0xFE, 0xBB, 0xBC, 0xAC, 0x0D, 0x7B, 0xAD, 0x74, 0xF0, 0xFE,
- 0xCD, 0x87, 0xAD, 0xF4, 0xE5, 0xF3, 0xB8, 0x7B, 0x74, 0x74, 0x17, 0x0E, 0x2F, 0x1B, 0xA1, 0x7F,
- 0x3B, 0x12, 0x2F, 0xB6, 0x45, 0x7C, 0x3D, 0xCE, 0x3E, 0x7F, 0x7B, 0xFE, 0x76, 0xD2, 0xB8, 0xA0,
- 0xE4, 0x7A, 0x52, 0x7B, 0xF8, 0xFE, 0xF0, 0x62, 0xD2, 0x3F, 0xB9, 0x3B, 0x0F, 0xC8, 0xFD, 0xF9,
- 0xB9, 0xF7, 0x3D, 0xAC, 0x05, 0xE4, 0xE5, 0x45, 0x3F, 0x20, 0x49, 0x6B, 0xE0, 0x77, 0x1A, 0xB5,
- 0xC3, 0xAD, 0xCE, 0x8E, 0x48, 0xAE, 0x0E, 0xF9, 0xD1, 0xF6, 0xD7, 0xDE, 0x8B, 0x6E, 0xB7, 0x15,
- 0x0D, 0xBF, 0x6D, 0xBD, 0xBE, 0xDD, 0x7D, 0x3D, 0xD8, 0x7D, 0x3F, 0x7C, 0xDF, 0xE9, 0xED, 0x74,
- 0x07, 0xE4, 0xBA, 0xF7, 0xBE, 0x33, 0xDA, 0x19, 0x4E, 0x26, 0xEF, 0xDE, 0xF5, 0x5F, 0xF9, 0x9D,
- 0xEF, 0x49, 0xE7, 0x62, 0xDA, 0xB9, 0x3F, 0x1E, 0x74, 0x4E, 0x6A, 0xEF, 0x8E, 0xCF, 0x9A, 0xAD,
- 0xDE, 0xF5, 0xF6, 0xF8, 0x6C, 0x77, 0xDA, 0x4D, 0x8F, 0x3B, 0xEF, 0xBB, 0xCD, 0xF1, 0xDB, 0x5A,
- 0x48, 0x3E, 0x47, 0x87, 0xDB, 0xE3, 0x37, 0xBB, 0xEC, 0xF2, 0x9A, 0x74, 0xDE, 0x74, 0xDF, 0xA6,
- 0xEC, 0x2A, 0x3C, 0x19, 0x34, 0x3B, 0x9D, 0xD3, 0x0B, 0xFA, 0xEA, 0x70, 0x9B, 0xBC, 0xDB, 0xF2,
- 0x3E, 0x82, 0xFE, 0x07, 0x9F, 0xE8, 0x6F, 0xB5, 0xCE, 0xF4, 0xA2, 0x19, 0x78, 0x2F, 0x69, 0xFF,
- 0xE4, 0xBA, 0x2F, 0x6F, 0xE7, 0x38, 0x78, 0xD5, 0xBF, 0xED, 0x65, 0xEF, 0xC3, 0xC3, 0x43, 0x53,
- 0xE3, 0x51, 0x3D, 0xA1, 0x31, 0x25, 0xA2, 0x1C, 0xAE, 0x16, 0xFE, 0x01, 0xB6, 0xB5, 0xB4, 0xC2,
- 0xDC, 0x4F, 0x05, 0xBD, 0x17, 0x75, 0x9F, 0x7A, 0x51, 0x42, 0xE4, 0x1E, 0x40, 0xA0, 0x09, 0x9A,
- 0xD8, 0xFC, 0x77, 0x19, 0x3F, 0x35, 0x15, 0x3F, 0x35, 0xC2, 0x7D, 0xCD, 0x28, 0x1C, 0x01, 0x83,
- 0x87, 0x4F, 0xEF, 0x98, 0x47, 0xEB, 0x31, 0xBB, 0xA7, 0x41, 0x5D, 0x22, 0x3B, 0x4D, 0x73, 0x26,
- 0xFD, 0xAD, 0xD8, 0x46, 0x38, 0x98, 0x9A, 0xA4, 0x5A, 0x2C, 0xF8, 0x5F, 0x89, 0x47, 0x21, 0xB0,
- 0x81, 0xCB, 0x84, 0xF8, 0xAB, 0x7C, 0x27, 0x4A, 0xEA, 0xC3, 0x6C, 0x3C, 0x62, 0xF7, 0xE0, 0xD0,
- 0x23, 0xC6, 0x99, 0xA0, 0x5A, 0x2B, 0x9D, 0xFF, 0x5E, 0x90, 0xB9, 0xA5, 0x0F, 0xA3, 0x84, 0x84,
- 0x34, 0xD5, 0xFE, 0x22, 0x99, 0xD9, 0x28, 0x89, 0xC2, 0x65, 0x10, 0x99, 0x8B, 0xA8, 0x34, 0x99,
- 0xCF, 0x9F, 0x65, 0x71, 0x10, 0x11, 0x10, 0x73, 0x4D, 0xE4, 0x50, 0xF1, 0x34, 0x91, 0x6E, 0xB5,
- 0x88, 0xAB, 0xB9, 0x9B, 0x6D, 0xA1, 0x5B, 0x96, 0xDD, 0x7A, 0x6B, 0x67, 0xE9, 0xBA, 0x75, 0xB9,
- 0x17, 0xE3, 0xFD, 0x9A, 0x4C, 0x81, 0xF1, 0xA0, 0x14, 0xEE, 0x9E, 0x09, 0x50, 0xE9, 0x13, 0x87,
- 0xCB, 0x43, 0xF2, 0xC8, 0xB0, 0x60, 0x40, 0x05, 0xEA, 0x96, 0x8C, 0xD4, 0x85, 0x24, 0xB0, 0x6F,
- 0xFE, 0x8C, 0xCA, 0xBC, 0x67, 0x3D, 0x8B, 0x13, 0xB8, 0x0D, 0x3A, 0xFD, 0x11, 0xCD, 0x42, 0xA6,
- 0x2A, 0x6D, 0x45, 0x53, 0x65, 0xBC, 0x5C, 0x84, 0x65, 0xDA, 0x93, 0xBC, 0x16, 0xA4, 0x1F, 0x4B,
- 0x05, 0xE0, 0x05, 0x37, 0xCF, 0x91, 0x9B, 0x1F, 0x6A, 0x75, 0x7B, 0xF7, 0x97, 0x9C, 0x87, 0x9D,
- 0xE6, 0x2F, 0x73, 0x3B, 0xDF, 0x5B, 0xA4, 0xE4, 0x56, 0x13, 0xFE, 0x29, 0x32, 0xEF, 0x8B, 0x25,
- 0x0B, 0xC3, 0xE7, 0xF8, 0xA7, 0x60, 0x10, 0xE9, 0x94, 0x80, 0xDB, 0x3B, 0x2F, 0x5F, 0xF8, 0xC3,
- 0x02, 0x98, 0x0B, 0xF6, 0x24, 0x3C, 0x21, 0x3E, 0xCB, 0x52, 0xE7, 0x79, 0xF3, 0x97, 0x5C, 0x9F,
- 0x5B, 0x3B, 0x28, 0xFB, 0xE2, 0x2E, 0x71, 0xB2, 0xB4, 0xD8, 0x34, 0x66, 0x5C, 0xDB, 0x4A, 0x35,
- 0xBC, 0x6F, 0x92, 0x2C, 0x0C, 0xB3, 0x92, 0xED, 0xE7, 0xBF, 0x2F, 0x4D, 0x13, 0xF7, 0xCF, 0x9A,
- 0xBF, 0xCC, 0x44, 0x02, 0xD9, 0x64, 0x04, 0xB9, 0xC6, 0x49, 0x22, 0x41, 0x04, 0x35, 0x9A, 0xE6,
- 0x1C, 0x84, 0x5B, 0x03, 0xD8, 0xDE, 0x6D, 0xFA, 0x74, 0x6C, 0xCE, 0xE7, 0x7B, 0x0D, 0x99, 0xD7,
- 0xA0, 0x6C, 0xF1, 0x12, 0x16, 0x8B, 0xFD, 0x51, 0xC6, 0x3D, 0xE4, 0x41, 0x1B, 0x53, 0x83, 0x9A,
- 0xB3, 0x84, 0x8A, 0x2C, 0xE1, 0x9A, 0x1F, 0x79, 0x19, 0x1A, 0xBB, 0x3D, 0xA6, 0xE2, 0x58, 0xD9,
- 0x7D, 0xF7, 0xE1, 0x8D, 0x0F, 0x3B, 0xE6, 0x0B, 0x04, 0x6F, 0x2D, 0x02, 0x38, 0x30, 0x9C, 0x97,
- 0xE3, 0x54, 0xF6, 0x43, 0x82, 0x01, 0x22, 0xEF, 0xE8, 0x83, 0x41, 0x2D, 0xB1, 0x40, 0xA4, 0x36,
- 0xAE, 0x1B, 0xC5, 0x2E, 0x80, 0x71, 0x73, 0x76, 0x07, 0x4A, 0x20, 0x2E, 0xFD, 0x22, 0x6E, 0x2C,
- 0xE6, 0x72, 0xF8, 0x69, 0xE7, 0xBB, 0xC9, 0x1E, 0x3B, 0xA8, 0xB7, 0x1C, 0xB2, 0xCF, 0x0E, 0x5A,
- 0xE0, 0x5E, 0x65, 0x6E, 0xE4, 0xB9, 0xAF, 0x58, 0x40, 0x07, 0xB9, 0xC3, 0xE1, 0x31, 0x48, 0x6C,
- 0xB1, 0x85, 0x28, 0xE2, 0x5B, 0xCD, 0xE6, 0x86, 0x4B, 0x0F, 0x48, 0x00, 0x39, 0xCC, 0xD0, 0x8F,
- 0xAF, 0xAE, 0x2E, 0xAE, 0xBE, 0xE8, 0x35, 0x5A, 0xD3, 0x6F, 0x1C, 0x4D, 0xAF, 0x71, 0xD3, 0x11,
- 0x76, 0x42, 0x47, 0x09, 0x4D, 0x27, 0x97, 0x44, 0x4C, 0x8C, 0xD4, 0xBE, 0x23, 0x41, 0x56, 0x16,
- 0x84, 0xA1, 0xDC, 0xC8, 0xA2, 0x70, 0x39, 0x9D, 0x6A, 0xAF, 0x40, 0xCD, 0x47, 0x90, 0xEA, 0xDA,
- 0xC2, 0x26, 0x71, 0x4C, 0xB9, 0x6F, 0xE8, 0x31, 0x20, 0xEA, 0x16, 0x35, 0xAD, 0x84, 0x7E, 0xCB,
- 0x68, 0x2A, 0x52, 0x1B, 0x2C, 0xD7, 0xD0, 0x2F, 0x07, 0x7D, 0xDD, 0xD2, 0x1B, 0xE8, 0x47, 0x3A,
- 0xF0, 0x46, 0xCC, 0x39, 0x52, 0x89, 0x5C, 0xD0, 0xA4, 0x3E, 0xCC, 0xC0, 0xA0, 0xB8, 0x6E, 0xB6,
- 0x23, 0x9B, 0x71, 0x4E, 0x93, 0x93, 0xFE, 0xD9, 0xA9, 0xAB, 0x5F, 0x29, 0x46, 0xB4, 0x53, 0x28,
- 0x48, 0x74, 0x4B, 0x5E, 0x51, 0x7E, 0xC8, 0xE1, 0x84, 0x05, 0xBE, 0x11, 0x99, 0x6D, 0x24, 0xE1,
- 0x49, 0x12, 0xB2, 0x40, 0x01, 0x0A, 0x9E, 0x2D, 0x1E, 0x62, 0xEA, 0xEA, 0x23, 0x50, 0x86, 0x6E,
- 0x79, 0x76, 0x98, 0x05, 0x82, 0xC5, 0x01, 0x75, 0x37, 0x5A, 0x30, 0xE3, 0x60, 0x41, 0xAE, 0x8E,
- 0xB9, 0x19, 0x61, 0xCC, 0x77, 0x75, 0x15, 0xA1, 0xF2, 0xB8, 0xB6, 0xEE, 0x14, 0x4F, 0x9D, 0x92,
- 0x56, 0x4E, 0x49, 0xCB, 0xB8, 0x4A, 0xE0, 0x34, 0x3F, 0x18, 0xC3, 0x3C, 0xCE, 0xD4, 0x51, 0x05,
- 0xCC, 0xA7, 0x23, 0x02, 0x9C, 0x7C, 0x40, 0x6D, 0xBA, 0x7A, 0x63, 0xDD, 0x41, 0xA9, 0x3A, 0xC8,
- 0xAF, 0x6A, 0xC4, 0x2F, 0x6B, 0x44, 0xDD, 0xEE, 0x3A, 0x64, 0x5F, 0x21, 0x07, 0x55, 0xE4, 0xA0,
- 0x8C, 0x7C, 0x28, 0x8D, 0x64, 0x1D, 0x72, 0xA0, 0x90, 0x93, 0x8A, 0x88, 0x89, 0x14, 0x51, 0x85,
- 0xBD, 0x3A, 0x6A, 0x13, 0x05, 0xD2, 0xAD, 0xA4, 0x22, 0x66, 0x62, 0x83, 0x97, 0x92, 0x61, 0x40,
- 0x7D, 0x77, 0xA3, 0x09, 0x33, 0x2C, 0xB6, 0xDD, 0xAD, 0xE6, 0x9A, 0x33, 0x12, 0x75, 0x46, 0x56,
- 0x65, 0x30, 0x2B, 0x33, 0xA8, 0xF5, 0xC8, 0x1D, 0xD5, 0xD6, 0x31, 0x98, 0x99, 0x56, 0x60, 0x47,
- 0xDC, 0x0B, 0x98, 0x77, 0xEB, 0x2E, 0xBD, 0xC5, 0x9C, 0xB1, 0x85, 0x85, 0x5A, 0x5C, 0x06, 0xBA,
- 0x01, 0x94, 0x5E, 0x8B, 0xA5, 0x7C, 0x80, 0xFA, 0x9E, 0x5B, 0xD9, 0x5A, 0x02, 0xDC, 0xA6, 0xF7,
- 0xD4, 0x3B, 0x8C, 0xC2, 0x90, 0xA0, 0xED, 0xA6, 0xC0, 0x41, 0x3E, 0xD1, 0xCD, 0xB9, 0x15, 0xAD,
- 0xC5, 0x79, 0xC2, 0x45, 0x2C, 0x7F, 0x3D, 0x8B, 0x23, 0x03, 0x5C, 0xCE, 0xF5, 0x6C, 0xD4, 0x61,
- 0x6A, 0x83, 0x1E, 0xC7, 0x62, 0xF2, 0x13, 0x17, 0x2A, 0x0C, 0x54, 0xA2, 0x7C, 0x69, 0xDE, 0x58,
- 0x0B, 0x91, 0x56, 0x7C, 0xEA, 0xA2, 0xB7, 0xE2, 0x54, 0xA8, 0xBC, 0x8A, 0x5D, 0x9A, 0x4B, 0x1D,
- 0x94, 0x61, 0xB9, 0xBD, 0x2F, 0xA0, 0xFA, 0x7C, 0x0E, 0xE7, 0x01, 0xFF, 0x13, 0x68, 0xF9, 0xE8,
- 0x5F, 0x17, 0x60, 0xC9, 0xA3, 0x34, 0x78, 0x8B, 0xBB, 0x0D, 0xE3, 0xC0, 0xF9, 0x8F, 0x6D, 0x7C,
- 0xF9, 0x1F, 0xFB, 0xA6, 0x66, 0x9A, 0x07, 0xFF, 0x6A, 0x48, 0x0D, 0x1B, 0xC2, 0xFC, 0xD2, 0xBA,
- 0xB1, 0x08, 0x80, 0xED, 0x7F, 0x9B, 0xFF, 0xB1, 0x25, 0xB8, 0x02, 0x6B, 0xDF, 0x45, 0x90, 0x49,
- 0xF0, 0x24, 0x34, 0xB0, 0x68, 0xA4, 0x91, 0xCD, 0x4D, 0x43, 0xB8, 0xA4, 0x72, 0x8D, 0x35, 0x51,
- 0xD3, 0x6D, 0x88, 0x53, 0x50, 0x5B, 0xAC, 0x04, 0xBF, 0x3E, 0x24, 0x7A, 0x15, 0x5B, 0x17, 0x00,
- 0xC9, 0x3D, 0xCA, 0x0C, 0x3D, 0x22, 0x97, 0x52, 0xCB, 0x0C, 0x02, 0x42, 0xA7, 0x89, 0xE7, 0x2A,
- 0xAD, 0x1D, 0x14, 0x30, 0x17, 0xA2, 0xE0, 0xBC, 0x1C, 0x2D, 0x15, 0xEA, 0xAA, 0xFD, 0x17, 0x0A,
- 0xA3, 0xD6, 0x12, 0x8A, 0x04, 0x31, 0xAD, 0xD8, 0x79, 0xC6, 0x72, 0x75, 0x4C, 0x59, 0xBA, 0x35,
- 0x59, 0x5D, 0x96, 0xAD, 0x04, 0xAE, 0x2F, 0x8D, 0xFE, 0xD7, 0x3D, 0x16, 0x8E, 0xB5, 0x12, 0x3F,
- 0xF8, 0x97, 0xFB, 0x2B, 0x46, 0xE4, 0xCD, 0x3F, 0xBC, 0x21, 0x70, 0x05, 0xA6, 0x41, 0x6D, 0x1E,
- 0x4D, 0x0D, 0xB3, 0xF6, 0xAB, 0xAE, 0x49, 0x8A, 0xAE, 0x1E, 0x92, 0xFB, 0xBC, 0xA7, 0xC4, 0x8C,
- 0xD7, 0xD6, 0x70, 0x5E, 0xB4, 0x28, 0xF9, 0x82, 0xEC, 0xE6, 0x48, 0x26, 0xA2, 0xB6, 0x56, 0x64,
- 0x52, 0xD5, 0xCA, 0xE8, 0x5A, 0x63, 0xFF, 0xD7, 0x4A, 0x40, 0xB7, 0x98, 0xBA, 0x4E, 0x15, 0x8C,
- 0xB3, 0x00, 0x1C, 0x93, 0x3E, 0x1D, 0x69, 0x03, 0x26, 0x03, 0x75, 0x35, 0x46, 0x5A, 0x81, 0xC1,
- 0xCC, 0x03, 0xC3, 0x2B, 0xFB, 0xF3, 0x1E, 0x16, 0xBF, 0xFB, 0x97, 0xAA, 0xAA, 0x81, 0xD4, 0x8B,
- 0x33, 0x5D, 0x59, 0x59, 0xD5, 0x4B, 0xE0, 0xD2, 0x08, 0xA0, 0x5B, 0x8B, 0x3C, 0x3A, 0x8C, 0xFC,
- 0x87, 0x52, 0xF6, 0x4D, 0xBB, 0x0F, 0x87, 0x01, 0x49, 0xD3, 0x73, 0xB8, 0x01, 0x43, 0xF7, 0x42,
- 0x50, 0xB8, 0xB2, 0xC2, 0xFD, 0xE6, 0xE6, 0x66, 0x15, 0x29, 0xA1, 0x21, 0x14, 0xDB, 0x8A, 0x2B,
- 0xF0, 0x49, 0xD3, 0xF1, 0x81, 0x30, 0x18, 0xD2, 0x1A, 0xC6, 0xF0, 0x25, 0xE3, 0x47, 0x5C, 0x71,
- 0xF4, 0xF4, 0x22, 0xA6, 0xFC, 0x33, 0xDC, 0x95, 0x32, 0xCB, 0x1A, 0xAD, 0xA6, 0x68, 0xFA, 0x8F,
- 0xD8, 0x3E, 0xCA, 0x0D, 0x76, 0xC1, 0x7A, 0xBA, 0x56, 0xA1, 0xFC, 0x9F, 0x61, 0xB9, 0x94, 0x28,
- 0xD6, 0x70, 0x9C, 0x40, 0x80, 0x5A, 0xC3, 0x31, 0xC4, 0x1A, 0x41, 0x17, 0xFC, 0x26, 0x6B, 0xF9,
- 0xCD, 0xFE, 0x19, 0x7E, 0x97, 0x76, 0x1E, 0x15, 0x25, 0x91, 0xAA, 0xAF, 0x50, 0x02, 0x9F, 0xDD,
- 0xE9, 0xA6, 0x15, 0xB9, 0x55, 0x0A, 0x50, 0x1B, 0x46, 0x41, 0xD0, 0x8F, 0xE2, 0x83, 0x27, 0xD6,
- 0x9D, 0xC5, 0x7A, 0x31, 0xC8, 0xD9, 0x5C, 0x6E, 0xB1, 0xBC, 0xB5, 0x44, 0x4F, 0xA1, 0xEC, 0x5F,
- 0x4B, 0x15, 0x01, 0x3F, 0x23, 0x8B, 0x7B, 0xAC, 0xD4, 0xA5, 0x36, 0x28, 0x0F, 0x56, 0x3F, 0xD5,
- 0x3C, 0xCB, 0x5F, 0xCC, 0xAE, 0x6B, 0x51, 0x9B, 0xC0, 0x38, 0x57, 0x92, 0x8B, 0x4A, 0xB2, 0xC8,
- 0x13, 0x01, 0xA8, 0x58, 0xC7, 0x2E, 0xC4, 0x4D, 0x6B, 0x7A, 0x7C, 0xBF, 0x5C, 0x83, 0xC2, 0xDF,
- 0xF5, 0xD5, 0x12, 0x33, 0x08, 0xC4, 0xD3, 0x95, 0x4B, 0x29, 0x5F, 0x37, 0x29, 0x8A, 0x0E, 0x62,
- 0x47, 0xA3, 0x51, 0x4A, 0xC5, 0x47, 0x0C, 0x49, 0x56, 0xB2, 0x98, 0x9F, 0xC8, 0x90, 0x04, 0x8C,
- 0x45, 0x3C, 0x8C, 0xB2, 0x94, 0x46, 0x99, 0xA8, 0xA4, 0x16, 0x63, 0x21, 0xCC, 0x5E, 0xFA, 0xE7,
- 0x9F, 0x8B, 0xC9, 0x7E, 0x5A, 0x0B, 0x96, 0xD3, 0xEB, 0x3D, 0xBF, 0x34, 0xD9, 0xF7, 0x6B, 0x89,
- 0xB9, 0x7A, 0xE9, 0xFF, 0x67, 0x4B, 0x21, 0x65, 0x4B, 0xF1, 0xB0, 0x54, 0x2E, 0x62, 0x62, 0x29,
- 0xE6, 0xC9, 0x82, 0x91, 0x97, 0x7C, 0x16, 0x0D, 0x1A, 0x2B, 0x25, 0x55, 0x9E, 0x97, 0x7D, 0x95,
- 0x43, 0x40, 0x59, 0x71, 0xE5, 0x35, 0x11, 0x06, 0x34, 0xE0, 0x63, 0x64, 0xF2, 0x41, 0xEB, 0xA7,
- 0xD1, 0x94, 0x26, 0x87, 0x24, 0xA5, 0x06, 0x24, 0xCD, 0x65, 0xDC, 0x41, 0xA8, 0xE9, 0x04, 0xEB,
- 0x76, 0x6D, 0x6E, 0x12, 0x05, 0xCE, 0x33, 0x77, 0xC4, 0xB1, 0x26, 0x03, 0xF9, 0xB2, 0xCA, 0x09,
- 0xD4, 0xC6, 0xBE, 0x12, 0xA4, 0x3E, 0x52, 0x25, 0xA8, 0x61, 0x5A, 0xD0, 0x76, 0xC0, 0x35, 0x5F,
- 0x26, 0x51, 0x4C, 0xC6, 0xB2, 0x07, 0x83, 0x35, 0x74, 0x0F, 0xA4, 0x66, 0x6D, 0x34, 0x91, 0x60,
- 0xA9, 0x73, 0x29, 0xFC, 0x66, 0xD9, 0xC2, 0x70, 0x4B, 0x57, 0xC9, 0xB0, 0xBD, 0xF4, 0xA5, 0x35,
- 0x59, 0x83, 0xE0, 0x0B, 0x6C, 0x62, 0xE0, 0x1E, 0x68, 0x64, 0xF2, 0x7B, 0x00, 0x77, 0x6B, 0xB6,
- 0xA3, 0x3D, 0xD6, 0x8E, 0x6A, 0x35, 0x53, 0x55, 0xE9, 0xAE, 0x0B, 0x6D, 0x4E, 0x74, 0x23, 0x0B,
- 0x4B, 0x10, 0xAA, 0x9A, 0x59, 0x0C, 0x38, 0x1B, 0x81, 0xAA, 0xBA, 0xC0, 0x11, 0xD6, 0x98, 0x66,
- 0xA9, 0x23, 0xF1, 0x97, 0x1D, 0xC9, 0x13, 0xB5, 0x07, 0x95, 0xF5, 0x05, 0xD4, 0x31, 0xAB, 0x25,
- 0x86, 0x30, 0xD3, 0x29, 0x13, 0xDE, 0x04, 0x03, 0x90, 0x07, 0x5A, 0xD5, 0x05, 0x14, 0xB5, 0x8E,
- 0x1C, 0x4D, 0x44, 0xB8, 0x1C, 0x05, 0xF9, 0xF0, 0x6B, 0x9A, 0x0F, 0xBC, 0xB4, 0x18, 0xDD, 0x97,
- 0x80, 0x50, 0xD2, 0xE6, 0xE0, 0x88, 0x8F, 0xF2, 0x21, 0xF4, 0xB2, 0x05, 0x9D, 0x02, 0x58, 0xFC,
- 0xC6, 0x71, 0x3E, 0x8A, 0x27, 0xC5, 0x68, 0x42, 0xEF, 0x17, 0x78, 0x51, 0x01, 0xF5, 0xA9, 0xEE,
- 0x28, 0x1B, 0xDB, 0x68, 0xCE, 0xF3, 0x41, 0x6B, 0x29, 0x7F, 0xF0, 0xFF, 0x28, 0x7F, 0xCC, 0xC7,
- 0x85, 0x34, 0x71, 0x31, 0x1A, 0xB3, 0x42, 0x96, 0x61, 0x18, 0xFF, 0x90, 0x93, 0xA4, 0xD4, 0x13,
- 0x97, 0x7A, 0x5A, 0xF1, 0xB3, 0xB6, 0x53, 0x98, 0x8E, 0x31, 0xAA, 0xF8, 0xE3, 0xC8, 0xF6, 0xF0,
- 0xF7, 0x3C, 0xF2, 0x65, 0x6D, 0x69, 0x5A, 0xA1, 0x31, 0x82, 0x3A, 0x57, 0x37, 0xCB, 0x7E, 0x9A,
- 0xFD, 0xB7, 0xAD, 0xE8, 0xD1, 0xF1, 0xE9, 0x71, 0xFF, 0xB8, 0x5C, 0x38, 0x23, 0xE7, 0x25, 0x93,
- 0x8A, 0x2B, 0x5D, 0xFA, 0xB2, 0x22, 0x80, 0x02, 0x1B, 0x45, 0x01, 0x7B, 0xDD, 0xDC, 0x54, 0x7E,
- 0xF1, 0xB6, 0x77, 0x71, 0x6E, 0xC7, 0x24, 0x01, 0x8F, 0x24, 0x15, 0xE6, 0xC2, 0x82, 0x44, 0xF9,
- 0xE0, 0xD7, 0xC7, 0xA5, 0x72, 0x5D, 0x7E, 0x61, 0x70, 0xC4, 0xDC, 0x52, 0xA7, 0xA9, 0x7E, 0x78,
- 0xE2, 0x62, 0x5D, 0x99, 0xBF, 0x04, 0x41, 0x72, 0x1A, 0x2D, 0x13, 0x55, 0x11, 0x67, 0x46, 0xE5,
- 0x30, 0x2F, 0xEE, 0xB2, 0x75, 0x0D, 0xD3, 0xC8, 0xB4, 0xC4, 0x84, 0xA5, 0xE5, 0x46, 0xA5, 0x12,
- 0x14, 0xFE, 0xA2, 0xB6, 0xE7, 0x8B, 0x91, 0x24, 0xB7, 0x5A, 0x73, 0xAB, 0x6F, 0x41, 0x2A, 0x3E,
- 0x58, 0x04, 0x23, 0x66, 0x39, 0xDB, 0x16, 0x77, 0xA3, 0x43, 0xEE, 0x61, 0x5C, 0x7F, 0xBA, 0x35,
- 0x78, 0xD2, 0x3C, 0x79, 0x61, 0x9E, 0xFC, 0xB1, 0x7B, 0x2E, 0x1C, 0x45, 0xF9, 0xDA, 0xE2, 0x98,
- 0xF6, 0x10, 0x58, 0xBB, 0x6D, 0x2F, 0x7D, 0x18, 0x20, 0xD2, 0x83, 0xCB, 0x00, 0xF4, 0x63, 0x58,
- 0xFF, 0x4A, 0xEE, 0x88, 0x7A, 0x09, 0xAA, 0xA2, 0xAD, 0x73, 0x54, 0xD8, 0xEE, 0xFD, 0x81, 0xA3,
- 0xF2, 0xCE, 0x65, 0x18, 0x48, 0x97, 0xC3, 0x92, 0x37, 0x8B, 0x75, 0xC1, 0x61, 0x19, 0x31, 0x64,
- 0x6C, 0x00, 0xE3, 0xCD, 0x5D, 0x49, 0x13, 0xD5, 0x1C, 0xB4, 0xF0, 0x1B, 0x08, 0x8A, 0x4F, 0x39,
- 0xCE, 0x9A, 0x38, 0xAD, 0x62, 0x72, 0xC5, 0x23, 0xC8, 0x4A, 0x67, 0x89, 0xC0, 0x6E, 0x10, 0x0D,
- 0x0D, 0x7C, 0x64, 0x9A, 0xA1, 0xB6, 0x1D, 0x3E, 0x37, 0xD7, 0xBC, 0xD9, 0x54, 0xFA, 0x4B, 0x62,
- 0x79, 0xD5, 0xB0, 0x8B, 0x1C, 0x56, 0xCC, 0x75, 0x7D, 0x1F, 0xF4, 0xA3, 0x4E, 0x29, 0xAF, 0x48,
- 0xA4, 0x53, 0xD1, 0x83, 0xC4, 0x86, 0xA2, 0x41, 0xBE, 0x91, 0x40, 0x44, 0x72, 0x4A, 0x33, 0x5D,
- 0xC7, 0xCA, 0xD2, 0x0B, 0x28, 0x49, 0x7A, 0xB2, 0x73, 0x95, 0x49, 0x6B, 0x25, 0x06, 0xFE, 0xC8,
- 0xD7, 0xF0, 0xC7, 0xA1, 0xD0, 0xA3, 0x83, 0x9B, 0x49, 0x2B, 0x83, 0xA4, 0x23, 0x64, 0x83, 0xA9,
- 0x37, 0xE4, 0xBB, 0xA8, 0x2D, 0x2F, 0xCB, 0xB4, 0x16, 0x50, 0x70, 0x71, 0x83, 0xBB, 0x11, 0x30,
- 0x52, 0x5A, 0xC4, 0x9E, 0x94, 0xA8, 0xC7, 0x8F, 0x10, 0x1F, 0x53, 0x4A, 0x20, 0x06, 0x20, 0xA6,
- 0x40, 0xD0, 0xA7, 0x42, 0x8A, 0x54, 0xE6, 0x92, 0x53, 0x2A, 0x20, 0xCA, 0x48, 0xCD, 0xE2, 0xC1,
- 0x85, 0x78, 0xD4, 0x46, 0xD6, 0x80, 0xFD, 0xDC, 0xBD, 0x73, 0x33, 0xDE, 0x90, 0x68, 0x09, 0x56,
- 0x36, 0x3D, 0x9A, 0xA6, 0x52, 0x5C, 0x54, 0xC7, 0x19, 0xF8, 0xA8, 0xA1, 0x03, 0x5A, 0x23, 0x84,
- 0x11, 0x1E, 0x84, 0x8A, 0x01, 0x40, 0x7F, 0x42, 0xC3, 0x1C, 0x22, 0x70, 0x08, 0x20, 0x82, 0xA0,
- 0x7F, 0x49, 0x0D, 0xF7, 0x64, 0x05, 0xC9, 0xF8, 0xD8, 0x6D, 0x35, 0xF0, 0x9D, 0x66, 0x95, 0xEC,
- 0x20, 0xA5, 0xBD, 0x68, 0x24, 0xFA, 0x64, 0x98, 0x1A, 0x50, 0x00, 0xAC, 0xD9, 0x01, 0xA0, 0x1E,
- 0x24, 0x5E, 0x63, 0x2B, 0x3F, 0xEF, 0x04, 0x2A, 0xBB, 0x00, 0xAB, 0xBB, 0x8E, 0x87, 0x5F, 0x39,
- 0x4F, 0x19, 0xA7, 0x39, 0x26, 0x00, 0x7B, 0x93, 0x68, 0x7A, 0x99, 0x30, 0x2E, 0xCE, 0x64, 0x1B,
- 0x6A, 0x6C, 0xB4, 0xE4, 0xF5, 0xA9, 0x87, 0x15, 0x79, 0x3F, 0xC5, 0x8B, 0xCB, 0x0C, 0xF3, 0xBA,
- 0x53, 0x79, 0x77, 0xB1, 0x86, 0x70, 0x21, 0x50, 0x66, 0x38, 0xB3, 0x29, 0x74, 0xB0, 0xFA, 0xA1,
- 0x48, 0x82, 0x7A, 0x4F, 0xB7, 0x42, 0xE2, 0xC1, 0x44, 0xED, 0x81, 0xF9, 0xDC, 0xC2, 0xD8, 0xE1,
- 0x94, 0x83, 0x5A, 0x0A, 0xB5, 0x02, 0x45, 0xC6, 0x95, 0xCD, 0x98, 0x35, 0x1D, 0x6A, 0x58, 0x88,
- 0x61, 0xE0, 0xAF, 0xFE, 0x05, 0x0F, 0x1E, 0x1C, 0xC8, 0x55, 0x3F, 0xE1, 0x23, 0xE3, 0x7E, 0xF4,
- 0x23, 0x3E, 0x3E, 0xAF, 0xF0, 0xF1, 0x79, 0x1D, 0x1F, 0xB4, 0xAA, 0x3C, 0x98, 0x0C, 0x80, 0xEC,
- 0x19, 0xE1, 0x64, 0x4C, 0x13, 0x58, 0xC0, 0x43, 0x50, 0x25, 0x7F, 0x8B, 0xB3, 0x84, 0xFE, 0x98,
- 0xB3, 0xDE, 0x84, 0x8D, 0xC4, 0x23, 0xFE, 0x8A, 0xD5, 0xFF, 0x82, 0x4B, 0x3C, 0x70, 0x3D, 0x97,
- 0x79, 0x6D, 0x5A, 0x49, 0x28, 0x3F, 0x7E, 0x2B, 0x91, 0x7E, 0xE4, 0x42, 0x78, 0xA9, 0x38, 0xC8,
- 0xDF, 0xB7, 0xF4, 0x00, 0xBC, 0x11, 0xF8, 0x29, 0x35, 0x75, 0xBC, 0x0B, 0xA5, 0xFC, 0x29, 0x30,
- 0x64, 0xA8, 0xC0, 0x47, 0xDD, 0xD9, 0xDC, 0x12, 0xAE, 0x01, 0x8A, 0xF1, 0xA3, 0x29, 0xB0, 0xEA,
- 0xC9, 0x02, 0xD7, 0x9E, 0x40, 0x26, 0x04, 0x91, 0xE0, 0x48, 0xC8, 0xA7, 0x8D, 0x2F, 0x07, 0x9B,
- 0x37, 0x35, 0xC8, 0x43, 0x2E, 0xFC, 0x98, 0x2E, 0x0C, 0x36, 0x6F, 0xFE, 0x6D, 0x36, 0xC6, 0xCC,
- 0x5A, 0x76, 0xA4, 0x96, 0x4C, 0xF6, 0xF4, 0x0B, 0xBF, 0x71, 0x09, 0x48, 0x5D, 0x49, 0x78, 0x45,
- 0x34, 0x03, 0x6B, 0x43, 0x61, 0xE1, 0x07, 0xFF, 0x47, 0x09, 0xF8, 0x91, 0x9E, 0x07, 0xCE, 0xBD,
- 0xE6, 0x3D, 0x5E, 0x2F, 0x3E, 0x85, 0xE9, 0x56, 0xE9, 0xC1, 0x4A, 0xC7, 0xEF, 0x53, 0x3A, 0x76,
- 0x59, 0xA2, 0x14, 0x4A, 0x14, 0x59, 0x88, 0x1A, 0x6A, 0x50, 0x0E, 0x51, 0x98, 0x89, 0x17, 0xCD,
- 0x81, 0x02, 0x9B, 0x73, 0x34, 0x5B, 0x3A, 0x02, 0x0F, 0xF4, 0xF5, 0x45, 0xEE, 0xFC, 0x74, 0x76,
- 0x7A, 0x22, 0x44, 0x7C, 0xA5, 0x62, 0x22, 0xD0, 0xAA, 0x2E, 0x2C, 0x2F, 0xCF, 0x9C, 0x89, 0xE4,
- 0xA1, 0x28, 0x75, 0x30, 0x31, 0x28, 0x87, 0xFE, 0x74, 0x31, 0xFC, 0x0A, 0x71, 0xD6, 0xD0, 0xCF,
- 0x52, 0x48, 0x58, 0x5B, 0x36, 0xA2, 0xF7, 0xFB, 0x97, 0xF6, 0xAE, 0xDD, 0x84, 0xBA, 0x00, 0xB4,
- 0x0A, 0x69, 0x19, 0xEE, 0x7D, 0xFE, 0xB7, 0x90, 0xB7, 0xFF, 0x1E, 0x32, 0x83, 0xA8, 0x95, 0x42,
- 0x58, 0x2A, 0xF0, 0xAB, 0xB8, 0x93, 0x24, 0x9A, 0x4A, 0xB4, 0xE3, 0x24, 0xC1, 0x4B, 0xE9, 0x43,
- 0x85, 0xA2, 0x0D, 0x61, 0x31, 0xA5, 0x89, 0xE6, 0x47, 0x34, 0xD5, 0x78, 0x24, 0xB4, 0x34, 0x8B,
- 0x63, 0x68, 0x5C, 0x56, 0xF4, 0x61, 0xEB, 0xC5, 0xEB, 0xCB, 0xFB, 0x8C, 0x66, 0xD4, 0xCF, 0x97,
- 0x69, 0x52, 0xD1, 0x0B, 0x56, 0x50, 0xDF, 0x10, 0xEE, 0x7E, 0xB9, 0xC9, 0xEB, 0xA9, 0x8C, 0x73,
- 0x8C, 0xA2, 0x1B, 0x2D, 0x35, 0x07, 0xE9, 0x26, 0x40, 0xD5, 0xE5, 0x59, 0x10, 0xCC, 0xDB, 0x2B,
- 0xB4, 0xA0, 0xF1, 0x8A, 0x44, 0x24, 0x9F, 0xCB, 0x67, 0x7F, 0xE4, 0xC9, 0xA9, 0xE2, 0x82, 0x50,
- 0xF2, 0x54, 0xA9, 0x36, 0xAD, 0x0D, 0x63, 0x83, 0x6A, 0x8C, 0xA7, 0x82, 0x70, 0x0F, 0xAF, 0x51,
- 0xE9, 0xC2, 0x2C, 0x6A, 0x29, 0xDC, 0xDE, 0x46, 0x5F, 0xCB, 0x6D, 0xE9, 0x89, 0x7C, 0x2A, 0x25,
- 0xE3, 0xAE, 0xAE, 0x63, 0x55, 0x45, 0xB1, 0x3E, 0x25, 0x61, 0x5A, 0x26, 0x5B, 0x54, 0x06, 0x26,
- 0x77, 0x0B, 0x70, 0x9B, 0x06, 0x29, 0x1C, 0xBD, 0x7E, 0x7F, 0xCE, 0x46, 0xD1, 0xCE, 0x11, 0x80,
- 0x69, 0xC5, 0x3E, 0x93, 0xD7, 0xE0, 0x24, 0xCC, 0x73, 0x07, 0x32, 0xE9, 0x4A, 0x03, 0x0E, 0xA9,
- 0x98, 0x44, 0xFE, 0x81, 0x7E, 0xA0, 0x3B, 0x3A, 0xFC, 0xBB, 0x09, 0x35, 0x47, 0xCD, 0xA5, 0xD0,
- 0xA4, 0xFA, 0x74, 0x70, 0xF5, 0x06, 0xC2, 0x53, 0x0C, 0xA5, 0x01, 0x17, 0x50, 0x34, 0xD7, 0x74,
- 0x7C, 0x7A, 0x7D, 0x0C, 0x29, 0xC8, 0x7F, 0x21, 0x37, 0x66, 0xBB, 0xAA, 0x6C, 0xB8, 0xF3, 0xEA,
- 0x75, 0x56, 0x2E, 0x03, 0x7A, 0x61, 0x8C, 0x58, 0x0F, 0x29, 0x7E, 0xFB, 0x7B, 0xF4, 0x9E, 0x8D,
- 0x15, 0xD2, 0x6A, 0x5D, 0x6F, 0xCE, 0x76, 0x90, 0x67, 0x89, 0xD5, 0x43, 0x2C, 0x70, 0x97, 0x1F,
- 0x29, 0x59, 0x95, 0x35, 0xDC, 0xF6, 0x48, 0x10, 0xE0, 0xC7, 0x5A, 0x03, 0x1B, 0x6A, 0x22, 0xB2,
- 0xD4, 0x42, 0x22, 0x29, 0x08, 0x90, 0xD2, 0x3E, 0x84, 0x39, 0xD3, 0x92, 0x65, 0x86, 0xB2, 0xA1,
- 0xBC, 0xFF, 0xC5, 0x9A, 0xA3, 0x64, 0x46, 0xE8, 0xCE, 0xF9, 0x6C, 0x73, 0x53, 0xD8, 0x85, 0x99,
- 0x18, 0x05, 0x52, 0x8A, 0x01, 0x1C, 0x9A, 0x7D, 0x68, 0x2D, 0x8C, 0xB2, 0x90, 0x58, 0xAB, 0x3D,
- 0xD2, 0xB6, 0x51, 0x55, 0x03, 0x54, 0x7C, 0x46, 0x01, 0x03, 0xCE, 0xB2, 0x24, 0x80, 0xA8, 0x8B,
- 0x39, 0xBA, 0xB2, 0x2D, 0xC5, 0xBA, 0xD0, 0x84, 0x0E, 0xEC, 0x67, 0xC8, 0x12, 0x95, 0x97, 0xAD,
- 0xA2, 0x27, 0x12, 0xC5, 0x77, 0x95, 0x9E, 0xC8, 0x6F, 0xE5, 0x84, 0xAA, 0xC8, 0x77, 0x88, 0x2F,
- 0x13, 0x5C, 0xD4, 0xD1, 0x13, 0xA0, 0x24, 0x83, 0x52, 0x34, 0x60, 0x2A, 0x2C, 0x37, 0xEE, 0xEB,
- 0xD3, 0xE9, 0xB4, 0x8E, 0xDF, 0x6A, 0xEB, 0x70, 0x82, 0xB2, 0x02, 0x5F, 0x5F, 0xC7, 0x21, 0x47,
- 0x15, 0x58, 0xF8, 0x6E, 0xE1, 0xAC, 0xBA, 0xE8, 0x42, 0x7F, 0x2B, 0xDE, 0xD4, 0xAA, 0xD2, 0x59,
- 0xE1, 0x73, 0x79, 0xDB, 0x7B, 0x3B, 0x2B, 0x20, 0x32, 0xC4, 0xAF, 0xB2, 0x90, 0x69, 0x20, 0x0D,
- 0x3B, 0xE5, 0x46, 0x56, 0x25, 0x85, 0x65, 0x5C, 0xB0, 0xE3, 0x2C, 0x9D, 0x18, 0x33, 0x60, 0xDD,
- 0x11, 0x96, 0xD2, 0x95, 0x43, 0x2D, 0x65, 0xB7, 0x0E, 0xB7, 0x0A, 0xFB, 0x70, 0x30, 0x83, 0x94,
- 0x79, 0xFB, 0xF3, 0x4F, 0x39, 0x5B, 0xDE, 0xF6, 0x92, 0x62, 0x71, 0xE1, 0xF3, 0xFC, 0xA9, 0x35,
- 0xAF, 0x69, 0xA5, 0xD1, 0xAF, 0xC4, 0x97, 0xBD, 0x46, 0xFE, 0x19, 0x3B, 0xFF, 0x9C, 0xAD, 0x81,
- 0xB1, 0x43, 0x23, 0x2A, 0xDC, 0x4C, 0x8C, 0xEA, 0x2F, 0x34, 0xE6, 0x63, 0x79, 0x29, 0xBF, 0x2D,
- 0xA0, 0x54, 0xA9, 0xD3, 0x68, 0x78, 0x3E, 0xFF, 0x9A, 0x42, 0x19, 0x1D, 0x65, 0xFE, 0x28, 0x20,
- 0x09, 0xC5, 0x82, 0xA3, 0x41, 0xBE, 0x92, 0xFB, 0x46, 0xC0, 0x86, 0x69, 0x03, 0x93, 0x6D, 0xCB,
- 0xDE, 0xB2, 0x77, 0x71, 0x64, 0x7F, 0x4D, 0xF7, 0x57, 0x4F, 0xD8, 0x5F, 0x34, 0x69, 0x58, 0x0B,
- 0xE7, 0xB5, 0xAB, 0x8A, 0x4D, 0x6A, 0x83, 0xFB, 0xC4, 0xA7, 0x70, 0x3D, 0x6F, 0xB3, 0xCC, 0xB6,
- 0x1A, 0xE4, 0x5F, 0x60, 0xD4, 0x31, 0xBA, 0x95, 0x2F, 0x92, 0xF4, 0x81, 0x7B, 0x18, 0x5B, 0x17,
- 0x54, 0x26, 0x70, 0x49, 0xD5, 0x87, 0x34, 0xB9, 0xD3, 0x9C, 0x2F, 0x39, 0xC3, 0xB7, 0x3C, 0xA8,
- 0x03, 0xE4, 0x37, 0x9C, 0x72, 0x39, 0xB0, 0xBF, 0x07, 0x5D, 0x33, 0x2A, 0x41, 0x79, 0xB1, 0x26,
- 0x9B, 0xE6, 0x7C, 0x02, 0x82, 0x01, 0x70, 0xB1, 0xA3, 0x48, 0xCD, 0x2B, 0xCB, 0x98, 0x9B, 0x57,
- 0x96, 0x54, 0xE2, 0x5F, 0x59, 0xCC, 0xDB, 0x9F, 0xFC, 0xDB, 0x4C, 0xF9, 0x7F, 0x5B, 0x28, 0x36,
- 0x32, 0xF9, 0xE1, 0x09, 0xF7, 0x56, 0x3F, 0x45, 0xAD, 0x47, 0x51, 0xBB, 0xF7, 0xFF, 0x17, 0x53,
- 0xE8, 0x9D, 0x36, 0x92, 0x29, 0x00, 0x00
-};
-
-#define SPIFFS_MAXLENGTH_FILEPATH 32
-const char *excludeListFile = "/.exclude.files";
-
-typedef struct ExcludeListS {
- char *item;
- ExcludeListS *next;
-} ExcludeList;
-
-static ExcludeList *excludes = NULL;
-
-static bool matchWild(const char *pattern, const char *testee) {
- const char *nxPat = NULL, *nxTst = NULL;
-
- while (*testee) {
- if (( *pattern == '?' ) || (*pattern == *testee)){
- pattern++;testee++;
- continue;
- }
- if (*pattern=='*'){
- nxPat=pattern++; nxTst=testee;
- continue;
- }
- if (nxPat){
- pattern = nxPat+1; testee=++nxTst;
- continue;
- }
- return false;
- }
- while (*pattern=='*'){pattern++;}
- return (*pattern == 0);
-}
-
-static bool addExclude(const char *item){
- size_t len = strlen(item);
- if(!len){
- return false;
- }
- ExcludeList *e = (ExcludeList *)malloc(sizeof(ExcludeList));
- if(!e){
- return false;
- }
- e->item = (char *)malloc(len+1);
- if(!e->item){
- free(e);
- return false;
- }
- memcpy(e->item, item, len+1);
- e->next = excludes;
- excludes = e;
- return true;
-}
-
-static void loadExcludeList(fs::FS &_fs, const char *filename){
- static char linebuf[SPIFFS_MAXLENGTH_FILEPATH];
- fs::File excludeFile=_fs.open(filename, "r");
- if(!excludeFile){
- //addExclude("/*.js.gz");
- return;
- }
-#ifdef ESP32
- if(excludeFile.isDirectory()){
- excludeFile.close();
- return;
- }
-#endif
- if (excludeFile.size() > 0){
- uint8_t idx;
- bool isOverflowed = false;
- while (excludeFile.available()){
- linebuf[0] = '\0';
- idx = 0;
- int lastChar;
- do {
- lastChar = excludeFile.read();
- if(lastChar != '\r'){
- linebuf[idx++] = (char) lastChar;
- }
- } while ((lastChar >= 0) && (lastChar != '\n') && (idx < SPIFFS_MAXLENGTH_FILEPATH));
-
- if(isOverflowed){
- isOverflowed = (lastChar != '\n');
- continue;
- }
- isOverflowed = (idx >= SPIFFS_MAXLENGTH_FILEPATH);
- linebuf[idx-1] = '\0';
- if(!addExclude(linebuf)){
- excludeFile.close();
- return;
- }
- }
- }
- excludeFile.close();
-}
-
-static bool isExcluded(fs::FS &_fs, const char *filename) {
- if(excludes == NULL){
- loadExcludeList(_fs, excludeListFile);
- }
- ExcludeList *e = excludes;
- while(e){
- if (matchWild(e->item, filename)){
- return true;
- }
- e = e->next;
- }
- return false;
-}
-
-// WEB HANDLER IMPLEMENTATION
-
-#ifdef ESP32
-SPIFFSEditor::SPIFFSEditor(const fs::FS& fs, const String& username, const String& password)
-#else
-SPIFFSEditor::SPIFFSEditor(const String& username, const String& password, const fs::FS& fs)
-#endif
-:_fs(fs)
-,_username(username)
-,_password(password)
-,_authenticated(false)
-,_startTime(0)
-{}
-
-bool SPIFFSEditor::canHandle(AsyncWebServerRequest *request){
- if(request->url().equalsIgnoreCase("/edit")){
- if(request->method() == HTTP_GET){
- if(request->hasParam("list"))
- return true;
- if(request->hasParam("edit")){
- request->_tempFile = _fs.open(request->arg("edit"), "r");
- if(!request->_tempFile){
- return false;
- }
-#ifdef ESP32
- if(request->_tempFile.isDirectory()){
- request->_tempFile.close();
- return false;
- }
-#endif
- }
- if(request->hasParam("download")){
- request->_tempFile = _fs.open(request->arg("download"), "r");
- if(!request->_tempFile){
- return false;
- }
-#ifdef ESP32
- if(request->_tempFile.isDirectory()){
- request->_tempFile.close();
- return false;
- }
-#endif
- }
- request->addInterestingHeader("If-Modified-Since");
- return true;
- }
- else if(request->method() == HTTP_POST)
- return true;
- else if(request->method() == HTTP_DELETE)
- return true;
- else if(request->method() == HTTP_PUT)
- return true;
-
- }
- return false;
-}
-
-
-void SPIFFSEditor::handleRequest(AsyncWebServerRequest *request){
- if(_username.length() && _password.length() && !request->authenticate(_username.c_str(), _password.c_str()))
- return request->requestAuthentication();
-
- if(request->method() == HTTP_GET){
- if(request->hasParam("list")){
- String path = request->getParam("list")->value();
-#ifdef ESP32
- File dir = _fs.open(path);
-#else
- Dir dir = _fs.openDir(path);
-#endif
- path = String();
- String output = "[";
-#ifdef ESP32
- File entry = dir.openNextFile();
- while(entry){
-#else
- while(dir.next()){
- fs::File entry = dir.openFile("r");
-#endif
- if (isExcluded(_fs, entry.name())) {
-#ifdef ESP32
- entry = dir.openNextFile();
-#endif
- continue;
- }
- if (output != "[") output += ',';
- output += "{\"type\":\"";
- output += "file";
- output += "\",\"name\":\"";
- output += String(entry.name());
- output += "\",\"size\":";
- output += String(entry.size());
- output += "}";
-#ifdef ESP32
- entry = dir.openNextFile();
-#else
- entry.close();
-#endif
- }
-#ifdef ESP32
- dir.close();
-#endif
- output += "]";
- request->send(200, "application/json", output);
- output = String();
- }
- else if(request->hasParam("edit") || request->hasParam("download")){
- request->send(request->_tempFile, request->_tempFile.name(), String(), request->hasParam("download"));
- }
- else {
- const char * buildTime = __DATE__ " " __TIME__ " GMT";
- if (request->header("If-Modified-Since").equals(buildTime)) {
- request->send(304);
- } else {
- AsyncWebServerResponse *response = request->beginResponse_P(200, "text/html", edit_htm_gz, edit_htm_gz_len);
- response->addHeader("Content-Encoding", "gzip");
- response->addHeader("Last-Modified", buildTime);
- request->send(response);
- }
- }
- } else if(request->method() == HTTP_DELETE){
- if(request->hasParam("path", true)){
- _fs.remove(request->getParam("path", true)->value());
- request->send(200, "", "DELETE: "+request->getParam("path", true)->value());
- } else
- request->send(404);
- } else if(request->method() == HTTP_POST){
- if(request->hasParam("data", true, true) && _fs.exists(request->getParam("data", true, true)->value()))
- request->send(200, "", "UPLOADED: "+request->getParam("data", true, true)->value());
- else
- request->send(500);
- } else if(request->method() == HTTP_PUT){
- if(request->hasParam("path", true)){
- String filename = request->getParam("path", true)->value();
- if(_fs.exists(filename)){
- request->send(200);
- } else {
- fs::File f = _fs.open(filename, "w");
- if(f){
- f.write((uint8_t)0x00);
- f.close();
- request->send(200, "", "CREATE: "+filename);
- } else {
- request->send(500);
- }
- }
- } else
- request->send(400);
- }
-}
-
-void SPIFFSEditor::handleUpload(AsyncWebServerRequest *request, const String& filename, size_t index, uint8_t *data, size_t len, bool final){
- if(!index){
- if(!_username.length() || request->authenticate(_username.c_str(),_password.c_str())){
- _authenticated = true;
- request->_tempFile = _fs.open(filename, "w");
- _startTime = millis();
- }
- }
- if(_authenticated && request->_tempFile){
- if(len){
- request->_tempFile.write(data,len);
- }
- if(final){
- request->_tempFile.close();
- }
- }
-}
diff --git a/ESP32/lib/ESPAsyncWebServer/src/SPIFFSEditor.h b/ESP32/lib/ESPAsyncWebServer/src/SPIFFSEditor.h
deleted file mode 100644
index 3586429..0000000
--- a/ESP32/lib/ESPAsyncWebServer/src/SPIFFSEditor.h
+++ /dev/null
@@ -1,24 +0,0 @@
-#ifndef SPIFFSEditor_H_
-#define SPIFFSEditor_H_
-#include
-
-class SPIFFSEditor: public AsyncWebHandler {
- private:
- fs::FS _fs;
- String _username;
- String _password;
- bool _authenticated;
- uint32_t _startTime;
- public:
-#ifdef ESP32
- SPIFFSEditor(const fs::FS& fs, const String& username=String(), const String& password=String());
-#else
- SPIFFSEditor(const String& username=String(), const String& password=String(), const fs::FS& fs=SPIFFS);
-#endif
- virtual bool canHandle(AsyncWebServerRequest *request) override final;
- virtual void handleRequest(AsyncWebServerRequest *request) override final;
- virtual void handleUpload(AsyncWebServerRequest *request, const String& filename, size_t index, uint8_t *data, size_t len, bool final) override final;
- virtual bool isRequestHandlerTrivial() override final {return false;}
-};
-
-#endif
diff --git a/ESP32/lib/ESPAsyncWebServer/src/StringArray.h b/ESP32/lib/ESPAsyncWebServer/src/StringArray.h
deleted file mode 100644
index 4c0aa70..0000000
--- a/ESP32/lib/ESPAsyncWebServer/src/StringArray.h
+++ /dev/null
@@ -1,193 +0,0 @@
-/*
- Asynchronous WebServer library for Espressif MCUs
-
- Copyright (c) 2016 Hristo Gochkov. All rights reserved.
- This file is part of the esp8266 core for Arduino environment.
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-*/
-#ifndef STRINGARRAY_H_
-#define STRINGARRAY_H_
-
-#include "stddef.h"
-#include "WString.h"
-
-template
-class LinkedListNode {
- T _value;
- public:
- LinkedListNode* next;
- LinkedListNode(const T val): _value(val), next(nullptr) {}
- ~LinkedListNode(){}
- const T& value() const { return _value; };
- T& value(){ return _value; }
-};
-
-template class Item = LinkedListNode>
-class LinkedList {
- public:
- typedef Item ItemType;
- typedef std::function OnRemove;
- typedef std::function Predicate;
- private:
- ItemType* _root;
- OnRemove _onRemove;
-
- class Iterator {
- ItemType* _node;
- public:
- Iterator(ItemType* current = nullptr) : _node(current) {}
- Iterator(const Iterator& i) : _node(i._node) {}
- Iterator& operator ++() { _node = _node->next; return *this; }
- bool operator != (const Iterator& i) const { return _node != i._node; }
- const T& operator * () const { return _node->value(); }
- const T* operator -> () const { return &_node->value(); }
- };
-
- public:
- typedef const Iterator ConstIterator;
- ConstIterator begin() const { return ConstIterator(_root); }
- ConstIterator end() const { return ConstIterator(nullptr); }
-
- LinkedList(OnRemove onRemove) : _root(nullptr), _onRemove(onRemove) {}
- ~LinkedList(){}
- void add(const T& t){
- auto it = new ItemType(t);
- if(!_root){
- _root = it;
- } else {
- auto i = _root;
- while(i->next) i = i->next;
- i->next = it;
- }
- }
- T& front() const {
- return _root->value();
- }
-
- bool isEmpty() const {
- return _root == nullptr;
- }
- size_t length() const {
- size_t i = 0;
- auto it = _root;
- while(it){
- i++;
- it = it->next;
- }
- return i;
- }
- size_t count_if(Predicate predicate) const {
- size_t i = 0;
- auto it = _root;
- while(it){
- if (!predicate){
- i++;
- }
- else if (predicate(it->value())) {
- i++;
- }
- it = it->next;
- }
- return i;
- }
- const T* nth(size_t N) const {
- size_t i = 0;
- auto it = _root;
- while(it){
- if(i++ == N)
- return &(it->value());
- it = it->next;
- }
- return nullptr;
- }
- bool remove(const T& t){
- auto it = _root;
- auto pit = _root;
- while(it){
- if(it->value() == t){
- if(it == _root){
- _root = _root->next;
- } else {
- pit->next = it->next;
- }
-
- if (_onRemove) {
- _onRemove(it->value());
- }
-
- delete it;
- return true;
- }
- pit = it;
- it = it->next;
- }
- return false;
- }
- bool remove_first(Predicate predicate){
- auto it = _root;
- auto pit = _root;
- while(it){
- if(predicate(it->value())){
- if(it == _root){
- _root = _root->next;
- } else {
- pit->next = it->next;
- }
- if (_onRemove) {
- _onRemove(it->value());
- }
- delete it;
- return true;
- }
- pit = it;
- it = it->next;
- }
- return false;
- }
-
- void free(){
- while(_root != nullptr){
- auto it = _root;
- _root = _root->next;
- if (_onRemove) {
- _onRemove(it->value());
- }
- delete it;
- }
- _root = nullptr;
- }
-};
-
-
-class StringArray : public LinkedList {
-public:
-
- StringArray() : LinkedList(nullptr) {}
-
- bool containsIgnoreCase(const String& str){
- for (const auto& s : *this) {
- if (str.equalsIgnoreCase(s)) {
- return true;
- }
- }
- return false;
- }
-};
-
-
-
-
-#endif /* STRINGARRAY_H_ */
diff --git a/ESP32/lib/ESPAsyncWebServer/src/WebAuthentication.cpp b/ESP32/lib/ESPAsyncWebServer/src/WebAuthentication.cpp
deleted file mode 100644
index 45246a1..0000000
--- a/ESP32/lib/ESPAsyncWebServer/src/WebAuthentication.cpp
+++ /dev/null
@@ -1,235 +0,0 @@
-/*
- Asynchronous WebServer library for Espressif MCUs
-
- Copyright (c) 2016 Hristo Gochkov. All rights reserved.
- This file is part of the esp8266 core for Arduino environment.
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-*/
-#include "WebAuthentication.h"
-#include
-#ifdef ESP32
-#include "mbedtls/md5.h"
-#else
-#include "md5.h"
-#endif
-
-
-// Basic Auth hash = base64("username:password")
-
-bool checkBasicAuthentication(const char * hash, const char * username, const char * password){
- if(username == NULL || password == NULL || hash == NULL)
- return false;
-
- size_t toencodeLen = strlen(username)+strlen(password)+1;
- size_t encodedLen = base64_encode_expected_len(toencodeLen);
- if(strlen(hash) != encodedLen)
- return false;
-
- char *toencode = new char[toencodeLen+1];
- if(toencode == NULL){
- return false;
- }
- char *encoded = new char[base64_encode_expected_len(toencodeLen)+1];
- if(encoded == NULL){
- delete[] toencode;
- return false;
- }
- sprintf(toencode, "%s:%s", username, password);
- if(base64_encode_chars(toencode, toencodeLen, encoded) > 0 && memcmp(hash, encoded, encodedLen) == 0){
- delete[] toencode;
- delete[] encoded;
- return true;
- }
- delete[] toencode;
- delete[] encoded;
- return false;
-}
-
-static bool getMD5(uint8_t * data, uint16_t len, char * output){//33 bytes or more
-#ifdef ESP32
- mbedtls_md5_context _ctx;
-#else
- md5_context_t _ctx;
-#endif
- uint8_t i;
- uint8_t * _buf = (uint8_t*)malloc(16);
- if(_buf == NULL)
- return false;
- memset(_buf, 0x00, 16);
-#ifdef ESP32
- mbedtls_md5_init(&_ctx);
- mbedtls_md5_starts_ret(&_ctx);
- mbedtls_md5_update_ret(&_ctx, data, len);
- mbedtls_md5_finish_ret(&_ctx, _buf);
-#else
- MD5Init(&_ctx);
- MD5Update(&_ctx, data, len);
- MD5Final(_buf, &_ctx);
-#endif
- for(i = 0; i < 16; i++) {
- sprintf(output + (i * 2), "%02x", _buf[i]);
- }
- free(_buf);
- return true;
-}
-
-static String genRandomMD5(){
-#ifdef ESP8266
- uint32_t r = RANDOM_REG32;
-#else
- uint32_t r = rand();
-#endif
- char * out = (char*)malloc(33);
- if(out == NULL || !getMD5((uint8_t*)(&r), 4, out))
- return "";
- String res = String(out);
- free(out);
- return res;
-}
-
-static String stringMD5(const String& in){
- char * out = (char*)malloc(33);
- if(out == NULL || !getMD5((uint8_t*)(in.c_str()), in.length(), out))
- return "";
- String res = String(out);
- free(out);
- return res;
-}
-
-String generateDigestHash(const char * username, const char * password, const char * realm){
- if(username == NULL || password == NULL || realm == NULL){
- return "";
- }
- char * out = (char*)malloc(33);
- String res = String(username);
- res.concat(":");
- res.concat(realm);
- res.concat(":");
- String in = res;
- in.concat(password);
- if(out == NULL || !getMD5((uint8_t*)(in.c_str()), in.length(), out))
- return "";
- res.concat(out);
- free(out);
- return res;
-}
-
-String requestDigestAuthentication(const char * realm){
- String header = "realm=\"";
- if(realm == NULL)
- header.concat("asyncesp");
- else
- header.concat(realm);
- header.concat( "\", qop=\"auth\", nonce=\"");
- header.concat(genRandomMD5());
- header.concat("\", opaque=\"");
- header.concat(genRandomMD5());
- header.concat("\"");
- return header;
-}
-
-bool checkDigestAuthentication(const char * header, const char * method, const char * username, const char * password, const char * realm, bool passwordIsHash, const char * nonce, const char * opaque, const char * uri){
- if(username == NULL || password == NULL || header == NULL || method == NULL){
- //os_printf("AUTH FAIL: missing requred fields\n");
- return false;
- }
-
- String myHeader = String(header);
- int nextBreak = myHeader.indexOf(",");
- if(nextBreak < 0){
- //os_printf("AUTH FAIL: no variables\n");
- return false;
- }
-
- String myUsername = String();
- String myRealm = String();
- String myNonce = String();
- String myUri = String();
- String myResponse = String();
- String myQop = String();
- String myNc = String();
- String myCnonce = String();
-
- myHeader += ", ";
- do {
- String avLine = myHeader.substring(0, nextBreak);
- avLine.trim();
- myHeader = myHeader.substring(nextBreak+1);
- nextBreak = myHeader.indexOf(",");
-
- int eqSign = avLine.indexOf("=");
- if(eqSign < 0){
- //os_printf("AUTH FAIL: no = sign\n");
- return false;
- }
- String varName = avLine.substring(0, eqSign);
- avLine = avLine.substring(eqSign + 1);
- if(avLine.startsWith("\"")){
- avLine = avLine.substring(1, avLine.length() - 1);
- }
-
- if(varName.equals("username")){
- if(!avLine.equals(username)){
- //os_printf("AUTH FAIL: username\n");
- return false;
- }
- myUsername = avLine;
- } else if(varName.equals("realm")){
- if(realm != NULL && !avLine.equals(realm)){
- //os_printf("AUTH FAIL: realm\n");
- return false;
- }
- myRealm = avLine;
- } else if(varName.equals("nonce")){
- if(nonce != NULL && !avLine.equals(nonce)){
- //os_printf("AUTH FAIL: nonce\n");
- return false;
- }
- myNonce = avLine;
- } else if(varName.equals("opaque")){
- if(opaque != NULL && !avLine.equals(opaque)){
- //os_printf("AUTH FAIL: opaque\n");
- return false;
- }
- } else if(varName.equals("uri")){
- if(uri != NULL && !avLine.equals(uri)){
- //os_printf("AUTH FAIL: uri\n");
- return false;
- }
- myUri = avLine;
- } else if(varName.equals("response")){
- myResponse = avLine;
- } else if(varName.equals("qop")){
- myQop = avLine;
- } else if(varName.equals("nc")){
- myNc = avLine;
- } else if(varName.equals("cnonce")){
- myCnonce = avLine;
- }
- } while(nextBreak > 0);
-
- String ha1 = (passwordIsHash) ? String(password) : stringMD5(myUsername + ":" + myRealm + ":" + String(password));
- String ha2 = String(method) + ":" + myUri;
- String response = ha1 + ":" + myNonce + ":" + myNc + ":" + myCnonce + ":" + myQop + ":" + stringMD5(ha2);
-
- if(myResponse.equals(stringMD5(response))){
- //os_printf("AUTH SUCCESS\n");
- return true;
- }
-
- //os_printf("AUTH FAIL: password\n");
- return false;
-}
diff --git a/ESP32/lib/ESPAsyncWebServer/src/WebAuthentication.h b/ESP32/lib/ESPAsyncWebServer/src/WebAuthentication.h
deleted file mode 100644
index ff68265..0000000
--- a/ESP32/lib/ESPAsyncWebServer/src/WebAuthentication.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- Asynchronous WebServer library for Espressif MCUs
-
- Copyright (c) 2016 Hristo Gochkov. All rights reserved.
- This file is part of the esp8266 core for Arduino environment.
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-*/
-
-#ifndef WEB_AUTHENTICATION_H_
-#define WEB_AUTHENTICATION_H_
-
-#include "Arduino.h"
-
-bool checkBasicAuthentication(const char * header, const char * username, const char * password);
-String requestDigestAuthentication(const char * realm);
-bool checkDigestAuthentication(const char * header, const char * method, const char * username, const char * password, const char * realm, bool passwordIsHash, const char * nonce, const char * opaque, const char * uri);
-
-//for storing hashed versions on the device that can be authenticated against
-String generateDigestHash(const char * username, const char * password, const char * realm);
-
-#endif
diff --git a/ESP32/lib/ESPAsyncWebServer/src/WebHandlerImpl.h b/ESP32/lib/ESPAsyncWebServer/src/WebHandlerImpl.h
deleted file mode 100644
index 9b7ba1b..0000000
--- a/ESP32/lib/ESPAsyncWebServer/src/WebHandlerImpl.h
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- Asynchronous WebServer library for Espressif MCUs
-
- Copyright (c) 2016 Hristo Gochkov. All rights reserved.
- This file is part of the esp8266 core for Arduino environment.
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-*/
-#ifndef ASYNCWEBSERVERHANDLERIMPL_H_
-#define ASYNCWEBSERVERHANDLERIMPL_H_
-
-#include
-#ifdef ASYNCWEBSERVER_REGEX
-#include
-#endif
-
-#include "stddef.h"
-#include
-
-class AsyncStaticWebHandler: public AsyncWebHandler {
- using File = fs::File;
- using FS = fs::FS;
- private:
- bool _getFile(AsyncWebServerRequest *request);
- bool _fileExists(AsyncWebServerRequest *request, const String& path);
- uint8_t _countBits(const uint8_t value) const;
- protected:
- FS _fs;
- String _uri;
- String _path;
- String _default_file;
- String _cache_control;
- String _last_modified;
- AwsTemplateProcessor _callback;
- bool _isDir;
- bool _gzipFirst;
- uint8_t _gzipStats;
- public:
- AsyncStaticWebHandler(const char* uri, FS& fs, const char* path, const char* cache_control);
- virtual bool canHandle(AsyncWebServerRequest *request) override final;
- virtual void handleRequest(AsyncWebServerRequest *request) override final;
- AsyncStaticWebHandler& setIsDir(bool isDir);
- AsyncStaticWebHandler& setDefaultFile(const char* filename);
- AsyncStaticWebHandler& setCacheControl(const char* cache_control);
- AsyncStaticWebHandler& setLastModified(const char* last_modified);
- AsyncStaticWebHandler& setLastModified(struct tm* last_modified);
- #ifdef ESP8266
- AsyncStaticWebHandler& setLastModified(time_t last_modified);
- AsyncStaticWebHandler& setLastModified(); //sets to current time. Make sure sntp is runing and time is updated
- #endif
- AsyncStaticWebHandler& setTemplateProcessor(AwsTemplateProcessor newCallback) {_callback = newCallback; return *this;}
-};
-
-class AsyncCallbackWebHandler: public AsyncWebHandler {
- private:
- protected:
- String _uri;
- WebRequestMethodComposite _method;
- ArRequestHandlerFunction _onRequest;
- ArUploadHandlerFunction _onUpload;
- ArBodyHandlerFunction _onBody;
- bool _isRegex;
- public:
- AsyncCallbackWebHandler() : _uri(), _method(HTTP_ANY), _onRequest(NULL), _onUpload(NULL), _onBody(NULL), _isRegex(false) {}
- void setUri(const String& uri){
- _uri = uri;
- _isRegex = uri.startsWith("^") && uri.endsWith("$");
- }
- void setMethod(WebRequestMethodComposite method){ _method = method; }
- void onRequest(ArRequestHandlerFunction fn){ _onRequest = fn; }
- void onUpload(ArUploadHandlerFunction fn){ _onUpload = fn; }
- void onBody(ArBodyHandlerFunction fn){ _onBody = fn; }
-
- virtual bool canHandle(AsyncWebServerRequest *request) override final{
-
- if(!_onRequest)
- return false;
-
- if(!(_method & request->method()))
- return false;
-
-#ifdef ASYNCWEBSERVER_REGEX
- if (_isRegex) {
- std::regex pattern(_uri.c_str());
- std::smatch matches;
- std::string s(request->url().c_str());
- if(std::regex_search(s, matches, pattern)) {
- for (size_t i = 1; i < matches.size(); ++i) { // start from 1
- request->_addPathParam(matches[i].str().c_str());
- }
- } else {
- return false;
- }
- } else
-#endif
- if (_uri.length() && _uri.startsWith("/*.")) {
- String uriTemplate = String (_uri);
- uriTemplate = uriTemplate.substring(uriTemplate.lastIndexOf("."));
- if (!request->url().endsWith(uriTemplate))
- return false;
- }
- else
- if (_uri.length() && _uri.endsWith("*")) {
- String uriTemplate = String(_uri);
- uriTemplate = uriTemplate.substring(0, uriTemplate.length() - 1);
- if (!request->url().startsWith(uriTemplate))
- return false;
- }
- else if(_uri.length() && (_uri != request->url() && !request->url().startsWith(_uri+"/")))
- return false;
-
- request->addInterestingHeader("ANY");
- return true;
- }
-
- virtual void handleRequest(AsyncWebServerRequest *request) override final {
- if((_username != "" && _password != "") && !request->authenticate(_username.c_str(), _password.c_str()))
- return request->requestAuthentication();
- if(_onRequest)
- _onRequest(request);
- else
- request->send(500);
- }
- virtual void handleUpload(AsyncWebServerRequest *request, const String& filename, size_t index, uint8_t *data, size_t len, bool final) override final {
- if((_username != "" && _password != "") && !request->authenticate(_username.c_str(), _password.c_str()))
- return request->requestAuthentication();
- if(_onUpload)
- _onUpload(request, filename, index, data, len, final);
- }
- virtual void handleBody(AsyncWebServerRequest *request, uint8_t *data, size_t len, size_t index, size_t total) override final {
- if((_username != "" && _password != "") && !request->authenticate(_username.c_str(), _password.c_str()))
- return request->requestAuthentication();
- if(_onBody)
- _onBody(request, data, len, index, total);
- }
- virtual bool isRequestHandlerTrivial() override final {return _onRequest ? false : true;}
-};
-
-#endif /* ASYNCWEBSERVERHANDLERIMPL_H_ */
diff --git a/ESP32/lib/ESPAsyncWebServer/src/WebHandlers.cpp b/ESP32/lib/ESPAsyncWebServer/src/WebHandlers.cpp
deleted file mode 100644
index 1f435e6..0000000
--- a/ESP32/lib/ESPAsyncWebServer/src/WebHandlers.cpp
+++ /dev/null
@@ -1,220 +0,0 @@
-/*
- Asynchronous WebServer library for Espressif MCUs
-
- Copyright (c) 2016 Hristo Gochkov. All rights reserved.
- This file is part of the esp8266 core for Arduino environment.
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-*/
-#include "ESPAsyncWebServer.h"
-#include "WebHandlerImpl.h"
-
-AsyncStaticWebHandler::AsyncStaticWebHandler(const char* uri, FS& fs, const char* path, const char* cache_control)
- : _fs(fs), _uri(uri), _path(path), _default_file("index.htm"), _cache_control(cache_control), _last_modified(""), _callback(nullptr)
-{
- // Ensure leading '/'
- if (_uri.length() == 0 || _uri[0] != '/') _uri = "/" + _uri;
- if (_path.length() == 0 || _path[0] != '/') _path = "/" + _path;
-
- // If path ends with '/' we assume a hint that this is a directory to improve performance.
- // However - if it does not end with '/' we, can't assume a file, path can still be a directory.
- _isDir = _path[_path.length()-1] == '/';
-
- // Remove the trailing '/' so we can handle default file
- // Notice that root will be "" not "/"
- if (_uri[_uri.length()-1] == '/') _uri = _uri.substring(0, _uri.length()-1);
- if (_path[_path.length()-1] == '/') _path = _path.substring(0, _path.length()-1);
-
- // Reset stats
- _gzipFirst = false;
- _gzipStats = 0xF8;
-}
-
-AsyncStaticWebHandler& AsyncStaticWebHandler::setIsDir(bool isDir){
- _isDir = isDir;
- return *this;
-}
-
-AsyncStaticWebHandler& AsyncStaticWebHandler::setDefaultFile(const char* filename){
- _default_file = String(filename);
- return *this;
-}
-
-AsyncStaticWebHandler& AsyncStaticWebHandler::setCacheControl(const char* cache_control){
- _cache_control = String(cache_control);
- return *this;
-}
-
-AsyncStaticWebHandler& AsyncStaticWebHandler::setLastModified(const char* last_modified){
- _last_modified = String(last_modified);
- return *this;
-}
-
-AsyncStaticWebHandler& AsyncStaticWebHandler::setLastModified(struct tm* last_modified){
- char result[30];
- strftime (result,30,"%a, %d %b %Y %H:%M:%S %Z", last_modified);
- return setLastModified((const char *)result);
-}
-
-#ifdef ESP8266
-AsyncStaticWebHandler& AsyncStaticWebHandler::setLastModified(time_t last_modified){
- return setLastModified((struct tm *)gmtime(&last_modified));
-}
-
-AsyncStaticWebHandler& AsyncStaticWebHandler::setLastModified(){
- time_t last_modified;
- if(time(&last_modified) == 0) //time is not yet set
- return *this;
- return setLastModified(last_modified);
-}
-#endif
-bool AsyncStaticWebHandler::canHandle(AsyncWebServerRequest *request){
- if(request->method() != HTTP_GET
- || !request->url().startsWith(_uri)
- || !request->isExpectedRequestedConnType(RCT_DEFAULT, RCT_HTTP)
- ){
- return false;
- }
- if (_getFile(request)) {
- // We interested in "If-Modified-Since" header to check if file was modified
- if (_last_modified.length())
- request->addInterestingHeader("If-Modified-Since");
-
- if(_cache_control.length())
- request->addInterestingHeader("If-None-Match");
-
- DEBUGF("[AsyncStaticWebHandler::canHandle] TRUE\n");
- return true;
- }
-
- return false;
-}
-
-bool AsyncStaticWebHandler::_getFile(AsyncWebServerRequest *request)
-{
- // Remove the found uri
- String path = request->url().substring(_uri.length());
-
- // We can skip the file check and look for default if request is to the root of a directory or that request path ends with '/'
- bool canSkipFileCheck = (_isDir && path.length() == 0) || (path.length() && path[path.length()-1] == '/');
-
- path = _path + path;
-
- // Do we have a file or .gz file
- if (!canSkipFileCheck && _fileExists(request, path))
- return true;
-
- // Can't handle if not default file
- if (_default_file.length() == 0)
- return false;
-
- // Try to add default file, ensure there is a trailing '/' ot the path.
- if (path.length() == 0 || path[path.length()-1] != '/')
- path += "/";
- path += _default_file;
-
- return _fileExists(request, path);
-}
-
-#ifdef ESP32
-#define FILE_IS_REAL(f) (f == true && !f.isDirectory())
-#else
-#define FILE_IS_REAL(f) (f == true)
-#endif
-
-bool AsyncStaticWebHandler::_fileExists(AsyncWebServerRequest *request, const String& path)
-{
- bool fileFound = false;
- bool gzipFound = false;
-
- String gzip = path + ".gz";
-
- if (_gzipFirst) {
- request->_tempFile = _fs.open(gzip, "r");
- gzipFound = FILE_IS_REAL(request->_tempFile);
- if (!gzipFound){
- request->_tempFile = _fs.open(path, "r");
- fileFound = FILE_IS_REAL(request->_tempFile);
- }
- } else {
- request->_tempFile = _fs.open(path, "r");
- fileFound = FILE_IS_REAL(request->_tempFile);
- if (!fileFound){
- request->_tempFile = _fs.open(gzip, "r");
- gzipFound = FILE_IS_REAL(request->_tempFile);
- }
- }
-
- bool found = fileFound || gzipFound;
-
- if (found) {
- // Extract the file name from the path and keep it in _tempObject
- size_t pathLen = path.length();
- char * _tempPath = (char*)malloc(pathLen+1);
- snprintf(_tempPath, pathLen+1, "%s", path.c_str());
- request->_tempObject = (void*)_tempPath;
-
- // Calculate gzip statistic
- _gzipStats = (_gzipStats << 1) + (gzipFound ? 1 : 0);
- if (_gzipStats == 0x00) _gzipFirst = false; // All files are not gzip
- else if (_gzipStats == 0xFF) _gzipFirst = true; // All files are gzip
- else _gzipFirst = _countBits(_gzipStats) > 4; // IF we have more gzip files - try gzip first
- }
-
- return found;
-}
-
-uint8_t AsyncStaticWebHandler::_countBits(const uint8_t value) const
-{
- uint8_t w = value;
- uint8_t n;
- for (n=0; w!=0; n++) w&=w-1;
- return n;
-}
-
-void AsyncStaticWebHandler::handleRequest(AsyncWebServerRequest *request)
-{
- // Get the filename from request->_tempObject and free it
- String filename = String((char*)request->_tempObject);
- free(request->_tempObject);
- request->_tempObject = NULL;
- if((_username != "" && _password != "") && !request->authenticate(_username.c_str(), _password.c_str()))
- return request->requestAuthentication();
-
- if (request->_tempFile == true) {
- String etag = String(request->_tempFile.size());
- if (_last_modified.length() && _last_modified == request->header("If-Modified-Since")) {
- request->_tempFile.close();
- request->send(304); // Not modified
- } else if (_cache_control.length() && request->hasHeader("If-None-Match") && request->header("If-None-Match").equals(etag)) {
- request->_tempFile.close();
- AsyncWebServerResponse * response = new AsyncBasicResponse(304); // Not modified
- response->addHeader("Cache-Control", _cache_control);
- response->addHeader("ETag", etag);
- request->send(response);
- } else {
- AsyncWebServerResponse * response = new AsyncFileResponse(request->_tempFile, filename, String(), false, _callback);
- if (_last_modified.length())
- response->addHeader("Last-Modified", _last_modified);
- if (_cache_control.length()){
- response->addHeader("Cache-Control", _cache_control);
- response->addHeader("ETag", etag);
- }
- request->send(response);
- }
- } else {
- request->send(404);
- }
-}
diff --git a/ESP32/lib/ESPAsyncWebServer/src/WebRequest.cpp b/ESP32/lib/ESPAsyncWebServer/src/WebRequest.cpp
deleted file mode 100644
index bbce5ca..0000000
--- a/ESP32/lib/ESPAsyncWebServer/src/WebRequest.cpp
+++ /dev/null
@@ -1,1008 +0,0 @@
-/*
- Asynchronous WebServer library for Espressif MCUs
-
- Copyright (c) 2016 Hristo Gochkov. All rights reserved.
- This file is part of the esp8266 core for Arduino environment.
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-*/
-#include "ESPAsyncWebServer.h"
-#include "WebResponseImpl.h"
-#include "WebAuthentication.h"
-
-#ifndef ESP8266
-#define os_strlen strlen
-#endif
-
-static const String SharedEmptyString = String();
-
-#define __is_param_char(c) ((c) && ((c) != '{') && ((c) != '[') && ((c) != '&') && ((c) != '='))
-
-enum { PARSE_REQ_START, PARSE_REQ_HEADERS, PARSE_REQ_BODY, PARSE_REQ_END, PARSE_REQ_FAIL };
-
-AsyncWebServerRequest::AsyncWebServerRequest(AsyncWebServer* s, AsyncClient* c)
- : _client(c)
- , _server(s)
- , _handler(NULL)
- , _response(NULL)
- , _temp()
- , _parseState(0)
- , _version(0)
- , _method(HTTP_ANY)
- , _url()
- , _host()
- , _contentType()
- , _boundary()
- , _authorization()
- , _reqconntype(RCT_HTTP)
- , _isDigest(false)
- , _isMultipart(false)
- , _isPlainPost(false)
- , _expectingContinue(false)
- , _contentLength(0)
- , _parsedLength(0)
- , _headers(LinkedList([](AsyncWebHeader *h){ delete h; }))
- , _params(LinkedList([](AsyncWebParameter *p){ delete p; }))
- , _pathParams(LinkedList([](String *p){ delete p; }))
- , _multiParseState(0)
- , _boundaryPosition(0)
- , _itemStartIndex(0)
- , _itemSize(0)
- , _itemName()
- , _itemFilename()
- , _itemType()
- , _itemValue()
- , _itemBuffer(0)
- , _itemBufferIndex(0)
- , _itemIsFile(false)
- , _tempObject(NULL)
-{
- c->onError([](void *r, AsyncClient* c, int8_t error){ (void)c; AsyncWebServerRequest *req = (AsyncWebServerRequest*)r; req->_onError(error); }, this);
- c->onAck([](void *r, AsyncClient* c, size_t len, uint32_t time){ (void)c; AsyncWebServerRequest *req = (AsyncWebServerRequest*)r; req->_onAck(len, time); }, this);
- c->onDisconnect([](void *r, AsyncClient* c){ AsyncWebServerRequest *req = (AsyncWebServerRequest*)r; req->_onDisconnect(); delete c; }, this);
- c->onTimeout([](void *r, AsyncClient* c, uint32_t time){ (void)c; AsyncWebServerRequest *req = (AsyncWebServerRequest*)r; req->_onTimeout(time); }, this);
- c->onData([](void *r, AsyncClient* c, void *buf, size_t len){ (void)c; AsyncWebServerRequest *req = (AsyncWebServerRequest*)r; req->_onData(buf, len); }, this);
- c->onPoll([](void *r, AsyncClient* c){ (void)c; AsyncWebServerRequest *req = ( AsyncWebServerRequest*)r; req->_onPoll(); }, this);
-}
-
-AsyncWebServerRequest::~AsyncWebServerRequest(){
- _headers.free();
-
- _params.free();
- _pathParams.free();
-
- _interestingHeaders.free();
-
- if(_response != NULL){
- delete _response;
- }
-
- if(_tempObject != NULL){
- free(_tempObject);
- }
-
- if(_tempFile){
- _tempFile.close();
- }
-}
-
-void AsyncWebServerRequest::_onData(void *buf, size_t len){
- size_t i = 0;
- while (true) {
-
- if(_parseState < PARSE_REQ_BODY){
- // Find new line in buf
- char *str = (char*)buf;
- for (i = 0; i < len; i++) {
- if (str[i] == '\n') {
- break;
- }
- }
- if (i == len) { // No new line, just add the buffer in _temp
- char ch = str[len-1];
- str[len-1] = 0;
- _temp.reserve(_temp.length()+len);
- _temp.concat(str);
- _temp.concat(ch);
- } else { // Found new line - extract it and parse
- str[i] = 0; // Terminate the string at the end of the line.
- _temp.concat(str);
- _temp.trim();
- _parseLine();
- if (++i < len) {
- // Still have more buffer to process
- buf = str+i;
- len-= i;
- continue;
- }
- }
- } else if(_parseState == PARSE_REQ_BODY){
- // A handler should be already attached at this point in _parseLine function.
- // If handler does nothing (_onRequest is NULL), we don't need to really parse the body.
- const bool needParse = _handler && !_handler->isRequestHandlerTrivial();
- if(_isMultipart){
- if(needParse){
- size_t i;
- for(i=0; ihandleBody(this, (uint8_t*)buf, len, _parsedLength, _contentLength);
- _parsedLength += len;
- } else if(needParse) {
- size_t i;
- for(i=0; ihandleRequest(this);
- else send(501);
- }
- }
- break;
- }
-}
-
-void AsyncWebServerRequest::_removeNotInterestingHeaders(){
- if (_interestingHeaders.containsIgnoreCase("ANY")) return; // nothing to do
- for(const auto& header: _headers){
- if(!_interestingHeaders.containsIgnoreCase(header->name().c_str())){
- _headers.remove(header);
- }
- }
-}
-
-void AsyncWebServerRequest::_onPoll(){
- //os_printf("p\n");
- if(_response != NULL && _client != NULL && _client->canSend() && !_response->_finished()){
- _response->_ack(this, 0, 0);
- }
-}
-
-void AsyncWebServerRequest::_onAck(size_t len, uint32_t time){
- //os_printf("a:%u:%u\n", len, time);
- if(_response != NULL){
- if(!_response->_finished()){
- _response->_ack(this, len, time);
- } else {
- AsyncWebServerResponse* r = _response;
- _response = NULL;
- delete r;
- }
- }
-}
-
-void AsyncWebServerRequest::_onError(int8_t error){
- (void)error;
-}
-
-void AsyncWebServerRequest::_onTimeout(uint32_t time){
- (void)time;
- //os_printf("TIMEOUT: %u, state: %s\n", time, _client->stateToString());
- _client->close();
-}
-
-void AsyncWebServerRequest::onDisconnect (ArDisconnectHandler fn){
- _onDisconnectfn=fn;
-}
-
-void AsyncWebServerRequest::_onDisconnect(){
- //os_printf("d\n");
- if(_onDisconnectfn) {
- _onDisconnectfn();
- }
- _server->_handleDisconnect(this);
-}
-
-void AsyncWebServerRequest::_addParam(AsyncWebParameter *p){
- _params.add(p);
-}
-
-void AsyncWebServerRequest::_addPathParam(const char *p){
- _pathParams.add(new String(p));
-}
-
-void AsyncWebServerRequest::_addGetParams(const String& params){
- size_t start = 0;
- while (start < params.length()){
- int end = params.indexOf('&', start);
- if (end < 0) end = params.length();
- int equal = params.indexOf('=', start);
- if (equal < 0 || equal > end) equal = end;
- String name = params.substring(start, equal);
- String value = equal + 1 < end ? params.substring(equal + 1, end) : String();
- _addParam(new AsyncWebParameter(urlDecode(name), urlDecode(value)));
- start = end + 1;
- }
-}
-
-bool AsyncWebServerRequest::_parseReqHead(){
- // Split the head into method, url and version
- int index = _temp.indexOf(' ');
- String m = _temp.substring(0, index);
- index = _temp.indexOf(' ', index+1);
- String u = _temp.substring(m.length()+1, index);
- _temp = _temp.substring(index+1);
-
- if(m == "GET"){
- _method = HTTP_GET;
- } else if(m == "POST"){
- _method = HTTP_POST;
- } else if(m == "DELETE"){
- _method = HTTP_DELETE;
- } else if(m == "PUT"){
- _method = HTTP_PUT;
- } else if(m == "PATCH"){
- _method = HTTP_PATCH;
- } else if(m == "HEAD"){
- _method = HTTP_HEAD;
- } else if(m == "OPTIONS"){
- _method = HTTP_OPTIONS;
- }
-
- String g = String();
- index = u.indexOf('?');
- if(index > 0){
- g = u.substring(index +1);
- u = u.substring(0, index);
- }
- _url = urlDecode(u);
- _addGetParams(g);
-
- if(!_temp.startsWith("HTTP/1.0"))
- _version = 1;
-
- _temp = String();
- return true;
-}
-
-bool strContains(String src, String find, bool mindcase = true) {
- int pos=0, i=0;
- const int slen = src.length();
- const int flen = find.length();
-
- if (slen < flen) return false;
- while (pos <= (slen - flen)) {
- for (i=0; i < flen; i++) {
- if (mindcase) {
- if (src[pos+i] != find[i]) i = flen + 1; // no match
- } else if (tolower(src[pos+i]) != tolower(find[i])) i = flen + 1; // no match
- }
- if (i == flen) return true;
- pos++;
- }
- return false;
-}
-
-bool AsyncWebServerRequest::_parseReqHeader(){
- int index = _temp.indexOf(':');
- if(index){
- String name = _temp.substring(0, index);
- String value = _temp.substring(index + 2);
- if(name.equalsIgnoreCase("Host")){
- _host = value;
- } else if(name.equalsIgnoreCase("Content-Type")){
- _contentType = value.substring(0, value.indexOf(';'));
- if (value.startsWith("multipart/")){
- _boundary = value.substring(value.indexOf('=')+1);
- _boundary.replace("\"","");
- _isMultipart = true;
- }
- } else if(name.equalsIgnoreCase("Content-Length")){
- _contentLength = atoi(value.c_str());
- } else if(name.equalsIgnoreCase("Expect") && value == "100-continue"){
- _expectingContinue = true;
- } else if(name.equalsIgnoreCase("Authorization")){
- if(value.length() > 5 && value.substring(0,5).equalsIgnoreCase("Basic")){
- _authorization = value.substring(6);
- } else if(value.length() > 6 && value.substring(0,6).equalsIgnoreCase("Digest")){
- _isDigest = true;
- _authorization = value.substring(7);
- }
- } else {
- if(name.equalsIgnoreCase("Upgrade") && value.equalsIgnoreCase("websocket")){
- // WebSocket request can be uniquely identified by header: [Upgrade: websocket]
- _reqconntype = RCT_WS;
- } else {
- if(name.equalsIgnoreCase("Accept") && strContains(value, "text/event-stream", false)){
- // WebEvent request can be uniquely identified by header: [Accept: text/event-stream]
- _reqconntype = RCT_EVENT;
- }
- }
- }
- _headers.add(new AsyncWebHeader(name, value));
- }
- _temp = String();
- return true;
-}
-
-void AsyncWebServerRequest::_parsePlainPostChar(uint8_t data){
- if(data && (char)data != '&')
- _temp += (char)data;
- if(!data || (char)data == '&' || _parsedLength == _contentLength){
- String name = "body";
- String value = _temp;
- if(!_temp.startsWith("{") && !_temp.startsWith("[") && _temp.indexOf('=') > 0){
- name = _temp.substring(0, _temp.indexOf('='));
- value = _temp.substring(_temp.indexOf('=') + 1);
- }
- _addParam(new AsyncWebParameter(urlDecode(name), urlDecode(value), true));
- _temp = String();
- }
-}
-
-void AsyncWebServerRequest::_handleUploadByte(uint8_t data, bool last){
- _itemBuffer[_itemBufferIndex++] = data;
-
- if(last || _itemBufferIndex == 1460){
- //check if authenticated before calling the upload
- if(_handler)
- _handler->handleUpload(this, _itemFilename, _itemSize - _itemBufferIndex, _itemBuffer, _itemBufferIndex, false);
- _itemBufferIndex = 0;
- }
-}
-
-enum {
- EXPECT_BOUNDARY,
- PARSE_HEADERS,
- WAIT_FOR_RETURN1,
- EXPECT_FEED1,
- EXPECT_DASH1,
- EXPECT_DASH2,
- BOUNDARY_OR_DATA,
- DASH3_OR_RETURN2,
- EXPECT_FEED2,
- PARSING_FINISHED,
- PARSE_ERROR
-};
-
-void AsyncWebServerRequest::_parseMultipartPostByte(uint8_t data, bool last){
-#define itemWriteByte(b) do { _itemSize++; if(_itemIsFile) _handleUploadByte(b, last); else _itemValue+=(char)(b); } while(0)
-
- if(!_parsedLength){
- _multiParseState = EXPECT_BOUNDARY;
- _temp = String();
- _itemName = String();
- _itemFilename = String();
- _itemType = String();
- }
-
- if(_multiParseState == WAIT_FOR_RETURN1){
- if(data != '\r'){
- itemWriteByte(data);
- } else {
- _multiParseState = EXPECT_FEED1;
- }
- } else if(_multiParseState == EXPECT_BOUNDARY){
- if(_parsedLength < 2 && data != '-'){
- _multiParseState = PARSE_ERROR;
- return;
- } else if(_parsedLength - 2 < _boundary.length() && _boundary.c_str()[_parsedLength - 2] != data){
- _multiParseState = PARSE_ERROR;
- return;
- } else if(_parsedLength - 2 == _boundary.length() && data != '\r'){
- _multiParseState = PARSE_ERROR;
- return;
- } else if(_parsedLength - 3 == _boundary.length()){
- if(data != '\n'){
- _multiParseState = PARSE_ERROR;
- return;
- }
- _multiParseState = PARSE_HEADERS;
- _itemIsFile = false;
- }
- } else if(_multiParseState == PARSE_HEADERS){
- if((char)data != '\r' && (char)data != '\n')
- _temp += (char)data;
- if((char)data == '\n'){
- if(_temp.length()){
- if(_temp.length() > 12 && _temp.substring(0, 12).equalsIgnoreCase("Content-Type")){
- _itemType = _temp.substring(14);
- _itemIsFile = true;
- } else if(_temp.length() > 19 && _temp.substring(0, 19).equalsIgnoreCase("Content-Disposition")){
- _temp = _temp.substring(_temp.indexOf(';') + 2);
- while(_temp.indexOf(';') > 0){
- String name = _temp.substring(0, _temp.indexOf('='));
- String nameVal = _temp.substring(_temp.indexOf('=') + 2, _temp.indexOf(';') - 1);
- if(name == "name"){
- _itemName = nameVal;
- } else if(name == "filename"){
- _itemFilename = nameVal;
- _itemIsFile = true;
- }
- _temp = _temp.substring(_temp.indexOf(';') + 2);
- }
- String name = _temp.substring(0, _temp.indexOf('='));
- String nameVal = _temp.substring(_temp.indexOf('=') + 2, _temp.length() - 1);
- if(name == "name"){
- _itemName = nameVal;
- } else if(name == "filename"){
- _itemFilename = nameVal;
- _itemIsFile = true;
- }
- }
- _temp = String();
- } else {
- _multiParseState = WAIT_FOR_RETURN1;
- //value starts from here
- _itemSize = 0;
- _itemStartIndex = _parsedLength;
- _itemValue = String();
- if(_itemIsFile){
- if(_itemBuffer)
- free(_itemBuffer);
- _itemBuffer = (uint8_t*)malloc(1460);
- if(_itemBuffer == NULL){
- _multiParseState = PARSE_ERROR;
- return;
- }
- _itemBufferIndex = 0;
- }
- }
- }
- } else if(_multiParseState == EXPECT_FEED1){
- if(data != '\n'){
- _multiParseState = WAIT_FOR_RETURN1;
- itemWriteByte('\r'); _parseMultipartPostByte(data, last);
- } else {
- _multiParseState = EXPECT_DASH1;
- }
- } else if(_multiParseState == EXPECT_DASH1){
- if(data != '-'){
- _multiParseState = WAIT_FOR_RETURN1;
- itemWriteByte('\r'); itemWriteByte('\n'); _parseMultipartPostByte(data, last);
- } else {
- _multiParseState = EXPECT_DASH2;
- }
- } else if(_multiParseState == EXPECT_DASH2){
- if(data != '-'){
- _multiParseState = WAIT_FOR_RETURN1;
- itemWriteByte('\r'); itemWriteByte('\n'); itemWriteByte('-'); _parseMultipartPostByte(data, last);
- } else {
- _multiParseState = BOUNDARY_OR_DATA;
- _boundaryPosition = 0;
- }
- } else if(_multiParseState == BOUNDARY_OR_DATA){
- if(_boundaryPosition < _boundary.length() && _boundary.c_str()[_boundaryPosition] != data){
- _multiParseState = WAIT_FOR_RETURN1;
- itemWriteByte('\r'); itemWriteByte('\n'); itemWriteByte('-'); itemWriteByte('-');
- uint8_t i;
- for(i=0; i<_boundaryPosition; i++)
- itemWriteByte(_boundary.c_str()[i]);
- _parseMultipartPostByte(data, last);
- } else if(_boundaryPosition == _boundary.length() - 1){
- _multiParseState = DASH3_OR_RETURN2;
- if(!_itemIsFile){
- _addParam(new AsyncWebParameter(_itemName, _itemValue, true));
- } else {
- if(_itemSize){
- //check if authenticated before calling the upload
- if(_handler) _handler->handleUpload(this, _itemFilename, _itemSize - _itemBufferIndex, _itemBuffer, _itemBufferIndex, true);
- _itemBufferIndex = 0;
- _addParam(new AsyncWebParameter(_itemName, _itemFilename, true, true, _itemSize));
- }
- free(_itemBuffer);
- _itemBuffer = NULL;
- }
-
- } else {
- _boundaryPosition++;
- }
- } else if(_multiParseState == DASH3_OR_RETURN2){
- if(data == '-' && (_contentLength - _parsedLength - 4) != 0){
- //os_printf("ERROR: The parser got to the end of the POST but is expecting %u bytes more!\nDrop an issue so we can have more info on the matter!\n", _contentLength - _parsedLength - 4);
- _contentLength = _parsedLength + 4;//lets close the request gracefully
- }
- if(data == '\r'){
- _multiParseState = EXPECT_FEED2;
- } else if(data == '-' && _contentLength == (_parsedLength + 4)){
- _multiParseState = PARSING_FINISHED;
- } else {
- _multiParseState = WAIT_FOR_RETURN1;
- itemWriteByte('\r'); itemWriteByte('\n'); itemWriteByte('-'); itemWriteByte('-');
- uint8_t i; for(i=0; i<_boundary.length(); i++) itemWriteByte(_boundary.c_str()[i]);
- _parseMultipartPostByte(data, last);
- }
- } else if(_multiParseState == EXPECT_FEED2){
- if(data == '\n'){
- _multiParseState = PARSE_HEADERS;
- _itemIsFile = false;
- } else {
- _multiParseState = WAIT_FOR_RETURN1;
- itemWriteByte('\r'); itemWriteByte('\n'); itemWriteByte('-'); itemWriteByte('-');
- uint8_t i; for(i=0; i<_boundary.length(); i++) itemWriteByte(_boundary.c_str()[i]);
- itemWriteByte('\r'); _parseMultipartPostByte(data, last);
- }
- }
-}
-
-void AsyncWebServerRequest::_parseLine(){
- if(_parseState == PARSE_REQ_START){
- if(!_temp.length()){
- _parseState = PARSE_REQ_FAIL;
- _client->close();
- } else {
- _parseReqHead();
- _parseState = PARSE_REQ_HEADERS;
- }
- return;
- }
-
- if(_parseState == PARSE_REQ_HEADERS){
- if(!_temp.length()){
- //end of headers
- _server->_rewriteRequest(this);
- _server->_attachHandler(this);
- _removeNotInterestingHeaders();
- if(_expectingContinue){
- const char * response = "HTTP/1.1 100 Continue\r\n\r\n";
- _client->write(response, os_strlen(response));
- }
- //check handler for authentication
- if(_contentLength){
- _parseState = PARSE_REQ_BODY;
- } else {
- _parseState = PARSE_REQ_END;
- if(_handler) _handler->handleRequest(this);
- else send(501);
- }
- } else _parseReqHeader();
- }
-}
-
-size_t AsyncWebServerRequest::headers() const{
- return _headers.length();
-}
-
-bool AsyncWebServerRequest::hasHeader(const String& name) const {
- for(const auto& h: _headers){
- if(h->name().equalsIgnoreCase(name)){
- return true;
- }
- }
- return false;
-}
-
-bool AsyncWebServerRequest::hasHeader(const __FlashStringHelper * data) const {
- PGM_P p = reinterpret_cast(data);
- size_t n = 0;
- while (1) {
- if (pgm_read_byte(p+n) == 0) break;
- n += 1;
- }
- char * name = (char*) malloc(n+1);
- name[n] = 0;
- if (name) {
- for(size_t b=0; bname().equalsIgnoreCase(name)){
- return h;
- }
- }
- return nullptr;
-}
-
-AsyncWebHeader* AsyncWebServerRequest::getHeader(const __FlashStringHelper * data) const {
- PGM_P p = reinterpret_cast(data);
- size_t n = strlen_P(p);
- char * name = (char*) malloc(n+1);
- if (name) {
- strcpy_P(name, p);
- AsyncWebHeader* result = getHeader( String(name));
- free(name);
- return result;
- } else {
- return nullptr;
- }
-}
-
-AsyncWebHeader* AsyncWebServerRequest::getHeader(size_t num) const {
- auto header = _headers.nth(num);
- return header ? *header : nullptr;
-}
-
-size_t AsyncWebServerRequest::params() const {
- return _params.length();
-}
-
-bool AsyncWebServerRequest::hasParam(const String& name, bool post, bool file) const {
- for(const auto& p: _params){
- if(p->name() == name && p->isPost() == post && p->isFile() == file){
- return true;
- }
- }
- return false;
-}
-
-bool AsyncWebServerRequest::hasParam(const __FlashStringHelper * data, bool post, bool file) const {
- PGM_P p = reinterpret_cast(data);
- size_t n = strlen_P(p);
-
- char * name = (char*) malloc(n+1);
- name[n] = 0;
- if (name) {
- strcpy_P(name,p);
- bool result = hasParam( name, post, file);
- free(name);
- return result;
- } else {
- return false;
- }
-}
-
-AsyncWebParameter* AsyncWebServerRequest::getParam(const String& name, bool post, bool file) const {
- for(const auto& p: _params){
- if(p->name() == name && p->isPost() == post && p->isFile() == file){
- return p;
- }
- }
- return nullptr;
-}
-
-AsyncWebParameter* AsyncWebServerRequest::getParam(const __FlashStringHelper * data, bool post, bool file) const {
- PGM_P p = reinterpret_cast(data);
- size_t n = strlen_P(p);
- char * name = (char*) malloc(n+1);
- if (name) {
- strcpy_P(name, p);
- AsyncWebParameter* result = getParam(name, post, file);
- free(name);
- return result;
- } else {
- return nullptr;
- }
-}
-
-AsyncWebParameter* AsyncWebServerRequest::getParam(size_t num) const {
- auto param = _params.nth(num);
- return param ? *param : nullptr;
-}
-
-void AsyncWebServerRequest::addInterestingHeader(const String& name){
- if(!_interestingHeaders.containsIgnoreCase(name))
- _interestingHeaders.add(name);
-}
-
-void AsyncWebServerRequest::send(AsyncWebServerResponse *response){
- _response = response;
- if(_response == NULL){
- _client->close(true);
- _onDisconnect();
- return;
- }
- if(!_response->_sourceValid()){
- delete response;
- _response = NULL;
- send(500);
- }
- else {
- _client->setRxTimeout(0);
- _response->_respond(this);
- }
-}
-
-AsyncWebServerResponse * AsyncWebServerRequest::beginResponse(int code, const String& contentType, const String& content){
- return new AsyncBasicResponse(code, contentType, content);
-}
-
-AsyncWebServerResponse * AsyncWebServerRequest::beginResponse(FS &fs, const String& path, const String& contentType, bool download, AwsTemplateProcessor callback){
- if(fs.exists(path) || (!download && fs.exists(path+".gz")))
- return new AsyncFileResponse(fs, path, contentType, download, callback);
- return NULL;
-}
-
-AsyncWebServerResponse * AsyncWebServerRequest::beginResponse(File content, const String& path, const String& contentType, bool download, AwsTemplateProcessor callback){
- if(content == true)
- return new AsyncFileResponse(content, path, contentType, download, callback);
- return NULL;
-}
-
-AsyncWebServerResponse * AsyncWebServerRequest::beginResponse(Stream &stream, const String& contentType, size_t len, AwsTemplateProcessor callback){
- return new AsyncStreamResponse(stream, contentType, len, callback);
-}
-
-AsyncWebServerResponse * AsyncWebServerRequest::beginResponse(const String& contentType, size_t len, AwsResponseFiller callback, AwsTemplateProcessor templateCallback){
- return new AsyncCallbackResponse(contentType, len, callback, templateCallback);
-}
-
-AsyncWebServerResponse * AsyncWebServerRequest::beginChunkedResponse(const String& contentType, AwsResponseFiller callback, AwsTemplateProcessor templateCallback){
- if(_version)
- return new AsyncChunkedResponse(contentType, callback, templateCallback);
- return new AsyncCallbackResponse(contentType, 0, callback, templateCallback);
-}
-
-AsyncResponseStream * AsyncWebServerRequest::beginResponseStream(const String& contentType, size_t bufferSize){
- return new AsyncResponseStream(contentType, bufferSize);
-}
-
-AsyncWebServerResponse * AsyncWebServerRequest::beginResponse_P(int code, const String& contentType, const uint8_t * content, size_t len, AwsTemplateProcessor callback){
- return new AsyncProgmemResponse(code, contentType, content, len, callback);
-}
-
-AsyncWebServerResponse * AsyncWebServerRequest::beginResponse_P(int code, const String& contentType, PGM_P content, AwsTemplateProcessor callback){
- return beginResponse_P(code, contentType, (const uint8_t *)content, strlen_P(content), callback);
-}
-
-void AsyncWebServerRequest::send(int code, const String& contentType, const String& content){
- send(beginResponse(code, contentType, content));
-}
-
-void AsyncWebServerRequest::send(FS &fs, const String& path, const String& contentType, bool download, AwsTemplateProcessor callback){
- if(fs.exists(path) || (!download && fs.exists(path+".gz"))){
- send(beginResponse(fs, path, contentType, download, callback));
- } else send(404);
-}
-
-void AsyncWebServerRequest::send(File content, const String& path, const String& contentType, bool download, AwsTemplateProcessor callback){
- if(content == true){
- send(beginResponse(content, path, contentType, download, callback));
- } else send(404);
-}
-
-void AsyncWebServerRequest::send(Stream &stream, const String& contentType, size_t len, AwsTemplateProcessor callback){
- send(beginResponse(stream, contentType, len, callback));
-}
-
-void AsyncWebServerRequest::send(const String& contentType, size_t len, AwsResponseFiller callback, AwsTemplateProcessor templateCallback){
- send(beginResponse(contentType, len, callback, templateCallback));
-}
-
-void AsyncWebServerRequest::sendChunked(const String& contentType, AwsResponseFiller callback, AwsTemplateProcessor templateCallback){
- send(beginChunkedResponse(contentType, callback, templateCallback));
-}
-
-void AsyncWebServerRequest::send_P(int code, const String& contentType, const uint8_t * content, size_t len, AwsTemplateProcessor callback){
- send(beginResponse_P(code, contentType, content, len, callback));
-}
-
-void AsyncWebServerRequest::send_P(int code, const String& contentType, PGM_P content, AwsTemplateProcessor callback){
- send(beginResponse_P(code, contentType, content, callback));
-}
-
-void AsyncWebServerRequest::redirect(const String& url){
- AsyncWebServerResponse * response = beginResponse(302);
- response->addHeader("Location",url);
- send(response);
-}
-
-bool AsyncWebServerRequest::authenticate(const char * username, const char * password, const char * realm, bool passwordIsHash){
- if(_authorization.length()){
- if(_isDigest)
- return checkDigestAuthentication(_authorization.c_str(), methodToString(), username, password, realm, passwordIsHash, NULL, NULL, NULL);
- else if(!passwordIsHash)
- return checkBasicAuthentication(_authorization.c_str(), username, password);
- else
- return _authorization.equals(password);
- }
- return false;
-}
-
-bool AsyncWebServerRequest::authenticate(const char * hash){
- if(!_authorization.length() || hash == NULL)
- return false;
-
- if(_isDigest){
- String hStr = String(hash);
- int separator = hStr.indexOf(":");
- if(separator <= 0)
- return false;
- String username = hStr.substring(0, separator);
- hStr = hStr.substring(separator + 1);
- separator = hStr.indexOf(":");
- if(separator <= 0)
- return false;
- String realm = hStr.substring(0, separator);
- hStr = hStr.substring(separator + 1);
- return checkDigestAuthentication(_authorization.c_str(), methodToString(), username.c_str(), hStr.c_str(), realm.c_str(), true, NULL, NULL, NULL);
- }
-
- return (_authorization.equals(hash));
-}
-
-void AsyncWebServerRequest::requestAuthentication(const char * realm, bool isDigest){
- AsyncWebServerResponse * r = beginResponse(401);
- if(!isDigest && realm == NULL){
- r->addHeader("WWW-Authenticate", "Basic realm=\"Login Required\"");
- } else if(!isDigest){
- String header = "Basic realm=\"";
- header.concat(realm);
- header.concat("\"");
- r->addHeader("WWW-Authenticate", header);
- } else {
- String header = "Digest ";
- header.concat(requestDigestAuthentication(realm));
- r->addHeader("WWW-Authenticate", header);
- }
- send(r);
-}
-
-bool AsyncWebServerRequest::hasArg(const char* name) const {
- for(const auto& arg: _params){
- if(arg->name() == name){
- return true;
- }
- }
- return false;
-}
-
-bool AsyncWebServerRequest::hasArg(const __FlashStringHelper * data) const {
- PGM_P p = reinterpret_cast(data);
- size_t n = strlen_P(p);
- char * name = (char*) malloc(n+1);
- if (name) {
- strcpy_P(name, p);
- bool result = hasArg( name );
- free(name);
- return result;
- } else {
- return false;
- }
-}
-
-
-const String& AsyncWebServerRequest::arg(const String& name) const {
- for(const auto& arg: _params){
- if(arg->name() == name){
- return arg->value();
- }
- }
- return SharedEmptyString;
-}
-
-const String& AsyncWebServerRequest::arg(const __FlashStringHelper * data) const {
- PGM_P p = reinterpret_cast(data);
- size_t n = strlen_P(p);
- char * name = (char*) malloc(n+1);
- if (name) {
- strcpy_P(name, p);
- const String & result = arg( String(name) );
- free(name);
- return result;
- } else {
- return SharedEmptyString;
- }
-
-}
-
-const String& AsyncWebServerRequest::arg(size_t i) const {
- return getParam(i)->value();
-}
-
-const String& AsyncWebServerRequest::argName(size_t i) const {
- return getParam(i)->name();
-}
-
-const String& AsyncWebServerRequest::pathArg(size_t i) const {
- auto param = _pathParams.nth(i);
- return param ? **param : SharedEmptyString;
-}
-
-const String& AsyncWebServerRequest::header(const char* name) const {
- AsyncWebHeader* h = getHeader(String(name));
- return h ? h->value() : SharedEmptyString;
-}
-
-const String& AsyncWebServerRequest::header(const __FlashStringHelper * data) const {
- PGM_P p = reinterpret_cast(data);
- size_t n = strlen_P(p);
- char * name = (char*) malloc(n+1);
- if (name) {
- strcpy_P(name, p);
- const String & result = header( (const char *)name );
- free(name);
- return result;
- } else {
- return SharedEmptyString;
- }
-};
-
-
-const String& AsyncWebServerRequest::header(size_t i) const {
- AsyncWebHeader* h = getHeader(i);
- return h ? h->value() : SharedEmptyString;
-}
-
-const String& AsyncWebServerRequest::headerName(size_t i) const {
- AsyncWebHeader* h = getHeader(i);
- return h ? h->name() : SharedEmptyString;
-}
-
-String AsyncWebServerRequest::urlDecode(const String& text) const {
- char temp[] = "0x00";
- unsigned int len = text.length();
- unsigned int i = 0;
- String decoded = String();
- decoded.reserve(len); // Allocate the string internal buffer - never longer from source text
- while (i < len){
- char decodedChar;
- char encodedChar = text.charAt(i++);
- if ((encodedChar == '%') && (i + 1 < len)){
- temp[2] = text.charAt(i++);
- temp[3] = text.charAt(i++);
- decodedChar = strtol(temp, NULL, 16);
- } else if (encodedChar == '+') {
- decodedChar = ' ';
- } else {
- decodedChar = encodedChar; // normal ascii char
- }
- decoded.concat(decodedChar);
- }
- return decoded;
-}
-
-
-const char * AsyncWebServerRequest::methodToString() const {
- if(_method == HTTP_ANY) return "ANY";
- else if(_method & HTTP_GET) return "GET";
- else if(_method & HTTP_POST) return "POST";
- else if(_method & HTTP_DELETE) return "DELETE";
- else if(_method & HTTP_PUT) return "PUT";
- else if(_method & HTTP_PATCH) return "PATCH";
- else if(_method & HTTP_HEAD) return "HEAD";
- else if(_method & HTTP_OPTIONS) return "OPTIONS";
- return "UNKNOWN";
-}
-
-const char *AsyncWebServerRequest::requestedConnTypeToString() const {
- switch (_reqconntype) {
- case RCT_NOT_USED: return "RCT_NOT_USED";
- case RCT_DEFAULT: return "RCT_DEFAULT";
- case RCT_HTTP: return "RCT_HTTP";
- case RCT_WS: return "RCT_WS";
- case RCT_EVENT: return "RCT_EVENT";
- default: return "ERROR";
- }
-}
-
-bool AsyncWebServerRequest::isExpectedRequestedConnType(RequestedConnectionType erct1, RequestedConnectionType erct2, RequestedConnectionType erct3) {
- bool res = false;
- if ((erct1 != RCT_NOT_USED) && (erct1 == _reqconntype)) res = true;
- if ((erct2 != RCT_NOT_USED) && (erct2 == _reqconntype)) res = true;
- if ((erct3 != RCT_NOT_USED) && (erct3 == _reqconntype)) res = true;
- return res;
-}
diff --git a/ESP32/lib/ESPAsyncWebServer/src/WebResponseImpl.h b/ESP32/lib/ESPAsyncWebServer/src/WebResponseImpl.h
deleted file mode 100644
index 9a64e3a..0000000
--- a/ESP32/lib/ESPAsyncWebServer/src/WebResponseImpl.h
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- Asynchronous WebServer library for Espressif MCUs
-
- Copyright (c) 2016 Hristo Gochkov. All rights reserved.
- This file is part of the esp8266 core for Arduino environment.
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-*/
-#ifndef ASYNCWEBSERVERRESPONSEIMPL_H_
-#define ASYNCWEBSERVERRESPONSEIMPL_H_
-
-#ifdef Arduino_h
-// arduino is not compatible with std::vector
-#undef min
-#undef max
-#endif
-#include
-// It is possible to restore these defines, but one can use _min and _max instead. Or std::min, std::max.
-
-class AsyncBasicResponse: public AsyncWebServerResponse {
- private:
- String _content;
- public:
- AsyncBasicResponse(int code, const String& contentType=String(), const String& content=String());
- void _respond(AsyncWebServerRequest *request);
- size_t _ack(AsyncWebServerRequest *request, size_t len, uint32_t time);
- bool _sourceValid() const { return true; }
-};
-
-class AsyncAbstractResponse: public AsyncWebServerResponse {
- private:
- String _head;
- // Data is inserted into cache at begin().
- // This is inefficient with vector, but if we use some other container,
- // we won't be able to access it as contiguous array of bytes when reading from it,
- // so by gaining performance in one place, we'll lose it in another.
- std::vector _cache;
- size_t _readDataFromCacheOrContent(uint8_t* data, const size_t len);
- size_t _fillBufferAndProcessTemplates(uint8_t* buf, size_t maxLen);
- protected:
- AwsTemplateProcessor _callback;
- public:
- AsyncAbstractResponse(AwsTemplateProcessor callback=nullptr);
- void _respond(AsyncWebServerRequest *request);
- size_t _ack(AsyncWebServerRequest *request, size_t len, uint32_t time);
- bool _sourceValid() const { return false; }
- virtual size_t _fillBuffer(uint8_t *buf __attribute__((unused)), size_t maxLen __attribute__((unused))) { return 0; }
-};
-
-#ifndef TEMPLATE_PLACEHOLDER
-#define TEMPLATE_PLACEHOLDER '%'
-#endif
-
-#define TEMPLATE_PARAM_NAME_LENGTH 32
-class AsyncFileResponse: public AsyncAbstractResponse {
- using File = fs::File;
- using FS = fs::FS;
- private:
- File _content;
- String _path;
- void _setContentType(const String& path);
- public:
- AsyncFileResponse(FS &fs, const String& path, const String& contentType=String(), bool download=false, AwsTemplateProcessor callback=nullptr);
- AsyncFileResponse(File content, const String& path, const String& contentType=String(), bool download=false, AwsTemplateProcessor callback=nullptr);
- ~AsyncFileResponse();
- bool _sourceValid() const { return !!(_content); }
- virtual size_t _fillBuffer(uint8_t *buf, size_t maxLen) override;
-};
-
-class AsyncStreamResponse: public AsyncAbstractResponse {
- private:
- Stream *_content;
- public:
- AsyncStreamResponse(Stream &stream, const String& contentType, size_t len, AwsTemplateProcessor callback=nullptr);
- bool _sourceValid() const { return !!(_content); }
- virtual size_t _fillBuffer(uint8_t *buf, size_t maxLen) override;
-};
-
-class AsyncCallbackResponse: public AsyncAbstractResponse {
- private:
- AwsResponseFiller _content;
- size_t _filledLength;
- public:
- AsyncCallbackResponse(const String& contentType, size_t len, AwsResponseFiller callback, AwsTemplateProcessor templateCallback=nullptr);
- bool _sourceValid() const { return !!(_content); }
- virtual size_t _fillBuffer(uint8_t *buf, size_t maxLen) override;
-};
-
-class AsyncChunkedResponse: public AsyncAbstractResponse {
- private:
- AwsResponseFiller _content;
- size_t _filledLength;
- public:
- AsyncChunkedResponse(const String& contentType, AwsResponseFiller callback, AwsTemplateProcessor templateCallback=nullptr);
- bool _sourceValid() const { return !!(_content); }
- virtual size_t _fillBuffer(uint8_t *buf, size_t maxLen) override;
-};
-
-class AsyncProgmemResponse: public AsyncAbstractResponse {
- private:
- const uint8_t * _content;
- size_t _readLength;
- public:
- AsyncProgmemResponse(int code, const String& contentType, const uint8_t * content, size_t len, AwsTemplateProcessor callback=nullptr);
- bool _sourceValid() const { return true; }
- virtual size_t _fillBuffer(uint8_t *buf, size_t maxLen) override;
-};
-
-class cbuf;
-
-class AsyncResponseStream: public AsyncAbstractResponse, public Print {
- private:
- cbuf *_content;
- public:
- AsyncResponseStream(const String& contentType, size_t bufferSize);
- ~AsyncResponseStream();
- bool _sourceValid() const { return (_state < RESPONSE_END); }
- virtual size_t _fillBuffer(uint8_t *buf, size_t maxLen) override;
- size_t write(const uint8_t *data, size_t len);
- size_t write(uint8_t data);
- using Print::write;
-};
-
-#endif /* ASYNCWEBSERVERRESPONSEIMPL_H_ */
diff --git a/ESP32/lib/ESPAsyncWebServer/src/WebResponses.cpp b/ESP32/lib/ESPAsyncWebServer/src/WebResponses.cpp
deleted file mode 100644
index a22e991..0000000
--- a/ESP32/lib/ESPAsyncWebServer/src/WebResponses.cpp
+++ /dev/null
@@ -1,699 +0,0 @@
-/*
- Asynchronous WebServer library for Espressif MCUs
-
- Copyright (c) 2016 Hristo Gochkov. All rights reserved.
- This file is part of the esp8266 core for Arduino environment.
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-*/
-#include "ESPAsyncWebServer.h"
-#include "WebResponseImpl.h"
-#include "cbuf.h"
-
-// Since ESP8266 does not link memchr by default, here's its implementation.
-void* memchr(void* ptr, int ch, size_t count)
-{
- unsigned char* p = static_cast(ptr);
- while(count--)
- if(*p++ == static_cast(ch))
- return --p;
- return nullptr;
-}
-
-
-/*
- * Abstract Response
- * */
-const char* AsyncWebServerResponse::_responseCodeToString(int code) {
- switch (code) {
- case 100: return "Continue";
- case 101: return "Switching Protocols";
- case 200: return "OK";
- case 201: return "Created";
- case 202: return "Accepted";
- case 203: return "Non-Authoritative Information";
- case 204: return "No Content";
- case 205: return "Reset Content";
- case 206: return "Partial Content";
- case 300: return "Multiple Choices";
- case 301: return "Moved Permanently";
- case 302: return "Found";
- case 303: return "See Other";
- case 304: return "Not Modified";
- case 305: return "Use Proxy";
- case 307: return "Temporary Redirect";
- case 400: return "Bad Request";
- case 401: return "Unauthorized";
- case 402: return "Payment Required";
- case 403: return "Forbidden";
- case 404: return "Not Found";
- case 405: return "Method Not Allowed";
- case 406: return "Not Acceptable";
- case 407: return "Proxy Authentication Required";
- case 408: return "Request Time-out";
- case 409: return "Conflict";
- case 410: return "Gone";
- case 411: return "Length Required";
- case 412: return "Precondition Failed";
- case 413: return "Request Entity Too Large";
- case 414: return "Request-URI Too Large";
- case 415: return "Unsupported Media Type";
- case 416: return "Requested range not satisfiable";
- case 417: return "Expectation Failed";
- case 500: return "Internal Server Error";
- case 501: return "Not Implemented";
- case 502: return "Bad Gateway";
- case 503: return "Service Unavailable";
- case 504: return "Gateway Time-out";
- case 505: return "HTTP Version not supported";
- default: return "";
- }
-}
-
-AsyncWebServerResponse::AsyncWebServerResponse()
- : _code(0)
- , _headers(LinkedList([](AsyncWebHeader *h){ delete h; }))
- , _contentType()
- , _contentLength(0)
- , _sendContentLength(true)
- , _chunked(false)
- , _headLength(0)
- , _sentLength(0)
- , _ackedLength(0)
- , _writtenLength(0)
- , _state(RESPONSE_SETUP)
-{
- for(auto header: DefaultHeaders::Instance()) {
- _headers.add(new AsyncWebHeader(header->name(), header->value()));
- }
-}
-
-AsyncWebServerResponse::~AsyncWebServerResponse(){
- _headers.free();
-}
-
-void AsyncWebServerResponse::setCode(int code){
- if(_state == RESPONSE_SETUP)
- _code = code;
-}
-
-void AsyncWebServerResponse::setContentLength(size_t len){
- if(_state == RESPONSE_SETUP)
- _contentLength = len;
-}
-
-void AsyncWebServerResponse::setContentType(const String& type){
- if(_state == RESPONSE_SETUP)
- _contentType = type;
-}
-
-void AsyncWebServerResponse::addHeader(const String& name, const String& value){
- _headers.add(new AsyncWebHeader(name, value));
-}
-
-String AsyncWebServerResponse::_assembleHead(uint8_t version){
- if(version){
- addHeader("Accept-Ranges","none");
- if(_chunked)
- addHeader("Transfer-Encoding","chunked");
- }
- String out = String();
- int bufSize = 300;
- char buf[bufSize];
-
- snprintf(buf, bufSize, "HTTP/1.%d %d %s\r\n", version, _code, _responseCodeToString(_code));
- out.concat(buf);
-
- if(_sendContentLength) {
- snprintf(buf, bufSize, "Content-Length: %d\r\n", _contentLength);
- out.concat(buf);
- }
- if(_contentType.length()) {
- snprintf(buf, bufSize, "Content-Type: %s\r\n", _contentType.c_str());
- out.concat(buf);
- }
-
- for(const auto& header: _headers){
- snprintf(buf, bufSize, "%s: %s\r\n", header->name().c_str(), header->value().c_str());
- out.concat(buf);
- }
- _headers.free();
-
- out.concat("\r\n");
- _headLength = out.length();
- return out;
-}
-
-bool AsyncWebServerResponse::_started() const { return _state > RESPONSE_SETUP; }
-bool AsyncWebServerResponse::_finished() const { return _state > RESPONSE_WAIT_ACK; }
-bool AsyncWebServerResponse::_failed() const { return _state == RESPONSE_FAILED; }
-bool AsyncWebServerResponse::_sourceValid() const { return false; }
-void AsyncWebServerResponse::_respond(AsyncWebServerRequest *request){ _state = RESPONSE_END; request->client()->close(); }
-size_t AsyncWebServerResponse::_ack(AsyncWebServerRequest *request, size_t len, uint32_t time){ (void)request; (void)len; (void)time; return 0; }
-
-/*
- * String/Code Response
- * */
-AsyncBasicResponse::AsyncBasicResponse(int code, const String& contentType, const String& content){
- _code = code;
- _content = content;
- _contentType = contentType;
- if(_content.length()){
- _contentLength = _content.length();
- if(!_contentType.length())
- _contentType = "text/plain";
- }
- addHeader("Connection","close");
-}
-
-void AsyncBasicResponse::_respond(AsyncWebServerRequest *request){
- _state = RESPONSE_HEADERS;
- String out = _assembleHead(request->version());
- size_t outLen = out.length();
- size_t space = request->client()->space();
- if(!_contentLength && space >= outLen){
- _writtenLength += request->client()->write(out.c_str(), outLen);
- _state = RESPONSE_WAIT_ACK;
- } else if(_contentLength && space >= outLen + _contentLength){
- out += _content;
- outLen += _contentLength;
- _writtenLength += request->client()->write(out.c_str(), outLen);
- _state = RESPONSE_WAIT_ACK;
- } else if(space && space < outLen){
- String partial = out.substring(0, space);
- _content = out.substring(space) + _content;
- _contentLength += outLen - space;
- _writtenLength += request->client()->write(partial.c_str(), partial.length());
- _state = RESPONSE_CONTENT;
- } else if(space > outLen && space < (outLen + _contentLength)){
- size_t shift = space - outLen;
- outLen += shift;
- _sentLength += shift;
- out += _content.substring(0, shift);
- _content = _content.substring(shift);
- _writtenLength += request->client()->write(out.c_str(), outLen);
- _state = RESPONSE_CONTENT;
- } else {
- _content = out + _content;
- _contentLength += outLen;
- _state = RESPONSE_CONTENT;
- }
-}
-
-size_t AsyncBasicResponse::_ack(AsyncWebServerRequest *request, size_t len, uint32_t time){
- (void)time;
- _ackedLength += len;
- if(_state == RESPONSE_CONTENT){
- size_t available = _contentLength - _sentLength;
- size_t space = request->client()->space();
- //we can fit in this packet
- if(space > available){
- _writtenLength += request->client()->write(_content.c_str(), available);
- _content = String();
- _state = RESPONSE_WAIT_ACK;
- return available;
- }
- //send some data, the rest on ack
- String out = _content.substring(0, space);
- _content = _content.substring(space);
- _sentLength += space;
- _writtenLength += request->client()->write(out.c_str(), space);
- return space;
- } else if(_state == RESPONSE_WAIT_ACK){
- if(_ackedLength >= _writtenLength){
- _state = RESPONSE_END;
- }
- }
- return 0;
-}
-
-
-/*
- * Abstract Response
- * */
-
-AsyncAbstractResponse::AsyncAbstractResponse(AwsTemplateProcessor callback): _callback(callback)
-{
- // In case of template processing, we're unable to determine real response size
- if(callback) {
- _contentLength = 0;
- _sendContentLength = false;
- _chunked = true;
- }
-}
-
-void AsyncAbstractResponse::_respond(AsyncWebServerRequest *request){
- addHeader("Connection","close");
- _head = _assembleHead(request->version());
- _state = RESPONSE_HEADERS;
- _ack(request, 0, 0);
-}
-
-size_t AsyncAbstractResponse::_ack(AsyncWebServerRequest *request, size_t len, uint32_t time){
- (void)time;
- if(!_sourceValid()){
- _state = RESPONSE_FAILED;
- request->client()->close();
- return 0;
- }
- _ackedLength += len;
- size_t space = request->client()->space();
-
- size_t headLen = _head.length();
- if(_state == RESPONSE_HEADERS){
- if(space >= headLen){
- _state = RESPONSE_CONTENT;
- space -= headLen;
- } else {
- String out = _head.substring(0, space);
- _head = _head.substring(space);
- _writtenLength += request->client()->write(out.c_str(), out.length());
- return out.length();
- }
- }
-
- if(_state == RESPONSE_CONTENT){
- size_t outLen;
- if(_chunked){
- if(space <= 8){
- return 0;
- }
- outLen = space;
- } else if(!_sendContentLength){
- outLen = space;
- } else {
- outLen = ((_contentLength - _sentLength) > space)?space:(_contentLength - _sentLength);
- }
-
- uint8_t *buf = (uint8_t *)malloc(outLen+headLen);
- if (!buf) {
- // os_printf("_ack malloc %d failed\n", outLen+headLen);
- return 0;
- }
-
- if(headLen){
- memcpy(buf, _head.c_str(), _head.length());
- }
-
- size_t readLen = 0;
-
- if(_chunked){
- // HTTP 1.1 allows leading zeros in chunk length. Or spaces may be added.
- // See RFC2616 sections 2, 3.6.1.
- readLen = _fillBufferAndProcessTemplates(buf+headLen+6, outLen - 8);
- if(readLen == RESPONSE_TRY_AGAIN){
- free(buf);
- return 0;
- }
- outLen = sprintf((char*)buf+headLen, "%x", readLen) + headLen;
- while(outLen < headLen + 4) buf[outLen++] = ' ';
- buf[outLen++] = '\r';
- buf[outLen++] = '\n';
- outLen += readLen;
- buf[outLen++] = '\r';
- buf[outLen++] = '\n';
- } else {
- readLen = _fillBufferAndProcessTemplates(buf+headLen, outLen);
- if(readLen == RESPONSE_TRY_AGAIN){
- free(buf);
- return 0;
- }
- outLen = readLen + headLen;
- }
-
- if(headLen){
- _head = String();
- }
-
- if(outLen){
- _writtenLength += request->client()->write((const char*)buf, outLen);
- }
-
- if(_chunked){
- _sentLength += readLen;
- } else {
- _sentLength += outLen - headLen;
- }
-
- free(buf);
-
- if((_chunked && readLen == 0) || (!_sendContentLength && outLen == 0) || (!_chunked && _sentLength == _contentLength)){
- _state = RESPONSE_WAIT_ACK;
- }
- return outLen;
-
- } else if(_state == RESPONSE_WAIT_ACK){
- if(!_sendContentLength || _ackedLength >= _writtenLength){
- _state = RESPONSE_END;
- if(!_chunked && !_sendContentLength)
- request->client()->close(true);
- }
- }
- return 0;
-}
-
-size_t AsyncAbstractResponse::_readDataFromCacheOrContent(uint8_t* data, const size_t len)
-{
- // If we have something in cache, copy it to buffer
- const size_t readFromCache = std::min(len, _cache.size());
- if(readFromCache) {
- memcpy(data, _cache.data(), readFromCache);
- _cache.erase(_cache.begin(), _cache.begin() + readFromCache);
- }
- // If we need to read more...
- const size_t needFromFile = len - readFromCache;
- const size_t readFromContent = _fillBuffer(data + readFromCache, needFromFile);
- return readFromCache + readFromContent;
-}
-
-size_t AsyncAbstractResponse::_fillBufferAndProcessTemplates(uint8_t* data, size_t len)
-{
- if(!_callback)
- return _fillBuffer(data, len);
-
- const size_t originalLen = len;
- len = _readDataFromCacheOrContent(data, len);
- // Now we've read 'len' bytes, either from cache or from file
- // Search for template placeholders
- uint8_t* pTemplateStart = data;
- while((pTemplateStart < &data[len]) && (pTemplateStart = (uint8_t*)memchr(pTemplateStart, TEMPLATE_PLACEHOLDER, &data[len - 1] - pTemplateStart + 1))) { // data[0] ... data[len - 1]
- uint8_t* pTemplateEnd = (pTemplateStart < &data[len - 1]) ? (uint8_t*)memchr(pTemplateStart + 1, TEMPLATE_PLACEHOLDER, &data[len - 1] - pTemplateStart) : nullptr;
- // temporary buffer to hold parameter name
- uint8_t buf[TEMPLATE_PARAM_NAME_LENGTH + 1];
- String paramName;
- // If closing placeholder is found:
- if(pTemplateEnd) {
- // prepare argument to callback
- const size_t paramNameLength = std::min(sizeof(buf) - 1, (unsigned int)(pTemplateEnd - pTemplateStart - 1));
- if(paramNameLength) {
- memcpy(buf, pTemplateStart + 1, paramNameLength);
- buf[paramNameLength] = 0;
- paramName = String(reinterpret_cast(buf));
- } else { // double percent sign encountered, this is single percent sign escaped.
- // remove the 2nd percent sign
- memmove(pTemplateEnd, pTemplateEnd + 1, &data[len] - pTemplateEnd - 1);
- len += _readDataFromCacheOrContent(&data[len - 1], 1) - 1;
- ++pTemplateStart;
- }
- } else if(&data[len - 1] - pTemplateStart + 1 < TEMPLATE_PARAM_NAME_LENGTH + 2) { // closing placeholder not found, check if it's in the remaining file data
- memcpy(buf, pTemplateStart + 1, &data[len - 1] - pTemplateStart);
- const size_t readFromCacheOrContent = _readDataFromCacheOrContent(buf + (&data[len - 1] - pTemplateStart), TEMPLATE_PARAM_NAME_LENGTH + 2 - (&data[len - 1] - pTemplateStart + 1));
- if(readFromCacheOrContent) {
- pTemplateEnd = (uint8_t*)memchr(buf + (&data[len - 1] - pTemplateStart), TEMPLATE_PLACEHOLDER, readFromCacheOrContent);
- if(pTemplateEnd) {
- // prepare argument to callback
- *pTemplateEnd = 0;
- paramName = String(reinterpret_cast(buf));
- // Copy remaining read-ahead data into cache
- _cache.insert(_cache.begin(), pTemplateEnd + 1, buf + (&data[len - 1] - pTemplateStart) + readFromCacheOrContent);
- pTemplateEnd = &data[len - 1];
- }
- else // closing placeholder not found in file data, store found percent symbol as is and advance to the next position
- {
- // but first, store read file data in cache
- _cache.insert(_cache.begin(), buf + (&data[len - 1] - pTemplateStart), buf + (&data[len - 1] - pTemplateStart) + readFromCacheOrContent);
- ++pTemplateStart;
- }
- }
- else // closing placeholder not found in content data, store found percent symbol as is and advance to the next position
- ++pTemplateStart;
- }
- else // closing placeholder not found in content data, store found percent symbol as is and advance to the next position
- ++pTemplateStart;
- if(paramName.length()) {
- // call callback and replace with result.
- // Everything in range [pTemplateStart, pTemplateEnd] can be safely replaced with parameter value.
- // Data after pTemplateEnd may need to be moved.
- // The first byte of data after placeholder is located at pTemplateEnd + 1.
- // It should be located at pTemplateStart + numBytesCopied (to begin right after inserted parameter value).
- const String paramValue(_callback(paramName));
- const char* pvstr = paramValue.c_str();
- const unsigned int pvlen = paramValue.length();
- const size_t numBytesCopied = std::min(pvlen, static_cast(&data[originalLen - 1] - pTemplateStart + 1));
- // make room for param value
- // 1. move extra data to cache if parameter value is longer than placeholder AND if there is no room to store
- if((pTemplateEnd + 1 < pTemplateStart + numBytesCopied) && (originalLen - (pTemplateStart + numBytesCopied - pTemplateEnd - 1) < len)) {
- _cache.insert(_cache.begin(), &data[originalLen - (pTemplateStart + numBytesCopied - pTemplateEnd - 1)], &data[len]);
- //2. parameter value is longer than placeholder text, push the data after placeholder which not saved into cache further to the end
- memmove(pTemplateStart + numBytesCopied, pTemplateEnd + 1, &data[originalLen] - pTemplateStart - numBytesCopied);
- len = originalLen; // fix issue with truncated data, not sure if it has any side effects
- } else if(pTemplateEnd + 1 != pTemplateStart + numBytesCopied)
- //2. Either parameter value is shorter than placeholder text OR there is enough free space in buffer to fit.
- // Move the entire data after the placeholder
- memmove(pTemplateStart + numBytesCopied, pTemplateEnd + 1, &data[len] - pTemplateEnd - 1);
- // 3. replace placeholder with actual value
- memcpy(pTemplateStart, pvstr, numBytesCopied);
- // If result is longer than buffer, copy the remainder into cache (this could happen only if placeholder text itself did not fit entirely in buffer)
- if(numBytesCopied < pvlen) {
- _cache.insert(_cache.begin(), pvstr + numBytesCopied, pvstr + pvlen);
- } else if(pTemplateStart + numBytesCopied < pTemplateEnd + 1) { // result is copied fully; if result is shorter than placeholder text...
- // there is some free room, fill it from cache
- const size_t roomFreed = pTemplateEnd + 1 - pTemplateStart - numBytesCopied;
- const size_t totalFreeRoom = originalLen - len + roomFreed;
- len += _readDataFromCacheOrContent(&data[len - roomFreed], totalFreeRoom) - roomFreed;
- } else { // result is copied fully; it is longer than placeholder text
- const size_t roomTaken = pTemplateStart + numBytesCopied - pTemplateEnd - 1;
- len = std::min(len + roomTaken, originalLen);
- }
- }
- } // while(pTemplateStart)
- return len;
-}
-
-
-/*
- * File Response
- * */
-
-AsyncFileResponse::~AsyncFileResponse(){
- if(_content)
- _content.close();
-}
-
-void AsyncFileResponse::_setContentType(const String& path){
- if (path.endsWith(".html")) _contentType = "text/html";
- else if (path.endsWith(".htm")) _contentType = "text/html";
- else if (path.endsWith(".css")) _contentType = "text/css";
- else if (path.endsWith(".json")) _contentType = "application/json";
- else if (path.endsWith(".js")) _contentType = "application/javascript";
- else if (path.endsWith(".png")) _contentType = "image/png";
- else if (path.endsWith(".gif")) _contentType = "image/gif";
- else if (path.endsWith(".jpg")) _contentType = "image/jpeg";
- else if (path.endsWith(".ico")) _contentType = "image/x-icon";
- else if (path.endsWith(".svg")) _contentType = "image/svg+xml";
- else if (path.endsWith(".eot")) _contentType = "font/eot";
- else if (path.endsWith(".woff")) _contentType = "font/woff";
- else if (path.endsWith(".woff2")) _contentType = "font/woff2";
- else if (path.endsWith(".ttf")) _contentType = "font/ttf";
- else if (path.endsWith(".xml")) _contentType = "text/xml";
- else if (path.endsWith(".pdf")) _contentType = "application/pdf";
- else if (path.endsWith(".zip")) _contentType = "application/zip";
- else if(path.endsWith(".gz")) _contentType = "application/x-gzip";
- else _contentType = "text/plain";
-}
-
-AsyncFileResponse::AsyncFileResponse(FS &fs, const String& path, const String& contentType, bool download, AwsTemplateProcessor callback): AsyncAbstractResponse(callback){
- _code = 200;
- _path = path;
-
- if(!download && !fs.exists(_path) && fs.exists(_path+".gz")){
- _path = _path+".gz";
- addHeader("Content-Encoding", "gzip");
- _callback = nullptr; // Unable to process zipped templates
- _sendContentLength = true;
- _chunked = false;
- }
-
- _content = fs.open(_path, "r");
- _contentLength = _content.size();
-
- if(contentType == "")
- _setContentType(path);
- else
- _contentType = contentType;
-
- int filenameStart = path.lastIndexOf('/') + 1;
- char buf[26+path.length()-filenameStart];
- char* filename = (char*)path.c_str() + filenameStart;
-
- if(download) {
- // set filename and force download
- snprintf(buf, sizeof (buf), "attachment; filename=\"%s\"", filename);
- } else {
- // set filename and force rendering
- snprintf(buf, sizeof (buf), "inline; filename=\"%s\"", filename);
- }
- addHeader("Content-Disposition", buf);
-}
-
-AsyncFileResponse::AsyncFileResponse(File content, const String& path, const String& contentType, bool download, AwsTemplateProcessor callback): AsyncAbstractResponse(callback){
- _code = 200;
- _path = path;
-
- if(!download && String(content.name()).endsWith(".gz") && !path.endsWith(".gz")){
- addHeader("Content-Encoding", "gzip");
- _callback = nullptr; // Unable to process gzipped templates
- _sendContentLength = true;
- _chunked = false;
- }
-
- _content = content;
- _contentLength = _content.size();
-
- if(contentType == "")
- _setContentType(path);
- else
- _contentType = contentType;
-
- int filenameStart = path.lastIndexOf('/') + 1;
- char buf[26+path.length()-filenameStart];
- char* filename = (char*)path.c_str() + filenameStart;
-
- if(download) {
- snprintf(buf, sizeof (buf), "attachment; filename=\"%s\"", filename);
- } else {
- snprintf(buf, sizeof (buf), "inline; filename=\"%s\"", filename);
- }
- addHeader("Content-Disposition", buf);
-}
-
-size_t AsyncFileResponse::_fillBuffer(uint8_t *data, size_t len){
- return _content.read(data, len);
-}
-
-/*
- * Stream Response
- * */
-
-AsyncStreamResponse::AsyncStreamResponse(Stream &stream, const String& contentType, size_t len, AwsTemplateProcessor callback): AsyncAbstractResponse(callback) {
- _code = 200;
- _content = &stream;
- _contentLength = len;
- _contentType = contentType;
-}
-
-size_t AsyncStreamResponse::_fillBuffer(uint8_t *data, size_t len){
- size_t available = _content->available();
- size_t outLen = (available > len)?len:available;
- size_t i;
- for(i=0;iread();
- return outLen;
-}
-
-/*
- * Callback Response
- * */
-
-AsyncCallbackResponse::AsyncCallbackResponse(const String& contentType, size_t len, AwsResponseFiller callback, AwsTemplateProcessor templateCallback): AsyncAbstractResponse(templateCallback) {
- _code = 200;
- _content = callback;
- _contentLength = len;
- if(!len)
- _sendContentLength = false;
- _contentType = contentType;
- _filledLength = 0;
-}
-
-size_t AsyncCallbackResponse::_fillBuffer(uint8_t *data, size_t len){
- size_t ret = _content(data, len, _filledLength);
- if(ret != RESPONSE_TRY_AGAIN){
- _filledLength += ret;
- }
- return ret;
-}
-
-/*
- * Chunked Response
- * */
-
-AsyncChunkedResponse::AsyncChunkedResponse(const String& contentType, AwsResponseFiller callback, AwsTemplateProcessor processorCallback): AsyncAbstractResponse(processorCallback) {
- _code = 200;
- _content = callback;
- _contentLength = 0;
- _contentType = contentType;
- _sendContentLength = false;
- _chunked = true;
- _filledLength = 0;
-}
-
-size_t AsyncChunkedResponse::_fillBuffer(uint8_t *data, size_t len){
- size_t ret = _content(data, len, _filledLength);
- if(ret != RESPONSE_TRY_AGAIN){
- _filledLength += ret;
- }
- return ret;
-}
-
-/*
- * Progmem Response
- * */
-
-AsyncProgmemResponse::AsyncProgmemResponse(int code, const String& contentType, const uint8_t * content, size_t len, AwsTemplateProcessor callback): AsyncAbstractResponse(callback) {
- _code = code;
- _content = content;
- _contentType = contentType;
- _contentLength = len;
- _readLength = 0;
-}
-
-size_t AsyncProgmemResponse::_fillBuffer(uint8_t *data, size_t len){
- size_t left = _contentLength - _readLength;
- if (left > len) {
- memcpy_P(data, _content + _readLength, len);
- _readLength += len;
- return len;
- }
- memcpy_P(data, _content + _readLength, left);
- _readLength += left;
- return left;
-}
-
-
-/*
- * Response Stream (You can print/write/printf to it, up to the contentLen bytes)
- * */
-
-AsyncResponseStream::AsyncResponseStream(const String& contentType, size_t bufferSize){
- _code = 200;
- _contentLength = 0;
- _contentType = contentType;
- _content = new cbuf(bufferSize);
-}
-
-AsyncResponseStream::~AsyncResponseStream(){
- delete _content;
-}
-
-size_t AsyncResponseStream::_fillBuffer(uint8_t *buf, size_t maxLen){
- return _content->read((char*)buf, maxLen);
-}
-
-size_t AsyncResponseStream::write(const uint8_t *data, size_t len){
- if(_started())
- return 0;
-
- if(len > _content->room()){
- size_t needed = len - _content->room();
- _content->resizeAdd(needed);
- }
- size_t written = _content->write((const char*)data, len);
- _contentLength += written;
- return written;
-}
-
-size_t AsyncResponseStream::write(uint8_t data){
- return write(&data, 1);
-}
diff --git a/ESP32/lib/ESPAsyncWebServer/src/WebServer.cpp b/ESP32/lib/ESPAsyncWebServer/src/WebServer.cpp
deleted file mode 100644
index 95c2dd6..0000000
--- a/ESP32/lib/ESPAsyncWebServer/src/WebServer.cpp
+++ /dev/null
@@ -1,193 +0,0 @@
-/*
- Asynchronous WebServer library for Espressif MCUs
-
- Copyright (c) 2016 Hristo Gochkov. All rights reserved.
- This file is part of the esp8266 core for Arduino environment.
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-*/
-#include "ESPAsyncWebServer.h"
-#include "WebHandlerImpl.h"
-
-bool ON_STA_FILTER(AsyncWebServerRequest *request) {
- return WiFi.localIP() == request->client()->localIP();
-}
-
-bool ON_AP_FILTER(AsyncWebServerRequest *request) {
- return WiFi.localIP() != request->client()->localIP();
-}
-
-
-AsyncWebServer::AsyncWebServer(uint16_t port)
- : _server(port)
- , _rewrites(LinkedList([](AsyncWebRewrite* r){ delete r; }))
- , _handlers(LinkedList([](AsyncWebHandler* h){ delete h; }))
-{
- _catchAllHandler = new AsyncCallbackWebHandler();
- if(_catchAllHandler == NULL)
- return;
- _server.onClient([](void *s, AsyncClient* c){
- if(c == NULL)
- return;
- c->setRxTimeout(3);
- AsyncWebServerRequest *r = new AsyncWebServerRequest((AsyncWebServer*)s, c);
- if(r == NULL){
- c->close(true);
- c->free();
- delete c;
- }
- }, this);
-}
-
-AsyncWebServer::~AsyncWebServer(){
- reset();
- end();
- if(_catchAllHandler) delete _catchAllHandler;
-}
-
-AsyncWebRewrite& AsyncWebServer::addRewrite(AsyncWebRewrite* rewrite){
- _rewrites.add(rewrite);
- return *rewrite;
-}
-
-bool AsyncWebServer::removeRewrite(AsyncWebRewrite *rewrite){
- return _rewrites.remove(rewrite);
-}
-
-AsyncWebRewrite& AsyncWebServer::rewrite(const char* from, const char* to){
- return addRewrite(new AsyncWebRewrite(from, to));
-}
-
-AsyncWebHandler& AsyncWebServer::addHandler(AsyncWebHandler* handler){
- _handlers.add(handler);
- return *handler;
-}
-
-bool AsyncWebServer::removeHandler(AsyncWebHandler *handler){
- return _handlers.remove(handler);
-}
-
-void AsyncWebServer::begin(){
- _server.setNoDelay(true);
- _server.begin();
-}
-
-void AsyncWebServer::end(){
- _server.end();
-}
-
-#if ASYNC_TCP_SSL_ENABLED
-void AsyncWebServer::onSslFileRequest(AcSSlFileHandler cb, void* arg){
- _server.onSslFileRequest(cb, arg);
-}
-
-void AsyncWebServer::beginSecure(const char *cert, const char *key, const char *password){
- _server.beginSecure(cert, key, password);
-}
-#endif
-
-void AsyncWebServer::_handleDisconnect(AsyncWebServerRequest *request){
- delete request;
-}
-
-void AsyncWebServer::_rewriteRequest(AsyncWebServerRequest *request){
- for(const auto& r: _rewrites){
- if (r->match(request)){
- request->_url = r->toUrl();
- request->_addGetParams(r->params());
- }
- }
-}
-
-void AsyncWebServer::_attachHandler(AsyncWebServerRequest *request){
- for(const auto& h: _handlers){
- if (h->filter(request) && h->canHandle(request)){
- request->setHandler(h);
- return;
- }
- }
-
- request->addInterestingHeader("ANY");
- request->setHandler(_catchAllHandler);
-}
-
-
-AsyncCallbackWebHandler& AsyncWebServer::on(const char* uri, WebRequestMethodComposite method, ArRequestHandlerFunction onRequest, ArUploadHandlerFunction onUpload, ArBodyHandlerFunction onBody){
- AsyncCallbackWebHandler* handler = new AsyncCallbackWebHandler();
- handler->setUri(uri);
- handler->setMethod(method);
- handler->onRequest(onRequest);
- handler->onUpload(onUpload);
- handler->onBody(onBody);
- addHandler(handler);
- return *handler;
-}
-
-AsyncCallbackWebHandler& AsyncWebServer::on(const char* uri, WebRequestMethodComposite method, ArRequestHandlerFunction onRequest, ArUploadHandlerFunction onUpload){
- AsyncCallbackWebHandler* handler = new AsyncCallbackWebHandler();
- handler->setUri(uri);
- handler->setMethod(method);
- handler->onRequest(onRequest);
- handler->onUpload(onUpload);
- addHandler(handler);
- return *handler;
-}
-
-AsyncCallbackWebHandler& AsyncWebServer::on(const char* uri, WebRequestMethodComposite method, ArRequestHandlerFunction onRequest){
- AsyncCallbackWebHandler* handler = new AsyncCallbackWebHandler();
- handler->setUri(uri);
- handler->setMethod(method);
- handler->onRequest(onRequest);
- addHandler(handler);
- return *handler;
-}
-
-AsyncCallbackWebHandler& AsyncWebServer::on(const char* uri, ArRequestHandlerFunction onRequest){
- AsyncCallbackWebHandler* handler = new AsyncCallbackWebHandler();
- handler->setUri(uri);
- handler->onRequest(onRequest);
- addHandler(handler);
- return *handler;
-}
-
-AsyncStaticWebHandler& AsyncWebServer::serveStatic(const char* uri, fs::FS& fs, const char* path, const char* cache_control){
- AsyncStaticWebHandler* handler = new AsyncStaticWebHandler(uri, fs, path, cache_control);
- addHandler(handler);
- return *handler;
-}
-
-void AsyncWebServer::onNotFound(ArRequestHandlerFunction fn){
- _catchAllHandler->onRequest(fn);
-}
-
-void AsyncWebServer::onFileUpload(ArUploadHandlerFunction fn){
- _catchAllHandler->onUpload(fn);
-}
-
-void AsyncWebServer::onRequestBody(ArBodyHandlerFunction fn){
- _catchAllHandler->onBody(fn);
-}
-
-void AsyncWebServer::reset(){
- _rewrites.free();
- _handlers.free();
-
- if (_catchAllHandler != NULL){
- _catchAllHandler->onRequest(NULL);
- _catchAllHandler->onUpload(NULL);
- _catchAllHandler->onBody(NULL);
- }
-}
-
diff --git a/ESP32/lib/ESPAsyncWebServer/src/edit.htm b/ESP32/lib/ESPAsyncWebServer/src/edit.htm
deleted file mode 100644
index 43d4984..0000000
--- a/ESP32/lib/ESPAsyncWebServer/src/edit.htm
+++ /dev/null
@@ -1,627 +0,0 @@
-
-
-
-
-ESP Editor
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/ESP32/platformio.ini b/ESP32/platformio.ini
index 5c5f4a3..c8e435f 100644
--- a/ESP32/platformio.ini
+++ b/ESP32/platformio.ini
@@ -1,20 +1,23 @@
-; PlatformIO Project Configuration File
-;
-; Build options: build flags, source filter
-; Upload options: custom upload port, speed and extra flags
-; Library options: dependencies, extra library storages
-; Advanced options: extra scripting
-;
-; Please visit documentation for the other options and examples
-; https://docs.platformio.org/page/projectconf.html
-
-[env:nodemcu-32s]
-platform = espressif32
-board = nodemcu-32s
-framework = arduino
-monitor_speed = 115200
-#upload_protocol = espota
-#upload_port = 192.168.1.166
-upload_speed = 921600
-build_type = debug
-monitor_filters = esp32_exception_decoder
+; PlatformIO Project Configuration File
+;
+; Build options: build flags, source filter
+; Upload options: custom upload port, speed and extra flags
+; Library options: dependencies, extra library storages
+; Advanced options: extra scripting
+;
+; Please visit documentation for the other options and examples
+; https://docs.platformio.org/page/projectconf.html
+
+[env:nodemcu-32s]
+platform = espressif32
+board = nodemcu-32s
+framework = arduino
+monitor_speed = 115200
+#upload_protocol = espota
+#upload_port = 192.168.1.166
+upload_speed = 921600
+build_type = debug
+monitor_filters = esp32_exception_decoder
+lib_deps = fhessel/esp32_https_server@^1.0.0
+build_flags =
+ -DHTTPS_LOGLEVEL=3
diff --git a/ESP32/src/Status.h b/ESP32/src/Status.h
new file mode 100644
index 0000000..bc99389
--- /dev/null
+++ b/ESP32/src/Status.h
@@ -0,0 +1,25 @@
+#pragma once
+
+#include
+
+struct Status
+{
+ char realtime[32] = {0}; // UTC date and time, in format YYYY-MM-DDTHH:mm:ss.sssZ
+
+ uint16_t batteryVoltage = 0; // in mV
+ uint16_t batteryOutputCurrent = 0; // in mV
+ int16_t temperature = 0; // in tenth of °C
+ int32_t altitude = 0; // in mm above sea level (can be negative if below sea level, or depending on atmospheric conditions)
+ float latitude = -1000.0f; // in decimal degrees
+ float longitude = -1000.0f; // in decimal degrees
+ float gpsAltitude = -1000.0f; // in meters, above sea level
+
+ float speed = 0.0f;
+
+ // current trip
+ uint32_t tripDistance = 0; // in meters
+ uint16_t tripMovingTime = 0; // cumulated seconds, only when moving at non-zero speed
+ uint16_t tripTotalTime = 0; // total trip time in seconds
+ uint32_t tripAscendingElevation = 0; // cumulated ascending elevation, in millimeters
+ uint32_t tripMotorEnergy = 0; // in Joules
+};
diff --git a/ESP32/src/WebServer.cpp b/ESP32/src/WebServer.cpp
new file mode 100644
index 0000000..4b8951e
--- /dev/null
+++ b/ESP32/src/WebServer.cpp
@@ -0,0 +1,175 @@
+#include "WebServer.h"
+
+#include "DebugLog.h"
+#include "DataLogger.h"
+
+#include
+#include
+#include
+
+#include "HTTPServer.hpp"
+#include "SSLCert.hpp"
+#include "HTTPRequest.hpp"
+#include "HTTPResponse.hpp"
+
+/** Check if we have multiple cores */
+#if CONFIG_FREERTOS_UNICORE
+#define WEBSERVER_RUNNING_CORE 0
+#else
+#define WEBSERVER_RUNNING_CORE 1
+#endif
+
+using namespace httpsserver;
+
+detail::WebServer WebServer;
+
+namespace detail
+{
+ HTTPServer httpServer;
+
+ WebServer::WebServer()
+ {
+ }
+
+ WebServer::~WebServer()
+ {
+ }
+
+ void WebServer::begin()
+ {
+ ::DebugLog.println("Creating server task... ");
+ xTaskCreatePinnedToCore(WebServer::ServerTask_, "webserver", 6144, nullptr, 1, nullptr, WEBSERVER_RUNNING_CORE);
+ }
+
+ void WebServer::setStatus(const Status& status)
+ {
+ status_ = status;
+ }
+
+ void WebServer::ServerTask_(void* params)
+ {
+ // Main HTML page
+ ResourceNode* nodeRoot = new ResourceNode("/", "GET", &WebServer::HandleIndex_);
+ ResourceNode* nodeIndex = new ResourceNode("/index.html", "GET", &WebServer::HandleIndex_);
+ httpServer.registerNode(nodeRoot);
+ httpServer.registerNode(nodeIndex);
+
+ // API
+ ResourceNode* nodeGetStatus = new ResourceNode("/api/status", "GET", &WebServer::HandleGetStatus_);
+ ResourceNode* nodePostInfo = new ResourceNode("/api/info", "POST", &WebServer::HandlePostInfo_);
+ httpServer.registerNode(nodeGetStatus);
+ httpServer.registerNode(nodePostInfo);
+
+ // Default node (either a static file, if found, or a 404 error)
+ ResourceNode* nodeDefault = new ResourceNode("", "GET", &WebServer::HandleDefault_);
+ httpServer.setDefaultNode(nodeDefault);
+
+ ::DebugLog.println("Starting server... ");
+ httpServer.start();
+ if (httpServer.isRunning()) {
+ ::DebugLog.println("Server ready.");
+
+ while(true) {
+ httpServer.loop();
+ delay(1);
+ }
+ }
+ }
+
+ void WebServer::HandleIndex_(HTTPRequest * request, HTTPResponse * response)
+ {
+ // Status code is 200 OK by default.
+ response->setHeader("Content-Type", "text/html");
+
+ File file = SPIFFS.open("/www/index.html");
+ SendContent_(file, response);
+ file.close();
+ }
+
+ void WebServer::HandleGetStatus_(httpsserver::HTTPRequest * request, httpsserver::HTTPResponse * response)
+ {
+ const Status& status = ::WebServer.status_;
+
+ int v = status.batteryVoltage;
+ int c = status.batteryOutputCurrent;
+ int s = (int)(status.speed * 1000.0f + 0.5f);
+ int temp = status.temperature;
+ int alt = status.altitude;
+
+ int td = status.tripDistance;
+ int ttt = status.tripTotalTime;
+ int tmt = status.tripMovingTime;
+ int tae = status.tripAscendingElevation / 100; // convert mm to dm
+ int tme = status.tripMotorEnergy / 360; // convert Joules to dWh (tenth of Wh)
+
+ float latitude = -1000.0f;
+ float longitude = -1000.0f;
+ char realtime[64] = {0};
+
+ const char* logFileName = DataLogger::get().currentLogFileName();
+ if(String(logFileName).startsWith("/log/")) logFileName += 5;
+
+ int totalSize = (int)(SPIFFS.totalBytes() / 1000);
+ int usedSize = (int)(SPIFFS.usedBytes() / 1000);
+
+ char json[256];
+ sprintf(json, "{\"v\":%d,\"c\":%d,\"s\":%d,\"td\":%d,\"ttt\":%d,\"tmt\":%d,\"tae\":%d,\"tme\":%d,\"temp\":%d,\"alt\":%d,\"log\":\"%s\",\"tot\":%d,\"used\":%d,\"lat\":%.5f,\"lng\":%.5f,\"d\":\"%s\"}", v, c, s, td, ttt, tmt, tae, tme, temp, alt, logFileName, totalSize, usedSize, latitude, longitude, realtime);
+
+ response->setHeader("Content-Type", "text/json");
+ response->print(json);
+ }
+
+ void WebServer::HandlePostInfo_(httpsserver::HTTPRequest * request, httpsserver::HTTPResponse * response)
+ {
+ request->discardRequestBody();
+ }
+
+ void WebServer::HandleDefault_(HTTPRequest * request, HTTPResponse * response)
+ {
+ // Discard request body, if we received any
+ // We do this, as this is the default node and may also server POST/PUT requests
+ request->discardRequestBody();
+
+ std::string filePath = "/www";
+ std::string fullURL = request->getRequestString();
+ filePath = filePath + fullURL.substr(0, fullURL.find("?"));
+ //::DebugLog.println(filePath.c_str());
+ File file = SPIFFS.open(filePath.c_str());
+
+ if(!file || file.isDirectory())
+ {
+ // We've not found any matching file, so this is a 404 error
+
+ response->setStatusCode(404);
+ response->setStatusText("Not Found");
+
+ response->setHeader("Content-Type", "text/html");
+
+ response->println("");
+ response->println("");
+ response->println("Not Found");
+ response->println("404 Not Found
The requested resource was not found on this server.
");
+ response->println("");
+ }
+ else
+ {
+ // We've found a file, send the content
+
+ response->setHeader("Cache-Control", "max-age=5184000");
+
+ SendContent_(file, response);
+ }
+
+ file.close();
+ }
+
+ void WebServer::SendContent_(Stream& stream, httpsserver::HTTPResponse * response)
+ {
+ uint8_t buffer[512];
+ while(stream.available())
+ {
+ size_t numBytes = stream.readBytes(buffer, sizeof(buffer));
+ response->write(buffer, numBytes);
+ }
+ }
+}
diff --git a/ESP32/src/WebServer.h b/ESP32/src/WebServer.h
new file mode 100644
index 0000000..35516e4
--- /dev/null
+++ b/ESP32/src/WebServer.h
@@ -0,0 +1,39 @@
+#pragma once
+
+#include "Status.h"
+
+class Stream;
+
+namespace httpsserver
+{
+ class HTTPRequest;
+ class HTTPResponse;
+}
+
+namespace detail
+{
+ class WebServer
+ {
+ public:
+ WebServer();
+ ~WebServer();
+
+ void begin();
+
+ void setStatus(const Status& status);
+
+ private:
+ static void ServerTask_(void* params);
+ static void HandleIndex_(httpsserver::HTTPRequest * request, httpsserver::HTTPResponse * response);
+ static void HandleGetStatus_(httpsserver::HTTPRequest * request, httpsserver::HTTPResponse * response);
+ static void HandlePostInfo_(httpsserver::HTTPRequest * request, httpsserver::HTTPResponse * response);
+ static void HandleDefault_(httpsserver::HTTPRequest * request, httpsserver::HTTPResponse * response);
+
+ static void SendContent_(Stream& stream, httpsserver::HTTPResponse * response);
+
+ private:
+ Status status_;
+ };
+}
+
+extern detail::WebServer WebServer;
diff --git a/ESP32/src/vehicle-monitor.cpp b/ESP32/src/vehicle-monitor.cpp
index 87ce2df..70a8237 100644
--- a/ESP32/src/vehicle-monitor.cpp
+++ b/ESP32/src/vehicle-monitor.cpp
@@ -4,13 +4,14 @@
#include "ADC.h"
#include "OTA.h"
#include "DataLogger.h"
+#include "WebServer.h"
+#include "Status.h"
#include "utils.h"
#include
#include
#include
#include
-#include
#include
@@ -23,8 +24,6 @@
#define DUMMY_DATA 0
#define ENABLE_GPS_COORDINATES 1
-AsyncWebServer server(80);
-
ADC currentSensor(36);
ADC batterySensor(39);
Dps310 pressureSensor = Dps310();
@@ -38,21 +37,7 @@ const int numImpulsesPerTurn = 2;
const float wheelCircumferenceMeters = wheelDiameterInches * 0.0254f * 3.1415f / (float)numImpulsesPerTurn;
const uint32_t wheelCircumferenceMillimeters = (uint32_t)(wheelCircumferenceMeters * 1000.0f + 0.5f);
-uint16_t batteryVoltage = 0; // in mV
-uint16_t batteryOutputCurrent = 0; // in mV
-int16_t temperature = 0; // in tenth of °C
-int32_t altitude = 0; // in mm above sea level (can be negative if below sea level, or depending on atmospheric conditions)
-float latitude = -1000.0f; // in decimal degrees
-float longitude = -1000.0f; // in decimal degrees
-float gpsAltitude = -1000.0f; // in meters, above sea level
-char realtime[32] = {0}; // UTC date and time, in format YYYY-MM-DDTHH:mm:ss.sssZ
-
-// current trip
-uint32_t tripDistance = 0; // in meters
-uint16_t tripMovingTime = 0; // cumulated seconds, only when moving at non-zero speed
-uint16_t tripTotalTime = 0; // total trip time in seconds
-uint32_t tripAscendingElevation = 0; // cumulated ascending elevation, in millimeters
-uint32_t tripMotorEnergy = 0; // in Joules
+Status status;
WiFiMulti wifiMulti;
wl_status_t wifi_STA_status = WL_NO_SHIELD;
@@ -206,7 +191,9 @@ void setup()
pressureSensor.begin(Wire);
- server.on("/api/debug/log", HTTP_GET, [](AsyncWebServerRequest *request){
+ WebServer.begin();
+
+ /*server.on("/api/debug/log", HTTP_GET, [](AsyncWebServerRequest *request){
AsyncResponseStream *response = request->beginResponseStream("text/plain");
int logPartIdx = 0;
while(true)
@@ -248,14 +235,6 @@ void setup()
server.on("/api/info", HTTP_POST, [](AsyncWebServerRequest *request){
//DebugLog.println("/api/info");
- /*int params = request->params();
- for(int i=0;igetParam(i);
- DebugLog.print(p->name().c_str());
- DebugLog.print("=");
- DebugLog.println(p->value().c_str());
- }*/
-
AsyncWebParameter* latitudeParam = request->getParam("lat", true);
AsyncWebParameter* longitudeParam = request->getParam("lng", true);
AsyncWebParameter* altitudeParam = request->getParam("alt", true);
@@ -330,7 +309,7 @@ void setup()
server.serveStatic("/", SPIFFS, "/www/").setCacheControl("max-age=5184000");
server.begin();
- DebugLog.println("HTTP server started");
+ DebugLog.println("HTTP server started");*/
digitalWrite(debugLedPin, LOW);
}
@@ -401,8 +380,8 @@ void handle_ADC_measures()
averageV *= 27.000f; // account for voltage divider to retrieve the input voltage
averageC = std::max(0.0f, averageC - 2.5f) / 0.0238f; // convert voltage to current, according to the sensor linear relation
- batteryVoltage = (uint16_t)(averageV * 1000.0f + 0.5f);
- batteryOutputCurrent = (uint16_t)(averageC * 1000.0f + 0.5f);
+ status.batteryVoltage = (uint16_t)(averageV * 1000.0f + 0.5f);
+ status.batteryOutputCurrent = (uint16_t)(averageC * 1000.0f + 0.5f);
#if DUMMY_DATA
batteryVoltage = (uint16_t)((float)random(4000, 4020) / 100.0f * 1000.0f + 0.5f);
@@ -422,7 +401,7 @@ void handle_pressure_measure()
DebugLog.print("Failed to measure temperature: "); DebugLog.println(ret);
return;
}
- temperature = (int16_t)(temp * 10.0f + 0.5f);
+ status.temperature = (int16_t)(temp * 10.0f + 0.5f);
float pressure; // in Pa
pressureSensor.measurePressureOnce(pressure, oversampling);
@@ -464,7 +443,7 @@ void handle_pressure_measure()
break;
}
}
- altitude = (int32_t)(alt * 1000.0f + 0.5f);
+ status.altitude = (int32_t)(alt * 1000.0f + 0.5f);
/*DebugLog.print("temperature="); DebugLog.print(temp); DebugLog.print("°C");
DebugLog.print(" pressure="); DebugLog.print(pressure); DebugLog.print("Pa");
@@ -484,14 +463,14 @@ void loop()
lastLoopMillis = now;
static DataLogger::Entry entry;
- entry.batteryVoltage = (float)batteryVoltage / 1000.0f;
- entry.batteryOutputCurrent = (float)batteryOutputCurrent / 1000.0f;
+ entry.batteryVoltage = (float)status.batteryVoltage / 1000.0f;
+ entry.batteryOutputCurrent = (float)status.batteryOutputCurrent / 1000.0f;
entry.speed = getSpeed();
- entry.temperature = (float)temperature / 10.0f;
- entry.altitude = (float)altitude / 1000.0f;
+ entry.temperature = (float)status.temperature / 10.0f;
+ entry.altitude = (float)status.altitude / 1000.0f;
- entry.latitude = latitude;
- entry.longitude = longitude;
+ entry.latitude = status.latitude;
+ entry.longitude = status.longitude;
if(entry.speed > 0.0f)
{
@@ -499,12 +478,12 @@ void loop()
if(!DataLogger::get().isOpen())
{
DebugLog.println("Starting DataLogger");
- DataLogger::get().open(realtime);
- tripDistance = 0;
- tripMovingTime = 0;
- tripTotalTime = 0;
- tripAscendingElevation = 0;
- tripMotorEnergy = 0;
+ DataLogger::get().open(status.realtime);
+ status.tripDistance = 0;
+ status.tripMovingTime = 0;
+ status.tripTotalTime = 0;
+ status.tripAscendingElevation = 0;
+ status.tripMotorEnergy = 0;
}
}
else
@@ -557,18 +536,22 @@ void loop()
if(isOnTrip)
{
- tripTotalTime += newSeconds;
- if(isMoving) tripMovingTime += newSeconds;
- tripDistance += newMeters;
+ status.tripTotalTime += newSeconds;
+ if(isMoving) status.tripMovingTime += newSeconds;
+ status.tripDistance += newMeters;
- tripAscendingElevation += clampedPositiveAltitudeChange;
+ status.tripAscendingElevation += clampedPositiveAltitudeChange;
static float remainingEnergy = 0.0f;
float newEnergy = entry.batteryVoltage * entry.batteryOutputCurrent * ((float)dt / 1000.0f) + remainingEnergy;
uint32_t newEnergyIntegralJoules = (uint32_t)newEnergy;
remainingEnergy = newEnergy - (float)newEnergyIntegralJoules;
- tripMotorEnergy += newEnergyIntegralJoules;
+ status.tripMotorEnergy += newEnergyIntegralJoules;
}
+ status.speed = getSpeed();
+
+ WebServer.setStatus(status);
+
delay(isOnTrip ? 10 : 1000);
}
diff --git a/WebApp/src/monitor-api.ts b/WebApp/src/monitor-api.ts
index 9ff0631..41d80f5 100644
--- a/WebApp/src/monitor-api.ts
+++ b/WebApp/src/monitor-api.ts
@@ -85,7 +85,7 @@ export class MonitorApi {
maximumAge: 3000,
};
- //navigator.geolocation.getCurrentPosition(updatePosition, () => updatePosition(null), options);
+ navigator.geolocation.getCurrentPosition(updatePosition, () => updatePosition(null), options);
}
const defaultPosition : GeolocationPosition = {