#include "mesh/http/WebServer.h" #include "NodeDB.h" #include "graphics/Screen.h" #include "main.h" #include "mesh/http/WiFiAPClient.h" #include "sleep.h" #include #include #include #include #include #ifndef NO_ESP32 #include "esp_task_wdt.h" #endif // Persistant Data Storage #include Preferences prefs; /* Including the esp32_https_server library will trigger a compile time error. I've tracked it down to a reoccurrance of this bug: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=57824 The work around is described here: https://forums.xilinx.com/t5/Embedded-Development-Tools/Error-with-Standard-Libaries-in-Zynq/td-p/450032 Long story short is we need "#undef str" before including the esp32_https_server. - Jm Casler (jm@casler.org) Oct 2020 */ #undef str // Includes for the https server // https://github.com/fhessel/esp32_https_server #include #include #include #include #include // The HTTPS Server comes in a separate namespace. For easier use, include it here. using namespace httpsserver; #include "mesh/http/ContentHandler.h" static SSLCert *cert; static HTTPSServer *secureServer; static HTTPServer *insecureServer; volatile bool isWebServerReady; volatile bool isCertReady; static void handleWebResponse() { if (isWifiAvailable()) { if (isWebServerReady) { // We're going to handle the DNS responder here so it // will be ignored by the NRF boards. handleDNSResponse(); if (secureServer) secureServer->loop(); insecureServer->loop(); } } } static void taskCreateCert(void *parameter) { prefs.begin("MeshtasticHTTPS", false); #if 0 // Delete the saved certs (used in debugging) DEBUG_MSG("Deleting any saved SSL keys ...\n"); // prefs.clear(); prefs.remove("PK"); prefs.remove("cert"); #endif DEBUG_MSG("Checking if we have a previously saved SSL Certificate.\n"); size_t pkLen = prefs.getBytesLength("PK"); size_t certLen = prefs.getBytesLength("cert"); if (pkLen && certLen) { DEBUG_MSG("Existing SSL Certificate found!\n"); uint8_t *pkBuffer = new uint8_t[pkLen]; prefs.getBytes("PK", pkBuffer, pkLen); uint8_t *certBuffer = new uint8_t[certLen]; prefs.getBytes("cert", certBuffer, certLen); cert = new SSLCert(certBuffer, certLen, pkBuffer, pkLen); DEBUG_MSG("Retrieved Private Key: %d Bytes\n", cert->getPKLength()); DEBUG_MSG("Retrieved Certificate: %d Bytes\n", cert->getCertLength()); } else { DEBUG_MSG("Creating the certificate. This may take a while. Please wait...\n"); yield(); cert = new SSLCert(); yield(); int createCertResult = createSelfSignedCert(*cert, KEYSIZE_2048, "CN=meshtastic.local,O=Meshtastic,C=US", "20190101000000", "20300101000000"); yield(); if (createCertResult != 0) { DEBUG_MSG("Creating the certificate failed\n"); } else { DEBUG_MSG("Creating the certificate was successful\n"); DEBUG_MSG("Created Private Key: %d Bytes\n", cert->getPKLength()); DEBUG_MSG("Created Certificate: %d Bytes\n", cert->getCertLength()); prefs.putBytes("PK", (uint8_t *)cert->getPKData(), cert->getPKLength()); prefs.putBytes("cert", (uint8_t *)cert->getCertData(), cert->getCertLength()); } } isCertReady = true; // Must delete self, can't just fall out vTaskDelete(NULL); } void createSSLCert() { bool runLoop = false; if (isWifiAvailable() && !isCertReady) { // Create a new process just to handle creating the cert. // This is a workaround for Bug: https://github.com/fhessel/esp32_https_server/issues/48 // jm@casler.org (Oct 2020) xTaskCreate(taskCreateCert, /* Task function. */ "createCert", /* String with name of task. */ // 16384, /* Stack size in bytes. */ 8192, /* Stack size in bytes. */ NULL, /* Parameter passed as input of the task */ 16, /* Priority of the task. */ NULL); /* Task handle. */ DEBUG_MSG("Waiting for SSL Cert to be generated.\n"); while (!isCertReady) { if ((millis() / 500) % 2) { if (runLoop) { DEBUG_MSG("."); yield(); esp_task_wdt_reset(); if (millis() / 1000 >= 3) { screen->setSSLFrames(); } } runLoop = false; } else { runLoop = true; } } DEBUG_MSG("SSL Cert Ready!\n"); } } WebServerThread *webServerThread; WebServerThread::WebServerThread() : concurrency::OSThread("WebServerThread") {} int32_t WebServerThread::runOnce() { // DEBUG_MSG("WebServerThread::runOnce()\n"); handleWebResponse(); // Loop every 5ms. return (5); } void initWebServer() { DEBUG_MSG("Initializing Web Server ...\n"); // We can now use the new certificate to setup our server as usual. secureServer = new HTTPSServer(cert); insecureServer = new HTTPServer(); registerHandlers(insecureServer, secureServer); if (secureServer) { DEBUG_MSG("Starting Secure Web Server...\n"); secureServer->start(); } DEBUG_MSG("Starting Insecure Web Server...\n"); insecureServer->start(); if (insecureServer->isRunning()) { DEBUG_MSG("Web Servers Ready! :-) \n"); isWebServerReady = true; } else { DEBUG_MSG("Web Servers Failed! ;-( \n"); } }